def apply_essential(self, engine, gf, real=False, kfes=0): if kfes > 0: return c0 = self.vt.make_value_or_expression(self)[0] if real: dprint1("Apply Ess.(real)" + str(self._sel_index), 'c0', c0) else: dprint1("Apply Ess.(imag)" + str(self._sel_index), 'c0', c0) name = self.get_root_phys().dep_vars[0] fes = engine.get_fes(self.get_root_phys(), name=name) fec_name = fes.FEColl().Name() mesh = engine.get_emesh(mm=self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0] * mesh.bdr_attributes.Max() for idx in self._sel_index: bdr_attr[idx - 1] = 1 ess_vdofs = mfem.intArray() fes.GetEssentialVDofs(mfem.intArray(bdr_attr), ess_vdofs, 0) vdofs = np.where(np.array(ess_vdofs.ToList()) == -1)[0] dofs = mfem.intArray([fes.VDofToDof(i) for i in vdofs]) fes.BuildDofToArrays() coeff1 = SCoeff(c0, self.get_root_phys().ind_vars, self._local_ns, self._global_ns, real=real) gf.ProjectCoefficient(coeff1, dofs, 0)
def apply_essential(self, engine, gf, real=False, kfes=0): if kfes > 1: return if real: dprint1("Apply Ess.(real)" + str(self._sel_index)) else: dprint1("Apply Ess.(imag)" + str(self._sel_index)) Exyz = self.vt.make_value_or_expression(self) mesh = engine.get_mesh(mm=self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0] * mesh.bdr_attributes.Max() for idx in self._sel_index: bdr_attr[idx - 1] = 1 if kfes == 0: coeff1 = Exy(2, Exyz, self.get_root_phys().ind_vars, self._local_ns, self._global_ns, real=real) gf.ProjectBdrCoefficientTangent(coeff1, mfem.intArray(bdr_attr)) elif kfes == 1: coeff1 = Ez(Exyz, self.get_root_phys().ind_vars, self._local_ns, self._global_ns, real=real) gf.ProjectBdrCoefficient(coeff1, mfem.intArray(bdr_attr))
def make_inv_mat(self, idx, inv): ro = np.hstack([0, np.cumsum(np.array(self.lsize)[idx])]) row = mfem.intArray(list(ro)) col = mfem.intArray(list(ro)) mat = mfem.BlockOperator(row, col) for ii, i in enumerate(idx): mat.SetBlock(ii, ii, inv[i]) return mat
def get_global_blkmat_interleave(self): ''' This routine ordered unkonws in the following order Re FFE1, Im FES1, ReFES2, Im FES2, ... If self.complex is False, it assembles a nomal block matrix FES1, FES2... ''' roffsets, coffsets = self.get_local_partitioning(convert_real=True, interleave=True) dprint1("offsets", roffsets, coffsets) ro = mfem.intArray(list(roffsets)) co = mfem.intArray(list(coffsets)) glcsr = mfem.BlockOperator(ro, co) ii = 0 for i in range(self.shape[0]): jj = 0 for j in range(self.shape[1]): if self[i, j] is not None: if use_parallel: if isinstance(self[i, j], chypre.CHypreMat): gcsr = self[i, j] cp = self[i, j].GetColPartArray() rp = self[i, j].GetRowPartArray() s = self[i, j].shape #if (cp == rp).all() and s[0] == s[1]: if gcsr[0] is not None: csr = ToScipyCoo(gcsr[0]).tocsr() gcsr[0] = ToHypreParCSR(csr, col_starts=cp) if gcsr[1] is not None: csr = ToScipyCoo(gcsr[1]).tocsr() gcsr[1] = ToHypreParCSR(csr, col_starts=cp) gcsrm = ToHypreParCSR(-csr, col_starts=cp) dprint2(i, j, s, rp, cp) else: assert False, "unsupported block element " + str( type(self[i, j])) else: if isinstance(self[i, j], ScipyCoo): gcsr = self[i, j].get_mfem_sparsemat() if gcsr[1] is not None: gcsrm = mfem.SparseMatrix(gcsr[1]) gcsrm *= -1. else: assert False, "unsupported block element " + type( self[i, j]) glcsr.SetBlock(ii, jj, gcsr[0]) if self.complex: glcsr.SetBlock(ii + 1, jj + 1, gcsr[0]) if gcsr[1] is not None: glcsr.SetBlock(ii + 1, jj, gcsr[1]) glcsr.SetBlock(ii, jj + 1, gcsrm) jj = jj + 2 if self.complex else jj + 1 ii = ii + 2 if self.complex else ii + 1 return glcsr
def make_sub_matrix(self, src_mat, roffset, coffset, row_idx, col_idx): ro = mfem.intArray(list(roffset)) co = mfem.intArray(list(coffset)) mat = mfem.BlockOperator(ro, co) for ii, i in enumerate(row_idx): for jj, j in enumerate(col_idx): m = get_block(src_mat, i, j) if m is None: continue mat.SetBlock(ii, jj, m) return mat
def add_mesh_refined_level(self, name, engine, inc=1, refine_dom=None): emesh_idx, old_refine, element, order, fecdim, vdim = self._dataset[ name][-1] new_refine = old_refine + 1 if not (emesh_idx, new_refine) in self._refined_mesh_storage: m = self._refined_mesh_storage[(emesh_idx, old_refine)] m2 = self._owner.new_mesh_from_mesh(m) for i in range(inc): if refine_dom is None: m2.UniformRefinement() else: attr = m2.GetAttributeArray() idx = list(np.where(np.in1d(attr, refine_dom))[0]) idx0 = mfem.intArray(idx) m2.GeneralRefinement(idx0) # this is parallel refinement m2.GetEdgeVertexTable() self._refined_mesh_storage[(emesh_idx, old_refine + inc)] = m2 else: m2 = self._refined_mesh_storage[(emesh_idx, new_refine)] fec = self.get_or_allocate_fec(element, order, fecdim) key1 = (emesh_idx, old_refine, element, order, fecdim, vdim) key2 = (emesh_idx, new_refine, element, order, fecdim, vdim) fes1 = self.get_or_allocate_fes(*key1) fes2 = self.get_or_allocate_fes(*key2) P = self.get_or_allocate_transfer(name, key1, key2, engine) h = self._hierarchies[name] h.AddLevel(m2, fes2, P, False, False, False) self._dataset[name].append(key2) return len(self._dataset[name])
def mfem_smoother(name, **kwargs): prc = kwargs.pop('prc') blockname = kwargs.pop('blockname') row = prc.get_row_by_name(blockname) col = prc.get_col_by_name(blockname) mat = prc.get_operator_block(row, col) if isinstance(mat, mfem.ComplexOperator): conv = mat.GetConvention() blockOffsets = mfem.intArray() blockOffsets.SetSize(3) blockOffsets[0] = 0 blockOffsets[1] = mat.Height() // 2 blockOffsets[2] = mat.Height() // 2 blockOffsets.PartialSum() smoother = mfem.BlockDiagonalPreconditioner(blockOffsets) m_r = mat._real_operator #m_i = mat._imag_operator pc_r = _create_smoother(name, m_r) pc_i = mfem.ScaledOperator( pc_r, 1 if conv == mfem.ComplexOperator.HERMITIAN else -1) smoother.SetDiagonalBlock(0, pc_r) smoother.SetDiagonalBlock(1, pc_i) smoother._smoothers = (pc_r, pc_i) else: smoother = _create_smoother(name, mat) return smoother
def test_course_to_file_map(): mesh_file = "../data/inline-quad.mesh" device = mfem.Device('cpu') mesh = mfem.Mesh(mesh_file, 1, 1) refinements = mfem.RefinementArray() refinements.Append(mfem.Refinement(0, 0b11)) refinements.Append(mfem.Refinement(1, 0b10)) refinements.Append(mfem.Refinement(2, 0b01)) mesh.GeneralRefinement(refinements) cft = mesh.GetRefinementTransforms() coarse_to_fine = mfem.Table() coarse_to_ref_type = mfem.intArray() ref_type_to_matrix = mfem.Table() ref_type_to_geom = mfem.GeometryTypeArray() cft.GetCoarseToFineMap(mesh, coarse_to_fine, coarse_to_ref_type, ref_type_to_matrix, ref_type_to_geom) print("coarse_to_fine element number mapping:") coarse_to_fine.Print() print("ref_type_to_geom mapping:") for i in range(ref_type_to_geom.Size()): g = ref_type_to_geom[i] print("ref_type: " + str(i) + "=> geom: " + str(g))
def gather_blkvec_merged(self, size_hint=None, symmetric=False): ''' Construct MFEM::BlockVector This routine ordered unkonws in the following order (Re_FES1_node1, Im_FES1_node1, Re_FES1_node2, Im_FES1_node2, ...) ''' assert self.complex, "this format is complex only" roffsets = self.get_local_partitioning_v(size_hint=size_hint) roffsets = np.sum(np.diff(roffsets).reshape(-1, 2), 1) roffsets = np.hstack([0, np.cumsum(roffsets)]) dprint1("roffsets(vector)", roffsets) offset = mfem.intArray(list(roffsets)) vec = mfem.BlockVector(offset) vec._offsets = offset # in order to keep it from freed data = [] ii = 0 jj = 0 # Here I don't like that I am copying the data between two vectors.. # But, avoiding this takes the large rearangement of program flow... for i in range(self.shape[0]): if self[i, 0] is not None: if isinstance(self[i, 0], chypre.CHypreVec): rr = self[i, 0][0].GetDataArray() if self[i, 0][1] is not None: if symmetric: ii = -self[i, 0][1].GetDataArray() else: ii = self[i, 0][1].GetDataArray() else: ii = rr * 0 vv = np.hstack([rr, ii]) vec.GetBlock(i).Assign(vv) elif isinstance(self[i, 0], ScipyCoo): arr = np.atleast_1d(self[i, 0].toarray().squeeze()) if symmetric: arr = np.hstack([np.real(arr), -np.imag(arr)]) else: arr = np.hstack([np.real(arr), np.imag(arr)]) vec.GetBlock(i).Assign(arr) else: assert False, "not implemented, " + str(type(self[i, 0])) else: vec.GetBlock(i).Assign(0.0) return vec
def apply_essential_1(self, method, real, c0, vdim, vvdim, bdr_attr): if vdim == 1: coeff1 = SCoeff(c0[0], self.get_root_phys().ind_vars, self._local_ns, self._global_ns, real=real) else: coeff1 = VCoeff(vdim, c0, self.get_root_phys().ind_vars, self._local_ns, self._global_ns, real=real) assert not (vvdim != -1 and vdim > 1), "Wrong setting...(vvdim != -1 and vdim > 1)" #print vvdim, vdim, method, coeff1 if vvdim == -1: method(coeff1, mfem.intArray(bdr_attr)) else: for cp in vvdim: method(coeff1, mfem.intArray(bdr_attr), cp)
def apply_essential(self, engine, gf, kfes, real=False, **kwargs): mesh = engine.get_mesh(mm=self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0] * mesh.bdr_attributes.Max() for idx in self._sel_index: bdr_attr[idx - 1] = 1 if kfes == 0: coeff1 = mfem.VectorArrayCoefficient(3) coeff1.Set(0, mfem.ConstantCoefficient(0.0)) coeff1.Set(1, mfem.ConstantCoefficient(0.0)) coeff1.Set(2, mfem.ConstantCoefficient(0.0)) gf.ProjectBdrCoefficientTangent(coeff1, mfem.intArray(bdr_attr))
def FindPoints(self, pp, warn=True, inv_trans=None): r"""count, element_id, integration_points = FindPoints(points, warn=True, int_trans=None)""" import numpy as np import mfem.par as mfem pp = np.array(pp, copy=False, dtype=float).transpose() M = mfem.DenseMatrix(pp.shape[0], pp.shape[1]) M.Assign(pp) elem_ids = mfem.intArray() int_points = mfem.IntegrationPointArray() count = _mesh.Mesh_FindPoints(self, M, elem_ids, int_points, warn, inv_trans) elem_ids = elem_ids.ToList() return count, elem_ids, int_points
def gather_blkvec_interleave(self, size_hint=None): ''' Construct MFEM::BlockVector This routine ordered unkonws in the following order Re FFE1, Im FES1, ReFES2, Im FES2, ... If self.complex is False, it assembles a nomal block vector This routine is used together with get_global_blkmat_interleave(self): ''' roffsets = self.get_local_partitioning_v(convert_real=True, interleave=True, size_hint=size_hint) dprint1("roffsets(vector)", roffsets) offset = mfem.intArray(list(roffsets)) vec = mfem.BlockVector(offset) vec._offsets = offset # in order to keep it from freed data = [] ii = 0 jj = 0 # Here I don't like that I am copying the data between two vectors.. # But, avoiding this takes the large rearangement of program flow... for i in range(self.shape[0]): if self[i, 0] is not None: if isinstance(self[i, 0], chypre.CHypreVec): vec.GetBlock(ii).Assign(self[i, 0][0].GetDataArray()) if self.complex: if self[i, 0][1] is not None: vec.GetBlock(ii + 1).Assign( self[i, 0][1].GetDataArray()) else: vec.GetBlock(ii + 1).Assign(0.0) elif isinstance(self[i, 0], ScipyCoo): arr = np.atleast_1d(self[i, 0].toarray().squeeze()) vec.GetBlock(ii).Assign(np.real(arr)) if self.complex: vec.GetBlock(ii + 1).Assign(np.imag(arr)) else: assert False, "not implemented, " + str(type(self[i, 0])) else: vec.GetBlock(ii).Assign(0.0) if self.complex: vec.GetBlock(ii + 1).Assign(0.0) ii = ii + 2 if self.complex else ii + 1 return vec
def apply_essential(self, engine, gf, real = False, kfes = 0): if kfes > 1: return if real: dprint1("Apply Ess.(real)" + str(self._sel_index)) else: dprint1("Apply Ess.(imag)" + str(self._sel_index)) Erphiz = self.vt.make_value_or_expression(self) mesh = engine.get_mesh(mm = self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0]*mesh.bdr_attributes.Max() for idx in self._sel_index: bdr_attr[idx-1] = 1 if kfes == 0: coeff1 = mfem.VectorArrayCoefficient(2) coeff1.Set(0, mfem.ConstantCoefficient(0.0)) coeff1.Set(1, mfem.ConstantCoefficient(0.0)) gf.ProjectBdrCoefficientTangent(coeff1, mfem.intArray(bdr_attr)) elif kfes == 1: coeff1 = mfem.ConstantCoefficient(0.0) gf.ProjectBdrCoefficient(coeff1, mfem.intArray(bdr_attr))
def do_findpoints(mesh, *args): sdim = mesh.SpaceDimension() shape = args[0].shape size= len(args[0].flatten()) ptx = np.vstack([t.flatten() for t in args]).transpose().flatten() ptx2 = mfem.Vector(ptx) point_mat = mfem.DenseMatrix(ptx2.GetData(), size, sdim) elem_id = mfem.intArray() ips = mfem.IntegrationPointArray() num_found = mesh.FindPoints(point_mat, elem_id, ips, True) elem_id = np.array(elem_id.ToList()) return v, elem_id, ips
def apply_essential(self, engine, gf, real=False, kfes=0): if kfes > 0: return if real: dprint1("Apply Ess.(real)" + str(self._sel_index)) else: dprint1("Apply Ess.(imag)" + str(self._sel_index)) mesh = engine.get_mesh(mm=self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0] * mesh.bdr_attributes.Max() for idx in self._sel_index: bdr_attr[idx - 1] = 1 coeff1 = mfem.ConstantCoefficient(0.0) gf.ProjectBdrCoefficient(coeff1, mfem.intArray(bdr_attr))
def make_sub_vec(self, src_vec, idx, inv=False, nocopy=False): if inv: idx = [k for k in range(self.nb) if not k in idx] size = [src_vec.BlockSize(i) for i in idx] offset = np.hstack([0, np.cumsum(size, dtype=int)]) offset = mfem.intArray(list(offset)) sub_vec = mfem.BlockVector(offset) sub_vec._offsets = offset # in order to keep it from freed for k, i in enumerate(idx): if nocopy: sub_vec.GetBlock(k).Assign(0.0) else: sub_vec.GetBlock(k).Assign(src_vec.GetBlock(i).GetDataArray()) return sub_vec
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)
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 apply_essential(self, engine, gf, real = False, kfes = 0): if kfes == 0: return if real: dprint1("Apply Ess.(real)" + str(self._sel_index)) coeff = mfem.ConstantCoefficient(float(self.psi0)) else: return #dprint1("Apply Ess.(imag)" + str(self._sel_index)) #coeff = mfem.ConstantCoefficient(complex(self.psi0).imag) coeff = self.restrict_coeff(coeff, engine) mesh = engine.get_mesh(mm = self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0]*mesh.bdr_attributes.Max() ess_bdr = self.get_essential_idx(1) dprint1("Essential boundaries", ess_bdr) for idx in ess_bdr: bdr_attr[idx-1] = 1 gf.ProjectBdrCoefficient(coeff, mfem.intArray(bdr_attr))
def apply_essential(self, engine, gf, real=False, kfes=0): if kfes != 0: return if real: dprint1("Apply Ess.(real)" + str(self._sel_index)) else: dprint1("Apply Ess.(imag)" + str(self._sel_index)) f_name = self._make_f_name() coeff1 = Et(3, f_name, self.get_root_phys().ind_vars, self._local_ns, self._global_ns, real=real) coeff1 = self.restrict_coeff(coeff1, engine, vec=True) mesh = engine.get_mesh(mm=self) ibdr = mesh.bdr_attributes.ToList() bdr_attr = [0] * mesh.bdr_attributes.Max() for idx in self._sel_index: bdr_attr[idx - 1] = 1 gf.ProjectBdrCoefficientTangent(coeff1, mfem.intArray(bdr_attr))
# 7. Set up the linear form F(.) which corresponds to the right-hand side of # the FEM linear system, which in this case is (f,phi_i) where f=1.0 and # phi_i are the basis functions in the test finite element fespace. one = mfem.ConstantCoefficient(1.0) F = mfem.ParLinearForm(test_space) F.AddDomainIntegrator(mfem.DomainLFIntegrator(one)) F.Assemble() x0 = mfem.ParGridFunction(x0_space) x0.Assign(0.0) # 8. Set up the mixed bilinear form for the primal trial unknowns, B0, # the mixed bilinear form for the interfacial unknowns, Bhat, # the inverse stiffness matrix on the discontinuous test space, Sinv, # and the stiffness matrix on the continuous trial space, S0. ess_bdr = mfem.intArray(pmesh.bdr_attributes.Max()) ess_bdr.Assign(1) ess_dof = mfem.intArray() x0_space.GetEssentialVDofs(ess_bdr, ess_dof) B0 = mfem.ParMixedBilinearForm(x0_space, test_space) B0.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) B0.Assemble() B0.EliminateEssentialBCFromTrialDofs(ess_dof, x0, F) B0.Finalize() Bhat = mfem.ParMixedBilinearForm(xhat_space, test_space) Bhat.AddTraceFaceIntegrator(mfem.TraceJumpIntegrator()) Bhat.Assemble() Bhat.Finalize()
# corresponding to the Laplacian operator -Delta, by adding the Diffusion # and Mass domain integrators. a = mfem.ParBilinearForm(fespace) a.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) a.AddDomainIntegrator(mfem.MassIntegrator(one)) # 8. Assemble the linear system, apply conforming constraints, etc. a.Assemble() a.Finalize() mat = a.ParallelAssemble() mat.Print("parmatrix") A = mfem.HypreParMatrix() B = mfem.Vector() X = mfem.Vector() empty_tdof_list = mfem.intArray() a.FormLinearSystem(empty_tdof_list, x, b, A, X, B) 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) # 10. Recover the solution as a finite element grid function. a.RecoverFEMSolution(X, b, x) # 12. Compute and print the L^2 norm of the error.
l2_coll = mfem.L2_FECollection(order, dim) R_space = mfem.ParFiniteElementSpace(pmesh, hdiv_coll) W_space = mfem.ParFiniteElementSpace(pmesh, l2_coll) dimR = R_space.GlobalTrueVSize() dimW = W_space.GlobalTrueVSize() if verbose: print("***********************************************************") print("dim(R) = " + str(dimR)) print("dim(W) = " + str(dimW)) print("dim(R+W) = " + str(dimR + dimW)) print("***********************************************************") block_offsets = intArray([0, R_space.GetVSize(), W_space.GetVSize()]) block_offsets.PartialSum() block_trueOffsets = intArray([0, R_space.TrueVSize(), W_space.TrueVSize()]) block_trueOffsets.PartialSum() k = mfem.ConstantCoefficient(1.0) fcoeff = fFunc(dim) fnatcoeff = f_natural() gcoeff = gFunc() ucoeff = uFunc_ex(dim) pcoeff = pFunc_ex() x = mfem.BlockVector(block_offsets) rhs = mfem.BlockVector(block_offsets)
def get_global_blkmat_merged(self, symmetric=False): ''' This routine ordered unkonws in the following order Re FFE1, Im FES1, ReFES2, Im FES2, ... matrix FES1, FES2... ''' assert self.complex, "this format is complex only" roffsets, coffsets = self.get_local_partitioning() roffsets = np.sum(np.diff(roffsets).reshape(-1, 2), 1) coffsets = np.sum(np.diff(coffsets).reshape(-1, 2), 1) roffsets = np.hstack([0, np.cumsum(roffsets)]) coffsets = np.hstack([0, np.cumsum(coffsets)]) dprint1("Generating MFEM BlockMatrix: shape = " + str((len(roffsets) - 1, len(coffsets) - 1))) dprint1("Generating MFEM BlockMatrix: roffset/coffset = ", roffsets, coffsets) ro = mfem.intArray(list(roffsets)) co = mfem.intArray(list(coffsets)) glcsr = mfem.BlockOperator(ro, co) ii = 0 for j in range(self.shape[1]): jfirst = True for i in range(self.shape[0]): if self[i, j] is not None: if use_parallel: if isinstance(self[i, j], chypre.CHypreMat): gcsr = self[i, j] cp = self[i, j].GetColPartArray() rp = self[i, j].GetRowPartArray() rsize_local = rp[1] - rp[0] if jfirst: csize_local = cp[1] - cp[0] csize = allgather(csize_local) cstarts = np.hstack([0, np.cumsum(csize)]) jfirst = False s = self[i, j].shape # if (cp == rp).all() and s[0] == s[1]: ''' if gcsr[0] is not None: csc = ToScipyCoo(gcsr[0]).tocsc() csc1 = [csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)] if symmetric: csc1m = [-csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)] else: csc1 = [None]*len(csize) csc1m = [None]*len(csize) if gcsr[1] is not None: csc = ToScipyCoo(gcsr[1]).tocsc() if not symmetric: csc2 = [ csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)] csc2m = [-csc[:,cstarts[k]:cstarts[k+1]] for k in range(len(cstarts)-1)] else: csc2 = [None]*len(csize) csc2m = [None]*len(csize) if symmetric: csr = scipy.sparse.bmat([sum(zip(csc1, csc2m), ()), sum(zip(csc2m, csc1m), ())]).tocsr() else: csr = scipy.sparse.bmat([sum(zip(csc1, csc2m), ()), sum(zip(csc2, csc1), ())]).tocsr() cp2 = [(cp*2)[0], (cp*2)[1], np.sum(csize)*2] #gcsr[1] = ToHypreParCSR(csr, col_starts =cp) gcsr = ToHypreParCSR(csr, col_starts =cp2) ''' if gcsr[0] is None: csr = scipy.sparse.csr_matrix( (rsize_local, cstarts[-1]), dtype=np.float64) cp3 = [cp[0], cp[1], cstarts[-1]] gcsa = ToHypreParCSR(csr, col_starts=cp3) else: gcsa = gcsr[0] if gcsr[1] is None: csr = scipy.sparse.csr_matrix( (rsize_local, cstarts[-1]), dtype=np.float64) cp3 = [cp[0], cp[1], cstarts[-1]] gcsb = ToHypreParCSR(csr, col_starts=cp3) else: gcsb = gcsr[1] else: assert False, "unsupported block element " + \ str(type(self[i, j])) else: if isinstance(self[i, j], ScipyCoo): ''' if symmetric: tmp = scipy.sparse.bmat([[ self[i, j].real, -self[i, j].imag], [-self[i, j].imag, -self[i, j].real]]) else: tmp = scipy.sparse.bmat([[self[i, j].real, -self[i, j].imag], [self[i, j].imag, self[i, j].real]]) ''' csra = self[i, j].real.tocsr() csrb = self[i, j].imag.tocsr() csra.eliminate_zeros() csrb.eliminate_zeros() gcsa = mfem.SparseMatrix(csra) gcsb = mfem.SparseMatrix(csrb) else: assert False, "unsupported block element " + \ type(self[i, j]) Hermitian = False if symmetric else True gcsr = mfem.ComplexOperator(gcsa, gcsb, False, False, Hermitian) gcsr._real_operator = gcsa gcsr._imag_operator = gcsb glcsr.SetBlock(i, j, gcsr) return glcsr
# needed on the right hand side of the generalized eigenvalue problem # below. The boundary conditions are implemented by marking only boundary # attribute 1 as essential. We use special values on the diagonal to # shift the Dirichlet eigenvalues out of the computational range. After # serial/parallel assembly we extract the corresponding parallel matrices # A and M. lamb = mfem.Vector(pmesh.attributes.Max()) lamb.Assign(1.0) lamb[0] = lamb[1] * 50 lambda_func = mfem.PWConstCoefficient(lamb) mu = mfem.Vector(pmesh.attributes.Max()) mu.Assign(1.0) mu[0] = mu[1] * 50 mu_func = mfem.PWConstCoefficient(mu) ess_bdr = mfem.intArray(pmesh.bdr_attributes.Max()) ess_bdr.Assign(0) ess_bdr[0] = 1 a = mfem.ParBilinearForm(fespace) a.AddDomainIntegrator(mfem.ElasticityIntegrator(lambda_func, mu_func)) if (myid == 0): print("matrix ... ") a.Assemble() a.EliminateEssentialBCDiag(ess_bdr, 1.0) a.Finalize() m = mfem.ParBilinearForm(fespace) m.AddDomainIntegrator(mfem.VectorMassIntegrator()) m.Assemble()
def __init__(self, fespace, ess_bdr, visc, mu, K): mfem.PyTimeDependentOperator.__init__(self, 2 * fespace.TrueVSize(), 0.0) rel_tol = 1e-8 skip_zero_entries = 0 ref_density = 1.0 self.ess_tdof_list = intArray() self.z = mfem.Vector(self.Height() // 2) self.fespace = fespace self.viscosity = visc self.newton_solver = mfem.NewtonSolver(fespace.GetComm()) M = mfem.ParBilinearForm(fespace) S = mfem.ParBilinearForm(fespace) H = mfem.ParNonlinearForm(fespace) self.M = M self.H = H self.S = S rho = mfem.ConstantCoefficient(ref_density) M.AddDomainIntegrator(mfem.VectorMassIntegrator(rho)) M.Assemble(skip_zero_entries) M.EliminateEssentialBC(ess_bdr) M.Finalize(skip_zero_entries) self.Mmat = M.ParallelAssemble() fespace.GetEssentialTrueDofs(ess_bdr, self.ess_tdof_list) self.Mmat.EliminateRowsCols(self.ess_tdof_list) M_solver = mfem.CGSolver(fespace.GetComm()) M_prec = mfem.HypreSmoother() M_solver.iterative_mode = False M_solver.SetRelTol(rel_tol) M_solver.SetAbsTol(0.0) M_solver.SetMaxIter(30) M_solver.SetPrintLevel(0) M_prec.SetType(mfem.HypreSmoother.Jacobi) M_solver.SetPreconditioner(M_prec) M_solver.SetOperator(self.Mmat) self.M_solver = M_solver self.M_prec = M_prec model = mfem.NeoHookeanModel(mu, K) H.AddDomainIntegrator(mfem.HyperelasticNLFIntegrator(model)) H.SetEssentialTrueDofs(self.ess_tdof_list) self.model = model visc_coeff = mfem.ConstantCoefficient(visc) S.AddDomainIntegrator(mfem.VectorDiffusionIntegrator(visc_coeff)) S.Assemble(skip_zero_entries) S.EliminateEssentialBC(ess_bdr) S.Finalize(skip_zero_entries) self.reduced_oper = ReducedSystemOperator(M, S, H, self.ess_tdof_list) J_hypreSmoother = mfem.HypreSmoother() J_hypreSmoother.SetType(mfem.HypreSmoother.l1Jacobi) J_hypreSmoother.SetPositiveDiagonal(True) J_prec = J_hypreSmoother J_minres = mfem.MINRESSolver(fespace.GetComm()) J_minres.SetRelTol(rel_tol) J_minres.SetAbsTol(0.0) J_minres.SetMaxIter(300) J_minres.SetPrintLevel(-1) J_minres.SetPreconditioner(J_prec) self.J_solver = J_minres self.J_prec = J_prec newton_solver = mfem.NewtonSolver(fespace.GetComm()) newton_solver.iterative_mode = False newton_solver.SetSolver(self.J_solver) newton_solver.SetOperator(self.reduced_oper) newton_solver.SetPrintLevel(1) #print Newton iterations newton_solver.SetRelTol(rel_tol) newton_solver.SetAbsTol(0.0) newton_solver.SetMaxIter(10) self.newton_solver = newton_solver
# 7. Define the parallel vector finite element spaces representing the mesh # deformation x_gf, the velocity v_gf, and the initial configuration, # x_ref. Define also the elastic energy density, w_gf, which is in a # discontinuous higher-order space. Since x and v are integrated in time # as a system, we group them together in block vector vx, on the unique # parallel degrees of freedom, with offsets given by array true_offset. fec = mfem.H1_FECollection(order, dim) fespace = mfem.ParFiniteElementSpace(pmesh, fec, dim) glob_size = fespace.GlobalTrueVSize() if (myid == 0): print('Number of velocity/deformation unknowns: ' + str(glob_size)) true_size = fespace.TrueVSize() true_offset = mfem.intArray(3) true_offset[0] = 0 true_offset[1] = true_size true_offset[2] = 2 * true_size vx = mfem.BlockVector(true_offset) v_gf = mfem.ParGridFunction(fespace) x_gf = mfem.ParGridFunction(fespace) x_ref = mfem.ParGridFunction(fespace) pmesh.GetNodes(x_ref) w_fec = mfem.L2_FECollection(order + 1, dim) w_fespace = mfem.ParFiniteElementSpace(pmesh, w_fec) w_gf = mfem.ParGridFunction(w_fespace)
# 4. Project a NURBS mesh to a piecewise-quadratic curved mesh. Make sure # that the mesh is non-conforming if it has quads or hexes and refine it if (mesh.NURBSext): mesh.UniformRefinement() if ref_levels > 0: ref_levels = ref_levels - 1 mesh.SetCurvature(2) mesh.EnsureNCMesh() for l in range(ref_levels): mesh.UniformRefinement() # 5. Define a parallel mesh by partitioning the serial mesh. Once the # parallel mesh is defined, the serial mesh can be deleted. pmesh = mfem.ParMesh(MPI.COMM_WORLD, mesh) del mesh ess_bdr = mfem.intArray(pmesh.bdr_attributes.Max()) ess_bdr.Assign(1) # 6. Define a finite element space on the mesh. The polynomial order is one # (linear) by default, but this can be changed on the command line. fec = mfem.H1_FECollection(order, dim) fespace = mfem.ParFiniteElementSpace(pmesh, fec) # 7. As in Example 1p, we set up bilinear and linear forms corresponding to # the Laplace problem -\Delta u = 1. We don't assemble the discrete # problem yet, this will be done in the inner loop. a = mfem.ParBilinearForm(fespace) b = mfem.ParLinearForm(fespace) one = mfem.ConstantCoefficient(1.0) bdr = BdrCoefficient()
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)