示例#1
0
    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