def __init__(self, spaces, mass, offsets): self.pressure_mass = mass self.block_offsets = offsets super(JacobianPreconditioner, self).__init__(offsets[2]) self.gamma = 0.00001 # The mass matrix and preconditioner do not change every Newton cycle, so we # only need to define them once self.mass_prec = mfem.GSSmoother(mass) mass_pcg = mfem.CGSolver() mass_pcg.SetRelTol(1e-12) mass_pcg.SetAbsTol(1e-12) mass_pcg.SetMaxIter(200) mass_pcg.SetPrintLevel(0) mass_pcg.SetPreconditioner(self.mass_prec) mass_pcg.SetOperator(self.pressure_mass) mass_pcg.iterative_mode = False self.mass_pcg = mass_pcg # The stiffness matrix does change every Newton cycle, so we will define it # during SetOperator self.stiff_pcg = None self.stiff_prec = None
def SetOperator(self, op): self.jacobian = mfem.Opr2BlockOpr(op) if (self.stiff_prec == None): # Initialize the stiffness preconditioner and solver stiff_prec_gs = mfem.GSSmoother() self.stiff_prec = stiff_prec_gs stiff_pcg_iter = mfem.GMRESSolver() stiff_pcg_iter.SetRelTol(1e-8) stiff_pcg_iter.SetAbsTol(1e-8) stiff_pcg_iter.SetMaxIter(200) stiff_pcg_iter.SetPrintLevel(0) stiff_pcg_iter.SetPreconditioner(self.stiff_prec) stiff_pcg_iter.iterative_mode = False self.stiff_pcg = stiff_pcg_iter # At each Newton cycle, compute the new stiffness preconditioner by updating # the iterative solver which, in turn, updates its preconditioner self.stiff_pcg.SetOperator(self.jacobian.GetBlock(0, 0))
a.AddBdrFaceIntegrator(mfem.DGElasticityIntegrator(lambda_c, mu_c, alpha, kappa), dir_bdr) print('matrix ...') a.Assemble() A = mfem.SparseMatrix() B = mfem.Vector() X = mfem.Vector() a.FormLinearSystem(ess_tdof_list, x, b, A, X, B); print('...done') A.PrintInfo(sys.stdout) # 11. Define a simple symmetric Gauss-Seidel preconditioner and use it to # solve the system Ax=b with PCG for the symmetric formulation, or GMRES # for the non-symmetric. M = mfem.GSSmoother(A) rtol = 1e-6 if (alpha == -1.0): mfem.PCG(A, M, B, X, 3, 5000, rtol*rtol, 0.0) else: mfem.GMRES(A, M, B, X, 3, 5000, 50, rtol*rtol, 0.0) # 12. Recover the solution as a finite element grid function 'x'. a.RecoverFEMSolution(X, b, x) # 13. Use the DG solution space as the mesh nodal space. This allows us to # save the displaced mesh as a curved DG mesh. mesh.SetNodalFESpace(fespace) reference_nodes = mfem.Vector() if (visualization): reference_nodes.Assign(mesh.GetNodes())
BT = mfem.Transpose(B) darcyOp = mfem.BlockOperator(block_offsets) darcyOp.SetBlock(0, 0, M) darcyOp.SetBlock(0, 1, BT) darcyOp.SetBlock(1, 0, B) MinvBt = mfem.Transpose(B) Md = mfem.Vector(M.Height()) M.GetDiag(Md) for i in range(Md.Size()): MinvBt.ScaleRow(i, 1 / Md[i]) S = mfem.Mult(B, MinvBt) invM = mfem.DSmoother(M) invS = mfem.GSSmoother(S) invM.iterative_mode = False invS.iterative_mode = False darcyPrec = mfem.BlockDiagonalPreconditioner(block_offsets) darcyPrec.SetDiagonalBlock(0, invM) darcyPrec.SetDiagonalBlock(1, invS) maxIter = 500 rtol = 1e-6 atol = 1e-10 stime = clock() solver = mfem.MINRESSolver() solver.SetAbsTol(atol) solver.SetRelTol(rtol)
def run(order=1, static_cond=False, meshfile=def_meshfile, visualization=False): mesh = mfem.Mesh(meshfile, 1, 1) dim = mesh.Dimension() # 3. Refine the mesh to increase the resolution. In this example we do # 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the # largest number that gives a final mesh with no more than 50,000 # elements. ref_levels = int(np.floor( np.log(50000. / mesh.GetNE()) / np.log(2.) / dim)) for x in range(ref_levels): mesh.UniformRefinement() #5. Define a finite element space on the mesh. Here we use vector finite # elements, i.e. dim copies of a scalar finite element space. The vector # dimension is specified by the last argument of the FiniteElementSpace # constructor. For NURBS meshes, we use the (degree elevated) NURBS space # associated with the mesh nodes. if order > 0: fec = mfem.H1_FECollection(order, dim) elif mesh.GetNodes(): fec = mesh.GetNodes().OwnFEC() prinr("Using isoparametric FEs: " + str(fec.Name())) else: order = 1 fec = mfem.H1_FECollection(order, dim) fespace = mfem.FiniteElementSpace(mesh, fec) print('Number of finite element unknowns: ' + str(fespace.GetTrueVSize())) # 5. Determine the list of true (i.e. conforming) essential boundary dofs. # In this example, the boundary conditions are defined by marking all # the boundary attributes from the mesh as essential (Dirichlet) and # converting them to a list of true dofs. ess_tdof_list = mfem.intArray() if mesh.bdr_attributes.Size() > 0: ess_bdr = mfem.intArray([1] * mesh.bdr_attributes.Max()) ess_bdr = mfem.intArray(mesh.bdr_attributes.Max()) ess_bdr.Assign(1) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) #6. Set up the linear form b(.) which corresponds to the right-hand side of # the FEM linear system, which in this case is (1,phi_i) where phi_i are # the basis functions in the finite element fespace. b = mfem.LinearForm(fespace) one = mfem.ConstantCoefficient(1.0) b.AddDomainIntegrator(mfem.DomainLFIntegrator(one)) b.Assemble() #7. Define the solution vector x as a finite element grid function # corresponding to fespace. Initialize x with initial guess of zero, # which satisfies the boundary conditions. x = mfem.GridFunction(fespace) x.Assign(0.0) #8. Set up the bilinear form a(.,.) on the finite element space # corresponding to the Laplacian operator -Delta, by adding the Diffusion # domain integrator. a = mfem.BilinearForm(fespace) a.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) #9. Assemble the bilinear form and the corresponding linear system, # applying any necessary transformations such as: eliminating boundary # conditions, applying conforming constraints for non-conforming AMR, # static condensation, etc. if static_cond: a.EnableStaticCondensation() a.Assemble() A = mfem.OperatorPtr() B = mfem.Vector() X = mfem.Vector() a.FormLinearSystem(ess_tdof_list, x, b, A, X, B) print("Size of linear system: " + str(A.Height())) # 10. Solve AA = mfem.OperatorHandle2SparseMatrix(A) M = mfem.GSSmoother(AA) mfem.PCG(AA, M, B, X, 1, 200, 1e-12, 0.0) # 11. Recover the solution as a finite element grid function. a.RecoverFEMSolution(X, b, x) # 12. Save the refined mesh and the solution. This output can be viewed later # using GLVis: "glvis -m refined.mesh -g sol.gf". mesh.Print('refined.mesh', 8) x.Save('sol.gf', 8) #13. Send the solution by socket to a GLVis server. if (visualization): sol_sock = mfem.socketstream("localhost", 19916) sol_sock.precision(8) sol_sock.send_solution(mesh, x)