def test(self): rhs = self.rhs sol = self.sol Ainv = Pardiso(self.A, is_symmetric=True) for i in range(3): self.assertLess(np.linalg.norm(Ainv * rhs[:, i] - sol[:, i]), TOL) self.assertLess(np.linalg.norm(Ainv * rhs - sol, np.inf), TOL) Ainv.clean()
def test_n_threads(self): print('testing setting n_threads') Ainv = Pardiso(self.A, is_symmetric=True, n_threads=1) self.assertEqual(Ainv.n_threads, 1) Ainv2 = Pardiso(self.A, is_symmetric=True, n_threads=4) self.assertEqual(Ainv2.n_threads, 4) self.assertEqual(Ainv2.n_threads, Ainv.n_threads) Ainv.n_threads = 3 self.assertEqual(Ainv.n_threads, 3) self.assertEqual(Ainv2.n_threads, Ainv.n_threads) with self.assertRaises(TypeError): Ainv.n_threads = 2.3
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 solve_2D_potentials(rho1, rho2, h, A, B): """ Here we solve the 2D DC problem for potentials (using SimPEG Mesg Class) """ sigma = 1.0 / rho2 * np.ones(mesh.nC) sigma[mesh.gridCC[:, 1] >= -h] = 1.0 / rho1 # since the model is 2D q = np.zeros(mesh.nC) a = utils.closestPoints(mesh, A[:2]) b = utils.closestPoints(mesh, B[:2]) q[a] = 1.0 / mesh.vol[a] q[b] = -1.0 / mesh.vol[b] # q = q * 1./mesh.vol A = ( mesh.cellGrad.T * utils.sdiag(1.0 / (mesh.dim * mesh.aveF2CC.T * (1.0 / sigma))) * mesh.cellGrad ) Ainv = Pardiso(A) V = Ainv * q return V
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 getError(self): # Test function # PDE: Curl(Curl E) + E = q def e_fun(x): x = np.cos(x) cx, cy, cz = x[:, 0], x[:, 1], x[:, 2] return np.c_[cy * cz, cx * cz, cx * cy] def h_fun(x): cx, cy, cz = np.cos(x[:, 0]), np.cos(x[:, 1]), np.cos(x[:, 2]) sx, sy, sz = np.sin(x[:, 0]), np.sin(x[:, 1]), np.sin(x[:, 2]) return np.c_[(-sy + sz) * cx, (sx - sz) * cy, (-sx + sy) * cz] def q_fun(x): return 3 * e_fun(x) mesh = self.M C = mesh.edge_curl if 'Face' in self.myTest: e_ana = mesh.project_face_vector(e_fun(mesh.faces)) q_ana = mesh.project_face_vector(q_fun(mesh.faces)) e_bc = e_fun(mesh.boundary_edges).reshape(-1, order='F') MeI = mesh.get_edge_inner_product(invert_matrix=True) M_be = mesh.boundary_edge_vector_integral Mf = mesh.get_face_inner_product() A = Mf @ C @ MeI @ C.T @ Mf + Mf rhs = Mf @ q_ana + Mf @ C @ MeI @ M_be @ e_bc elif "Edge" in self.myTest: e_ana = mesh.project_edge_vector(e_fun(mesh.edges)) q_ana = mesh.project_edge_vector(q_fun(mesh.edges)) h_bc = h_fun(mesh.boundary_edges).reshape(-1, order='F') Mf = mesh.get_face_inner_product() Me = mesh.get_edge_inner_product() M_be = mesh.boundary_edge_vector_integral A = C.T @ Mf @ C + Me rhs = Me @ q_ana + M_be * h_bc e_test = Pardiso(A, is_symmetric=True, is_positive_definite=True) * rhs diff = e_test - e_ana if "Face" in self.myTest: if "Curv" in self._meshType or "Tree" in self._meshType: err = np.linalg.norm(Mf * diff) else: err = np.linalg.norm(e_test - e_ana) / np.sqrt(mesh.n_faces) elif "Edge" in self.myTest: if "Curv" in self._meshType or "Tree" in self._meshType: err = np.linalg.norm(Me * diff) else: err = np.linalg.norm(e_test - e_ana) / np.sqrt(mesh.n_edges) return err
def solve_2D_potentials(rho1, rho2, h, A, B): """ Here we solve the 2D DC problem for potentials (using SimPEG Mesh Class) """ sigma = 1.0 / rho2 * np.ones(mesh.nC) sigma[mesh.gridCC[:, 1] >= -h] = 1.0 / rho1 # since the model is 2D q = np.zeros(mesh.nC) a = utils.closestPoints(mesh, A[:2]) q[a] = 1.0 / mesh.vol[a] if B is not None: b = utils.closestPoints(mesh, B[:2]) q[b] = -1.0 / mesh.vol[b] # Use a Neumann Boundary Condition (so pole source is reasonable) fxm, fxp, fym, fyp = mesh.faceBoundaryInd n_xm = fxm.sum() n_xp = fxp.sum() n_ym = fym.sum() n_yp = fyp.sum() xBC_xm = np.zeros(n_xm) # 0.5*a_xm xBC_xp = np.zeros(n_xp) # 0.5*a_xp/b_xp yBC_xm = np.ones(n_xm) # 0.5*(1.-b_xm) yBC_xp = np.ones(n_xp) # 0.5*(1.-1./b_xp) xBC_ym = np.zeros(n_ym) # 0.5*a_ym xBC_yp = np.zeros(n_yp) # 0.5*a_yp/b_yp yBC_ym = np.ones(n_ym) # 0.5*(1.-b_ym) yBC_yp = np.ones(n_yp) # 0.5*(1.-1./b_yp) sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]]) sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]]) xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx] xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy] yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx] yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy] x_BC = np.r_[xBC_x, xBC_y] y_BC = np.r_[yBC_x, yBC_y] V = utils.sdiag(mesh.vol) Div = V * mesh.faceDiv P_BC, B = mesh.getBCProjWF_simple() M = B * mesh.aveCC2F Grad = Div.T - P_BC * utils.sdiag(y_BC) * M A = (Div * utils.sdiag(1.0 / (mesh.dim * mesh.aveF2CC.T * (1.0 / sigma))) * Grad) A[0, 0] = A[0, 0] + 1. # Because Neumann Ainv = Pardiso(A) V = Ainv * q return V
def test(self): rhs = self.rhs sol = self.sol Ainv = Pardiso(self.A, is_symmetric=True, check_accuracy=True) self.assertRaises(Exception, lambda: Ainv * rhs) Ainv.clean() Ainv = Pardiso(self.A) for i in range(3): self.assertLess(np.linalg.norm(Ainv * rhs[:, i] - sol[:, i]), TOL) self.assertLess(np.linalg.norm(Ainv * rhs - sol, np.inf), TOL) Ainv.clean()
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 if self._meshType == "rotateCurv": nodes_x, nodes_y, nodes_z = mesh.node_list nodes_x -= 0.25 nodes_y -= 0.25 nodes_z -= 0.25 mesh = discretize.CurvilinearMesh([nodes_x, nodes_y, nodes_z]) else: mesh.origin = np.r_[-0.25, -0.25, -0.25] phi_ana = phi(mesh.nodes) q_ana = q_fun(mesh.nodes) j_ana = np.r_[j_funX(mesh.edges_x), j_funY(mesh.edges_y), j_funZ(mesh.edges_z)] if self.boundary_type == "Nuemann": # Nuemann with J defined at boundary nodes jx_bc = j_funX(mesh.boundary_nodes) jy_bc = j_funY(mesh.boundary_nodes) jz_bc = j_funZ(mesh.boundary_nodes) j_bc = np.c_[jx_bc, jy_bc, jz_bc] M_bn = mesh.boundary_node_vector_integral B_bc = sp.csr_matrix((mesh.n_nodes, mesh.n_nodes)) b_bc = M_bn @ (j_bc.reshape(-1, order='F')) else: 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) # construct matrix with robin operator if self.boundary_type == "Robin": alpha = 1.0 else: # get indices of x0, y0 and z0 boundaries n_boundary_faces = len(j_bc_dot_n) robin_locs = np.any(mesh.boundary_faces == -0.25, axis=1) alpha = np.zeros(n_boundary_faces) alpha[robin_locs] = 1.0 beta = 1.0 gamma = alpha * phi_bc + beta * j_bc_dot_n B_bc, b_bc = mesh.edge_divergence_weak_form_robin( alpha, beta, gamma) Me = mesh.get_edge_inner_product() Mn = sp.diags(mesh.average_node_to_cell.T @ mesh.cell_volumes) G = mesh.nodal_gradient A = -G.T @ Me @ G + B_bc rhs = Mn @ q_ana - b_bc if self.boundary_type == "Nuemann": A[0, :] = 0.0 A[0, 0] = 1.0 rhs[0] = phi_ana[0] phi_test = Pardiso(A) * rhs if self.boundary_type == "Nuemann": # set them both to have a 0 mean phi_test -= phi_test.mean() phi_ana -= phi_ana.mean() err = np.linalg.norm(phi_test - phi_ana) / np.sqrt(mesh.n_nodes) return err
def test(self): rhs = self.rhs Ainv = Pardiso(self.A, check_accuracy=True) sol = Ainv * rhs sol = Ainv * rhs.real