예제 #1
0
 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)
예제 #2
0
 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)
예제 #3
0
 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)
예제 #4
0
 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
예제 #5
0
    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
예제 #6
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
예제 #7
0
 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
예제 #8
0
    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
예제 #9
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)

        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
예제 #10
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
        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
예제 #11
0
    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
예제 #12
0
 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
예제 #13
0
 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
예제 #14
0
 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
예제 #15
0
 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
예제 #16
0
 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
예제 #17
0
    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]])
예제 #18
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
예제 #19
0
 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
예제 #20
0
    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
예제 #21
0
    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
예제 #22
0
    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]
예제 #23
0
    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]
예제 #24
0
    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
예제 #25
0
    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
예제 #26
0
    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
예제 #27
0
    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]])
예제 #28
0
 def simpleFail(x):
     return np.sin(x), -sdiag(np.cos(x))
예제 #29
0
 def simpleFunction(x):
     return np.sin(x), lambda xi: sdiag(np.cos(x)) * xi
예제 #30
0
 def simplePass(x):
     return np.sin(x), sdiag(np.cos(x))