Small refactor (VectorField) and add some examples

This commit is contained in:
Chris Hodapp 2021-06-08 20:17:17 -04:00 committed by Chris Hodapp
parent fb30ca862e
commit 8ca32a67dd

View File

@ -13,49 +13,13 @@ from vispy.scene import visuals
import opensimplex
def curl_3d(grads: np.array) -> np.array:
"""Computes curl from an array of gradients.
'grads' should have shape (N1, N2, ..., 3, 3). Each 3x3 matrix in
should be the Jacobian of the function at some point.
Each output vector is the (x,y,z) coordinates of the curl at that
corresponding point.
Parameters:
grads -- numpy array of gradients, shape (..., 3, 3)
Returns:
numpy array of shape (..., 3) containing curl vectors
"""
cx = grads[..., 2, 1] - grads[..., 1, 2]
cy = grads[..., 0, 2] - grads[..., 2, 0]
cz = grads[..., 1, 0] - grads[..., 0, 1]
return np.stack((cx, cy, cz), axis=-1)
# TODO: Make VectorField class that defines grad and curl?
class Potential(object):
"""Represents a potential function for a vector field."""
def __init__(self):
self.x_spx = opensimplex.OpenSimplex(seed=0)
self.y_spx = opensimplex.OpenSimplex(seed=12345)
self.z_spx = opensimplex.OpenSimplex(seed=45678)
class VectorField(object):
def eval(self, x: float, y: float, z: float) -> np.array:
"""Evaluates potential function at a single point (x,y,z).
Returns a numpy array of the 3-dimensional vector.
"""
y2 = y + 0.2*math.sin(1*x) + 0.2*math.sin(1.25*z)
x2 = x
z2 = z
f1 = np.array([
self.x_spx.noise3d(x2, y2, z2),
self.y_spx.noise3d(x2, y2, z2),
self.z_spx.noise3d(x2, y2, z2),
])
f2 = np.array([z*0.5, 0, 0])
return f1# + f2
raise Exception("Not implemented")
def grad(self, x: float, y: float, z: float, eps: float=1e-3) -> np.array:
"""Returns an array with this potential function's gradients.
@ -81,18 +45,84 @@ class Potential(object):
p_dy = self.eval(x, y+eps, z)
p_dz = self.eval(x, y, z+eps)
return (np.stack((p_dx, p_dy, p_dz)) - p).T / eps
@staticmethod
def curl_3d(grads: np.array) -> np.array:
"""Computes curl from an array of gradients.
'grads' should have shape (N1, N2, ..., 3, 3). Each 3x3 matrix in
should be the Jacobian of the function at some point.
Each output vector is the (x,y,z) coordinates of the curl at that
corresponding point.
Parameters:
grads -- numpy array of gradients, shape (..., 3, 3)
Returns:
numpy array of shape (..., 3) containing curl vectors
"""
cx = grads[..., 2, 1] - grads[..., 1, 2]
cy = grads[..., 0, 2] - grads[..., 2, 0]
cz = grads[..., 1, 0] - grads[..., 0, 1]
return np.stack((cx, cy, cz), axis=-1)
class SimplexPotential(VectorField):
"""Represents a potential function for a vector field."""
def __init__(self):
self.x_spx = opensimplex.OpenSimplex(seed=0)
self.y_spx = opensimplex.OpenSimplex(seed=12345)
self.z_spx = opensimplex.OpenSimplex(seed=45678)
def eval(self, x: float, y: float, z: float) -> np.array:
y2 = y + 0.1*math.sin(1*x) + 0.1*math.sin(1.25*z)
x2 = x
z2 = z
f1 = np.array([
self.x_spx.noise3d(x2, y2, z2),
self.y_spx.noise3d(x2, y2, z2),
self.z_spx.noise3d(x2, y2, z2),
])
f2 = np.array([z*0.5, 0, 0])
return f1 + f2
class TentacleWtf(VectorField):
def eval(self, x: float, y: float, z: float) -> np.array:
x2 = x + 0.05*math.sin(4*y) + 0.2*math.sin(4.25*z)
y2 = y
z2 = 0
f = 1.0
x3 = x2*math.cos(f*y2) - z2*math.sin(f*y2)
z3 = x2*math.sin(f*y2) + z2*math.cos(f*y2)
y3 = y2
f1 = np.array([
x3, y3, z3,
])
return f1
class KindaTwist(VectorField):
def eval(self, x: float, y: float, z: float) -> np.array:
f = 2.0
x2 = x*math.cos(f*y) - z*math.sin(f*y)
z2 = x*math.sin(f*y) + z*math.cos(f*y)
y2 = 0
x3 = 0.5*z2
y3 = y2
z3 = 0
f1 = np.array([
x3, y3, z3,
])
return f1
def generate(grid):
p = Potential()
p = KindaTwist()
grads = np.array([p.grad(*pt) for pt in grid])
curl = curl_3d(grads)
curl = p.curl_3d(grads)
return curl
class Data(object):
def __init__(self, view):
self.use_tubes = False
self.view = view
s = 0.1
s = 0.15
self.s = s
count = 8
xs = zs = np.linspace(-s, s, count)