diff --git a/SimPEG/Mesh/NewTreeMesh.py b/SimPEG/Mesh/NewTreeMesh.py deleted file mode 100644 index 8520f245..00000000 --- a/SimPEG/Mesh/NewTreeMesh.py +++ /dev/null @@ -1,1274 +0,0 @@ -import numpy as np, scipy.sparse as sp -from SimPEG.Utils import ndgrid, mkvc, sdiag, volTetra -from BaseMesh import BaseMesh -from InnerProducts import InnerProducts - -NUM, ACTIVE, NX, NY, NZ = range(5) # Do not put anything after NZ -NUM, ACTIVE, PARENT, EDIR, ENODE0, ENODE1 = range(6) -NUM, ACTIVE, PARENT, FDIR, FEDGE0, FEDGE1, FEDGE2, FEDGE3 = range(8) -NUM, ACTIVE, PARENT, CFACE0, CFACE1, CFACE2, CFACE3, CFACE4, CFACE5 = range(9) - -# The following classes are wrappers to make indexing easier - -class TreeIndexer(object): - def __init__(self, treeMesh, index=slice(None)): - self.M = treeMesh - if index == 'active': - array = getattr(self.M, self._pointer) - index = array[:,ACTIVE] == 1 - self.index = index - - @property - def C(self): return getattr(self.M, '_cells', None) - @property - def F(self): return getattr(self.M, '_faces', None) - @property - def E(self): return getattr(self.M, '_edges', None) - @property - def N(self): return getattr(self.M, '_nodes', None) - - def sort(self, vec): - self.M.number() - P = np.argsort(self.num) - if len(vec.shape) == 1: - return vec[P] - return vec[P,:] - - def _ind(self, column): - array = getattr(self.M, self._pointer) - ind = np.atleast_2d(array[self.index,:])[:,column] - return self._SubTree(self.M, ind) - - def at(self, index=slice(None)): - self.index = index - return self - -class TreeNode(TreeIndexer): - _SubTree = None - _pointer = '_nodes' - @property - def num(self): return self.N[self.index, NUM] - @property - def vec(self): return self.N[self.index,:][:,NX:] - @property - def x(self): return self.N[self.index,:][:,NX] - @property - def y(self): return self.N[self.index,:][:,NY] - @property - def z(self): return self.N[self.index,:][:,NZ] - -class TreeEdge(TreeIndexer): - _SubTree = TreeNode - _pointer = '_edges' - - @property - def num(self):return self.E[self.index, NUM] - @property - def dir(self):return self.E[self.index, EDIR] - @property - def isleaf(self):return self.E[self.index, ACTIVE] == 1 - - @property - def n0(self): return self._ind(ENODE0) - @property - def n1(self): return self._ind(ENODE1) - @property - def nodes(self): - return [self.n0, self.n1] - @property - def length(self): - return np.sum((self.n1.vec - self.n0.vec)**2,axis=1)**0.5 - @property - def center(self): - return (self.n0.vec + self.n1.vec)/2.0 - -class TreeFace(TreeIndexer): - _SubTree = TreeEdge - _pointer = '_faces' - - @property - def num(self):return self.F[self.index, NUM] - @property - def dir(self):return self.F[self.index, FDIR] - @property - def isleaf(self):return self.F[self.index, ACTIVE] == 1 - - # fX fY fZ - # n2___________n3 n2___________n3 n2___________n3 - # | e1 | | e1 | | e1 | - # | | | | | | - # e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y - # | | ^ | | ^ | | ^ - # |___________| |___> y |___________| |___> x |___________| |___> x - # n0 e0 n1 n0 e0 n1 n0 e0 n1 - - @property - def e0(self): return self._ind(FEDGE0) - @property - def e1(self): return self._ind(FEDGE1) - @property - def e2(self): return self._ind(FEDGE2) - @property - def e3(self): return self._ind(FEDGE3) - @property - def n0(self): return self.e0.n0 - @property - def n1(self): return self.e0.n1 - @property - def n2(self): return self.e1.n0 - @property - def n3(self): return self.e1.n1 - @property - def nodes(self): - return [self.n0, self.n1, self.n2, self.n3] - @property - def center(self): - return (self.n0.vec + self.n1.vec + self.n2.vec + self.n3.vec)/4.0 - @property - def area(self): - - n0 = self.n0.vec # 2------3 3------2 - n1 = self.n1.vec # | | ---> | | - n2 = self.n3.vec # | | | | - n3 = self.n2.vec # 0------1 0------1 - - a = np.sum((n1 - n0)**2,axis=1)**0.5 - b = np.sum((n2 - n1)**2,axis=1)**0.5 - c = np.sum((n3 - n2)**2,axis=1)**0.5 - d = np.sum((n0 - n3)**2,axis=1)**0.5 - p = np.sum((n2 - n0)**2,axis=1)**0.5 - q = np.sum((n3 - n1)**2,axis=1)**0.5 - - # Area of an arbitrary quadrilateral (in a plane) - V = 0.25 * (4.0*(p**2)*(q**2) - (a**2 + c**2 - b**2 - d**2)**2)**0.5 - return V - - @property - def children(self): - if self.isleaf: return None - ind = int(self.index) # can not get children of a fancy slice at the moment. - subInds = np.argwhere(self.F[:,PARENT] == ind).flatten() - return TreeFace(self.M, subInds) - - - def refine(self, function, level): - - int(self.index) # should only be able to refine one at a time. - - toLevel = function(self) - - if toLevel < level+1: - return - - inds, rows = self.M.refineFace(self.index) - for i in inds: - TreeFace(self.M, i).refine(function, level + 1) - - -class TreeCell(TreeIndexer): - _SubTree = TreeFace - _pointer = '_cells' - - @property - def num(self):return self.C[self.index, NUM] - @property - def isleaf(self):return self.C[self.index, ACTIVE] == 1 - - @property - def fXm(self): return self._ind(CFACE0) - @property - def fXp(self): return self._ind(CFACE1) - @property - def fYm(self): return self._ind(CFACE2) - @property - def fYp(self): return self._ind(CFACE3) - @property - def fZm(self): return self._ind(CFACE4) - @property - def fZp(self): return self._ind(CFACE5) - - # fZp - # | - # 6 ------eX3------ 7 - # /| | / | - # /eZ2 . / eZ3 - # eY2 | fYp eY3 | - # / | / fXp| - # 4 ------eX2----- 5 | - # |fXm 2 -----eX1--|---- 3 z - # eZ0 / | eY1 ^ y - # | eY0 . fYm eZ1 / | / - # | / | | / | / - # 0 ------eX0------1 o----> x - # | - # fZm - # - # - # fX fY fZ - # 2___________3 2___________3 2___________3 - # | e1 | | e1 | | e1 | - # | | | | | | - # e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y - # | | ^ | | ^ | | ^ - # |___________| |___> y |___________| |___> x |___________| |___> x - # 0 e0 1 0 e0 1 0 e0 1 - # - # Mapping Nodes: numOnFace > numOnCell - # - # fXm 0>0, 1>2, 2>4, 3>6 fYm 0>0, 1>1, 2>4, 3>5 fZm 0>0, 1>1, 2>2, 3>3 - # fXp 0>1, 1>3, 2>5, 3>7 fYp 0>2, 1>3, 2>6, 3>7 fZp 0>4, 1>5, 2>6, 3>7 - - @property - def eX0(self): return self.fZm.e0 - @property - def eX1(self): return self.fZm.e1 - @property - def eX2(self): return self.fZp.e0 - @property - def eX3(self): return self.fZp.e1 - - @property - def eY0(self): return self.fZm.e2 - @property - def eY1(self): return self.fZm.e3 - @property - def eY2(self): return self.fZp.e2 - @property - def eY3(self): return self.fZp.e3 - - @property - def eZ0(self): return self.fXm.e2 - @property - def eZ1(self): return self.fXp.e2 - @property - def eZ2(self): return self.fXm.e3 - @property - def eZ3(self): return self.fXp.e3 - - @property - def n0(self): return self.fZm.n0 - @property - def n1(self): return self.fZm.n1 - @property - def n2(self): return self.fZm.n2 - @property - def n3(self): return self.fZm.n3 - @property - def n4(self): return self.fZp.n0 - @property - def n5(self): return self.fZp.n1 - @property - def n6(self): return self.fZp.n2 - @property - def n7(self): return self.fZp.n3 - @property - def nodes(self): - return [self.n0, self.n1, self.n2, self.n3, self.n4, self.n5, self.n6, self.n7] - @property - def center(self): - return (self.n0.vec + self.n1.vec + self.n2.vec + self.n3.vec + - self.n4.vec + self.n5.vec + self.n6.vec + self.n7.vec)/8.0 - - @property - def vol(self): - # - # 6 --------------- 7 - # /| / | - # / | / | - # / | / | - # / | / | - # 4 -------------- 5 | - # | 2 ----------|---- 3 z - # | / | / ^ y - # | / | / | / - # | / | / | / - # 0 ---------------1 o----> x - - - # __ Look at the 4 (I mixed up the Z axis, sorry) - # / - n0, n1, n2, n3, n4, n5, n6, n7 = (self.n4.index, self.n5.index, self.n6.index, self.n7.index, - self.n0.index, self.n1.index, self.n2.index, self.n3.index) - - vol1 = (volTetra(self.M._nodes[:,NX:], n4, n5, n0, n6) + # cut edge top - volTetra(self.M._nodes[:,NX:], n5, n6, n7, n3) + # cut edge top - volTetra(self.M._nodes[:,NX:], n5, n0, n6, n3) + # middle - volTetra(self.M._nodes[:,NX:], n5, n1, n0, n3) + # cut edge bottom - volTetra(self.M._nodes[:,NX:], n0, n6, n3, n2)) # cut edge bottom - - vol2 = (volTetra(self.M._nodes[:,NX:], n4, n7, n5, n1) + # cut edge top - volTetra(self.M._nodes[:,NX:], n4, n6, n7, n2) + # cut edge top - volTetra(self.M._nodes[:,NX:], n4, n2, n7, n1) + # middle - volTetra(self.M._nodes[:,NX:], n1, n2, n0, n4) + # cut edge bottom - volTetra(self.M._nodes[:,NX:], n1, n3, n2, n7)) # cut edge bottom - - return (vol1 + vol2)/2.0 - - @property - def children(self): - if self.isleaf: return None - ind = int(self.index) # can not get children of a fancy slice at the moment. - subInds = np.argwhere(self.C[:,PARENT] == ind).flatten() - return TreeCell(self.M, subInds) - - def refine(self, function, level): - - int(self.index) # should only be able to refine one at a time. - - toLevel = function(self) - - if toLevel < level+1: - return - - inds, rows = self.M.refineCell(self.index) - for i in inds: - TreeCell(self.M, i).refine(function, level + 1) - - -class TreeMesh(InnerProducts, BaseMesh): - - _meshType = 'TREEMESH' - _unitDimensions = [1, 1, 1] - - def __init__(self, h_in, x0=None): - assert type(h_in) in [list, tuple], 'h_in must be a list' - assert len(h_in) > 1, "len(h_in) must be greater than 1" - - h = range(len(h_in)) - for i, h_i in enumerate(h_in): - if Utils.isScalar(h_i) and type(h_i) is not np.ndarray: - # This gives you something over the unit cube. - h_i = self._unitDimensions[i] * np.ones(int(h_i))/int(h_i) - elif type(h_i) is list: - h_i = Utils.meshTensor(h_i) - assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) - assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) - h[i] = h_i[:] # make a copy. - self.h = h - - if x0 is None: - x0 = np.zeros(len(h)) - else: - assert type(x0) in [list, tuple, np.ndarray], 'x0 must be an array' - x0 = np.array(x0, dtype=float) - assert len(x0) == self.dim, 'x0 must have the same dimensions as the mesh' - - BaseMesh.__init__(self, np.array([x.size for x in h]), x0) - if self.dim == 2: - self._init2D() - else: - self._init3D() - - self.isNumbered = False - - def _init2D(self): - XY = ndgrid(*[np.r_[0, h.cumsum()] for h in self.h]) - - nCx, nCy = [len(h) for h in self.h] - - vnC = [nCx , nCy ] - vnN = [nCx+1, nCy+1] - - vnEx = [nCx , nCy+1] - vnEy = [nCx+1, nCy ] - - vnFx = [nCx+1, nCy ] - vnFy = [nCx , nCy+1] - - nC = np.prod(vnC) - nN = np.prod(vnN) - nFx = np.prod(vnFx) - nFy = np.prod(vnFy) - nF = nFx + nFy - nEx = np.prod(vnEx) - nEy = np.prod(vnEy) - nE = nEx + nEy - - N = np.c_[np.arange(nN), np.ones(nN), XY] - - iN = np.arange(nN, dtype=int).reshape(vnN, order='F') - - # Pointers to the nodes for the edges - pnEx = np.c_[mkvc(iN[:-1,:]), mkvc(iN[1:,:])] - pnEy = np.c_[mkvc(iN[:,:-1]), mkvc(iN[:,1:])] - - iEx = np.arange(nEx, dtype=int).reshape(*vnEx, order='F') - iEy = np.arange(nEy, dtype=int).reshape(*vnEy, order='F') + nEx - - zEx = np.zeros(nEx, dtype=int) - zEy = np.zeros(nEy, dtype=int) - - Ex = np.c_[mkvc(iEx), zEx+1, zEx-1, zEx+0, pnEx] - Ey = np.c_[mkvc(iEy), zEy+1, zEy-1, zEy+1, pnEy] - - # Pointers to the edges for the faces - vFz = np.c_[mkvc(iEx[:,:-1]), mkvc(iEx[:,1:]), mkvc(iEy[:-1,:]), mkvc(iEy[1:,:])] - - iC = np.arange(nC, dtype=int) - - zC = np.zeros(nC, dtype=int) - - C = np.c_[iC, zC+1, zC-1, zC+2, vFz] - - self._nodes = N - self._edges = np.r_[Ex, Ey] - self._faces = C - - - def _init3D(self): - XYZ = ndgrid(*[np.r_[0, h.cumsum()] for h in self.h]) - - nCx, nCy, nCz = [len(h) for h in self.h] - - vnC = [nCx , nCy , nCz ] - vnN = [nCx+1, nCy+1, nCz+1] - - vnEx = [nCx , nCy+1, nCz+1] - vnEy = [nCx+1, nCy , nCz+1] - vnEz = [nCx+1, nCy+1, nCz ] - - vnFx = [nCx+1, nCy , nCz ] - vnFy = [nCx , nCy+1, nCz ] - vnFz = [nCx , nCy , nCz+1] - - nC = np.prod(vnC) - nN = np.prod(vnN) - nFx = np.prod(vnFx) - nFy = np.prod(vnFy) - nFz = np.prod(vnFz) - nF = nFx + nFy + nFz - nEx = np.prod(vnEx) - nEy = np.prod(vnEy) - nEz = np.prod(vnEz) - nE = nEx + nEy + nEz - - N = np.c_[np.arange(XYZ.shape[0]), np.ones(XYZ.shape[0]), XYZ] - - iN = np.arange(nN, dtype=int).reshape(vnN, order='F') - - # Pointers to the nodes for the edges - pnEx = np.c_[mkvc(iN[:-1,:,:]), mkvc(iN[1:,:,:])] - pnEy = np.c_[mkvc(iN[:,:-1,:]), mkvc(iN[:,1:,:])] - pnEz = np.c_[mkvc(iN[:,:,:-1]), mkvc(iN[:,:,1:])] - - iEx = np.arange(nEx, dtype=int).reshape(*vnEx, order='F') - iEy = np.arange(nEy, dtype=int).reshape(*vnEy, order='F') + nEx - iEz = np.arange(nEz, dtype=int).reshape(*vnEz, order='F') + nEx + nEy - - zEx = np.zeros(nEx, dtype=int) - zEy = np.zeros(nEy, dtype=int) - zEz = np.zeros(nEz, dtype=int) - - Ex = np.c_[mkvc(iEx), zEx+1, zEx-1, zEx+0, pnEx] - Ey = np.c_[mkvc(iEy), zEy+1, zEy-1, zEy+1, pnEy] - Ez = np.c_[mkvc(iEz), zEz+1, zEz-1, zEz+2, pnEz] - - # Pointers to the edges for the faces - peFx = np.c_[ mkvc(iEy[:,:,:-1]), mkvc(iEy[:,:,1:]), mkvc(iEz[:,:-1,:]), mkvc(iEz[:,1:,:])] - peFy = np.c_[mkvc(iEx[:,:,:-1]), mkvc(iEx[:,:,1:]), mkvc(iEz[:-1,:,:]), mkvc(iEz[1:,:,:])] - peFz = np.c_[mkvc(iEx[:,:-1,:]), mkvc(iEx[:,1:,:]), mkvc(iEy[:-1,:,:]), mkvc(iEy[1:,:,:]) ] - - iFx = np.arange(nFx, dtype=int).reshape(*vnFx, order='F') - iFy = np.arange(nFy, dtype=int).reshape(*vnFy, order='F') + nFx - iFz = np.arange(nFz, dtype=int).reshape(*vnFz, order='F') + nFx + nFy - - zFx = np.zeros(nFx, dtype=int) - zFy = np.zeros(nFy, dtype=int) - zFz = np.zeros(nFz, dtype=int) - - Fx = np.c_[mkvc(iFx), zFx+1, zFx-1, zFx+0, peFx] - Fy = np.c_[mkvc(iFy), zFy+1, zFy-1, zFy+1, peFy] - Fz = np.c_[mkvc(iFz), zFz+1, zFz-1, zFz+2, peFz] - - # Pointers to the faces for the cells - pfCx = np.c_[mkvc(iFx[:-1,:,:]), mkvc(iFx[1:,:,:])] - pfCy = np.c_[mkvc(iFy[:,:-1,:]), mkvc(iFy[:,1:,:])] - pfCz = np.c_[mkvc(iFz[:,:,:-1]), mkvc(iFz[:,:,1:])] - - iC = np.arange(nC, dtype=int) - - zC = np.zeros(nC, dtype=int) - - C = np.c_[iC, zC+1, zC-1, pfCx, pfCy, pfCz] - - self._nodes = N - self._edges = np.r_[Ex, Ey, Ez] - self._faces = np.r_[Fx, Fy, Fz] - self._cells = C - - @property - def isNumbered(self): - return self._numbered - @isNumbered.setter - def isNumbered(self, value): - assert value is False, 'Can only set to False.' - self._numbered = False - for name in ['vol', 'area', 'edge', 'gridCC', 'gridN', 'gridEx', 'gridEy', 'gridEz', 'gridFx', 'gridFy', 'gridFz']: - if hasattr(self, '_'+name): - delattr(self, '_'+name) - - def number(self): - if self._numbered: - return - - dtypeN = [('x',float),('y',float)] - if self.dim == 3: - dtypeN += [('z',float)] - dtypeV = [('v', int)] - - N = TreeNode(self, 'active') - E = TreeEdge(self, 'active') - F = TreeFace(self, 'active') - self._nodes[:,NUM] = -1 - self._edges[:,NUM] = -1 - self._faces[:,NUM] = -1 - if self.dim == 3: - C = TreeCell(self, 'active') - self._cells[:,NUM] = -1 - - - def doNumbering(indexer, nodes, dtype): - grid = np.zeros(np.sum(indexer.index), dtype=dtype) - grid['x'][:] = nodes.x - grid['y'][:] = nodes.y - if self.dim == 3: - grid['z'][:] = nodes.z - if 'v' in [d[0] for d in dtype]: - grid['v'][:] = indexer.dir - P = np.argsort(grid, order=[d[0] for d in reversed(dtype)]) - cnt = np.zeros(P.size, dtype=int) - cnt[P] = np.arange(P.size) - return cnt - - self._nodes[N.index, NUM] = doNumbering(N, N, dtypeN) - - self._edges[E.index, NUM] = doNumbering(E, E.n0, dtypeN + dtypeV) - - dtype = dtypeN if self.dim == 2 else (dtypeN + dtypeV) - self._faces[F.index, NUM] = doNumbering(F, F.n0, dtype) - - if self.dim == 3: - self._cells[C.index, NUM] = doNumbering(C, C.n0, dtypeN) - - self._numbered = True - - @property - def nC(self): - if self.dim == 2: - return np.sum(self._faces[:,ACTIVE] == 1) - return np.sum(self._cells[:,ACTIVE] == 1) - - @property - def nN(self): - return np.sum(self._nodes[:,ACTIVE] == 1) - - @property - def nE(self): - if self.dim == 2: - return self.nEx + self.nEy - return self.nEx + self.nEy + self.nEz - - @property - def nF(self): - if self.dim == 2: - return self.nFx + self.nFy - return self.nFx + self.nFy + self.nFz - - @property - def nEx(self): - return np.sum((self._edges[:,ACTIVE] == 1) & (self._edges[:,EDIR] == 0)) - - @property - def nEy(self): - return np.sum((self._edges[:,ACTIVE] == 1) & (self._edges[:,EDIR] == 1)) - - @property - def nEz(self): - if self.dim == 2: return None - return np.sum((self._edges[:,ACTIVE] == 1) & (self._edges[:,EDIR] == 2)) - - @property - def nFx(self): - if self.dim == 2: return self.nEy - return np.sum((self._faces[:,ACTIVE] == 1) & (self._faces[:,FDIR] == 0)) - - @property - def nFy(self): - if self.dim == 2: return self.nEx - return np.sum((self._faces[:,ACTIVE] == 1) & (self._faces[:,FDIR] == 1)) - - @property - def nFz(self): - if self.dim == 2: return None - return np.sum((self._faces[:,ACTIVE] == 1) & (self._faces[:,FDIR] == 2)) - - @property - def edge(self): - if getattr(self, '_edge', None) is None: - E = TreeEdge(self, 'active') - self._edge = E.sort(E.length) - return self._edge - - @property - def area(self): - if getattr(self, '_area', None) is None: - if self.dim == 2: - self._area = np.r_[self.edge[self.nEx:], self.edge[:self.nEx]] - elif self.dim == 3: - F = TreeFace(self, 'active') - self._area = F.sort(F.area) - return self._area - - @property - def vol(self): - if getattr(self, '_vol', None) is None: - if self.dim == 2: - F = TreeFace(self, 'active') - self._vol = F.sort(F.area) - elif self.dim == 3: - C = TreeCell(self, 'active') - self._vol = C.sort(C.vol) - return self._vol - - @property - def gridN(self): - N = TreeNode(self, 'active') - return N.sort(N.vec) - - @property - def gridCC(self): - if self.dim == 2: - F = TreeFace(self, 'active') - return F.sort(F.center) - C = TreeCell(self, 'active') - return C.sort(C.center) - - @property - def gridEx(self): - E = TreeEdge(self, (self._edges[:,ACTIVE] == 1) & (self._edges[:,EDIR] == 0)) - return E.sort(E.center) - - @property - def gridEy(self): - E = TreeEdge(self, (self._edges[:,ACTIVE] == 1) & (self._edges[:,EDIR] == 1)) - return E.sort(E.center) - - @property - def gridEz(self): - if self.dim == 2: return None - E = TreeEdge(self, (self._edges[:,ACTIVE] == 1) & (self._edges[:,EDIR] == 2)) - return E.sort(E.center) - - @property - def gridFx(self): - if self.dim == 2: - return self.gridEy - else: - F = TreeFace(self, (self._faces[:,ACTIVE] == 1) & (self._faces[:,FDIR] == 0)) - return F.sort(F.center) - - @property - def gridFy(self): - if self.dim == 2: - return self.gridEx - else: - F = TreeFace(self, (self._faces[:,ACTIVE] == 1) & (self._faces[:,FDIR] == 1)) - return F.sort(F.center) - - @property - def gridFz(self): - if self.dim == 2: return None - F = TreeFace(self, (self._faces[:,ACTIVE] == 1) & (self._faces[:,FDIR] == 2)) - return F.sort(F.center) - - def _push(self, attr, rows): - self.isNumbered = False - rows = np.atleast_2d(rows) - X = getattr(self, attr) - offset = X.shape[0] - rowNumer = np.arange(rows.shape[0], dtype=int) + offset - rows[:,0] = rowNumer*0-1 - setattr(self, attr, np.vstack((X, rows)).astype(X.dtype)) - if rows.shape[0] == 1: - return offset, rows.flatten() - return rowNumer, rows - - def addNode(self, between): - """Add a node between the node in list between""" - between = np.array(between).flatten() - nodes = self._nodes[between.astype(int), :] - newNode = np.mean(nodes, axis=0) - newNode[ACTIVE] = 1 - return self._push('_nodes', newNode) - - def refineEdge(self, index): - e = self._edges[index,:] - if e[ACTIVE] == 0: - # search for the children up to one level deep - subInds = np.argwhere(self._edges[:,PARENT] == index).flatten() - return subInds, self._edges[subInds,:] - - self._edges[index, ACTIVE] = 0 - - newNode, node = self.addNode(e[[ENODE0, ENODE1]]) - - Es = np.zeros((2, 6)) - Es[:, ACTIVE] = 1 - Es[:, PARENT] = index - Es[:, EDIR] = e[EDIR] - Es[0, ENODE0] = e[ENODE0] - Es[0, ENODE1] = newNode - Es[1, ENODE0] = newNode - Es[1, ENODE1] = e[ENODE1] - return self._push('_edges', Es) - - def refineFace(self, index): - f = self._faces[index,:] - if f[ACTIVE] == 0: - # search for the children up to one level deep - subInds = np.argwhere(self._faces[:,PARENT] == index).flatten() - return subInds, self._faces[subInds,:] - - self._faces[index, ACTIVE] = 0 - - # Refine the outer edges - E0i, E0 = self.refineEdge(f[FEDGE0]) - E1i, E1 = self.refineEdge(f[FEDGE1]) - E2i, E2 = self.refineEdge(f[FEDGE2]) - E3i, E3 = self.refineEdge(f[FEDGE3]) - - nodeNums = [n.index for n in TreeFace(self, index).nodes] - newNode, node = self.addNode(nodeNums) - - # Refine the inner edges - # new faces and edges - # 2_______________3 _______________ - # | e1--> | | | | - # ^ | | ^ | 2 3 3 | y z z - # | | | | | | | ^ ^ ^ - # | | + | | ---> |---0---+---1---| | | | - # e2 | | e3 | | | | | | - # | | | 0 2 1 | z-----> x y-----> x x-----> y - # |_______________| |_______|_______| - # 0 e0--> 1 - - nE = np.zeros((4,6)) - nE[:, ACTIVE] = 1 - nE[:, PARENT] = -1 - nE[:, EDIR] = [0,0,1,1] if f[FDIR] == 2 else [0,0,2,2] if f[FDIR] == 1 else [1,1,2,2] - nE[0, ENODE0] = E2[0, ENODE1] - nE[0, ENODE1] = newNode - nE[1, ENODE0] = newNode - nE[1, ENODE1] = E3[0, ENODE1] - nE[2, ENODE0] = E0[0, ENODE1] - nE[2, ENODE1] = newNode - nE[3, ENODE0] = newNode - nE[3, ENODE1] = E1[0, ENODE1] - nEi, nE = self._push('_edges', nE) - - # Add four new faces - nF = np.zeros((4,8)) - nF[:, ACTIVE] = 1 - nF[:, PARENT] = index - nF[:, FDIR] = f[FDIR] - - feInds = [FEDGE0,FEDGE1,FEDGE2,FEDGE3] - nF[0, feInds] = [E0i[0], nEi[0], E2i[0], nEi[2]] - nF[1, feInds] = [E0i[1], nEi[1], nEi[2], E3i[0]] - nF[2, feInds] = [nEi[0], E1i[0], E2i[1], nEi[3]] - nF[3, feInds] = [nEi[1], E1i[1], nEi[3], E3i[1]] - - return self._push('_faces', nF) - - - def refineCell(self, index): - c = self._cells[index,:] - if c[ACTIVE] == 0: - # search for the children up to one level deep - subInds = np.argwhere(self._cells[:,PARENT] == index).flatten() - return subInds, self._cells[subInds,:] - - self._cells[index, ACTIVE] = 0 - - # Refine the outer faces - fXm, rfXm = self.refineFace(c[CFACE0]) - fXp, rfXp = self.refineFace(c[CFACE1]) - fYm, rfYm = self.refineFace(c[CFACE2]) - fYp, rfYp = self.refineFace(c[CFACE3]) - fZm, rfZm = self.refineFace(c[CFACE4]) - fZp, rfZp = self.refineFace(c[CFACE5]) - - nodes = TreeCell(self, index).fXm.nodes + TreeCell(self, index).fXp.nodes - nodeNums = [n.index for n in nodes] - newNode, node = self.addNode(nodeNums) - - # .----------------.----------------. - # /| /| /| - # / | / | / | - # / | 6 / | 7 / | - # / | / | / | - # .----------------.----+-----------. | - # /| . ---------/|----.----------/|----. - # fZp / | /| / | /| / | /| - # | / | / | 4 / | / | 5 / | / | - # 6 ------eX3------ 7 / | / | / | / | / | / | - # /| | / | . -------------- .----------------. |/ | - # /eZ2 . / eZ3 | . ---+------|----.----+------|----. | - # eY2 | fYp eY3 | | /| .______|___/|____.______|___/|____. - # / | / fXp| | / | / 2 | / | / 3 | / | / - # 4 ------eX2----- 5 | | / | / | / | / | / | / - # |fXm 2 -----eX1--|---- 3 z . ---+---------- . ---+---------- . | / - # eZ0 / | eY1 ^ y | |/ | |/ | |/ - # | eY0 . fYm eZ1 / | / | . ----------|----.-----------|----. - # | / | | / | / | / 0 | / 1 | / - # 0 ------eX0------1 o----> x | / | / | / - # | | / | / | / - # fZm . -------------- . -------------- . - # - # - # fX fY fZ - # 2___________3 2___________3 2___________3 - # | e1 | | e1 | | e1 | - # | | | | | | - # e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y - # | | ^ | | ^ | | ^ - # |___________| |___> y |___________| |___> x |___________| |___> x - # 0 e0 1 0 e0 1 0 e0 1 - - nE = np.zeros((6,6)) - nE[:, ACTIVE] = 1 - nE[:, PARENT] = -1 - nE[:, EDIR] = [0, 0, 1, 1, 2, 2] - - nE[0, ENODE0] = TreeFace(self, fXm[0]).n3.index - nE[0, ENODE1] = newNode - nE[1, ENODE0] = newNode - nE[1, ENODE1] = TreeFace(self, fXp[0]).n3.index - - nE[2, ENODE0] = TreeFace(self, fYm[0]).n3.index - nE[2, ENODE1] = newNode - nE[3, ENODE0] = newNode - nE[3, ENODE1] = TreeFace(self, fYp[0]).n3.index - - nE[4, ENODE0] = TreeFace(self, fZm[0]).n3.index - nE[4, ENODE1] = newNode - nE[5, ENODE0] = newNode - nE[5, ENODE1] = TreeFace(self, fZp[0]).n3.index - - nEi, nE = self._push('_edges', nE) - - nF = np.zeros((12,8)) - nF[:, ACTIVE] = 1 - nF[:, PARENT] = -1 - nF[:, FDIR] = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2] - - feInds = [FEDGE0,FEDGE1,FEDGE2,FEDGE3] - nF[0, feInds] = [rfZm[0, FEDGE3], nEi[2], rfYm[0, FEDGE3], nEi[4]] - nF[1, feInds] = [rfZm[2, FEDGE3], nEi[3], nEi[4], rfYp[0, FEDGE3]] - nF[2, feInds] = [nEi[2], rfZp[0, FEDGE3], rfYm[2, FEDGE3], nEi[5]] - nF[3, feInds] = [nEi[3], rfZp[2, FEDGE3], nEi[5], rfYp[2, FEDGE3]] - - nF[4, feInds] = [rfZm[0, FEDGE1], nEi[0], rfXm[0, FEDGE3], nEi[4]] - nF[5, feInds] = [rfZm[1, FEDGE1], nEi[1], nEi[4], rfXp[0, FEDGE3]] - nF[6, feInds] = [nEi[0], rfZp[0, FEDGE1], rfXm[2, FEDGE3], nEi[5]] - nF[7, feInds] = [nEi[1], rfZp[1, FEDGE1], nEi[5], rfXp[2, FEDGE3]] - - nF[8, feInds] = [rfYm[0, FEDGE1], nEi[0], rfXm[0, FEDGE1], nEi[2]] - nF[9, feInds] = [rfYm[1, FEDGE1], nEi[1], nEi[2], rfXp[0, FEDGE1]] - nF[10,feInds] = [nEi[0], rfYp[0, FEDGE1], rfXm[1, FEDGE1], nEi[3]] - nF[11,feInds] = [nEi[1], rfYp[1, FEDGE1], nEi[3], rfXp[1, FEDGE1]] - - nFi, nF = self._push('_faces', nF) - - nC = np.zeros((8,9)) - nC[:, ACTIVE] = 1 - nC[:, PARENT] = index - - cfInds = [CFACE0,CFACE1,CFACE2,CFACE3,CFACE4,CFACE5] - nC[0, cfInds] = [fXm[0], nFi[0], fYm[0], nFi[4], fZm[ 0], nFi[ 8]] - nC[1, cfInds] = [nFi[0], fXp[0], fYm[1], nFi[5], fZm[ 1], nFi[ 9]] - nC[2, cfInds] = [fXm[1], nFi[1], nFi[4], fYp[0], fZm[ 2], nFi[10]] - nC[3, cfInds] = [nFi[1], fXp[1], nFi[5], fYp[1], fZm[ 3], nFi[11]] - nC[4, cfInds] = [fXm[2], nFi[2], fYm[2], nFi[6], nFi[ 8], fZp[ 0]] - nC[5, cfInds] = [nFi[2], fXp[2], fYm[3], nFi[7], nFi[ 9], fZp[ 1]] - nC[6, cfInds] = [fXm[3], nFi[3], nFi[6], fYp[2], nFi[10], fZp[ 2]] - nC[7, cfInds] = [nFi[3], fXp[3], nFi[7], fYp[3], nFi[11], fZp[ 3]] - - return self._push('_cells', nC) - - def _index(self, attr, index): - index = [index] if np.isscalar(index) else list(index) - C = getattr(self, attr) - cSub = [] - iSub = [] - for I in index: - if C[I, ACTIVE] == 1: - iSub += [I] - cSub += [C[I, :]] - else: - subInds = np.argwhere(C[:,PARENT] == I).flatten() - i, c = self._index(attr, subInds) - iSub += i - cSub += [c] - return iSub, np.vstack(cSub) - - @property - def faceDiv(self): - if getattr(self, '_faceDiv', None) is None: - self.number() - - if self.dim == 2: - offset = np.r_[self.nFx, -self.nEx] # this switches from edge to face numbering - C = self._faces - sign_face = zip([-1,1,-1,1],[FEDGE0, FEDGE1, FEDGE2, FEDGE3]) - faceStr = '_edges' - elif self.dim == 3: - C = self._cells - sign_face = zip([-1,1,-1,1,-1,1],[CFACE0, CFACE1, CFACE2, CFACE3, CFACE4, CFACE5]) - faceStr = '_faces' - - # TODO: Preallocate! - I, J, V = [], [], [] - activeCells = C[:,ACTIVE] == 1 - for cell in C[activeCells]: - for sign, face in sign_face: - ij, jrow = self._index(faceStr, cell[face]) - I += [cell[NUM]]*len(ij) - if self.dim == 2: - J += list(jrow[:,0] + offset[jrow[:,EDIR]]) - elif self.dim == 3: - J += list(jrow[:,0]) - V += [sign]*len(ij) - VOL = self.vol - D = sp.csr_matrix((V,(I,J)), shape=(self.nC, self.nF)) - S = self.area - self._faceDiv = sdiag(1/VOL)*D*sdiag(S) - return self._faceDiv - - @property - def edgeCurl(self): - """Construct the 3D curl operator.""" - assert self.dim > 2, "Edge Curl only programed for 3D." - - if getattr(self, '_edgeCurl', None) is None: - self.number() - # TODO: Preallocate! - I, J, V = [], [], [] - F = self._faces - sign_edge = zip([-1,1,-1,1],[FEDGE0, FEDGE1, FEDGE2, FEDGE3]) - activeFaces = F[:,ACTIVE] == 1 - for face in F[activeFaces]: - for sign, edge in sign_edge: - ij, jrow = self._index('_edges', face[edge]) - I += [face[NUM]]*len(ij) - J += list(jrow[:,0]) - V += [sign]*len(ij) - C = sp.csr_matrix((V,(I,J)), shape=(self.nF, self.nE)) - S = self.area - L = self.edge - self._edgeCurl = sdiag(1.0/S)*C*sdiag(L) - return self._edgeCurl - - @property - def nodalGrad(self): - if getattr(self, '_nodalGrad', None) is None: - self.number() - # TODO: Preallocate! - I, J, V = [], [], [] - E = self._edges - N = self._nodes - activeEdges = E[:,ACTIVE] == 1 - for edge in E[activeEdges]: - I += [edge[NUM], edge[NUM]] - J += [N[edge[ENODE0], NUM], N[edge[ENODE1], NUM]] - V += [-1, 1] - G = sp.csr_matrix((V,(I,J)), shape=(self.nE, self.nN)) - L = self.edge - self._nodalGrad = sdiag(1.0/L)*G - return self._nodalGrad - - - def _getFaceP(self, face0, face1, face2): - if self.dim == 2: - raise NotImplementedError() - - I, J, V = [], [], [] - - Cs = self._cells - activeCells = Cs[:,ACTIVE] == 1 - for cellInd in np.argwhere(activeCells): - - C = TreeCell(self, cellInd) - - face = getattr(C, face0) - if face.isleaf: - j = [int(face.num)] - elif self.dim == 2: - raise NotImplementedError() - j = face.children[0 if 'm' in face1 else 1].index - elif self.dim == 3: - raise NotImplementedError() - j = face.children[0 if 'm' in face1 else 1, - 0 if 'm' in face2 else 1].index - lenj = len(j) - I += [int(C.num)]*lenj - J += j - V += [1./lenj]*lenj - return sp.csr_matrix((V,(I,J)), shape=(self.nC, self.nF)) - - def _getEdgeP(self, edge0, edge1, edge2): - - if self.dim == 2: - raise NotImplementedError() - - I, J, V = [], [], [] - - - Cs = self._cells - activeCells = Cs[:,ACTIVE] == 1 - for cellInd in np.argwhere(activeCells): - - C = TreeCell(self, cellInd) - - if self.dim == 2: - raise NotImplementedError() - e2f = lambda e: ('f' + {'X':'Y','Y':'X'}[e[1]] - + {'0':'m','1':'p'}[e[2]]) - face = cell.faceDict[e2f(edge0)] - if face.isleaf: - j = face.index - else: - j = face.children[0 if 'm' in e2f(edge1) else 1].index - # Need to flip the numbering for edges - if 'X' in edge0: - j = [jj - self.nFx for jj in j] - elif 'Y' in edge0: - j = [jj + self.nFy for jj in j] - elif self.dim == 3: - edge = getattr(C, edge0) - if edge.isleaf: - j = [int(edge.num)] - else: - raise NotImplementedError() - mSide = lambda e: {'0':True,'1':True,'2':False,'3':False}[e[2]] - j = edge.children[0 if mSide(edge1) else 1, - 0 if mSide(edge2) else 1].index - lenj = len(j) - I += [int(C.num)]*lenj - J += j - V += [1./lenj]*lenj - return sp.csr_matrix((V,(I,J)), shape=(self.nC, self.nE)) - - def _getFacePxx(self): - def Pxx(xFace, yFace): - self.number() - xP = self._getFaceP(xFace, yFace, None) - yP = self._getFaceP(yFace, xFace, None) - return sp.vstack((xP, yP)) - return Pxx - - def _getEdgePxx(self): - def Pxx(xEdge, yEdge): - self.number() - xP = self._getEdgeP(xEdge, yEdge, None) - yP = self._getEdgeP(yEdge, xEdge, None) - return sp.vstack((xP, yP)) - return Pxx - - def _getFacePxxx(self): - def Pxxx(xFace, yFace, zFace): - self.number() - xP = self._getFaceP(xFace, yFace, zFace) - yP = self._getFaceP(yFace, xFace, zFace) - zP = self._getFaceP(zFace, xFace, yFace) - return sp.vstack((xP, yP, zP)) - return Pxxx - - def _getEdgePxxx(self): - def Pxxx(xEdge, yEdge, zEdge): - self.number() - xP = self._getEdgeP(xEdge, yEdge, zEdge) - yP = self._getEdgeP(yEdge, xEdge, zEdge) - zP = self._getEdgeP(zEdge, xEdge, yEdge) - return sp.vstack((xP, yP, zP)) - return Pxxx - - def refine(self, function): - if self.dim == 3: - TreeCell(self, 0).refine(function, 0) - elif self.dim == 2: - TreeFace(self, 0).refine(function, 0) - - def plotGrid(self, ax=None, text=True, showIt=False, figsize=(10,8)): - import matplotlib.pyplot as plt - - - - - if self.dim == 3: - axOpts = {'projection':'3d'} - if ax is None: ax = plt.subplot(111, **axOpts) - C = TreeCell(self, 'active') - - - # fZp - # | - # 6 ------eX3------ 7 - # /| | / | - # /eZ2 . / eZ3 - # eY2 | fYp eY3 | - # / | / fXp| - # 4 ------eX2----- 5 | - # |fXm 2 -----eX1--|---- 3 z - # eZ0 / | eY1 ^ y - # | eY0 . fYm eZ1 / | / - # | / | | / | / - # 0 ------eX0------1 o----> x - # | - # fZm - # - - - - Es = TreeEdge(self, 'active') - ax.plot(np.c_[Es.n0.x, Es.n1.x, Es.n1.x+np.nan].flatten(), np.c_[Es.n0.y, Es.n1.y, Es.n1.y+np.nan].flatten(), 'b-', zs=np.c_[Es.n0.z, Es.n1.z, Es.n1.z+np.nan].flatten()) - # n1, n2, n3, n4, n5 = 0, 1, 3, 2, 0 - # eX = np.c_[C.nodes[n1].x, C.nodes[n2].x, C.nodes[n3].x, C.nodes[n4].x, C.nodes[n5].x, [np.nan]*self.nC] - # eY = np.c_[C.nodes[n1].y, C.nodes[n2].y, C.nodes[n3].y, C.nodes[n4].y, C.nodes[n5].y, [np.nan]*self.nC] - # eZ = np.c_[C.nodes[n1].z, C.nodes[n2].z, C.nodes[n3].z, C.nodes[n4].z, C.nodes[n5].z, [np.nan]*self.nC] - # ax.plot(eX.flatten(), eY.flatten(), 'b-', zs=eZ.flatten()) - - # n1, n2, n3, n4, n5 = 4, 5, 7, 6, 4 - # eX = np.c_[C.nodes[n1].x, C.nodes[n2].x, C.nodes[n3].x, C.nodes[n4].x, C.nodes[n5].x, [np.nan]*self.nC] - # eY = np.c_[C.nodes[n1].y, C.nodes[n2].y, C.nodes[n3].y, C.nodes[n4].y, C.nodes[n5].y, [np.nan]*self.nC] - # eZ = np.c_[C.nodes[n1].z, C.nodes[n2].z, C.nodes[n3].z, C.nodes[n4].z, C.nodes[n5].z, [np.nan]*self.nC] - # ax.plot(eX.flatten(), eY.flatten(), 'r-', zs=eZ.flatten()) - - ax.plot(self.gridN[:,0], self.gridN[:,1], 'bs', zs=self.gridN[:,2]) - ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'ro', zs=self.gridCC[:,2]) - - ax.set_xlabel('x') - ax.set_ylabel('y') - ax.set_zlabel('z') - if showIt: plt.show() - return ax - - N = self._nodes - E = self._edges - C = self._faces - - if ax is None:f, ax = plt.subplots(1,1,figsize=figsize) - - Es = TreeEdge(self, 'active') - ax.plot(np.c_[Es.n0.x, Es.n1.x, Es.n1.x+np.nan].flatten(), np.c_[Es.n0.y, Es.n1.y, Es.n1.y+np.nan].flatten(), 'b-') - Ns = TreeNode(self, 'active') - ax.plot(Ns.x, Ns.y, 'k.') - - gridCC = self.gridCC - if text: - [ax.text(cc[0], cc[1],i) for i, cc in enumerate(gridCC)] - ax.plot(gridCC[:,0], gridCC[:,1], 'r.') - gridFx = self.gridFx - gridFy = self.gridFy - if text: - [ax.text(cc[0], cc[1],i) for i, cc in enumerate(np.vstack((gridFx,gridFy)))] - gridEx = self.gridEx - gridEy = self.gridEy - # if text: - # [ax.text(cc[0], cc[1],i) for i, cc in enumerate(np.vstack((gridEx,gridEy)))] - - # for E in self._edges: - # if E[ACTIVE] == 0: continue - # ex = N[E[[ENODE0,ENODE1]],NX] - # ey = N[E[[ENODE0,ENODE1]],NY] - # ax.plot(ex, ey, 'b-') - # ax.text(ex.mean(), ey.mean(), E[NUM]) - - if showIt: - plt.show() - - - - -if __name__ == '__main__': - from SimPEG import Mesh, Utils - import matplotlib.pyplot as plt - - # tM = TreeMesh([np.ones(3),np.ones(2)]) - tM = TreeMesh([np.ones(2),1,1]) - - # tM.refine(lambda c:2) - tM.refineCell(0) - tM.refineCell(2) - # tM.refineCell(7) - - # M = Mesh.TensorMesh([4,4,4]) - # print tM.gridN - M.gridN - tM.plotGrid() - - # plt.show() - - - - # tM.refineFace(0) - # tM.refineFace(1) - # tM.refineFace(3) - # tM.refineFace(9) - - # print tM._nodes[:,NUM] - # tM.number() - # print tM._nodes[:,NUM] - # print tM._edges[:,NUM] - - # print TreeFace(tM,'active').e3.n1.index - - # Mr = TreeMesh([2,1,1]) - # Mr.refineCell(0) - - # print Mr.vol - - # M = TreeMesh([2,2,2]) - # M.number() - # M.refineCell(0) - # M.refineCell(3) - # assert M.isNumbered is False - # C = TreeCell(M, 'active') - # M.getEdgeInnerProduct() - - # tM = TreeMesh([100,100,100]) - # print tM.vol - - - # print tM._faces - # print tM._edges[0,:] - # print tM.vol - - - # tM.number() - # print tM._index('_edges',3)[1] - - - # print tM._edges[:,[0,1,3, 4,5 ]] - - # plt.subplot(211) - # plt.spy(tM.faceDiv) - # tM.plotGrid(ax=plt.subplot(212)) - - # plt.figure(2) - # plt.plot(SortByX0(tM.gridCC),'b.') - # plt.show() - - - M = TreeMesh([[(1,3)],[(1,3)],[(1,3)]]) - - def refFunc(cell): - n = 5 - np.sum((cell.center.flatten() - np.r_[1.5, 1.5, 1.5])**2)**0.5 * 2 - print n, cell.center - return n - return 1 - M.refine(refFunc) - print M.nC - - M.plotGrid(text=False) - plt.show() - diff --git a/SimPEG/Mesh/PointerTree.py b/SimPEG/Mesh/PointerTree.py deleted file mode 100644 index a5ed562b..00000000 --- a/SimPEG/Mesh/PointerTree.py +++ /dev/null @@ -1,1669 +0,0 @@ -# ___ ___ ___ ___ ___ -# /\ \ ___ /\__\ /\ \ /\ \ /\ \ -# /::\ \ /\ \ /::| | /::\ \ /::\ \ /::\ \ -# /:/\ \ \ \:\ \ /:|:| | /:/\:\ \ /:/\:\ \ /:/\:\ \ -# _\:\~\ \ \ /::\__\ /:/|:|__|__ /::\~\:\ \ /::\~\:\ \ /:/ \:\ \ -# /\ \:\ \ \__\ __/:/\/__//:/ |::::\__\/:/\:\ \:\__\/:/\:\ \:\__\/:/__/_\:\__\ -# \:\ \:\ \/__//\/:/ / \/__/~~/:/ /\/__\:\/:/ /\:\~\:\ \/__/\:\ /\ \/__/ -# \:\ \:\__\ \::/__/ /:/ / \::/ / \:\ \:\__\ \:\ \:\__\ -# \:\/:/ / \:\__\ /:/ / \/__/ \:\ \/__/ \:\/:/ / -# \::/ / \/__/ /:/ / \:\__\ \::/ / -# \/__/ \/__/ \/__/ \/__/ -# ___ ___ ___ ___ ___ ___ -# /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ -# /::\ \ /::\ \ \:\ \ /::\ \ /::\ \ /::\ \ -# /:/\:\ \ /:/\:\ \ \:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ -# /:/ \:\ \ /:/ \:\ \ /::\ \ /::\~\:\ \ /::\~\:\ \ /::\~\:\ \ -# /:/__/ \:\__\/:/__/ \:\__\ /:/\:\__\/:/\:\ \:\__\/:/\:\ \:\__\/:/\:\ \:\__\ -# \:\ \ /:/ /\:\ \ \/__//:/ \/__/\/_|::\/:/ /\:\~\:\ \/__/\:\~\:\ \/__/ -# \:\ /:/ / \:\ \ /:/ / |:|::/ / \:\ \:\__\ \:\ \:\__\ -# \:\/:/ / \:\ \ \/__/ |:|\/__/ \:\ \/__/ \:\ \/__/ -# \::/ / \:\__\ |:| | \:\__\ \:\__\ -# \/__/ \/__/ \|__| \/__/ \/__/ -# -# -# @rowanc1, Nov. 10, 2015 -# -# .----------------.----------------. -# /| /| /| -# / | / | / | -# / | 011 / | 111 / | -# / | / | / | -# .----------------.----+-----------. | -# /| . ---------/|----.----------/|----. -# / | /| / | /| / | /| -# / | / | 001 / | / | 101 / | / | -# / | / | / | / | / | / | -# . -------------- .----------------. |/ | -# | . ---+------|----.----+------|----. | -# | /| .______|___/|____.______|___/|____. -# | / | / 010 | / | / 110| / | / -# | / | / | / | / | / | / -# . ---+---------- . ---+---------- . | / -# | |/ | |/ | |/ z -# | . ----------|----.-----------|----. ^ y -# | / 000 | / 100 | / | / -# | / | / | / | / -# | / | / | / o----> x -# . -------------- . -------------- . -# -# -# Face Refinement: -# -# 2_______________3 _______________ -# | | | | | -# ^ | | | (0,1) | (1,1) | -# | | | | | | -# | | x | ---> |-------+-------| -# t1 | | | | | -# | | | (0,0) | (1,0) | -# |_______________| |_______|_______| -# 0 t0--> 1 -# -# -# Face and Edge naming conventions: -# -# fZp -# | -# 6 ------eX3------ 7 -# /| | / | -# /eZ2 . / eZ3 -# eY2 | fYp eY3 | -# / | / fXp| -# 4 ------eX2----- 5 | -# |fXm 2 -----eX1--|---- 3 z -# eZ0 / | eY1 ^ y -# | eY0 . fYm eZ1 / | / -# | / | | / | / -# 0 ------eX0------1 o----> x -# | -# fZm -# -# -# fX fY fZ -# 2___________3 2___________3 2___________3 -# | e1 | | e1 | | e1 | -# | | | | | | -# e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y -# | | ^ | | ^ | | ^ -# |___________| |___> y |___________| |___> x |___________| |___> x -# 0 e0 1 0 e0 1 0 e0 1 -# - -from SimPEG import np, sp, Utils, Solver, Mesh -import matplotlib.pyplot as plt -import matplotlib -from mpl_toolkits.mplot3d import Axes3D -import matplotlib.colors as colors -import matplotlib.cm as cmx - -import TreeUtils -from SimPEG.Mesh.InnerProducts import InnerProducts -from SimPEG.Mesh.BaseMesh import BaseMesh -import time - -MAX_BITS = 20 - -class Tree(BaseMesh, InnerProducts): - def __init__(self, h_in, x0_in=None, levels=3): - assert type(h_in) is list, 'h_in must be a list' - assert len(h_in) > 1, "len(h_in) must be greater than 1" - - h = range(len(h_in)) - for i, h_i in enumerate(h_in): - if type(h_i) in [int, long, float]: - # This gives you something over the unit cube. - h_i = np.ones(int(h_i))/int(h_i) - elif type(h_i) is list: - h_i = Utils.meshTensor(h_i) - assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) - assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) - assert len(h_i) == 2**levels, "must make h and levels match" - h[i] = h_i[:] # make a copy. - self.h = h - - x0 = np.zeros(len(h)) - if x0_in is not None: - assert len(h) == len(x0_in), "Dimension mismatch. x0 != len(h)" - for i in range(len(h)): - x_i, h_i = x0_in[i], h[i] - if Utils.isScalar(x_i): - x0[i] = x_i - elif x_i == '0': - x0[i] = 0.0 - elif x_i == 'C': - x0[i] = -h_i.sum()*0.5 - elif x_i == 'N': - x0[i] = -h_i.sum() - else: - raise Exception("x0[%i] must be a scalar or '0' to be zero, 'C' to center, or 'N' to be negative." % i) - - BaseMesh.__init__(self, [len(_) for _ in h], x0) - - self._levels = levels - self._levelBits = int(np.ceil(np.sqrt(levels)))+1 - - self.__dirty__ = True #: The numbering is dirty! - - self._cells = set() - self._cells.add(0) - - @property - def __dirty__(self): - return self.__dirtyFaces__ or self.__dirtyEdges__ or self.__dirtyNodes__ or self.__dirtyHanging__ - - @__dirty__.setter - def __dirty__(self, val): - assert val is True - self.__dirtyFaces__ = True - self.__dirtyEdges__ = True - self.__dirtyNodes__ = True - self.__dirtyHanging__ = True - - deleteThese = [ - '__sortedCells', - '_gridCC', '_gridN', '_gridFx', '_gridFy', '_gridFz', '_gridEx', '_gridEy', '_gridEz', - '_area', '_edge', '_vol', - '_faceDiv', '_edgeCurl', '_nodalGrad' - ] - for p in deleteThese: - if hasattr(self, p): delattr(self, p) - - @property - def levels(self): return self._levels - - @property - def dim(self): return len(self.h) - - @property - def nC(self): return len(self._cells) - - @property - def nN(self): - self.number() - return len(self._nodes) - len(self._hangingN) - - @property - def nF(self): - return self.nFx + self.nFy + (0 if self.dim == 2 else self.nFz) - - @property - def nFx(self): - self.number() - return len(self._facesX) - len(self._hangingFx) - - @property - def nFy(self): - self.number() - return len(self._facesY) - len(self._hangingFy) - - @property - def nFz(self): - if self.dim == 2: return None - self.number() - return len(self._facesZ) - len(self._hangingFz) - - @property - def nE(self): - return self.nEx + self.nEy + (0 if self.dim == 2 else self.nEz) - - @property - def nEx(self): - if self.dim == 2:return self.nFy - self.number() - return len(self._edgesX) - len(self._hangingEx) - - @property - def nEy(self): - if self.dim == 2:return self.nFx - self.number() - return len(self._edgesY) - len(self._hangingEy) - - @property - def nEz(self): - if self.dim == 2: return None - self.number() - return len(self._edgesZ) - len(self._hangingEz) - - @property - def nhN(self): - self.number() - return len(self._hangingN) - - @property - def nhF(self): - return self.nhFx + self.nhFy + (0 if self.dim == 2 else self.nhFz) - - @property - def nhFx(self): - self.number() - return len(self._hangingFx) - - @property - def nhFy(self): - self.number() - return len(self._hangingFy) - - @property - def nhFz(self): - if self.dim == 2: return None - self.number() - return len(self._hangingFz) - - @property - def nhE(self): - return self.nhEx + self.nhEy + (0 if self.dim == 2 else self.nhEz) - - @property - def nhEx(self): - if self.dim == 2:return self.nhFy - self.number() - return len(self._hangingEx) - - @property - def nhEy(self): - if self.dim == 2:return self.nhFx - self.number() - return len(self._hangingEy) - - @property - def nhEz(self): - if self.dim == 2: return None - self.number() - return len(self._hangingEz) - - - @property - def ntN(self): - self.number() - return len(self._nodes) - - @property - def ntF(self): - return self.ntFx + self.ntFy + (0 if self.dim == 2 else self.ntFz) - - @property - def ntFx(self): - self.number() - return len(self._facesX) - - @property - def ntFy(self): - self.number() - return len(self._facesY) - - @property - def ntFz(self): - if self.dim == 2: return None - self.number() - return len(self._facesZ) - - @property - def ntE(self): - return self.ntEx + self.ntEy + (0 if self.dim == 2 else self.ntEz) - - @property - def ntEx(self): - if self.dim == 2:return self.ntFy - self.number() - return len(self._edgesX) - - @property - def ntEy(self): - if self.dim == 2:return self.ntFx - self.number() - return len(self._edgesY) - - @property - def ntEz(self): - if self.dim == 2: return None - self.number() - return len(self._edgesZ) - - @property - def _sortedCells(self): - if getattr(self, '__sortedCells', None) is None: - self.__sortedCells = sorted(self._cells) - return self.__sortedCells - - @property - def permuteCC(self): - #TODO: cache these? - P = SortGrid(self.gridCC) - return sp.identity(self.nC).tocsr()[P,:] - - @property - def permuteF(self): - #TODO: cache these? - P = SortGrid(self.gridFx) - P += SortGrid(self.gridFy, offset=self.nFx) - if self.dim == 3: - P += SortGrid(self.gridFz, offset=self.nFx+self.nFy) - return sp.identity(self.nF).tocsr()[P,:] - - @property - def permuteE(self): - #TODO: cache these? - if self.dim == 2: - P = SortGrid(self.gridFy) - P += SortGrid(self.gridFx, offset=self.nEx) - return sp.identity(self.nE).tocsr()[P,:] - if self.dim == 3: - P = SortGrid(self.gridEx) - P += SortGrid(self.gridEy, offset=self.nEx) - P += SortGrid(self.gridEz, offset=self.nEx+self.nEy) - return sp.identity(self.nE).tocsr()[P,:] - - def _index(self, pointer): - assert len(pointer) is self.dim+1 - assert pointer[-1] <= self.levels - return TreeUtils.index(self.dim, MAX_BITS, self._levelBits, pointer[:-1], pointer[-1]) - - def _pointer(self, index): - assert type(index) in [int, long] - return TreeUtils.point(self.dim, MAX_BITS, self._levelBits, index) - - def __contains__(self, v): - return self._asIndex(v) in self._cells - - def refine(self, function=None, recursive=True, cells=None, balance=True, verbose=False, _inRecursion=False): - - if not _inRecursion: - self.__dirty__ = True - if verbose: print 'Refining Mesh' - - cells = cells if cells is not None else sorted(self._cells) - recurse = [] - tic = time.time() - for cell in cells: - p = self._pointer(cell) - do = function(self._cellC(cell)) > p[-1] - if do: - recurse += self._refineCell(cell) - - if verbose: print ' ', time.time() - tic - - if recursive and len(recurse) > 0: - recurse += self.refine(function=function, recursive=True, cells=recurse, balance=balance, _inRecursion=True) - - if balance and not _inRecursion: - self.balance() - return recurse - - def _refineCell(self, pointer): - pointer = self._asPointer(pointer) - ind = self._asIndex(pointer) - assert ind in self - h = self._levelWidth(pointer[-1])/2 # halfWidth - nL = pointer[-1] + 1 # new level - add = lambda p:p[0]+p[1] - added = [] - def addCell(p): - i = self._index(p+[nL]) - self._cells.add(i) - added.append(i) - - addCell(map(add, zip(pointer[:-1], [0,0,0][:self.dim]))) - addCell(map(add, zip(pointer[:-1], [h,0,0][:self.dim]))) - addCell(map(add, zip(pointer[:-1], [0,h,0][:self.dim]))) - addCell(map(add, zip(pointer[:-1], [h,h,0][:self.dim]))) - if self.dim == 3: - addCell(map(add, zip(pointer[:-1], [0,0,h]))) - addCell(map(add, zip(pointer[:-1], [h,0,h]))) - addCell(map(add, zip(pointer[:-1], [0,h,h]))) - addCell(map(add, zip(pointer[:-1], [h,h,h]))) - self._cells.remove(ind) - return added - - def corsen(self, function=None): - self.__dirty__ = True - raise Exception('Not yet implemented') - - - def _corsenCell(self, pointer): - raise Exception('Not yet implemented') - - # something like this: ?? - pointer = self._asPointer(pointer) - ind = self._asIndex(pointer) - assert ind in self - - parent = self._parentPointer(ind) - children = _childPointers(parent) - for child in children: - self._cells.remove(self._asIndex(child)) - - parentInd = self._asIndex(parent) - self._cells.add(parentInd) - return parentInd - - def _asPointer(self, ind): - if type(ind) in [int, long]: - return self._pointer(ind) - if type(ind) is list: - assert len(ind) == (self.dim + 1), str(ind) +' is not valid pointer' - assert ind[-1] <= self.levels, str(ind) +' is not valid pointer' - return ind - if isinstance(ind, np.ndarray): - return ind.tolist() - raise Exception - - def _asIndex(self, pointer): - if type(pointer) in [int, long]: - return pointer - if type(pointer) is list: - return self._index(pointer) - raise Exception - - - def _childPointers(self, pointer, direction=0, positive=True, returnAll=False): - l = self._levelWidth(pointer[-1] + 1) - - if self.dim == 2: - - children = [ - [pointer[0] , pointer[1] , pointer[-1] + 1], - [pointer[0] + l, pointer[1] , pointer[-1] + 1], - [pointer[0] , pointer[1] + l, pointer[-1] + 1], - [pointer[0] + l, pointer[1] + l, pointer[-1] + 1] - ] - - elif self.dim == 3: - - children = [ - [pointer[0] , pointer[1] , pointer[2] , pointer[-1] + 1], - [pointer[0] + l, pointer[1] , pointer[2] , pointer[-1] + 1], - [pointer[0] , pointer[1] + l, pointer[2] , pointer[-1] + 1], - [pointer[0] + l, pointer[1] + l, pointer[2] , pointer[-1] + 1], - [pointer[0] , pointer[1] , pointer[2] + l, pointer[-1] + 1], - [pointer[0] + l, pointer[1] , pointer[2] + l, pointer[-1] + 1], - [pointer[0] , pointer[1] + l, pointer[2] + l, pointer[-1] + 1], - [pointer[0] + l, pointer[1] + l, pointer[2] + l, pointer[-1] + 1] - ] - if direction == 0: ind = [0,2,4,6] if not positive else [1,3,5,7] - if direction == 1: ind = [0,1,4,5] if not positive else [2,3,6,7] - if direction == 2: ind = [0,1,2,3] if not positive else [4,5,6,7] - - if returnAll: - return children - return [children[_] for _ in ind[:(self.dim-1)*2]] - - - def _parentPointer(self, pointer): - mod = self._levelWidth(pointer[-1] - 1) - return [p - (p % mod) for p in pointer[:-1]] + [pointer[-1]-1] - - def _cellN(self, p): - p = self._asPointer(p) - return [hi[:p[ii]].sum() for ii, hi in enumerate(self.h)] - - def _cellH(self, p): - p = self._asPointer(p) - w = self._levelWidth(p[-1]) - return [hi[p[ii]:p[ii]+w].sum() for ii, hi in enumerate(self.h)] - - def _cellC(self, p): - return (np.array(self._cellH(p))/2.0 + self._cellN(p)).tolist() - - def _levelWidth(self, level): - return 2**(self.levels - level) - - def _isInsideMesh(self, pointer): - inside = True - for p in pointer[:-1]: - inside = inside and p >= 0 and p < 2**self.levels - return inside - - def _getNextCell(self, ind, direction=0, positive=True, _lookUp=True): - """ - Returns a None, int, list, or nested list - The int is the cell number. - - """ - if direction >= self.dim: return None - pointer = self._asPointer(ind) - if pointer[-1] > self.levels: return None - - step = (1 if positive else -1) * self._levelWidth(pointer[-1]) - nextCell = [p if ii is not direction else p + step for ii, p in enumerate(pointer)] - # raise Exception(pointer, nextCell) - if not self._isInsideMesh(nextCell): return None - - # it might be the same size as me? - if nextCell in self: return self._index(nextCell) - - if nextCell[-1] + 1 <= self.levels: # if I am not the smallest. - children = self._childPointers(pointer, direction=direction, positive=positive) - nextCells = [self._getNextCell(child, direction=direction, positive=positive, _lookUp=False) for child in children] - if nextCells[0] is not None: - return nextCells - - if not _lookUp: return None - - # it might be bigger than me? - return self._getNextCell(self._parentPointer(pointer), - direction=direction, positive=positive) - - def balance(self, recursive=True, cells=None, verbose=False, _inRecursion=False): - - tic = time.time() - if not _inRecursion: - self.__dirty__ = True - if verbose: print 'Balancing Mesh:' - - cells = cells if cells is not None else sorted(self._cells) - - # calcDepth = lambda i: lambda A: i if type(A) is not list else max(map(calcDepth(i+1), A)) - # flatten = lambda A: A if calcDepth(0)(A) == 1 else flatten([_ for __ in A for _ in (__ if type(__) is list else [__])]) - - recurse = set() - - for cell in cells: - p = self._asPointer(cell) - if p[-1] == self.levels: continue - - cs = range(6) - cs[0] = self._getNextCell(cell, direction=0, positive=False) - cs[1] = self._getNextCell(cell, direction=0, positive=True) - cs[2] = self._getNextCell(cell, direction=1, positive=False) - cs[3] = self._getNextCell(cell, direction=1, positive=True) - cs[4] = self._getNextCell(cell, direction=2, positive=False) # this will be None if in 2D - cs[5] = self._getNextCell(cell, direction=2, positive=True) # this will be None if in 2D - - do = np.any([ - type(c) is list and np.any([type(_) is list for _ in c]) - for c in cs - if c is not None - ]) - # depth = calcDepth(0)(cs) - # print depth, depth > 2, do, [jj for jj in flatten(cs) if jj is not None] - # recurse += [jj for jj in flatten(cs) if jj is not None] - - if do and cell in self: - newCells = self._refineCell(cell) - recurse.update([_ for _ in cs if type(_) in [int, long]]) # only add the bigger ones! - recurse.update(newCells) - - if verbose: print ' ', len(cells), time.time() - tic - if recursive and len(recurse) > 0: - self.balance(cells=sorted(recurse), _inRecursion=True) - - @property - def gridCC(self): - if getattr(self, '_gridCC', None) is None: - self._gridCC = np.zeros((len(self._cells),self.dim)) - for ii, ind in enumerate(self._sortedCells): - p = self._asPointer(ind) - self._gridCC[ii, :] = self._cellC(p) - return self._gridCC - - @property - def gridN(self): - self.number() - R = self._deflationMatrix('N', withHanging=False) - return R.T * self._gridN - - @property - def gridFx(self): - self.number() - R = self._deflationMatrix('Fx', withHanging=False) - return R.T * self._gridFx - - @property - def gridFy(self): - self.number() - R = self._deflationMatrix('Fy', withHanging=False) - return R.T * self._gridFy - - @property - def gridFz(self): - if self.dim < 3: return None - self.number() - R = self._deflationMatrix('Fz', withHanging=False) - return R.T * self._gridFz - - @property - def gridEx(self): - if self.dim == 2: return self.gridFy - self.number() - R = self._deflationMatrix('Ex', withHanging=False) - return R.T * self._gridEx - - @property - def gridEy(self): - if self.dim == 2: return self.gridFx - self.number() - R = self._deflationMatrix('Ey', withHanging=False) - return R.T * self._gridEy - - @property - def gridEz(self): - if self.dim < 3: return None - self.number() - R = self._deflationMatrix('Ez', withHanging=False) - return R.T * self._gridEz - - @property - def vol(self): - if getattr(self, '_vol', None) is None: - self._vol = np.zeros(len(self._cells)) - for ii, ind in enumerate(self._sortedCells): - p = self._asPointer(ind) - self._vol[ii] = np.prod(self._cellH(p)) - return self._vol - - @property - def area(self): - self.number() - if getattr(self, '_area', None) is None: - Rf = self._deflationMatrix('F', withHanging=False) - self._area = Rf.T * ( - np.r_[self._areaFxFull, self._areaFyFull] if self.dim == 2 else - np.r_[self._areaFxFull, self._areaFyFull, self._areaFzFull] - ) - return self._area - - @property - def edge(self): - self.number() - if self.dim == 2: - return np.r_[self.area[self.nFx:], self.area[:self.nFx]] - if getattr(self, '_edge', None) is None: - Re = self._deflationMatrix('E', withHanging=False) - self._edge = Re.T * np.r_[self._edgeExFull, self._edgeEyFull, self._edgeEzFull] - - return self._edge - - def _onSameLevel(self, i0, i1): - p0 = self._asPointer(i0) - p1 = self._asPointer(i1) - return p0[-1] == p1[-1] - - def _numberNodes(self, force=False): - if not self.__dirtyNodes__ and not force: return - - self._nodes = set() - - for ind in self._cells: - p = self._asPointer(ind) - w = self._levelWidth(p[-1]) - if self.dim == 2: - self._nodes.add(self._index([p[0] , p[1] , p[2]])) - self._nodes.add(self._index([p[0] + w, p[1] , p[2]])) - self._nodes.add(self._index([p[0] , p[1] + w, p[2]])) - self._nodes.add(self._index([p[0] + w, p[1] + w, p[2]])) - elif self.dim == 3: - self._nodes.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._nodes.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) - self._nodes.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) - self._nodes.add(self._index([p[0] + w, p[1] + w, p[2] , p[3]])) - self._nodes.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) - self._nodes.add(self._index([p[0] + w, p[1] , p[2] + w, p[3]])) - self._nodes.add(self._index([p[0] , p[1] + w, p[2] + w, p[3]])) - self._nodes.add(self._index([p[0] + w, p[1] + w, p[2] + w, p[3]])) - gridN = [] - self._n2i = dict() - for ii, n in enumerate(sorted(self._nodes)): - self._n2i[n] = ii - gridN.append( self._cellN( self._pointer(n) ) ) - self._gridN = np.array(gridN) - - self.__dirtyNodes__ = False - - def _numberFaces(self, force=False): - if not self.__dirtyFaces__ and not force: return - - self._facesX = set() - self._facesY = set() - if self.dim == 3: - self._facesZ = set() - - for ind in self._cells: - p = self._asPointer(ind) - w = self._levelWidth(p[-1]) - - if self.dim == 2: - self._facesX.add(self._index([p[0] , p[1] , p[2]])) - self._facesX.add(self._index([p[0] + w, p[1] , p[2]])) - self._facesY.add(self._index([p[0] , p[1] , p[2]])) - self._facesY.add(self._index([p[0] , p[1] + w, p[2]])) - elif self.dim == 3: - self._facesX.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._facesX.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) - self._facesY.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._facesY.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) - self._facesZ.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._facesZ.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) - - gridFx = [] - areaFx = [] - self._fx2i = dict() - for ii, fx in enumerate(sorted(self._facesX)): - self._fx2i[fx] = ii - p = self._pointer(fx) - n, h = self._cellN(p), self._cellH(p) - if self.dim == 2: - gridFx.append( [n[0], n[1] + h[1]/2.0] ) - areaFx.append( h[1] ) - elif self.dim == 3: - gridFx.append( [n[0], n[1] + h[1]/2.0, n[2] + h[2]/2.0] ) - areaFx.append( h[1]*h[2] ) - self._gridFx = np.array(gridFx) - self._areaFxFull = np.array(areaFx) - - gridFy = [] - areaFy = [] - self._fy2i = dict() - for ii, fy in enumerate(sorted(self._facesY)): - self._fy2i[fy] = ii - p = self._pointer(fy) - n, h = self._cellN(p), self._cellH(p) - if self.dim == 2: - gridFy.append( [n[0] + h[0]/2.0, n[1]] ) - areaFy.append( h[0] ) - elif self.dim == 3: - gridFy.append( [n[0] + h[0]/2.0, n[1], n[2] + h[2]/2.0] ) - areaFy.append( h[0]*h[2] ) - self._gridFy = np.array(gridFy) - self._areaFyFull = np.array(areaFy) - - if self.dim == 2: - self.__dirtyFaces__ = False - return - - gridFz = [] - areaFz = [] - self._fz2i = dict() - for ii, fz in enumerate(sorted(self._facesZ)): - self._fz2i[fz] = ii - p = self._pointer(fz) - n, h = self._cellN(p), self._cellH(p) - gridFz.append( [n[0] + h[0]/2.0, n[1] + h[1]/2.0, n[2]] ) - areaFz.append(h[0]*h[1]) - self._gridFz = np.array(gridFz) - self._areaFzFull = np.array(areaFz) - - self.__dirtyFaces__ = False - - def _numberEdges(self, force=False): - if self.dim == 2: - self.__dirtyEdges__ = False - return - if not self.__dirtyEdges__ and not force: return - - self._edgesX = set() - self._edgesY = set() - self._edgesZ = set() - - for ind in self._cells: - p = self._asPointer(ind) - w = self._levelWidth(p[-1]) - self._edgesX.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._edgesX.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) - self._edgesX.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) - self._edgesX.add(self._index([p[0] , p[1] + w, p[2] + w, p[3]])) - - self._edgesY.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._edgesY.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) - self._edgesY.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) - self._edgesY.add(self._index([p[0] + w, p[1] , p[2] + w, p[3]])) - - self._edgesZ.add(self._index([p[0] , p[1] , p[2] , p[3]])) - self._edgesZ.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) - self._edgesZ.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) - self._edgesZ.add(self._index([p[0] + w, p[1] + w, p[2] , p[3]])) - - gridEx = [] - edgeEx = [] - self._ex2i = dict() - for ii, ex in enumerate(sorted(self._edgesX)): - self._ex2i[ex] = ii - p = self._pointer(ex) - n, h = self._cellN(p), self._cellH(p) - gridEx.append( [n[0] + h[0]/2.0, n[1], n[2]] ) - edgeEx.append( h[0] ) - self._gridEx = np.array(gridEx) - self._edgeExFull = np.array(edgeEx) - - gridEy = [] - edgeEy = [] - self._ey2i = dict() - for ii, ey in enumerate(sorted(self._edgesY)): - self._ey2i[ey] = ii - p = self._pointer(ey) - n, h = self._cellN(p), self._cellH(p) - gridEy.append( [n[0], n[1] + h[1]/2.0, n[2]] ) - edgeEy.append( h[1] ) - self._gridEy = np.array(gridEy) - self._edgeEyFull = np.array(edgeEy) - - gridEz = [] - edgeEz = [] - self._ez2i = dict() - for ii, ez in enumerate(sorted(self._edgesZ)): - self._ez2i[ez] = ii - p = self._pointer(ez) - n, h = self._cellN(p), self._cellH(p) - gridEz.append( [n[0], n[1], n[2] + h[2]/2.0] ) - edgeEz.append( h[2] ) - self._gridEz = np.array(gridEz) - self._edgeEzFull = np.array(edgeEz) - - self.__dirtyEdges__ = False - - def _hanging(self, force=False): - if not self.__dirtyHanging__ and not force: return - - self._numberNodes(force=force) - self._numberFaces(force=force) - self._numberEdges(force=force) - - self._hangingN = dict() - self._hangingFx = dict() - self._hangingFy = dict() - if self.dim == 3: - self._hangingFz = dict() - self._hangingEx = dict() - self._hangingEy = dict() - self._hangingEz = dict() - - # Compute from x faces - for fx in self._facesX: - p = self._pointer(fx) - if p[-1] + 1 > self.levels: continue - sl = p[-1] + 1 #: small level - test = self._index(p[:-1] + [sl]) - if test not in self._facesX: - # Return early without checking the other faces - continue - w = self._levelWidth(sl) - - if self.dim == 2: - chy0 = self._cellH([p[0] , p[1] , sl])[1] - chy1 = self._cellH([p[0] , p[1] + w, sl])[1] - A = (chy0 + chy1) - - self._hangingFx[self._fx2i[test ]] = ([self._fx2i[fx], chy0 / A], ) - self._hangingFx[self._fx2i[self._index([p[0] , p[1] + w, sl])]] = ([self._fx2i[fx], chy1 / A], ) - - n0, n1 = fx, self._index([p[0], p[1] + 2*w, p[-1]]) - self._hangingN[self._n2i[test ]] = ([self._n2i[n0], 1.0], ) - self._hangingN[self._n2i[self._index([p[0] , p[1] + w, sl])]] = ([self._n2i[n0], 1.0 - chy0 / A], [self._n2i[n1], 1.0 - chy1 / A]) - self._hangingN[self._n2i[self._index([p[0] , p[1] + 2*w, sl])]] = ([self._n2i[n1], 1.0], ) - - elif self.dim == 3: - - chy0 = self._cellH([p[0] , p[1] , p[2] , sl])[1] - chy1 = self._cellH([p[0] , p[1] + w, p[2] , sl])[1] - chz0 = self._cellH([p[0] , p[1] , p[2] , sl])[2] - chz1 = self._cellH([p[0] , p[1] , p[2] + w, sl])[2] - lenY = chy0 + chy1 - lenZ = chz0 + chz1 - A = lenY * lenZ - - ey0 = fx - ey1 = self._index([p[0], p[1] , p[2] + 2*w, p[-1]]) - ez0 = fx - ez1 = self._index([p[0], p[1] + 2*w, p[2] , p[-1]]) - - n0 = fx - n1 = self._index([p[0], p[1] + 2*w, p[2] , p[-1]]) - n2 = self._index([p[0], p[1] , p[2] + 2*w, p[-1]]) - n3 = self._index([p[0], p[1] + 2*w, p[2] + 2*w, p[-1]]) - - self._hangingFx[self._fx2i[test ]] = ([self._fx2i[fx], chy0*chz0 / A ], ) - self._hangingFx[self._fx2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._fx2i[fx], chy1*chz0 / A ], ) - self._hangingFx[self._fx2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._fx2i[fx], chy0*chz1 / A ], ) - self._hangingFx[self._fx2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._fx2i[fx], chy1*chz1 / A ], ) - - self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], 1.0], ) - self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ey2i[ey0], 1.0], ) - self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) - self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) - self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + 2*w, sl])]] = ([self._ey2i[ey1], 1.0], ) - self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + 2*w, sl])]] = ([self._ey2i[ey1], 1.0], ) - - self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], 1.0], ) - self._hangingEz[self._ez2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ez2i[ez0], 1.0], ) - self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) - self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) - self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] , sl])]] = ([self._ez2i[ez1], 1.0], ) - self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] + w, sl])]] = ([self._ez2i[ez1], 1.0], ) - - # self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], chy0 / lenY], ) - # self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ey2i[ey0], chy1 / lenY], ) - # self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ey2i[ey0], chy0 / lenY / 2.0], [self._ey2i[ey1], chy0 / lenY / 2.0]) - # self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ey2i[ey0], chy1 / lenY / 2.0], [self._ey2i[ey1], chy1 / lenY / 2.0]) - # self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + 2*w, sl])]] = ([self._ey2i[ey1], chy0 / lenY], ) - # self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + 2*w, sl])]] = ([self._ey2i[ey1], chy1 / lenY], ) - - # self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], chz0 / lenZ], ) - # self._hangingEz[self._ez2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ], ) - # self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ez2i[ez0], chz0 / lenZ / 2.0], [self._ez2i[ez1], chz0 / lenZ / 2.0]) - # self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ / 2.0], [self._ez2i[ez1], chz1 / lenZ / 2.0]) - # self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] , sl])]] = ([self._ez2i[ez1], chz0 / lenZ], ) - # self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] + w, sl])]] = ([self._ez2i[ez1], chz1 / lenZ], ) - - self._hangingN[ self._n2i[ test ]] = ([self._n2i[n0], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0], p[1] + 2*w, p[2] , sl])]] = ([self._n2i[n1], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n2], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._n2i[n0], 0.25], [self._n2i[n1], 0.25], [self._n2i[n2], 0.25], [self._n2i[n3], 0.25]) - self._hangingN[ self._n2i[ self._index([p[0], p[1] + 2*w, p[2] + w, sl])]] = ([self._n2i[n1], 0.5], [self._n2i[n3], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0], p[1] , p[2] + 2*w, sl])]] = ([self._n2i[n2], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0], p[1] + w, p[2] + 2*w, sl])]] = ([self._n2i[n2], 0.5], [self._n2i[n3], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0], p[1] + 2*w, p[2] + 2*w, sl])]] = ([self._n2i[n3], 1.0], ) - - # Compute from y faces - for fy in self._facesY: - p = self._pointer(fy) - if p[-1] + 1 > self.levels: continue - sl = p[-1] + 1 #: small level - test = self._index(p[:-1] + [sl]) - if test not in self._facesY: - # Return early without checking the other faces - continue - w = self._levelWidth(sl) - - if self.dim == 2: - chx0 = self._cellH([p[0] , p[1] , sl])[0] - chx1 = self._cellH([p[0] + w, p[1] , sl])[0] - - self._hangingFy[self._fy2i[test ]] = ([self._fy2i[fy], chx0 / (chx0 + chx1)], ) - self._hangingFy[self._fy2i[self._index([p[0] + w, p[1] , sl])]] = ([self._fy2i[fy], chx1 / (chx0 + chx1)], ) - - n0, n1 = fy, self._index([p[0] + 2*w, p[1], p[-1]]) - self._hangingN[self._n2i[test ]] = ([self._n2i[n0], 1.0], ) - self._hangingN[self._n2i[self._index([p[0] + w, p[1] , sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) - self._hangingN[self._n2i[self._index([p[0] + 2*w, p[1] , sl])]] = ([self._n2i[n1], 1.0], ) - - elif self.dim == 3: - - chx0 = self._cellH([p[0] , p[1] , p[2] , sl])[0] - chx1 = self._cellH([p[0] + w, p[1] , p[2] , sl])[0] - chz0 = self._cellH([p[0] , p[1] , p[2] , sl])[2] - chz1 = self._cellH([p[0] , p[1] , p[2] + w, sl])[2] - lenX = chx0 + chx1 - lenZ = chz0 + chz1 - A = lenX * lenZ - - ex0 = fy - ex1 = self._index([p[0] , p[1], p[2] + 2*w, p[-1]]) - ez0 = fy - ez1 = self._index([p[0] + 2*w, p[1], p[2] , p[-1]]) - - n0 = fy - n1 = self._index([p[0] + 2*w, p[1], p[2] , p[-1]]) - n2 = self._index([p[0] , p[1], p[2] + 2*w, p[-1]]) - n3 = self._index([p[0] + 2*w, p[1], p[2] + 2*w, p[-1]]) - - self._hangingFy[self._fy2i[test ]] = ([self._fy2i[fy], chx0*chz0 / A ], ) - self._hangingFy[self._fy2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._fy2i[fy], chx1*chz0 / A ], ) - self._hangingFy[self._fy2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._fy2i[fy], chx0*chz1 / A ], ) - self._hangingFy[self._fy2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._fy2i[fy], chx1*chz1 / A ], ) - - self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], 1.0], ) - self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ex2i[ex0], 1.0], ) - self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) - self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) - self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], 1.0], ) - self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], 1.0], ) - - self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], 1.0], ) - self._hangingEz[self._ez2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], 1.0], ) - self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) - self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) - self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] , sl])]] = ([self._ez2i[ez1], 1.0], ) - self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez1], 1.0], ) - - # self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], chx0 / lenX], ) - # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ex2i[ex0], chx1 / lenX], ) - # self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], chx0 / lenX / 2.0], [self._ex2i[ex1], chx0 / lenX / 2.0]) - # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], chx1 / lenX / 2.0], [self._ex2i[ex1], chx1 / lenX / 2.0]) - # self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], chx0 / lenX], ) - # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], chx1 / lenX], ) - - # self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], chz0 / lenZ], ) - # self._hangingEz[self._ez2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ], ) - # self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ez2i[ez0], chz0 / lenZ / 2.0], [self._ez2i[ez1], chz0 / lenZ / 2.0]) - # self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ / 2.0], [self._ez2i[ez1], chz1 / lenZ / 2.0]) - # self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] , sl])]] = ([self._ez2i[ez1], chz0 / lenZ], ) - # self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez1], chz1 / lenZ], ) - - self._hangingN[ self._n2i[ test ]] = ([self._n2i[n0], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1], p[2] , sl])]] = ([self._n2i[n1], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n2], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._n2i[n0], 0.25], [self._n2i[n1], 0.25], [self._n2i[n2], 0.25], [self._n2i[n3], 0.25]) - self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1], p[2] + w, sl])]] = ([self._n2i[n1], 0.5], [self._n2i[n3], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] , p[1], p[2] + 2*w, sl])]] = ([self._n2i[n2], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0] + w, p[1], p[2] + 2*w, sl])]] = ([self._n2i[n2], 0.5], [self._n2i[n3], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1], p[2] + 2*w, sl])]] = ([self._n2i[n3], 1.0], ) - - if self.dim == 2: - self.__dirtyHanging__ = False - return - - # Compute from z faces - for fz in self._facesZ: - p = self._pointer(fz) - if p[-1] + 1 > self.levels: continue - sl = p[-1] + 1 #: small level - test = self._index(p[:-1] + [sl]) - if test not in self._facesZ: - # Return early without checking the other faces - continue - w = self._levelWidth(sl) - - chx0 = self._cellH([p[0] , p[1] , p[2] , sl])[0] - chx1 = self._cellH([p[0] + w, p[1] , p[2] , sl])[0] - chy0 = self._cellH([p[0] , p[1] , p[2] , sl])[1] - chy1 = self._cellH([p[0] , p[1] + w, p[2] , sl])[1] - lenX = chx0 + chx1 - lenY = chy0 + chy1 - A = lenX * lenY - - ex0 = fz - ex1 = self._index([p[0] , p[1] + 2*w, p[2], p[-1]]) - ey0 = fz - ey1 = self._index([p[0] + 2*w, p[1] , p[2], p[-1]]) - - n0 = fz - n1 = self._index([p[0] + 2*w, p[1] , p[2], p[-1]]) - n2 = self._index([p[0] , p[1] + 2*w, p[2], p[-1]]) - n3 = self._index([p[0] + 2*w, p[1] + 2*w, p[2], p[-1]]) - - self._hangingFz[self._fz2i[test ]] = ([self._fz2i[fz], chx0*chy0 / A ], ) - self._hangingFz[self._fz2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._fz2i[fz], chx1*chy0 / A ], ) - self._hangingFz[self._fz2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._fz2i[fz], chx0*chy1 / A ], ) - self._hangingFz[self._fz2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._fz2i[fz], chx1*chy1 / A ], ) - - self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], 1.0], ) - self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ex2i[ex0], 1.0], ) - self._hangingEx[self._ex2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) - self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) - self._hangingEx[self._ex2i[self._index([p[0] , p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], 1.0], ) - self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], 1.0], ) - - self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], 1.0], ) - self._hangingEy[self._ey2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], 1.0], ) - self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) - self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) - self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] , p[2], sl])]] = ([self._ey2i[ey1], 1.0], ) - self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey1], 1.0], ) - - # self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], chx0 / lenX], ) - # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ex2i[ex0], chx1 / lenX], ) - # self._hangingEx[self._ex2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], chx0 / lenX / 2.0], [self._ex2i[ex1], chx0 / lenX / 2.0]) - # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], chx1 / lenX / 2.0], [self._ex2i[ex1], chx1 / lenX / 2.0]) - # self._hangingEx[self._ex2i[self._index([p[0] , p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], chx0 / lenX], ) - # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], chx1 / lenX], ) - - # self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], chy0 / lenY], ) - # self._hangingEy[self._ey2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], chy1 / lenY], ) - # self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ey2i[ey0], chy0 / lenY / 2.0], [self._ey2i[ey1], chy0 / lenY / 2.0]) - # self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], chy1 / lenY / 2.0], [self._ey2i[ey1], chy1 / lenY / 2.0]) - # self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] , p[2], sl])]] = ([self._ey2i[ey1], chy0 / lenY], ) - # self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey1], chy1 / lenY], ) - - self._hangingN[ self._n2i[ test ]] = ([self._n2i[n0], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1] , p[2], sl])]] = ([self._n2i[n1], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n2], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._n2i[n0], 0.25], [self._n2i[n1], 0.25], [self._n2i[n2], 0.25], [self._n2i[n3], 0.25]) - self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1] + w, p[2], sl])]] = ([self._n2i[n1], 0.5], [self._n2i[n3], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] , p[1] + 2*w, p[2], sl])]] = ([self._n2i[n2], 1.0], ) - self._hangingN[ self._n2i[ self._index([p[0] + w, p[1] + 2*w, p[2], sl])]] = ([self._n2i[n2], 0.5], [self._n2i[n3], 0.5]) - self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1] + 2*w, p[2], sl])]] = ([self._n2i[n3], 1.0], ) - - self.__dirtyHanging__ = False - - def number(self, balance=True, force=False): - if not self.__dirty__ and not force: return - if balance: self.balance() - self._hanging(force=force) - - def _deflationMatrix(self, location, withHanging=True, asOnes=False): - assert location in ['N','F','Fx','Fy'] + (['Fz','E','Ex','Ey','Ez'] if self.dim == 3 else []) - - args = dict() - args['N'] = (self._nodes, self._hangingN, self._n2i ) - args['Fx'] = (self._facesX, self._hangingFx, self._fx2i) - args['Fy'] = (self._facesY, self._hangingFy, self._fy2i) - if self.dim == 3: - args['Fz'] = (self._facesZ, self._hangingFz, self._fz2i) - args['Ex'] = (self._edgesX, self._hangingEx, self._ex2i) - args['Ey'] = (self._edgesY, self._hangingEy, self._ey2i) - args['Ez'] = (self._edgesZ, self._hangingEz, self._ez2i) - if location in ['F', 'E']: - Rlist = [self._deflationMatrix(location + subLoc, withHanging=withHanging, asOnes=asOnes) for subLoc in ['x','y','z'][:self.dim]] - return sp.block_diag(Rlist) - return self.__deflationMatrix(*args[location], withHanging=withHanging, asOnes=asOnes) - - def __deflationMatrix(self, theSet, theHang, theIndex, withHanging=True, asOnes=False): - reducedInd = dict() # final reduced index - ii = 0 - I,J,V = [],[],[] - for fx in sorted(theSet): - if theIndex[fx] not in theHang: - reducedInd[theIndex[fx]] = ii - I += [theIndex[fx]] - J += [ii] - V += [1.0] - ii += 1 - if withHanging: - for hfkey in theHang.keys(): - hf = theHang[hfkey] - I += [hfkey]*len(hf) - J += [reducedInd[_[0]] for _ in hf] - if asOnes: - V += [1.0]*len(hf) - else: - V += [_[1] for _ in hf] - return sp.csr_matrix((V,(I,J)), shape=(len(theSet), len(reducedInd))) - - @property - def faceDiv(self): - if getattr(self, '_faceDiv', None) is None: - self.number() - - # TODO: Preallocate! - I, J, V = [], [], [] - PM = [-1,1]*self.dim # plus / minus - - # TODO total number of faces? - offset = [0]*2 + [self.ntFx]*2 + [self.ntFx+self.ntFy]*2 - - for ii, ind in enumerate(self._sortedCells): - - p = self._pointer(ind) - w = self._levelWidth(p[-1]) - - if self.dim == 2: - faces = [ - self._fx2i[self._index([ p[0] , p[1] , p[2]])], - self._fx2i[self._index([ p[0] + w, p[1] , p[2]])], - self._fy2i[self._index([ p[0] , p[1] , p[2]])], - self._fy2i[self._index([ p[0] , p[1] + w, p[2]])] - ] - elif self.dim == 3: - faces = [ - self._fx2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._fx2i[self._index([ p[0] + w, p[1] , p[2] , p[3]])], - self._fy2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._fy2i[self._index([ p[0] , p[1] + w, p[2] , p[3]])], - self._fz2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._fz2i[self._index([ p[0] , p[1] , p[2] + w, p[3]])] - ] - - for off, pm, face in zip(offset,PM,faces): - I += [ii] - J += [face + off] - V += [pm] - - D = sp.csr_matrix((V,(I,J)), shape=(self.nC, self.ntF)) - R = self._deflationMatrix('F',asOnes=True) - VOL = self.vol - if self.dim == 2: - S = np.r_[self._areaFxFull, self._areaFyFull] - elif self.dim == 3: - S = np.r_[self._areaFxFull, self._areaFyFull, self._areaFzFull] - self._faceDiv = Utils.sdiag(1.0/VOL)*D*Utils.sdiag(S)*R - return self._faceDiv - - @property - def edgeCurl(self): - """Construct the 3D curl operator.""" - assert self.dim > 2, "Edge Curl only programed for 3D." - - if getattr(self, '_edgeCurl', None) is None: - self.number() - # TODO: Preallocate! - I, J, V = [], [], [] - faceOffset = 0 - offset = [self.ntEx]*2 + [self.ntEx+self.ntEy]*2 - PM = [1, -1, -1, 1] - for ii, fx in enumerate(sorted(self._facesX)): - - p = self._pointer(fx) - w = self._levelWidth(p[-1]) - - edges = [ - self._ey2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._ey2i[self._index([ p[0] , p[1] , p[2] + w, p[3]])], - self._ez2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._ez2i[self._index([ p[0] , p[1] + w, p[2] , p[3]])], - ] - - for off, pm, edge in zip(offset,PM,edges): - I += [ii + faceOffset] - J += [edge + off] - V += [pm] - - faceOffset = self.ntFx - offset = [0]*2 + [self.ntEx+self.ntEy]*2 - PM = [-1, 1, 1, -1] - for ii, fy in enumerate(sorted(self._facesY)): - - p = self._pointer(fy) - w = self._levelWidth(p[-1]) - - edges = [ - self._ex2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._ex2i[self._index([ p[0] , p[1] , p[2] + w, p[3]])], - self._ez2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._ez2i[self._index([ p[0] + w, p[1] , p[2] , p[3]])], - ] - - for off, pm, edge in zip(offset,PM,edges): - I += [ii + faceOffset] - J += [edge + off] - V += [pm] - - faceOffset = self.ntFx + self.ntFy - offset = [0]*2 + [self.ntEx]*2 - PM = [1, -1, -1, 1] - for ii, fz in enumerate(sorted(self._facesZ)): - - p = self._pointer(fz) - w = self._levelWidth(p[-1]) - - edges = [ - self._ex2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._ex2i[self._index([ p[0] , p[1] + w, p[2] , p[3]])], - self._ey2i[self._index([ p[0] , p[1] , p[2] , p[3]])], - self._ey2i[self._index([ p[0] + w, p[1] , p[2] , p[3]])], - ] - - for off, pm, edge in zip(offset,PM,edges): - I += [ii + faceOffset] - J += [edge + off] - V += [pm] - - Rf = self._deflationMatrix('F', withHanging=True, asOnes=False) - Re = self._deflationMatrix('E') - - Rf_ave = Utils.sdiag(1./Rf.sum(axis=0)) * Rf.T - - C = sp.csr_matrix((V,(I,J)), shape=(self.ntF, self.ntE)) - S = np.r_[self._areaFxFull, self._areaFyFull, self._areaFzFull] - L = np.r_[self._edgeExFull, self._edgeEyFull, self._edgeEzFull] - self._edgeCurl = Rf_ave*Utils.sdiag(1.0/S)*C*Utils.sdiag(L)*Re - return self._edgeCurl - - - @property - def nodalGrad(self): - raise Exception('Not yet implemented!') - # if getattr(self, '_nodalGrad', None) is None: - # self.number() - # # TODO: Preallocate! - # I, J, V = [], [], [] - # # kinda a hack for the 2D gradient - # # because edges are not stored - # edges = self.faces if self.dim == 2 else self.edges - # for edge in edges: - # if self.dim == 3: - # I += [edge.num, edge.num] - # elif self.dim == 2 and edge.faceType == 'x': - # I += [edge.num + self.nFy, edge.num + self.nFy] - # elif self.dim == 2 and edge.faceType == 'y': - # I += [edge.num - self.nFx, edge.num - self.nFx] - # J += [edge.node0.num, edge.node1.num] - # V += [-1, 1] - # G = sp.csr_matrix((V,(I,J)), shape=(self.nE, self.nN)) - # L = self.edge - # self._nodalGrad = Utils.sdiag(1/L)*G - # return self._nodalGrad - - def _getFaceP(self, xFace, yFace, zFace): - ind1, ind2, ind3 = [], [], [] - for ind in self._sortedCells: - p = self._pointer(ind) - w = self._levelWidth(p[-1]) - - posX = 0 if xFace == 'fXm' else w - posY = 0 if yFace == 'fYm' else w - if self.dim == 3: - posZ = 0 if zFace == 'fZm' else w - - ind1.append( self._fx2i[self._index([ p[0] + posX, p[1]] + p[2:])] ) - ind2.append( self._fy2i[self._index([ p[0], p[1] + posY] + p[2:])] + self.ntFx ) - if self.dim == 3: - ind3.append( self._fz2i[self._index([ p[0], p[1], p[2] + posZ, p[3]])] + self.ntFx + self.ntFy ) - - if self.dim == 2: - IND = np.r_[ind1, ind2] - if self.dim == 3: - IND = np.r_[ind1, ind2, ind3] - - PXXX = sp.coo_matrix((np.ones(self.dim*self.nC), (range(self.dim*self.nC), IND)), shape=(self.dim*self.nC, self.ntF)).tocsr() - - Rf = self._deflationMatrix('F', withHanging=True, asOnes=True) - - return PXXX * Rf - - def _getFacePxx(self): - self.number() - def Pxx(xFace, yFace): - return self._getFaceP(xFace, yFace, None) - return Pxx - - def _getFacePxxx(self): - self.number() - def Pxxx(xFace, yFace, zFace): - return self._getFaceP(xFace, yFace, zFace) - return Pxxx - - def _getEdgeP(self, xEdge, yEdge, zEdge): - if self.dim == 2: raise Exception('Not implemented') # this should be a reordering of the face inner product? - - ind1, ind2, ind3 = [], [], [] - for ind in self._sortedCells: - p = self._pointer(ind) - w = self._levelWidth(p[-1]) - - posX = [0,0] if xEdge == 'eX0' else [w, 0] if xEdge == 'eX1' else [0,w] if xEdge == 'eX2' else [w,w] - posY = [0,0] if yEdge == 'eY0' else [w, 0] if yEdge == 'eY1' else [0,w] if yEdge == 'eY2' else [w,w] - posZ = [0,0] if zEdge == 'eZ0' else [w, 0] if zEdge == 'eZ1' else [0,w] if zEdge == 'eZ2' else [w,w] - - ind1.append( self._ex2i[self._index([ p[0] , p[1] + posX[0], p[2] + posX[1], p[3]])] ) - ind2.append( self._ey2i[self._index([ p[0] + posY[0], p[1] , p[2] + posY[1], p[3]])] + self.ntEx ) - ind3.append( self._ez2i[self._index([ p[0] + posZ[0], p[1] + posZ[1], p[2] , p[3]])] + self.ntEx + self.ntEy ) - - IND = np.r_[ind1, ind2, ind3] - - PXXX = sp.coo_matrix((np.ones(self.dim*self.nC), (range(self.dim*self.nC), IND)), shape=(self.dim*self.nC, self.ntE)).tocsr() - - Re = self._deflationMatrix('E') - - return PXXX * Re - - def _getEdgePxx(self): - raise Exception('Not implemented') # this should be a reordering of the face inner product? - def _getEdgePxxx(self): - self.number() - def Pxxx(xEdge, yEdge, zEdge): - return self._getEdgeP(xEdge, yEdge, zEdge) - return Pxxx - - - def plotGrid(self, ax=None, showIt=False, - grid=True, - cells=True, cellLine=False, - nodes=False, - facesX=False, facesY=False, facesZ=False, - edgesX=False, edgesY=False, edgesZ=False): - - # self.number() - - axOpts = {'projection':'3d'} if self.dim == 3 else {} - if ax is None: - ax = plt.subplot(111, **axOpts) - else: - assert isinstance(ax,matplotlib.axes.Axes), "ax must be an Axes!" - fig = ax.figure - - if grid: - for ind in self._sortedCells: - p = self._asPointer(ind) - n = self._cellN(p) - h = self._cellH(p) - x = [n[0] , n[0] + h[0], n[0] + h[0], n[0] , n[0]] - y = [n[1] , n[1] , n[1] + h[1], n[1] + h[1], n[1]] - if self.dim == 2: - ax.plot(x,y, 'b-') - elif self.dim == 3: - ax.plot(x,y, 'b-', zs=[n[2]]*5) - z = [n[2] + h[2], n[2] + h[2], n[2] + h[2], n[2] + h[2], n[2] + h[2]] - ax.plot(x,y, 'b-', zs=z) - sides = [0,0], [h[0],0], [0,h[1]], [h[0],h[1]] - for s in sides: - x = [n[0] + s[0], n[0] + s[0]] - y = [n[1] + s[1], n[1] + s[1]] - z = [n[2] , n[2] + h[2]] - ax.plot(x,y, 'b-', zs=z) - - if self.dim == 2: - if cells: - ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r.') - if cellLine: - ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r:') - ax.plot(self.gridCC[[0,-1],0], self.gridCC[[0,-1],1], 'ro') - if nodes: - ax.plot(self._gridN[:,0], self._gridN[:,1], 'ms') - ax.plot(self._gridN[self._hangingN.keys(),0], self._gridN[self._hangingN.keys(),1], 'ms', ms=10, mfc='none', mec='m') - if facesX: - ax.plot(self._gridFx[self._hangingFx.keys(),0], self._gridFx[self._hangingFx.keys(),1], 'gs', ms=10, mfc='none', mec='g') - ax.plot(self._gridFx[:,0], self._gridFx[:,1], 'g>') - if facesY: - ax.plot(self._gridFy[self._hangingFy.keys(),0], self._gridFy[self._hangingFy.keys(),1], 'gs', ms=10, mfc='none', mec='g') - ax.plot(self._gridFy[:,0], self._gridFy[:,1], 'g^') - elif self.dim == 3: - if cells: - ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r.', zs=self.gridCC[:,2]) - if cellLine: - ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r:', zs=self.gridCC[:,2]) - ax.plot(self.gridCC[[0,-1],0], self.gridCC[[0,-1],1], 'ro', zs=self.gridCC[[0,-1],2]) - - if nodes: - ax.plot(self._gridN[:,0], self._gridN[:,1], 'ms', zs=self._gridN[:,2]) - ax.plot(self._gridN[self._hangingN.keys(),0], self._gridN[self._hangingN.keys(),1], 'ms', ms=10, mfc='none', mec='m', zs=self._gridN[self._hangingN.keys(),2]) - for key in self._hangingN.keys(): - for hf in self._hangingN[key]: - ind = [key, hf[0]] - ax.plot(self._gridN[ind,0], self._gridN[ind,1], 'm:', zs=self._gridN[ind,2]) - - if facesX: - ax.plot(self._gridFx[:,0], self._gridFx[:,1], 'g>', zs=self._gridFx[:,2]) - ax.plot(self._gridFx[self._hangingFx.keys(),0], self._gridFx[self._hangingFx.keys(),1], 'gs', ms=10, mfc='none', mec='g', zs=self._gridFx[self._hangingFx.keys(),2]) - for key in self._hangingFx.keys(): - for hf in self._hangingFx[key]: - ind = [key, hf[0]] - ax.plot(self._gridFx[ind,0], self._gridFx[ind,1], 'g:', zs=self._gridFx[ind,2]) - - if facesY: - ax.plot(self._gridFy[:,0], self._gridFy[:,1], 'g^', zs=self._gridFy[:,2]) - ax.plot(self._gridFy[self._hangingFy.keys(),0], self._gridFy[self._hangingFy.keys(),1], 'gs', ms=10, mfc='none', mec='g', zs=self._gridFy[self._hangingFy.keys(),2]) - for key in self._hangingFy.keys(): - for hf in self._hangingFy[key]: - ind = [key, hf[0]] - ax.plot(self._gridFy[ind,0], self._gridFy[ind,1], 'g:', zs=self._gridFy[ind,2]) - - if facesZ: - ax.plot(self._gridFz[:,0], self._gridFz[:,1], 'g^', zs=self._gridFz[:,2]) - ax.plot(self._gridFz[self._hangingFz.keys(),0], self._gridFz[self._hangingFz.keys(),1], 'gs', ms=10, mfc='none', mec='g', zs=self._gridFz[self._hangingFz.keys(),2]) - for key in self._hangingFz.keys(): - for hf in self._hangingFz[key]: - ind = [key, hf[0]] - ax.plot(self._gridFz[ind,0], self._gridFz[ind,1], 'g:', zs=self._gridFz[ind,2]) - - if edgesX: - ax.plot(self._gridEx[:,0], self._gridEx[:,1], 'k>', zs=self._gridEx[:,2]) - ax.plot(self._gridEx[self._hangingEx.keys(),0], self._gridEx[self._hangingEx.keys(),1], 'ks', ms=10, mfc='none', mec='k', zs=self._gridEx[self._hangingEx.keys(),2]) - for key in self._hangingEx.keys(): - for hf in self._hangingEx[key]: - ind = [key, hf[0]] - ax.plot(self._gridEx[ind,0], self._gridEx[ind,1], 'k:', zs=self._gridEx[ind,2]) - - - if edgesY: - ax.plot(self._gridEy[:,0], self._gridEy[:,1], 'k<', zs=self._gridEy[:,2]) - ax.plot(self._gridEy[self._hangingEy.keys(),0], self._gridEy[self._hangingEy.keys(),1], 'ks', ms=10, mfc='none', mec='k', zs=self._gridEy[self._hangingEy.keys(),2]) - for key in self._hangingEy.keys(): - for hf in self._hangingEy[key]: - ind = [key, hf[0]] - ax.plot(self._gridEy[ind,0], self._gridEy[ind,1], 'k:', zs=self._gridEy[ind,2]) - - if edgesZ: - ax.plot(self._gridEz[:,0], self._gridEz[:,1], 'k^', zs=self._gridEz[:,2]) - ax.plot(self._gridEz[self._hangingEz.keys(),0], self._gridEz[self._hangingEz.keys(),1], 'ks', ms=10, mfc='none', mec='k', zs=self._gridEz[self._hangingEz.keys(),2]) - for key in self._hangingEz.keys(): - for hf in self._hangingEz[key]: - ind = [key, hf[0]] - ax.plot(self._gridEz[ind,0], self._gridEz[ind,1], 'k:', zs=self._gridEz[ind,2]) - - if showIt:plt.show() - - - def plotImage(self, I, ax=None, showIt=True): - if self.dim == 3: raise Exception() - - if ax is None: ax = plt.subplot(111) - jet = cm = plt.get_cmap('jet') - cNorm = colors.Normalize(vmin=I.min(), vmax=I.max()) - scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) - ax.set_xlim((self.x0[0], self.h[0].sum())) - ax.set_ylim((self.x0[1], self.h[1].sum())) - for ii, node in enumerate(self._sortedCells): - x0, sz = self._cellN(node), self._cellH(node) - ax.add_patch(plt.Rectangle((x0[0], x0[1]), sz[0], sz[1], facecolor=scalarMap.to_rgba(I[ii]), edgecolor='k')) - # if text: ax.text(self.center[0],self.center[1],self.num) - scalarMap._A = [] # http://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots - plt.colorbar(scalarMap) - if showIt: plt.show() - - -def SortGrid(grid, offset=0): - """ - Sorts a grid by the x0 location. - """ - - eps = 1e-7 - def mycmp(c1,c2): - c1 = grid[c1-offset] - c2 = grid[c2-offset] - if c1.size == 2: - if np.abs(c1[1] - c2[1]) < eps: - return c1[0] - c2[0] - return c1[1] - c2[1] - elif c1.size == 3: - if np.abs(c1[2] - c2[2]) < eps: - if np.abs(c1[1] - c2[1]) < eps: - return c1[0] - c2[0] - return c1[1] - c2[1] - return c1[2] - c2[2] - - class K(object): - def __init__(self, obj, *args): - self.obj = obj - def __lt__(self, other): - return mycmp(self.obj, other.obj) < 0 - def __gt__(self, other): - return mycmp(self.obj, other.obj) > 0 - def __eq__(self, other): - return mycmp(self.obj, other.obj) == 0 - def __le__(self, other): - return mycmp(self.obj, other.obj) <= 0 - def __ge__(self, other): - return mycmp(self.obj, other.obj) >= 0 - def __ne__(self, other): - return mycmp(self.obj, other.obj) != 0 - - return sorted(range(offset,grid.shape[0]+offset), key=K) - - -class NotBalancedException(Exception): - pass - -if __name__ == '__main__': - - - def function(xc): - r = xc - np.array([0.5*128]*len(xc)) - dist = np.sqrt(r.dot(r)) - # if dist < 0.05: - # return 5 - if dist < 0.1*128: - return 4 - if dist < 0.3*128: - return 3 - if dist < 1.0*128: - return 2 - else: - return 0 - - # T = Tree([[(1,128)],[(1,128)],[(1,128)]],levels=7) - # T = Tree([128,128,128],levels=7) - T = Tree([[(1,16)],[(1,16)]],levels=4) - # T = Tree([[(1,128)],[(1,128)]],levels=7) - # T.refine(lambda xc:1, balance=False) - # T._index([0,0,0]) - # T._pointer(0) - - - tic = time.time() - T.refine(function)#, balance=False) - print time.time() - tic - print T.nC - - T.plotImage(np.random.rand(T.nC),showIt=True) - - print T.getFaceInnerProduct() - # print T.gridFz - - - # T._refineCell([8,0,1]) - # T._refineCell([8,0,2]) - # T._refineCell([12,0,2]) - # T._refineCell([8,4,2]) - # T._refineCell([6,0,3]) - # T._refineCell([8,8,1]) - # T._refineCell([0,0,0,1]) - # T.__dirty__ = True - - - print T.gridFx.shape[0], T.nFx - - - - ax = plt.subplot(211) - ax.spy(T.edgeCurl) - - # print Mesh.TensorMesh([2,2,2]).edgeCurl.todense() - # print T.edgeCurl.todense() - # print Mesh.TensorMesh([2,2,2]).edgeCurl.todense() - T.edgeCurl.todense() - # print T.gridEy - Mesh.TensorMesh([2,2,2]).gridEy - - # print T.edge - # T.plotGrid(ax=ax) - - # R = deflationMatrix(T._facesX, T._hangingFx, T._fx2i) - # print R - - ax = plt.subplot(212)#, projection='3d') - ax.spy(Mesh.TensorMesh([2,2,2]).edgeCurl) - - # ax = plt.subplot(313) - # ax.spy(T.faceDiv[:,:T.nFx] * R) - - - # T.balance() - # T.plotGrid(ax=ax) - - # cx = T._getNextCell([0,0,1],direction=0,positive=True) - # print cx - # # print [T._asPointer(_) for _ in cx] - # cx = T._getNextCell([8,0,3],direction=0,positive=False) - # print T._asPointer(cx) - # cx = T._getNextCell([8,8,1],direction=1,positive=False) - # print cx, #[T._asPointer(_) for _ in cx] - # cm = T._getNextCell([64,80,4],direction=0,positive=False) - # cy = T._getNextCell([64,80,4],direction=1,positive=True) - # cp = T._getNextCell([64,80,4],direction=1,positive=False) - - # ax.plot( T._cellN([4,0,1])[0],T._cellN([4,0,1])[1], 'yd') - # ax.plot( T._cellN(cx)[0],T._cellN(cx)[1], 'ys') - # ax.plot( T._cellN(cm)[0],T._cellN(cm)[1], 'ys') - # ax.plot( T._cellN(cy)[0],T._cellN(cy)[1], 'ys') - # ax.plot( T._cellN(cp[0])[0],T._cellN(cp[0])[1], 'ys') - # ax.plot( T._cellN(cp[1])[0],T._cellN(cp[1])[1], 'ys') - - - - - - # print T.nN - - plt.show() - diff --git a/SimPEG/Mesh/TreeMesh.py b/SimPEG/Mesh/TreeMesh.py index d2d18972..aa697ec1 100644 --- a/SimPEG/Mesh/TreeMesh.py +++ b/SimPEG/Mesh/TreeMesh.py @@ -1,26 +1,1548 @@ +# ___ ___ ___ ___ ___ +# /\ \ ___ /\__\ /\ \ /\ \ /\ \ +# /::\ \ /\ \ /::| | /::\ \ /::\ \ /::\ \ +# /:/\ \ \ \:\ \ /:|:| | /:/\:\ \ /:/\:\ \ /:/\:\ \ +# _\:\~\ \ \ /::\__\ /:/|:|__|__ /::\~\:\ \ /::\~\:\ \ /:/ \:\ \ +# /\ \:\ \ \__\ __/:/\/__//:/ |::::\__\/:/\:\ \:\__\/:/\:\ \:\__\/:/__/_\:\__\ +# \:\ \:\ \/__//\/:/ / \/__/~~/:/ /\/__\:\/:/ /\:\~\:\ \/__/\:\ /\ \/__/ +# \:\ \:\__\ \::/__/ /:/ / \::/ / \:\ \:\__\ \:\ \:\__\ +# \:\/:/ / \:\__\ /:/ / \/__/ \:\ \/__/ \:\/:/ / +# \::/ / \/__/ /:/ / \:\__\ \::/ / +# \/__/ \/__/ \/__/ \/__/ +# ___ ___ ___ ___ ___ ___ +# /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ +# /::\ \ /::\ \ \:\ \ /::\ \ /::\ \ /::\ \ +# /:/\:\ \ /:/\:\ \ \:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ +# /:/ \:\ \ /:/ \:\ \ /::\ \ /::\~\:\ \ /::\~\:\ \ /::\~\:\ \ +# /:/__/ \:\__\/:/__/ \:\__\ /:/\:\__\/:/\:\ \:\__\/:/\:\ \:\__\/:/\:\ \:\__\ +# \:\ \ /:/ /\:\ \ \/__//:/ \/__/\/_|::\/:/ /\:\~\:\ \/__/\:\~\:\ \/__/ +# \:\ /:/ / \:\ \ /:/ / |:|::/ / \:\ \:\__\ \:\ \:\__\ +# \:\/:/ / \:\ \ \/__/ |:|\/__/ \:\ \/__/ \:\ \/__/ +# \::/ / \:\__\ |:| | \:\__\ \:\__\ +# \/__/ \/__/ \|__| \/__/ \/__/ +# +# +# @rowanc1, Nov. 10, 2015 +# +# .----------------.----------------. +# /| /| /| +# / | / | / | +# / | 011 / | 111 / | +# / | / | / | +# .----------------.----+-----------. | +# /| . ---------/|----.----------/|----. +# / | /| / | /| / | /| +# / | / | 001 / | / | 101 / | / | +# / | / | / | / | / | / | +# . -------------- .----------------. |/ | +# | . ---+------|----.----+------|----. | +# | /| .______|___/|____.______|___/|____. +# | / | / 010 | / | / 110| / | / +# | / | / | / | / | / | / +# . ---+---------- . ---+---------- . | / +# | |/ | |/ | |/ z +# | . ----------|----.-----------|----. ^ y +# | / 000 | / 100 | / | / +# | / | / | / | / +# | / | / | / o----> x +# . -------------- . -------------- . +# +# +# Face Refinement: +# +# 2_______________3 _______________ +# | | | | | +# ^ | | | (0,1) | (1,1) | +# | | | | | | +# | | x | ---> |-------+-------| +# t1 | | | | | +# | | | (0,0) | (1,0) | +# |_______________| |_______|_______| +# 0 t0--> 1 +# +# +# Face and Edge naming conventions: +# +# fZp +# | +# 6 ------eX3------ 7 +# /| | / | +# /eZ2 . / eZ3 +# eY2 | fYp eY3 | +# / | / fXp| +# 4 ------eX2----- 5 | +# |fXm 2 -----eX1--|---- 3 z +# eZ0 / | eY1 ^ y +# | eY0 . fYm eZ1 / | / +# | / | | / | / +# 0 ------eX0------1 o----> x +# | +# fZm +# +# +# fX fY fZ +# 2___________3 2___________3 2___________3 +# | e1 | | e1 | | e1 | +# | | | | | | +# e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y +# | | ^ | | ^ | | ^ +# |___________| |___> y |___________| |___> x |___________| |___> x +# 0 e0 1 0 e0 1 0 e0 1 +# + from SimPEG import np, sp, Utils, Solver -from BaseMesh import BaseMesh -from InnerProducts import InnerProducts import matplotlib.pyplot as plt +import matplotlib from mpl_toolkits.mplot3d import Axes3D import matplotlib.colors as colors import matplotlib.cm as cmx +import TreeUtils +from InnerProducts import InnerProducts +from BaseMesh import BaseMesh +import time + +MAX_BITS = 20 + +class TreeMesh(BaseMesh, InnerProducts): + def __init__(self, h_in, x0_in=None, levels=3): + assert type(h_in) is list, 'h_in must be a list' + assert len(h_in) > 1, "len(h_in) must be greater than 1" + + h = range(len(h_in)) + for i, h_i in enumerate(h_in): + if type(h_i) in [int, long, float]: + # This gives you something over the unit cube. + h_i = np.ones(int(h_i))/int(h_i) + elif type(h_i) is list: + h_i = Utils.meshTensor(h_i) + assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) + assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) + assert len(h_i) == 2**levels, "must make h and levels match" + h[i] = h_i[:] # make a copy. + self.h = h + + x0 = np.zeros(len(h)) + if x0_in is not None: + assert len(h) == len(x0_in), "Dimension mismatch. x0 != len(h)" + for i in range(len(h)): + x_i, h_i = x0_in[i], h[i] + if Utils.isScalar(x_i): + x0[i] = x_i + elif x_i == '0': + x0[i] = 0.0 + elif x_i == 'C': + x0[i] = -h_i.sum()*0.5 + elif x_i == 'N': + x0[i] = -h_i.sum() + else: + raise Exception("x0[%i] must be a scalar or '0' to be zero, 'C' to center, or 'N' to be negative." % i) + + BaseMesh.__init__(self, [len(_) for _ in h], x0) + + self._levels = levels + self._levelBits = int(np.ceil(np.sqrt(levels)))+1 + + self.__dirty__ = True #: The numbering is dirty! + + self._cells = set() + self._cells.add(0) + + @property + def __dirty__(self): + return self.__dirtyFaces__ or self.__dirtyEdges__ or self.__dirtyNodes__ or self.__dirtyHanging__ + + @__dirty__.setter + def __dirty__(self, val): + assert val is True + self.__dirtyFaces__ = True + self.__dirtyEdges__ = True + self.__dirtyNodes__ = True + self.__dirtyHanging__ = True + + deleteThese = [ + '__sortedCells', + '_gridCC', '_gridN', '_gridFx', '_gridFy', '_gridFz', '_gridEx', '_gridEy', '_gridEz', + '_area', '_edge', '_vol', + '_faceDiv', '_edgeCurl', '_nodalGrad' + ] + for p in deleteThese: + if hasattr(self, p): delattr(self, p) + + @property + def levels(self): return self._levels + + @property + def dim(self): return len(self.h) + + @property + def nC(self): return len(self._cells) + + @property + def nN(self): + self.number() + return len(self._nodes) - len(self._hangingN) + + @property + def nF(self): + return self.nFx + self.nFy + (0 if self.dim == 2 else self.nFz) + + @property + def nFx(self): + self.number() + return len(self._facesX) - len(self._hangingFx) + + @property + def nFy(self): + self.number() + return len(self._facesY) - len(self._hangingFy) + + @property + def nFz(self): + if self.dim == 2: return None + self.number() + return len(self._facesZ) - len(self._hangingFz) + + @property + def nE(self): + return self.nEx + self.nEy + (0 if self.dim == 2 else self.nEz) + + @property + def nEx(self): + if self.dim == 2:return self.nFy + self.number() + return len(self._edgesX) - len(self._hangingEx) + + @property + def nEy(self): + if self.dim == 2:return self.nFx + self.number() + return len(self._edgesY) - len(self._hangingEy) + + @property + def nEz(self): + if self.dim == 2: return None + self.number() + return len(self._edgesZ) - len(self._hangingEz) + + @property + def nhN(self): + self.number() + return len(self._hangingN) + + @property + def nhF(self): + return self.nhFx + self.nhFy + (0 if self.dim == 2 else self.nhFz) + + @property + def nhFx(self): + self.number() + return len(self._hangingFx) + + @property + def nhFy(self): + self.number() + return len(self._hangingFy) + + @property + def nhFz(self): + if self.dim == 2: return None + self.number() + return len(self._hangingFz) + + @property + def nhE(self): + return self.nhEx + self.nhEy + (0 if self.dim == 2 else self.nhEz) + + @property + def nhEx(self): + if self.dim == 2:return self.nhFy + self.number() + return len(self._hangingEx) + + @property + def nhEy(self): + if self.dim == 2:return self.nhFx + self.number() + return len(self._hangingEy) + + @property + def nhEz(self): + if self.dim == 2: return None + self.number() + return len(self._hangingEz) -def SortByX0(): + @property + def ntN(self): + self.number() + return len(self._nodes) + + @property + def ntF(self): + return self.ntFx + self.ntFy + (0 if self.dim == 2 else self.ntFz) + + @property + def ntFx(self): + self.number() + return len(self._facesX) + + @property + def ntFy(self): + self.number() + return len(self._facesY) + + @property + def ntFz(self): + if self.dim == 2: return None + self.number() + return len(self._facesZ) + + @property + def ntE(self): + return self.ntEx + self.ntEy + (0 if self.dim == 2 else self.ntEz) + + @property + def ntEx(self): + if self.dim == 2:return self.ntFy + self.number() + return len(self._edgesX) + + @property + def ntEy(self): + if self.dim == 2:return self.ntFx + self.number() + return len(self._edgesY) + + @property + def ntEz(self): + if self.dim == 2: return None + self.number() + return len(self._edgesZ) + + @property + def _sortedCells(self): + if getattr(self, '__sortedCells', None) is None: + self.__sortedCells = sorted(self._cells) + return self.__sortedCells + + @property + def permuteCC(self): + #TODO: cache these? + P = SortGrid(self.gridCC) + return sp.identity(self.nC).tocsr()[P,:] + + @property + def permuteF(self): + #TODO: cache these? + P = SortGrid(self.gridFx) + P += SortGrid(self.gridFy, offset=self.nFx) + if self.dim == 3: + P += SortGrid(self.gridFz, offset=self.nFx+self.nFy) + return sp.identity(self.nF).tocsr()[P,:] + + @property + def permuteE(self): + #TODO: cache these? + if self.dim == 2: + P = SortGrid(self.gridFy) + P += SortGrid(self.gridFx, offset=self.nEx) + return sp.identity(self.nE).tocsr()[P,:] + if self.dim == 3: + P = SortGrid(self.gridEx) + P += SortGrid(self.gridEy, offset=self.nEx) + P += SortGrid(self.gridEz, offset=self.nEx+self.nEy) + return sp.identity(self.nE).tocsr()[P,:] + + def _index(self, pointer): + assert len(pointer) is self.dim+1 + assert pointer[-1] <= self.levels + return TreeUtils.index(self.dim, MAX_BITS, self._levelBits, pointer[:-1], pointer[-1]) + + def _pointer(self, index): + assert type(index) in [int, long] + return TreeUtils.point(self.dim, MAX_BITS, self._levelBits, index) + + def __contains__(self, v): + return self._asIndex(v) in self._cells + + def refine(self, function=None, recursive=True, cells=None, balance=True, verbose=False, _inRecursion=False): + + if not _inRecursion: + self.__dirty__ = True + if verbose: print 'Refining Mesh' + + cells = cells if cells is not None else sorted(self._cells) + recurse = [] + tic = time.time() + for cell in cells: + p = self._pointer(cell) + do = function(self._cellC(cell)) > p[-1] + if do: + recurse += self._refineCell(cell) + + if verbose: print ' ', time.time() - tic + + if recursive and len(recurse) > 0: + recurse += self.refine(function=function, recursive=True, cells=recurse, balance=balance, _inRecursion=True) + + if balance and not _inRecursion: + self.balance() + return recurse + + def _refineCell(self, pointer): + pointer = self._asPointer(pointer) + ind = self._asIndex(pointer) + assert ind in self + h = self._levelWidth(pointer[-1])/2 # halfWidth + nL = pointer[-1] + 1 # new level + add = lambda p:p[0]+p[1] + added = [] + def addCell(p): + i = self._index(p+[nL]) + self._cells.add(i) + added.append(i) + + addCell(map(add, zip(pointer[:-1], [0,0,0][:self.dim]))) + addCell(map(add, zip(pointer[:-1], [h,0,0][:self.dim]))) + addCell(map(add, zip(pointer[:-1], [0,h,0][:self.dim]))) + addCell(map(add, zip(pointer[:-1], [h,h,0][:self.dim]))) + if self.dim == 3: + addCell(map(add, zip(pointer[:-1], [0,0,h]))) + addCell(map(add, zip(pointer[:-1], [h,0,h]))) + addCell(map(add, zip(pointer[:-1], [0,h,h]))) + addCell(map(add, zip(pointer[:-1], [h,h,h]))) + self._cells.remove(ind) + return added + + def corsen(self, function=None): + self.__dirty__ = True + raise Exception('Not yet implemented') + + + def _corsenCell(self, pointer): + raise Exception('Not yet implemented') + + # something like this: ?? + pointer = self._asPointer(pointer) + ind = self._asIndex(pointer) + assert ind in self + + parent = self._parentPointer(ind) + children = _childPointers(parent) + for child in children: + self._cells.remove(self._asIndex(child)) + + parentInd = self._asIndex(parent) + self._cells.add(parentInd) + return parentInd + + def _asPointer(self, ind): + if type(ind) in [int, long]: + return self._pointer(ind) + if type(ind) is list: + assert len(ind) == (self.dim + 1), str(ind) +' is not valid pointer' + assert ind[-1] <= self.levels, str(ind) +' is not valid pointer' + return ind + if isinstance(ind, np.ndarray): + return ind.tolist() + raise Exception + + def _asIndex(self, pointer): + if type(pointer) in [int, long]: + return pointer + if type(pointer) is list: + return self._index(pointer) + raise Exception + + + def _childPointers(self, pointer, direction=0, positive=True, returnAll=False): + l = self._levelWidth(pointer[-1] + 1) + + if self.dim == 2: + + children = [ + [pointer[0] , pointer[1] , pointer[-1] + 1], + [pointer[0] + l, pointer[1] , pointer[-1] + 1], + [pointer[0] , pointer[1] + l, pointer[-1] + 1], + [pointer[0] + l, pointer[1] + l, pointer[-1] + 1] + ] + + elif self.dim == 3: + + children = [ + [pointer[0] , pointer[1] , pointer[2] , pointer[-1] + 1], + [pointer[0] + l, pointer[1] , pointer[2] , pointer[-1] + 1], + [pointer[0] , pointer[1] + l, pointer[2] , pointer[-1] + 1], + [pointer[0] + l, pointer[1] + l, pointer[2] , pointer[-1] + 1], + [pointer[0] , pointer[1] , pointer[2] + l, pointer[-1] + 1], + [pointer[0] + l, pointer[1] , pointer[2] + l, pointer[-1] + 1], + [pointer[0] , pointer[1] + l, pointer[2] + l, pointer[-1] + 1], + [pointer[0] + l, pointer[1] + l, pointer[2] + l, pointer[-1] + 1] + ] + if direction == 0: ind = [0,2,4,6] if not positive else [1,3,5,7] + if direction == 1: ind = [0,1,4,5] if not positive else [2,3,6,7] + if direction == 2: ind = [0,1,2,3] if not positive else [4,5,6,7] + + if returnAll: + return children + return [children[_] for _ in ind[:(self.dim-1)*2]] + + + def _parentPointer(self, pointer): + mod = self._levelWidth(pointer[-1] - 1) + return [p - (p % mod) for p in pointer[:-1]] + [pointer[-1]-1] + + def _cellN(self, p): + p = self._asPointer(p) + return [hi[:p[ii]].sum() for ii, hi in enumerate(self.h)] + + def _cellH(self, p): + p = self._asPointer(p) + w = self._levelWidth(p[-1]) + return [hi[p[ii]:p[ii]+w].sum() for ii, hi in enumerate(self.h)] + + def _cellC(self, p): + return (np.array(self._cellH(p))/2.0 + self._cellN(p)).tolist() + + def _levelWidth(self, level): + return 2**(self.levels - level) + + def _isInsideMesh(self, pointer): + inside = True + for p in pointer[:-1]: + inside = inside and p >= 0 and p < 2**self.levels + return inside + + def _getNextCell(self, ind, direction=0, positive=True, _lookUp=True): + """ + Returns a None, int, list, or nested list + The int is the cell number. + + """ + if direction >= self.dim: return None + pointer = self._asPointer(ind) + if pointer[-1] > self.levels: return None + + step = (1 if positive else -1) * self._levelWidth(pointer[-1]) + nextCell = [p if ii is not direction else p + step for ii, p in enumerate(pointer)] + # raise Exception(pointer, nextCell) + if not self._isInsideMesh(nextCell): return None + + # it might be the same size as me? + if nextCell in self: return self._index(nextCell) + + if nextCell[-1] + 1 <= self.levels: # if I am not the smallest. + children = self._childPointers(pointer, direction=direction, positive=positive) + nextCells = [self._getNextCell(child, direction=direction, positive=positive, _lookUp=False) for child in children] + if nextCells[0] is not None: + return nextCells + + if not _lookUp: return None + + # it might be bigger than me? + return self._getNextCell(self._parentPointer(pointer), + direction=direction, positive=positive) + + def balance(self, recursive=True, cells=None, verbose=False, _inRecursion=False): + + tic = time.time() + if not _inRecursion: + self.__dirty__ = True + if verbose: print 'Balancing Mesh:' + + cells = cells if cells is not None else sorted(self._cells) + + # calcDepth = lambda i: lambda A: i if type(A) is not list else max(map(calcDepth(i+1), A)) + # flatten = lambda A: A if calcDepth(0)(A) == 1 else flatten([_ for __ in A for _ in (__ if type(__) is list else [__])]) + + recurse = set() + + for cell in cells: + p = self._asPointer(cell) + if p[-1] == self.levels: continue + + cs = range(6) + cs[0] = self._getNextCell(cell, direction=0, positive=False) + cs[1] = self._getNextCell(cell, direction=0, positive=True) + cs[2] = self._getNextCell(cell, direction=1, positive=False) + cs[3] = self._getNextCell(cell, direction=1, positive=True) + cs[4] = self._getNextCell(cell, direction=2, positive=False) # this will be None if in 2D + cs[5] = self._getNextCell(cell, direction=2, positive=True) # this will be None if in 2D + + do = np.any([ + type(c) is list and np.any([type(_) is list for _ in c]) + for c in cs + if c is not None + ]) + # depth = calcDepth(0)(cs) + # print depth, depth > 2, do, [jj for jj in flatten(cs) if jj is not None] + # recurse += [jj for jj in flatten(cs) if jj is not None] + + if do and cell in self: + newCells = self._refineCell(cell) + recurse.update([_ for _ in cs if type(_) in [int, long]]) # only add the bigger ones! + recurse.update(newCells) + + if verbose: print ' ', len(cells), time.time() - tic + if recursive and len(recurse) > 0: + self.balance(cells=sorted(recurse), _inRecursion=True) + + @property + def gridCC(self): + if getattr(self, '_gridCC', None) is None: + self._gridCC = np.zeros((len(self._cells),self.dim)) + for ii, ind in enumerate(self._sortedCells): + p = self._asPointer(ind) + self._gridCC[ii, :] = self._cellC(p) + return self._gridCC + + @property + def gridN(self): + self.number() + R = self._deflationMatrix('N', withHanging=False) + return R.T * self._gridN + + @property + def gridFx(self): + self.number() + R = self._deflationMatrix('Fx', withHanging=False) + return R.T * self._gridFx + + @property + def gridFy(self): + self.number() + R = self._deflationMatrix('Fy', withHanging=False) + return R.T * self._gridFy + + @property + def gridFz(self): + if self.dim < 3: return None + self.number() + R = self._deflationMatrix('Fz', withHanging=False) + return R.T * self._gridFz + + @property + def gridEx(self): + if self.dim == 2: return self.gridFy + self.number() + R = self._deflationMatrix('Ex', withHanging=False) + return R.T * self._gridEx + + @property + def gridEy(self): + if self.dim == 2: return self.gridFx + self.number() + R = self._deflationMatrix('Ey', withHanging=False) + return R.T * self._gridEy + + @property + def gridEz(self): + if self.dim < 3: return None + self.number() + R = self._deflationMatrix('Ez', withHanging=False) + return R.T * self._gridEz + + @property + def vol(self): + if getattr(self, '_vol', None) is None: + self._vol = np.zeros(len(self._cells)) + for ii, ind in enumerate(self._sortedCells): + p = self._asPointer(ind) + self._vol[ii] = np.prod(self._cellH(p)) + return self._vol + + @property + def area(self): + self.number() + if getattr(self, '_area', None) is None: + Rf = self._deflationMatrix('F', withHanging=False) + self._area = Rf.T * ( + np.r_[self._areaFxFull, self._areaFyFull] if self.dim == 2 else + np.r_[self._areaFxFull, self._areaFyFull, self._areaFzFull] + ) + return self._area + + @property + def edge(self): + self.number() + if self.dim == 2: + return np.r_[self.area[self.nFx:], self.area[:self.nFx]] + if getattr(self, '_edge', None) is None: + Re = self._deflationMatrix('E', withHanging=False) + self._edge = Re.T * np.r_[self._edgeExFull, self._edgeEyFull, self._edgeEzFull] + + return self._edge + + def _onSameLevel(self, i0, i1): + p0 = self._asPointer(i0) + p1 = self._asPointer(i1) + return p0[-1] == p1[-1] + + def _numberNodes(self, force=False): + if not self.__dirtyNodes__ and not force: return + + self._nodes = set() + + for ind in self._cells: + p = self._asPointer(ind) + w = self._levelWidth(p[-1]) + if self.dim == 2: + self._nodes.add(self._index([p[0] , p[1] , p[2]])) + self._nodes.add(self._index([p[0] + w, p[1] , p[2]])) + self._nodes.add(self._index([p[0] , p[1] + w, p[2]])) + self._nodes.add(self._index([p[0] + w, p[1] + w, p[2]])) + elif self.dim == 3: + self._nodes.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._nodes.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) + self._nodes.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) + self._nodes.add(self._index([p[0] + w, p[1] + w, p[2] , p[3]])) + self._nodes.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) + self._nodes.add(self._index([p[0] + w, p[1] , p[2] + w, p[3]])) + self._nodes.add(self._index([p[0] , p[1] + w, p[2] + w, p[3]])) + self._nodes.add(self._index([p[0] + w, p[1] + w, p[2] + w, p[3]])) + gridN = [] + self._n2i = dict() + for ii, n in enumerate(sorted(self._nodes)): + self._n2i[n] = ii + gridN.append( self._cellN( self._pointer(n) ) ) + self._gridN = np.array(gridN) + + self.__dirtyNodes__ = False + + def _numberFaces(self, force=False): + if not self.__dirtyFaces__ and not force: return + + self._facesX = set() + self._facesY = set() + if self.dim == 3: + self._facesZ = set() + + for ind in self._cells: + p = self._asPointer(ind) + w = self._levelWidth(p[-1]) + + if self.dim == 2: + self._facesX.add(self._index([p[0] , p[1] , p[2]])) + self._facesX.add(self._index([p[0] + w, p[1] , p[2]])) + self._facesY.add(self._index([p[0] , p[1] , p[2]])) + self._facesY.add(self._index([p[0] , p[1] + w, p[2]])) + elif self.dim == 3: + self._facesX.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._facesX.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) + self._facesY.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._facesY.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) + self._facesZ.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._facesZ.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) + + gridFx = [] + areaFx = [] + self._fx2i = dict() + for ii, fx in enumerate(sorted(self._facesX)): + self._fx2i[fx] = ii + p = self._pointer(fx) + n, h = self._cellN(p), self._cellH(p) + if self.dim == 2: + gridFx.append( [n[0], n[1] + h[1]/2.0] ) + areaFx.append( h[1] ) + elif self.dim == 3: + gridFx.append( [n[0], n[1] + h[1]/2.0, n[2] + h[2]/2.0] ) + areaFx.append( h[1]*h[2] ) + self._gridFx = np.array(gridFx) + self._areaFxFull = np.array(areaFx) + + gridFy = [] + areaFy = [] + self._fy2i = dict() + for ii, fy in enumerate(sorted(self._facesY)): + self._fy2i[fy] = ii + p = self._pointer(fy) + n, h = self._cellN(p), self._cellH(p) + if self.dim == 2: + gridFy.append( [n[0] + h[0]/2.0, n[1]] ) + areaFy.append( h[0] ) + elif self.dim == 3: + gridFy.append( [n[0] + h[0]/2.0, n[1], n[2] + h[2]/2.0] ) + areaFy.append( h[0]*h[2] ) + self._gridFy = np.array(gridFy) + self._areaFyFull = np.array(areaFy) + + if self.dim == 2: + self.__dirtyFaces__ = False + return + + gridFz = [] + areaFz = [] + self._fz2i = dict() + for ii, fz in enumerate(sorted(self._facesZ)): + self._fz2i[fz] = ii + p = self._pointer(fz) + n, h = self._cellN(p), self._cellH(p) + gridFz.append( [n[0] + h[0]/2.0, n[1] + h[1]/2.0, n[2]] ) + areaFz.append(h[0]*h[1]) + self._gridFz = np.array(gridFz) + self._areaFzFull = np.array(areaFz) + + self.__dirtyFaces__ = False + + def _numberEdges(self, force=False): + if self.dim == 2: + self.__dirtyEdges__ = False + return + if not self.__dirtyEdges__ and not force: return + + self._edgesX = set() + self._edgesY = set() + self._edgesZ = set() + + for ind in self._cells: + p = self._asPointer(ind) + w = self._levelWidth(p[-1]) + self._edgesX.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._edgesX.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) + self._edgesX.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) + self._edgesX.add(self._index([p[0] , p[1] + w, p[2] + w, p[3]])) + + self._edgesY.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._edgesY.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) + self._edgesY.add(self._index([p[0] , p[1] , p[2] + w, p[3]])) + self._edgesY.add(self._index([p[0] + w, p[1] , p[2] + w, p[3]])) + + self._edgesZ.add(self._index([p[0] , p[1] , p[2] , p[3]])) + self._edgesZ.add(self._index([p[0] + w, p[1] , p[2] , p[3]])) + self._edgesZ.add(self._index([p[0] , p[1] + w, p[2] , p[3]])) + self._edgesZ.add(self._index([p[0] + w, p[1] + w, p[2] , p[3]])) + + gridEx = [] + edgeEx = [] + self._ex2i = dict() + for ii, ex in enumerate(sorted(self._edgesX)): + self._ex2i[ex] = ii + p = self._pointer(ex) + n, h = self._cellN(p), self._cellH(p) + gridEx.append( [n[0] + h[0]/2.0, n[1], n[2]] ) + edgeEx.append( h[0] ) + self._gridEx = np.array(gridEx) + self._edgeExFull = np.array(edgeEx) + + gridEy = [] + edgeEy = [] + self._ey2i = dict() + for ii, ey in enumerate(sorted(self._edgesY)): + self._ey2i[ey] = ii + p = self._pointer(ey) + n, h = self._cellN(p), self._cellH(p) + gridEy.append( [n[0], n[1] + h[1]/2.0, n[2]] ) + edgeEy.append( h[1] ) + self._gridEy = np.array(gridEy) + self._edgeEyFull = np.array(edgeEy) + + gridEz = [] + edgeEz = [] + self._ez2i = dict() + for ii, ez in enumerate(sorted(self._edgesZ)): + self._ez2i[ez] = ii + p = self._pointer(ez) + n, h = self._cellN(p), self._cellH(p) + gridEz.append( [n[0], n[1], n[2] + h[2]/2.0] ) + edgeEz.append( h[2] ) + self._gridEz = np.array(gridEz) + self._edgeEzFull = np.array(edgeEz) + + self.__dirtyEdges__ = False + + def _hanging(self, force=False): + if not self.__dirtyHanging__ and not force: return + + self._numberNodes(force=force) + self._numberFaces(force=force) + self._numberEdges(force=force) + + self._hangingN = dict() + self._hangingFx = dict() + self._hangingFy = dict() + if self.dim == 3: + self._hangingFz = dict() + self._hangingEx = dict() + self._hangingEy = dict() + self._hangingEz = dict() + + # Compute from x faces + for fx in self._facesX: + p = self._pointer(fx) + if p[-1] + 1 > self.levels: continue + sl = p[-1] + 1 #: small level + test = self._index(p[:-1] + [sl]) + if test not in self._facesX: + # Return early without checking the other faces + continue + w = self._levelWidth(sl) + + if self.dim == 2: + chy0 = self._cellH([p[0] , p[1] , sl])[1] + chy1 = self._cellH([p[0] , p[1] + w, sl])[1] + A = (chy0 + chy1) + + self._hangingFx[self._fx2i[test ]] = ([self._fx2i[fx], chy0 / A], ) + self._hangingFx[self._fx2i[self._index([p[0] , p[1] + w, sl])]] = ([self._fx2i[fx], chy1 / A], ) + + n0, n1 = fx, self._index([p[0], p[1] + 2*w, p[-1]]) + self._hangingN[self._n2i[test ]] = ([self._n2i[n0], 1.0], ) + self._hangingN[self._n2i[self._index([p[0] , p[1] + w, sl])]] = ([self._n2i[n0], 1.0 - chy0 / A], [self._n2i[n1], 1.0 - chy1 / A]) + self._hangingN[self._n2i[self._index([p[0] , p[1] + 2*w, sl])]] = ([self._n2i[n1], 1.0], ) + + elif self.dim == 3: + + chy0 = self._cellH([p[0] , p[1] , p[2] , sl])[1] + chy1 = self._cellH([p[0] , p[1] + w, p[2] , sl])[1] + chz0 = self._cellH([p[0] , p[1] , p[2] , sl])[2] + chz1 = self._cellH([p[0] , p[1] , p[2] + w, sl])[2] + lenY = chy0 + chy1 + lenZ = chz0 + chz1 + A = lenY * lenZ + + ey0 = fx + ey1 = self._index([p[0], p[1] , p[2] + 2*w, p[-1]]) + ez0 = fx + ez1 = self._index([p[0], p[1] + 2*w, p[2] , p[-1]]) + + n0 = fx + n1 = self._index([p[0], p[1] + 2*w, p[2] , p[-1]]) + n2 = self._index([p[0], p[1] , p[2] + 2*w, p[-1]]) + n3 = self._index([p[0], p[1] + 2*w, p[2] + 2*w, p[-1]]) + + self._hangingFx[self._fx2i[test ]] = ([self._fx2i[fx], chy0*chz0 / A ], ) + self._hangingFx[self._fx2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._fx2i[fx], chy1*chz0 / A ], ) + self._hangingFx[self._fx2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._fx2i[fx], chy0*chz1 / A ], ) + self._hangingFx[self._fx2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._fx2i[fx], chy1*chz1 / A ], ) + + self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], 1.0], ) + self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ey2i[ey0], 1.0], ) + self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) + self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) + self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + 2*w, sl])]] = ([self._ey2i[ey1], 1.0], ) + self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + 2*w, sl])]] = ([self._ey2i[ey1], 1.0], ) + + self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], 1.0], ) + self._hangingEz[self._ez2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ez2i[ez0], 1.0], ) + self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) + self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) + self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] , sl])]] = ([self._ez2i[ez1], 1.0], ) + self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] + w, sl])]] = ([self._ez2i[ez1], 1.0], ) + + # self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], chy0 / lenY], ) + # self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ey2i[ey0], chy1 / lenY], ) + # self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ey2i[ey0], chy0 / lenY / 2.0], [self._ey2i[ey1], chy0 / lenY / 2.0]) + # self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ey2i[ey0], chy1 / lenY / 2.0], [self._ey2i[ey1], chy1 / lenY / 2.0]) + # self._hangingEy[self._ey2i[self._index([p[0], p[1] , p[2] + 2*w, sl])]] = ([self._ey2i[ey1], chy0 / lenY], ) + # self._hangingEy[self._ey2i[self._index([p[0], p[1] + w, p[2] + 2*w, sl])]] = ([self._ey2i[ey1], chy1 / lenY], ) + + # self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], chz0 / lenZ], ) + # self._hangingEz[self._ez2i[self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ], ) + # self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._ez2i[ez0], chz0 / lenZ / 2.0], [self._ez2i[ez1], chz0 / lenZ / 2.0]) + # self._hangingEz[self._ez2i[self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ / 2.0], [self._ez2i[ez1], chz1 / lenZ / 2.0]) + # self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] , sl])]] = ([self._ez2i[ez1], chz0 / lenZ], ) + # self._hangingEz[self._ez2i[self._index([p[0], p[1] + 2*w, p[2] + w, sl])]] = ([self._ez2i[ez1], chz1 / lenZ], ) + + self._hangingN[ self._n2i[ test ]] = ([self._n2i[n0], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0], p[1] + w, p[2] , sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0], p[1] + 2*w, p[2] , sl])]] = ([self._n2i[n1], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0], p[1] , p[2] + w, sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n2], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0], p[1] + w, p[2] + w, sl])]] = ([self._n2i[n0], 0.25], [self._n2i[n1], 0.25], [self._n2i[n2], 0.25], [self._n2i[n3], 0.25]) + self._hangingN[ self._n2i[ self._index([p[0], p[1] + 2*w, p[2] + w, sl])]] = ([self._n2i[n1], 0.5], [self._n2i[n3], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0], p[1] , p[2] + 2*w, sl])]] = ([self._n2i[n2], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0], p[1] + w, p[2] + 2*w, sl])]] = ([self._n2i[n2], 0.5], [self._n2i[n3], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0], p[1] + 2*w, p[2] + 2*w, sl])]] = ([self._n2i[n3], 1.0], ) + + # Compute from y faces + for fy in self._facesY: + p = self._pointer(fy) + if p[-1] + 1 > self.levels: continue + sl = p[-1] + 1 #: small level + test = self._index(p[:-1] + [sl]) + if test not in self._facesY: + # Return early without checking the other faces + continue + w = self._levelWidth(sl) + + if self.dim == 2: + chx0 = self._cellH([p[0] , p[1] , sl])[0] + chx1 = self._cellH([p[0] + w, p[1] , sl])[0] + + self._hangingFy[self._fy2i[test ]] = ([self._fy2i[fy], chx0 / (chx0 + chx1)], ) + self._hangingFy[self._fy2i[self._index([p[0] + w, p[1] , sl])]] = ([self._fy2i[fy], chx1 / (chx0 + chx1)], ) + + n0, n1 = fy, self._index([p[0] + 2*w, p[1], p[-1]]) + self._hangingN[self._n2i[test ]] = ([self._n2i[n0], 1.0], ) + self._hangingN[self._n2i[self._index([p[0] + w, p[1] , sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) + self._hangingN[self._n2i[self._index([p[0] + 2*w, p[1] , sl])]] = ([self._n2i[n1], 1.0], ) + + elif self.dim == 3: + + chx0 = self._cellH([p[0] , p[1] , p[2] , sl])[0] + chx1 = self._cellH([p[0] + w, p[1] , p[2] , sl])[0] + chz0 = self._cellH([p[0] , p[1] , p[2] , sl])[2] + chz1 = self._cellH([p[0] , p[1] , p[2] + w, sl])[2] + lenX = chx0 + chx1 + lenZ = chz0 + chz1 + A = lenX * lenZ + + ex0 = fy + ex1 = self._index([p[0] , p[1], p[2] + 2*w, p[-1]]) + ez0 = fy + ez1 = self._index([p[0] + 2*w, p[1], p[2] , p[-1]]) + + n0 = fy + n1 = self._index([p[0] + 2*w, p[1], p[2] , p[-1]]) + n2 = self._index([p[0] , p[1], p[2] + 2*w, p[-1]]) + n3 = self._index([p[0] + 2*w, p[1], p[2] + 2*w, p[-1]]) + + self._hangingFy[self._fy2i[test ]] = ([self._fy2i[fy], chx0*chz0 / A ], ) + self._hangingFy[self._fy2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._fy2i[fy], chx1*chz0 / A ], ) + self._hangingFy[self._fy2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._fy2i[fy], chx0*chz1 / A ], ) + self._hangingFy[self._fy2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._fy2i[fy], chx1*chz1 / A ], ) + + self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], 1.0], ) + self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ex2i[ex0], 1.0], ) + self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) + self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) + self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], 1.0], ) + self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], 1.0], ) + + self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], 1.0], ) + self._hangingEz[self._ez2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], 1.0], ) + self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) + self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], 0.5], [self._ez2i[ez1], 0.5]) + self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] , sl])]] = ([self._ez2i[ez1], 1.0], ) + self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez1], 1.0], ) + + # self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], chx0 / lenX], ) + # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ex2i[ex0], chx1 / lenX], ) + # self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], chx0 / lenX / 2.0], [self._ex2i[ex1], chx0 / lenX / 2.0]) + # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ex2i[ex0], chx1 / lenX / 2.0], [self._ex2i[ex1], chx1 / lenX / 2.0]) + # self._hangingEx[self._ex2i[self._index([p[0] , p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], chx0 / lenX], ) + # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1], p[2] + 2*w, sl])]] = ([self._ex2i[ex1], chx1 / lenX], ) + + # self._hangingEz[self._ez2i[test ]] = ([self._ez2i[ez0], chz0 / lenZ], ) + # self._hangingEz[self._ez2i[self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ], ) + # self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._ez2i[ez0], chz0 / lenZ / 2.0], [self._ez2i[ez1], chz0 / lenZ / 2.0]) + # self._hangingEz[self._ez2i[self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez0], chz1 / lenZ / 2.0], [self._ez2i[ez1], chz1 / lenZ / 2.0]) + # self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] , sl])]] = ([self._ez2i[ez1], chz0 / lenZ], ) + # self._hangingEz[self._ez2i[self._index([p[0] + 2*w, p[1], p[2] + w, sl])]] = ([self._ez2i[ez1], chz1 / lenZ], ) + + self._hangingN[ self._n2i[ test ]] = ([self._n2i[n0], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0] + w, p[1], p[2] , sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1], p[2] , sl])]] = ([self._n2i[n1], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0] , p[1], p[2] + w, sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n2], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] + w, p[1], p[2] + w, sl])]] = ([self._n2i[n0], 0.25], [self._n2i[n1], 0.25], [self._n2i[n2], 0.25], [self._n2i[n3], 0.25]) + self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1], p[2] + w, sl])]] = ([self._n2i[n1], 0.5], [self._n2i[n3], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] , p[1], p[2] + 2*w, sl])]] = ([self._n2i[n2], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0] + w, p[1], p[2] + 2*w, sl])]] = ([self._n2i[n2], 0.5], [self._n2i[n3], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1], p[2] + 2*w, sl])]] = ([self._n2i[n3], 1.0], ) + + if self.dim == 2: + self.__dirtyHanging__ = False + return + + # Compute from z faces + for fz in self._facesZ: + p = self._pointer(fz) + if p[-1] + 1 > self.levels: continue + sl = p[-1] + 1 #: small level + test = self._index(p[:-1] + [sl]) + if test not in self._facesZ: + # Return early without checking the other faces + continue + w = self._levelWidth(sl) + + chx0 = self._cellH([p[0] , p[1] , p[2] , sl])[0] + chx1 = self._cellH([p[0] + w, p[1] , p[2] , sl])[0] + chy0 = self._cellH([p[0] , p[1] , p[2] , sl])[1] + chy1 = self._cellH([p[0] , p[1] + w, p[2] , sl])[1] + lenX = chx0 + chx1 + lenY = chy0 + chy1 + A = lenX * lenY + + ex0 = fz + ex1 = self._index([p[0] , p[1] + 2*w, p[2], p[-1]]) + ey0 = fz + ey1 = self._index([p[0] + 2*w, p[1] , p[2], p[-1]]) + + n0 = fz + n1 = self._index([p[0] + 2*w, p[1] , p[2], p[-1]]) + n2 = self._index([p[0] , p[1] + 2*w, p[2], p[-1]]) + n3 = self._index([p[0] + 2*w, p[1] + 2*w, p[2], p[-1]]) + + self._hangingFz[self._fz2i[test ]] = ([self._fz2i[fz], chx0*chy0 / A ], ) + self._hangingFz[self._fz2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._fz2i[fz], chx1*chy0 / A ], ) + self._hangingFz[self._fz2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._fz2i[fz], chx0*chy1 / A ], ) + self._hangingFz[self._fz2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._fz2i[fz], chx1*chy1 / A ], ) + + self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], 1.0], ) + self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ex2i[ex0], 1.0], ) + self._hangingEx[self._ex2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) + self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], 0.5], [self._ex2i[ex1], 0.5]) + self._hangingEx[self._ex2i[self._index([p[0] , p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], 1.0], ) + self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], 1.0], ) + + self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], 1.0], ) + self._hangingEy[self._ey2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], 1.0], ) + self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) + self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], 0.5], [self._ey2i[ey1], 0.5]) + self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] , p[2], sl])]] = ([self._ey2i[ey1], 1.0], ) + self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey1], 1.0], ) + + # self._hangingEx[self._ex2i[test ]] = ([self._ex2i[ex0], chx0 / lenX], ) + # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ex2i[ex0], chx1 / lenX], ) + # self._hangingEx[self._ex2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], chx0 / lenX / 2.0], [self._ex2i[ex1], chx0 / lenX / 2.0]) + # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ex2i[ex0], chx1 / lenX / 2.0], [self._ex2i[ex1], chx1 / lenX / 2.0]) + # self._hangingEx[self._ex2i[self._index([p[0] , p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], chx0 / lenX], ) + # self._hangingEx[self._ex2i[self._index([p[0] + w, p[1] + 2*w, p[2], sl])]] = ([self._ex2i[ex1], chx1 / lenX], ) + + # self._hangingEy[self._ey2i[test ]] = ([self._ey2i[ey0], chy0 / lenY], ) + # self._hangingEy[self._ey2i[self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], chy1 / lenY], ) + # self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._ey2i[ey0], chy0 / lenY / 2.0], [self._ey2i[ey1], chy0 / lenY / 2.0]) + # self._hangingEy[self._ey2i[self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey0], chy1 / lenY / 2.0], [self._ey2i[ey1], chy1 / lenY / 2.0]) + # self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] , p[2], sl])]] = ([self._ey2i[ey1], chy0 / lenY], ) + # self._hangingEy[self._ey2i[self._index([p[0] + 2*w, p[1] + w, p[2], sl])]] = ([self._ey2i[ey1], chy1 / lenY], ) + + self._hangingN[ self._n2i[ test ]] = ([self._n2i[n0], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0] + w, p[1] , p[2], sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n1], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1] , p[2], sl])]] = ([self._n2i[n1], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0] , p[1] + w, p[2], sl])]] = ([self._n2i[n0], 0.5], [self._n2i[n2], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] + w, p[1] + w, p[2], sl])]] = ([self._n2i[n0], 0.25], [self._n2i[n1], 0.25], [self._n2i[n2], 0.25], [self._n2i[n3], 0.25]) + self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1] + w, p[2], sl])]] = ([self._n2i[n1], 0.5], [self._n2i[n3], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] , p[1] + 2*w, p[2], sl])]] = ([self._n2i[n2], 1.0], ) + self._hangingN[ self._n2i[ self._index([p[0] + w, p[1] + 2*w, p[2], sl])]] = ([self._n2i[n2], 0.5], [self._n2i[n3], 0.5]) + self._hangingN[ self._n2i[ self._index([p[0] + 2*w, p[1] + 2*w, p[2], sl])]] = ([self._n2i[n3], 1.0], ) + + self.__dirtyHanging__ = False + + def number(self, balance=True, force=False): + if not self.__dirty__ and not force: return + if balance: self.balance() + self._hanging(force=force) + + def _deflationMatrix(self, location, withHanging=True, asOnes=False): + assert location in ['N','F','Fx','Fy'] + (['Fz','E','Ex','Ey','Ez'] if self.dim == 3 else []) + + args = dict() + args['N'] = (self._nodes, self._hangingN, self._n2i ) + args['Fx'] = (self._facesX, self._hangingFx, self._fx2i) + args['Fy'] = (self._facesY, self._hangingFy, self._fy2i) + if self.dim == 3: + args['Fz'] = (self._facesZ, self._hangingFz, self._fz2i) + args['Ex'] = (self._edgesX, self._hangingEx, self._ex2i) + args['Ey'] = (self._edgesY, self._hangingEy, self._ey2i) + args['Ez'] = (self._edgesZ, self._hangingEz, self._ez2i) + if location in ['F', 'E']: + Rlist = [self._deflationMatrix(location + subLoc, withHanging=withHanging, asOnes=asOnes) for subLoc in ['x','y','z'][:self.dim]] + return sp.block_diag(Rlist) + return self.__deflationMatrix(*args[location], withHanging=withHanging, asOnes=asOnes) + + def __deflationMatrix(self, theSet, theHang, theIndex, withHanging=True, asOnes=False): + reducedInd = dict() # final reduced index + ii = 0 + I,J,V = [],[],[] + for fx in sorted(theSet): + if theIndex[fx] not in theHang: + reducedInd[theIndex[fx]] = ii + I += [theIndex[fx]] + J += [ii] + V += [1.0] + ii += 1 + if withHanging: + for hfkey in theHang.keys(): + hf = theHang[hfkey] + I += [hfkey]*len(hf) + J += [reducedInd[_[0]] for _ in hf] + if asOnes: + V += [1.0]*len(hf) + else: + V += [_[1] for _ in hf] + return sp.csr_matrix((V,(I,J)), shape=(len(theSet), len(reducedInd))) + + @property + def faceDiv(self): + if getattr(self, '_faceDiv', None) is None: + self.number() + + # TODO: Preallocate! + I, J, V = [], [], [] + PM = [-1,1]*self.dim # plus / minus + + # TODO total number of faces? + offset = [0]*2 + [self.ntFx]*2 + [self.ntFx+self.ntFy]*2 + + for ii, ind in enumerate(self._sortedCells): + + p = self._pointer(ind) + w = self._levelWidth(p[-1]) + + if self.dim == 2: + faces = [ + self._fx2i[self._index([ p[0] , p[1] , p[2]])], + self._fx2i[self._index([ p[0] + w, p[1] , p[2]])], + self._fy2i[self._index([ p[0] , p[1] , p[2]])], + self._fy2i[self._index([ p[0] , p[1] + w, p[2]])] + ] + elif self.dim == 3: + faces = [ + self._fx2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._fx2i[self._index([ p[0] + w, p[1] , p[2] , p[3]])], + self._fy2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._fy2i[self._index([ p[0] , p[1] + w, p[2] , p[3]])], + self._fz2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._fz2i[self._index([ p[0] , p[1] , p[2] + w, p[3]])] + ] + + for off, pm, face in zip(offset,PM,faces): + I += [ii] + J += [face + off] + V += [pm] + + D = sp.csr_matrix((V,(I,J)), shape=(self.nC, self.ntF)) + R = self._deflationMatrix('F',asOnes=True) + VOL = self.vol + if self.dim == 2: + S = np.r_[self._areaFxFull, self._areaFyFull] + elif self.dim == 3: + S = np.r_[self._areaFxFull, self._areaFyFull, self._areaFzFull] + self._faceDiv = Utils.sdiag(1.0/VOL)*D*Utils.sdiag(S)*R + return self._faceDiv + + @property + def edgeCurl(self): + """Construct the 3D curl operator.""" + assert self.dim > 2, "Edge Curl only programed for 3D." + + if getattr(self, '_edgeCurl', None) is None: + self.number() + # TODO: Preallocate! + I, J, V = [], [], [] + faceOffset = 0 + offset = [self.ntEx]*2 + [self.ntEx+self.ntEy]*2 + PM = [1, -1, -1, 1] + for ii, fx in enumerate(sorted(self._facesX)): + + p = self._pointer(fx) + w = self._levelWidth(p[-1]) + + edges = [ + self._ey2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._ey2i[self._index([ p[0] , p[1] , p[2] + w, p[3]])], + self._ez2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._ez2i[self._index([ p[0] , p[1] + w, p[2] , p[3]])], + ] + + for off, pm, edge in zip(offset,PM,edges): + I += [ii + faceOffset] + J += [edge + off] + V += [pm] + + faceOffset = self.ntFx + offset = [0]*2 + [self.ntEx+self.ntEy]*2 + PM = [-1, 1, 1, -1] + for ii, fy in enumerate(sorted(self._facesY)): + + p = self._pointer(fy) + w = self._levelWidth(p[-1]) + + edges = [ + self._ex2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._ex2i[self._index([ p[0] , p[1] , p[2] + w, p[3]])], + self._ez2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._ez2i[self._index([ p[0] + w, p[1] , p[2] , p[3]])], + ] + + for off, pm, edge in zip(offset,PM,edges): + I += [ii + faceOffset] + J += [edge + off] + V += [pm] + + faceOffset = self.ntFx + self.ntFy + offset = [0]*2 + [self.ntEx]*2 + PM = [1, -1, -1, 1] + for ii, fz in enumerate(sorted(self._facesZ)): + + p = self._pointer(fz) + w = self._levelWidth(p[-1]) + + edges = [ + self._ex2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._ex2i[self._index([ p[0] , p[1] + w, p[2] , p[3]])], + self._ey2i[self._index([ p[0] , p[1] , p[2] , p[3]])], + self._ey2i[self._index([ p[0] + w, p[1] , p[2] , p[3]])], + ] + + for off, pm, edge in zip(offset,PM,edges): + I += [ii + faceOffset] + J += [edge + off] + V += [pm] + + Rf = self._deflationMatrix('F', withHanging=True, asOnes=False) + Re = self._deflationMatrix('E') + + Rf_ave = Utils.sdiag(1./Rf.sum(axis=0)) * Rf.T + + C = sp.csr_matrix((V,(I,J)), shape=(self.ntF, self.ntE)) + S = np.r_[self._areaFxFull, self._areaFyFull, self._areaFzFull] + L = np.r_[self._edgeExFull, self._edgeEyFull, self._edgeEzFull] + self._edgeCurl = Rf_ave*Utils.sdiag(1.0/S)*C*Utils.sdiag(L)*Re + return self._edgeCurl + + + @property + def nodalGrad(self): + raise Exception('Not yet implemented!') + # if getattr(self, '_nodalGrad', None) is None: + # self.number() + # # TODO: Preallocate! + # I, J, V = [], [], [] + # # kinda a hack for the 2D gradient + # # because edges are not stored + # edges = self.faces if self.dim == 2 else self.edges + # for edge in edges: + # if self.dim == 3: + # I += [edge.num, edge.num] + # elif self.dim == 2 and edge.faceType == 'x': + # I += [edge.num + self.nFy, edge.num + self.nFy] + # elif self.dim == 2 and edge.faceType == 'y': + # I += [edge.num - self.nFx, edge.num - self.nFx] + # J += [edge.node0.num, edge.node1.num] + # V += [-1, 1] + # G = sp.csr_matrix((V,(I,J)), shape=(self.nE, self.nN)) + # L = self.edge + # self._nodalGrad = Utils.sdiag(1/L)*G + # return self._nodalGrad + + def _getFaceP(self, xFace, yFace, zFace): + ind1, ind2, ind3 = [], [], [] + for ind in self._sortedCells: + p = self._pointer(ind) + w = self._levelWidth(p[-1]) + + posX = 0 if xFace == 'fXm' else w + posY = 0 if yFace == 'fYm' else w + if self.dim == 3: + posZ = 0 if zFace == 'fZm' else w + + ind1.append( self._fx2i[self._index([ p[0] + posX, p[1]] + p[2:])] ) + ind2.append( self._fy2i[self._index([ p[0], p[1] + posY] + p[2:])] + self.ntFx ) + if self.dim == 3: + ind3.append( self._fz2i[self._index([ p[0], p[1], p[2] + posZ, p[3]])] + self.ntFx + self.ntFy ) + + if self.dim == 2: + IND = np.r_[ind1, ind2] + if self.dim == 3: + IND = np.r_[ind1, ind2, ind3] + + PXXX = sp.coo_matrix((np.ones(self.dim*self.nC), (range(self.dim*self.nC), IND)), shape=(self.dim*self.nC, self.ntF)).tocsr() + + Rf = self._deflationMatrix('F', withHanging=True, asOnes=True) + + return PXXX * Rf + + def _getFacePxx(self): + self.number() + def Pxx(xFace, yFace): + return self._getFaceP(xFace, yFace, None) + return Pxx + + def _getFacePxxx(self): + self.number() + def Pxxx(xFace, yFace, zFace): + return self._getFaceP(xFace, yFace, zFace) + return Pxxx + + def _getEdgeP(self, xEdge, yEdge, zEdge): + if self.dim == 2: raise Exception('Not implemented') # this should be a reordering of the face inner product? + + ind1, ind2, ind3 = [], [], [] + for ind in self._sortedCells: + p = self._pointer(ind) + w = self._levelWidth(p[-1]) + + posX = [0,0] if xEdge == 'eX0' else [w, 0] if xEdge == 'eX1' else [0,w] if xEdge == 'eX2' else [w,w] + posY = [0,0] if yEdge == 'eY0' else [w, 0] if yEdge == 'eY1' else [0,w] if yEdge == 'eY2' else [w,w] + posZ = [0,0] if zEdge == 'eZ0' else [w, 0] if zEdge == 'eZ1' else [0,w] if zEdge == 'eZ2' else [w,w] + + ind1.append( self._ex2i[self._index([ p[0] , p[1] + posX[0], p[2] + posX[1], p[3]])] ) + ind2.append( self._ey2i[self._index([ p[0] + posY[0], p[1] , p[2] + posY[1], p[3]])] + self.ntEx ) + ind3.append( self._ez2i[self._index([ p[0] + posZ[0], p[1] + posZ[1], p[2] , p[3]])] + self.ntEx + self.ntEy ) + + IND = np.r_[ind1, ind2, ind3] + + PXXX = sp.coo_matrix((np.ones(self.dim*self.nC), (range(self.dim*self.nC), IND)), shape=(self.dim*self.nC, self.ntE)).tocsr() + + Re = self._deflationMatrix('E') + + return PXXX * Re + + def _getEdgePxx(self): + raise Exception('Not implemented') # this should be a reordering of the face inner product? + def _getEdgePxxx(self): + self.number() + def Pxxx(xEdge, yEdge, zEdge): + return self._getEdgeP(xEdge, yEdge, zEdge) + return Pxxx + + + def plotGrid(self, ax=None, showIt=False, + grid=True, + cells=True, cellLine=False, + nodes=False, + facesX=False, facesY=False, facesZ=False, + edgesX=False, edgesY=False, edgesZ=False): + + # self.number() + + axOpts = {'projection':'3d'} if self.dim == 3 else {} + if ax is None: + ax = plt.subplot(111, **axOpts) + else: + assert isinstance(ax,matplotlib.axes.Axes), "ax must be an Axes!" + fig = ax.figure + + if grid: + for ind in self._sortedCells: + p = self._asPointer(ind) + n = self._cellN(p) + h = self._cellH(p) + x = [n[0] , n[0] + h[0], n[0] + h[0], n[0] , n[0]] + y = [n[1] , n[1] , n[1] + h[1], n[1] + h[1], n[1]] + if self.dim == 2: + ax.plot(x,y, 'b-') + elif self.dim == 3: + ax.plot(x,y, 'b-', zs=[n[2]]*5) + z = [n[2] + h[2], n[2] + h[2], n[2] + h[2], n[2] + h[2], n[2] + h[2]] + ax.plot(x,y, 'b-', zs=z) + sides = [0,0], [h[0],0], [0,h[1]], [h[0],h[1]] + for s in sides: + x = [n[0] + s[0], n[0] + s[0]] + y = [n[1] + s[1], n[1] + s[1]] + z = [n[2] , n[2] + h[2]] + ax.plot(x,y, 'b-', zs=z) + + if self.dim == 2: + if cells: + ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r.') + if cellLine: + ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r:') + ax.plot(self.gridCC[[0,-1],0], self.gridCC[[0,-1],1], 'ro') + if nodes: + ax.plot(self._gridN[:,0], self._gridN[:,1], 'ms') + ax.plot(self._gridN[self._hangingN.keys(),0], self._gridN[self._hangingN.keys(),1], 'ms', ms=10, mfc='none', mec='m') + if facesX: + ax.plot(self._gridFx[self._hangingFx.keys(),0], self._gridFx[self._hangingFx.keys(),1], 'gs', ms=10, mfc='none', mec='g') + ax.plot(self._gridFx[:,0], self._gridFx[:,1], 'g>') + if facesY: + ax.plot(self._gridFy[self._hangingFy.keys(),0], self._gridFy[self._hangingFy.keys(),1], 'gs', ms=10, mfc='none', mec='g') + ax.plot(self._gridFy[:,0], self._gridFy[:,1], 'g^') + elif self.dim == 3: + if cells: + ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r.', zs=self.gridCC[:,2]) + if cellLine: + ax.plot(self.gridCC[:,0], self.gridCC[:,1], 'r:', zs=self.gridCC[:,2]) + ax.plot(self.gridCC[[0,-1],0], self.gridCC[[0,-1],1], 'ro', zs=self.gridCC[[0,-1],2]) + + if nodes: + ax.plot(self._gridN[:,0], self._gridN[:,1], 'ms', zs=self._gridN[:,2]) + ax.plot(self._gridN[self._hangingN.keys(),0], self._gridN[self._hangingN.keys(),1], 'ms', ms=10, mfc='none', mec='m', zs=self._gridN[self._hangingN.keys(),2]) + for key in self._hangingN.keys(): + for hf in self._hangingN[key]: + ind = [key, hf[0]] + ax.plot(self._gridN[ind,0], self._gridN[ind,1], 'm:', zs=self._gridN[ind,2]) + + if facesX: + ax.plot(self._gridFx[:,0], self._gridFx[:,1], 'g>', zs=self._gridFx[:,2]) + ax.plot(self._gridFx[self._hangingFx.keys(),0], self._gridFx[self._hangingFx.keys(),1], 'gs', ms=10, mfc='none', mec='g', zs=self._gridFx[self._hangingFx.keys(),2]) + for key in self._hangingFx.keys(): + for hf in self._hangingFx[key]: + ind = [key, hf[0]] + ax.plot(self._gridFx[ind,0], self._gridFx[ind,1], 'g:', zs=self._gridFx[ind,2]) + + if facesY: + ax.plot(self._gridFy[:,0], self._gridFy[:,1], 'g^', zs=self._gridFy[:,2]) + ax.plot(self._gridFy[self._hangingFy.keys(),0], self._gridFy[self._hangingFy.keys(),1], 'gs', ms=10, mfc='none', mec='g', zs=self._gridFy[self._hangingFy.keys(),2]) + for key in self._hangingFy.keys(): + for hf in self._hangingFy[key]: + ind = [key, hf[0]] + ax.plot(self._gridFy[ind,0], self._gridFy[ind,1], 'g:', zs=self._gridFy[ind,2]) + + if facesZ: + ax.plot(self._gridFz[:,0], self._gridFz[:,1], 'g^', zs=self._gridFz[:,2]) + ax.plot(self._gridFz[self._hangingFz.keys(),0], self._gridFz[self._hangingFz.keys(),1], 'gs', ms=10, mfc='none', mec='g', zs=self._gridFz[self._hangingFz.keys(),2]) + for key in self._hangingFz.keys(): + for hf in self._hangingFz[key]: + ind = [key, hf[0]] + ax.plot(self._gridFz[ind,0], self._gridFz[ind,1], 'g:', zs=self._gridFz[ind,2]) + + if edgesX: + ax.plot(self._gridEx[:,0], self._gridEx[:,1], 'k>', zs=self._gridEx[:,2]) + ax.plot(self._gridEx[self._hangingEx.keys(),0], self._gridEx[self._hangingEx.keys(),1], 'ks', ms=10, mfc='none', mec='k', zs=self._gridEx[self._hangingEx.keys(),2]) + for key in self._hangingEx.keys(): + for hf in self._hangingEx[key]: + ind = [key, hf[0]] + ax.plot(self._gridEx[ind,0], self._gridEx[ind,1], 'k:', zs=self._gridEx[ind,2]) + + + if edgesY: + ax.plot(self._gridEy[:,0], self._gridEy[:,1], 'k<', zs=self._gridEy[:,2]) + ax.plot(self._gridEy[self._hangingEy.keys(),0], self._gridEy[self._hangingEy.keys(),1], 'ks', ms=10, mfc='none', mec='k', zs=self._gridEy[self._hangingEy.keys(),2]) + for key in self._hangingEy.keys(): + for hf in self._hangingEy[key]: + ind = [key, hf[0]] + ax.plot(self._gridEy[ind,0], self._gridEy[ind,1], 'k:', zs=self._gridEy[ind,2]) + + if edgesZ: + ax.plot(self._gridEz[:,0], self._gridEz[:,1], 'k^', zs=self._gridEz[:,2]) + ax.plot(self._gridEz[self._hangingEz.keys(),0], self._gridEz[self._hangingEz.keys(),1], 'ks', ms=10, mfc='none', mec='k', zs=self._gridEz[self._hangingEz.keys(),2]) + for key in self._hangingEz.keys(): + for hf in self._hangingEz[key]: + ind = [key, hf[0]] + ax.plot(self._gridEz[ind,0], self._gridEz[ind,1], 'k:', zs=self._gridEz[ind,2]) + + if showIt:plt.show() + + + def plotImage(self, I, ax=None, showIt=True): + if self.dim == 3: raise Exception() + + if ax is None: ax = plt.subplot(111) + jet = cm = plt.get_cmap('jet') + cNorm = colors.Normalize(vmin=I.min(), vmax=I.max()) + scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) + ax.set_xlim((self.x0[0], self.h[0].sum())) + ax.set_ylim((self.x0[1], self.h[1].sum())) + for ii, node in enumerate(self._sortedCells): + x0, sz = self._cellN(node), self._cellH(node) + ax.add_patch(plt.Rectangle((x0[0], x0[1]), sz[0], sz[1], facecolor=scalarMap.to_rgba(I[ii]), edgecolor='k')) + # if text: ax.text(self.center[0],self.center[1],self.num) + scalarMap._A = [] # http://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots + plt.colorbar(scalarMap) + if showIt: plt.show() + + +def SortGrid(grid, offset=0): + """ + Sorts a grid by the x0 location. + """ + eps = 1e-7 def mycmp(c1,c2): - if c1.x0.size == 2: - if np.abs(c1.x0[1] - c2.x0[1]) < eps: - return c1.x0[0] - c2.x0[0] - return c1.x0[1] - c2.x0[1] - elif c1.x0.size == 3: - if np.abs(c1.x0[2] - c2.x0[2]) < eps: - if np.abs(c1.x0[1] - c2.x0[1]) < eps: - return c1.x0[0] - c2.x0[0] - return c1.x0[1] - c2.x0[1] - return c1.x0[2] - c2.x0[2] + c1 = grid[c1-offset] + c2 = grid[c2-offset] + if c1.size == 2: + if np.abs(c1[1] - c2[1]) < eps: + return c1[0] - c2[0] + return c1[1] - c2[1] + elif c1.size == 3: + if np.abs(c1[2] - c2[2]) < eps: + if np.abs(c1[1] - c2[1]) < eps: + return c1[0] - c2[0] + return c1[1] - c2[1] + return c1[2] - c2[2] class K(object): def __init__(self, obj, *args): @@ -37,1107 +1559,111 @@ def SortByX0(): return mycmp(self.obj, other.obj) >= 0 def __ne__(self, other): return mycmp(self.obj, other.obj) != 0 - return K - -class TreeNode(object): - """docstring for TreeNode""" - - __slots__ = ['x0', 'num'] - - def __init__(self, mesh, x0=[0,0]): - self.x0 = np.array(x0, dtype=float) - mesh.nodes.add(self) - - @property - def center(self): return self.x0 - -class TreeEdge(object): - """docstring for TreeEdge""" - - __slots__ = ['mesh', 'children', 'depth', 'x0', 'num', 'edgeType', 'sz', 'node0', 'node1'] - - def __init__(self, mesh, x0=[0,0], edgeType=None, sz=[1,], depth=0, - node0=None, node1=None): - self.mesh = mesh - self.depth = depth - - self.x0 = x0 - self.sz = sz - self.edgeType = edgeType - - mesh.edges.add(self) - if edgeType is 'x': mesh.edgesX.add(self) - elif edgeType is 'y': mesh.edgesY.add(self) - elif edgeType is 'z': mesh.edgesZ.add(self) - - self.node0 = node0 if isinstance(node0,TreeNode) else TreeNode(mesh, x0=self.x0) - self.node1 = node1 if isinstance(node1,TreeNode) else TreeNode(mesh, x0=self.x0 + self.tangent*self.sz[0]) - - @property - def isleaf(self): return getattr(self, 'children', None) is None - - def refine(self): - if not self.isleaf: return - self.mesh.isNumbered = False - - self.children = np.empty(2,dtype=TreeFace) - # Create refined x0's - x0r_0 = self.x0 - x0r_1 = self.x0+0.5*self.tangent*self.sz - self.children[0] = TreeEdge(self.mesh, x0=x0r_0, edgeType=self.edgeType, sz=0.5*self.sz, depth=self.depth+1, node0=self.node0) - self.children[1] = TreeEdge(self.mesh, x0=x0r_1, edgeType=self.edgeType, sz=0.5*self.sz, depth=self.depth+1, node0=self.children[0].node1, node1=self.node1) - self.mesh.edges.remove(self) - if self.edgeType is 'x': - self.mesh.edgesX.remove(self) - elif self.edgeType is 'y': - self.mesh.edgesY.remove(self) - elif self.edgeType is 'z': - self.mesh.edgesZ.remove(self) - - @property - def tangent(self): - if self.edgeType is 'x': return np.r_[1.,0,0] - elif self.edgeType is 'y': return np.r_[0,1.,0] - elif self.edgeType is 'z': return np.r_[0,0,1.] - - def plotGrid(self, ax, text=False, lineOpts={'color':'r', 'ls': '-'}): - line = np.c_[self.node0.x0, self.node1.x0].T - ax.plot(line[:,0], line[:,1], zs=line[:,2], **lineOpts) - - @property - def center(self): - return 0.5*(self.node0.x0 + self.node1.x0) - - @property - def length(self): - return np.sqrt(((self.node1.x0 - self.node0.x0)**2).sum()) - - @property - def index(self): - if self.isleaf: return [self.num] - l = [edge.index for edge in self.children.flatten(order='F')] - # Flatten the list - # e.g. - # [[1,3],[4]] --> [1, 3, 4] - return [item for sublist in l for item in sublist] - -class TreeFace(object): - """docstring for TreeFace""" - - __slots__ = ['mesh', 'children', 'depth', 'num', 'faceType', 'sz', 'node0', 'node1', 'node2', 'node3', 'edge0', 'edge1', 'edge2', 'edge3', '_tangent0', '_tangent1'] - - def __init__(self, mesh, x0=[0,0], faceType=None, sz=[1,], depth=0, - node0=None, node1=None, - edge0=None, edge1=None, edge2=None, edge3=None): - - self.mesh = mesh - self.depth = depth - - self.faceType = faceType - self.sz = sz - - mesh.faces.add(self) - if faceType is 'x': mesh.facesX.add(self) - elif faceType is 'y': mesh.facesY.add(self) - elif faceType is 'z': mesh.facesZ.add(self) - if self.dim == 2: - # Add the nodes: - self.node0 = node0 if isinstance(node0,TreeNode) else TreeNode(mesh, x0=x0) - self.node1 = node1 if isinstance(node1,TreeNode) else TreeNode(mesh, x0=x0 + self.tangent0*self.sz[0]) - if self.dim == 3: - #TODO: Change this to edges - - # - # 2___________3 - # | e1 | - # | | - # e2| x |e3 t1 - # | | ^ - # |___________| |___> t0 - # 0 e0 1 - # - - N = {} - n0 = getattr(edge0, 'node0', None) or getattr(edge2, 'node0', None) - n1 = getattr(edge0, 'node1', None) or getattr(edge3, 'node0', None) - n2 = getattr(edge1, 'node0', None) or getattr(edge2, 'node1', None) - n3 = getattr(edge1, 'node1', None) or getattr(edge3, 'node1', None) - - eType = ['x', 'y'] if self.faceType == 'z' else ['x', 'z'] if self.faceType == 'y' else ['y', 'z'] - - e0 = edge0 if isinstance(edge0,TreeEdge) else TreeEdge(mesh, x0=x0, edgeType=eType[0], sz=np.r_[sz[0]], depth=depth, node0=n0, node1=n1) - n0, n1 = e0.node0, e0.node1 - - e1 = edge1 if isinstance(edge1,TreeEdge) else TreeEdge(mesh, x0=x0 + self.tangent1*self.sz[1], edgeType=eType[0], sz=np.r_[sz[0]], depth=depth, node0=n2, node1=n3) - n2, n3 = e1.node0, e1.node1 - - e2 = edge2 if isinstance(edge2,TreeEdge) else TreeEdge(mesh, x0=x0, edgeType=eType[1], sz=np.r_[sz[1]], depth=depth, node0=n0, node1=n2) - n0, n2 = e2.node0, e2.node1 - - e3 = edge3 if isinstance(edge3,TreeEdge) else TreeEdge(mesh, x0=x0 + self.tangent0*self.sz[0], edgeType=eType[1], sz=np.r_[sz[1]], depth=depth, node0=n1, node1=n3) - n1, n3 = e3.node0, e3.node1 - - # self.nodes = N - self.node0, self.node1, self.node2, self.node3 = n0, n1, n2, n3 - self.edge0, self.edge1, self.edge2, self.edge3 = e0, e1, e2, e3 - # self.edges = {'e0':e0, 'e1':e1, 'e2':e2, 'e3':e3} - - @property - def dim(self): return self.mesh.dim - - @property - def x0(self): return self.node0.x0 - - @property - def isleaf(self): return getattr(self, 'children', None) is None - - @property - def branchdepth(self): - if self.isleaf: - return self.depth - else: - return np.max([node.branchdepth for node in self.children.flatten('F')]) - - @property - def tangent0(self): - if getattr(self,'_tangent0',None) is None: - if self.faceType is 'x': t = np.r_[0,1.,0] - elif self.faceType is 'y': t = np.r_[1.,0,0] - elif self.faceType is 'z': t = np.r_[1.,0,0] - self._tangent0 = t[:self.dim] - return self._tangent0 - - @property - def tangent1(self): - if self.dim == 2: return - if getattr(self,'_tangent1',None) is None: - if self.faceType is 'x': t = np.r_[0,0,1.] - elif self.faceType is 'y': t = np.r_[0,0,1.] - elif self.faceType is 'z': t = np.r_[0,1.,0] - self._tangent1 = t - return self._tangent1 - - @property - def normal(self): - if self.faceType is 'x': n = np.r_[1.,0,0] - elif self.faceType is 'y': n = np.r_[0,1.,0] - elif self.faceType is 'z': n = np.r_[0,0,1.] - return n[:self.dim] - - @property - def index(self): - if self.isleaf: return [self.num] - l = [face.index for face in self.children.flatten(order='F')] - # Flatten the list - # e.g. - # [[1,3],[4]] --> [1, 3, 4] - return [item for sublist in l for item in sublist] - - @property - def area(self): - """area of the face""" - return self.sz.prod() - - @property - def length(self): - if self.dim == 3: raise Exception('face.length is not defined for 2D face') - return np.sqrt(((self.node1.x0 - self.node0.x0)**2).sum()) - - def refine(self): - if not self.isleaf: return - self.mesh.isNumbered = False - if self.dim == 2: - self._refine2D() - elif self.dim == 3: - self._refine3D() - - def _refine2D(self): - self.children = np.empty(2,dtype=TreeFace) - # Create refined x0's - x0r_0 = self.x0 - x0r_1 = self.x0+0.5*self.tangent0*self.sz - self.children[0] = TreeFace(self.mesh, x0=x0r_0, faceType=self.faceType, sz=0.5*self.sz, depth=self.depth+1, node0=self.node0) - self.children[1] = TreeFace(self.mesh, x0=x0r_1, faceType=self.faceType, sz=0.5*self.sz, depth=self.depth+1, node0=self.children[0].node1, node1=self.node1) - self.mesh.faces.remove(self) - if self.faceType is 'x': - self.mesh.facesX.remove(self) - elif self.faceType is 'y': - self.mesh.facesY.remove(self) - - def _refine3D(self): - # - # 2_______________3 _______________ - # | e1--> | | | | - # ^ | | ^ | (0,1) | (1,1) | - # | | | | | | | - # | | x | | ---> |-------+-------| - # e2 | | e3 | | | - # | | | (0,0) | (1,0) | - # |_______________| |_______|_______| - # 0 e0--> 1 - - - order = [{'c':[0,0], - 'e0': ('p', 'e0', [0]), 'e1': 'new' , - 'e2': ('p', 'e2', [0]), 'e3': 'new' }, - {'c':[1,0], - 'e0': ('p', 'e0', [1]), 'e1': 'new' , - 'e2': ('c', 'e3', [0,0]), 'e3': ('p', 'e3', [0])}, - {'c':[0,1], - 'e0': ('c', 'e1', [0,0]), 'e1': ('p', 'e1', [0]), - 'e2': ('p', 'e2', [1]), 'e3': 'new' }, - {'c':[1,1], - 'e0': ('c', 'e1', [1,0]), 'e1': ('p', 'e1', [1]), - 'e2': ('c', 'e3', [0,1]), 'e3': ('p', 'e3', [1])}] - - def getEdge(pointer): - if pointer is 'new': return - if pointer[0] == 'p': - return getattr(self, 'edg' + pointer[1]).children[pointer[2][0]] - if pointer[0] == 'c': - f = self.children[pointer[2][0],pointer[2][1]] - return getattr(f, 'edg' + pointer[1]) - - self.children = np.empty((2,2), dtype=TreeFace) - - for edge in [self.edge0, self.edge1, self.edge2, self.edge3]: - edge.refine() - - for O in order: - i, j = O['c'] - x0r = self.x0 + 0.5*i*self.tangent0*self.sz[0] + 0.5*j*self.tangent1*self.sz[1] - e0, e1, e2, e3 = getEdge(O['e0']), getEdge(O['e1']), getEdge(O['e2']), getEdge(O['e3']) - self.children[i,j] = TreeFace(self.mesh, x0=x0r, faceType=self.faceType, depth=self.depth+1, sz=0.5*self.sz, edge0=e0, edge1=e1, edge2=e2, edge3=e3) - - self.mesh.faces.remove(self) - if self.faceType is 'x': - self.mesh.facesX.remove(self) - elif self.faceType is 'y': - self.mesh.facesY.remove(self) - elif self.faceType is 'z': - self.mesh.facesZ.remove(self) - - def plotGrid(self, ax, text=True): - if not self.isleaf: return - if self.dim == 2: - line = np.c_[self.node0.x0, self.node1.x0].T - ax.plot(line[:,0], line[:,1],'b-') - if text: ax.text(self.center[0], self.center[1],self.num) - elif self.dim == 3: - if text: ax.text(self.center[0], self.center[1], self.center[2], self.num) - - @property - def center(self): - if self.dim == 2: - return self.x0 + 0.5*self.tangent0*self.sz[0] - elif self.dim == 3: - return self.x0 + 0.5*self.tangent0*self.sz[0] + 0.5*self.tangent1*self.sz[1] - - -class TreeCell(object): - - __slots__ = ['mesh', 'children', 'depth', 'num', 'sz', - 'node0', 'node1', 'node2', 'node3', - 'node4', 'node5', 'node6', 'node7', - 'fXm', 'fXp', 'fYm', 'fYp', 'fZm', 'fZp', - 'eX0','eX1','eX2','eX3', - 'eY0','eY1','eY2','eY3', - 'eZ0','eZ1','eZ2','eZ3'] - - def __init__(self, mesh, x0=[0,0], depth=0, sz=[1,1], - fXm=None, fXp=None, - fYm=None, fYp=None, - fZm=None, fZp=None): - - self.mesh = mesh - self.depth = depth - - self.sz = np.array(sz, dtype=float) - if self.dim == 2: - # - # 2___________3 - # | fYp | - # | | - # fXm| x |fXp y - # | | ^ - # |___________| |___> x - # 0 fYm 1 - # - n0 = getattr(fXm, 'node0', None) or getattr(fYm, 'node0', None) - n1 = getattr(fXp, 'node0', None) or getattr(fYm, 'node1', None) - n2 = getattr(fXm, 'node1', None) or getattr(fYp, 'node0', None) - n3 = getattr(fXp, 'node1', None) or getattr(fYp, 'node1', None) - - self.fXm = fXm if isinstance(fXm, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1] ], faceType='x', sz=np.r_[sz[1]], depth=depth, node0=n0, node1=n2) - n0, n2 = self.fXm.node0, self.fXm.node1 - - self.fXp = fXp if isinstance(fXp, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0]+sz[0], x0[1] ], faceType='x', sz=np.r_[sz[1]], depth=depth, node0=n1, node1=n3) - n1, n3 = self.fXp.node0, self.fXp.node1 - - self.fYm = fYm if isinstance(fYm, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1] ], faceType='y', sz=np.r_[sz[0]], depth=depth, node0=n0, node1=n1) - n0, n1 = self.fYm.node0, self.fYm.node1 - - self.fYp = fYp if isinstance(fYp, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1]+sz[1]], faceType='y', sz=np.r_[sz[0]], depth=depth, node0=n2, node1=n3) - n2, n3 = self.fYp.node0, self.fYp.node1 - - self.node0, self.node1, self.node2, self.node3 = n0, n1, n2, n3 - - elif self.dim == 3: - # fZp - # | - # 6 ------eX3------ 7 - # /| | / | - # /eZ2 . / eZ3 - # eY2 | fYp eY3 | - # / | / fXp| - # 4 ------eX2----- 5 | - # |fXm 2 -----eX1--|---- 3 z - # eZ0 / | eY1 ^ y - # | eY0 . fYm eZ1 / | / - # | / | | / | / - # 0 ------eX0------1 o----> x - # | - # fZm - # - # - # fX fY fZ - # 2___________3 2___________3 2___________3 - # | e1 | | e1 | | e1 | - # | | | | | | - # e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y - # | | ^ | | ^ | | ^ - # |___________| |___> y |___________| |___> x |___________| |___> x - # 0 e0 1 0 e0 1 0 e0 1 - # - # Mapping Nodes: numOnFace > numOnCell - # - # fXm 0>0, 1>2, 2>4, 3>6 fYm 0>0, 1>1, 2>4, 3>5 fZm 0>0, 1>1, 2>2, 3>3 - # fXp 0>1, 1>3, 2>5, 3>7 fYp 0>2, 1>3, 2>6, 3>7 fZp 0>4, 1>5, 2>6, 3>7 - - def getEdge(face, key): - if face is None: return - return getattr(face, key) - - E = {} - eX0 = getEdge(fYm, 'edge0') or getEdge(fZm, 'edge0') - eX1 = getEdge(fYp, 'edge0') or getEdge(fZm, 'edge1') - eX2 = getEdge(fYm, 'edge1') or getEdge(fZp, 'edge0') - eX3 = getEdge(fYp, 'edge1') or getEdge(fZp, 'edge1') - - eY0 = getEdge(fXm, 'edge0') or getEdge(fZm, 'edge2') - eY1 = getEdge(fXp, 'edge0') or getEdge(fZm, 'edge3') - eY2 = getEdge(fXm, 'edge1') or getEdge(fZp, 'edge2') - eY3 = getEdge(fXp, 'edge1') or getEdge(fZp, 'edge3') - - eZ0 = getEdge(fXm, 'edge2') or getEdge(fYm, 'edge2') - eZ1 = getEdge(fXp, 'edge2') or getEdge(fYm, 'edge3') - eZ2 = getEdge(fXm, 'edge3') or getEdge(fYp, 'edge2') - eZ3 = getEdge(fXp, 'edge3') or getEdge(fYp, 'edge3') - - - self.fXm = fXm if isinstance(fXm, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1] , x0[2] ], faceType='x', sz=np.r_[sz[1], sz[2]], depth=depth, edge0=eY0, edge1=eY2, edge2=eZ0, edge3=eZ2) - eY0, eY2, eZ0, eZ2 = self.fXm.edge0, self.fXm.edge1, self.fXm.edge2, self.fXm.edge3 - - self.fXp = fXp if isinstance(fXp, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0]+sz[0], x0[1] , x0[2] ], faceType='x', sz=np.r_[sz[1], sz[2]], depth=depth, edge0=eY1, edge1=eY3, edge2=eZ1, edge3=eZ3) - eY1, eY3, eZ1, eZ3 = self.fXp.edge0, self.fXp.edge1, self.fXp.edge2, self.fXp.edge3 - - self.fYm = fYm if isinstance(fYm, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1] , x0[2] ], faceType='y', sz=np.r_[sz[0], sz[2]], depth=depth, edge0=eX0, edge1=eX2, edge2=eZ0, edge3=eZ1) - eX0, eX2, eZ0, eZ1 = self.fYm.edge0, self.fYm.edge1, self.fYm.edge2, self.fYm.edge3 - - self.fYp = fYp if isinstance(fYp, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1]+sz[1], x0[2] ], faceType='y', sz=np.r_[sz[0], sz[2]], depth=depth, edge0=eX1, edge1=eX3, edge2=eZ2, edge3=eZ3) - eX1, eX3, eZ2, eZ3 = self.fYp.edge0, self.fYp.edge1, self.fYp.edge2, self.fYp.edge3 - - self.fZm = fZm if isinstance(fZm, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1] , x0[2] ], faceType='z', sz=np.r_[sz[0], sz[1]], depth=depth, edge0=eX0, edge1=eX1, edge2=eY0, edge3=eY1) - eX0, eX1, eY0, eY1 = self.fZm.edge0, self.fZm.edge1, self.fZm.edge2, self.fZm.edge3 - - self.fZp = fZp if isinstance(fZp, TreeFace) else TreeFace(mesh, x0=np.r_[x0[0] , x0[1] , x0[2]+sz[2]], faceType='z', sz=np.r_[sz[0], sz[1]], depth=depth, edge0=eX2, edge1=eX3, edge2=eY2, edge3=eY3) - eX2, eX3, eY2, eY3 = self.fZp.edge0, self.fZp.edge1, self.fZp.edge2, self.fZp.edge3 - - self.eX0, self.eX1, self.eX2, self.eX3, self.eY0, self.eY1, self.eY2, self.eY3, self.eZ0, self.eZ1, self.eZ2, self.eZ3 = eX0, eX1, eX2, eX3, eY0, eY1, eY2, eY3, eZ0, eZ1, eZ2, eZ3 - self.node0, self.node1, self.node2, self.node3, self.node4, self.node5, self.node6, self.node7 = self.fZm.node0, self.fZm.node1, self.fZm.node2, self.fZm.node3, self.fZp.node0, self.fZp.node1, self.fZp.node2, self.fZp.node3 - - mesh.cells.add(self) - - @property - def x0(self): return self.node0.x0 - - @property - def center(self): return self.x0 + 0.5*self.sz - - @property - def dim(self): return self.mesh.dim - - @property - def faceDict(self): - d = {"fXm":self.fXm, "fXp":self.fXp, "fYm":self.fYm, "fYp":self.fYp} - if self.dim == 3: - d["fZm"] = self.fZm - d["fZp"] = self.fZp - return d - - @property - def edgeDict(self): - if self.dim == 2: return None - return {'eX0': self.eX0, 'eX1': self.eX1, 'eX2': self.eX2, 'eX3': self.eX3, 'eY0': self.eY0, 'eY1': self.eY1, 'eY2': self.eY2, 'eY3': self.eY3, 'eZ0': self.eZ0, 'eZ1': self.eZ1, 'eZ2': self.eZ2, 'eZ3': self.eZ3} - - @property - def faceList(self): - l = [self.fXm, self.fXp, self.fYm, self.fYp] - if self.dim == 3: - l += [self.fZm, self.fZp] - return l - - @property - def edgeList(self): - if self.dim == 2: return None - return [self.eX0, self.eX1, self.eX2, self.eX3, self.eY0, self.eY1, self.eY2, self.eY3, self.eZ0, self.eZ1, self.eZ2, self.eZ3] - - @property - def isleaf(self): return getattr(self, 'children', None) is None - - def refine(self, function=None): - if not self.isleaf and function is None: return - - if function is not None: - do = function(self.center) > self.depth - if not do: return - - if self.dim == 2: - self._refine2D() - elif self.dim == 3: - self._refine3D() - - # pass the refine function to the children - if function is not None: - for child in self.children.flatten(): - child.refine(function) - - def _refine2D(self): - - self.mesh.isNumbered = False - - self.children = np.empty((2,2), dtype=TreeCell) - x0, sz = self.x0, self.sz - - for face in self.faceList: - face.refine() - - order = [{'c':[0,0], - 'fXm': ('p', 'fXm', [0]), 'fXp': 'new' , - 'fYm': ('p', 'fYm', [0]), 'fYp': 'new' }, - {'c':[1,0], - 'fXm': ('c', 'fXp', [0,0]), 'fXp': ('p', 'fXp', [0]), - 'fYm': ('p', 'fYm', [1]), 'fYp': 'new' }, - {'c':[0,1], - 'fXm': ('p', 'fXm', [1]), 'fXp': 'new' , - 'fYm': ('c', 'fYp', [0,0]), 'fYp': ('p', 'fYp', [0])}, - {'c':[1,1], - 'fXm': ('c', 'fXp', [0,1]), 'fXp': ('p', 'fXp', [1]), - 'fYm': ('c', 'fYp', [1,0]), 'fYp': ('p', 'fYp', [1])}] - - def getFace(pointer): - if pointer is 'new': return None - if pointer[0] == 'p': - return self.faceDict[pointer[1]].children[pointer[2][0],] - if pointer[0] == 'c': - return self.children[pointer[2][0],pointer[2][1]].faceDict[pointer[1]] - - for O in order: - i, j = O['c'] - x0r = np.r_[x0[0] + 0.5*i*sz[0], x0[1] + 0.5*j*sz[1]] - fXm, fXp, fYm, fYp = getFace(O['fXm']), getFace(O['fXp']), getFace(O['fYm']), getFace(O['fYp']) - self.children[i,j] = TreeCell(self.mesh, x0=x0r, depth=self.depth+1, sz=0.5*sz, fXm=fXm, fXp=fXp, fYm=fYm, fYp=fYp) - - self.mesh.cells.remove(self) - - - def _refine3D(self): - # .----------------.----------------. - # /| /| /| - # / | / | / | - # / | 011 / | 111 / | - # / | / | / | - # .----------------.----+-----------. | - # /| . ---------/|----.----------/|----. - # / | /| / | /| / | /| - # / | / | 001 / | / | 101 / | / | - # / | / | / | / | / | / | - # . -------------- .----------------. |/ | - # | . ---+------|----.----+------|----. | - # | /| .______|___/|____.______|___/|____. - # | / | / 010 | / | / 110| / | / - # | / | / | / | / | / | / - # . ---+---------- . ---+---------- . | / - # | |/ | |/ | |/ z - # | . ----------|----.-----------|----. ^ y - # | / 000 | / 100 | / | / - # | / | / | / | / - # | / | / | / o----> x - # . -------------- . -------------- . - # - # - # Face Refinement: - # - # 2_______________3 _______________ - # | | | | | - # ^ | | | (0,1) | (1,1) | - # | | | | | | - # | | x | ---> |-------+-------| - # t1 | | | | | - # | | | (0,0) | (1,0) | - # |_______________| |_______|_______| - # 0 t0--> 1 - - - order = [{'c':[0,0,0], - 'fXm': ('p', 'fXm', [0,0]), 'fXp': 'new' , - 'fYm': ('p', 'fYm', [0,0]), 'fYp': 'new' , - 'fZm': ('p', 'fZm', [0,0]), 'fZp': 'new' ,}, - {'c':[1,0,0], - 'fXm': ('c', 'fXp', [0,0,0]), 'fXp': ('p', 'fXp', [0,0]), - 'fYm': ('p', 'fYm', [1,0]), 'fYp': 'new' , - 'fZm': ('p', 'fZm', [1,0]), 'fZp': 'new' }, - {'c':[0,1,0], - 'fXm': ('p', 'fXm', [1,0]), 'fXp': 'new' , - 'fYm': ('c', 'fYp', [0,0,0]), 'fYp': ('p', 'fYp', [0,0]), - 'fZm': ('p', 'fZm', [0,1]), 'fZp': 'new' }, - {'c':[1,1,0], - 'fXm': ('c', 'fXp', [0,1,0]), 'fXp': ('p', 'fXp', [1,0]), - 'fYm': ('c', 'fYp', [1,0,0]), 'fYp': ('p', 'fYp', [1,0]), - 'fZm': ('p', 'fZm', [1,1]), 'fZp': 'new' }, - {'c':[0,0,1], - 'fXm': ('p', 'fXm', [0,1]), 'fXp': 'new' , - 'fYm': ('p', 'fYm', [0,1]), 'fYp': 'new' , - 'fZm': ('c', 'fZp', [0,0,0]), 'fZp': ('p', 'fZp', [0,0])}, - {'c':[1,0,1], - 'fXm': ('c', 'fXp', [0,0,1]), 'fXp': ('p', 'fXp', [0,1]), - 'fYm': ('p', 'fYm', [1,1]), 'fYp': 'new' , - 'fZm': ('c', 'fZp', [1,0,0]), 'fZp': ('p', 'fZp', [1,0])}, - {'c':[0,1,1], - 'fXm': ('p', 'fXm', [1,1]), 'fXp': 'new' , - 'fYm': ('c', 'fYp', [0,0,1]), 'fYp': ('p', 'fYp', [0,1]), - 'fZm': ('c', 'fZp', [0,1,0]), 'fZp': ('p', 'fZp', [0,1])}, - {'c':[1,1,1], - 'fXm': ('c', 'fXp', [0,1,1]), 'fXp': ('p', 'fXp', [1,1]), - 'fYm': ('c', 'fYp', [1,0,1]), 'fYp': ('p', 'fYp', [1,1]), - 'fZm': ('c', 'fZp', [1,1,0]), 'fZp': ('p', 'fZp', [1,1])}] - - self.mesh.isNumbered = False - - self.children = np.empty((2,2,2), dtype=TreeCell) - x0, sz = self.x0, self.sz - - for face in self.faceList: - face.refine() - - def getFace(pointer): - if pointer is 'new': return None - if pointer[0] == 'p': - return self.faceDict[pointer[1]].children[pointer[2][0],pointer[2][1]] - if pointer[0] == 'c': - return self.children[pointer[2][0],pointer[2][1],pointer[2][2]].faceDict[pointer[1]] - - for O in order: - i, j, k = O['c'] - x0r = np.r_[x0[0] + 0.5*i*sz[0], x0[1] + 0.5*j*sz[1], x0[2] + 0.5*k*sz[2]] - fXm, fXp, fYm, fYp, fZm, fZp = getFace(O['fXm']), getFace(O['fXp']), getFace(O['fYm']), getFace(O['fYp']), getFace(O['fZm']), getFace(O['fZp']) - self.children[i,j,k] = TreeCell(self.mesh, x0=x0r, depth=self.depth+1, sz=0.5*sz, fXm=fXm, fXp=fXp, fYm=fYm, fYp=fYp, fZm=fZm, fZp=fZp) - - self.mesh.cells.remove(self) - - @property - def faceIndex(self): - F = {} - for face in self.faces: - F[face] = self.faces[face].index - return F - - @property - def vol(self): return self.sz.prod() - - def viz(self, ax, color='none', text=False): - if not self.isleaf: return - x0, sz = self.x0, self.sz - ax.add_patch(plt.Rectangle((x0[0], x0[1]), sz[0], sz[1], facecolor=color, edgecolor='k')) - if text: ax.text(self.center[0],self.center[1],self.num) - - def plotGrid(self, ax, text=False): - if not self.isleaf: return - if self.dim == 2: - ax.plot(self.center[0],self.center[1],'ro') - if text: ax.text(self.center[0],self.center[1],self.num) - elif self.dim == 3: - ax.plot([self.center[0]],[self.center[1]],'ro', zs=[self.center[2]]) - if text: ax.text(self.center[0], self.center[1], self.center[2], self.num) - - -class TreeMesh(InnerProducts, BaseMesh): - """TreeMesh""" - - _meshType = 'TREE' - - def __init__(self, h_in, x0=None): - assert type(h_in) is list, 'h_in must be a list' - assert len(h_in) > 1, "len(h_in) must be greater than 1" - - h = range(len(h_in)) - for i, h_i in enumerate(h_in): - if type(h_i) in [int, long, float]: - # This gives you something over the unit cube. - h_i = np.ones(int(h_i))/int(h_i) - assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) - assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) - h[i] = h_i[:] # make a copy. - self.h = h - - if x0 is None: - x0 = np.zeros(self.dim) - else: - assert type(x0) in [list, np.ndarray], 'x0 must be a numpy array or a list' - x0 = np.array(x0, dtype=float) - assert len(x0) == self.dim, 'x0 must have the same dimensions as the mesh' - - # TODO: this has a lot of stuff which doesn't work for this style of mesh... - BaseMesh.__init__(self, np.array([x.size for x in h]), x0) - - # set the sets for holding the cells, nodes, faces, and edges - self.cells = set() - self.nodes = set() - self.faces = set() - self.facesX = set() - self.facesY = set() - if self.dim == 3: - self.facesZ = set() - self.edges = set() - self.edgesX = set() - self.edgesY = set() - self.edgesZ = set() - - self.children = np.empty([hi.size for hi in h],dtype=TreeCell) - - if self.dim == 2: - for i in range(h[0].size): - for j in range(h[1].size): - fXm = None if i is 0 else self.children[i-1][j].fXp - fYm = None if j is 0 else self.children[i][j-1].fYp - x0i = (np.r_[x0[0], h[0][:i]]).sum() - x0j = (np.r_[x0[1], h[1][:j]]).sum() - self.children[i][j] = TreeCell(self, x0=[x0i, x0j], depth=0, sz=[h[0][i], h[1][j]], fXm=fXm, fYm=fYm) - - elif self.dim == 3: - for i in range(h[0].size): - for j in range(h[1].size): - for k in range(h[2].size): - fXm = None if i is 0 else self.children[i-1][j][k].fXp - fYm = None if j is 0 else self.children[i][j-1][k].fYp - fZm = None if k is 0 else self.children[i][j][k-1].fZp - x0i = (np.r_[x0[0], h[0][:i]]).sum() - x0j = (np.r_[x0[1], h[1][:j]]).sum() - x0k = (np.r_[x0[2], h[2][:k]]).sum() - self.children[i][j][k] = TreeCell(self, x0=[x0i, x0j, x0k], depth=0, sz=[h[0][i], h[1][j], h[2][k]], fXm=fXm, fYm=fYm, fZm=fZm) - - isNumbered = Utils.dependentProperty('_isNumbered', False, ['_faceDiv'], 'Setting this to False will delete all operators.') - - @property - def branchdepth(self): - return np.max([node.branchdepth for node in self.children.flatten('F')]) - - def refine(self, function): - for cell in self.children.flatten(): - cell.refine(function) - - def number(self): - if self.isNumbered: return - - self.sortedCells = sorted(self.cells,key=SortByX0()) - for i, sC in enumerate(self.sortedCells): sC.num = i - - self.sortedNodes = sorted(self.nodes,key=SortByX0()) - for i, sN in enumerate(self.sortedNodes): sN.num = i - - self.sortedFaceX = sorted(self.facesX,key=SortByX0()) - for i, sFx in enumerate(self.sortedFaceX): sFx.num = i - - self.sortedFaceY = sorted(self.facesY,key=SortByX0()) - for i, sFy in enumerate(self.sortedFaceY): sFy.num = i + self.nFx - - if self.dim == 3: - self.sortedFaceZ = sorted(self.facesZ,key=SortByX0()) - for i, sFz in enumerate(self.sortedFaceZ): sFz.num = i + self.nFx + self.nFy - - self.sortedEdgeX = sorted(self.edgesX,key=SortByX0()) - for i, sEx in enumerate(self.sortedEdgeX): sEx.num = i - - self.sortedEdgeY = sorted(self.edgesY,key=SortByX0()) - for i, sEy in enumerate(self.sortedEdgeY): sEy.num = i + self.nEx - - self.sortedEdgeZ = sorted(self.edgesZ,key=SortByX0()) - for i, sEz in enumerate(self.sortedEdgeZ): sEz.num = i + self.nEx + self.nEy - - self.isNumbered = True - - @property - def dim(self): return len(self.h) - - @property - def nC(self): return len(self.cells) - - @property - def nN(self): return len(self.nodes) - - @property - def nF(self): return len(self.faces) - - @property - def nFx(self): return len(self.facesX) - - @property - def nFy(self): return len(self.facesY) - - @property - def nFz(self): return None if self.dim < 3 else len(self.facesZ) - - @property - def nE(self): - if self.dim == 2: - return len(self.faces) - elif self.dim == 3: - return len(self.edges) - - @property - def nEx(self): - if self.dim == 2: - return len(self.facesY) - elif self.dim == 3: - return len(self.edgesX) - - @property - def nEy(self): - if self.dim == 2: - return len(self.facesX) - elif self.dim == 3: - return len(self.edgesY) - - @property - def nEz(self): return None if self.dim < 3 else len(self.edgesZ) - - def _grid(self, key): - self.number() - sObjs = {'CC':self.sortedCells, - 'N':self.sortedNodes, - 'Fx': self.sortedFaceX, - 'Fy': self.sortedFaceY, - 'Fz': getattr(self,'sortedFaceZ', None), - 'Ex': getattr(self,'sortedEdgeX', self.sortedFaceY), - 'Ey': getattr(self,'sortedEdgeY', self.sortedFaceX), - 'Ez': getattr(self,'sortedEdgeZ', None)}[key] - G = np.empty((len(sObjs),self.dim)) - for ii, obj in enumerate(sObjs): - G[ii,:] = obj.center - return G - - @property - def gridCC(self): - if getattr(self, '_gridCC', None) is None: - self._gridCC = self._grid('CC') - return self._gridCC - - @property - def gridN(self): - if getattr(self, '_gridN', None) is None: - self._gridN = self._grid('N') - return self._gridN - - @property - def gridFx(self): - if getattr(self, '_gridFx', None) is None: - self._gridFx = self._grid('Fx') - return self._gridFx - - @property - def gridFy(self): - if getattr(self, '_gridFy', None) is None: - self._gridFy = self._grid('Fy') - return self._gridFy - - @property - def gridFz(self): - if self.dim == 2: return None - if getattr(self, '_gridFz', None) is None: - self._gridFz = self._grid('Fz') - return self._gridFz - - @property - def gridEx(self): - if self.dim == 2: return self.gridFy - if getattr(self, '_gridEx', None) is None: - self._gridEx = self._grid('Ex') - return self._gridEx - - @property - def gridEy(self): - if self.dim == 2: return self.gridFx - if getattr(self, '_gridEy', None) is None: - self._gridEy = self._grid('Ey') - return self._gridEy - - @property - def gridEz(self): - if self.dim == 2: return None - if getattr(self, '_gridEz', None) is None: - self._gridEz = self._grid('Ez') - return self._gridEz - - @property - def vol(self): - self.number() - return np.array([cell.vol for cell in self.sortedCells]) - - @property - def area(self): - self.number() - faces = self.sortedFaceX + self.sortedFaceY - if self.dim == 3: - faces += self.sortedFaceZ - return np.array([face.area for face in faces], dtype=float) - - @property - def edge(self): - self.number() - if self.dim == 2: - edges = self.sortedFaceY + self.sortedFaceX - elif self.dim == 3: - edges = self.sortedEdgeX + self.sortedEdgeY + self.sortedEdgeZ - return np.array([e.length for e in edges], dtype=float) - - @property - def faceDiv(self): - if getattr(self, '_faceDiv', None) is None: - self.number() - # TODO: Preallocate! - I, J, V = [], [], [] - for cell in self.sortedCells: - faces = cell.faceDict - for face in faces: - j = faces[face].index - I += [cell.num]*len(j) - J += j - V += [-1 if 'm' in face else 1]*len(j) - VOL = self.vol - D = sp.csr_matrix((V,(I,J)), shape=(self.nC, self.nF)) - S = self.area - self._faceDiv = Utils.sdiag(1/VOL)*D*Utils.sdiag(S) - return self._faceDiv - - @property - def edgeCurl(self): - """Construct the 3D curl operator.""" - assert self.dim > 2, "Edge Curl only programed for 3D." - - if getattr(self, '_edgeCurl', None) is None: - self.number() - # TODO: Preallocate! - I, J, V = [], [], [] - for face in self.faces: - for ii, edge in enumerate([face.edge0, face.edge1, face.edge2, face.edge3]): - j = edge.index - I += [face.num]*len(j) - J += j - isNeg = [True, False, True, False] - V += [-1 if isNeg[ii] else 1]*len(j) - C = sp.csr_matrix((V,(I,J)), shape=(self.nF, self.nE)) - S = self.area - L = self.edge - self._edgeCurl = Utils.sdiag(1/S)*C*Utils.sdiag(L) - return self._edgeCurl - - @property - def nodalGrad(self): - if getattr(self, '_nodalGrad', None) is None: - self.number() - # TODO: Preallocate! - I, J, V = [], [], [] - # kinda a hack for the 2D gradient - # because edges are not stored - edges = self.faces if self.dim == 2 else self.edges - for edge in edges: - if self.dim == 3: - I += [edge.num, edge.num] - elif self.dim == 2 and edge.faceType == 'x': - I += [edge.num + self.nFy, edge.num + self.nFy] - elif self.dim == 2 and edge.faceType == 'y': - I += [edge.num - self.nFx, edge.num - self.nFx] - J += [edge.node0.num, edge.node1.num] - V += [-1, 1] - G = sp.csr_matrix((V,(I,J)), shape=(self.nE, self.nN)) - L = self.edge - self._nodalGrad = Utils.sdiag(1/L)*G - return self._nodalGrad - - def _getFaceP(self, face0, face1, face2): - I, J, V = [], [], [] - for cell in self.sortedCells: - face = cell.faceDict[face0] - if face.isleaf: - j = face.index - elif self.dim == 2: - j = face.children[0 if 'm' in face1 else 1].index - elif self.dim == 3: - j = face.children[0 if 'm' in face1 else 1, - 0 if 'm' in face2 else 1].index - lenj = len(j) - I += [cell.num]*lenj - J += j - V += [1./lenj]*lenj - return sp.csr_matrix((V,(I,J)), shape=(self.nC, self.nF)) - - def _getEdgeP(self, edge0, edge1, edge2): - I, J, V = [], [], [] - for cell in self.sortedCells: - if self.dim == 2: - e2f = lambda e: ('f' + {'X':'Y','Y':'X'}[e[1]] - + {'0':'m','1':'p'}[e[2]]) - face = cell.faceDict[e2f(edge0)] - if face.isleaf: - j = face.index - else: - j = face.children[0 if 'm' in e2f(edge1) else 1].index - # Need to flip the numbering for edges - if 'X' in edge0: - j = [jj - self.nFx for jj in j] - elif 'Y' in edge0: - j = [jj + self.nFy for jj in j] - elif self.dim == 3: - edge = cell.edgeDict[edge0] - if edge.isleaf: - j = edge.index - else: - mSide = lambda e: {'0':True,'1':True,'2':False,'3':False}[e[2]] - j = edge.children[0 if mSide(edge1) else 1, - 0 if mSide(edge2) else 1].index - lenj = len(j) - I += [cell.num]*lenj - J += j - V += [1./lenj]*lenj - return sp.csr_matrix((V,(I,J)), shape=(self.nC, self.nE)) - - def _getFacePxx(self): - def Pxx(xFace, yFace): - self.number() - xP = self._getFaceP(xFace, yFace, None) - yP = self._getFaceP(yFace, xFace, None) - return sp.vstack((xP, yP)) - return Pxx - - def _getEdgePxx(self): - def Pxx(xEdge, yEdge): - self.number() - xP = self._getEdgeP(xEdge, yEdge, None) - yP = self._getEdgeP(yEdge, xEdge, None) - return sp.vstack((xP, yP)) - return Pxx - - def _getFacePxxx(self): - def Pxxx(xFace, yFace, zFace): - self.number() - xP = self._getFaceP(xFace, yFace, zFace) - yP = self._getFaceP(yFace, xFace, zFace) - zP = self._getFaceP(zFace, xFace, yFace) - return sp.vstack((xP, yP, zP)) - return Pxxx - - def _getEdgePxxx(self): - def Pxxx(xEdge, yEdge, zEdge): - self.number() - xP = self._getEdgeP(xEdge, yEdge, zEdge) - yP = self._getEdgeP(yEdge, xEdge, zEdge) - zP = self._getEdgeP(zEdge, xEdge, yEdge) - return sp.vstack((xP, yP, zP)) - return Pxxx - - def plotGrid(self, ax=None, text=False, centers=False, faces=False, edges=False, lines=True, nodes=False, showIt=False): - self.number() - - axOpts = {'projection':'3d'} if self.dim == 3 else {} - if ax is None: ax = plt.subplot(111, **axOpts) - - if lines: - [f.plotGrid(ax, text=text) for f in self.faces] - if centers: - [c.plotGrid(ax, text=text) for c in self.cells] - if faces: - fX = np.array([f.center for f in self.sortedFaceX]) - ax.plot(fX[:,0],fX[:,1],'g>') - fY = np.array([f.center for f in self.sortedFaceY]) - ax.plot(fY[:,0],fY[:,1],'g^') - if edges: - eX = np.array([e.center for e in self.sortedFaceY]) - ax.plot(eX[:,0],eX[:,1],'c>') - eY = np.array([e.center for e in self.sortedFaceX]) - ax.plot(eY[:,0],eY[:,1],'c^') - if nodes: - ns = np.array([n.x0 for n in self.sortedNodes]) - ax.plot(ns[:,0],ns[:,1],'bs') - - ax.set_xlim((self.x0[0], self.h[0].sum())) - ax.set_ylim((self.x0[1], self.h[1].sum())) - if self.dim == 3: - ax.set_zlim((self.x0[2], self.h[2].sum())) - ax.grid(True) - ax.hold(False) - ax.set_xlabel('x1') - ax.set_ylabel('x2') - if showIt: plt.show() - - def plotImage(self, I, ax=None, showIt=True): - if self.dim == 2: - self._plotImage2D(I, ax=ax, showIt=showIt) - elif self.dim == 3: - raise NotImplementedError('3D visualization is not yet implemented.') - - def _plotImage2D(self, I, ax=None, showIt=True): - if ax is None: ax = plt.subplot(111) - jet = cm = plt.get_cmap('jet') - cNorm = colors.Normalize(vmin=I.min(), vmax=I.max()) - scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) - ax.set_xlim((self.x0[0], self.h[0].sum())) - ax.set_ylim((self.x0[1], self.h[1].sum())) - for ii, node in enumerate(self.sortedCells): - node.viz(ax=ax, color=scalarMap.to_rgba(I[ii])) - scalarMap._A = [] # http://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots - plt.colorbar(scalarMap) - if showIt: plt.show() + return sorted(range(offset,grid.shape[0]+offset), key=K) +class NotBalancedException(Exception): + pass if __name__ == '__main__': - M = TreeMesh([np.ones(x) for x in [4,10]]) + def function(xc): - r = xc - np.r_[2.,6.] + r = xc - np.array([0.5*128]*len(xc)) dist = np.sqrt(r.dot(r)) - if dist < 1.0: + # if dist < 0.05: + # return 5 + if dist < 0.1*128: + return 4 + if dist < 0.3*128: return 3 - if dist < 1.5: + if dist < 1.0*128: return 2 else: - return 1 + return 0 - M.refine(function) + # T = Tree([[(1,128)],[(1,128)],[(1,128)]],levels=7) + # T = Tree([128,128,128],levels=7) + T = Tree([[(1,16)],[(1,16)]],levels=4) + # T = Tree([[(1,128)],[(1,128)]],levels=7) + # T.refine(lambda xc:1, balance=False) + # T._index([0,0,0]) + # T._pointer(0) - DIV = M.faceDiv - Mf = M.getFaceInnerProduct() - # plt.subplot(211) - # plt.spy(DIV) - M.plotGrid(ax=plt.subplot(111),text=True,showIt=True) - q = np.zeros(M.nC) - q[208] = -1.0 - q[291] = 1.0 - b = Solver(-DIV*Mf*DIV.T) * (q) - plt.figure() - M.plotImage(b) - # plt.gca().invert_yaxis() - print M.vol + tic = time.time() + T.refine(function)#, balance=False) + print time.time() - tic + print T.nC + + T.plotImage(np.random.rand(T.nC),showIt=True) + + print T.getFaceInnerProduct() + # print T.gridFz + + + # T._refineCell([8,0,1]) + # T._refineCell([8,0,2]) + # T._refineCell([12,0,2]) + # T._refineCell([8,4,2]) + # T._refineCell([6,0,3]) + # T._refineCell([8,8,1]) + # T._refineCell([0,0,0,1]) + # T.__dirty__ = True + + + print T.gridFx.shape[0], T.nFx + + + + ax = plt.subplot(211) + ax.spy(T.edgeCurl) + + # print Mesh.TensorMesh([2,2,2]).edgeCurl.todense() + # print T.edgeCurl.todense() + # print Mesh.TensorMesh([2,2,2]).edgeCurl.todense() - T.edgeCurl.todense() + # print T.gridEy - Mesh.TensorMesh([2,2,2]).gridEy + + # print T.edge + # T.plotGrid(ax=ax) + + # R = deflationMatrix(T._facesX, T._hangingFx, T._fx2i) + # print R + + ax = plt.subplot(212)#, projection='3d') + ax.spy(Mesh.TensorMesh([2,2,2]).edgeCurl) + + # ax = plt.subplot(313) + # ax.spy(T.faceDiv[:,:T.nFx] * R) + + + # T.balance() + # T.plotGrid(ax=ax) + + # cx = T._getNextCell([0,0,1],direction=0,positive=True) + # print cx + # # print [T._asPointer(_) for _ in cx] + # cx = T._getNextCell([8,0,3],direction=0,positive=False) + # print T._asPointer(cx) + # cx = T._getNextCell([8,8,1],direction=1,positive=False) + # print cx, #[T._asPointer(_) for _ in cx] + # cm = T._getNextCell([64,80,4],direction=0,positive=False) + # cy = T._getNextCell([64,80,4],direction=1,positive=True) + # cp = T._getNextCell([64,80,4],direction=1,positive=False) + + # ax.plot( T._cellN([4,0,1])[0],T._cellN([4,0,1])[1], 'yd') + # ax.plot( T._cellN(cx)[0],T._cellN(cx)[1], 'ys') + # ax.plot( T._cellN(cm)[0],T._cellN(cm)[1], 'ys') + # ax.plot( T._cellN(cy)[0],T._cellN(cy)[1], 'ys') + # ax.plot( T._cellN(cp[0])[0],T._cellN(cp[0])[1], 'ys') + # ax.plot( T._cellN(cp[1])[0],T._cellN(cp[1])[1], 'ys') + + + + + + # print T.nN + plt.show() + diff --git a/tests/mesh/test_NewTreeMesh.py b/tests/mesh/test_NewTreeMesh.py deleted file mode 100644 index 6dcffb86..00000000 --- a/tests/mesh/test_NewTreeMesh.py +++ /dev/null @@ -1,367 +0,0 @@ -from SimPEG.Mesh import TensorMesh -from SimPEG.Mesh.NewTreeMesh import TreeMesh, TreeCell -import numpy as np -import unittest -import matplotlib.pyplot as plt - -TOL = 1e-10 - -class TestQuadTreeMesh(unittest.TestCase): - - def setUp(self): - M = TreeMesh([np.ones(x) for x in [3,2]]) - M.refineFace(0) - self.M = M - M.number() - # M.plotGrid(showIt=True) - - def test_numbering(self): - M = TreeMesh([2,2,2]) - M.number() - M.refineCell(0) - M.refineCell(3) - assert M.isNumbered is False - - def test_MeshSizes(self): - self.assertTrue(self.M.nC==9) - self.assertTrue(self.M.nF==25) - self.assertTrue(self.M.nFx==12) - self.assertTrue(self.M.nFy==13) - self.assertTrue(self.M.nE==25) - self.assertTrue(self.M.nEx==13) - self.assertTrue(self.M.nEy==12) - - def test_gridCC(self): - x = np.r_[0.25,0.75,1.5,2.5,0.25,0.75,0.5,1.5,2.5] - y = np.r_[0.25,0.25,0.5,0.5,0.75,0.75,1.5,1.5,1.5] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridCC).flatten()) == 0) - - def test_gridN(self): - x = np.r_[0,0.5,1,2,3,0,0.5,1,0,0.5,1,2,3,0,1,2,3] - y = np.r_[0,0,0,0,0,.5,.5,.5,1,1,1,1,1,2,2,2,2] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridN).flatten()) == 0) - - def test_gridFx(self): - x = np.r_[0.0,0.5,1.0,2.0,3.0,0.0,0.5,1.0,0.0,1.0,2.0,3.0] - y = np.r_[0.25,0.25,0.25,0.5,0.5,0.75,0.75,0.75,1.5,1.5,1.5,1.5] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridFx).flatten()) == 0) - - def test_gridFy(self): - x = np.r_[0.25,0.75,1.5,2.5,0.25,0.75,0.25,0.75,1.5,2.5,0.5,1.5,2.5] - y = np.r_[0,0,0,0,0.5,0.5,1,1,1,1,2,2,2] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridFy).flatten()) == 0) - - def test_gridEx(self): - x = np.r_[0.25,0.75,1.5,2.5,0.25,0.75,0.25,0.75,1.5,2.5,0.5,1.5,2.5] - y = np.r_[0,0,0,0,0.5,0.5,1,1,1,1,2,2,2] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridEx).flatten()) == 0) - - def test_gridEy(self): - x = np.r_[0.0,0.5,1.0,2.0,3.0,0.0,0.5,1.0,0.0,1.0,2.0,3.0] - y = np.r_[0.25,0.25,0.25,0.5,0.5,0.75,0.75,0.75,1.5,1.5,1.5,1.5] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridEy).flatten()) == 0) - - def test_vol(self): - v = np.r_[0.25,0.25,1,1,0.25,0.25,1,1,1] - self.assertTrue(np.linalg.norm((v-self.M.vol)) < TOL) - - def test_edge(self): - ex = np.r_[0.5,0.5,1,1,0.5,0.5,0.5,0.5,1,1,1,1,1] - ey = np.r_[0.5,0.5,0.5,1,1,0.5,0.5,0.5,1,1,1,1] - self.assertTrue(np.linalg.norm((np.r_[ex,ey]-self.M.edge)) < TOL) - - def test_area(self): - ax = np.r_[0.5,0.5,0.5,1,1,0.5,0.5,0.5,1,1,1,1] - ay = np.r_[0.5,0.5,1,1,0.5,0.5,0.5,0.5,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.r_[ax,ay]-self.M.area)) < TOL) - -class TestOcTreeConnectivity(unittest.TestCase): - - def setUp(self): - self.oM = TreeMesh([1,1,1]) - self.oM.refine(lambda c: 1) - - def test_setup(self): - C = TreeCell(self.oM, 0) - children = C.children - assert not C.isleaf - assert len(children.index) == 8 - # assert not TreeCell(self.oM, 0).isleaf - c0, c1, c2, c3, c4, c5, c6, c7 = [TreeCell(self.oM, i) for i in range(1,9)] - - - # .----------------.----------------. - # /| /| /| - # / | / | / | - # / | c6 / | c7 / | - # / | / | / | - # .----------------.----+-----------. | - # /| . ---------/|----.----------/|----. - # fZp / | /| / | /| / | /| - # | / | / | c4 / | / | c5 / | X | - # 6 ------eX3------ 7 / | / | / | / | / | / | - # /| | / | . -------------- .----------------. |/ | - # /eZ2 . / eZ3 | . ---+------|----.----+------|----. | - # eY2 | fYp eY3 | | /| .______|___/|____.______|___/|____. - # / | / fXp| | / | / c2 | / | / c3 | / | / - # 4 ------eX2----- 5 | | / | / | / | / | / | / - # |fXm 2 -----eX1--|---- 3 z . ---+---------- . ---+---------- . | / - # eZ0 / | eY1 ^ y | |/ | |/ | |/ - # | eY0 . fYm eZ1 / | / | . ----------|----.-----------|----. - # | / | | / | / | / c0 | / c1 | / - # 0 ------eX0------1 o----> x | / | / | / - # | | / | / | / - # fZm . -------------- . -------------- . - # - # - # fX fY fZ - # 2___________3 2___________3 2___________3 - # | e1 | | e1 | | e1 | - # | | | | | | - # e2 | x | e3 z e2 | x | e3 z e2 | x | e3 y - # | | ^ | | ^ | | ^ - # |___________| |___> y |___________| |___> x |___________| |___> x - # 0 e0 1 0 e0 1 0 e0 1 - # - - - # there are two faces for each edge - for ii, c in enumerate([c0, c1, c2, c3, c4, c5, c6, c7]): - assert c.fZm.e0.index == c.fYm.e0.index, "Cell %d: fZm.e0 and fYm.e0"%ii - assert c.fZm.e1.index == c.fYp.e0.index, "Cell %d: fZm.e1 and fYp.e0"%ii - assert c.fZp.e0.index == c.fYm.e1.index, "Cell %d: fZp.e0 and fYm.e1"%ii - assert c.fZp.e1.index == c.fYp.e1.index, "Cell %d: fZp.e1 and fYp.e1"%ii - assert c.fZm.e2.index == c.fXm.e0.index, "Cell %d: fZm.e2 and fXm.e0"%ii - assert c.fZm.e3.index == c.fXp.e0.index, "Cell %d: fZm.e3 and fXp.e0"%ii - assert c.fZp.e2.index == c.fXm.e1.index, "Cell %d: fZp.e2 and fXm.e1"%ii - assert c.fZp.e3.index == c.fXp.e1.index, "Cell %d: fZp.e3 and fXp.e1"%ii - assert c.fYm.e2.index == c.fXm.e2.index, "Cell %d: fYm.e2 and fXm.e2"%ii - assert c.fYm.e3.index == c.fXp.e2.index, "Cell %d: fYm.e3 and fXp.e2"%ii - assert c.fYp.e2.index == c.fXm.e3.index, "Cell %d: fYp.e2 and fXm.e3"%ii - assert c.fYp.e3.index == c.fXp.e3.index, "Cell %d: fYp.e3 and fXp.e3"%ii - - assert c0.eZ1.index == c1.eZ0.index - assert c0.eZ3.index == c1.eZ2.index - assert c2.eZ1.index == c3.eZ0.index - assert c2.eZ3.index == c3.eZ2.index - - assert c4.eZ1.index == c5.eZ0.index - assert c4.eZ3.index == c5.eZ2.index - assert c6.eZ1.index == c7.eZ0.index - assert c6.eZ3.index == c7.eZ2.index - - assert c0.n7.index == c7.n0.index - - - - - -class SimpleOctreeOperatorTests(unittest.TestCase): - - def setUp(self): - h1 = np.random.rand(5) - h2 = np.random.rand(7) - h3 = np.random.rand(3) - self.tM = TensorMesh([h1,h2,h3]) - self.oM = TreeMesh([h1,h2,h3]) - self.tM2 = TensorMesh([h1,h2]) - self.oM2 = TreeMesh([h1,h2]) - # self.oM2.plotGrid(showIt=True) - - def test_faceDiv(self): - self.assertAlmostEqual((self.tM.faceDiv - self.oM.faceDiv).toarray().sum(), 0) - self.assertAlmostEqual((self.tM2.faceDiv - self.oM2.faceDiv).toarray().sum(), 0) - - def test_nodalGrad(self): - self.assertAlmostEqual((self.tM.nodalGrad - self.oM.nodalGrad).toarray().sum(), 0) - self.assertAlmostEqual((self.tM2.nodalGrad - self.oM2.nodalGrad).toarray().sum(), 0) - - def test_edgeCurl(self): - self.assertAlmostEqual((self.tM.edgeCurl - self.oM.edgeCurl).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.edgeCurl - self.oM2.edgeCurl).toarray().sum(), 0) - - def test_InnerProducts(self): - self.assertAlmostEqual((self.tM.getFaceInnerProduct() - self.oM.getFaceInnerProduct()).toarray().sum(), 0) - self.assertAlmostEqual((self.tM.getEdgeInnerProduct() - self.oM.getEdgeInnerProduct()).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.getFaceInnerProduct() - self.oM2.getFaceInnerProduct()).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.getEdgeInnerProduct() - self.oM2.getEdgeInnerProduct()).toarray().sum(), 0) - - -class SimpleOctreeOperatorTestsRefined(unittest.TestCase): - def setUp(self): - self.tM = TreeMesh([1,1,1]) - self.tM.refine(lambda c:2) - self.M = TensorMesh([4,4,4]) - - self.tM2 = TreeMesh([1,1]) - self.tM2.refine(lambda c:2) - self.M2 = TensorMesh([4,4]) - - def test_grids(self): - self.assertAlmostEqual((self.tM2.gridN - self.M2.gridN).sum(), 0) - self.assertAlmostEqual((self.tM2.gridCC - self.M2.gridCC).sum(), 0) - self.assertAlmostEqual((self.tM2.gridFx - self.M2.gridFx).sum(), 0) - self.assertAlmostEqual((self.tM2.gridFy - self.M2.gridFy).sum(), 0) - self.assertAlmostEqual((self.tM2.gridEx - self.M2.gridEx).sum(), 0) - self.assertAlmostEqual((self.tM2.gridEy - self.M2.gridEy).sum(), 0) - - self.assertAlmostEqual((self.tM.gridN - self.M.gridN).sum(), 0) - self.assertAlmostEqual((self.tM.gridCC - self.M.gridCC).sum(), 0) - self.assertAlmostEqual((self.tM.gridFx - self.M.gridFx).sum(), 0) - self.assertAlmostEqual((self.tM.gridFy - self.M.gridFy).sum(), 0) - self.assertAlmostEqual((self.tM.gridFz - self.M.gridFz).sum(), 0) - self.assertAlmostEqual((self.tM.gridEx - self.M.gridEx).sum(), 0) - self.assertAlmostEqual((self.tM.gridEy - self.M.gridEy).sum(), 0) - self.assertAlmostEqual((self.tM.gridEz - self.M.gridEz).sum(), 0) - - def test_InnerProducts(self): - self.assertAlmostEqual((self.tM.getFaceInnerProduct() - self.M.getFaceInnerProduct()).toarray().sum(), 0) - self.assertAlmostEqual((self.tM.getEdgeInnerProduct() - self.M.getEdgeInnerProduct()).toarray().sum(), 0) - - # self.assertAlmostEqual((self.tM2.getFaceInnerProduct() - self.M2.getFaceInnerProduct()).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.getEdgeInnerProduct() - self.M2.getEdgeInnerProduct()).toarray().sum(), 0) - - def test_faceDiv(self): - self.assertAlmostEqual((self.tM2.faceDiv - self.M2.faceDiv).toarray().sum(), 0) - self.assertAlmostEqual((self.tM.faceDiv - self.M.faceDiv).toarray().sum(), 0) - - def test_nodalGrad(self): - self.assertAlmostEqual((self.tM2.nodalGrad - self.M2.nodalGrad).toarray().sum(), 0) - self.assertAlmostEqual((self.tM.nodalGrad - self.M.nodalGrad).toarray().sum(), 0) - - def test_edgeCurl(self): - self.assertAlmostEqual((self.tM.edgeCurl - self.M.edgeCurl).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.edgeCurl - self.M2.edgeCurl).toarray().sum(), 0) - - def test_InnerProducts(self): - self.assertAlmostEqual((self.tM.getFaceInnerProduct() - self.M.getFaceInnerProduct()).toarray().sum(), 0) - self.assertAlmostEqual((self.tM.getEdgeInnerProduct() - self.M.getEdgeInnerProduct()).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.getFaceInnerProduct() - self.M2.getFaceInnerProduct()).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.getEdgeInnerProduct() - self.M2.getEdgeInnerProduct()).toarray().sum(), 0) - - -class TestOcTreeObjects(unittest.TestCase): - - def setUp(self): - self.M = TreeMesh([2,1,1]) - self.M.number() - - self.Mr = TreeMesh([2,1,1]) - self.Mr.refineCell(0) - self.Mr.number() - - def test_counts(self): - self.assertTrue(self.M.nC == 2) - self.assertTrue(self.M.nFx == 3) - self.assertTrue(self.M.nFy == 4) - self.assertTrue(self.M.nFz == 4) - self.assertTrue(self.M.nF == 11) - self.assertTrue(self.M.nEx == 8) - self.assertTrue(self.M.nEy == 6) - self.assertTrue(self.M.nEz == 6) - self.assertTrue(self.M.nE == 20) - self.assertTrue(self.M.nN == 12) - - self.assertTrue(self.Mr.nC == 9) - self.assertTrue(self.Mr.nFx == 13) - self.assertTrue(self.Mr.nFy == 14) - self.assertTrue(self.Mr.nFz == 14) - self.assertTrue(self.Mr.nF == 41) - - self.assertTrue(self.Mr.nN == 31) - self.assertTrue(self.Mr.nEx == 22) - self.assertTrue(self.Mr.nEy == 20) - self.assertTrue(self.Mr.nEz == 20) - - - def test_gridCC(self): - x = np.r_[0.25,0.75] - y = np.r_[0.5,0.5] - z = np.r_[0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridCC).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375] - y = np.r_[0.25,0.25,0.5,0.75,0.75,0.25,0.25,0.75,0.75] - z = np.r_[0.25,0.25,0.5,0.25,0.25,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridCC).flatten()) == 0) - - def test_gridN(self): - x = np.r_[0,0.5,1,0,0.5,1,0,0.5,1,0,0.5,1] - y = np.r_[0,0,0,1,1,1,0,0,0,1,1,1.] - z = np.r_[0,0,0,0,0,0,1,1,1,1,1,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridN).flatten()) == 0) - - x = np.r_[0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,1] - y = np.r_[0,0,0,0,0.5,0.5,0.5,1,1,1,1,0,0,0,0.5,0.5,0.5,1,1,1,0,0,0,0,0.5,0.5,0.5,1,1,1,1] - z = np.r_[0,0,0,0,0,0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1,1,1,1,1,1,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridN).flatten()) == 0) - - def test_gridFx(self): - x = np.r_[0.0,0.5,1.0] - y = np.r_[0.5,0.5,0.5] - z = np.r_[0.5,0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridFx).flatten()) == 0) - - x = np.r_[0.0,0.25,0.5,1.0,0.0,0.25,0.5,0.0,0.25,0.5,0.0,0.25,0.5] - y = np.r_[0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.25,0.25,0.25,0.75,0.75,0.75] - z = np.r_[0.25,0.25,0.25,0.5,0.25,0.25,0.25,0.75,0.75,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridFx).flatten()) == 0) - - def test_gridFy(self): - x = np.r_[0.25,0.75,0.25,0.75] - y = np.r_[0,0,1.,1.] - z = np.r_[0.5,0.5,0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridFy).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375] - y = np.r_[0,0,0,0.5,0.5,1,1,1,0,0,0.5,0.5,1,1] - z = np.r_[0.25,0.25,0.5,0.25,0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridFy).flatten()) == 0) - - def test_gridFz(self): - x = np.r_[0.25,0.75,0.25,0.75] - y = np.r_[0.5,0.5,0.5,0.5] - z = np.r_[0,0,1.,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridFz).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375,0.125,0.375,0.75,0.125,0.375] - y = np.r_[0.25,0.25,0.5,0.75,0.75,0.25,0.25,0.75,0.75,0.25,0.25,0.5,0.75,0.75] - z = np.r_[0,0,0,0,0,0.5,0.5,0.5,0.5,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridFz).flatten()) == 0) - - - def test_gridEx(self): - x = np.r_[0.25,0.75,0.25,0.75,0.25,0.75,0.25,0.75] - y = np.r_[0,0,1.,1.,0,0,1.,1.] - z = np.r_[0,0,0,0,1.,1.,1.,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridEx).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375,0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.75] - y = np.r_[0,0,0,0.5,0.5,1,1,1,0,0,0.5,0.5,1,1,0,0,0,0.5,0.5,1,1,1] - z = np.r_[0,0,0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,1,1,1,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridEx).flatten()) == 0) - - def test_gridEy(self): - x = np.r_[0,0.5,1,0,0.5,1] - y = np.r_[0.5,0.5,0.5,0.5,0.5,0.5] - z = np.r_[0,0,0,1.,1.,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridEy).flatten()) == 0) - - x = np.r_[0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5] - y = np.r_[0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.25,0.25,0.25,0.75,0.75,0.75,0.25,0.25,0.25,0.5,0.75,0.75,0.75] - z = np.r_[0,0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,1,1,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridEy).flatten()) == 0) - - def test_gridEz(self): - x = np.r_[0,0.5,1,0,0.5,1] - y = np.r_[0,0,0,1.,1.,1.] - z = np.r_[0.5,0.5,0.5,0.5,0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridEz).flatten()) == 0) - - x = np.r_[0,0.25,0.5,1,0 ,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5,0 ,0.25,0.5,0 ,0.25,0.5] - y = np.r_[0,0 ,0 ,0,0.5,0.5 ,0.5,1,1 ,1 ,1,0,0 ,0 ,0.5,0.5 ,0.5,1 ,1 ,1 ] - z = np.r_[0.25,0.25,0.25,0.5,0.25,0.25,0.25,0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridEz).flatten()) == 0) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/mesh/test_TreeMesh.py b/tests/mesh/test_TreeMesh.py index 977392cb..82288f99 100644 --- a/tests/mesh/test_TreeMesh.py +++ b/tests/mesh/test_TreeMesh.py @@ -1,504 +1,158 @@ -from SimPEG.Mesh import TensorMesh -from SimPEG.Mesh.TreeMesh import TreeMesh, TreeFace, TreeCell +from SimPEG import Mesh import numpy as np -import unittest import matplotlib.pyplot as plt +import unittest TOL = 1e-10 -class TestOcTreeObjects(unittest.TestCase): - def setUp(self): - self.M = TreeMesh([2,1,1]) - self.M.number() - self.Mr = TreeMesh([2,1,1]) - self.Mr.children[0,0,0].refine() - self.Mr.number() - - def q(s): - if s[0] == 'M': - m = self.M - s = s[1:] - else: - m = self.Mr - c = m.sortedCells[int(s[1])] - if len(s) == 2: return c - if s[2] == 'f' and len(s) == 5: return c.faceDict[s[2:]] - if s[2] == 'f': return getattr(c.faceDict[s[2:5]], 'edg' +s[5:]) - if s[2] == 'e': return getattr(c,s[2:]) - if s[2] == 'n': return getattr(c,'node'+s[3:]) - - self.q = q +class TestSimpleQuadTree(unittest.TestCase): def test_counts(self): - self.assertTrue(self.M.nC == 2) - self.assertTrue(self.M.nFx == 3) - self.assertTrue(self.M.nFy == 4) - self.assertTrue(self.M.nFz == 4) - self.assertTrue(self.M.nF == 11) - self.assertTrue(self.M.nEx == 8) - self.assertTrue(self.M.nEy == 6) - self.assertTrue(self.M.nEz == 6) - self.assertTrue(self.M.nE == 20) - self.assertTrue(self.M.nN == 12) - - self.assertTrue(self.Mr.nC == 9) - self.assertTrue(self.Mr.nFx == 13) - self.assertTrue(self.Mr.nFy == 14) - self.assertTrue(self.Mr.nFz == 14) - self.assertTrue(self.Mr.nF == 41) - - - for cell in self.Mr.sortedCells: - for e in cell.edgeDict: - self.assertTrue(cell.edgeDict[e].edgeType==e[1].lower()) - - self.assertTrue(self.Mr.nN == 31) - self.assertTrue(self.Mr.nEx == 22) - self.assertTrue(self.Mr.nEy == 20) - self.assertTrue(self.Mr.nEz == 20) - - def test_sizes(self): - q = self.q - - for key in ['Mc0','Mc1']: - self.assertTrue(q(key).vol == 0.5) - self.assertTrue(q(key+'fXm').area == 1.) - self.assertTrue(q(key+'fXp').area == 1.) - self.assertTrue(q(key+'fYm').area == 0.5) - self.assertTrue(q(key+'fYp').area == 0.5) - self.assertTrue(q(key+'fZm').area == 0.5) - self.assertTrue(q(key+'fZp').area == 0.5) - - def test_pointersM(self): - q = self.q - - self.assertTrue(q('Mc0fXp') is q('Mc1fXm')) - self.assertTrue(q('Mc0fXpe0') is q('Mc1fXme0')) - self.assertTrue(q('Mc0fXpe1') is q('Mc1fXme1')) - self.assertTrue(q('Mc0fXpe2') is q('Mc1fXme2')) - self.assertTrue(q('Mc0fXpe3') is q('Mc1fXme3')) - self.assertTrue(q('Mc0fYp') is not q('c1fYm')) - self.assertTrue(q('Mc0fXm') is not q('c1fXm')) - - # Test connectivity of shared edges - self.assertTrue(q('Mc0fZpe3') is not q('c1fZpe0')) - self.assertTrue(q('Mc0fZpe3') is not q('c1fZpe1')) - self.assertTrue(q('Mc0fZpe3') is q('Mc1fZpe2')) - self.assertTrue(q('Mc0fZpe3') is not q('c1fZpe3')) - - self.assertTrue(q('Mc0fZme3') is not q('c1fZme0')) - self.assertTrue(q('Mc0fZme3') is not q('c1fZme1')) - self.assertTrue(q('Mc0fZme3') is q('Mc1fZme2')) - self.assertTrue(q('Mc0fZme3') is not q('c1fZme3')) - - self.assertTrue(q('Mc0fYpe3') is not q('c1fYpe0')) - self.assertTrue(q('Mc0fYpe3') is not q('c1fYpe1')) - self.assertTrue(q('Mc0fYpe3') is q('Mc1fYpe2')) - self.assertTrue(q('Mc0fYpe3') is not q('c1fYpe3')) - - self.assertTrue(q('Mc0fYme3') is not q('c1fYme0')) - self.assertTrue(q('Mc0fYme3') is not q('c1fYme1')) - self.assertTrue(q('Mc0fYme3') is q('Mc1fYme2')) - self.assertTrue(q('Mc0fYme3') is not q('c1fYme3')) - - self.assertTrue(q('Mc0fZme3') is q('Mc1fXme0')) - self.assertTrue(q('Mc0fZpe3') is q('Mc1fXme1')) - self.assertTrue(q('Mc0fYme3') is q('Mc1fXme2')) - self.assertTrue(q('Mc0fYpe3') is q('Mc1fXme3')) - - self.assertTrue(q('Mc0fZme3') is q('Mc0fXpe0')) - self.assertTrue(q('Mc0fZpe3') is q('Mc0fXpe1')) - self.assertTrue(q('Mc0fYme3') is q('Mc0fXpe2')) - self.assertTrue(q('Mc0fYpe3') is q('Mc0fXpe3')) - - self.assertTrue(q('Mc1fZme2') is q('Mc1fXme0')) - self.assertTrue(q('Mc1fZpe2') is q('Mc1fXme1')) - self.assertTrue(q('Mc1fYme2') is q('Mc1fXme2')) - self.assertTrue(q('Mc1fYpe2') is q('Mc1fXme3')) - - self.assertTrue(q('Mc1fZme2') is q('Mc0fXpe0')) - self.assertTrue(q('Mc1fZpe2') is q('Mc0fXpe1')) - self.assertTrue(q('Mc1fYme2') is q('Mc0fXpe2')) - self.assertTrue(q('Mc1fYpe2') is q('Mc0fXpe3')) - - - def test_nodePointers(self): - q = self.q - c0 = self.Mr.sortedCells[0] - c0n0 = c0.node0 - self.assertTrue(c0n0 is q('c0n0')) - self.assertTrue(np.all(q('c0n0').center == np.r_[0,0,0.])) - self.assertTrue(q('c0n0').num == 0) - self.assertTrue(q('c0n1').num == 1) - self.assertTrue(q('c0n2').num == 4) - self.assertTrue(q('c0n3').num == 5) - self.assertTrue(q('c0n4').num == 11) - self.assertTrue(q('c0n5').num == 12) - self.assertTrue(q('c0n6').num == 14) - self.assertTrue(q('c0n7').num == 15) - - def test_pointersMr(self): - q = self.q - - c0 = self.Mr.sortedCells[0] - c0fXm = c0.fXm - c0eX0 = c0.eX0 - c0fYme0 = c0.fYm.edge0 - self.assertTrue(c0 is q('c0')) - self.assertTrue(c0fXm is q('c0fXm')) - self.assertTrue(c0eX0 is q('c0eX0')) - self.assertTrue(c0fYme0 is q('c0fYme0')) - - self.assertTrue(q('c0').depth == 1) - self.assertTrue(q('c1').depth == 1) - self.assertTrue(q('c2').depth == 0) - - # Make sure we know where the center of the cells are. - self.assertTrue(np.all(q('c0').center == np.r_[0.125,0.25,0.25])) - self.assertTrue(np.all(q('c1').center == np.r_[0.375,0.25,0.25])) - self.assertTrue(np.all(q('c2').center == np.r_[0.75,0.5,0.5])) - self.assertTrue(np.all(q('c3').center == np.r_[0.125,0.75,0.25])) - self.assertTrue(np.all(q('c4').center == np.r_[0.375,0.75,0.25])) - self.assertTrue(np.all(q('c5').center == np.r_[0.125,0.25,0.75])) - self.assertTrue(np.all(q('c6').center == np.r_[0.375,0.25,0.75])) - self.assertTrue(np.all(q('c7').center == np.r_[0.125,0.75,0.75])) - self.assertTrue(np.all(q('c8').center == np.r_[0.375,0.75,0.75])) - - # Test X face connectivity and locations and stuff... - self.assertTrue(np.all(q('c0fXm').center == np.r_[0,0.25,0.25])) - self.assertTrue(np.all(q('c0fXp').center == np.r_[0.25,0.25,0.25])) - self.assertTrue(q('c0fXp') is q('c1fXm')) - self.assertTrue(np.all(q('c1fXp').center == np.r_[0.5,0.25,0.25])) - self.assertTrue(np.all(q('c2fXm').center == np.r_[0.5,0.5,0.5])) - self.assertTrue(q('c2fXm').branchdepth == 1) - self.assertTrue(q('c2fXm').children[0,0] is q('c1fXp')) - self.assertTrue(np.all(q('c3fXm').center == np.r_[0,0.75,0.25])) - self.assertTrue(np.all(q('c3fXp').center == np.r_[0.25,0.75,0.25])) - self.assertTrue(q('c4fXm') is q('c3fXp')) - self.assertTrue(q('c2fXm').children[1,0] is q('c4fXp')) - - #Test some internal stuff (edges held by cell should be same as inside) - for key in ['Mc0', 'Mc1'] + ['c%d'%i for i in range(9)]: - self.assertTrue(q(key+'eX0') is q(key+'fZme0')) - self.assertTrue(q(key+'eX1') is q(key+'fZme1')) - self.assertTrue(q(key+'eX2') is q(key+'fZpe0')) - self.assertTrue(q(key+'eX3') is q(key+'fZpe1')) - - self.assertTrue(q(key+'eX0') is q(key+'fYme0')) - self.assertTrue(q(key+'eX1') is q(key+'fYpe0')) - self.assertTrue(q(key+'eX2') is q(key+'fYme1')) - self.assertTrue(q(key+'eX3') is q(key+'fYpe1')) - - self.assertTrue(q(key+'eY0') is q(key+'fXme0')) - self.assertTrue(q(key+'eY1') is q(key+'fXpe0')) - self.assertTrue(q(key+'eY2') is q(key+'fXme1')) - self.assertTrue(q(key+'eY3') is q(key+'fXpe1')) - - self.assertTrue(q(key+'eY0') is q(key+'fZme2')) - self.assertTrue(q(key+'eY1') is q(key+'fZme3')) - self.assertTrue(q(key+'eY2') is q(key+'fZpe2')) - self.assertTrue(q(key+'eY3') is q(key+'fZpe3')) - - self.assertTrue(q(key+'eZ0') is q(key+'fXme2')) - self.assertTrue(q(key+'eZ1') is q(key+'fXpe2')) - self.assertTrue(q(key+'eZ2') is q(key+'fXme3')) - self.assertTrue(q(key+'eZ3') is q(key+'fXpe3')) - - self.assertTrue(q(key+'eZ0') is q(key+'fYme2')) - self.assertTrue(q(key+'eZ1') is q(key+'fYme3')) - self.assertTrue(q(key+'eZ2') is q(key+'fYpe2')) - self.assertTrue(q(key+'eZ3') is q(key+'fYpe3')) - - #Test some edge stuff - self.assertTrue(np.all(q('c0eX0').center == np.r_[0.125,0,0])) - self.assertTrue(np.all(q('c0eX1').center == np.r_[0.125,0.5,0])) - self.assertTrue(np.all(q('c0eX2').center == np.r_[0.125,0,0.5])) - self.assertTrue(np.all(q('c0eX3').center == np.r_[0.125,0.5,0.5])) - - self.assertTrue(np.all(q('c5eX0').center == np.r_[0.125,0,0.5])) - self.assertTrue(np.all(q('c5eX1').center == np.r_[0.125,0.5,0.5])) - self.assertTrue(q('c5eX0') is q('c0eX2')) - self.assertTrue(q('c5eX1') is q('c0eX3')) - - self.assertTrue(np.all(q('c0eY0').center == np.r_[0,0.25,0])) - self.assertTrue(np.all(q('c0eY1').center == np.r_[0.25,0.25,0])) - self.assertTrue(np.all(q('c0eY2').center == np.r_[0,0.25,0.5])) - self.assertTrue(np.all(q('c0eY3').center == np.r_[0.25,0.25,0.5])) - - self.assertTrue(np.all(q('c1eY0').center == np.r_[0.25,0.25,0])) - self.assertTrue(np.all(q('c1eY2').center == np.r_[0.25,0.25,0.5])) - self.assertTrue(q('c1eY0') is q('c0eY1')) - self.assertTrue(q('c1eY2') is q('c0eY3')) - - - self.assertTrue(np.all(q('c0eZ0').center == np.r_[0,0,0.25])) - self.assertTrue(np.all(q('c0eZ1').center == np.r_[0.25,0,0.25])) - self.assertTrue(np.all(q('c0eZ2').center == np.r_[0,0.5,0.25])) - self.assertTrue(np.all(q('c0eZ3').center == np.r_[0.25,0.5,0.25])) - - self.assertTrue(np.all(q('c3eZ0').center == np.r_[0,0.5,0.25])) - self.assertTrue(np.all(q('c3eZ1').center == np.r_[0.25,0.5,0.25])) - self.assertTrue(q('c3eZ0') is q('c0eZ2')) - self.assertTrue(q('c3eZ1') is q('c0eZ3')) - - - self.assertTrue(q('c0fXp') is q('c1fXm')) - self.assertTrue(q('c0fYp') is not q('c1fYm')) - self.assertTrue(q('c0fXm') is not q('c1fXm')) - - self.assertTrue(q('c1fXp') is q('c2fXm').children[0,0]) - - self.assertTrue(q('c1fYp') is q('c4fYm')) - self.assertTrue(q('c1fZp') is q('c6fZm')) - - self.assertTrue(q('c6fXp') is q('c2fXm').children[0,1]) - - self.assertTrue(q('c4fXp') is q('c2fXm').children[1,0]) - - - def test_gridCC(self): - x = np.r_[0.25,0.75] - y = np.r_[0.5,0.5] - z = np.r_[0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridCC).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375] - y = np.r_[0.25,0.25,0.5,0.75,0.75,0.25,0.25,0.75,0.75] - z = np.r_[0.25,0.25,0.5,0.25,0.25,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridCC).flatten()) == 0) - - def test_gridN(self): - x = np.r_[0,0.5,1,0,0.5,1,0,0.5,1,0,0.5,1] - y = np.r_[0,0,0,1,1,1,0,0,0,1,1,1.] - z = np.r_[0,0,0,0,0,0,1,1,1,1,1,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridN).flatten()) == 0) - - x = np.r_[0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,1] - y = np.r_[0,0,0,0,0.5,0.5,0.5,1,1,1,1,0,0,0,0.5,0.5,0.5,1,1,1,0,0,0,0,0.5,0.5,0.5,1,1,1,1] - z = np.r_[0,0,0,0,0,0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1,1,1,1,1,1,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridN).flatten()) == 0) - - def test_gridFx(self): - x = np.r_[0.0,0.5,1.0] - y = np.r_[0.5,0.5,0.5] - z = np.r_[0.5,0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridFx).flatten()) == 0) - - x = np.r_[0.0,0.25,0.5,1.0,0.0,0.25,0.5,0.0,0.25,0.5,0.0,0.25,0.5] - y = np.r_[0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.25,0.25,0.25,0.75,0.75,0.75] - z = np.r_[0.25,0.25,0.25,0.5,0.25,0.25,0.25,0.75,0.75,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridFx).flatten()) == 0) - - def test_gridFy(self): - x = np.r_[0.25,0.75,0.25,0.75] - y = np.r_[0,0,1.,1.] - z = np.r_[0.5,0.5,0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridFy).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375] - y = np.r_[0,0,0,0.5,0.5,1,1,1,0,0,0.5,0.5,1,1] - z = np.r_[0.25,0.25,0.5,0.25,0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridFy).flatten()) == 0) - - def test_gridFz(self): - x = np.r_[0.25,0.75,0.25,0.75] - y = np.r_[0.5,0.5,0.5,0.5] - z = np.r_[0,0,1.,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridFz).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375,0.125,0.375,0.75,0.125,0.375] - y = np.r_[0.25,0.25,0.5,0.75,0.75,0.25,0.25,0.75,0.75,0.25,0.25,0.5,0.75,0.75] - z = np.r_[0,0,0,0,0,0.5,0.5,0.5,0.5,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridFz).flatten()) == 0) - - - def test_gridEx(self): - x = np.r_[0.25,0.75,0.25,0.75,0.25,0.75,0.25,0.75] - y = np.r_[0,0,1.,1.,0,0,1.,1.] - z = np.r_[0,0,0,0,1.,1.,1.,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridEx).flatten()) == 0) - - x = np.r_[0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.125,0.375,0.125,0.375,0.75,0.125,0.375,0.125,0.375,0.75] - y = np.r_[0,0,0,0.5,0.5,1,1,1,0,0,0.5,0.5,1,1,0,0,0,0.5,0.5,1,1,1] - z = np.r_[0,0,0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,1,1,1,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridEx).flatten()) == 0) - - def test_gridEy(self): - x = np.r_[0,0.5,1,0,0.5,1] - y = np.r_[0.5,0.5,0.5,0.5,0.5,0.5] - z = np.r_[0,0,0,1.,1.,1.] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridEy).flatten()) == 0) - - x = np.r_[0,0.25,0.5,1,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5] - y = np.r_[0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.25,0.25,0.25,0.75,0.75,0.75,0.25,0.25,0.25,0.5,0.75,0.75,0.75] - z = np.r_[0,0,0,0,0,0,0,0.5,0.5,0.5,0.5,0.5,0.5,1,1,1,1,1,1,1] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridEy).flatten()) == 0) - - def test_gridEz(self): - x = np.r_[0,0.5,1,0,0.5,1] - y = np.r_[0,0,0,1.,1.,1.] - z = np.r_[0.5,0.5,0.5,0.5,0.5,0.5] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.M.gridEz).flatten()) == 0) - - x = np.r_[0,0.25,0.5,1,0 ,0.25,0.5,0,0.25,0.5,1,0,0.25,0.5,0 ,0.25,0.5,0 ,0.25,0.5] - y = np.r_[0,0 ,0 ,0,0.5,0.5 ,0.5,1,1 ,1 ,1,0,0 ,0 ,0.5,0.5 ,0.5,1 ,1 ,1 ] - z = np.r_[0.25,0.25,0.25,0.5,0.25,0.25,0.25,0.25,0.25,0.25,0.5,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75] - self.assertTrue(np.linalg.norm((np.c_[x,y,z]-self.Mr.gridEz).flatten()) == 0) - - -class TestQuadTreeObjects(unittest.TestCase): - - def setUp(self): - self.M = TreeMesh([2,1]) - self.Mr = TreeMesh([2,1]) - self.Mr.children[0,0].refine() - self.Mr.number() - # self.Mr.plotGrid(showIt=True) - - def test_pointersM(self): - c0 = self.M.children[0,0] - c0fXm = c0.fXm - c0fXp = c0.fXp - c0fYm = c0.fYm - c0fYp = c0.fYp - - c1 = self.M.children[1,0] - c1fXm = c1.fXm - c1fXp = c1.fXp - c1fYm = c1.fYm - c1fYp = c1.fYp - - self.assertTrue(c0fXp is c1fXm) - self.assertTrue(c0fYp is not c1fYm) - self.assertTrue(c0fXm is not c1fXm) - - self.assertTrue(c0fXm.area == 1) - self.assertTrue(c0fYm.area == 0.5) - - self.assertTrue(c0.node1 is c1.node0) - self.assertTrue(c0.node3 is c1.node2) - self.assertTrue(self.M.nN == 6) - - - def test_pointersMr(self): - c0 = self.Mr.sortedCells[0] - c0fXm = c0.fXm - c0fXp = c0.fXp - c0fYm = c0.fYm - c0fYp = c0.fYp - - c1 = self.Mr.sortedCells[1] - c1fXm = c1.fXm - c1fXp = c1.fXp - c1fYm = c1.fYm - c1fYp = c1.fYp - - c2 = self.Mr.sortedCells[2] - c2fXm = c2.fXm - c2fXp = c2.fXp - c2fYm = c2.fYm - c2fYp = c2.fYp - - c4 = self.Mr.sortedCells[4] - c4fXm = c4.fXm - c4fXp = c4.fXp - c4fYm = c4.fYm - c4fYp = c4.fYp - - self.assertTrue(c0fXp is c1fXm) - self.assertTrue(c1fXp.node0 is c2fXm.node0) - self.assertTrue(c1fXp.node0 is c2fXm.node0) - self.assertTrue(c4fYm is c1fYp) - self.assertTrue(c4fXp.node1 is c2fXm.node1) - self.assertTrue(c4fXp.node0 is c1fYp.node1) - self.assertTrue(c0fXp.node1 is c4fYm.node0) - - self.assertTrue(self.Mr.nN == 11) - - self.assertTrue(np.all(c1fXp.node0.x0 == np.r_[0.5,0])) - self.assertTrue(np.all(c1fYp.node0.x0 == np.r_[0.25,0.5])) - - -class TestQuadTreeMesh(unittest.TestCase): - - def setUp(self): - M = TreeMesh([np.ones(x) for x in [3,2]]) - for ii in range(1): - M.children[ii,ii].refine() - self.M = M + nc = 8 + h1 = np.random.rand(nc)*nc*0.5 + nc*0.5 + h2 = np.random.rand(nc)*nc*0.5 + nc*0.5 + h = [hi/np.sum(hi) for hi in [h1, h2]] # normalize + M = Mesh.TreeMesh(h) + M._refineCell([0,0,0]) + M._refineCell([0,0,1]) M.number() # M.plotGrid(showIt=True) + assert M.nhFx == 2 + assert M.nFx == 9 - def test_MeshSizes(self): - self.assertTrue(self.M.nC==9) - self.assertTrue(self.M.nF==25) - self.assertTrue(self.M.nFx==12) - self.assertTrue(self.M.nFy==13) - self.assertTrue(self.M.nE==25) - self.assertTrue(self.M.nEx==13) - self.assertTrue(self.M.nEy==12) + assert np.allclose(M.vol.sum(), 1.0) - def test_gridCC(self): - x = np.r_[0.25,0.75,1.5,2.5,0.25,0.75,0.5,1.5,2.5] - y = np.r_[0.25,0.25,0.5,0.5,0.75,0.75,1.5,1.5,1.5] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridCC).flatten()) == 0) + assert np.allclose(np.r_[M._areaFxFull, M._areaFyFull], M._deflationMatrix('F') * M.area) - def test_gridN(self): - x = np.r_[0,0.5,1,2,3,0,0.5,1,0,0.5,1,2,3,0,1,2,3] - y = np.r_[0,0,0,0,0,.5,.5,.5,1,1,1,1,1,2,2,2,2] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridN).flatten()) == 0) - - def test_gridFx(self): - x = np.r_[0.0,0.5,1.0,2.0,3.0,0.0,0.5,1.0,0.0,1.0,2.0,3.0] - y = np.r_[0.25,0.25,0.25,0.5,0.5,0.75,0.75,0.75,1.5,1.5,1.5,1.5] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridFx).flatten()) == 0) - - def test_gridFy(self): - x = np.r_[0.25,0.75,1.5,2.5,0.25,0.75,0.25,0.75,1.5,2.5,0.5,1.5,2.5] - y = np.r_[0,0,0,0,0.5,0.5,1,1,1,1,2,2,2] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridFy).flatten()) == 0) - - def test_gridEx(self): - x = np.r_[0.25,0.75,1.5,2.5,0.25,0.75,0.25,0.75,1.5,2.5,0.5,1.5,2.5] - y = np.r_[0,0,0,0,0.5,0.5,1,1,1,1,2,2,2] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridEx).flatten()) == 0) - - def test_gridEy(self): - x = np.r_[0.0,0.5,1.0,2.0,3.0,0.0,0.5,1.0,0.0,1.0,2.0,3.0] - y = np.r_[0.25,0.25,0.25,0.5,0.5,0.75,0.75,0.75,1.5,1.5,1.5,1.5] - self.assertTrue(np.linalg.norm((np.c_[x,y]-self.M.gridEy).flatten()) == 0) - - -class SimpleOctreeOperatorTests(unittest.TestCase): - - def setUp(self): - h1 = np.random.rand(5) - h2 = np.random.rand(7) - h3 = np.random.rand(3) - self.tM = TensorMesh([h1,h2,h3]) - self.oM = TreeMesh([h1,h2,h3]) - self.tM2 = TensorMesh([h1,h2]) - self.oM2 = TreeMesh([h1,h2]) def test_faceDiv(self): - self.assertAlmostEqual((self.tM.faceDiv - self.oM.faceDiv).toarray().sum(), 0) - self.assertAlmostEqual((self.tM2.faceDiv - self.oM2.faceDiv).toarray().sum(), 0) - def test_nodalGrad(self): - self.assertAlmostEqual((self.tM.nodalGrad - self.oM.nodalGrad).toarray().sum(), 0) - self.assertAlmostEqual((self.tM2.nodalGrad - self.oM2.nodalGrad).toarray().sum(), 0) + hx, hy = np.r_[1.,2,3,4], np.r_[5.,6,7,8] + T = Mesh.TreeMesh([hx, hy], levels=2) + T.refine(lambda xc:2) + # T.plotGrid(showIt=True) + M = Mesh.TensorMesh([hx, hy]) + assert M.nC == T.nC + assert M.nF == T.nF + assert M.nFx == T.nFx + assert M.nFy == T.nFy + assert M.nE == T.nE + assert M.nEx == T.nEx + assert M.nEy == T.nEy + assert np.allclose(M.area, T.permuteF*T.area) + assert np.allclose(M.edge, T.permuteE*T.edge) + assert np.allclose(M.vol, T.permuteCC*T.vol) + + # plt.subplot(211).spy(M.faceDiv) + # plt.subplot(212).spy(T.permuteCC*T.faceDiv*T.permuteF.T) + # plt.show() + + assert (M.faceDiv - T.permuteCC*T.faceDiv*T.permuteF.T).nnz == 0 + + +class TestOcTree(unittest.TestCase): + + def test_counts(self): + nc = 8 + h1 = np.random.rand(nc)*nc*0.5 + nc*0.5 + h2 = np.random.rand(nc)*nc*0.5 + nc*0.5 + h3 = np.random.rand(nc)*nc*0.5 + nc*0.5 + h = [hi/np.sum(hi) for hi in [h1, h2, h3]] # normalize + M = Mesh.TreeMesh(h, levels=3) + M._refineCell([0,0,0,0]) + M._refineCell([0,0,0,1]) + M.number() + # M.plotGrid(showIt=True) + # assert M.nhFx == 2 + # assert M.nFx == 9 + + assert np.allclose(M.vol.sum(), 1.0) + + # assert np.allclose(M._areaFxFull, (M._deflationMatrix('F') * M.area)[:M.ntFx]) + # assert np.allclose(M._areaFyFull, (M._deflationMatrix('F') * M.area)[M.ntFx:(M.ntFx+M.ntFy)]) + # assert np.allclose(M._areaFzFull, (M._deflationMatrix('F') * M.area)[(M.ntFx+M.ntFy):]) + + # assert np.allclose(M._edgeExFull, (M._deflationMatrix('E') * M.edge)[:M.ntEx]) + # assert np.allclose(M._edgeEyFull, (M._deflationMatrix('E') * M.edge)[M.ntEx:(M.ntEx+M.ntEy)]) + # assert np.allclose(M._edgeEzFull, (M._deflationMatrix('E') * M.edge)[(M.ntEx+M.ntEy):]) + + def test_faceDiv(self): + + hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] + M = Mesh.TreeMesh([hx, hy, hz], levels=2) + M.refine(lambda xc:2) + # M.plotGrid(showIt=True) + Mr = Mesh.TensorMesh([hx, hy, hz]) + assert M.nC == Mr.nC + assert M.nF == Mr.nF + assert M.nFx == Mr.nFx + assert M.nFy == Mr.nFy + assert M.nE == Mr.nE + assert M.nEx == Mr.nEx + assert M.nEy == Mr.nEy + assert np.allclose(Mr.area, M.permuteF*M.area) + assert np.allclose(Mr.edge, M.permuteE*M.edge) + assert np.allclose(Mr.vol, M.permuteCC*M.vol) + + # plt.subplot(211).spy(Mr.faceDiv) + # plt.subplot(212).spy(M.permuteCC*M.faceDiv*M.permuteF.T) + # plt.show() + + assert (Mr.faceDiv - M.permuteCC*M.faceDiv*M.permuteF.T).nnz == 0 + def test_edgeCurl(self): - self.assertAlmostEqual((self.tM.edgeCurl - self.oM.edgeCurl).toarray().sum(), 0) - # self.assertAlmostEqual((self.tM2.edgeCurl - self.oM2.edgeCurl).toarray().sum(), 0) - def test_InnerProducts(self): - self.assertAlmostEqual((self.tM.getFaceInnerProduct() - self.oM.getFaceInnerProduct()).toarray().sum(), 0) - self.assertAlmostEqual((self.tM2.getFaceInnerProduct() - self.oM2.getFaceInnerProduct()).toarray().sum(), 0) - self.assertAlmostEqual((self.tM2.getEdgeInnerProduct() - self.oM2.getEdgeInnerProduct()).toarray().sum(), 0) - self.assertAlmostEqual((self.tM.getEdgeInnerProduct() - self.oM.getEdgeInnerProduct()).toarray().sum(), 0) + hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] + M = Mesh.TreeMesh([hx, hy, hz], levels=2) + M.refine(lambda xc:2) + # M.plotGrid(showIt=True) + Mr = Mesh.TensorMesh([hx, hy, hz]) + + # plt.subplot(211).spy(Mr.faceDiv) + # plt.subplot(212).spy(M.permuteCC.T*M.faceDiv*M.permuteF) + # plt.show() + + assert (Mr.edgeCurl - M.permuteF*M.edgeCurl*M.permuteE.T).nnz == 0 + + def test_faceInnerProduct(self): + + hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] + # hx, hy, hz = [[(1,4)], [(1,4)], [(1,4)]] + + M = Mesh.TreeMesh([hx, hy, hz], levels=2) + M.refine(lambda xc:2) + # M.plotGrid(showIt=True) + Mr = Mesh.TensorMesh([hx, hy, hz]) + + # plt.subplot(211).spy(Mr.getFaceInnerProduct()) + # plt.subplot(212).spy(M.getFaceInnerProduct()) + # plt.show() + + # print M.nC, M.nF, M.getFaceInnerProduct().shape, M.permuteF.shape + + assert np.allclose(Mr.getFaceInnerProduct().todense(), (M.permuteF * M.getFaceInnerProduct() * M.permuteF.T).todense()) + assert np.allclose(Mr.getEdgeInnerProduct().todense(), (M.permuteE * M.getEdgeInnerProduct() * M.permuteE.T).todense()) + + def test_VectorIdenties(self): + hx, hy, hz = [[(1,4)], [(1,4)], [(1,4)]] + + M = Mesh.TreeMesh([hx, hy, hz], levels=2) + Mr = Mesh.TensorMesh([hx, hy, hz]) + + assert (M.faceDiv * M.edgeCurl).nnz == 0 + assert (Mr.faceDiv * Mr.edgeCurl).nnz == 0 + + hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] + + M = Mesh.TreeMesh([hx, hy, hz], levels=2) + Mr = Mesh.TensorMesh([hx, hy, hz]) + + assert np.max(np.abs((M.faceDiv * M.edgeCurl).todense().flatten())) < TOL + assert np.max(np.abs((Mr.faceDiv * Mr.edgeCurl).todense().flatten())) < TOL + if __name__ == '__main__': diff --git a/tests/mesh/test_pointerMesh.py b/tests/mesh/test_pointerMesh.py deleted file mode 100644 index 753873b1..00000000 --- a/tests/mesh/test_pointerMesh.py +++ /dev/null @@ -1,160 +0,0 @@ -from SimPEG import Mesh -from SimPEG.Mesh.PointerTree import Tree -import numpy as np -import matplotlib.pyplot as plt -import unittest - -TOL = 1e-10 - - - -class TestSimpleQuadTree(unittest.TestCase): - - def test_counts(self): - nc = 8 - h1 = np.random.rand(nc)*nc*0.5 + nc*0.5 - h2 = np.random.rand(nc)*nc*0.5 + nc*0.5 - h = [hi/np.sum(hi) for hi in [h1, h2]] # normalize - M = Tree(h) - M._refineCell([0,0,0]) - M._refineCell([0,0,1]) - M.number() - # M.plotGrid(showIt=True) - assert M.nhFx == 2 - assert M.nFx == 9 - - assert np.allclose(M.vol.sum(), 1.0) - - assert np.allclose(np.r_[M._areaFxFull, M._areaFyFull], M._deflationMatrix('F') * M.area) - - - def test_faceDiv(self): - - hx, hy = np.r_[1.,2,3,4], np.r_[5.,6,7,8] - T = Tree([hx, hy], levels=2) - T.refine(lambda xc:2) - # T.plotGrid(showIt=True) - M = Mesh.TensorMesh([hx, hy]) - assert M.nC == T.nC - assert M.nF == T.nF - assert M.nFx == T.nFx - assert M.nFy == T.nFy - assert M.nE == T.nE - assert M.nEx == T.nEx - assert M.nEy == T.nEy - assert np.allclose(M.area, T.permuteF*T.area) - assert np.allclose(M.edge, T.permuteE*T.edge) - assert np.allclose(M.vol, T.permuteCC*T.vol) - - # plt.subplot(211).spy(M.faceDiv) - # plt.subplot(212).spy(T.permuteCC*T.faceDiv*T.permuteF.T) - # plt.show() - - assert (M.faceDiv - T.permuteCC*T.faceDiv*T.permuteF.T).nnz == 0 - - -class TestOcTree(unittest.TestCase): - - def test_counts(self): - nc = 8 - h1 = np.random.rand(nc)*nc*0.5 + nc*0.5 - h2 = np.random.rand(nc)*nc*0.5 + nc*0.5 - h3 = np.random.rand(nc)*nc*0.5 + nc*0.5 - h = [hi/np.sum(hi) for hi in [h1, h2, h3]] # normalize - M = Tree(h, levels=3) - M._refineCell([0,0,0,0]) - M._refineCell([0,0,0,1]) - M.number() - # M.plotGrid(showIt=True) - # assert M.nhFx == 2 - # assert M.nFx == 9 - - assert np.allclose(M.vol.sum(), 1.0) - - # assert np.allclose(M._areaFxFull, (M._deflationMatrix('F') * M.area)[:M.ntFx]) - # assert np.allclose(M._areaFyFull, (M._deflationMatrix('F') * M.area)[M.ntFx:(M.ntFx+M.ntFy)]) - # assert np.allclose(M._areaFzFull, (M._deflationMatrix('F') * M.area)[(M.ntFx+M.ntFy):]) - - # assert np.allclose(M._edgeExFull, (M._deflationMatrix('E') * M.edge)[:M.ntEx]) - # assert np.allclose(M._edgeEyFull, (M._deflationMatrix('E') * M.edge)[M.ntEx:(M.ntEx+M.ntEy)]) - # assert np.allclose(M._edgeEzFull, (M._deflationMatrix('E') * M.edge)[(M.ntEx+M.ntEy):]) - - def test_faceDiv(self): - - hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] - M = Tree([hx, hy, hz], levels=2) - M.refine(lambda xc:2) - # M.plotGrid(showIt=True) - Mr = Mesh.TensorMesh([hx, hy, hz]) - assert M.nC == Mr.nC - assert M.nF == Mr.nF - assert M.nFx == Mr.nFx - assert M.nFy == Mr.nFy - assert M.nE == Mr.nE - assert M.nEx == Mr.nEx - assert M.nEy == Mr.nEy - assert np.allclose(Mr.area, M.permuteF*M.area) - assert np.allclose(Mr.edge, M.permuteE*M.edge) - assert np.allclose(Mr.vol, M.permuteCC*M.vol) - - # plt.subplot(211).spy(Mr.faceDiv) - # plt.subplot(212).spy(M.permuteCC*M.faceDiv*M.permuteF.T) - # plt.show() - - assert (Mr.faceDiv - M.permuteCC*M.faceDiv*M.permuteF.T).nnz == 0 - - - def test_edgeCurl(self): - - hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] - M = Tree([hx, hy, hz], levels=2) - M.refine(lambda xc:2) - # M.plotGrid(showIt=True) - Mr = Mesh.TensorMesh([hx, hy, hz]) - - # plt.subplot(211).spy(Mr.faceDiv) - # plt.subplot(212).spy(M.permuteCC.T*M.faceDiv*M.permuteF) - # plt.show() - - assert (Mr.edgeCurl - M.permuteF*M.edgeCurl*M.permuteE.T).nnz == 0 - - def test_faceInnerProduct(self): - - hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] - # hx, hy, hz = [[(1,4)], [(1,4)], [(1,4)]] - - M = Tree([hx, hy, hz], levels=2) - M.refine(lambda xc:2) - # M.plotGrid(showIt=True) - Mr = Mesh.TensorMesh([hx, hy, hz]) - - # plt.subplot(211).spy(Mr.getFaceInnerProduct()) - # plt.subplot(212).spy(M.getFaceInnerProduct()) - # plt.show() - - # print M.nC, M.nF, M.getFaceInnerProduct().shape, M.permuteF.shape - - assert np.allclose(Mr.getFaceInnerProduct().todense(), (M.permuteF * M.getFaceInnerProduct() * M.permuteF.T).todense()) - assert np.allclose(Mr.getEdgeInnerProduct().todense(), (M.permuteE * M.getEdgeInnerProduct() * M.permuteE.T).todense()) - - def test_VectorIdenties(self): - hx, hy, hz = [[(1,4)], [(1,4)], [(1,4)]] - - M = Tree([hx, hy, hz], levels=2) - Mr = Mesh.TensorMesh([hx, hy, hz]) - - assert (M.faceDiv * M.edgeCurl).nnz == 0 - assert (Mr.faceDiv * Mr.edgeCurl).nnz == 0 - - hx, hy, hz = np.r_[1.,2,3,4], np.r_[5.,6,7,8], np.r_[9.,10,11,12] - - M = Tree([hx, hy, hz], levels=2) - Mr = Mesh.TensorMesh([hx, hy, hz]) - - assert np.max(np.abs((M.faceDiv * M.edgeCurl).todense().flatten())) < TOL - assert np.max(np.abs((Mr.faceDiv * Mr.edgeCurl).todense().flatten())) < TOL - - - -if __name__ == '__main__': - unittest.main()