def __init__(self, fespace, alpha, kappa, u): mfem.PyTimeDependentOperator.__init__(self, fespace.GetTrueVSize(), 0.0) rel_tol = 1e-8 self.alpha = alpha self.kappa = kappa self.T = None self.K = None self.M = None self.fespace = fespace self.ess_tdof_list = intArray() self.Mmat = mfem.HypreParMatrix() self.Kmat = mfem.HypreParMatrix() self.M_solver = mfem.CGSolver(fespace.GetComm()) self.M_prec = mfem.HypreSmoother() self.T_solver = mfem.CGSolver(fespace.GetComm()) self.T_prec = mfem.HypreSmoother() self.z = mfem.Vector(self.Height()) self.M = mfem.ParBilinearForm(fespace) self.M.AddDomainIntegrator(mfem.MassIntegrator()) self.M.Assemble() self.M.FormSystemMatrix(self.ess_tdof_list, self.Mmat) self.M_solver.iterative_mode = False self.M_solver.SetRelTol(rel_tol) self.M_solver.SetAbsTol(0.0) self.M_solver.SetMaxIter(100) self.M_solver.SetPrintLevel(0) self.M_prec.SetType(mfem.HypreSmoother.Jacobi) self.M_solver.SetPreconditioner(self.M_prec) self.M_solver.SetOperator(self.Mmat) self.T_solver.iterative_mode = False self.T_solver.SetRelTol(rel_tol) self.T_solver.SetAbsTol(0.0) self.T_solver.SetMaxIter(100) self.T_solver.SetPrintLevel(0) self.T_solver.SetPreconditioner(self.T_prec) self.SetParameters(u)
def updStiffMatMS(self, elmLst, elmCompStiffMat): self.K = mfem.ParBilinearForm(self.fespace) lambVec = mfem.Vector(self.fespace.GetMesh().attributes.Max()) lambVec.Assign(self.lmbda) lambVec[0] = lambVec[1] lambda_func = mfem.PWConstCoefficient(lambVec) muVec = mfem.Vector(self.fespace.GetMesh().attributes.Max()) muVec.Assign(self.mu) muVec[0] = muVec[1] mu_func = mfem.PWConstCoefficient(muVec) self.K.AddDomainIntegrator( mfem.ElasticityIntegrator(lambda_func, mu_func)) self.K.Assemble(0, elmLst, elmCompStiffMat, False, True) self.Kmat = mfem.HypreParMatrix() empty_tdof_list = intArray() self.K.FormLinearSystem(empty_tdof_list, self.x_gfBdr, self.bx, self.Kmat, self.vx.GetBlock(1), self.Bx, 1)
print("Iteration: " + str(ref_it) + ", number of unknowns: " + str(global_dofs)) # 15. Recompute the field on the current mesh: assemble the stiffness # matrix and the right-hand side. a.Assemble() b.Assemble() # 16. Project the exact solution to the essential DOFs. x.ProjectBdrCoefficient(bdr, ess_bdr) # 17. Create and solve the parallel linear system. ess_tdof_list = mfem.intArray() fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) A = mfem.HypreParMatrix() B = mfem.Vector() X = mfem.Vector() a.FormLinearSystem(ess_tdof_list, x, b, A, X, B) amg = mfem.HypreBoomerAMG(A) amg.SetPrintLevel(0) pcg = mfem.HyprePCG(A) pcg.SetTol(1e-12) pcg.SetMaxIter(200) pcg.SetPrintLevel(0) pcg.SetPreconditioner(amg) pcg.Mult(B, X) # 18. Extract the local solution on each processor. a.RecoverFEMSolution(X, b, x)
def ToHypreParCSR(mat, check_partitioning=False, verbose=False, col_starts=None, assert_non_square_no_col_starts=True): ''' convert scipy sparse matrix to hypre vertically stack csr matrix to generte HYPRE Par CSR Note: row partitioning is inferred from distribution of input matrix. column patitioning needs to be specified col_starts. If col_starts is not given, column partitioning is chosen to be the same as row partitioning. This works if matrix is square (M = N). For an aribtrary rectangular matrix, the column partitioning can be different from the row partitioning. For example, MFEM mixedbilinearfomr uses different partitiong rules for row and column. ToDo: change default assert_non_square_no_col_starts to False ''' from mpi4py import MPI import mfem.par as mfem if mfem.sizeof_HYPRE_Int() == 4: dtype = 'int32' else: dtype = 'int64' comm = MPI.COMM_WORLD num_proc = MPI.COMM_WORLD.size myid = MPI.COMM_WORLD.rank def verbose_message(m, n, nrows, i, j, data, row_starts, col_starts): for k in range(num_proc): MPI.COMM_WORLD.Barrier() if myid == k: print 'MyID : ', k print(m, n), nrows, len(data), i, j, data, row_starts, col_starts print 'NNZ', np.sum(data != 0.0) MPI.COMM_WORLD.Barrier() from scipy.sparse import csr_matrix if isinstance(mat, csr_matrix): mat = mat.astype('float') ml, nl = mat.shape n_array = comm.allgather(nl) else: raise ValueError("Import Matrix Format should be csr or None") # collect row array to determin the size of matrix m_array = comm.allgather(ml) rows = [0] + list(np.cumsum(m_array)) m = rows[-1] row_starts = np.array([rows[myid], rows[myid + 1], m], dtype=dtype) n = nl nrows = ml i = mat.indptr.astype(dtype) j = mat.indices.astype(dtype) data = mat.data if col_starts is None and m != nl: col_starts = get_assumed_patitioning(nl) if assert_non_square_no_col_starts: assert False, "col_starts must be specified for non diagonal array" if col_starts is None: col_starts = row_starts.copy() col_starts[-1] = n if col_starts[0] > n: col_starts[0] = n if col_starts[1] > n: col_starts[1] = n col_starts[2] = n else: # make sure that dtype is right.... col_starts = np.array(col_starts, dtype=dtype) if check_partitioning: ch = get_assumed_patitioning(m) if (row_starts[0] != ch[0] or row_starts[1] != ch[1] or nrows != ch[2]): for k in range(num_proc): MPI.COMM_WORLD.Barrier() if myid == k: print 'MyID : ', k print ch, nrows, row_starts, col_starts print 'NNZ', np.sum(data != 0.0) MPI.COMM_WORLD.Barrier() raise ValueError("partitioning of input matrix is not correct") if verbose: verbose_message(m, n, nrows, i, j, data, row_starts, col_starts) # # it seems row_starts and col_starts are both to determin # which part is treated diagnal element. # if (m == n and row_starts[0] == col_starts[0] and row_starts[1] == col_starts[1]): # this will cause hypre_CSRMatrixReorder call. M = mfem.HypreParMatrix(MPI.COMM_WORLD, nrows, m, n, [i, j, data, col_starts]) M.CopyRowStarts() M.CopyColStarts() else: M = mfem.HypreParMatrix(MPI.COMM_WORLD, nrows, m, n, [i, j, data, row_starts, col_starts]) M.CopyRowStarts() M.CopyColStarts() return M
def run(order = 1, static_cond = False, meshfile = def_meshfile, visualization = False, use_strumpack = False): mesh = mfem.Mesh(meshfile, 1,1) dim = mesh.Dimension() ref_levels = int(np.floor(np.log(10000./mesh.GetNE())/np.log(2.)/dim)) for x in range(ref_levels): mesh.UniformRefinement(); mesh.ReorientTetMesh(); pmesh = mfem.ParMesh(MPI.COMM_WORLD, mesh) del mesh par_ref_levels = 2 for l in range(par_ref_levels): pmesh.UniformRefinement(); if order > 0: fec = mfem.H1_FECollection(order, dim) elif mesh.GetNodes(): fec = mesh.GetNodes().OwnFEC() print( "Using isoparametric FEs: " + str(fec.Name())); else: order = 1 fec = mfem.H1_FECollection(order, dim) fespace =mfem.ParFiniteElementSpace(pmesh, fec) fe_size = fespace.GlobalTrueVSize() if (myid == 0): print('Number of finite element unknowns: '+ str(fe_size)) ess_tdof_list = mfem.intArray() if pmesh.bdr_attributes.Size()>0: ess_bdr = mfem.intArray(pmesh.bdr_attributes.Max()) ess_bdr.Assign(1) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) # the basis functions in the finite element fespace. b = mfem.ParLinearForm(fespace) one = mfem.ConstantCoefficient(1.0) b.AddDomainIntegrator(mfem.DomainLFIntegrator(one)) b.Assemble(); x = mfem.ParGridFunction(fespace); x.Assign(0.0) a = mfem.ParBilinearForm(fespace); a.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) if static_cond: a.EnableStaticCondensation() a.Assemble(); A = mfem.HypreParMatrix() B = mfem.Vector() X = mfem.Vector() a.FormLinearSystem(ess_tdof_list, x, b, A, X, B) if (myid == 0): print("Size of linear system: " + str(x.Size())) print("Size of linear system: " + str(A.GetGlobalNumRows())) if use_strumpack: import mfem.par.strumpack as strmpk Arow = strmpk.STRUMPACKRowLocMatrix(A) args = ["--sp_hss_min_sep_size", "128", "--sp_enable_hss"] strumpack = strmpk.STRUMPACKSolver(args, MPI.COMM_WORLD) strumpack.SetPrintFactorStatistics(True) strumpack.SetPrintSolveStatistics(False) strumpack.SetKrylovSolver(strmpk.KrylovSolver_DIRECT); strumpack.SetReorderingStrategy(strmpk.ReorderingStrategy_METIS) strumpack.SetMC64Job(strmpk.MC64Job_NONE) # strumpack.SetSymmetricPattern(True) strumpack.SetOperator(Arow) strumpack.SetFromCommandLine() strumpack.Mult(B, X); else: amg = mfem.HypreBoomerAMG(A) cg = mfem.CGSolver(MPI.COMM_WORLD) cg.SetRelTol(1e-12) cg.SetMaxIter(200) cg.SetPrintLevel(1) cg.SetPreconditioner(amg) cg.SetOperator(A) cg.Mult(B, X); a.RecoverFEMSolution(X, b, x) smyid = '{:0>6d}'.format(myid) mesh_name = "mesh."+smyid sol_name = "sol."+smyid pmesh.Print(mesh_name, 8) x.Save(sol_name, 8)
def run(order = 1, static_cond = False, meshfile = def_meshfile, visualization = False): mesh = mfem.Mesh(meshfile, 1,1) dim = mesh.Dimension() ref_levels = int(np.floor(np.log(10000./mesh.GetNE())/np.log(2.)/dim)) for x in range(ref_levels): mesh.UniformRefinement(); mesh.ReorientTetMesh(); pmesh = mfem.ParMesh(MPI.COMM_WORLD, mesh) del mesh par_ref_levels = 2 for l in range(par_ref_levels): pmesh.UniformRefinement(); 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.ParFiniteElementSpace(pmesh, fec) fe_size = fespace.GlobalTrueVSize() if (myid == 0): print('Number of finite element unknowns: '+ str(fe_size)) ess_tdof_list = mfem.intArray() if pmesh.bdr_attributes.Size()>0: ess_bdr = mfem.intArray(pmesh.bdr_attributes.Max()) ess_bdr.Assign(1) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) # the basis functions in the finite element fespace. b = mfem.ParLinearForm(fespace) one = mfem.ConstantCoefficient(1.0) b.AddDomainIntegrator(mfem.DomainLFIntegrator(one)) b.Assemble(); x = mfem.ParGridFunction(fespace); x.Assign(0.0) a = mfem.ParBilinearForm(fespace); a.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) if static_cond: a.EnableStaticCondensation() a.Assemble(); A = mfem.HypreParMatrix() B = mfem.Vector() X = mfem.Vector() a.FormLinearSystem(ess_tdof_list, x, b, A, X, B) if (myid == 0): print("Size of linear system: " + str(x.Size())) print("Size of linear system: " + str(A.GetGlobalNumRows())) amg = mfem.HypreBoomerAMG(A) pcg = mfem.HyprePCG(A) pcg.SetTol(1e-12) pcg.SetMaxIter(200) pcg.SetPrintLevel(2) pcg.SetPreconditioner(amg) pcg.Mult(B, X); a.RecoverFEMSolution(X, b, x) smyid = '{:0>6d}'.format(myid) mesh_name = "mesh."+smyid sol_name = "sol."+smyid pmesh.PrintToFile(mesh_name, 8) x.SaveToFile(sol_name, 8)
def __init__(self, fespace, lmbda=1., mu=1., rho=1., visc=0.0, vess_tdof_list=None, vess_bdr=None, xess_tdof_list=None, xess_bdr=None, v_gfBdr=None, x_gfBdr=None, deform=None, velo=None, vx=None): mfem.PyTimeDependentOperator.__init__(self, 2 * fespace.GetTrueVSize(), 0.0) self.lmbda = lmbda self.mu = mu self.viscosity = visc self.deform = deform self.velo = velo self.x_gfBdr = x_gfBdr self.v_gfBdr = v_gfBdr self.vx = vx self.z = mfem.Vector(self.Height() / 2) self.z.Assign(0.0) self.w = mfem.Vector(self.Height() / 2) self.w.Assign(0.0) self.tmpVec = mfem.Vector(self.Height() / 2) self.tmpVec.Assign(0.0) self.fespace = fespace self.xess_bdr = xess_bdr self.vess_bdr = vess_bdr self.xess_tdof_list = xess_tdof_list self.vess_tdof_list = vess_tdof_list # setting up linear form cv = mfem.Vector(3) cv.Assign(0.0) #self.zero_coef = mfem.ConstantCoefficient(0.0) self.zero_coef = mfem.VectorConstantCoefficient(cv) self.bx = mfem.LinearForm(self.fespace) self.bx.AddDomainIntegrator( mfem.VectorBoundaryLFIntegrator(self.zero_coef)) self.bx.Assemble() self.bv = mfem.LinearForm(self.fespace) self.bv.AddDomainIntegrator( mfem.VectorBoundaryLFIntegrator(self.zero_coef)) self.bv.Assemble() self.Bx = mfem.Vector() self.Bv = mfem.Vector() # setting up bilinear forms self.M = mfem.ParBilinearForm(self.fespace) self.K = mfem.ParBilinearForm(self.fespace) self.S = mfem.ParBilinearForm(self.fespace) self.ro = mfem.ConstantCoefficient(rho) self.M.AddDomainIntegrator(mfem.VectorMassIntegrator(self.ro)) self.M.Assemble(0) self.M.EliminateEssentialBC(self.vess_bdr) self.M.Finalize(0) self.Mmat = self.M.ParallelAssemble() self.M_solver = mfem.CGSolver(self.fespace.GetComm()) self.M_solver.iterative_mode = False self.M_solver.SetRelTol(1e-8) self.M_solver.SetAbsTol(0.0) self.M_solver.SetMaxIter(30) self.M_solver.SetPrintLevel(0) self.M_prec = mfem.HypreSmoother() self.M_prec.SetType(mfem.HypreSmoother.Jacobi) self.M_solver.SetPreconditioner(self.M_prec) self.M_solver.SetOperator(self.Mmat) lambVec = mfem.Vector(self.fespace.GetMesh().attributes.Max()) print('Number of volume attributes : ' + str(self.fespace.GetMesh().attributes.Max())) lambVec.Assign(lmbda) lambVec[0] = lambVec[1] * 1.0 lambda_func = mfem.PWConstCoefficient(lambVec) muVec = mfem.Vector(self.fespace.GetMesh().attributes.Max()) muVec.Assign(mu) muVec[0] = muVec[1] * 1.0 mu_func = mfem.PWConstCoefficient(muVec) self.K.AddDomainIntegrator( mfem.ElasticityIntegrator(lambda_func, mu_func)) self.K.Assemble(0) # to set essential BC to zero value uncomment #self.K.EliminateEssentialBC(self.xess_bdr) #self.K.Finalize(0) #self.Kmat = self.K.ParallelAssemble() # to set essential BC to non-zero uncomment self.Kmat = mfem.HypreParMatrix() visc_coeff = mfem.ConstantCoefficient(visc) self.S.AddDomainIntegrator(mfem.VectorDiffusionIntegrator(visc_coeff)) self.S.Assemble(0) #self.S.EliminateEssentialBC(self.vess_bdr) #self.S.Finalize(0) #self.Smat = self.S.ParallelAssemble() self.Smat = mfem.HypreParMatrix() # VX solver for implicit time-stepping self.VX_solver = mfem.CGSolver(self.fespace.GetComm()) self.VX_solver.iterative_mode = False self.VX_solver.SetRelTol(1e-8) self.VX_solver.SetAbsTol(0.0) self.VX_solver.SetMaxIter(30) self.VX_solver.SetPrintLevel(0) self.VX_prec = mfem.HypreSmoother() self.VX_prec.SetType(mfem.HypreSmoother.Jacobi) self.VX_solver.SetPreconditioner(self.VX_prec) # setting up operators empty_tdof_list = intArray() self.S.FormLinearSystem(empty_tdof_list, self.v_gfBdr, self.bv, self.Smat, self.vx.GetBlock(0), self.Bv, 1) self.K.FormLinearSystem(empty_tdof_list, self.x_gfBdr, self.bx, self.Kmat, self.vx.GetBlock(1), self.Bx, 1)