def faceDivx(self): """Construct divergence operator in the x component (face-stg to cell-centres).""" if getattr(self, '_faceDivx', None) is None: D1 = kron3(speye(self.nCz), speye(self.nCy), ddx(self.nCx)[:, 1:]) S = self.r(self.area, 'F', 'Fx', 'V') V = self.vol self._faceDivx = sdiag(1 / V) * D1 * sdiag(S) return self._faceDivx
def aveFz2CC(self): "Construct the averaging operator on cell faces in the z direction to cell centers." if self.dim < 3: return None if getattr(self, '_aveFz2CC', None) is None: n = self.vnC if(self.dim == 3): self._aveFz2CC = kron3(av(n[2]), speye(n[1]), speye(n[0])) return self._aveFz2CC
def faceDivz(self): """Construct divergence operator in the z component (face-stg to cell-centres).""" if getattr(self, '_faceDivz', None) is None: D3 = kron3(ddx(self.nCz), speye(self.nCy), speye(self.nCx)) S = self.r(self.area, 'F', 'Fz', 'V') V = self.vol self._faceDivz = sdiag(1 / V) * D3 * sdiag(S) return self._faceDivz
def faceDivx(self): """Construct divergence operator in the x component (face-stg to cell-centres).""" if getattr(self, '_faceDivx', None) is None: D1 = kron3(speye(self.nCz), speye(self.nCy), ddx(self.nCx)[:,1:]) S = self.r(self.area, 'F', 'Fx', 'V') V = self.vol self._faceDivx = sdiag(1/V)*D1*sdiag(S) return self._faceDivx
def faceDivz(self): """Construct divergence operator in the z component (face-stg to cell-centres).""" if getattr(self, '_faceDivz', None) is None: D3 = kron3(ddx(self.nCz), speye(self.nCy), speye(self.nCx)) S = self.r(self.area, 'F', 'Fz', 'V') V = self.vol self._faceDivz = sdiag(1/V)*D3*sdiag(S) return self._faceDivz
def _cellGradyStencil(self): if self.dim < 2: return None BC = ['neumann', 'neumann'] n = self.vnC if (self.dim == 2): G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0])) elif (self.dim == 3): G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0])) return G2
def _cellGradyStencil(self): if self.dim < 2: return None BC = ['neumann', 'neumann'] n = self.vnC if(self.dim == 2): G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0])) elif(self.dim == 3): G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0])) return G2
def _cellGradxStencil(self): BC = ['neumann', 'neumann'] n = self.vnC if(self.dim == 1): G1 = ddxCellGrad(n[0], BC) elif(self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC)) elif(self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC)) return G1
def faceDivy(self): """Construct divergence operator in the y component (face-stg to cell-centres).""" raise NotImplementedError('Wrapping the ddx is not yet implemented.') if getattr(self, '_faceDivy', None) is None: # TODO: this needs to wrap to join up faces which are connected in the cylinder D2 = kron3(speye(self.nCz), ddx(self.nCy), speye(self.nCx)) S = self.r(self.area, 'F', 'Fy', 'V') V = self.vol self._faceDivy = sdiag(1 / V) * D2 * sdiag(S) return self._faceDivy
def faceDivy(self): """Construct divergence operator in the y component (face-stg to cell-centres).""" raise NotImplementedError('Wrapping the ddx is not yet implemented.') if getattr(self, '_faceDivy', None) is None: # TODO: this needs to wrap to join up faces which are connected in the cylinder D2 = kron3(speye(self.nCz), ddx(self.nCy), speye(self.nCx)) S = self.r(self.area, 'F', 'Fy', 'V') V = self.vol self._faceDivy = sdiag(1/V)*D2*sdiag(S) return self._faceDivy
def _cellGradxStencil(self): BC = ['neumann', 'neumann'] n = self.vnC if (self.dim == 1): G1 = ddxCellGrad(n[0], BC) elif (self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC)) elif (self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC)) return G1
def fget(self): if self.dim < 3: return None if getattr(self, '_cellGradz', None) is None: BC = ['neumann', 'neumann'] n = self.vnC G3 = kron3(ddxCellGrad(n[2], BC), speye(n[1]), speye(n[0])) # Compute areas of cell faces & volumes V = self.aveCC2F*self.vol L = self.r(self.area/V, 'F','Fz', 'V') self._cellGradz = sdiag(L)*G3 return self._cellGradz
def aveEy2CC(self): "Construct the averaging operator on cell edges in the y direction to cell centers." if self.dim < 2: return None if getattr(self, '_aveEy2CC', None) is None: # The number of cell centers in each direction n = self.vnC if(self.dim == 2): self._aveEy2CC = sp.kron(speye(n[1]), av(n[0])) elif(self.dim == 3): self._aveEy2CC = kron3(av(n[2]), speye(n[1]), av(n[0])) return self._aveEy2CC
def aveFx2CC(self): "Construct the averaging operator on cell faces in the x direction to cell centers." if getattr(self, '_aveFx2CC', None) is None: n = self.vnC if(self.dim == 1): self._aveFx2CC = av(n[0]) elif(self.dim == 2): self._aveFx2CC = sp.kron(speye(n[1]), av(n[0])) elif(self.dim == 3): self._aveFx2CC = kron3(speye(n[2]), speye(n[1]), av(n[0])) return self._aveFx2CC
def aveF2CCV(self): "Construct the averaging operator on cell faces to cell centers." if getattr(self, '_aveF2CCV', None) is None: n = self.vnC if self.isSymmetric: avR = av(n[0])[:,1:] avR[0,0] = 1. self._aveF2CCV = sp.block_diag((sp.kron(speye(n[2]), avR), sp.kron(av(n[2]), speye(n[0]))), format="csr") else: raise NotImplementedError('wrapping in the averaging is not yet implemented') return self._aveF2CCV
def fget(self): if(self.dim < 3): return None if(self._faceDivz is None): # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces D3 = kron3(ddx(n[2]), speye(n[1]), speye(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fz', 'V') V = self.vol self._faceDivz = sdiag(1/V)*D3*sdiag(S) return self._faceDivz
def nodalLaplacian(self): """ Construct laplacian operator (nodes to edges). """ if getattr(self, '_nodalLaplacian', None) is None: print('Warning: Laplacian has not been tested rigorously.') # The number of cell centers in each direction n = self.vnC # Compute divergence operator on faces if (self.dim == 1): D1 = sdiag(1. / self.hx) * ddx(self.nCx) L = -D1.T * D1 elif (self.dim == 2): D1 = sdiag(1. / self.hx) * ddx(n[0]) D2 = sdiag(1. / self.hy) * ddx(n[1]) L1 = sp.kron(speye(n[1] + 1), -D1.T * D1) L2 = sp.kron(-D2.T * D2, speye(n[0] + 1)) L = L1 + L2 elif (self.dim == 3): D1 = sdiag(1. / self.hx) * ddx(n[0]) D2 = sdiag(1. / self.hy) * ddx(n[1]) D3 = sdiag(1. / self.hz) * ddx(n[2]) L1 = kron3(speye(n[2] + 1), speye(n[1] + 1), -D1.T * D1) L2 = kron3(speye(n[2] + 1), -D2.T * D2, speye(n[0] + 1)) L3 = kron3(-D3.T * D3, speye(n[1] + 1), speye(n[0] + 1)) L = L1 + L2 + L3 self._nodalLaplacian = L return self._nodalLaplacian
def fget(self): if(self._nodalLaplacian is None): print 'Warning: Laplacian has not been tested rigorously.' # The number of cell centers in each direction n = self.vnC # Compute divergence operator on faces if(self.dim == 1): D1 = sdiag(1./self.hx) * ddx(mesh.nCx) L = - D1.T*D1 elif(self.dim == 2): D1 = sdiag(1./self.hx) * ddx(n[0]) D2 = sdiag(1./self.hy) * ddx(n[1]) L1 = sp.kron(speye(n[1]+1), - D1.T * D1) L2 = sp.kron(- D2.T * D2, speye(n[0]+1)) L = L1 + L2 elif(self.dim == 3): D1 = sdiag(1./self.hx) * ddx(n[0]) D2 = sdiag(1./self.hy) * ddx(n[1]) D3 = sdiag(1./self.hz) * ddx(n[2]) L1 = kron3(speye(n[2]+1), speye(n[1]+1), - D1.T * D1) L2 = kron3(speye(n[2]+1), - D2.T * D2, speye(n[0]+1)) L3 = kron3(- D3.T * D3, speye(n[1]+1), speye(n[0]+1)) L = L1 + L2 + L3 self._nodalLaplacian = L return self._nodalLaplacian
def fget(self): if self.dim < 2: return None if getattr(self, '_cellGrady', None) is None: BC = ['neumann', 'neumann'] n = self.vnC if(self.dim == 2): G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0])) elif(self.dim == 3): G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0])) # Compute areas of cell faces & volumes V = self.aveCC2F*self.vol L = self.r(self.area/V, 'F','Fy', 'V') self._cellGrady = sdiag(L)*G2 return self._cellGrady
def cellGradBC(self): """ The cell centered Gradient boundary condition matrix """ if getattr(self, '_cellGradBC', None) is None: BC = self.setCellGradBC(self._cellGradBC_list) n = self.vnC if (self.dim == 1): G = ddxCellGradBC(n[0], BC[0]) elif (self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGradBC(n[0], BC[0])) G2 = sp.kron(ddxCellGradBC(n[1], BC[1]), speye(n[0])) G = sp.block_diag((G1, G2), format="csr") elif (self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGradBC(n[0], BC[0])) G2 = kron3(speye(n[2]), ddxCellGradBC(n[1], BC[1]), speye(n[0])) G3 = kron3(ddxCellGradBC(n[2], BC[2]), speye(n[1]), speye(n[0])) G = sp.block_diag((G1, G2, G3), format="csr") # Compute areas of cell faces & volumes S = self.area V = self.aveCC2F * self.vol # Average volume between adjacent cells self._cellGradBC = sdiag(S / V) * G return self._cellGradBC
def aveF2CCV(self): "Construct the averaging operator on cell faces to cell centers." if getattr(self, '_aveF2CCV', None) is None: n = self.vnC if self.isSymmetric: avR = av(n[0])[:, 1:] avR[0, 0] = 1. self._aveF2CCV = sp.block_diag((sp.kron(speye( n[2]), avR), sp.kron(av(n[2]), speye(n[0]))), format="csr") else: raise NotImplementedError( 'wrapping in the averaging is not yet implemented') return self._aveF2CCV
def aveN2F(self): "Construct the averaging operator on cell nodes to cell faces, keeping each dimension separate." if getattr(self, '_aveN2F', None) is None: # The number of cell centers in each direction n = self.vnC if(self.dim == 1): self._aveN2F = av(n[0]) elif(self.dim == 2): self._aveN2F = sp.vstack((sp.kron(av(n[1]), speye(n[0]+1)), sp.kron(speye(n[1]+1), av(n[0]))), format="csr") elif(self.dim == 3): self._aveN2F = sp.vstack((kron3(av(n[2]), av(n[1]), speye(n[0]+1)), kron3(av(n[2]), speye(n[1]+1), av(n[0])), kron3(speye(n[2]+1), av(n[1]), av(n[0]))), format="csr") return self._aveN2F
def fget(self): if getattr(self, '_cellGradx', None) is None: BC = ['neumann', 'neumann'] n = self.vnC if(self.dim == 1): G1 = ddxCellGrad(n[0], BC) elif(self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC)) elif(self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC)) # Compute areas of cell faces & volumes V = self.aveCC2F*self.vol L = self.r(self.area/V, 'F','Fx', 'V') self._cellGradx = sdiag(L)*G1 return self._cellGradx
def fget(self): if(self.dim < 2): return None if(self._faceDivy is None): # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces if(self.dim == 2): D2 = sp.kron(ddx(n[1]), speye(n[0])) elif(self.dim == 3): D2 = kron3(speye(n[2]), ddx(n[1]), speye(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fy', 'V') V = self.vol self._faceDivy = sdiag(1/V)*D2*sdiag(S) return self._faceDivy
def faceDivy(self): if (self.dim < 2): return None if getattr(self, '_faceDivy', None) is None: # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces if (self.dim == 2): D2 = sp.kron(ddx(n[1]), speye(n[0])) elif (self.dim == 3): D2 = kron3(speye(n[2]), ddx(n[1]), speye(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fy', 'V') V = self.vol self._faceDivy = sdiag(1 / V) * D2 * sdiag(S) return self._faceDivy
def faceDivz(self): """ Construct divergence operator in the z component (face-stg to cell-centres). """ if(self.dim < 3): return None if getattr(self, '_faceDivz', None) is None: # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces D3 = kron3(ddx(n[2]), speye(n[1]), speye(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fz', 'V') V = self.vol self._faceDivz = sdiag(1/V)*D3*sdiag(S) return self._faceDivz
def fget(self): if(self._faceDivx is None): # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces if(self.dim == 1): D1 = ddx(n[0]) elif(self.dim == 2): D1 = sp.kron(speye(n[1]), ddx(n[0])) elif(self.dim == 3): D1 = kron3(speye(n[2]), speye(n[1]), ddx(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fx', 'V') V = self.vol self._faceDivx = sdiag(1/V)*D1*sdiag(S) return self._faceDivx
def aveF2CC(self): "Construct the averaging operator on cell faces to cell centers." if getattr(self, '_aveF2CC', None) is None: n = self.vnC if self.isSymmetric: avR = av(n[0])[:, 1:] avR[0, 0] = 1. self._aveF2CC = (0.5) * sp.hstack((sp.kron(speye( n[2]), avR), sp.kron(av(n[2]), speye(n[0]))), format="csr") else: raise NotImplementedError( 'wrapping in the averaging is not yet implemented') # self._aveF2CC = (1./3.)*sp.hstack((kron3(speye(n[2]), speye(n[1]), av(n[0])), # kron3(speye(n[2]), av(n[1]), speye(n[0])), # kron3(av(n[2]), speye(n[1]), speye(n[0]))), format="csr") return self._aveF2CC
def faceDivz(self): """ Construct divergence operator in the z component (face-stg to cell-centers). """ if (self.dim < 3): return None if getattr(self, '_faceDivz', None) is None: # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces D3 = kron3(ddx(n[2]), speye(n[1]), speye(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fz', 'V') V = self.vol self._faceDivz = sdiag(1 / V) * D3 * sdiag(S) return self._faceDivz
def faceDivx(self): """ Construct divergence operator in the x component (face-stg to cell-centres). """ if getattr(self, '_faceDivx', None) is None: # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces if (self.dim == 1): D1 = ddx(n[0]) elif (self.dim == 2): D1 = sp.kron(speye(n[1]), ddx(n[0])) elif (self.dim == 3): D1 = kron3(speye(n[2]), speye(n[1]), ddx(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fx', 'V') V = self.vol self._faceDivx = sdiag(1 / V) * D1 * sdiag(S) return self._faceDivx
def faceDivx(self): """ Construct divergence operator in the x component (face-stg to cell-centres). """ if getattr(self, '_faceDivx', None) is None: # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces if(self.dim == 1): D1 = ddx(n[0]) elif(self.dim == 2): D1 = sp.kron(speye(n[1]), ddx(n[0])) elif(self.dim == 3): D1 = kron3(speye(n[2]), speye(n[1]), ddx(n[0])) # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fx', 'V') V = self.vol self._faceDivx = sdiag(1/V)*D1*sdiag(S) return self._faceDivx
def aveCC2F(self): "Construct the averaging operator on cell cell centers to faces." if getattr(self, '_aveCC2F', None) is None: n = self.vnC if(self.dim == 1): self._aveCC2F = avExtrap(n[0]) elif(self.dim == 2): self._aveCC2F = sp.vstack((sp.kron(speye(n[1]), avExtrap(n[0])), sp.kron(avExtrap(n[1]), speye(n[0]))), format="csr") elif(self.dim == 3): self._aveCC2F = sp.vstack((kron3(speye(n[2]), speye(n[1]), avExtrap(n[0])), kron3(speye(n[2]), avExtrap(n[1]), speye(n[0])), kron3(avExtrap(n[2]), speye(n[1]), speye(n[0]))), format="csr") return self._aveCC2F
def _cellGradStencil(self): BC = self.setCellGradBC(self._cellGradBC_list) n = self.vnC if(self.dim == 1): G = ddxCellGrad(n[0], BC[0]) elif(self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC[0])) G2 = sp.kron(ddxCellGrad(n[1], BC[1]), speye(n[0])) G = sp.vstack((G1, G2), format="csr") elif(self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC[0])) G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC[1]), speye(n[0])) G3 = kron3(ddxCellGrad(n[2], BC[2]), speye(n[1]), speye(n[0])) G = sp.vstack((G1, G2, G3), format="csr") return G
def _cellGradStencil(self): BC = self.setCellGradBC(self._cellGradBC_list) n = self.vnC if (self.dim == 1): G = ddxCellGrad(n[0], BC[0]) elif (self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC[0])) G2 = sp.kron(ddxCellGrad(n[1], BC[1]), speye(n[0])) G = sp.vstack((G1, G2), format="csr") elif (self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC[0])) G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC[1]), speye(n[0])) G3 = kron3(ddxCellGrad(n[2], BC[2]), speye(n[1]), speye(n[0])) G = sp.vstack((G1, G2, G3), format="csr") return G
def aveF2CC(self): "Construct the averaging operator on cell faces to cell centers." if getattr(self, '_aveF2CC', None) is None: n = self.vnC if self.isSymmetric: avR = av(n[0])[:,1:] avR[0,0] = 1. self._aveF2CC = (0.5)*sp.hstack((sp.kron(speye(n[2]), avR), sp.kron(av(n[2]), speye(n[0]))), format="csr") else: raise NotImplementedError('wrapping in the averaging is not yet implemented') # self._aveF2CC = (1./3.)*sp.hstack((kron3(speye(n[2]), speye(n[1]), av(n[0])), # kron3(speye(n[2]), av(n[1]), speye(n[0])), # kron3(av(n[2]), speye(n[1]), speye(n[0]))), format="csr") return self._aveF2CC
def aveCC2F(grid): "Construct the averaging operator on cell cell centers to faces." if grid.ndim == 1: aveCC2F = av_extrap(grid.shape[0]) elif grid.ndim == 2: aveCC2F = sp.vstack( (sp.kron(speye(grid.shape[1]), av_extrap(grid.shape[0])), sp.kron(av_extrap(grid.shape[1]), speye(grid.shape[0]))), format="csr") elif grid.ndim == 3: aveCC2F = sp.vstack( (kron3(speye(grid.shape[2]), speye(grid.shape[1]), av_extrap(grid.shape[0])), kron3(speye(grid.shape[2]), av_extrap(grid.shape[1]), speye(grid.shape[0])), kron3(av_extrap(grid.shape[2]), speye(grid.shape[1]), speye(grid.shape[0]))), format="csr") return aveCC2F
def fget(self): if(self._nodalGrad is None): # The number of cell centers in each direction n = self.vnC # Compute divergence operator on faces if(self.dim == 1): G = ddx(n[0]) elif(self.dim == 2): D1 = sp.kron(speye(n[1]+1), ddx(n[0])) D2 = sp.kron(ddx(n[1]), speye(n[0]+1)) G = sp.vstack((D1, D2), format="csr") elif(self.dim == 3): D1 = kron3(speye(n[2]+1), speye(n[1]+1), ddx(n[0])) D2 = kron3(speye(n[2]+1), ddx(n[1]), speye(n[0]+1)) D3 = kron3(ddx(n[2]), speye(n[1]+1), speye(n[0]+1)) G = sp.vstack((D1, D2, D3), format="csr") # Compute lengths of cell edges L = self.edge self._nodalGrad = sdiag(1/L)*G return self._nodalGrad
def fget(self): if(self._cellGradBC is None): BC = self.setCellGradBC(self._cellGradBC_list) n = self.vnC if(self.dim == 1): G = ddxCellGradBC(n[0], BC[0]) elif(self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGradBC(n[0], BC[0])) G2 = sp.kron(ddxCellGradBC(n[1], BC[1]), speye(n[0])) G = sp.block_diag((G1, G2), format="csr") elif(self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGradBC(n[0], BC[0])) G2 = kron3(speye(n[2]), ddxCellGradBC(n[1], BC[1]), speye(n[0])) G3 = kron3(ddxCellGradBC(n[2], BC[2]), speye(n[1]), speye(n[0])) G = sp.block_diag((G1, G2, G3), format="csr") # Compute areas of cell faces & volumes S = self.area V = self.aveCC2F*self.vol # Average volume between adjacent cells self._cellGradBC = sdiag(S/V)*G return self._cellGradBC
def fget(self): if(self._faceDiv is None): # The number of cell centers in each direction n = self.vnC # Compute faceDivergence operator on faces if(self.dim == 1): D = ddx(n[0]) elif(self.dim == 2): D1 = sp.kron(speye(n[1]), ddx(n[0])) D2 = sp.kron(ddx(n[1]), speye(n[0])) D = sp.hstack((D1, D2), format="csr") elif(self.dim == 3): D1 = kron3(speye(n[2]), speye(n[1]), ddx(n[0])) D2 = kron3(speye(n[2]), ddx(n[1]), speye(n[0])) D3 = kron3(ddx(n[2]), speye(n[1]), speye(n[0])) D = sp.hstack((D1, D2, D3), format="csr") # Compute areas of cell faces & volumes S = self.area V = self.vol self._faceDiv = sdiag(1/V)*D*sdiag(S) return self._faceDiv
def cellGradBC(self): """ The cell centered Gradient boundary condition matrix """ if getattr(self, '_cellGradBC', None) is None: BC = self.setCellGradBC(self._cellGradBC_list) n = self.vnC if(self.dim == 1): G = ddxCellGradBC(n[0], BC[0]) elif(self.dim == 2): G1 = sp.kron(speye(n[1]), ddxCellGradBC(n[0], BC[0])) G2 = sp.kron(ddxCellGradBC(n[1], BC[1]), speye(n[0])) G = sp.block_diag((G1, G2), format="csr") elif(self.dim == 3): G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGradBC(n[0], BC[0])) G2 = kron3(speye(n[2]), ddxCellGradBC(n[1], BC[1]), speye(n[0])) G3 = kron3(ddxCellGradBC(n[2], BC[2]), speye(n[1]), speye(n[0])) G = sp.block_diag((G1, G2, G3), format="csr") # Compute areas of cell faces & volumes S = self.area V = self.aveCC2F*self.vol # Average volume between adjacent cells self._cellGradBC = sdiag(S/V)*G return self._cellGradBC
def faceDiv(self): """ Construct divergence operator (face-stg to cell-centres). """ if getattr(self, '_faceDiv', None) is None: n = self.vnC # Compute faceDivergence operator on faces if (self.dim == 1): D = ddx(n[0]) elif (self.dim == 2): D1 = sp.kron(speye(n[1]), ddx(n[0])) D2 = sp.kron(ddx(n[1]), speye(n[0])) D = sp.hstack((D1, D2), format="csr") elif (self.dim == 3): D1 = kron3(speye(n[2]), speye(n[1]), ddx(n[0])) D2 = kron3(speye(n[2]), ddx(n[1]), speye(n[0])) D3 = kron3(ddx(n[2]), speye(n[1]), speye(n[0])) D = sp.hstack((D1, D2, D3), format="csr") # Compute areas of cell faces & volumes S = self.area V = self.vol self._faceDiv = sdiag(1 / V) * D * sdiag(S) return self._faceDiv
def faceDiv(self): """ Construct divergence operator (face-stg to cell-centres). """ if getattr(self, '_faceDiv', None) is None: n = self.vnC # Compute faceDivergence operator on faces if(self.dim == 1): D = ddx(n[0]) elif(self.dim == 2): D1 = sp.kron(speye(n[1]), ddx(n[0])) D2 = sp.kron(ddx(n[1]), speye(n[0])) D = sp.hstack((D1, D2), format="csr") elif(self.dim == 3): D1 = kron3(speye(n[2]), speye(n[1]), ddx(n[0])) D2 = kron3(speye(n[2]), ddx(n[1]), speye(n[0])) D3 = kron3(ddx(n[2]), speye(n[1]), speye(n[0])) D = sp.hstack((D1, D2, D3), format="csr") # Compute areas of cell faces & volumes S = self.area V = self.vol self._faceDiv = sdiag(1/V)*D*sdiag(S) return self._faceDiv
def getBCProjWF_simple(self, discretization='CC'): """ The weak form boundary condition projection matrices when mixed boundary condition is used """ if discretization is not 'CC': raise NotImplementedError('Boundary conditions only implemented' 'for CC discretization.') def projBC(n): ij = ([0, n], [0, 1]) vals = [0, 0] vals[0] = 1 vals[1] = 1 return sp.csr_matrix((vals, ij), shape=(n+1, 2)) def projDirichlet(n, bc): bc = checkBC(bc) ij = ([0, n], [0, 1]) vals = [0, 0] if(bc[0] == 'dirichlet'): vals[0] = -1 if(bc[1] == 'dirichlet'): vals[1] = 1 return sp.csr_matrix((vals, ij), shape=(n+1, 2)) BC = [['dirichlet', 'dirichlet'], ['dirichlet', 'dirichlet'], ['dirichlet', 'dirichlet']] n = self.vnC indF = self.faceBoundaryInd if(self.dim == 1): Pbc = projDirichlet(n[0], BC[0]) B = projBC(n[0]) indF = indF[0] | indF[1] Pbc = Pbc*sdiag(self.area[indF]) elif(self.dim == 2): Pbc1 = sp.kron(speye(n[1]), projDirichlet(n[0], BC[0])) Pbc2 = sp.kron(projDirichlet(n[1], BC[1]), speye(n[0])) Pbc = sp.block_diag((Pbc1, Pbc2), format="csr") B1 = sp.kron(speye(n[1]), projBC(n[0])) B2 = sp.kron(projBC(n[1]), speye(n[0])) B = sp.block_diag((B1, B2), format="csr") indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3])] Pbc = Pbc*sdiag(self.area[indF]) elif(self.dim == 3): Pbc1 = kron3(speye(n[2]), speye(n[1]), projDirichlet(n[0], BC[0])) Pbc2 = kron3(speye(n[2]), projDirichlet(n[1], BC[1]), speye(n[0])) Pbc3 = kron3(projDirichlet(n[2], BC[2]), speye(n[1]), speye(n[0])) Pbc = sp.block_diag((Pbc1, Pbc2, Pbc3), format="csr") B1 = kron3(speye(n[2]), speye(n[1]), projBC(n[0])) B2 = kron3(speye(n[2]), projBC(n[1]), speye(n[0])) B3 = kron3(projBC(n[2]), speye(n[1]), speye(n[0])) B = sp.block_diag((B1, B2, B3), format="csr") indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3]), (indF[4] | indF[5])] Pbc = Pbc*sdiag(self.area[indF]) return Pbc, B.T
def fields(self, epsilon, mu, sig0): Smu = sp.block_diag([sdiag(mu*self.sy0), sdiag(mu*self.sx0)]) SmuI = sp.block_diag([sdiag(1./(mu*self.sy0)), sdiag(1./(mu*self.sx0))]) Smuisig = sp.block_diag([sdiag(self.sigs*self.sigy*(1./epsilon)*self.sy0), sdiag(self.sigs*self.sigx*(1./epsilon)*self.sx0)]) Ssig = sp.block_diag([sdiag((self.sigy*mu/epsilon+self.sigs)*self.sy0), sdiag((self.sigx*mu/epsilon+self.sigs)*self.sx0)]) Mesepsisig = sdiag(self.mesh.aveE2CCV.T*np.r_[1./epsilon*sig0*self.sigy*self.sy0, 1./epsilon*sig0*self.sigx*self.sx0]) Messig = sdiag(self.mesh.aveE2CCV.T*np.r_[(sig0+self.sigy)*self.sy0, (sig0+self.sigx)*self.sx0]) Meseps = sdiag(self.mesh.aveE2CCV.T*np.r_[epsilon*self.sy0, epsilon*self.sx0]) MesepsI = sdInv(Meseps) Icc = sp.hstack((speye(self.mesh.nC), speye(self.mesh.nC))) curl = self.mesh.edgeCurl curlvec = sp.block_diag((curl[:,:self.mesh.nEx], curl[:,self.mesh.nEx:])) if self.stability==False: raise Exception("Stability condition is not satisfied!!") elif self.sigx is False: print "Warning: Absorbing boundary condition was not set yet!!" start = clock() print "" print "***** Start Computing Electromagnetic Wave *****" print "" print (">> dt: %5.2e s")%(self.dt) print (">> Optimal dt: %5.2e s")%(self.topt) print (">> Main frequency, fmain: %5.2e Hz")%(self.fmain) print (">> Cell per wavelength (G): %5.2e")%(self.G) if self.storefield==True: self._Fields ={} #TODO: parallize in terms of sources nsrc = len(self.survey.srcList) for isrc, src in enumerate(self.survey.srcList): print (" Src at (%7.2f, %7.2f): %4i/%4i")%(src.loc[0], src.loc[0], isrc+1, nsrc) hd0 = np.zeros(2*self.mesh.nC) hd1 = np.zeros(2*self.mesh.nC) hId0 = np.zeros(2*self.mesh.nC) hId1 = np.zeros(2*self.mesh.nC) e0 = np.zeros(self.mesh.nE) e1 = np.zeros(self.mesh.nE) eI0 = np.zeros(self.mesh.nE) eI1 = np.zeros(self.mesh.nE) time = src.time dt = src.dt jm, je = src.getq(self.mesh) h = np.zeros((self.mesh.nC, time.size)) e = np.zeros((self.mesh.nE, time.size)) for i in range(time.size-1): eI0 = eI1.copy() eI1 = eI0 + dt*e0 e1 = e0 + MesepsI*dt*(curl.T*(Icc*hd1)-Messig*e0-Mesepsisig*eI1-je*src.wave[i]) e0 = e1.copy() e[:,i] = e1 hId0 = hId1.copy() hId1 = hId0 + dt*hd0 hd1 = hd0 - SmuI*dt*(curlvec*e0+Ssig*hd0+Smuisig*hId1+jm*src.wave[i]*0.5) hd0 = hd1.copy() h[:,i] = Icc*hd1 self._Fields['E', src]= e self._Fields['H', src]= h elapsed = clock()-start print (">>Elapsed time: %5.2e s")%(elapsed) return self._Fields elif self.storefield==False: Data = {} nsrc = len(self.survey.srcList) for isrc, src in enumerate(self.survey.srcList): print (" Src at (%7.2f, %7.2f): %4i/%4i")%(src.loc[0], src.loc[0], isrc+1, nsrc) hd0 = np.zeros(2*mesh.nC) hd1 = np.zeros(2*mesh.nC) hId0 = np.zeros(2*mesh.nC) hId1 = np.zeros(2*mesh.nC) e0 = np.zeros(mesh.nE) e1 = np.zeros(mesh.nE) eI0 = np.zeros(mesh.nE) eI1 = np.zeros(mesh.nE) time = src.time dt = src.dt jm, je = src.getq(self.mesh) h = np.zeros((mesh.nC, time.size)) e = np.zeros((mesh.nE, time.size)) for i in range(time.size-1): eI0 = eI1.copy() eI1 = eI0 + dt*e0 e1 = e0 + MesepsI*dt*(curl.T*(Icc*hd1)-Messig*e0-Mesepsisig*eI1-je*src.wave[i]) e0 = e1.copy() e[:,i] = e1 hId0 = hId1.copy() hId1 = hId0 + dt*hd0 hd1 = hd0 - SmuI*dt*(curlvec*e0+Ssig*hd0+Smuisig*hId1+jm*src.wave[i]) hd0 = hd1.copy() h[:,i] = Icc*hd1 for rx in src.rxList: Proj = rx.getP(self.mesh) if rx.rxtype.find('E') >= 0: flag = 'E' Data[src, rx] = (Proj*e) elif rx.rxtype.find('H') >= 0: flag = 'H' Data[src, rx] = (Proj*h) elapsed = clock()-start print (">>Elapsed time: %5.2e s")%(elapsed) return Data
def fields(self, epsilon, mu, sig0): Seps = sp.block_diag( [sdiag(epsilon * self.sy0), sdiag(epsilon * self.sx0)]) SepsI = sp.block_diag([ sdiag(1. / (epsilon * self.sy0)), sdiag(1. / (epsilon * self.sx0)) ]) Sepsisig = sp.block_diag([ sdiag(sig0 * self.sigy * (1. / epsilon) * self.sy0), sdiag(sig0 * self.sigx * (1. / epsilon) * self.sx0) ]) Ssig = sp.block_diag([ sdiag((self.sigy + sig0) * self.sy0), sdiag((self.sigx + sig0) * self.sx0) ]) Mesmuisigs = sdiag(self.mesh.aveE2CCV.T * np.r_[self.sigs * self.sigy / epsilon * self.sy0, self.sigs * self.sigx / epsilon * self.sx0]) Messigs = sdiag( self.mesh.aveE2CCV.T * np.r_[(self.sigs + self.sigy * mu / epsilon) * self.sy0, (self.sigs + self.sigx * mu / epsilon) * self.sx0]) Mesmu = sdiag(self.mesh.aveE2CCV.T * np.r_[mu * self.sy0, mu * self.sx0]) MesmuI = sdInv(Mesmu) Icc = sp.hstack((speye(self.mesh.nC), speye(self.mesh.nC))) curl = self.mesh.edgeCurl curlvec = sp.block_diag( (curl[:, :self.mesh.nEx], curl[:, self.mesh.nEx:])) if self.stability == False: raise Exception("Stability condition is not satisfied!!") elif self.sigx is False: print "Warning: Absorbing boundary condition was not set yet!!" start = clock() print "" print "***** Start Computing Electromagnetic Wave *****" print "" print(">> dt: %5.2e s") % (self.dt) print(">> Optimal dt: %5.2e s") % (self.topt) print(">> Main frequency, fmain: %5.2e Hz") % (self.fmain) print(">> Cell per wavelength (G): %5.2e") % (self.G) if self.storefield == True: self._Fields = {} #TODO: parallize in terms of sources nsrc = len(self.survey.srcList) for isrc, src in enumerate(self.survey.srcList): print(" Src at (%7.2f, %7.2f): %4i/%4i") % ( src.loc[0], src.loc[0], isrc + 1, nsrc) h0 = np.zeros(self.mesh.nE) h1 = np.zeros(self.mesh.nE) hI0 = np.zeros(self.mesh.nE) hI1 = np.zeros(self.mesh.nE) ed0 = np.zeros(2 * self.mesh.nC) ed1 = np.zeros(2 * self.mesh.nC) eId0 = np.zeros(2 * self.mesh.nC) eId1 = np.zeros(2 * self.mesh.nC) time = src.time dt = src.dt je, jm = src.getq(self.mesh) h = np.zeros((self.mesh.nE, time.size)) e = np.zeros((self.mesh.nC, time.size)) for i in range(time.size - 1): eId0 = eId1.copy() eId1 = eId0 + dt * ed0 ed1 = ed0 + SepsI * dt * ( curlvec * (h1) - Ssig * ed0 - Sepsisig * eId1 - je * src.wave[i]) ed0 = ed1.copy() e[:, i] = Icc * ed1 hI0 = hI1.copy() hI1 = hI0 + dt * h0 h1 = h0 - MesmuI * dt * (curl.T * (Icc * ed0) + Messigs * h0 + Mesmuisigs * hI1 + jm * src.wave[i]) h0 = h1.copy() h[:, i] = h1 self._Fields['E', src] = e self._Fields['H', src] = h elapsed = clock() - start print(">>Elapsed time: %5.2e s") % (elapsed) return self._Fields elif self.storefield == False: Data = {} nsrc = len(self.survey.srcList) for isrc, src in enumerate(self.survey.srcList): print(" Src at (%7.2f, %7.2f): %4i/%4i") % ( src.loc[0], src.loc[0], isrc + 1, nsrc) h0 = np.zeros(mesh.nE) h1 = np.zeros(mesh.nE) hI0 = np.zeros(mesh.nE) hI1 = np.zeros(mesh.nE) ed0 = np.zeros(2 * mesh.nC) ed1 = np.zeros(2 * mesh.nC) eId0 = np.zeros(2 * mesh.nC) eId1 = np.zeros(2 * mesh.nC) time = src.time dt = src.dt je, jm = src.getq(self.mesh) h = np.zeros((mesh.nE, time.size)) e = np.zeros((mesh.nC, time.size)) for i in range(time.size - 1): eId0 = eId1.copy() eId1 = eId0 + dt * ed0 ed1 = ed0 + SepsI * dt * (curlvec * (h1) - Ssig * ed0 - Sepsisig * eId1 - je * wave[i]) ed0 = ed1.copy() e[:, i] = Icc * ed1 hI0 = hI1.copy() hI1 = hI0 + dt * h0 h1 = h0 - MesmuI * dt * (curl.T * (Icc * ed0) + Messigs * h0 + Mesmuisigs * hI1 + jm * wave[i]) h0 = h1.copy() h[:, i] = h1 for rx in src.rxList: Proj = rx.getP(self.mesh) if rx.rxtype.find('E') >= 0: flag = 'E' Data[src, rx] = (Proj * e) elif rx.rxtype.find('H') >= 0: flag = 'H' Data[src, rx] = (Proj * h) elapsed = clock() - start print(">>Elapsed time: %5.2e s") % (elapsed) return Data
def fget(self): if(self._edgeCurl is None): assert self.dim > 1, "Edge Curl only programed for 2 or 3D." # The number of cell centers in each direction n = self.vnC # Compute lengths of cell edges L = self.edge # Compute areas of cell faces S = self.area # Compute divergence operator on faces if self.dim == 2: D21 = sp.kron(ddx(n[1]), speye(n[0])) D12 = sp.kron(speye(n[1]), ddx(n[0])) C = sp.hstack((-D21, D12), format="csr") self._edgeCurl = C*sdiag(1/S) elif self.dim == 3: D32 = kron3(ddx(n[2]), speye(n[1]), speye(n[0]+1)) D23 = kron3(speye(n[2]), ddx(n[1]), speye(n[0]+1)) D31 = kron3(ddx(n[2]), speye(n[1]+1), speye(n[0])) D13 = kron3(speye(n[2]), speye(n[1]+1), ddx(n[0])) D21 = kron3(speye(n[2]+1), ddx(n[1]), speye(n[0])) D12 = kron3(speye(n[2]+1), speye(n[1]), ddx(n[0])) O1 = spzeros(np.shape(D32)[0], np.shape(D31)[1]) O2 = spzeros(np.shape(D31)[0], np.shape(D32)[1]) O3 = spzeros(np.shape(D21)[0], np.shape(D13)[1]) C = sp.vstack((sp.hstack((O1, -D32, D23)), sp.hstack((D31, O2, -D13)), sp.hstack((-D21, D12, O3))), format="csr") self._edgeCurl = sdiag(1/S)*(C*sdiag(L)) return self._edgeCurl
def getBCProjWF(self, BC, discretization='CC'): """ The weak form boundary condition projection matrices. Examples:: BC = 'neumann' # Neumann in all directions BC = ['neumann', 'dirichlet', 'neumann'] # 3D, Dirichlet in y Neumann else BC = [['neumann', 'dirichlet'], 'dirichlet', 'dirichlet'] # 3D, Neumann in x on bottom of domain, # Dirichlet else """ if discretization is not 'CC': raise NotImplementedError('Boundary conditions only implemented for CC discretization.') if(type(BC) is str): BC = [BC for _ in self.vnC] # Repeat the str self.dim times elif(type(BC) is list): assert len(BC) == self.dim, 'BC list must be the size of your mesh' else: raise Exception("BC must be a str or a list.") for i, bc_i in enumerate(BC): BC[i] = checkBC(bc_i) def projDirichlet(n, bc): bc = checkBC(bc) ij = ([0,n], [0,1]) vals = [0,0] if(bc[0] == 'dirichlet'): vals[0] = -1 if(bc[1] == 'dirichlet'): vals[1] = 1 return sp.csr_matrix((vals, ij), shape=(n+1,2)) def projNeumannIn(n, bc): bc = checkBC(bc) P = sp.identity(n+1).tocsr() if(bc[0] == 'neumann'): P = P[1:,:] if(bc[1] == 'neumann'): P = P[:-1,:] return P def projNeumannOut(n, bc): bc = checkBC(bc) ij = ([0, 1],[0, n]) vals = [0,0] if(bc[0] == 'neumann'): vals[0] = 1 if(bc[1] == 'neumann'): vals[1] = 1 return sp.csr_matrix((vals, ij), shape=(2,n+1)) n = self.vnC indF = self.faceBoundaryInd if(self.dim == 1): Pbc = projDirichlet(n[0], BC[0]) indF = indF[0] | indF[1] Pbc = Pbc*sdiag(self.area[indF]) Pin = projNeumannIn(n[0], BC[0]) Pout = projNeumannOut(n[0], BC[0]) elif(self.dim == 2): Pbc1 = sp.kron(speye(n[1]), projDirichlet(n[0], BC[0])) Pbc2 = sp.kron(projDirichlet(n[1], BC[1]), speye(n[0])) Pbc = sp.block_diag((Pbc1, Pbc2), format="csr") indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3])] Pbc = Pbc*sdiag(self.area[indF]) P1 = sp.kron(speye(n[1]), projNeumannIn(n[0], BC[0])) P2 = sp.kron(projNeumannIn(n[1], BC[1]), speye(n[0])) Pin = sp.block_diag((P1, P2), format="csr") P1 = sp.kron(speye(n[1]), projNeumannOut(n[0], BC[0])) P2 = sp.kron(projNeumannOut(n[1], BC[1]), speye(n[0])) Pout = sp.block_diag((P1, P2), format="csr") elif(self.dim == 3): Pbc1 = kron3(speye(n[2]), speye(n[1]), projDirichlet(n[0], BC[0])) Pbc2 = kron3(speye(n[2]), projDirichlet(n[1], BC[1]), speye(n[0])) Pbc3 = kron3(projDirichlet(n[2], BC[2]), speye(n[1]), speye(n[0])) Pbc = sp.block_diag((Pbc1, Pbc2, Pbc3), format="csr") indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3]), (indF[4] | indF[5])] Pbc = Pbc*sdiag(self.area[indF]) P1 = kron3(speye(n[2]), speye(n[1]), projNeumannIn(n[0], BC[0])) P2 = kron3(speye(n[2]), projNeumannIn(n[1], BC[1]), speye(n[0])) P3 = kron3(projNeumannIn(n[2], BC[2]), speye(n[1]), speye(n[0])) Pin = sp.block_diag((P1, P2, P3), format="csr") P1 = kron3(speye(n[2]), speye(n[1]), projNeumannOut(n[0], BC[0])) P2 = kron3(speye(n[2]), projNeumannOut(n[1], BC[1]), speye(n[0])) P3 = kron3(projNeumannOut(n[2], BC[2]), speye(n[1]), speye(n[0])) Pout = sp.block_diag((P1, P2, P3), format="csr") return Pbc, Pin, Pout