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