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
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
def getError(self): # Test function def phi_fun(x): return np.cos(np.pi * x) def j_fun(x): return np.pi * np.sin(np.pi * x) def phi_deriv(x): return -j_fun(x) def q_fun(x): return (np.pi**2) * np.cos(np.pi * x) xc_ana = phi_fun(self.M.gridCC) q_ana = q_fun(self.M.gridCC) j_ana = j_fun(self.M.gridFx) # Get boundary locations vecN = self.M.vectorNx vecC = self.M.vectorCCx # Setup Mixed B.C (alpha, beta, gamma) alpha_xm, alpha_xp = 1., 1. beta_xm, beta_xp = 1., 1. alpha = np.r_[alpha_xm, alpha_xp] beta = np.r_[beta_xm, beta_xp] vecN = self.M.vectorNx vecC = self.M.vectorCCx phi_bc = phi_fun(vecN[[0, -1]]) phi_deriv_bc = phi_deriv(vecN[[0, -1]]) gamma = alpha * phi_bc + beta * phi_deriv_bc x_BC, y_BC = getxBCyBC_CC(self.M, alpha, beta, gamma) sigma = np.ones(self.M.nC) Mfrho = self.M.getFaceInnerProduct(1. / sigma) MfrhoI = self.M.getFaceInnerProduct(1. / sigma, invMat=True) V = discretize.utils.sdiag(self.M.vol) Div = V * self.M.faceDiv P_BC, B = self.M.getBCProjWF_simple() q = q_fun(self.M.gridCC) M = B * self.M.aveCC2F G = Div.T - P_BC * discretize.utils.sdiag(y_BC) * M # Mrhoj = D.T V phi + P_BC*discretize.utils.sdiag(y_BC)*M phi - P_BC*x_BC rhs = V * q + Div * MfrhoI * P_BC * x_BC A = Div * MfrhoI * G if self.myTest == 'xc': # TODO: fix the null space Ainv = Solver(A) xc = Ainv * rhs err = np.linalg.norm((xc - xc_ana), np.inf) else: NotImplementedError return err
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 # get indices of x0 boundary and y0 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 = 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
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
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.sin(np.pi * x) j_fun = lambda x: np.pi * np.cos(np.pi * x) q_fun = lambda x: -1 * (np.pi**2) * phi(x) mesh = self.M mesh.origin = [ -0.25, ] phi_ana = phi(mesh.nodes) j_ana = j_fun(mesh.edges_x) q_ana = q_fun(mesh.nodes) phi_bc = phi(mesh.boundary_nodes) j_bc = j_fun(mesh.boundary_nodes) # construct matrix with robin operator beta = 1.0 if self.boundary_type == "Robin": alpha = 1.0 elif self.boundary_type == "Mixed": alpha = np.r_[1.0, 0.0] else: alpha = 0.0 gamma = alpha * phi_bc + beta * j_bc * mesh.boundary_face_outward_normals Me = mesh.get_edge_inner_product() Mn = sp.diags(mesh.average_node_to_cell.T @ mesh.cell_volumes) G = mesh.nodal_gradient B_bc, b_bc = mesh.edge_divergence_weak_form_robin(alpha, beta, gamma) 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 = Solver(A) * rhs err = np.linalg.norm(phi_test - phi_ana, np.inf) return err
def getError(self): # Create some functions to integrate fun = lambda x: np.sin(2*np.pi*x[:, 0])*np.sin(2*np.pi*x[:, 1])*np.sin(2*np.pi*x[:, 2]) sol = lambda x: -3.*((2*np.pi)**2)*fun(x) self.M.setCellGradBC('dirichlet') D = self.M.faceDiv G = self.M.cellGrad if self.forward: sA = sol(self.M.gridCC) sN = D*G*fun(self.M.gridCC) err = np.linalg.norm((sA - sN), np.inf) else: fA = fun(self.M.gridCC) fN = Solver(D*G) * (sol(self.M.gridCC)) err = np.linalg.norm((fA - fN), np.inf) return err
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.cos(np.pi * x[:, 1]) * np.sin(np.pi * x[:, 0]) q_fun = lambda x: -2 * (np.pi**2) * phi(x) mesh = self.M if self._meshType == "rotateCurv": nodes_x, nodes_y = mesh.node_list nodes_x -= 0.25 nodes_y -= 0.25 mesh = discretize.CurvilinearMesh([nodes_x, nodes_y]) else: mesh.origin = np.r_[-0.25, -0.25] phi_ana = phi(mesh.nodes) q_ana = q_fun(mesh.nodes) 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) j_bc = np.c_[jx_bc, jy_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) j_bc = np.c_[jx_bc, jy_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 boundary and y0 boundary 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 = Solver(A) * rhs err = np.linalg.norm(phi_test - phi_ana, np.inf) return err
def run(plotIt=True, n=60): np.random.seed(5) # Here we are going to rearrange the equations: # (phi_ - phi)/dt = A*(d2fdphi2*(phi_ - phi) + dfdphi - L*phi_) # (phi_ - phi)/dt = A*(d2fdphi2*phi_ - d2fdphi2*phi + dfdphi - L*phi_) # (phi_ - phi)/dt = A*d2fdphi2*phi_ + A*( - d2fdphi2*phi + dfdphi - L*phi_) # phi_ - phi = dt*A*d2fdphi2*phi_ + dt*A*(- d2fdphi2*phi + dfdphi - L*phi_) # phi_ - dt*A*d2fdphi2 * phi_ = dt*A*(- d2fdphi2*phi + dfdphi - L*phi_) + phi # (I - dt*A*d2fdphi2) * phi_ = dt*A*(- d2fdphi2*phi + dfdphi - L*phi_) + phi # (I - dt*A*d2fdphi2) * phi_ = dt*A*dfdphi - dt*A*d2fdphi2*phi - dt*A*L*phi_ + phi # (dt*A*d2fdphi2 - I) * phi_ = dt*A*d2fdphi2*phi + dt*A*L*phi_ - phi - dt*A*dfdphi # (dt*A*d2fdphi2 - I - dt*A*L) * phi_ = (dt*A*d2fdphi2 - I)*phi - dt*A*dfdphi h = [(0.25, n)] M = discretize.TensorMesh([h, h]) # Constants D = a = epsilon = 1. I = discretize.utils.speye(M.nC) # Operators A = D * M.faceDiv * M.cellGrad L = epsilon**2 * M.faceDiv * M.cellGrad duration = 75 elapsed = 0. dexp = -5 phi = np.random.normal(loc=0.5, scale=0.01, size=M.nC) ii, jj = 0, 0 PHIS = [] capture = np.logspace(-1, np.log10(duration), 8) while elapsed < duration: dt = min(100, np.exp(dexp)) elapsed += dt dexp += 0.05 dfdphi = a**2 * 2 * phi * (1 - phi) * (1 - 2 * phi) d2fdphi2 = discretize.utils.sdiag(a**2 * 2 * (1 - 6 * phi * (1 - phi))) MAT = (dt * A * d2fdphi2 - I - dt * A * L) rhs = (dt * A * d2fdphi2 - I) * phi - dt * A * dfdphi phi = Solver(MAT) * rhs if elapsed > capture[jj]: PHIS += [(elapsed, phi.copy())] jj += 1 if ii % 10 == 0: print(ii, elapsed) ii += 1 if plotIt: fig, axes = plt.subplots(2, 4, figsize=(14, 6)) axes = np.array(axes).flatten().tolist() for ii, ax in zip(np.linspace(0, len(PHIS) - 1, len(axes)), axes): ii = int(ii) M.plotImage(PHIS[ii][1], ax=ax) ax.axis('off') ax.set_title('Elapsed Time: {0:4.1f}'.format(PHIS[ii][0]))
def getError(self): # Test function def phi_fun(x): return (np.cos(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) * np.cos(np.pi * x[:, 2])) def j_funX(x): return (np.pi * np.sin(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) * np.cos(np.pi * x[:, 2])) def j_funY(x): return (np.pi * np.cos(np.pi * x[:, 0]) * np.sin(np.pi * x[:, 1]) * np.cos(np.pi * x[:, 2])) def j_funZ(x): return (np.pi * np.cos(np.pi * x[:, 0]) * np.cos(np.pi * x[:, 1]) * np.sin(np.pi * x[:, 2])) def phideriv_funX(x): return -j_funX(x) def phideriv_funY(x): return -j_funY(x) def phideriv_funZ(x): return -j_funZ(x) def q_fun(x): return 3 * (np.pi**2) * phi_fun(x) xc_ana = phi_fun(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, jY_ana] # Get boundary locations fxm, fxp, fym, fyp, fzm, fzp = self.M.faceBoundaryInd gBFxm = self.M.gridFx[fxm, :] gBFxp = self.M.gridFx[fxp, :] gBFym = self.M.gridFy[fym, :] gBFyp = self.M.gridFy[fyp, :] gBFzm = self.M.gridFz[fzm, :] gBFzp = self.M.gridFz[fzp, :] # Setup Mixed B.C (alpha, beta, gamma) alpha_xm = np.ones_like(gBFxm[:, 0]) alpha_xp = np.ones_like(gBFxp[:, 0]) beta_xm = np.ones_like(gBFxm[:, 0]) beta_xp = np.ones_like(gBFxp[:, 0]) alpha_ym = np.ones_like(gBFym[:, 1]) alpha_yp = np.ones_like(gBFyp[:, 1]) beta_ym = np.ones_like(gBFym[:, 1]) beta_yp = np.ones_like(gBFyp[:, 1]) alpha_zm = np.ones_like(gBFzm[:, 2]) alpha_zp = np.ones_like(gBFzp[:, 2]) beta_zm = np.ones_like(gBFzm[:, 2]) beta_zp = np.ones_like(gBFzp[:, 2]) phi_bc_xm, phi_bc_xp = phi_fun(gBFxm), phi_fun(gBFxp) phi_bc_ym, phi_bc_yp = phi_fun(gBFym), phi_fun(gBFyp) phi_bc_zm, phi_bc_zp = phi_fun(gBFzm), phi_fun(gBFzp) phiderivX_bc_xm = phideriv_funX(gBFxm) phiderivX_bc_xp = phideriv_funX(gBFxp) phiderivY_bc_ym = phideriv_funY(gBFym) phiderivY_bc_yp = phideriv_funY(gBFyp) phiderivY_bc_zm = phideriv_funZ(gBFzm) phiderivY_bc_zp = phideriv_funZ(gBFzp) def gamma_fun(alpha, beta, phi, phi_deriv): return alpha * phi + beta * phi_deriv gamma_xm = gamma_fun(alpha_xm, beta_xm, phi_bc_xm, phiderivX_bc_xm) gamma_xp = gamma_fun(alpha_xp, beta_xp, phi_bc_xp, phiderivX_bc_xp) gamma_ym = gamma_fun(alpha_ym, beta_ym, phi_bc_ym, phiderivY_bc_ym) gamma_yp = gamma_fun(alpha_yp, beta_yp, phi_bc_yp, phiderivY_bc_yp) gamma_zm = gamma_fun(alpha_zm, beta_zm, phi_bc_zm, phiderivY_bc_zm) gamma_zp = gamma_fun(alpha_zp, beta_zp, phi_bc_zp, phiderivY_bc_zp) alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp] beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp] gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp] x_BC, y_BC = getxBCyBC_CC(self.M, alpha, beta, gamma) sigma = np.ones(self.M.nC) Mfrho = self.M.getFaceInnerProduct(1. / sigma) MfrhoI = self.M.getFaceInnerProduct(1. / sigma, invMat=True) V = discretize.utils.sdiag(self.M.vol) Div = V * self.M.faceDiv P_BC, B = self.M.getBCProjWF_simple() q = q_fun(self.M.gridCC) M = B * self.M.aveCC2F G = Div.T - P_BC * discretize.utils.sdiag(y_BC) * M rhs = V * q + Div * MfrhoI * P_BC * x_BC A = Div * MfrhoI * G if self.myTest == 'xc': # TODO: fix the null space Ainv = Solver(A) xc = Ainv * rhs err = np.linalg.norm((xc - xc_ana), np.inf) else: NotImplementedError return err