This commit is contained in:
Lars Ruthotto committed 2013-07-10 09:07:34 -07:00
commit f359e70662
27 files changed
+759 -230

No files matched your search

+205
View File
@@ -0,0 +1,205 @@
import numpy as np
class BaseMesh(object):
"""BaseMesh does all the counting you don't want to do.
x0 origin ndarray (dim, )
n number of cells ndarray (dim, )
dim dimension of mesh int 1, 2, or 3
nCx num cells in x dir int
nCy num cells in y dir int
nCz num cells in z dir int
nC total number of cells int
nNx num nodes in x dir int
nNy num nodes in y dir int
nNz num nodes in z dir int
nN total number of nodes int
nEx num edges in x dir ndarray [nEx_x, nEx_y, nEx_z]
nEy num edges in y dir ndarray [nEy_x, nEy_y, nEy_z]
nEz num edges in z dir ndarray [nEz_x, nEz_y, nEz_z]
nE total number of edges ndarray (dim, )
nFx num faces in x dir ndarray [nFx_x, nFx_y, nFx_z]
nFy num faces in y dir ndarray [nFy_x, nFy_y, nFy_z]
nFz num faces in z dir ndarray [nFz_x, nFz_y, nFz_z]
nF total number of faces ndarray (dim, )
"""
def __init__(self, n, x0=None):
# Check inputs
if x0 is None:
x0 = np.zeros(len(n))
if not len(n) == len(x0):
raise Exception("Dimension mismatch. x0 != len(n)")
if len(n) > 3:
raise Exception("Dimensions higher than 3 are not supported.")
# Ensure x0 & n are 1D vectors
self._n = np.array(n, dtype=int).ravel()
self._x0 = np.array(x0).ravel()
self._dim = len(n)
def x0():
doc = "Origin of the mesh"
fget = lambda self: self._x0
return locals()
x0 = property(**x0())
def n():
doc = "Number of Cells in each dimension (array of integers)"
fget = lambda self: self._n
return locals()
n = property(**n())
def dim():
doc = "The dimension of the mesh (1, 2, or 3)."
fget = lambda self: self._dim
return locals()
dim = property(**dim())
def nCx():
doc = "Number oc cells in the x direction"
fget = lambda self: self.n[0]
return locals()
nCx = property(**nCx())
def nCy():
doc = "Number of cells in the y direction"
def fget(self):
if self.dim > 1:
return self.n[1]
else:
return None
return locals()
nCy = property(**nCy())
def nCz():
doc = "Number of cells in the z direction"
def fget(self):
if self.dim > 2:
return self.n[2]
else:
return None
return locals()
nCz = property(**nCz())
def nC():
doc = "Total number of cells"
fget = lambda self: np.prod(self.n)
return locals()
nC = property(**nC())
def nNx():
doc = "Number of nodes in the x-direction"
fget = lambda self: self.nCx + 1
return locals()
nNx = property(**nNx())
def nNy():
doc = "Number of noes in the y-direction"
def fget(self):
if self.dim > 1:
return self.n[1] + 1
else:
return None
return locals()
nNy = property(**nNy())
def nNz():
doc = "Number of nodes in the z-direction"
def fget(self):
if self.dim > 2:
return self.n[2] + 1
else:
return None
return locals()
nNz = property(**nNz())
def nN():
doc = "Total number of nodes"
fget = lambda self: self.n + 1
return locals()
nN = property(**nN())
def nEx():
doc = "Number of x-edges"
fget = lambda self: np.array([x for x in [self.nCx, self.nNy, self.nNz] if not x is None])
return locals()
nEx = property(**nEx())
def nEy():
doc = "Number of y-edges"
def fget(self):
if self.dim > 1:
return np.array([x for x in [self.nNx, self.nCy, self.nNz] if not x is None])
else:
return None
return locals()
nEy = property(**nEy())
def nEz():
doc = "Number of z-edges"
def fget(self):
if self.dim > 2:
return np.array([x for x in [self.nNx, self.nNy, self.nCz] if not x is None])
else:
return None
return locals()
nEz = property(**nEz())
def nE():
doc = "Total number of edges"
fget = lambda self: np.array([np.prod(x) for x in [self.nEx, self.nEy, self.nEz] if not x is None])
return locals()
nE = property(**nE())
def nFx():
doc = "Number of x-faces"
fget = lambda self: np.array([x for x in [self.nNx, self.nCy, self.nCz] if not x is None])
return locals()
nFx = property(**nFx())
def nFy():
doc = "Number of y-faces"
def fget(self):
if self.dim > 1:
return np.array([x for x in [self.nCx, self.nNy, self.nCz] if not x is None])
else:
return None
return locals()
nFy = property(**nFy())
def nFz():
doc = "Number of z-faces"
def fget(self):
if self.dim > 2:
return np.array([x for x in [self.nCx, self.nCy, self.nNz] if not x is None])
else:
return None
return locals()
nFz = property(**nFz())
def nF():
doc = "Total number of faces in each dimension"
fget = lambda self: np.array([np.prod(x) for x in [self.nFx, self.nFy, self.nFz] if not x is None])
return locals()
nF = property(**nF())
if __name__ == '__main__':
m = BaseMesh([3, 2, 4])
print m.n
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-130
View File
@@ -1,130 +0,0 @@
import numpy as np
class Mesh(object):
"""docstring for Mesh"""
def __init__(self, h):
if type(h) != list:
raise Exception("Type of h must be a list variable. e.g. [5, 4, 2] or [[1,1,1],[0.5,0.5]]")
if np.sum([np.size(x) for x in h]) == len(h):
# We have specified a shorthand for the mesh e.g. [5, 4, 2]
# We will recreate the h, such that it lies on the unit cube/square/line
domain = 1. # (must be a float)
h = [np.ones(x)*(domain/x) for x in h]
dim = len(h)
if dim > 1 and np.all([len(np.shape(x)) > 1 and np.shape(x)[1] > 1 for x in h]):
# The h has internal structure, and is not a vector
# Thus, we must be describing the verticies of the mesh
# Hence, the mesh is a Logically Orthogonal Mesh
self.meshType = 'LOM'
else:
# Could add other checks, but here the default is a rectangular mesh
self.meshType = 'RECT'
if self.meshType != 'LOM':
# Ensure that the h is a numpy array, with shape: (n,)
h = [np.array(x).ravel() for x in h]
# Define the number of nodes
if self.meshType == 'LOM':
self._nnodes = np.array(np.shape(h[0]))
else:
self._nnodes = np.array([len(x) for x in h]) + 1
self._nc = self._nnodes - 1
self._ncells = np.prod(self._nc)
self._h = h
self._dim = dim
m = self._nnodes
if dim == 1:
self._nfaces = np.prod(m)
self._nedges = np.prod(m)
elif dim == 2:
self._nfx = m - [0, 1]
self._nfy = m - [1, 0]
self._nex = m - [1, 0]
self._ney = m - [0, 1]
self._nfaces = [np.prod(self.nfx), np.prod(self.nfy)]
self._nedges = [np.prod(self.nex), np.prod(self.ney)]
elif dim == 3:
self._nfx = m - [0, 1, 1]
self._nfy = m - [1, 0, 1]
self._nfz = m - [1, 1, 0]
self._nex = m - [1, 0, 0]
self._ney = m - [0, 1, 0]
self._nez = m - [0, 0, 1]
self._nfaces = [np.prod(self.nfx), np.prod(self.nfy), np.prod(self.nfz)]
self._nedges = [np.prod(self.nex), np.prod(self.ney), np.prod(self.nez)]
def dim():
doc = "The dimension of the mesh: 1, 2, or 3"
fget = lambda self: self._dim
return locals()
dim = property(**dim())
def nc():
doc = "Number of cells in each direction of the mesh"
fget = lambda self: self._nc
return locals()
nc = property(**nc())
def ncells():
doc = "Number of cells in the mesh"
fget = lambda self: self._ncells
return locals()
ncells = property(**ncells())
def nfaces():
doc = "Number of faces in each direction of the mesh"
fget = lambda self: self._nfaces
return locals()
nfaces = property(**nfaces())
def nedges():
doc = "Number of edges in each direction of the mesh"
fget = lambda self: self._nedges
return locals()
nedges = property(**nedges())
def nfx():
doc = "Number of faces in the x direction of the mesh"
fget = lambda self: self._nfx if self.dim > 1 else None
return locals()
nfx = property(**nfx())
def nfy():
doc = "Number of faces in the y direction of the mesh"
fget = lambda self: self._nfy if self.dim > 1 else None
return locals()
nfy = property(**nfy())
def nfz():
doc = "Number of faces in the z direction of the mesh"
fget = lambda self: self._nfz if self.dim > 2 else None
return locals()
nfz = property(**nfz())
def nex():
doc = "Number of edges in the x direction of the mesh"
fget = lambda self: self._nex if self.dim > 1 else None
return locals()
nex = property(**nex())
def ney():
doc = "Number of edges in the y direction of the mesh"
fget = lambda self: self._ney if self.dim > 1 else None
return locals()
ney = property(**ney())
def nez():
doc = "Number of edges in the z direction of the mesh"
fget = lambda self: self._nez if self.dim > 2 else None
return locals()
nez = property(**nez())
+144
View File
@@ -0,0 +1,144 @@
import numpy as np
from utils import ndgrid
class TensorGrid(object):
"""
Define nodal, cell-centered and staggered tensor grids for 1, 2 and 3
dimensions.
This class is inherited by TensorMesh
"""
def __init__(self):
pass
def vectorNx():
doc = "Nodal grid vector (1D) in the x direction."
fget = lambda self: np.r_[0., self.hx.cumsum()] + self.x0[0]
return locals()
vectorNx = property(**vectorNx())
def vectorNy():
doc = "Nodal grid vector (1D) in the y direction."
fget = lambda self: None if self.dim < 2 else np.r_[0., self.hy.cumsum()] + self.x0[1]
return locals()
vectorNy = property(**vectorNy())
def vectorNz():
doc = "Nodal grid vector (1D) in the z direction."
fget = lambda self: None if self.dim < 3 else np.r_[0., self.hz.cumsum()] + self.x0[2]
return locals()
vectorNz = property(**vectorNz())
def vectorCCx():
doc = "Cell-centered grid vector (1D) in the x direction."
fget = lambda self: np.r_[0, self.hx[:-1].cumsum()] + self.hx*0.5 + self.x0[0]
return locals()
vectorCCx = property(**vectorCCx())
def vectorCCy():
doc = "Cell-centered grid vector (1D) in the y direction."
fget = lambda self: None if self.dim < 2 else np.r_[0, self.hy[:-1].cumsum()] + self.hy*0.5 + self.x0[1]
return locals()
vectorCCy = property(**vectorCCy())
def vectorCCz():
doc = "Cell-centered grid vector (1D) in the z direction."
fget = lambda self: None if self.dim < 3 else np.r_[0, self.hz[:-1].cumsum()] + self.hz*0.5 + self.x0[2]
return locals()
vectorCCz = property(**vectorCCz())
def gridCC():
doc = "Cell-centered grid."
def fget(self):
if self._gridCC is None:
self._gridCC = ndgrid([x for x in [self.vectorCCx, self.vectorCCy, self.vectorCCz] if not x is None])
return self._gridCC
return locals()
_gridCC = None # Store grid by default
gridCC = property(**gridCC())
def gridN():
doc = "Nodal grid."
def fget(self):
if self._gridN is None:
self._gridN = ndgrid([x for x in [self.vectorNx, self.vectorNy, self.vectorNz] if not x is None])
return self._gridN
return locals()
_gridN = None # Store grid by default
gridN = property(**gridN())
def gridFx():
doc = "Face staggered grid in the x direction."
def fget(self):
if self._gridFx is None:
self._gridFx = ndgrid([x for x in [self.vectorNx, self.vectorCCy, self.vectorCCz] if not x is None])
return self._gridFx
return locals()
_gridFx = None # Store grid by default
gridFx = property(**gridFx())
def gridFy():
doc = "Face staggered grid in the y direction."
def fget(self):
if self._gridFy is None:
self._gridFy = ndgrid([x for x in [self.vectorCCx, self.vectorNy, self.vectorCCz] if not x is None])
return self._gridFy
return locals()
_gridFy = None # Store grid by default
gridFy = property(**gridFy())
def gridFz():
doc = "Face staggered grid in the z direction."
def fget(self):
if self._gridFz is None:
self._gridFz = ndgrid([x for x in [self.vectorCCx, self.vectorCCy, self.vectorNz] if not x is None])
return self._gridFz
return locals()
_gridFz = None # Store grid by default
gridFz = property(**gridFz())
def gridEx():
doc = "Edge staggered grid in the x direction."
def fget(self):
if self._gridEx is None:
self._gridEx = ndgrid([x for x in [self.vectorCCx, self.vectorNy, self.vectorNz] if not x is None])
return self._gridEx
return locals()
_gridEx = None # Store grid by default
gridEx = property(**gridEx())
def gridEy():
doc = "Edge staggered grid in the y direction."
def fget(self):
if self._gridEy is None:
self._gridEy = ndgrid([x for x in [self.vectorNx, self.vectorCCy, self.vectorNz] if not x is None])
return self._gridEy
return locals()
_gridEy = None # Store grid by default
gridEy = property(**gridEy())
def gridEz():
doc = "Edge staggered grid in the z direction."
def fget(self):
if self._gridEz is None:
self._gridEz = ndgrid([x for x in [self.vectorNx, self.vectorNy, self.vectorCCz] if not x is None])
return self._gridEz
return locals()
_gridEz = None # Store grid by default
gridEz = property(**gridEz())
def getBoundaryIndex(self, gridType):
"""Needed for faces edges and cells"""
pass
def getCellNumbering(self):
pass
+82
View File
@@ -0,0 +1,82 @@
import numpy as np
from BaseMesh import BaseMesh
from TensorGrid import TensorGrid
from TensorView import TensorView
class TensorMesh(BaseMesh, TensorGrid, TensorView):
"""
TensorMesh is a mesh class that deals with tensor product meshes.
Any Mesh that has a constant width along the entire axis
such that it can defined by a single width vector, called 'h'.
e.g.
hx = np.array([1,1,1])
hy = np.array([1,2])
hz = np.array([1,1,1,1])
mesh = TensorMesh([hx, hy, hz])
"""
def __init__(self, h, x0=None):
super(TensorMesh, self).__init__(np.array([len(x) for x in h]), x0)
assert len(h) == len(x0), "Dimension mismatch. x0 != len(h)"
for i, h_i in enumerate(h):
assert type(h_i) == np.ndarray, ("h[%i] is not a numpy array." % i)
# Ensure h contains 1D vectors
self._h = [x.ravel() for x in h]
def h():
doc = "h is a list containing the cell widths of the tensor mesh in each dimension."
fget = lambda self: self._h
return locals()
h = property(**h())
def hx():
doc = "Width of cells in the x direction"
fget = lambda self: self._h[0]
return locals()
hx = property(**hx())
def hy():
doc = "Width of cells in the y direction"
fget = lambda self: None if self.dim < 2 else self._h[1]
return locals()
hy = property(**hy())
def hz():
doc = "Width of cells in the z direction"
fget = lambda self: None if self.dim < 3 else self._h[2]
return locals()
hz = property(**hz())
if __name__ == '__main__':
print('Welcome to tensor mesh!')
testDim = 1
h1 = 0.3*np.ones((1, 7))
h1[:, 0] = 0.5
h1[:, -1] = 0.6
h2 = .5 * np.ones((1, 4))
h3 = .4 * np.ones((1, 6))
x0 = np.zeros((3, 1))
if testDim == 1:
h = [h1]
x0 = x0[0]
elif testDim == 2:
h = [h1, h2]
x0 = x0[0:2]
else:
h = [h1, h2, h3]
I = np.linspace(0, 1, 8)
M = TensorMesh(h, x0)
xn = M.plotGrid()
+96
View File
@@ -0,0 +1,96 @@
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
class TensorView(object):
"""
Provides viewing functions for TensorMesh
This class is inherited by TensorMesh
"""
def __init__(self):
pass
def plotImage(self, I):
if self.dim == 1:
fig = plt.figure(1)
fig.clf()
ax = plt.subplot(111)
if np.size(I) == self.n[0]:
print 'cell-centered image'
xx = self.gridCC
ax.plot(xx[0], I, 'ro')
elif np.size(I) == self.n[0]+1:
print 'nodal image'
xx = self.gridN
ax.plot(xx[0], I, 'bs')
fig.show()
def plotGrid(self):
"""Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions."""
if self.dim == 1:
fig = plt.figure(1)
fig.clf()
ax = plt.subplot(111)
xn = self.gridN
xc = self.gridCC
print xn
ax.hold(True)
ax.plot(xn, np.ones(np.shape(xn)), 'bs')
ax.plot(xc, np.ones(np.shape(xc)), 'ro')
ax.plot(xn, np.ones(np.shape(xn)), 'k--')
ax.grid(True)
ax.hold(False)
ax.set_xlabel('x1')
fig.show()
elif self.dim == 2:
fig = plt.figure(2)
fig.clf()
ax = plt.subplot(111)
xn = self.gridN
xc = self.gridCC
xs1 = self.gridFx
xs2 = self.gridFy
ax.hold(True)
ax.plot(xn[:, 0], xn[:, 1], 'bs')
ax.plot(xc[:, 0], xc[:, 1], 'ro')
ax.plot(xs1[:, 0], xs1[:, 1], 'g>')
ax.plot(xs2[:, 0], xs2[:, 1], 'g^')
ax.grid(True)
ax.hold(False)
ax.set_xlabel('x1')
ax.set_ylabel('x2')
fig.show()
elif self.dim == 3:
fig = plt.figure(3)
fig.clf()
ax = fig.add_subplot(111, projection='3d')
xn = self.gridN
xc = self.gridCC
xfs1 = self.gridFx
xfs2 = self.gridFy
xfs3 = self.gridFz
xes1 = self.gridEx
xes2 = self.gridEy
xes3 = self.gridEz
ax.hold(True)
ax.plot(xn[:, 0], xn[:, 1], 'bs', zs=xn[:, 2])
ax.plot(xc[:, 0], xc[:, 1], 'ro', zs=xc[:, 2])
ax.plot(xfs1[:, 0], xfs1[:, 1], 'g>', zs=xfs1[:, 2])
ax.plot(xfs2[:, 0], xfs2[:, 1], 'g<', zs=xfs2[:, 2])
ax.plot(xfs3[:, 0], xfs3[:, 1], 'g^', zs=xfs3[:, 2])
ax.plot(xes1[:, 0], xes1[:, 1], 'k>', zs=xes1[:, 2])
ax.plot(xes2[:, 0], xes2[:, 1], 'k<', zs=xes2[:, 2])
ax.plot(xes3[:, 0], xes3[:, 1], 'k^', zs=xes3[:, 2])
ax.grid(True)
ax.hold(False)
ax.set_xlabel('x1')
ax.set_ylabel('x2')
ax.set_zlabel('x3')
fig.show()
-3
View File
@@ -1,3 +0,0 @@
# init.py
from test_mesh import *
+11
View File
@@ -0,0 +1,11 @@
import glob
import unittest
# This code will run all tests in directory named test_*.py
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
suites = [unittest.defaultTestLoader.loadTestsFromName(str) for str
in module_strings]
testSuite = unittest.TestSuite(suites)
text_runner = unittest.TextTestRunner().run(testSuite)
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
python -m unittest discover
+88
View File
@@ -0,0 +1,88 @@
import unittest
import sys
sys.path.append('../')
from BaseMesh import BaseMesh
import numpy as np
class TestBaseMesh(unittest.TestCase):
def setUp(self):
self.mesh = BaseMesh([6, 2, 3])
def test_meshDimensions(self):
self.assertTrue(self.mesh.dim, 3)
def test_mesh_nc(self):
self.assertTrue(np.all(self.mesh.n == [6, 2, 3]))
def test_mesh_nc_xyz(self):
x = np.all(self.mesh.nCx == 6)
y = np.all(self.mesh.nCy == 2)
z = np.all(self.mesh.nCz == 3)
self.assertTrue(np.all([x, y, z]))
def test_mesh_nf(self):
x = np.all(self.mesh.nFx == [7, 2, 3])
y = np.all(self.mesh.nFy == [6, 3, 3])
z = np.all(self.mesh.nFz == [6, 2, 4])
self.assertTrue(np.all([x, y, z]))
def test_mesh_ne(self):
x = np.all(self.mesh.nEx == [6, 3, 4])
y = np.all(self.mesh.nEy == [7, 2, 4])
z = np.all(self.mesh.nEz == [7, 3, 3])
self.assertTrue(np.all([x, y, z]))
def test_mesh_numbers(self):
c = self.mesh.nC == 36
f = np.all(self.mesh.nF == [42, 54, 48])
e = np.all(self.mesh.nE == [72, 56, 63])
self.assertTrue(np.all([c, f, e]))
class TestMeshNumbers2D(unittest.TestCase):
def setUp(self):
self.mesh = BaseMesh([6, 2])
def test_meshDimensions(self):
self.assertTrue(self.mesh.dim, 2)
def test_mesh_nc(self):
self.assertTrue(np.all(self.mesh.n == [6, 2]))
def test_mesh_nc_xyz(self):
x = np.all(self.mesh.nCx == 6)
y = np.all(self.mesh.nCy == 2)
z = self.mesh.nCz is None
self.assertTrue(np.all([x, y, z]))
def test_mesh_nf(self):
x = np.all(self.mesh.nFx == [7, 2])
y = np.all(self.mesh.nFy == [6, 3])
z = self.mesh.nFz is None
self.assertTrue(np.all([x, y, z]))
def test_mesh_ne(self):
x = np.all(self.mesh.nEx == [6, 3])
y = np.all(self.mesh.nEy == [7, 2])
z = self.mesh.nEz is None
self.assertTrue(np.all([x, y, z]))
def test_mesh_numbers(self):
c = self.mesh.nC == 12
f = np.all(self.mesh.nF == [14, 18])
e = np.all(self.mesh.nE == [18, 14])
self.assertTrue(np.all([c, f, e]))
if __name__ == '__main__':
unittest.main()
-74
View File
@@ -1,74 +0,0 @@
import unittest
import sys
sys.path.append('../')
from Mesh import Mesh
import numpy as np
class TestMeshNumbers3D(unittest.TestCase):
def setUp(self):
self.mesh = Mesh([6, 2, 3])
def test_meshDimensions(self):
self.assertTrue(self.mesh.dim, 3)
def test_mesh_nc(self):
self.assertTrue(np.all(self.mesh.nc == [6, 2, 3]))
def test_mesh_nf(self):
x = np.all(self.mesh.nfx == [7, 2, 3])
y = np.all(self.mesh.nfy == [6, 3, 3])
z = np.all(self.mesh.nfz == [6, 2, 4])
self.assertTrue(np.all([x, y, z]))
def test_mesh_ne(self):
x = np.all(self.mesh.nex == [6, 3, 4])
y = np.all(self.mesh.ney == [7, 2, 4])
z = np.all(self.mesh.nez == [7, 3, 3])
self.assertTrue(np.all([x, y, z]))
def test_mesh_numbers(self):
c = self.mesh.ncells == 36
f = np.all(self.mesh.nfaces == [42, 54, 48])
e = np.all(self.mesh.nedges == [72, 56, 63])
self.assertTrue(np.all([c, f, e]))
class TestMeshNumbers2D(unittest.TestCase):
def setUp(self):
self.mesh = Mesh([6, 2])
def test_meshDimensions(self):
self.assertTrue(self.mesh.dim, 2)
def test_mesh_nc(self):
self.assertTrue(np.all(self.mesh.nc == [6, 2]))
def test_mesh_nf(self):
x = np.all(self.mesh.nfx == [7, 2])
y = np.all(self.mesh.nfy == [6, 3])
z = self.mesh.nfz is None
self.assertTrue(np.all([x, y, z]))
def test_mesh_ne(self):
x = np.all(self.mesh.nex == [6, 3])
y = np.all(self.mesh.ney == [7, 2])
z = self.mesh.nez is None
self.assertTrue(np.all([x, y, z]))
def test_mesh_numbers(self):
c = self.mesh.ncells == 12
f = np.all(self.mesh.nfaces == [14, 18])
e = np.all(self.mesh.nedges == [18, 14])
self.assertTrue(np.all([c, f, e]))
if __name__ == '__main__':
unittest.main()
+34
View File
@@ -0,0 +1,34 @@
import numpy as np
import unittest
import sys
sys.path.append('../')
from TensorMesh import TensorMesh
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
a = np.array([1, 1, 1])
b = np.array([1, 2])
x0 = np.array([3, 5])
self.mesh2 = TensorMesh([a, b], x0)
def test_vectorN_2D(self):
testNx = np.array([3, 4, 5, 6])
testNy = np.array([5, 6, 8])
xtest = np.all(self.mesh2.vectorNx == testNx)
ytest = np.all(self.mesh2.vectorNy == testNy)
self.assertTrue(xtest and ytest)
def test_vectorCC_2D(self):
testNx = np.array([3.5, 4.5, 5.5])
testNy = np.array([5.5, 7])
xtest = np.all(self.mesh2.vectorCCx == testNx)
ytest = np.all(self.mesh2.vectorCCy == testNy)
self.assertTrue(xtest and ytest)
if __name__ == '__main__':
unittest.main()
+53
View File
@@ -0,0 +1,53 @@
import numpy as np
import unittest
import sys
sys.path.append('../')
from utils import mkvc, ndgrid
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.a = np.array([1, 2, 3])
self.b = np.array([1, 2])
self.c = np.array([1, 2, 3, 4])
def test_mkvc1(self):
x = mkvc(self.a)
self.assertTrue(x.shape, (3,))
def test_mkvc2(self):
x = mkvc(self.a, 2)
self.assertTrue(x.shape, (3, 1))
def test_mkvc3(self):
x = mkvc(self.a, 3)
self.assertTrue(x.shape, (3, 1, 1))
def test_ndgrid_2D(self):
XY = ndgrid([self.a, self.b])
X1_test = np.array([1, 2, 3, 1, 2, 3])
X2_test = np.array([1, 1, 1, 2, 2, 2])
xtest = np.all(XY[:, 0] == X1_test)
ytest = np.all(XY[:, 1] == X2_test)
self.assertTrue(xtest and ytest)
def test_ndgrid_3D(self):
XYZ = ndgrid([self.a, self.b, self.c])
X1_test = np.array([1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3])
X2_test = np.array([1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2])
X3_test = np.array([1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4])
xtest = np.all(XYZ[:, 0] == X1_test)
ytest = np.all(XYZ[:, 1] == X2_test)
ztest = np.all(XYZ[:, 2] == X3_test)
self.assertTrue(xtest and ytest and ztest)
if __name__ == '__main__':
unittest.main()
+43 -23
View File
@@ -1,4 +1,5 @@
from numpy import *
import numpy as np
def diff(A, d):
@@ -43,35 +44,54 @@ def ave(A, d):
print('d must be 1,2 or 3')
def reshapeF(sp, d):
return reshape(sp, d, 'F')
def reshapeF(x, size):
return np.reshape(x, size, order='F')
def mkvc(A):
return reshape(A, [size(A), 1], 'F').flatten()
def mkvc(x, numDims=1):
"""Creates a vector with the number of dimension specified
e.g.:
a = np.array(1,2,3)
mkvc(a, 1).shape
> (3, )
mkvc(a, 2).shape
> (3, 1)
mkvc(a, 3).shape
> (3, 1, 1)
"""
assert type(x) == np.ndarray, "Vector must be a numpy array"
if numDims == 1:
return x.flatten(order='F')
elif numDims == 2:
return x.flatten(order='F')[:, np.newaxis]
elif numDims == 3:
return x.flatten(order='F')[:, np.newaxis, np.newaxis]
def ndgrid(x, y, z):
def ndgrid(*args):
"""Form tensorial grid for 1, 2 and 3 dimensions. Return X1,X2,X3 arrays depending on the dimension"""
n1 = size(x)
n2 = size(y)
n3 = size(z)
X = zeros([n1, n2, n3])
Y = zeros([n1, n2, n3])
Z = zeros([n1, n2, n3])
for i in range(0, n2):
for j in range(0, n3):
X[:, i, j] = x
# you can either pass a list [x1, x2, x3] or each seperately
if type(args[0]) == list:
xin = args[0]
else:
xin = args
for i in range(0, n1):
for j in range(0, n3):
Y[i, :, j] = y
for i in range(0, n1):
for j in range(0, n2):
Z[i, j, :] = z
return (X, Y, Z)
if len(xin) == 1:
return xin
elif len(xin) == 2:
X2, X1 = [mkvc(x) for x in np.broadcast_arrays(mkvc(xin[1], 1), mkvc(xin[0], 2))]
return np.c_[X1, X2]
elif len(xin) == 3:
X3, X2, X1 = [mkvc(x) for x in np.broadcast_arrays(mkvc(xin[2], 1), mkvc(xin[1], 2), mkvc(xin[0], 3))]
return np.c_[X1, X2, X3]
def ind2sub(shape, ind):