def set_point(self, T, ip, g, l, t=None): self.x = T.Transform(ip) self.t = t T.SetIntPoint(ip) nor = mfem.Vector(self.sdim) mfem.CalcOrtho(T.Jacobian(), nor) self.nor = nor.GetDataArray().copy()
def ncface_values(self, ifaces=None, irs=None, gtypes=None, locs=None, mesh=None, **kwargs): size = len(locs) ret = np.zeros((size, self.sdim)) if ifaces is None: return nor = mfem.Vector(self.sdim) if mesh.Dimension() == 3: m = mesh.GetFaceTransformation elif mesh.Dimension() == 2: m = mesh.GetElementTransformation idx = 0 for i, gtype, in zip(ifaces, gtypes): ir = irs[gtype] nv = ir.GetNPoints() T = m(i) for j in range(nv): T.SetIntPoint(ir.IntPoint(i)) mfem.CalcOrtho(T.Jacobian(), nor) ret[idx, :] = nor.GetDataArray().copy() idx = idx + 1 from petram.helper.right_broadcast import div ret = div(ret, np.sqrt(np.sum(ret**2, -1))) if self.comp == -1: return ret return ret[:, self.comp - 1]
def nodal_values(self, ibele=None, mesh=None, iverts_f=None, **kwargs): # iele = None, elattr = None, el2v = None, # wverts = None, locs = None, g = None g = mfem.Geometry() size = len(iverts_f) #wverts = np.zeros(size) ret = np.zeros((size, self.sdim)) if ibele is None: return ibe = ibele[0] el = mesh.GetBdrElement(ibe) rule = g.GetVertices(el.GetGeometryType()) nv = rule.GetNPoints() for ibe in ibele: T = mesh.GetBdrElementTransformation(ibe) bverts = mesh.GetBdrElement(ibe).GetVerticesArray() for i in range(nv): nor = mfem.Vector(self.sdim) T.SetIntPoint(rule.IntPoint(i)) mfem.CalcOrtho(T.Jacobian(), nor) idx = np.searchsorted(iverts_f, bverts[i]) ret[idx, :] += nor.GetDataArray().copy() #wverts[idx] = wverts[idx] + 1 #for i in range(self.sdim): ret[:,i] /= wvert # normalize to length one. ret = ret / np.sqrt(np.sum(ret**2, 1)).reshape(-1, 1) if self.comp == -1: return ret return ret[:, self.comp - 1]
def preprocess_params(self, engine): ### find normal (outward) vector... mesh = engine.get_emesh(mm=self) fespace = engine.fespaces[self.get_root_phys().dep_vars[0]] nbe = mesh.GetNBE() ibe = np.array([ i for i in range(nbe) if mesh.GetBdrElement(i).GetAttribute() == self._sel_index[0] ]) dprint1("idb", ibe) el = mesh.GetBdrElement(ibe[0]) Tr = fespace.GetBdrElementTransformation(ibe[0]) rules = mfem.IntegrationRules() ir = rules.Get(el.GetGeometryType(), 1) Tr.SetIntPoint(ir.IntPoint(0)) nor = mfem.Vector(2) mfem.CalcOrtho(Tr.Jacobian(), nor) self.norm = nor.GetDataArray().copy() self.norm = self.norm / np.sqrt(np.sum(self.norm**2)) dprint1("Normal Vector " + list(self.norm).__repr__()) ### find rectangular shape edges = np.array([mesh.GetBdrElementEdges(i)[0] for i in ibe]).flatten() d = {} for x in edges: d[x] = x in d edges = [x for x in d.keys() if not d[x]] ivert = [mesh.GetEdgeVertices(x) for x in edges] ivert = connect_pairs2(ivert)[0] vv = np.vstack([mesh.GetVertexArray(i) for i in ivert]) self.ctr = (vv[0] + vv[-1]) / 2.0 dprint1("Center " + list(self.ctr).__repr__()) ### rectangular port self.a_vec = (vv[0] - vv[-1]) self.a = np.sqrt(np.sum(self.a_vec**2)) self.a_vec /= self.a self.c = vv[-1] dprint1("Cornor " + self.c.__repr__()) dprint1("Edge " + self.a.__repr__()) dprint1("Edge Vec." + list(self.a_vec).__repr__()) Erz, Ephi = self.get_e_coeff_cls() Hrz, Hphi = self.get_h_coeff_cls() if self.mode == 'TE': dprint1("E field pattern") c1 = Ephi(self, real=True) c2 = Hphi(0.0, self, real=False) for p in vv: dprint1(p.__repr__() + ' : ' + c1.EvalValue(p).__repr__()) dprint1("H field pattern") for p in vv: dprint1(p.__repr__() + ' : ' + c2.EvalValue(p).__repr__())
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 set_point(self, T, ip, g, l, t=None): nor = mfem.Vector(self.sdim) mfem.CalcOrtho(T.Jacobian(), nor) self.nor = nor.GetDataArray().copy()
def preprocess_params(self, engine): ### find normal (outward) vector... mesh = engine.get_emesh(mm=self) ### fespace = engine.fespaces[self.get_root_phys().dep_vars[0]] nbe = mesh.GetNBE() ibe = np.array([ i for i in range(nbe) if mesh.GetBdrElement(i).GetAttribute() == self._sel_index[0] ]) dprint1("idb", ibe) el = mesh.GetBdrElement(ibe[0]) Tr = fespace.GetBdrElementTransformation(ibe[0]) rules = mfem.IntegrationRules() ir = rules.Get(el.GetGeometryType(), 1) Tr.SetIntPoint(ir.IntPoint(0)) nor = mfem.Vector(3) mfem.CalcOrtho(Tr.Jacobian(), nor) self.norm = nor.GetDataArray().copy() self.norm = self.norm / np.sqrt(np.sum(self.norm**2)) #freq = self._global_ns["freq"] #self.omega = freq * 2 * np.pi #dprint1("Frequency " + (freq).__repr__()) dprint1("Normal Vector " + list(self.norm).__repr__()) ### find rectangular shape if str(self.mode).upper().strip() in ['TE', 'TM', 'TEM']: edges = np.array([mesh.GetBdrElementEdges(i)[0] for i in ibe]).flatten() d = {} for x in edges: d[x] = x in d edges = [x for x in d.keys() if not d[x]] ivert = [mesh.GetEdgeVertices(x) for x in edges] ivert = connect_pairs(ivert) vv = np.vstack([mesh.GetVertexArray(i) for i in ivert]) self.ctr = (np.max(vv, 0) + np.min(vv, 0)) / 2.0 dprint1("Center " + list(self.ctr).__repr__()) ### rectangular port #idx = np.argsort(np.sqrt(np.sum((vv - self.ctr)**2,1))) #corners = vv[idx[-4:],:] # since vv is cyclic I need to omit last one element here.. idx = np.argsort(np.sqrt(np.sum((vv[:-1] - self.ctr)**2, 1))) corners = vv[:-1][idx[-4:], :] for i in range(4): dprint1("Corner " + list(corners[i]).__repr__()) tmp = np.sort(np.sqrt(np.sum((corners - corners[0, :])**2, 1))) self.b = tmp[1] self.a = tmp[2] tmp = np.argsort(np.sqrt(np.sum((corners - corners[0, :])**2, 1))) self.c = corners[0] # corner self.b_vec = corners[tmp[1]] - corners[0] self.a_vec = np.cross(self.b_vec, self.norm) # self.a_vec = corners[tmp[2]]-corners[0] self.b_vec = self.b_vec / np.sqrt(np.sum(self.b_vec**2)) self.a_vec = self.a_vec / np.sqrt(np.sum(self.a_vec**2)) if np.sum(np.cross(self.a_vec, self.b_vec) * self.norm) > 0: self.a_vec = -self.a_vec if self.mode == 'TEM': ''' special handling set a vector along PEC-like edge, regardless the actual length of edges ''' for i in range(nbe): if (edges[0] in mesh.GetBdrElementEdges(i)[0] and self._sel_index[0] != mesh.GetBdrAttribute(i)): dprint1("Checking surface :", mesh.GetBdrAttribute(i)) attr = mesh.GetBdrAttribute(i) break for node in self.get_root_phys().walk(): if not isinstance(node, Bdry): continue if not node.enabled: continue if attr in node._sel_index: break from petram.model import Pair ivert = mesh.GetEdgeVertices(edges[0]) vect = mesh.GetVertexArray(ivert[0]) - mesh.GetVertexArray( ivert[1]) vect = vect / np.sqrt(np.sum(vect**2)) do_swap = False if (isinstance(node, Pair) and np.abs(np.sum(self.a_vec * vect)) > 0.9): do_swap = True if (not isinstance(node, Pair) and np.abs(np.sum(self.a_vec * vect)) < 0.001): do_swap = True if do_swap: dprint1("swapping port edges") tmp = self.a_vec self.a_vec = -self.b_vec self.b_vec = tmp # - sign is to keep a \times b direction. tmp = self.a self.a = self.b self.b = tmp if self.a_vec[np.argmax(np.abs(self.a_vec))] < 0: self.a_vec = -self.a_vec self.b_vec = -self.b_vec dprint1("Long Edge " + self.a.__repr__()) dprint1("Long Edge Vec." + list(self.a_vec).__repr__()) dprint1("Short Edge " + self.b.__repr__()) dprint1("Short Edge Vec." + list(self.b_vec).__repr__()) elif self.mode == 'Coax(TEM)': edges = np.array([mesh.GetBdrElementEdges(i)[0] for i in ibe]).flatten() d = {} for x in edges: d[x] = x in d edges = [x for x in d.keys() if not d[x]] ivert = [mesh.GetEdgeVertices(x) for x in edges] iv1, iv2 = connect_pairs(ivert) # index of outer/inner circles vv1 = np.vstack([mesh.GetVertexArray(i) for i in iv1]) vv2 = np.vstack([mesh.GetVertexArray(i) for i in iv2]) ctr1, a1 = find_circle_center_radius(vv1, self.norm) ctr2, b1 = find_circle_center_radius(vv2, self.norm) self.ctr = np.mean((ctr1, ctr2), 0) self.a = a1 if a1 < b1 else b1 self.b = a1 if a1 > b1 else b1 dprint1("Big R: " + self.b.__repr__()) dprint1("Small R: " + self.a.__repr__()) dprint1("Center: " + self.ctr.__repr__()) vv = vv1 C_Et, C_jwHt = self.get_coeff_cls() self.vt.preprocess_params(self) inc_amp, inc_phase, eps, mur = self.vt.make_value_or_expression(self) dprint1("E field pattern", eps, mur) Et = C_Et(3, self, real=True, eps=eps, mur=mur) for p in vv: dprint1(p.__repr__() + ' : ' + Et.EvalValue(p).__repr__()) dprint1("H field pattern") Ht = C_jwHt(3, 0.0, self, real=False, eps=eps, mur=mur) for p in vv: dprint1(p.__repr__() + ' : ' + Ht.EvalValue(p).__repr__())