class Gradient:
def __init__(self, f):
if not isinstance(f, types.FunctionType):
raise TypeError("El arguento de Gradient debe ser del Tipo Función")
else:
if len(inspect.getargspec(f)[0]) != 2:
raise TypeError("El primer arguento de Gradient debe ser del Tipo Función de Dos Variables: x e y")
self.f = f
def __call__(self, x0, y0):
dfdx = scidiff(lambda x: self.f(x,y0), x0, dx = 1e-11)
dfdy = scidiff(lambda x: self.f(x0,x), y0, dx = 1e-11)
return np.array([dfdx, dfdy])
class VectorFieldOverS1:
def __init__(self, X, smplsz = 20):
if not isinstance(X, types.FunctionType):
raise TypeError("El primer arguento de VectorFieldOverS1 debe ser del Tipo Función")
else:
if len(inspect.getargspec(X)[0]) != 2:
raise TypeError("El primer arguento de VectorFieldOverS1 debe ser del Tipo Función de Dos Variables: x e y")
else:
self.X = X
self.smplsz = smplsz
self.x = np.array([np.cos(i*2*np.pi/smplsz) for i in xrange(0, smplsz)])
self.y = np.array([np.sin(i*2*np.pi/self.smplsz) for i in xrange(0, smplsz)])
self.aughsmplsz = 10*smplsz
self.t = np.linspace(0, 2*np.pi, self.aughsmplsz)
self.maxplotrange = 2*max(abs(np.vectorize(X)(self.x,self.y)))
self.s = np.linspace(-self.maxplotrange, self.maxplotrange, self.aughsmplsz)
self.X_as_vector = np.vectorize(X)(self.x,self.y)
def __str__(self):
return inspect.getsourcelines(self.X)[0][0]
def __call__(self, f, x, y):
return f(x,y)
def plot_as_vector_field(self):
plt.figure(figsize = (4,4))
plt.axes(polar = False)
plt.xlim(-2,2)
plt.ylim(-2,2)
Xval = np.vectorize(self.X)(self.x, self.y)
plt.quiver(self.x, self.y, -Xval*self.y, Xval*self.x,\
color='b', units='x', linewidths=(2,), edgecolors=('k'), headaxislength=5)
plt.gca().add_patch(mpatches.Circle((0,0), 1, fc = 'w', ec = 'k', zorder = 0, linestyle = 'dashed'))
plt.title(self.__str__() + "\n As Tangent Vector Field")
plt.show()
def plot_as_normal_vector_field(self):
u = np.cos(self.t)
v = np.sin(self.t)
plt.figure(figsize = (4,4))
plt.axes(polar = True)
plt.plot(self.t, (np.vectorize(self.X)(u, v)+1))
plt.plot(self.t, np.ones(self.aughsmplsz), linestyle = 'dashed', color = 'k')
plt.title(self.__str__() + "\n As Normal Vector Field")
plt.show()
def plot_in_tangent_bundle(self):
ss, tt = np.meshgrid(self.s, self.t)
X = np.cos(tt)
Y = np.sin(tt)
Z = ss
fig = plt.figure(figsize = (4,4))
ax = plt.gca(projection = '3d')
plt.plot(np.sin(self.t), np.cos(self.t), 0, linestyle = 'dashed', color = 'k')
plt.plot(np.sin(self.t), np.cos(self.t), np.vectorize(self.X)(np.cos(self.t),np.sin(self.t)), color = 'r')
plt.title(self.__str__() + "\n In Tangent Bundle")
ax.plot_surface(X, Y, Z, alpha = 0.3, linewidth = 0.0, color = 'g', antialiased = True)
plt.show()
def __add__(self, other):
return VectorFieldOverS1(lambda x, y: self.X(x,y) + other.X(x,y))
def __sub__(self, other):
return VectorFieldOverS1(lambda x, y: self.X(x,y) - other.X(x,y))
def composite(self, other):
GY = Gradient(other.X)
Z = lambda x, y: self.X(x,y)*np.dot(GY(x,y), np.array([-y, x]))
return VectorFieldOverS1(Z)
def __mul__(self, other):
GY = Gradient(other.X)
GX = Gradient(self.X)
Z = lambda x, y: self.X(x,y)*np.dot(GY(x,y), np.array([-y, x])) - other.X(x,y)*np.dot(GX(x,y), np.array([-y, x]))
return VectorFieldOverS1(Z)
def __neg__(self):
return VectorFieldOverS1(lambda x, y: -self.X(x,y))