Exemple #1
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
Exemple #2
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
Exemple #3
0
    def _getInnerProduct(self, projType, prop=None, invProp=False, invMat=False, doFast=True):
        """get the inner product matrix

        Parameters
        ----------

        str : projType
            'F' for faces 'E' for edges

        numpy.ndarray : prop
            material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))

        bool : invProp
            inverts the material property

        bool : invMat
            inverts the matrix

        bool : doFast
            do a faster implementation if available.


        Returns
        -------

        scipy.sparse.csr_matrix
            M, the inner product matrix (nE, nE)

        """
        assert projType in ['F', 'E'], "projType must be 'F' for faces or 'E' for edges"

        fast = None
        if hasattr(self, '_fastInnerProduct') and doFast:
            fast = self._fastInnerProduct(projType, prop=prop, invProp=invProp, invMat=invMat)
        if fast is not None:
            return fast

        if invProp:
            prop = invPropertyTensor(self, prop)

        tensorType = TensorType(self, prop)

        Mu = makePropertyTensor(self, prop)
        Ps = self._getInnerProductProjectionMatrices(projType, tensorType)
        A = np.sum([P.T * Mu * P for P in Ps])

        if invMat and tensorType < 3:
            A = sdInv(A)
        elif invMat and tensorType == 3:
            raise Exception('Solver needed to invert A.')

        return A
Exemple #4
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
Exemple #5
0
    def getError(self):
        #Test function
        phi = lambda x: np.cos(0.5 * np.pi * x[:, 0]) * np.cos(0.5 * np.pi *
                                                               x[:, 1])
        j_funX = lambda x: -0.5 * np.pi * np.sin(
            0.5 * np.pi * x[:, 0]) * np.cos(0.5 * np.pi * x[:, 1])
        j_funY = lambda x: -0.5 * np.pi * np.cos(
            0.5 * np.pi * x[:, 0]) * np.sin(0.5 * np.pi * x[:, 1])
        q_fun = lambda x: -2 * ((0.5 * 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

        cxm, cxp, cym, cyp = self.M.cellBoundaryInd
        fxm, fxp, fym, fyp = self.M.faceBoundaryInd

        gBFx = self.M.gridFx[(fxm | fxp), :]
        gBFy = self.M.gridFy[(fym | fyp), :]

        gBCx = self.M.gridCC[(cxm | cxp), :]
        gBCy = self.M.gridCC[(cym | cyp), :]

        phi_bc = phi(np.r_[gBCx, gBCy])
        j_bc = np.r_[j_funX(gBFx), j_funY(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', 'neumann'],
                                           ['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

        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 _fastInnerProduct(
        self, projType, prop=None, invProp=False, invMat=False
    ):
        """
            Fast version of getFaceInnerProduct.
            This does not handle the case of a full tensor prop.

            :param numpy.array prop: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
            :param str projType: 'E' or 'F'
            :param bool returnP: returns the projection matrices
            :param bool invProp: inverts the material property
            :param bool invMat: inverts the matrix
            :rtype: scipy.sparse.csr_matrix
            :return: M, the inner product matrix (nF, nF)
        """
        assert projType in ['F', 'E'], (
            "projType must be 'F' for faces or 'E' for edges"
        )

        if prop is None:
            prop = np.ones(self.nC)

        if invProp:
            prop = 1./prop

        if utils.isScalar(prop):
            prop = prop*np.ones(self.nC)

        # number of elements we are averaging (equals dim for regular
        # meshes, but for cyl, where we use symmetry, it is 1 for edge
        # variables and 2 for face variables)
        if self._meshType == 'CYL':
            n_elements = np.sum(getattr(self, 'vn'+projType).nonzero())
        else:
            n_elements = self.dim

        # Isotropic? or anisotropic?
        if prop.size == self.nC:
            Av = getattr(self, 'ave'+projType+'2CC')
            Vprop = self.vol * utils.mkvc(prop)
            M = n_elements * utils.sdiag(Av.T * Vprop)

        elif prop.size == self.nC*self.dim:
            Av = getattr(self, 'ave'+projType+'2CCV')

            # if cyl, then only certain components are relevant due to symmetry
            # for faces, x, z matters, for edges, y (which is theta) matters
            if self._meshType == 'CYL':
                if projType == 'E':
                    prop = prop[:, 1]  # this is the action of a projection mat
                elif projType == 'F':
                    prop = prop[:, [0, 2]]

            V = sp.kron(sp.identity(n_elements), utils.sdiag(self.vol))
            M = utils.sdiag(Av.T * V * utils.mkvc(prop))
        else:
            return None

        if invMat:
            return utils.sdInv(M)
        else:
            return M