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
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.0 / 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
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', showIt=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
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
def DCfun(mesh, pts): D = mesh.faceDiv G = D.T sigma = 1e-2*np.ones(mesh.nC) Msigi = mesh.getFaceInnerProduct(1./sigma) MsigI = Utils.sdInv(Msigi) A = D*MsigI*G A[-1,-1] /= mesh.vol[-1] # Remove null space rhs = np.zeros(mesh.nC) txind = Utils.meshutils.closestPoints(mesh, pts) rhs[txind] = np.r_[1,-1] return A, rhs
def DCfun(mesh, pts): D = mesh.faceDiv G = D.T sigma = 1e-2 * np.ones(mesh.nC) Msigi = mesh.getFaceInnerProduct(1. / sigma) MsigI = Utils.sdInv(Msigi) A = D * MsigI * G A[-1, -1] /= mesh.vol[-1] # Remove null space rhs = np.zeros(mesh.nC) txind = Utils.meshutils.closestPoints(mesh, pts) rhs[txind] = np.r_[1, -1] return A, rhs
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
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', showIt=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
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
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
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.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) if prop.size == self.nC: Av = getattr(self, 'ave' + projType + '2CC') Vprop = self.vol * Utils.mkvc(prop) M = self.dim * Utils.sdiag(Av.T * Vprop) elif prop.size == self.nC * self.dim: Av = getattr(self, 'ave' + projType + '2CCV') V = sp.kron(sp.identity(self.dim), 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
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.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) if prop.size == self.nC: Av = getattr(self, 'ave'+projType+'2CC') Vprop = self.vol * Utils.mkvc(prop) M = self.dim * Utils.sdiag(Av.T * Vprop) elif prop.size == self.nC*self.dim: Av = getattr(self, 'ave'+projType+'2CCV') V = sp.kron(sp.identity(self.dim), 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
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 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