def ncface_values(self, ifaces=None, irs=None, gtypes=None, **kwargs): if not self.isDerived: self.set_funcs() ndim = self.gfr.FESpace().GetMesh().Dimension() d = mfem.DenseMatrix() p = mfem.DenseMatrix() data = [] def get_method(gf, ndim): if gf is None: return None if ndim == 3: return gf.GetFaceVectorValues elif ndim == 2: return gf.GetVectorValues else: assert False, "ndim = 1 has no face" getvalr = get_method(self.gfr, ndim) getvali = get_method(self.gfi, ndim) for i, gtype, in zip(ifaces, gtypes): ir = irs[gtype] getvalr(i, 2, ir, d, p) # side = 2 (automatic?) v = d.GetDataArray().copy() if getvali is not None: getvali(i, 2, ir, d, p) vi = d.GetDataArray().copy() v = v + 1j * vi data.append(v) ret = np.hstack(data).transpose() return ret
def run_test(): m = mfem.DenseMatrix(3, 3) m.Assign(np.arange(9.).reshape(3, 3)) m.Print() print(np.arange(9.).reshape(3, 3)) x = np.zeros(5) + 1 y = np.zeros(5) + 2 z = np.zeros(5) + 3 mm = mfem.DenseMatrix(3, 5) mm.Assign(np.vstack([x, y, z])) mm.Print() mfem.Vector(mm.GetData(), 15).Print()
def __init__(self, lambda_, mu_, si=0, sj=0): super(StressCoefficient, self).__init__(0) self.lam = lambda_ # coefficient self.mu = mu_ # coefficient self.si = si ; self.sj = sj # component self.u = None # displacement GridFunction self.grad = mfem.DenseMatrix()
def get_vshape(fes, k1, idx): tr1 = fes.GetBdrElementTransformation(k1) el = fes.GetBE(k1) nodes1 = el.GetNodes() m = mfem.DenseMatrix(nodes1.GetNPoints(), tr1.GetSpaceDim()) tr1.SetIntPoint(nodes1.IntPoint(idx)) el.CalcVShape(tr1, m) return m.GetDataArray()[idx, :]
def __init__(self, coeff, S, direction, ref_point, pml_width, order, inv): self.coeffs = coeff self.direction = direction self.ref_p = ref_point self.pml_width = pml_width self.S = S self.order = order self.inv = inv self.K = mfem.DenseMatrix(self.width, self.height) super(LinearPML, self).__init__(coeff)
def get_vshape_all(fes, k1): tr1 = fes.GetBdrElementTransformation(k1) el = fes.GetBE(k1) nodes1 = el.GetNodes() m = mfem.DenseMatrix(nodes1.GetNPoints(), tr1.GetSpaceDim()) shape = [] for idx in range(nodes1.GetNPoints()): tr1.SetIntPoint(nodes1.IntPoint(idx)) el.CalcVShape(tr1, m) shape.append(m.GetDataArray()[idx, :].copy()) return np.stack(shape)
def __init__(self, coeff, slice1, slice2): CC_Vector.__init__(self, coeff) self.K = mfem.DenseMatrix(coeff.width, coeff.height) self.slice1 = slice1 self.slice2 = slice2 if len(slice1) == 1 and len(slice2) > 1: self._vdim = len(slice2) elif len(slice2) == 1 and len(slice1) > 1: self._vdim = len(slice1) else: assert False, "SliceVector output should be a vector" + \ str(slice1) + "/" + str(slice2)
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 get_vshape(fes, ibdr, mode='Bdr'): mesh = fes.GetMesh() GetTrans = getattr(fes, methods[mode]['Transformation']) GetElement = getattr(fes, methods[mode]['Element']) GetVDofs = getattr(fes, methods[mode]['VDofs']) GetVDofTrans = getattr(fes, methods[mode]['VDofTransformation']) ret = [None]*len(ibdr) if len(ibdr) == 0: return ret # this is to make sure that IntegraitonPoint in Eltrans is # set once... tr1 = GetTrans(0) el = GetElement(0) nodes1 = el.GetNodes() doftrans = GetVDofTrans(0) tr1.SetIntPoint(nodes1.IntPoint(0)) v0 = mfem.Vector(tr1.GetSpaceDim()) use_weight = True for iii, k1 in enumerate(ibdr): tr1 = GetTrans(k1) el = GetElement(k1) nodes1 = el.GetNodes() doftrans = GetVDofTrans(k1) m = mfem.DenseMatrix(nodes1.GetNPoints(), tr1.GetSpaceDim()) shape = [None]*nodes1.GetNPoints() vv = mfem.Vector(nodes1.GetNPoints()) for idx in range(len(shape)): tr1.SetIntPoint(nodes1.IntPoint(idx)) el.CalcVShape(tr1, m) if doftrans is not None: vv.Assign(0.0) vv[idx] = 1 doftrans.InvTransformPrimal(vv) m.MultTranspose(vv, v0) shape[idx] = v0.GetDataArray().copy() else: shape[idx] = m.GetDataArray()[idx, :].copy() ret[iii] = shape return ret
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 get_vshape(fes, ibdr, mode='Bdr'): mesh = fes.GetMesh() GetTrans = getattr(fes, methods[mode]['Transformation']) GetElement = getattr(fes, methods[mode]['Element']) GetVDofs = getattr(fes, methods[mode]['VDofs']) ret = [None] * len(ibdr) for iii, k1 in enumerate(ibdr): tr1 = GetTrans(k1) el = GetElement(k1) nodes1 = el.GetNodes() m = mfem.DenseMatrix(nodes1.GetNPoints(), tr1.GetSpaceDim()) shape = [None] * nodes1.GetNPoints() for idx in range(len(shape)): tr1.SetIntPoint(nodes1.IntPoint(idx)) el.CalcVShape(tr1, m) shape[idx] = m.GetDataArray()[idx, :].copy() ret[iii] = shape return ret
def __init__(self, coeff, slice1, slice2): CC_Scalar.__init__(self, coeff) self.K = mfem.DenseMatrix(coeff.width, coeff.height) self.slice1 = slice1 self.slice2 = slice2
def ncface_values(self, ifaces=None, irs=None, gtypes=None, **kwargs): if not self.isDerived: self.set_funcs() name = self.gfr.FESpace().FEColl().Name() ndim = self.gfr.FESpace().GetMesh().Dimension() isVector = False if (name.startswith('RT') or name.startswith('ND')): d = mfem.DenseMatrix() p = mfem.DenseMatrix() isVector = True else: d = mfem.Vector() p = mfem.DenseMatrix() data = [] def get_method(gf, ndim, isVector): if gf is None: return None if ndim == 3: if isVector: return gf.GetFaceVectorValues elif gf.VectorDim() > 1: def func(i, side, ir, vals, tr, in_gf=gf): in_gf.GetFaceValues(i, side, ir, vals, tr, vdim=self.comp) return func else: return gf.GetFaceValues elif ndim == 2: if isVector: def func(i, side, ir, vals, tr, in_gf=gf): in_gf.GetVectorValues(i, ir, vals, tr) return func elif gf.VectorDim() > 1: def func(i, side, ir, vals, tr, in_gf=gf): in_gf.GetValues(i, ir, vals, tr, vdim=self.comp - 1) return func else: def func(i, side, ir, vals, tr, in_gf=gf): in_gf.GetValues(i, ir, vals, tr) return return func else: assert False, "ndim = 1 has no face" return None getvalr = get_method(self.gfr, ndim, isVector) getvali = get_method(self.gfi, ndim, isVector) for i, gtype, in zip(ifaces, gtypes): ir = irs[gtype] getvalr(i, 2, ir, d, p) # side = 2 (automatic?) v = d.GetDataArray().copy() if isVector: v = v[self.comp - 1, :] if getvali is not None: getvali(i, 2, ir, d, p) # side = 2 (automatic?) vi = d.GetDataArray().copy() if isVector: vi = vi[self.comp - 1, :] v = v + 1j * vi data.append(v) data = np.hstack(data) return data
def __init__(self, model, x): self.x = x self.model = model self.J = mfem.DenseMatrix() mfem.PyCoefficient.__init__(self)
def preprocess_geometry(self, battrs, emesh_idx=0, decimate=1): # we will ignore deciamte for a moment mesh = self.mesh()[emesh_idx] self.battrs = battrs self.knowns = WKD() self.iverts = [] self.ifaces = [] if mesh.Dimension() == 3: def f1(ibele): iface, o = mesh.GetBdrElementFace(ibele) e1 = mesh.GetFaceElementTransformations(iface).Elem1No return mesh.GetAttribute(e1) def f2(ibele): iface, o = mesh.GetBdrElementFace(ibele) e2 = mesh.GetFaceElementTransformations(iface).Elem2No if e2 >= 0: return mesh.GetAttribute(e2) else: return -1 getface = mesh.GetBdrElementFace gettrans = mesh.GetBdrElementTransformation getarray = mesh.GetBdrArray getelement = mesh.GetBdrElement getbasegeom = mesh.GetBdrElementBaseGeometry getvertices = mesh.GetBdrElementVertices getattr1 = f1 getattr2 = f2 elif mesh.Dimension() == 2: def getface(x): return (x, 1) gettrans = mesh.GetElementTransformation getarray = mesh.GetDomainArray getelement = mesh.GetElement getbasegeom = mesh.GetElementBaseGeometry getvertices = mesh.GetElementVertices getattr1 = mesh.GetAttribute def getattr2(x): return -1 else: assert False, "NCFace Evaluator is not supported for this dimension" x = [getarray(battr) for battr in battrs] if np.sum([len(xx) for xx in x]) == 0: return ibdrs = np.hstack(x).astype(int).flatten() self.ibeles = np.array(ibdrs) ptx = [] data = [] ridx = [] ifaces = [] self.gtypes = np.zeros(len(self.ibeles), dtype=int) self.elattr1 = np.zeros(len(self.ibeles), dtype=int) self.elattr2 = np.zeros(len(self.ibeles), dtype=int) self.irs = {} gtype_st = -1 nele = 0 p = mfem.DenseMatrix() for k, i in enumerate(self.ibeles): verts = getvertices(i) gtype = getbasegeom(i) iface, ort = getface(i) #Trs = mesh.GetFaceElementTransformations(iface) if gtype != gtype_st: RefG = GR.Refine(gtype, self.refine) ir = RefG.RefPts npt = ir.GetNPoints() ele0 = np.array(RefG.RefGeoms.ToList()).reshape(-1, len(verts)) gtype_st = gtype self.irs[gtype] = ir # we handle quad as two triangles to handle mixed element case ele = [] for eee in ele0: if len(eee) == 3: ele.append(eee) elif len(eee) == 4: x = eee[:-1] y = np.array([eee[0], eee[2], eee[3]]) ele.extend([x, y]) ele = np.array(ele) if mesh.Dimension() == 3: eir = mfem.IntegrationRule(ir.GetNPoints()) fi = mesh.GetBdrFace(i) Transf = mesh.GetFaceElementTransformations(fi) Transf.Loc1.Transform(ir, eir) Transf.Elem1.Transform(eir, p) pt = p.GetDataArray().copy().transpose() elif mesh.Dimension() == 2: T = gettrans(i) T.Transform(ir, p) pt = p.GetDataArray().copy().transpose() #pt = np.vstack([T.Transform(ir.IntPoint(j)) for j in range(npt)]) ptx.append(pt) ridx.append(ele + nele) nele = nele + ir.GetNPoints() ifaces.append(iface) self.gtypes[k] = gtype self.elattr1[k] = getattr1(i) self.elattr2[k] = getattr2(i) self.ptx = np.vstack(ptx) self.ridx = np.vstack(ridx) self.ifaces = np.hstack(ifaces) self.emesh_idx = emesh_idx
def hcurln(fes1, fes2, coeff, is_complex=False, bdr='all', orderinc=1, verbose=False): mat, rstart = get_empty_map(fes2, fes1, is_complex=is_complex) mat2, rstart = get_empty_map(fes2, fes1, is_complex=is_complex) from petram.helper.element_map import map_element name_fes1 = fes1.FEColl().Name()[:2] name_fes2 = fes2.FEColl().Name()[:2] if verbose: if myid == 0: dprint1("fes", name_fes1, name_fes2) mesh1 = fes1.GetMesh() mesh2 = fes2.GetMesh() mesh2.Print("/home/shiraiwa/part.mesh") if verbose: if myid == 0: dprint1("NE", mesh1.GetNE(), mesh2.GetNE()) elmap, elmap_r = map_element(mesh1, mesh2, bdr, map_bdr=True) sdim1 = mesh1.SpaceDimension() sdim2 = mesh1.SpaceDimension() dim1 = mesh1.Dimension() dim2 = mesh2.Dimension() shape1 = mfem.DenseMatrix() shape2 = mfem.Vector() ip = mfem.IntegrationPoint() nor = mfem.Vector(sdim1) if USE_PARALLEL: # this is global TrueDoF (offset is not subtracted) P = fes1.Dof_TrueDof_Matrix() P1mat = ToScipyCoo(P).tocsr() #VDoFtoGTDoF1 = P.indices #P = fes2.Dof_TrueDof_Matrix() #P = ToScipyCoo(P).tocsr() #VDoFtoGTDoF2 = P.indices #P2mat = P vdofs1_senddata = [] shared_data = [] el2_2_node = {} el2_2_el1 = {} for d in elmap_r: for x in list(elmap_r[d]): el2_2_node[x] = d for x in list(elmap_r[d]): el2_2_el1[x] = elmap_r[d][x] # working for fes2 # find boundary element on mesh1 using mesh2 boundary el2_arr = [list() for x in range(nprc)] el1_arr = [list() for x in range(nprc)] fe2o_arr = [list() for x in range(nprc)] for i_el in range(fes2.GetNE()): attr = fes2.GetAttribute(i_el) if bdr != 'all' and not attr in bdr: continue el1_arr[el2_2_node[i_el]].append(el2_2_el1[i_el]) el2_arr[el2_2_node[i_el]].append(i_el) fe2 = fes2.GetFE(i_el) fe2o_arr[el2_2_node[i_el]].append(fe2.GetOrder()) if USE_PARALLEL: el1_arr = alltoall_vector(el1_arr, int) # transfer to mesh1 owners # working for fes1 # find elemet order on mesh1 fe1o_arr = [list() for x in range(nprc)] i_fe1_arr = [list() for x in range(nprc)] rank = 0 for rank, i_bdrs in enumerate(el1_arr): for i_bdr in i_bdrs: iface = mesh1.GetBdrElementEdgeIndex(i_bdr) transs = mesh1.GetFaceElementTransformations(iface) i_el1 = transs.Elem1No assert transs.Elem2No == -1, "boundary must be exterior for this operator" fe1 = fes1.GetFE(i_el1) fe1o_arr[rank].append(fe1.GetOrder()) i_fe1_arr[rank].append(i_el1) rank = rank + 1 if USE_PARALLEL: fe1o_arr = alltoall_vector(fe1o_arr, int) # transfer to mesh2 # working for fes2 locnor_arr = [list() for x in range(nprc)] data2_arr = [list() for x in range(nprc)] verbose1 = verbose for rank, i_el2s in enumerate(el2_arr): for i_el2, fe1o in zip(i_el2s, fe1o_arr[rank]): eltrans = fes2.GetElementTransformation(i_el2) fe2 = fes2.GetFE(i_el2) nd2 = fe2.GetDof() ir = get_rule(fe1o, fe2, eltrans, orderinc=orderinc, verbose=verbose1) verbose1 = False shape2.SetSize(nd2) data2 = [] locnors = [] for jj in range(ir.GetNPoints()): ip1 = ir.IntPoint(jj) eltrans.SetIntPoint(ip1) w = eltrans.Weight() * ip1.weight mfem.CalcOrtho(eltrans.Jacobian(), nor) nor2 = nor.GetDataArray() / np.linalg.norm(nor.GetDataArray()) fe2.CalcShape(ip1, shape2) if dim2 == 1: d = np.array([ip1.x] + list(eltrans.Transform(ip1)) + list(nor2)) locnors.append(d) elif dim2 == 2: d = np.array([ip1.x, ip1.y] + list(eltrans.Transform(ip1)) + list(nor2)) locnors.append(d) else: assert False, "boundary mesh must be dim=1 or 2" data2.append(w * shape2.GetDataArray().copy()) # np.vstack(locnors).shape = (#Npoints, dim2+sdim2*2) # np.vstack(data2).shape = (#Npoints, #NDoF2) #print("size here", np.vstack(locnors).shape, np.vstack(data2).shape) locnor_arr[rank].append(np.vstack(locnors)) data2_arr[rank].append(np.vstack(data2)) if USE_PARALLEL: locnor_arr = alltoall_vectorv(locnor_arr, float) # transfer to mesh1 ll = dim2 + 2 * sdim2 vdofs1_arr = [list() for x in range(nprc)] data1_arr = [list() for x in range(nprc)] # space to compute the coefficient MV = [mfem.Vector(sdim1), mfem.DenseMatrix(sdim1, sdim1)] max_misalignment = -np.inf for rank, i_fe1s in enumerate(i_fe1_arr): locnorss = locnor_arr[rank] sign_dict = {} for k, i_fe1 in enumerate(i_fe1s): fe1 = fes1.GetFE(i_fe1) nd1 = fe1.GetDof() eltrans = fes1.GetElementTransformation(i_fe1) doftrans = fes1.GetElementDofTransformation(i_fe1) #ctr = eval_element_center(fe1, eltrans) locnors2 = locnorss[k] shape1.SetSize(nd1, sdim1) vdofs1 = fes1.GetElementVDofs(i_fe1) dof_sign1 = np.array([ [1 if vv >= 0 else -1 for vv in vdofs1], ]) vdofs1 = [-1 - x if x < 0 else x for x in vdofs1] mat_doftrans = get_inv_doftrans(doftrans, dof_sign1) if USE_PARALLEL: # After DofTransformation is introduced we can not use GetGlobalTDofNumber, because # element local DoF could be linked with two TrueDoFs in neighber processes # We construct submatrix of Prolongation to construct element matrix # in TrueDof space vv1 = [ P1mat.indices[P1mat.indptr[ii]:P1mat.indptr[ii + 1]] for ii in vdofs1 ] vv3 = [ P1mat.data[P1mat.indptr[ii]:P1mat.indptr[ii + 1]] for ii in vdofs1 ] ngtof = np.sum([len(x) for x in vv3]) sub_p = np.zeros((nd1, ngtof)) k1 = 0 k2 = 0 for gtofs, weights in zip(vv1, vv3): for g, w in zip(gtofs, weights): sub_p[k1, k2] = w k2 = k2 + 1 k1 = k1 + 1 vdofs1 = np.hstack(vv1).flatten() mat_doftrans = mat_doftrans.dot(sub_p) res, misalignment = map_ir(fe1, eltrans, coeff, shape1, dim2, sdim2, locnors2, dof_sign1, mat_doftrans, MV) vdofs1_arr[rank].append(np.array(vdofs1)) data1_arr[rank].append(res) max_misalignment = np.max([max_misalignment, np.max(misalignment)]) # res.shape = (#Npoints, #DoF1) if USE_PARALLEL: vdofs1_arr = alltoall_vectorv(vdofs1_arr, int) # transfer to mesh2 if is_complex: data1_arr = alltoall_vectorv(data1_arr, complex) # transfer to mesh2 else: data1_arr = alltoall_vectorv(data1_arr, float) # transfer to mesh2 max_misalignment = np.max( MPI.COMM_WORLD.gather(max_misalignment, root=0)) dprint1("Max misalignment: ", max_misalignment) shared_data = [] for rank, i_el2s in enumerate(el2_arr): for k, i_el2 in enumerate(i_el2s): vdofs1 = vdofs1_arr[rank][k] fe2 = fes2.GetFE(i_el2) eltrans2 = fes2.GetElementTransformation(i_el2) vdofs2 = fes2.GetElementVDofs(i_el2) vdofs2 = [-1 - x if x < 0 else x for x in vdofs2] d1 = data1_arr[rank][k] d2 = data2_arr[rank][k] mm = d2.transpose().dot(d1) if USE_PARALLEL: # prepare data for not-owned DoFs, which will be shared later vdofs22 = [fes2.GetLocalTDofNumber(ii) for ii in vdofs2] vdofs22g = [fes2.GetGlobalTDofNumber(ii) for ii in vdofs2] kkk = 0 for v2, v2g in zip(vdofs22, vdofs22g): if v2 < 0: shared_data.append([v2g, mm[kkk, :], vdofs1]) kkk = kkk + 1 else: vdofs22 = vdofs2 for i, ltdof2 in enumerate(vdofs22): if ltdof2 < 0: continue for j, gtdof1 in enumerate(vdofs1): mat[ltdof2, gtdof1] = mat[ltdof2, gtdof1] + mm[i, j] if USE_PARALLEL: #nicePrint("shared data", shared_data) for source_id in range(nprc): data = comm.bcast(shared_data, root=source_id) myoffset = fes2.GetMyTDofOffset() for v2g, elmat, vdofs1 in data: if v2g >= myoffset and v2g < myoffset + mat.shape[0]: i = v2g - myoffset for j, gtdof1 in enumerate(vdofs1): mat[i, gtdof1] = mat[i, gtdof1] + elmat[j] #mat[i, vdofs1] = mat[i, vdofs1] + elmat from scipy.sparse import coo_matrix, csr_matrix if USE_PARALLEL: if is_complex: m1 = csr_matrix(mat.real, dtype=float) m2 = csr_matrix(mat.imag, dtype=float) else: m1 = csr_matrix(mat.real, dtype=float) m2 = None from mfem.common.chypre import CHypreMat start_col = fes1.GetMyTDofOffset() end_col = fes1.GetMyTDofOffset() + fes1.GetTrueVSize() col_starts = [start_col, end_col, mat.shape[1]] M = CHypreMat(m1, m2, col_starts=col_starts) else: from petram.helper.block_matrix import convert_to_ScipyCoo M = convert_to_ScipyCoo(coo_matrix(mat, dtype=mat.dtype)) return M
def convolve2d(fes1, fes2, kernel=delta, support=None, orderinc=5, is_complex=False, trial_domain='all', test_domain='all', verbose=False, coeff=None): ''' fill linear operator for convolution \int phi_test(x) func(x-x') phi_trial(x') dx Genralized version to multi-dim test/trial ScalarFE, ScalarFE : func is scalar VectorFE, ScalarFE : func is vector (vertical) ScalarFE, VectorFE : func is vector (horizontal) VectorFE, VectorFE : func matrix ''' mat, rstart = get_empty_map(fes2, fes1, is_complex=is_complex) if fes1.GetNE() == 0: assert False, "FESpace does not have element" eltrans1 = fes1.GetElementTransformation(0) ir = get_rule(fes1.GetFE(0), fes2.GetFE(0), eltrans1, orderinc, verbose) name_fes1 = fes1.FEColl().Name()[:2] name_fes2 = fes2.FEColl().Name()[:2] sdim = fes1.GetMesh().SpaceDimension() if name_fes1 in ['RT', 'ND']: shape1 = mfem.DenseMatrix() vdim1 = fes1.GetMesh().SpaceDimension() else: shape1 = mfem.Vector() vdim1 = 1 if name_fes2 in ['RT', 'ND']: shape2 = mfem.DenseMatrix() vdim2 = fes1.GetMesh().SpaceDimension() else: shape2 = mfem.Vector() vdim1 = 1 #nicePrint("shape", mat.shape, fes2.GetNE(), fes1.GetNE()) # communication strategy # (1) x2 (ir points on test space) is collected in each nodes # (2) x2 is send to other nodes # (3) each nodes compute \int f(x2-x1) phi(x1) # (4) non-zero results of (3) and global index should be send back # Step (1, 2) if verbose: dprint1("Step 1,2") x2_arr = [] i2_arr = [] ptx = mfem.DenseMatrix(ir.GetNPoints(), sdim) attrs1 = fes2.GetMesh().GetAttributeArray() attrs2 = fes2.GetMesh().GetAttributeArray() for i in range(fes2.GetNE()): # scan test space if test_domain != 'all': if not attrs1[i] in test_domain: continue eltrans = fes2.GetElementTransformation(i) eltrans.Transform(ir, ptx) x2_arr.append(ptx.GetDataArray().copy().transpose()) i2_arr.append(i) if support is not None: supports = np.array([support(np.mean(xxx, 0)) for xxx in x2_arr]) else: supports = -np.ones(len(x2_arr)) if len(i2_arr) > 0: ptx_x2 = np.stack(x2_arr) i2_arr = np.hstack(i2_arr) else: ptx_x2 = np.array([[[]]]) i2_arr = np.array([]) #nicePrint("x2 shape", ptx_x2.shape) if USE_PARALLEL: ## note: we could implement more advanced alg. to reduce ## the amount of data exchange.. x2_all = comm.allgather(ptx_x2) i2_all = comm.allgather(i2_arr) s_all = comm.allgather(supports) else: x2_all = [ptx_x2] i2_all = [i2_arr] s_all = [supports] #nicePrint("x2_all shape", supports.shape, len(x2_all), [tmp.shape for tmp in x2_all]) if USE_PARALLEL: #this is global TrueDoF (offset is not subtracted) P = fes1.Dof_TrueDof_Matrix() P = ToScipyCoo(P).tocsr() VDoFtoGTDoF1 = P.indices P = fes2.Dof_TrueDof_Matrix() P = ToScipyCoo(P).tocsr() VDoFtoGTDoF2 = P.indices # Step 3 if verbose: dprint1("Step 3") vdofs1_senddata = [] elmats_senddata = [] for knode1 in range(len(x2_all)): #dprint1("new knode1", myid, knode1) x2_onenode = x2_all[knode1] i2_onenode = i2_all[knode1] s_onenode = s_all[knode1] elmats_all = [] vdofs1_all = [] # collect vdofs for j in range(fes1.GetNE()): local_vdofs = fes1.GetElementVDofs(j) local_vdofs = [vv if vv >= 0 else -1 - vv for vv in local_vdofs] if USE_PARALLEL: subvdofs2 = [VDoFtoGTDoF1[i] for i in local_vdofs] vdofs1_all.append(subvdofs2) else: vdofs1_all.append(local_vdofs) #if myid == 0: # pr = profile_start() for i, x2s, su in zip(i2_onenode, x2_onenode, s_onenode): # loop over fes2 nd2 = len(x2s) #nicePrint("x2s", i, x2s.shape, x2s) elmats = [] for j in range(fes1.GetNE()): if trial_domain != 'all': if not attrs1[j] in trial_domain: continue # collect integration fe1 = fes1.GetFE(j) nd1 = fe1.GetDof() eltrans = fes1.GetElementTransformation(j) dof_sign1 = np.array( [1 if vv >= 0 else -1 for vv in fes1.GetElementVDofs(j)]) if name_fes1 in ['RT', 'ND']: shape1.SetSize(nd1, vdim1) else: shape1.SetSize(nd1) elmat = np.zeros((nd2, vdim2, nd1), dtype=mat.dtype) tmp_int = np.zeros((vdim2, nd1), dtype=mat.dtype).squeeze() #if myid == 0: print("fes1 idx", j) dataset = [] shapes = [] for jj in range(ir.GetNPoints()): ip1 = ir.IntPoint(jj) eltrans.SetIntPoint(ip1) x1 = eltrans.Transform(ip1) if name_fes1 in ['RT', 'ND']: fe1.CalcVShape(eltrans, shape1) else: fe1.CalcShape(ip1, shape1) w = eltrans.Weight() * ip1.weight ss = shape1.GetDataArray().copy() if len(ss.shape) > 1: #dof_sign1 = dof_sign1.reshape(-1, 1) ss = np.transpose(ss) ss = ss * dof_sign1 dataset.append((x1, w, ss)) has_contribution = False for kkk, x2 in enumerate(x2s): tmp_int *= 0.0 has_contribution2 = False for x1, w, shape_arr in dataset: s = np.sqrt(np.sum((x1 - x2)**2)) if su >= 0 and s > su: continue val = kernel(x2 - x1, (x2 + x1) / 2.0, w=w) if val is None: continue if coeff is not None: val = val * coeff((x2 + x1) / 2.0) tmp_int += np.dot(val, shape_arr) * w has_contribution2 = True if has_contribution2: elmat[kkk, ...] = tmp_int has_contribution = True if has_contribution: elmats.append((j, elmat)) #if myid == 0: # pr.dump_stats("/home/shiraiwa/test.prf") # profile_stop(pr) # assert False, "hoge" # pr = profile_start() if len(elmats) > 0: elmats_all.append((i, elmats)) vdofs1_senddata.append(vdofs1_all) elmats_senddata.append(elmats_all) # send this information to knodes; ''' if USE_PARALLEL: #nicePrint(vdofs1_all) #nicePrint("elmats", [len(x) for x in elmats_all]) if myid == knode1: vdofs1_data = comm.gather(vdofs1_all, root=knode1) elmats_data = comm.gather(elmats_all, root=knode1) else: _ = comm.gather(vdofs1_all, root=knode1) _ = comm.gather(elmats_all, root=knode1) else: vdofs1_data = [vdofs1_all,] elmats_data = [elmats_all,] ''' if USE_PARALLEL: knode1 = 0 for vdofs1_all, elmats_all in zip(vdofs1_senddata, elmats_senddata): if myid == knode1: vdofs1_data = comm.gather(vdofs1_all, root=knode1) elmats_data = comm.gather(elmats_all, root=knode1) else: _ = comm.gather(vdofs1_all, root=knode1) _ = comm.gather(elmats_all, root=knode1) knode1 = knode1 + 1 else: vdofs1_data = vdofs1_senddata elmats_data = elmats_senddata # Step 4 if verbose: dprint1("Step 4") shared_data = [] mpi_rank = 0 for vdofs1, elmats_all in zip(vdofs1_data, elmats_data): # loop over MPI nodes #nicePrint("len elmats", len(elmats_all)) #for i, elmats in enumerate(elmats_all): # corresponds to loop over fes2 if verbose: coupling = [len(elmats) for i, elmats in elmats_all] nicePrint("Element coupling for rank/count", mpi_rank, len(coupling)) nicePrint(" Average :", (0 if len(coupling) == 0 else np.mean(coupling))) nicePrint(" Max/Min :", (0 if len(coupling) == 0 else np.max(coupling)), (0 if len(coupling) == 0 else np.min(coupling))) mpi_rank += 1 for i, elmats in elmats_all: # corresponds to loop over fes2 vdofs2 = fes2.GetElementVDofs(i) dof_sign2 = np.array([ [1 if vv >= 0 else -1 for vv in vdofs2], ]).transpose() vdofs2 = [-1 - x if x < 0 else x for x in vdofs2] fe2 = fes2.GetFE(i) nd2 = fe2.GetDof() if name_fes2 in ['RT', 'ND']: shape2.SetSize(nd2, vdim2) else: shape2.SetSize(nd2) eltrans = fes2.GetElementTransformation(i) #for j, elmat in enumerate(elmats): for j, elmat in elmats: #print(vdofs1[j], elmat.shape) #if elmat is None: # continue mm = np.zeros((len(vdofs2), len(vdofs1[j])), dtype=float) for ii in range(ir.GetNPoints()): ip2 = ir.IntPoint(ii) eltrans.SetIntPoint(ip2) ww = eltrans.Weight() * ip2.weight if name_fes2 in ['RT', 'ND']: fe2.CalcVShape(eltrans, shape2) else: fe2.CalcShape(ip2, shape2) shape2 *= ww ss = shape2.GetDataArray().reshape(-1, vdim2) ss = ss * dof_sign2 tmp_int = elmat[ii, ...].reshape(vdim1, -1) tmp = np.dot(ss, tmp_int) mm = mm + tmp # preapre shared data if USE_PARALLEL: vdofs22 = [fes2.GetLocalTDofNumber(ii) for ii in vdofs2] vdofs22g = [VDoFtoGTDoF2[ii] for ii in vdofs2] kkk = 0 #for v2, v2g in zip(vdofs22, vdofs22g): for v2, v2g in zip(vdofs22, vdofs22g): if v2 < 0: shared_data.append([v2g, mm[kkk, :], vdofs1[j]]) kkk = kkk + 1 # merge contribution to final mat for k, vv in enumerate(vdofs1[j]): try: if USE_PARALLEL: mmm = mm[np.where(np.array(vdofs22) >= 0)[0], :] vdofs222 = [x for x in vdofs22 if x >= 0] else: vdofs222 = vdofs2 mmm = mm #if myid == 1: # print("check here", vdofs2, vdofs22, vdofs222) #print(mmm[:, [k]]) tmp = mat[vdofs222, vv] + mmm[:, [k]] mat[vdofs222, vv] = tmp.flatten() except: import traceback print("error", myid) #print(vdofs1, vdofs22, vdofs222, mmm.shape, k) traceback.print_exc() if USE_PARALLEL: for source_id in range(nprc): data = comm.bcast(shared_data, root=source_id) myoffset = fes2.GetMyTDofOffset() for v2g, elmat, vdofs1 in data: if v2g >= myoffset and v2g < myoffset + mat.shape[0]: i = v2g - myoffset #print("procesising this", myid, i, v2g, elmat, vdofs1) mat[i, vdofs1] = mat[i, vdofs1] + elmat from scipy.sparse import coo_matrix, csr_matrix if USE_PARALLEL: if is_complex: m1 = csr_matrix(mat.real, dtype=float) m2 = csr_matrix(mat.imag, dtype=float) else: m1 = csr_matrix(mat.real, dtype=float) m2 = None from mfem.common.chypre import CHypreMat start_col = fes1.GetMyTDofOffset() end_col = fes1.GetMyTDofOffset() + fes1.GetTrueVSize() col_starts = [start_col, end_col, mat.shape[1]] M = CHypreMat(m1, m2, col_starts=col_starts) else: from petram.helper.block_matrix import convert_to_ScipyCoo M = convert_to_ScipyCoo(coo_matrix(mat, dtype=mat.dtype)) return M
def convolve1d(fes1, fes2, kernel=delta, support=None, orderinc=5, is_complex=False, trial_domain='all', test_domain='all', verbose=False, coeff=None): ''' fill linear operator for convolution \int phi_test(x) func(x-x') phi_trial(x') dx ''' mat, rstart = get_empty_map(fes2, fes1, is_complex=is_complex) eltrans1 = fes1.GetElementTransformation(0) ir = get_rule(fes1.GetFE(0), fes2.GetFE(0), eltrans1, orderinc, verbose) shape1 = mfem.Vector() shape2 = mfem.Vector() #nicePrint("shape", mat.shape, fes2.GetNE(), fes1.GetNE()) # communication strategy # (1) x2 (ir points on test space) is collected in each nodes # (2) x2 is send to other nodes # (3) each nodes compute \int f(x2-x1) phi(x1) # (4) non-zero results of (3) and global index should be send back # Step (1, 2) if verbose: dprint1("Step 1,2") x2_arr = [] i2_arr = [] ptx = mfem.DenseMatrix(ir.GetNPoints(), 1) attrs1 = fes2.GetMesh().GetAttributeArray() attrs2 = fes2.GetMesh().GetAttributeArray() for i in range(fes2.GetNE()): # scan test space if test_domain != 'all': if not attrs1[i] in test_domain: continue eltrans = fes2.GetElementTransformation(i) eltrans.Transform(ir, ptx) x2_arr.append(ptx.GetDataArray().copy()) i2_arr.append(i) if len(i2_arr) > 0: ptx_x2 = np.vstack(x2_arr) i2_arr = np.hstack(i2_arr) else: ptx_x2 = np.array([[]]) i2_arr = np.array([]) #nicePrint("x2 shape", ptx_x2.shape) if USE_PARALLEL: ## note: we could implement more advanced alg. to reduce ## the amount of data exchange.. x2_all = comm.allgather(ptx_x2) i2_all = comm.allgather(i2_arr) else: x2_all = [ptx_x2] i2_all = [i2_arr] #nicePrint("x2_all shape", x2_all.shape) if USE_PARALLEL: #this is global TrueDoF (offset is not subtracted) P = fes1.Dof_TrueDof_Matrix() P = ToScipyCoo(P).tocsr() VDoFtoGTDoF1 = P.indices P = fes2.Dof_TrueDof_Matrix() P = ToScipyCoo(P).tocsr() VDoFtoGTDoF2 = P.indices # Step 3 if verbose: dprint1("Step 3") vdofs1_senddata = [] elmats_senddata = [] for knode1 in range(len(x2_all)): x2_onenode = x2_all[knode1] i2_onenode = i2_all[knode1] elmats_all = [] vdofs1_all = [] # collect vdofs for j in range(fes1.GetNE()): local_vdofs = fes1.GetElementVDofs(j) if USE_PARALLEL: subvdofs2 = [VDoFtoGTDoF1[i] for i in local_vdofs] vdofs1_all.append(subvdofs2) else: vdofs1_all.append(local_vdofs) for i, x2s in zip(i2_onenode, x2_onenode): # loop over fes2 nd2 = len(x2s) #nicePrint(x2s) elmats = [] for j in range(fes1.GetNE()): if trial_domain != 'all': if not attrs1[j] in trial_domain: continue # collect integration fe1 = fes1.GetFE(j) nd1 = fe1.GetDof() shape1.SetSize(nd1) eltrans = fes1.GetElementTransformation(j) tmp_int = np.zeros(shape1.Size(), dtype=mat.dtype) elmat = np.zeros((nd2, nd1), dtype=mat.dtype) #if myid == 0: print("fes1 idx", j) dataset = [] for jj in range(ir.GetNPoints()): ip1 = ir.IntPoint(jj) eltrans.SetIntPoint(ip1) x1 = eltrans.Transform(ip1)[0] fe1.CalcShape(ip1, shape1) w = eltrans.Weight() * ip1.weight dataset.append((x1, w, shape1.GetDataArray().copy())) has_contribution = False for kkk, x2 in enumerate(x2s): tmp_int *= 0.0 for x1, w, shape_arr in dataset: if support is not None: s = support((x1 + x2) / 2.0) if np.abs(x1 - x2) > s: continue has_contribution = True #if myid == 0: print("check here", x1, x2) val = kernel(x2 - x1, (x2 + x1) / 2.0, w=w) if coeff is not None: val = val * coeff((x2 + x1) / 2.0) #shape_arr *= w*val tmp_int += shape_arr * w * val elmat[kkk, :] = tmp_int if has_contribution: elmats.append((j, elmat)) #print(elmats) if len(elmats) > 0: elmats_all.append((i, elmats)) vdofs1_senddata.append(vdofs1_all) elmats_senddata.append(elmats_all) # send this information to knodes; ''' if USE_PARALLEL: #nicePrint(vdofs1_all) #nicePrint("elmats", [len(x) for x in elmats_all]) if myid == knode1: vdofs1_data = comm.gather(vdofs1_all, root=knode1) elmats_data = comm.gather(elmats_all, root=knode1) else: _ = comm.gather(vdofs1_all, root=knode1) _ = comm.gather(elmats_all, root=knode1) else: vdofs1_data = [vdofs1_all,] elmats_data = [elmats_all,] ''' if USE_PARALLEL: knode1 = 0 for vdofs1_all, elmats_all in zip(vdofs1_senddata, elmats_senddata): if myid == knode1: vdofs1_data = comm.gather(vdofs1_all, root=knode1) elmats_data = comm.gather(elmats_all, root=knode1) else: _ = comm.gather(vdofs1_all, root=knode1) _ = comm.gather(elmats_all, root=knode1) knode1 = knode1 + 1 else: vdofs1_data = vdofs1_senddata elmats_data = elmats_senddata # Step 4 if verbose: dprint1("Step 4") shared_data = [] mpi_rank = 0 for vdofs1, elmats_all in zip(vdofs1_data, elmats_data): # loop over MPI nodes #nicePrint("len elmats", len(elmats_all)) #for i, elmats in enumerate(elmats_all): # corresponds to loop over fes2 if verbose: coupling = [len(elmats) for i, elmats in elmats_all] nicePrint("Element coupling for rank", mpi_rank) nicePrint(" Average :", (0 if len(coupling) == 0 else np.mean(coupling))) nicePrint(" Max/Min :", (0 if len(coupling) == 0 else np.max(coupling)), (0 if len(coupling) == 0 else np.min(coupling))) mpi_rank += 1 for i, elmats in elmats_all: # corresponds to loop over fes2 vdofs2 = fes2.GetElementVDofs(i) fe2 = fes2.GetFE(i) nd2 = fe2.GetDof() shape2.SetSize(nd2) eltrans = fes2.GetElementTransformation(i) #for j, elmat in enumerate(elmats): for j, elmat in elmats: #print(vdofs1[j], elmat.shape) #if elmat is None: # continue mm = np.zeros((len(vdofs2), len(vdofs1[j])), dtype=float) for ii in range(ir.GetNPoints()): ip2 = ir.IntPoint(ii) eltrans.SetIntPoint(ip2) ww = eltrans.Weight() * ip2.weight fe2.CalcShape(ip2, shape2) shape2 *= ww tmp_int = elmat[ii, :] tmp = np.dot( np.atleast_2d(shape2.GetDataArray()).transpose(), np.atleast_2d(tmp_int)) mm = mm + tmp #print("check here", myid, mm.shape, tmp.shape) # merge contribution to final mat if USE_PARALLEL: vdofs22 = [fes2.GetLocalTDofNumber(ii) for ii in vdofs2] vdofs22g = [VDoFtoGTDoF2[ii] for ii in vdofs2] kkk = 0 for v2, v2g in zip(vdofs22, vdofs22g): if v2 < 0: shared_data.append([v2g, mm[kkk, :], vdofs1[j]]) kkk = kkk + 1 for k, vv in enumerate(vdofs1[j]): try: if USE_PARALLEL: mmm = mm[np.where(np.array(vdofs22) >= 0)[0], :] vdofs222 = [x for x in vdofs22 if x >= 0] else: vdofs222 = vdofs2 mmm = mm #if myid == 1: # print("check here", vdofs2, vdofs22, vdofs222) #print(mmm[:, [k]]) tmp = mat[vdofs222, vv] + mmm[:, [k]] mat[vdofs222, vv] = tmp.flatten() except: import traceback print("error", myid) #print(vdofs1, vdofs22, vdofs222, mmm.shape, k) traceback.print_exc() if USE_PARALLEL: for source_id in range(nprc): data = comm.bcast(shared_data, root=source_id) myoffset = fes2.GetMyTDofOffset() for v2g, elmat, vdofs1 in data: if v2g >= myoffset and v2g < myoffset + mat.shape[0]: i = v2g - myoffset #print("procesising this", myid, i, v2g, elmat, vdofs1) mat[i, vdofs1] = mat[i, vdofs1] + elmat from scipy.sparse import coo_matrix, csr_matrix if USE_PARALLEL: if is_complex: m1 = csr_matrix(mat.real, dtype=float) m2 = csr_matrix(mat.imag, dtype=float) else: m1 = csr_matrix(mat.real, dtype=float) m2 = None from mfem.common.chypre import CHypreMat start_col = fes1.GetMyTDofOffset() end_col = fes1.GetMyTDofOffset() + fes1.GetTrueVSize() col_starts = [start_col, end_col, mat.shape[1]] M = CHypreMat(m1, m2, col_starts=col_starts) #print("mat", M) else: from petram.helper.block_matrix import convert_to_ScipyCoo M = convert_to_ScipyCoo(coo_matrix(mat, dtype=mat.dtype)) return M
def __init__(self, value): v = mfem.Vector(np.transpose(value).flatten()) m = mfem.DenseMatrix(v.GetData(), value.shape[0], value.shape[1]) self.value = (v,m) mfem.MatrixConstantCoefficient.__init__(self, m)
def eval_shape(order = 1, refine = 5, elem_type = 0, fec = 'ND'): if fec == 'ND': fec_type = mfem.ND_FECollection if order < 1: assert False, "ND order is 1 and above" elif fec == 'RT': fec_type = mfem.RT_FECollection elif fec == 'H1': fec_type = mfem.H1_FECollection if order < 1: assert False, "H1 order is 1 and above" elif fec == 'L2': fec_type = mfem.L2_FECollection else: assert False, "unknown basis" if elem_type == 0: Nvert = 3; Nelem = 1; spaceDim = 2 elif elem_type == 1: Nvert = 4; Nelem = 1; spaceDim = 2 mesh = mfem.Mesh(2, Nvert, Nelem, 0, spaceDim) if elem_type == 0: tri_v = [[1., 0.3 ], [0., 1.,], [0, 0]] tri_e = [[0, 1, 2], ] for j in range(Nvert): mesh.AddVertex(tri_v[j]) for j in range(Nelem): mesh.AddTriangle(tri_e[j], j+1) mesh.FinalizeTriMesh(1,1, True) else: quad_v = [[-1, -1.3, ], [+1, -1, ], [+1, +1, ], [-1, +1,]] quad_e = [[0, 1, 2, 3]] for j in range(Nvert): mesh.AddVertex(quad_v[j]) for j in range(Nelem): mesh.AddQuad(quad_e[j], j+1) mesh.FinalizeQuadMesh(1,1, True) #mesh.PrintToFile('plot_basis.mesh', 8) fe_coll = fec_type(order, spaceDim) fespace = mfem.FiniteElementSpace(mesh, fe_coll) x = mfem.GridFunction(fespace) x.Assign(0.0) x[0] = 1.0 idx = 0 geom = mesh.GetElementBaseGeometry(idx) T = mesh.GetElementTransformation(idx) fe = fespace.GetFE(idx) fe_nd = fe.GetDof() ir = fe.GetNodes() npt = ir.GetNPoints() dof = np.vstack([T.Transform(ir.IntPoint(i)) for i in range(npt)]) RefG = mfem.GlobGeometryRefiner.Refine(geom, refine, 1); ir = RefG.RefPts npt = ir.GetNPoints() ptx = np.vstack([T.Transform(ir.IntPoint(i)) for i in range(npt)]) shape = [] if fec == 'ND' or fec == 'RT': mat = mfem.DenseMatrix(fe_nd, spaceDim) shape_func = fe.CalcVShape for i in range(npt): ip = ir.IntPoint(i) T.SetIntPoint(ip) fe.CalcVShape(T, mat) shape.append(mat.GetDataArray().copy()) else: vec = mfem.Vector(fe_nd) for i in range(npt): ip = ir.IntPoint(i) fe.CalcShape(ip, vec) shape.append(vec.GetDataArray().copy()) return dof, ptx, np.stack(shape)