def faceDivy(self): if (self.dim < 2): return None # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fy', 'V') V = self.vol return sdiag(1 / V) * self._faceDivStencily * sdiag(S)
def faceDivx(self): """ Construct divergence operator in the x component (face-stg to cell-centres). """ # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fx', 'V') V = self.vol return sdiag(1 / V) * self._faceDivStencilx * sdiag(S)
def faceDivz(self): """ Construct divergence operator in the z component (face-stg to cell-centers). """ if (self.dim < 3): return None # Compute areas of cell faces & volumes S = self.r(self.area, 'F', 'Fz', 'V') V = self.vol return sdiag(1 / V) * self._faceDivStencilz * sdiag(S)
def faceDiv(self): """ Construct divergence operator (face-stg to cell-centres). """ if getattr(self, '_faceDiv', None) is None: # Get the stencil of +1, -1's D = self._faceDivStencil # Compute areas of cell faces & volumes S = self.area V = self.vol self._faceDiv = sdiag(1 / V) * D * sdiag(S) return self._faceDiv
def test_zero(self): z = Zero() assert z == 0 assert not (z < 0) assert z <= 0 assert not (z > 0) assert z >= 0 assert +z == z assert -z == z assert z + 1 == 1 assert z + 3 + z == 3 assert z - 3 == -3 assert z - 3 - z == -3 assert 3 * z == 0 assert z * 3 == 0 assert z / 3 == 0 a = 1 a += z assert a == 1 a = 1 a += z assert a == 1 self.assertRaises(ZeroDivisionError, lambda: 3 / z) assert mkvc(z) == 0 assert sdiag(z) * a == 0 assert z.T == 0 assert z.transpose() == 0
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 _nodalLaplacianx(self): Hx = sdiag(1. / self.hx) if self.dim == 2: Hx = sp.kron(speye(self.nNy), Hx) elif self.dim == 3: Hx = kron3(speye(self.nNz), speye(self.nNy), Hx) return Hx.T * self._nodalGradStencilx * Hx
def getError(self): # Test function # PDE: Curl(Curl Ez) + Ez = q # faces_z are cell_centers on 2D mesh ez_fun = lambda x: np.cos(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) q_fun = lambda x: (1 + 2 * np.pi**2) * ez_fun(x) mesh = self.M ez_ana = ez_fun(mesh.cell_centers) q_ana = q_fun(mesh.cell_centers) ez_bc = ez_fun(mesh.boundary_edges) MeI = mesh.get_edge_inner_product(invert_matrix=True) M_be = mesh.boundary_edge_vector_integral V = utils.sdiag(mesh.cell_volumes) C = mesh.edge_curl A = V @ C @ MeI @ C.T @ V + V rhs = V @ q_ana + V @ C @ MeI @ M_be @ ez_bc ez_test = Pardiso(A) * rhs if self._meshType == "rotateCurv": err = np.linalg.norm(mesh.cell_volumes * (ez_test - ez_ana)) else: err = np.linalg.norm(ez_test - ez_ana) / np.sqrt(mesh.n_cells) return err
def getError(self): # Test function phi = lambda x: np.cos(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) j_funX = lambda x: -np.pi * np.sin(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) j_funY = lambda x: -np.pi * np.cos(np.pi * x[:, 0]) * np.sin(np.pi * x[:, 1]) q_fun = lambda x: -2 * (np.pi**2) * phi(x) mesh = self.M phi_ana = phi(mesh.cell_centers) q_ana = q_fun(mesh.cell_centers) phi_bc = phi(mesh.boundary_faces) MfI = mesh.get_face_inner_product(invert_matrix=True) M_bf = mesh.boundary_face_scalar_integral V = utils.sdiag(mesh.cell_volumes) G = -mesh.face_divergence.T * V D = mesh.face_divergence # Sinc the xc_bc is a known, move it to the RHS! A = V @ D @ MfI @ G rhs = V @ q_ana - V @ D @ MfI @ M_bf @ phi_bc phi_test = Solver(A) * rhs if self._meshType == "rotateCurv": err = np.linalg.norm(mesh.cell_volumes * (phi_test - phi_ana)) else: err = np.linalg.norm(phi_test - phi_ana) / np.sqrt(mesh.n_cells) return err
def getError(self): # Test function phi = lambda x: np.sin(np.pi * x[:, 0]) * np.sin( np.pi * x[:, 1]) * np.sin(np.pi * x[:, 2]) j_funX = lambda x: np.pi * np.cos(np.pi * x[:, 0]) * np.sin( np.pi * x[:, 1]) * np.sin(np.pi * x[:, 2]) j_funY = lambda x: np.pi * np.sin(np.pi * x[:, 0]) * np.cos( np.pi * x[:, 1]) * np.sin(np.pi * x[:, 2]) j_funZ = lambda x: np.pi * np.sin(np.pi * x[:, 0]) * np.sin( np.pi * x[:, 1]) * np.cos(np.pi * x[:, 2]) q_fun = lambda x: -3 * (np.pi**2) * phi(x) mesh = self.M phi_ana = phi(mesh.cell_centers) q_ana = q_fun(mesh.cell_centers) phi_bc = phi(mesh.boundary_faces) jx_bc = j_funX(mesh.boundary_faces) jy_bc = j_funY(mesh.boundary_faces) jz_bc = j_funZ(mesh.boundary_faces) j_bc = np.c_[jx_bc, jy_bc, jz_bc] j_bc_dot_n = np.sum(j_bc * mesh.boundary_face_outward_normals, axis=-1) MfI = mesh.get_face_inner_product(invert_matrix=True) V = utils.sdiag(mesh.cell_volumes) G = mesh.face_divergence.T * V D = mesh.face_divergence # construct matrix with robin operator # get indices of x0 boundary, y0, and z0 boundary n_bounary_faces = len(j_bc_dot_n) dirichlet_locs = np.any(mesh.boundary_faces == 0.0, axis=1) alpha = np.zeros(n_bounary_faces) alpha[dirichlet_locs] = 1.0 beta = np.zeros(n_bounary_faces) beta[~dirichlet_locs] = 1.0 gamma = alpha * phi_bc + beta * j_bc_dot_n B_bc, b_bc = mesh.cell_gradient_weak_form_robin(alpha=alpha, beta=beta, gamma=gamma) A = V @ D @ MfI @ (-G + B_bc) rhs = V @ q_ana - V @ D @ MfI @ b_bc phi_test = Pardiso(A) * rhs if self._meshType == "rotateCurv": err = np.linalg.norm(mesh.cell_volumes * (phi_test - phi_ana)) else: err = np.linalg.norm(phi_test - phi_ana) / np.sqrt(mesh.n_cells) return err
def edgeCurl(self): """ Construct the 3D curl operator. """ L = self.edge # Compute lengths of cell edges S = self.area # Compute areas of cell faces if getattr(self, '_edgeCurl', None) is None: assert self.dim > 1, "Edge Curl only programed for 2 or 3D." if self.dim == 2: self._edgeCurl = self._edgeCurlStencil*sdiag(1/S) elif self.dim == 3: self._edgeCurl = sdiag(1/S)*(self._edgeCurlStencil*sdiag(L)) return self._edgeCurl
def _nodalLaplaciany(self): Hy = sdiag(1. / self.hy) if self.dim == 1: return None elif self.dim == 2: Hy = sp.kron(Hy, speye(self.nNx)) elif self.dim == 3: Hy = kron3(speye(self.nNz), Hy, speye(self.nNx)) return Hy.T * self._nodalGradStencily * Hy
def nodalGrad(self): """ Construct gradient operator (nodes to edges). """ if getattr(self, '_nodalGrad', None) is None: G = self._nodalGradStencil L = self.edge self._nodalGrad = sdiag(1 / L) * G return self._nodalGrad
def innerProductDeriv(v=None): if v is None: warnings.warn( "Depreciation Warning: TensorMesh.innerProductDeriv." " You should be supplying a vector. " "Use: sdiag(u)*dMdprop", FutureWarning ) return dMdprop return utils.sdiag(v) * dMdprop
def cellGrad(self): """ The cell centered Gradient, takes you to cell faces. """ if getattr(self, '_cellGrad', None) is None: G = self._cellGradStencil S = self.area # Compute areas of cell faces & volumes V = self.aveCC2F * self.vol # Average volume between adjacent cells self._cellGrad = sdiag(S / V) * G return self._cellGrad
def cellGrady(self): if self.dim < 2: return None if getattr(self, '_cellGrady', None) is None: G2 = self._cellGradyStencil # 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 test_mat_shape(self): o = Identity() S = sdiag(np.r_[2, 3])[:1, :] self.assertRaises(ValueError, lambda: S + o) def check(exp, ans): assert np.all((exp).todense() == ans) check(S * o, [[2, 0]]) check(S * -o, [[-2, 0]])
def getError(self): #Test function phi = lambda x: np.cos(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) j_funX = lambda x: -np.pi * np.sin(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) j_funY = lambda x: -np.pi * np.cos(np.pi * x[:, 0]) * np.sin(np.pi * x[:, 1]) q_fun = lambda x: -2 * (np.pi**2) * phi(x) xc_ana = phi(self.M.gridCC) q_ana = q_fun(self.M.gridCC) jX_ana = j_funX(self.M.gridFx) jY_ana = j_funY(self.M.gridFy) j_ana = np.r_[jX_ana, jY_ana] #TODO: Check where our boundary conditions are CCx or Nx # fxm,fxp,fym,fyp = self.M.faceBoundaryInd # gBFx = self.M.gridFx[(fxm|fxp),:] # gBFy = self.M.gridFy[(fym|fyp),:] fxm, fxp, fym, fyp = self.M.cellBoundaryInd gBFx = self.M.gridCC[(fxm | fxp), :] gBFy = self.M.gridCC[(fym | fyp), :] bc = phi(np.r_[gBFx, gBFy]) # P = sp.csr_matrix(([-1,1],([0,self.M.nF-1],[0,1])), shape=(self.M.nF, 2)) P, Pin, Pout = self.M.getBCProjWF('dirichlet') Mc = self.M.getFaceInnerProduct() McI = utils.sdInv(self.M.getFaceInnerProduct()) G = -self.M.faceDiv.T * utils.sdiag(self.M.vol) D = self.M.faceDiv j = McI * (G * xc_ana + P * bc) q = D * j # self.M.plotImage(j, 'FxFy', show_it=True) # Rearrange if we know q to solve for x A = D * McI * G rhs = q_ana - D * McI * P * bc if self.myTest == 'j': err = np.linalg.norm((j - j_ana), np.inf) elif self.myTest == 'q': err = np.linalg.norm((q - q_ana), np.inf) elif self.myTest == 'xc': xc = Solver(A) * (rhs) err = np.linalg.norm((xc - xc_ana), np.inf) elif self.myTest == 'xcJ': xc = Solver(A) * (rhs) j = McI * (G * xc + P * bc) err = np.linalg.norm((j - j_ana), np.inf) return err
def cellGradx(self): """ Cell centered Gradient in the x dimension. Has neumann boundary conditions. """ if getattr(self, '_cellGradx', None) is None: G1 = self._cellGradxStencil # 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 getError(self): #Test function phi = lambda x: np.cos(0.5 * np.pi * x) j_fun = lambda x: -0.5 * np.pi * np.sin(0.5 * np.pi * x) q_fun = lambda x: -0.25 * (np.pi**2) * np.cos(0.5 * np.pi * x) xc_ana = phi(self.M.gridCC) q_ana = q_fun(self.M.gridCC) j_ana = j_fun(self.M.gridFx) #TODO: Check where our boundary conditions are CCx or Nx vecN = self.M.vectorNx vecC = self.M.vectorCCx phi_bc = phi(vecC[[0, -1]]) j_bc = j_fun(vecN[[0, -1]]) P, Pin, Pout = self.M.getBCProjWF([['dirichlet', 'neumann']]) Mc = self.M.getFaceInnerProduct() McI = utils.sdInv(self.M.getFaceInnerProduct()) V = utils.sdiag(self.M.vol) G = -Pin.T * Pin * self.M.faceDiv.T * V D = self.M.faceDiv j = McI * (G * xc_ana + P * phi_bc) q = V * D * Pin.T * Pin * j + V * D * Pout.T * j_bc # Rearrange if we know q to solve for x A = V * D * Pin.T * Pin * McI * G rhs = V * q_ana - V * D * Pin.T * Pin * McI * P * phi_bc - V * D * Pout.T * j_bc # A = D*McI*G # rhs = q_ana - D*McI*P*phi_bc if self.myTest == 'j': err = np.linalg.norm((Pin * j - Pin * j_ana), np.inf) elif self.myTest == 'q': err = np.linalg.norm((q - V * q_ana), np.inf) elif self.myTest == 'xc': #TODO: fix the null space xc, info = sp.linalg.minres(A, rhs, tol=1e-6) err = np.linalg.norm((xc - xc_ana), np.inf) if info > 0: print('Solve does not work well') print('ACCURACY', np.linalg.norm(utils.mkvc(A * xc) - rhs)) elif self.myTest == 'xcJ': #TODO: fix the null space xc, info = sp.linalg.minres(A, rhs, tol=1e-6) j = McI * (G * xc + P * phi_bc) err = np.linalg.norm((Pin * j - Pin * j_ana), np.inf) if info > 0: print('Solve does not work well') print('ACCURACY', np.linalg.norm(utils.mkvc(A * xc) - rhs)) return err
def getError(self): #Test function phi = lambda x: np.cos(np.pi * x) j_fun = lambda x: -np.pi * np.sin(np.pi * x) q_fun = lambda x: -(np.pi**2) * np.cos(np.pi * x) xc_ana = phi(self.M.gridCC) q_ana = q_fun(self.M.gridCC) j_ana = j_fun(self.M.gridFx) #TODO: Check where our boundary conditions are CCx or Nx # vec = self.M.vectorNx vec = self.M.vectorCCx phi_bc = phi(vec[[0, -1]]) j_bc = j_fun(vec[[0, -1]]) P, Pin, Pout = self.M.getBCProjWF([['dirichlet', 'dirichlet']]) Mc = self.M.getFaceInnerProduct() McI = utils.sdInv(self.M.getFaceInnerProduct()) V = utils.sdiag(self.M.vol) G = -Pin.T * Pin * self.M.faceDiv.T * V D = self.M.faceDiv j = McI * (G * xc_ana + P * phi_bc) q = V * D * Pin.T * Pin * j + V * D * Pout.T * j_bc # Rearrange if we know q to solve for x A = V * D * Pin.T * Pin * McI * G rhs = V * q_ana - V * D * Pin.T * Pin * McI * P * phi_bc - V * D * Pout.T * j_bc # A = D*McI*G # rhs = q_ana - D*McI*P*phi_bc if self.myTest == 'j': err = np.linalg.norm((j - j_ana), np.inf) elif self.myTest == 'q': err = np.linalg.norm((q - V * q_ana), np.inf) elif self.myTest == 'xc': #TODO: fix the null space solver = SolverCG(A, maxiter=1000) xc = solver * (rhs) print('ACCURACY', np.linalg.norm(utils.mkvc(A * xc) - rhs)) err = np.linalg.norm((xc - xc_ana), np.inf) elif self.myTest == 'xcJ': #TODO: fix the null space xc = Solver(A) * (rhs) print(np.linalg.norm(utils.mkvc(A * xc) - rhs)) j = McI * (G * xc + P * phi_bc) err = np.linalg.norm((j - j_ana), np.inf) return err
def _getInnerProductProjectionMatrices(self, projection_type, tensorType): """ Parameters ---------- projection_type : str 'F' for faces 'E' for edges tensorType : TensorType type of the tensor: TensorType(mesh, sigma) """ if not isinstance(tensorType, TensorType): raise TypeError("tensorType must be an instance of TensorType.") if projection_type not in ["F", "E"]: raise TypeError( "projection_type must be 'F' for faces or 'E' for edges") d = self.dim # We will multiply by sqrt on each side to keep symmetry V = sp.kron(sp.identity(d), sdiag(np.sqrt((2**(-d)) * self.cell_volumes))) nodes = ["000", "100", "010", "110", "001", "101", "011", "111"][:2**d] if projection_type == "F": locs = { "000": [("fXm", ), ("fXm", "fYm"), ("fXm", "fYm", "fZm")], "100": [("fXp", ), ("fXp", "fYm"), ("fXp", "fYm", "fZm")], "010": [None, ("fXm", "fYp"), ("fXm", "fYp", "fZm")], "110": [None, ("fXp", "fYp"), ("fXp", "fYp", "fZm")], "001": [None, None, ("fXm", "fYm", "fZp")], "101": [None, None, ("fXp", "fYm", "fZp")], "011": [None, None, ("fXm", "fYp", "fZp")], "111": [None, None, ("fXp", "fYp", "fZp")], } proj = getattr(self, "_getFaceP" + ("x" * d))() elif projection_type == "E": locs = { "000": [("eX0", ), ("eX0", "eY0"), ("eX0", "eY0", "eZ0")], "100": [("eX0", ), ("eX0", "eY1"), ("eX0", "eY1", "eZ1")], "010": [None, ("eX1", "eY0"), ("eX1", "eY0", "eZ2")], "110": [None, ("eX1", "eY1"), ("eX1", "eY1", "eZ3")], "001": [None, None, ("eX2", "eY2", "eZ0")], "101": [None, None, ("eX2", "eY3", "eZ1")], "011": [None, None, ("eX3", "eY2", "eZ2")], "111": [None, None, ("eX3", "eY3", "eZ3")], } proj = getattr(self, "_getEdgeP" + ("x" * d))() return [V * proj(*locs[node][d - 1]) for node in nodes]
def _getInnerProductProjectionMatrices(self, projType, tensorType): """ Parameters ---------- projType : str 'F' for faces 'E' for edges tensorType : TensorType type of the tensor: TensorType(mesh, sigma) """ assert isinstance( tensorType, TensorType), 'tensorType must be an instance of TensorType.' assert projType in [ 'F', 'E' ], "projType must be 'F' for faces or 'E' for edges" d = self.dim # We will multiply by sqrt on each side to keep symmetry V = sp.kron(sp.identity(d), sdiag(np.sqrt((2**(-d)) * self.vol))) nodes = ['000', '100', '010', '110', '001', '101', '011', '111'][:2**d] if projType == 'F': locs = { '000': [('fXm', ), ('fXm', 'fYm'), ('fXm', 'fYm', 'fZm')], '100': [('fXp', ), ('fXp', 'fYm'), ('fXp', 'fYm', 'fZm')], '010': [None, ('fXm', 'fYp'), ('fXm', 'fYp', 'fZm')], '110': [None, ('fXp', 'fYp'), ('fXp', 'fYp', 'fZm')], '001': [None, None, ('fXm', 'fYm', 'fZp')], '101': [None, None, ('fXp', 'fYm', 'fZp')], '011': [None, None, ('fXm', 'fYp', 'fZp')], '111': [None, None, ('fXp', 'fYp', 'fZp')] } proj = getattr(self, '_getFaceP' + ('x' * d))() elif projType == 'E': locs = { '000': [('eX0', ), ('eX0', 'eY0'), ('eX0', 'eY0', 'eZ0')], '100': [('eX0', ), ('eX0', 'eY1'), ('eX0', 'eY1', 'eZ1')], '010': [None, ('eX1', 'eY0'), ('eX1', 'eY0', 'eZ2')], '110': [None, ('eX1', 'eY1'), ('eX1', 'eY1', 'eZ3')], '001': [None, None, ('eX2', 'eY2', 'eZ0')], '101': [None, None, ('eX2', 'eY3', 'eZ1')], '011': [None, None, ('eX3', 'eY2', 'eZ2')], '111': [None, None, ('eX3', 'eY3', 'eZ3')] } proj = getattr(self, '_getEdgeP' + ('x' * d))() return [V * proj(*locs[node][d - 1]) for node in nodes]
def getError(self): # Test function phi = lambda x: np.sin(np.pi * x[:, 0]) * np.sin(np.pi * x[:, 1]) j_funX = lambda x: np.pi * np.cos(np.pi * x[:, 0]) * np.sin(np.pi * x[:, 1]) j_funY = lambda x: np.pi * np.sin(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) q_fun = lambda x: -2 * (np.pi**2) * phi(x) mesh = self.M phi_ana = phi(mesh.cell_centers) q_ana = q_fun(mesh.cell_centers) phi_bc = phi(mesh.boundary_faces) jx_bc = j_funX(mesh.boundary_faces) jy_bc = j_funY(mesh.boundary_faces) j_bc = np.c_[jx_bc, jy_bc] j_bc_dot_n = np.sum(j_bc * mesh.boundary_face_outward_normals, axis=-1) MfI = mesh.get_face_inner_product(invert_matrix=True) V = utils.sdiag(mesh.cell_volumes) G = mesh.face_divergence.T * V D = mesh.face_divergence # construct matrix with robin operator alpha = 0.0 beta = 1.0 gamma = alpha * phi_bc + beta * j_bc_dot_n B_bc, b_bc = mesh.cell_gradient_weak_form_robin(alpha=alpha, beta=beta, gamma=gamma) A = V @ D @ MfI @ (-G + B_bc) rhs = V @ q_ana - V @ D @ MfI @ b_bc phi_test, info = linalg.minres(A, rhs, tol=1e-6) phi_test -= phi_test.mean() phi_ana -= phi_ana.mean() # err = np.linalg.norm(phi_test - phi_ana)/np.sqrt(mesh.n_cells) if self._meshType == "rotateCurv": err = np.linalg.norm(mesh.cell_volumes * (phi_test - phi_ana)) else: err = np.linalg.norm((phi_test - phi_ana), np.inf) return err
def getError(self): # Test function phi = lambda x: np.sin(np.pi * x) j_fun = lambda x: np.pi * np.cos(np.pi * x) q_fun = lambda x: -(np.pi**2) * np.sin(np.pi * x) mesh = self.M xc_ana = phi(mesh.cell_centers) q_ana = q_fun(mesh.cell_centers) j_ana = j_fun(mesh.faces_x) phi_bc = phi(mesh.boundary_faces) j_bc = j_fun(mesh.boundary_faces) MfI = mesh.get_face_inner_product(invert_matrix=True) V = utils.sdiag(mesh.cell_volumes) G = mesh.face_divergence.T * V D = mesh.face_divergence # construct matrix with robin operator alpha = 0.0 beta = 1.0 gamma = alpha * phi_bc + beta * j_bc * mesh.boundary_face_outward_normals B_bc, b_bc = mesh.cell_gradient_weak_form_robin(alpha=alpha, beta=beta, gamma=gamma) j = MfI @ ((-G + B_bc) @ xc_ana + b_bc) q = D @ j # Since the xc_bc is a known, move it to the RHS! A = V @ D @ MfI @ (-G + B_bc) rhs = V @ q_ana - V @ D @ MfI @ b_bc xc_disc, info = sp.linalg.minres(A, rhs, tol=1e-6) if self.myTest == "j": err = np.linalg.norm((j - j_ana), np.inf) elif self.myTest == "xcJ": # TODO: fix the null space xc, info = linalg.minres(A, rhs, tol=1e-6) j = MfI @ ((-G + B_bc) @ xc + b_bc) err = np.linalg.norm((j - j_ana)) / np.sqrt(mesh.n_edges) if info > 0: print("Solve does not work well") print("ACCURACY", np.linalg.norm(utils.mkvc(A * xc) - rhs)) return err
def getError(self): # Test function phi = lambda x: np.cos(0.5 * np.pi * x) j_fun = lambda x: -0.5 * np.pi * np.sin(0.5 * np.pi * x) q_fun = lambda x: -0.25 * (np.pi**2) * np.cos(0.5 * np.pi * x) mesh = self.M xc_ana = phi(mesh.cell_centers) q_ana = q_fun(mesh.cell_centers) j_ana = j_fun(mesh.faces_x) phi_bc = phi(mesh.boundary_faces) j_bc = j_fun(mesh.boundary_faces) MfI = mesh.get_face_inner_product(invert_matrix=True) V = utils.sdiag(mesh.cell_volumes) G = mesh.face_divergence.T * V D = mesh.face_divergence # construct matrix with robin operator alpha = np.r_[1.0, 0.0] beta = np.r_[0.0, 1.0] gamma = alpha * phi_bc + beta * j_bc * mesh.boundary_face_outward_normals B_bc, b_bc = mesh.cell_gradient_weak_form_robin(alpha=alpha, beta=beta, gamma=gamma) A = V @ D @ MfI @ (-G + B_bc) rhs = V @ q_ana - V @ D @ MfI @ b_bc if self.myTest == "xc": xc = Solver(A) * rhs err = np.linalg.norm(xc - xc_ana) / np.sqrt(mesh.n_cells) elif self.myTest == "xcJ": xc = Solver(A) * rhs j = MfI @ ((-G + B_bc) @ xc + b_bc) err = np.linalg.norm(j - j_ana, np.inf) return err
def test_mat_one(self): o = Identity() S = sdiag(np.r_[2, 3]) def check(exp, ans): assert np.all((exp).todense() == ans) check(S * o, [[2, 0], [0, 3]]) check(o * S, [[2, 0], [0, 3]]) check(S * -o, [[-2, 0], [0, -3]]) check(-o * S, [[-2, 0], [0, -3]]) check(S / o, [[2, 0], [0, 3]]) check(S / -o, [[-2, 0], [0, -3]]) self.assertRaises(NotImplementedError, lambda: o / S) check(S + o, [[3, 0], [0, 4]]) check(o + S, [[3, 0], [0, 4]]) check(S - o, [[1, 0], [0, 2]]) check(S + -o, [[1, 0], [0, 2]]) check(-o + S, [[1, 0], [0, 2]])
def simpleFail(x): return np.sin(x), -sdiag(np.cos(x))
def simpleFunction(x): return np.sin(x), lambda xi: sdiag(np.cos(x)) * xi
def simplePass(x): return np.sin(x), sdiag(np.cos(x))