def write_output(self, pb=None, writemesh=False, N=1, t=0): if writemesh: if self.write_results_every > 0: self.resultsfiles = {} for res in self.results_to_write: outfile = XDMFFile( self.comm, self.output_path + '/results_' + pb.simname + '_' + res + '.xdmf', 'w') outfile.write_mesh(self.mesh) self.resultsfiles[res] = outfile return else: # write results every write_results_every steps if self.write_results_every > 0 and N % self.write_results_every == 0: # save solution to XDMF format for res in self.results_to_write: if res == 'velocity': self.resultsfiles[res].write_function(pb.v, t) elif res == 'acceleration': # passed in a is not a function but form, so we have to project a_proj = project(pb.acc, pb.V_v, pb.dx_, nm="Acceleration") self.resultsfiles[res].write_function(a_proj, t) elif res == 'pressure': self.resultsfiles[res].write_function(pb.p, t) elif res == 'cauchystress': stressfuncs = [] for n in range(pb.num_domains): stressfuncs.append(pb.ma[n].sigma(pb.v, pb.p)) cauchystress = project(stressfuncs, pb.Vd_tensor, pb.dx_, nm="CauchyStress") self.resultsfiles[res].write_function(cauchystress, t) elif res == 'reynolds': reynolds = project(re, pb.Vd_scalar, pb.dx_, nm="Reynolds") self.resultsfiles[res].write_function(reynolds, t) else: raise NameError( "Unknown output to write for fluid mechanics!")
solver.max_it = 200 solver.report = True ksp = solver.krylov_solver opts = PETSc.Options() opts.getAll() opts.view() option_prefix = ksp.getOptionsPrefix() opts[f"{option_prefix}ksp_type"] = "preonly" opts[f"{option_prefix}pc_type"] = "lu" opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps" ksp.setFromOptions() wfil = XDMFFile(comm, "disp_Visco_0_05_realEta_Fixed.xdmf", "w") wfil.write_mesh(mesh) with open("sfiles.txt", "w") as fil: fil.write(f"0.0, 0.0\n") for i, t in enumerate(timeVals): right_disp.value = stretchVals[i] print(f"Load step: {i+1}") set_output_file("viscoTrialrunW.log") num_its, converged = solver.solve(u) print(f"Newton iteration: {num_its}") dl_interp(CC, C) k_terms(dt, C, Cn, Cvn, C_quart, C_half, C_thr_quart, CCv, k_cache) CCv.vector.copy(result=Cv_iter.vector) CCv.x.scatter_forward()
solver.convergence_criterion = "incremental" solver.rtol = 1e-6 # The setting of ``convergence_criterion`` to ``"incremental"`` specifies # that the Newton solver should compute a norm of the solution increment # to check for convergence (the other possibility is to use # ``"residual"``, or to provide a user-defined check). The tolerance for # convergence is specified by ``rtol``. # # To run the solver and save the output to a VTK file for later # visualization, the solver is advanced in time from :math:`t_{n}` to # :math:`t_{n+1}` until a terminal time :math:`T` is reached:: # Output file file = XDMFFile(MPI.COMM_WORLD, "output.xdmf", "w") file.write_mesh(mesh) # Step in time t = 0.0 # Check if we are running on CI server and reduce run time if "CI" in os.environ.keys() or "GITHUB_ACTIONS" in os.environ.keys(): T = 3 * dt else: T = 50 * dt u.vector.copy(result=u0.vector) u0.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) while (t < T):
def solve(f0, f1, u, v, dt, num_steps): """Solve problem using the Runge Kutta method""" # Create solution vectors at RK intermediate stages un, vn = u.vector.copy(), v.vector.copy() # Solution at start of time step u0, v0 = u.vector.copy(), v.vector.copy() # Get Runge-Kutta timestepping data n_RK, a_runge, b_runge, c_runge = butcher(4) # Create lists to hold intermediate vectors ku, kv = n_RK * [None], n_RK * [None] file = XDMFFile(MPI.COMM_WORLD, "u.xdmf", "w") file.write_mesh(u.function_space.mesh) file.write_function(u, t=0.0) # print("Num dofs:", u.vector.size) t = 0.0 # loop_start = time.time() for step in range(num_steps): # print("Time step:", step, t, dt) # Store solution at start of time step as u0 and v0 u0 = u.vector.copy(result=u0) v0 = v.vector.copy(result=v0) # Runge Kutta steps, # https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods#Explicit_Runge%E2%80%93Kutta_methods for i in range(n_RK): un = u0.copy(result=un) vn = v0.copy(result=vn) for j in range(i): a = dt * a_runge[i, j] un.axpy(a, ku[j]) vn.axpy(a, kv[j]) # RK evaluation time tn = t + c_runge[i] * dt # Compute RHS vector ku[i] = f0(tn, un, vn, result=ku[i]) kv[i] = f1(tn, un, vn, result=kv[i]) # Update solution u.vector.axpy(dt * b_runge[i], ku[i]) v.vector.axpy(dt * b_runge[i], kv[i]) # Update time t += dt if step % 10 == 0: file.write_function(u, t=t) # print("Norm to file (u):", u.vector.norm()) # end = time.time() # print("RK time:", end - loop_start) # print("RK time per step:", (end - loop_start) / num_steps) return u
def write_output(self, pb, writemesh=False, N=1, t=0): if writemesh: if self.write_results_every > 0: self.resultsfiles = {} for res in self.results_to_write: outfile = XDMFFile(self.comm, self.output_path+'/results_'+pb.simname+'_'+res+'.xdmf', 'w') outfile.write_mesh(self.mesh) self.resultsfiles[res] = outfile return else: # write results every write_results_every steps if self.write_results_every > 0 and N % self.write_results_every == 0: # save solution to XDMF format for res in self.results_to_write: if res=='displacement': self.resultsfiles[res].write_function(pb.u, t) elif res=='velocity': # passed in v is not a function but form, so we have to project v_proj = project(pb.vel, pb.V_u, pb.dx_, nm="Velocity") self.resultsfiles[res].write_function(v_proj, t) elif res=='acceleration': # passed in a is not a function but form, so we have to project a_proj = project(pb.acc, pb.V_u, pb.dx_, nm="Acceleration") self.resultsfiles[res].write_function(a_proj, t) elif res=='pressure': self.resultsfiles[res].write_function(pb.p, t) elif res=='cauchystress': stressfuncs=[] for n in range(pb.num_domains): stressfuncs.append(pb.ma[n].sigma(pb.u,pb.p,ivar=pb.internalvars)) cauchystress = project(stressfuncs, pb.Vd_tensor, pb.dx_, nm="CauchyStress") self.resultsfiles[res].write_function(cauchystress, t) elif res=='trmandelstress': stressfuncs=[] for n in range(pb.num_domains): stressfuncs.append(tr(pb.ma[n].M(pb.u,pb.p,ivar=pb.internalvars))) trmandelstress = project(stressfuncs, pb.Vd_scalar, pb.dx_, nm="trMandelStress") self.resultsfiles[res].write_function(trmandelstress, t) elif res=='trmandelstress_e': stressfuncs=[] for n in range(pb.num_domains): if pb.mat_growth[n]: stressfuncs.append(tr(pb.ma[n].M_e(pb.u,pb.p,pb.ki.C(pb.u),ivar=pb.internalvars))) else: stressfuncs.append(as_ufl(0)) trmandelstress_e = project(stressfuncs, pb.Vd_scalar, pb.dx_, nm="trMandelStress_e") self.resultsfiles[res].write_function(trmandelstress_e, t) elif res=='vonmises_cauchystress': stressfuncs=[] for n in range(pb.num_domains): stressfuncs.append(pb.ma[n].sigma_vonmises(pb.u,pb.p,ivar=pb.internalvars)) vonmises_cauchystress = project(stressfuncs, pb.Vd_scalar, pb.dx_, nm="vonMises_CauchyStress") self.resultsfiles[res].write_function(vonmises_cauchystress, t) elif res=='pk1stress': stressfuncs=[] for n in range(pb.num_domains): stressfuncs.append(pb.ma[n].P(pb.u,pb.p,ivar=pb.internalvars)) pk1stress = project(stressfuncs, pb.Vd_tensor, pb.dx_, nm="PK1Stress") self.resultsfiles[res].write_function(pk1stress, t) elif res=='pk2stress': stressfuncs=[] for n in range(pb.num_domains): stressfuncs.append(pb.ma[n].S(pb.u,pb.p,ivar=pb.internalvars)) pk2stress = project(stressfuncs, pb.Vd_tensor, pb.dx_, nm="PK2Stress") self.resultsfiles[res].write_function(pk2stress, t) elif res=='jacobian': jacobian = project(pb.ki.J(pb.u), pb.Vd_scalar, pb.dx_, nm="Jacobian") self.resultsfiles[res].write_function(jacobian, t) elif res=='glstrain': glstrain = project(pb.ki.E(pb.u), pb.Vd_tensor, pb.dx_, nm="GreenLagrangeStrain") self.resultsfiles[res].write_function(glstrain, t) elif res=='eastrain': eastrain = project(pb.ki.e(pb.u), pb.Vd_tensor, pb.dx_, nm="EulerAlmansiStrain") self.resultsfiles[res].write_function(eastrain, t) elif res=='fiberstretch': fiberstretch = project(pb.ki.fibstretch(pb.u,pb.fib_func[0]), pb.Vd_scalar, pb.dx_, nm="FiberStretch") self.resultsfiles[res].write_function(fiberstretch, t) elif res=='fiberstretch_e': stretchfuncs=[] for n in range(pb.num_domains): if pb.mat_growth[n]: stretchfuncs.append(pb.ma[n].fibstretch_e(pb.ki.C(pb.u),pb.theta,pb.fib_func[0])) else: stretchfuncs.append(as_ufl(0)) fiberstretch_e = project(stretchfuncs, pb.Vd_scalar, pb.dx_, nm="FiberStretch_e") self.resultsfiles[res].write_function(fiberstretch_e, t) elif res=='theta': self.resultsfiles[res].write_function(pb.theta, t) elif res=='phi_remod': phifuncs=[] for n in range(pb.num_domains): if pb.mat_remodel[n]: phifuncs.append(pb.ma[n].phi_remod(pb.theta)) else: phifuncs.append(as_ufl(0)) phiremod = project(phifuncs, pb.Vd_scalar, pb.dx_, nm="phiRemodel") self.resultsfiles[res].write_function(phiremod, t) elif res=='tau_a': self.resultsfiles[res].write_function(pb.tau_a, t) elif res=='fiber1': fiber1 = project(pb.fib_func[0], pb.Vd_vector, pb.dx_, nm="Fiber1") self.resultsfiles[res].write_function(fiber1, t) elif res=='fiber2': fiber2 = project(pb.fib_func[1], pb.Vd_vector, pb.dx_, nm="Fiber2") self.resultsfiles[res].write_function(fiber2, t) else: raise NameError("Unknown output to write for solid mechanics!") if self.write_restart_every > 0 and N % self.write_restart_every == 0: self.writecheckpoint(pb, N)
def demo_stacked_cubes(outfile: XDMFFile, theta: float, gmsh: bool = True, quad: bool = False, compare: bool = False, res: float = 0.1): log_info( f"Run theta:{theta:.2f}, Quad: {quad}, Gmsh {gmsh}, Res {res:.2e}") celltype = "quadrilateral" if quad else "triangle" if gmsh: mesh, mt = gmsh_2D_stacked(celltype, theta) mesh.name = f"mesh_{celltype}_{theta:.2f}_gmsh" else: mesh_name = "mesh" filename = f"meshes/mesh_{celltype}_{theta:.2f}.xdmf" mesh_2D_dolfin(celltype, theta) with XDMFFile(MPI.COMM_WORLD, filename, "r") as xdmf: mesh = xdmf.read_mesh(name=mesh_name) mesh.name = f"mesh_{celltype}_{theta:.2f}" tdim = mesh.topology.dim fdim = tdim - 1 mesh.topology.create_connectivity(tdim, tdim) mesh.topology.create_connectivity(fdim, tdim) mt = xdmf.read_meshtags(mesh, name="facet_tags") # Helper until meshtags can be read in from xdmf V = VectorFunctionSpace(mesh, ("Lagrange", 1)) r_matrix = rotation_matrix([0, 0, 1], theta) g_vec = np.dot(r_matrix, [0, -1.25e2, 0]) g = Constant(mesh, PETSc.ScalarType(g_vec[:2])) def bottom_corner(x): return np.isclose(x, [[0], [0], [0]]).all(axis=0) # Fix bottom corner bc_value = np.array((0, ) * mesh.geometry.dim, dtype=PETSc.ScalarType) bottom_dofs = locate_dofs_geometrical(V, bottom_corner) bc_bottom = dirichletbc(bc_value, bottom_dofs, V) bcs = [bc_bottom] # Elasticity parameters E = PETSc.ScalarType(1.0e3) nu = 0 mu = Constant(mesh, E / (2.0 * (1.0 + nu))) lmbda = Constant(mesh, E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))) # Stress computation def sigma(v): return (2.0 * mu * sym(grad(v)) + lmbda * tr(sym(grad(v))) * Identity(len(v))) # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(sigma(u), grad(v)) * dx ds = Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=3) rhs = inner(Constant(mesh, PETSc.ScalarType( (0, 0))), v) * dx + inner(g, v) * ds def left_corner(x): return np.isclose(x.T, np.dot(r_matrix, [0, 2, 0])).all(axis=1) # Create multi point constraint mpc = MultiPointConstraint(V) with Timer("~Contact: Create contact constraint"): nh = create_normal_approximation(V, mt, 4) mpc.create_contact_slip_condition(mt, 4, 9, nh) with Timer("~Contact: Add non-slip condition at bottom interface"): bottom_normal = facet_normal_approximation(V, mt, 5) mpc.create_slip_constraint(V, (mt, 5), bottom_normal, bcs=bcs) with Timer("~Contact: Add tangential constraint at one point"): vertex = locate_entities_boundary(mesh, 0, left_corner) tangent = facet_normal_approximation(V, mt, 3, tangent=True) mtv = meshtags(mesh, 0, vertex, np.full(len(vertex), 6, dtype=np.int32)) mpc.create_slip_constraint(V, (mtv, 6), tangent, bcs=bcs) mpc.finalize() rtol = 1e-9 petsc_options = { "ksp_rtol": 1e-9, "pc_type": "gamg", "pc_gamg_type": "agg", "pc_gamg_square_graph": 2, "pc_gamg_threshold": 0.02, "pc_gamg_coarse_eq_limit": 1000, "pc_gamg_sym_graph": True, "mg_levels_ksp_type": "chebyshev", "mg_levels_pc_type": "jacobi", "mg_levels_esteig_ksp_type": "cg" # , "help": None, "ksp_view": None } # Solve Linear problem problem = LinearProblem(a, rhs, mpc, bcs=bcs, petsc_options=petsc_options) # Build near nullspace null_space = rigid_motions_nullspace(mpc.function_space) problem.A.setNearNullSpace(null_space) u_h = problem.solve() it = problem.solver.getIterationNumber() if MPI.COMM_WORLD.rank == 0: print("Number of iterations: {0:d}".format(it)) unorm = u_h.vector.norm() if MPI.COMM_WORLD.rank == 0: print(f"Norm of u: {unorm}") # Write solution to file ext = "_gmsh" if gmsh else "" u_h.name = "u_mpc_{0:s}_{1:.2f}{2:s}".format(celltype, theta, ext) outfile.write_mesh(mesh) outfile.write_function(u_h, 0.0, f"Xdmf/Domain/Grid[@Name='{mesh.name}'][1]") # Solve the MPC problem using a global transformation matrix # and numpy solvers to get reference values if not compare: return log_info("Solving reference problem with global matrix (using numpy)") with Timer("~MPC: Reference problem"): # Generate reference matrices and unconstrained solution A_org = assemble_matrix(form(a), bcs) A_org.assemble() L_org = assemble_vector(form(rhs)) apply_lifting(L_org, [form(a)], [bcs]) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(L_org, bcs) root = 0 with Timer("~MPC: Verification"): compare_mpc_lhs(A_org, problem.A, mpc, root=root) compare_mpc_rhs(L_org, problem.b, mpc, root=root) # Gather LHS, RHS and solution on one process A_csr = gather_PETScMatrix(A_org, root=root) K = gather_transformation_matrix(mpc, root=root) L_np = gather_PETScVector(L_org, root=root) u_mpc = gather_PETScVector(u_h.vector, root=root) if MPI.COMM_WORLD.rank == root: KTAK = K.T * A_csr * K reduced_L = K.T @ L_np # Solve linear system d = scipy.sparse.linalg.spsolve(KTAK, reduced_L) # Back substitution to full solution vector uh_numpy = K @ d assert np.allclose(uh_numpy, u_mpc, rtol=rtol)
def demo_stacked_cubes(outfile: XDMFFile, theta: float, gmsh: bool = False, ct: CellType = CellType.tetrahedron, compare: bool = True, res: float = 0.1, noslip: bool = False): celltype = "hexahedron" if ct == CellType.hexahedron else "tetrahedron" type_ext = "no_slip" if noslip else "slip" mesh_ext = "_gmsh_" if gmsh else "_" log_info(f"Run theta:{theta:.2f}, Cell: {celltype}, GMSH {gmsh}, Noslip: {noslip}") # Read in mesh if gmsh: mesh, mt = gmsh_3D_stacked(celltype, theta, res) tdim = mesh.topology.dim fdim = tdim - 1 mesh.topology.create_connectivity(tdim, tdim) mesh.topology.create_connectivity(fdim, tdim) else: mesh_3D_dolfin(theta, ct, celltype, res) MPI.COMM_WORLD.barrier() with XDMFFile(MPI.COMM_WORLD, f"meshes/mesh_{celltype}_{theta:.2f}.xdmf", "r") as xdmf: mesh = xdmf.read_mesh(name="mesh") tdim = mesh.topology.dim fdim = tdim - 1 mesh.topology.create_connectivity(tdim, tdim) mesh.topology.create_connectivity(fdim, tdim) mt = xdmf.read_meshtags(mesh, "facet_tags") mesh.name = f"mesh_{celltype}_{theta:.2f}{type_ext}{mesh_ext}" # Create functionspaces V = fem.VectorFunctionSpace(mesh, ("Lagrange", 1)) # Define boundary conditions # Bottom boundary is fixed in all directions bottom_dofs = fem.locate_dofs_topological(V, fdim, mt.find(5)) # type: ignore u_bc = np.array((0, ) * mesh.geometry.dim, dtype=PETSc.ScalarType) bc_bottom = fem.dirichletbc(u_bc, bottom_dofs, V) g_vec = np.array([0, 0, -4.25e-1], dtype=PETSc.ScalarType) if not noslip: # Helper for orienting traction r_matrix = rotation_matrix([1 / np.sqrt(2), 1 / np.sqrt(2), 0], -theta) # Top boundary has a given deformation normal to the interface g_vec = np.dot(r_matrix, g_vec) top_dofs = fem.locate_dofs_topological(V, fdim, mt.find(3)) # type: ignore bc_top = fem.dirichletbc(g_vec, top_dofs, V) bcs = [bc_bottom, bc_top] # Elasticity parameters E = PETSc.ScalarType(1.0e3) nu = 0 mu = fem.Constant(mesh, E / (2.0 * (1.0 + nu))) lmbda = fem.Constant(mesh, E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))) # Stress computation def sigma(v): return (2.0 * mu * sym(grad(v)) + lmbda * tr(sym(grad(v))) * Identity(len(v))) # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(sigma(u), grad(v)) * dx # NOTE: Traction deactivated until we have a way of fixing nullspace # g = fem.Constant(mesh, PETSc.ScalarType(g_vec)) # ds = Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=3) rhs = inner(fem.Constant(mesh, PETSc.ScalarType((0, 0, 0))), v) * dx # + inner(g, v) * ds bilinear_form = fem.form(a) linear_form = fem.form(rhs) mpc = MultiPointConstraint(V) if noslip: with Timer("~~Contact: Create non-elastic constraint"): mpc.create_contact_inelastic_condition(mt, 4, 9) else: with Timer("~Contact: Create contact constraint"): nh = create_normal_approximation(V, mt, 4) mpc.create_contact_slip_condition(mt, 4, 9, nh) with Timer("~~Contact: Add data and finialize MPC"): mpc.finalize() # Create null-space null_space = rigid_motions_nullspace(mpc.function_space) num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs with Timer(f"~~Contact: Assemble matrix ({num_dofs})"): A = assemble_matrix(bilinear_form, mpc, bcs=bcs) with Timer(f"~~Contact: Assemble vector ({num_dofs})"): b = assemble_vector(linear_form, mpc) apply_lifting(b, [bilinear_form], [bcs], mpc) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) fem.petsc.set_bc(b, bcs) # Solve Linear problem opts = PETSc.Options() opts["ksp_rtol"] = 1.0e-8 opts["pc_type"] = "gamg" opts["pc_gamg_type"] = "agg" opts["pc_gamg_coarse_eq_limit"] = 1000 opts["pc_gamg_sym_graph"] = True opts["mg_levels_ksp_type"] = "chebyshev" opts["mg_levels_pc_type"] = "jacobi" opts["mg_levels_esteig_ksp_type"] = "cg" opts["matptap_via"] = "scalable" # opts["pc_gamg_square_graph"] = 2 # opts["pc_gamg_threshold"] = 1e-2 # opts["help"] = None # List all available options # opts["ksp_view"] = None # List progress of solver # Create functionspace and build near nullspace A.setNearNullSpace(null_space) solver = PETSc.KSP().create(mesh.comm) solver.setOperators(A) solver.setFromOptions() u_h = fem.Function(mpc.function_space) with Timer("~~Contact: Solve"): solver.solve(b, u_h.vector) u_h.x.scatter_forward() with Timer("~~Contact: Backsubstitution"): mpc.backsubstitution(u_h.vector) it = solver.getIterationNumber() unorm = u_h.vector.norm() num_slaves = MPI.COMM_WORLD.allreduce(mpc.num_local_slaves, op=MPI.SUM) if mesh.comm.rank == 0: num_dofs = V.dofmap.index_map.size_global * V.dofmap.index_map_bs print(f"Number of dofs: {num_dofs}") print(f"Number of slaves: {num_slaves}") print(f"Number of iterations: {it}") print(f"Norm of u {unorm:.5e}") # Write solution to file u_h.name = f"u_{celltype}_{theta:.2f}{mesh_ext}{type_ext}".format(celltype, theta, type_ext, mesh_ext) outfile.write_mesh(mesh) outfile.write_function(u_h, 0.0, f"Xdmf/Domain/Grid[@Name='{mesh.name}'][1]") # Solve the MPC problem using a global transformation matrix # and numpy solvers to get reference values if not compare: return log_info("Solving reference problem with global matrix (using scipy)") with Timer("~~Contact: Reference problem"): A_org = fem.petsc.assemble_matrix(bilinear_form, bcs) A_org.assemble() L_org = fem.petsc.assemble_vector(linear_form) fem.petsc.apply_lifting(L_org, [bilinear_form], [bcs]) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) fem.petsc.set_bc(L_org, bcs) root = 0 with Timer("~~Contact: Compare LHS, RHS and solution"): compare_mpc_lhs(A_org, A, mpc, root=root) compare_mpc_rhs(L_org, b, mpc, root=root) # Gather LHS, RHS and solution on one process A_csr = gather_PETScMatrix(A_org, root=root) K = gather_transformation_matrix(mpc, root=root) L_np = gather_PETScVector(L_org, root=root) u_mpc = gather_PETScVector(u_h.vector, root=root) if MPI.COMM_WORLD.rank == root: KTAK = K.T * A_csr * K reduced_L = K.T @ L_np # Solve linear system d = scipy.sparse.linalg.spsolve(KTAK, reduced_L) # Back substitution to full solution vector uh_numpy = K @ d assert np.allclose(uh_numpy, u_mpc) list_timings(mesh.comm, [TimingType.wall])
for k, v in petsc_options.items(): opts[k] = v opts.prefixPop() solver.setFromOptions() with Timer("~PERIODIC: Assemble and solve MPC problem"): uh = problem.solve() # solver.view() it = solver.getIterationNumber() print("Constrained solver iterations {0:d}".format(it)) # Write solution to file uh.name = "u_mpc" outfile = XDMFFile(MPI.COMM_WORLD, "results/demo_periodic_geometrical.xdmf", "w") outfile.write_mesh(mesh) outfile.write_function(uh) print("----Verification----") # --------------------VERIFICATION------------------------- bilinear_form = fem.form(a) A_org = fem.petsc.assemble_matrix(bilinear_form, bcs) A_org.assemble() linear_form = fem.form(rhs) L_org = fem.petsc.assemble_vector(linear_form) fem.petsc.apply_lifting(L_org, [bilinear_form], [bcs]) L_org.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) fem.petsc.set_bc(L_org, bcs) solver.setOperators(A_org)