From e9d41ab95fd210562d6f23b9da02a9346172b1c5 Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Fri, 5 Jul 2013 16:00:19 -0700 Subject: [PATCH] Changed Mesh to BaseMesh. Added conventions of n{C-F-E}{x-y-z} so mesh.nCx will return the number of cells in the x direction. Added a unitTest to ensure the mesh dimensions. --- code/BaseMesh.py | 179 ++++++++++++++++++++++++++++++++++++ code/Mesh.py | 130 -------------------------- code/tests/test_basemesh.py | 88 ++++++++++++++++++ code/tests/test_mesh.py | 74 --------------- 4 files changed, 267 insertions(+), 204 deletions(-) create mode 100644 code/BaseMesh.py delete mode 100644 code/Mesh.py create mode 100644 code/tests/test_basemesh.py delete mode 100644 code/tests/test_mesh.py diff --git a/code/BaseMesh.py b/code/BaseMesh.py new file mode 100644 index 00000000..90ad07f3 --- /dev/null +++ b/code/BaseMesh.py @@ -0,0 +1,179 @@ +import numpy as np + + +class BaseMesh(object): + """BaseMesh does all the counting you don't want to do.""" + 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 diff --git a/code/Mesh.py b/code/Mesh.py deleted file mode 100644 index 8ca87165..00000000 --- a/code/Mesh.py +++ /dev/null @@ -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()) diff --git a/code/tests/test_basemesh.py b/code/tests/test_basemesh.py new file mode 100644 index 00000000..88655c60 --- /dev/null +++ b/code/tests/test_basemesh.py @@ -0,0 +1,88 @@ +import unittest +import sys +sys.path.append('../') +from BaseMesh import BaseMesh +import numpy as np + + +class TestMeshNumbers3D(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() diff --git a/code/tests/test_mesh.py b/code/tests/test_mesh.py deleted file mode 100644 index a700391f..00000000 --- a/code/tests/test_mesh.py +++ /dev/null @@ -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()