def assemble(self, *args, **kwargs): ''' integral() integral('boundary', [1,3]) # selection type and selection ''' engine = self._engine() self.process_kwargs(engine, kwargs) if len(args)>0: self._sel_mode = args[0] if len(args)>1: self._sel = args[1] lf1 = engine.new_lf(self._fes1()) one = mfem.ConstantCoefficient(1.0) coff = self.restrict_coeff(one, self._fes1()) if self._sel_mode == 'domain': intg = mfem.DomainLFIntegrator(coff) elif self._sel_mode == 'boundary': intg = mfem.BoundaryLFIntegrator(coff) else: assert False, "Selection Type must be either domain or boundary" lf1.AddDomainIntegrator(intg) lf1.Assemble() from mfem.common.chypre import LF2PyVec, PyVec2PyMat, MfemVec2PyVec v1 = MfemVec2PyVec(engine.b2B(lf1), None) v1 = PyVec2PyMat(v1) if not self._transpose: v1 = v1.transpose() return v1
def assemble(self, *args, **kwargs): engine = self._engine() direction = kwargs.pop("direction", 0) self.process_kwargs(engine, kwargs) x = args[0] y = args[1] if len(args)>1 else 0 z = args[2] if len(args)>2 else 0 sdim = self.fes1.GetMesh().SpaceDimension() if direction == 0: if sdim == 3: d = mfem.DeltaCoefficient(x, y, z, 1) elif sdim == 2: d = mfem.DeltaCoefficient(x, y, 1) elif sdim == 1: d = mfem.DeltaCoefficient(x, 1) else: assert False, "unsupported dimension" intg = mfem.DomainLFIntegrator(d) else: dir = mfem.Vector(direction) if sdim == 3: d = mfem.VectorDeltaCoefficient(dir, x, y, z, 1) elif sdim == 2: d = mfem.VectorDeltaCoefficient(dir, x, y, 1) elif sdim == 1: d = mfem.VectorDeltaCoefficient(dir,x, 1) else: assert False, "unsupported dimension" if self.fes1.FEColl().Name().startswith('ND'): intg = mfem.VectorFEDomainLFIntegrator(d) elif self.fes1.FEColl().Name().startswith('RT'): intg = mfem.VectorFEDomainLFIntegrator(d) else: intg = mfem.VectorDomainLFIntegrator(d) lf1 = engine.new_lf(self.fes1) lf1.AddDomainIntegrator(intg) lf1.Assemble() from mfem.common.chypre import LF2PyVec, PyVec2PyMat, MfemVec2PyVec v1 = MfemVec2PyVec(engine.b2B(lf1), None) v1 = PyVec2PyMat(v1) if not self._transpose: v1 = v1.transpose() return v1
def add_extra_contribution(self, engine, **kwargs): dprint1("Add Extra contribution" + str(self._sel_index)) from mfem.common.chypre import LF2PyVec, PyVec2PyMat, Array2PyVec, IdentityPyMat self.vt.preprocess_params(self) inc_amp, inc_phase, eps, mur = self.vt.make_value_or_expression(self) C_Et, C_jwHt = self.get_coeff_cls() fes = engine.get_fes(self.get_root_phys(), 0) lf1 = engine.new_lf(fes) Ht1 = C_jwHt(3, 0.0, self, real=True, eps=eps, mur=mur) Ht2 = self.restrict_coeff(Ht1, engine, vec=True) intg = mfem.VectorFEBoundaryTangentLFIntegrator(Ht2) lf1.AddBoundaryIntegrator(intg) lf1.Assemble() lf1i = engine.new_lf(fes) Ht3 = C_jwHt(3, 0.0, self, real=False, eps=eps, mur=mur) Ht4 = self.restrict_coeff(Ht3, engine, vec=True) intg = mfem.VectorFEBoundaryTangentLFIntegrator(Ht4) lf1i.AddBoundaryIntegrator(intg) lf1i.Assemble() lf2 = engine.new_lf(fes) Et = C_Et(3, self, real=True, eps=eps, mur=mur) Et = self.restrict_coeff(Et, engine, vec=True) intg = mfem.VectorFEDomainLFIntegrator(Et) lf2.AddBoundaryIntegrator(intg) lf2.Assemble() x = engine.new_gf(fes) x.Assign(0.0) arr = self.get_restriction_array(engine) x.ProjectBdrCoefficientTangent(Et, arr) t4 = np.array( [[np.sqrt(inc_amp) * np.exp(1j * inc_phase / 180. * np.pi)]]) weight = mfem.InnerProduct(engine.x2X(x), engine.b2B(lf2)) # # # v1 = LF2PyVec(lf1, lf1i) v1 *= -1 v2 = LF2PyVec(lf2, None, horizontal=True) #x = LF2PyVec(x, None) # # transfer x and lf2 to True DoF space to operate InnerProduct # # here lf2 and x is assume to be real value. # v2 *= 1. / weight v1 = PyVec2PyMat(v1) v2 = PyVec2PyMat(v2.transpose()) t4 = Array2PyVec(t4) t3 = IdentityPyMat(1) v2 = v2.transpose() ''' Format of extar (t2 is returnd as vertical(transposed) matrix) [M, t1] [ ] [ ] = [ ] [t2, t3] [t4] and it returns if Lagurangian will be saved. ''' return (v1, v2, t3, t4, True)
def assemble(self, *args, **kwargs): engine = self._engine() direction = kwargs.pop("direction", None) weight = kwargs.pop("weight", 1.0) weight = np.atleast_1d(weight) do_sum = kwargs.pop("sum", False) info1 = engine.get_fes_info(self.fes1) sdim = info1['sdim'] vdim = info1['vdim'] if (info1['element'].startswith('ND') or info1['element'].startswith('RT')): vdim = sdim if vdim > 1: if direction is None: direction = [0]*vdim direction[0] = 1 direction = np.atleast_1d(direction).astype(float, copy=False) direction = direction.reshape(-1, sdim) self.process_kwargs(engine, kwargs) pts = np.array(args[0], copy = False).reshape(-1, sdim) from mfem.common.chypre import LF2PyVec, PyVec2PyMat, MfemVec2PyVec, HStackPyVec vecs = [] for k, pt in enumerate(pts): w = float(weight[0] if len(weight) == 1 else weight[k]) if vdim == 1: if sdim == 3: x, y, z = pt d = mfem.DeltaCoefficient(x, y, z, w) elif sdim == 2: x, y = pt print("DeltaCoefficient call", type(x), type(y), type(x)) d = mfem.DeltaCoefficient(x, y, w) elif sdim == 1: x = pt d = mfem.DeltaCoefficient(x, w) else: assert False, "unsupported dimension" intg = mfem.DomainLFIntegrator(d) else: dir = direction[0] if len(direction) == 1 else direction[k] dd = mfem.Vector(dir) if sdim == 3: x, y, z = pt d = mfem.VectorDeltaCoefficient(dd, x, y, z, w) elif sdim == 2: x, y = pt d = mfem.VectorDeltaCoefficient(dd, x, y, w) elif sdim == 1: x = pt d = mfem.VectorDeltaCoefficient(dd,x, w) else: assert False, "unsupported dimension" if self.fes1.FEColl().Name().startswith('ND'): intg = mfem.VectorFEDomainLFIntegrator(d) elif self.fes1.FEColl().Name().startswith('RT'): intg = mfem.VectorFEDomainLFIntegrator(d) else: intg = mfem.VectorDomainLFIntegrator(d) if do_sum: if k == 0: lf1 = engine.new_lf(self.fes1) lf1.AddDomainIntegrator(intg) else: lf1 = engine.new_lf(self.fes1) lf1.AddDomainIntegrator(intg) lf1.Assemble() vecs.append(LF2PyVec(lf1)) if do_sum: lf1.Assemble() v1 = MfemVec2PyVec(engine.b2B(lf1), None) v1 = PyVec2PyMat(v1) else: v1 = HStackPyVec(vecs) if not self._transpose: v1 = v1.transpose() return v1
def assemble(self, *args, **kwargs): ''' integral() integral('boundary', [1,3]) # selection type and selection integral('boundary', [1,3], integrator = 'auto' or other MFEM linearform integrator integral('boundary', [1,3], weight = '1') ''' coeff = kwargs.pop("coeff", "1.0") coeff_type = kwargs.pop("coeff_type", "S") engine = self._engine() self.process_kwargs(engine, kwargs) if len(args)>0: self._sel_mode = args[0] if len(args)>1: self._sel = args[1] if (self.fes1.FEColl().Name().startswith('ND') or self.fes1.FEColl().Name().startswith('RT')): cdim = self.fes1.GetMesh().SpaceDimension() else: cdim = self.fes1.GetVDim() info1 = engine.get_fes_info(self.fes1) emesh_idx = info1['emesh_idx'] isDomain = (self._sel_mode == 'domain') from petram.helper.phys_module_util import default_lf_integrator integrator = kwargs.pop("integrator", "Auto") if integrator == 'Auto': integrator = default_lf_integrator(info1, isDomain) global_ns = globals() local_ns = {} real = True try: is_complex = np.iscomplex(complex(eval(coeff), global_ns, local_ns)) except: is_complex = kwargs.pop('is_complex', False) if isDomain: adder = 'AddDomainIntegrator' else: adder = 'AddBoundaryIntegrator' from petram.helper.phys_module_util import restricted_integrator from mfem.common.chypre import LF2PyVec, PyVec2PyMat, MfemVec2PyVec itg = restricted_integrator(engine, integrator, self._sel, coeff, coeff_type, cdim, emesh_idx, isDomain, self._ind_vars, local_ns, global_ns, True) lf1 = engine.new_lf(self._fes1()) getattr(lf1, adder)(itg) lf1.Assemble() if is_complex: itg = restricted_integrator(engine, integrator, self._sel, coeff, coeff_type, cdim, emesh_idx, isDomain, self._ind_vars, local_ns, global_ns, False) lf2 = engine.new_lf(self._fes1()) getattr(lf2, adder)(itg) lf2.Assemble() v1 = MfemVec2PyVec(engine.b2B(lf1), engine.b2B(lf2)) else: v1 = MfemVec2PyVec(engine.b2B(lf1), None) lf2 = None v1 = PyVec2PyMat(v1) if not self._transpose: v1 = v1.transpose() return v1
def assemble(self, *args, **kwargs): ''' looplintegral(18) # integrate around the bdr 18 # this mode is only avaiable on serial version. looplintegral([1,2,3], [4, 5]) # loop defined by two groups of boundaries ''' coeff = kwargs.pop("coeff", "1") coeff_type = kwargs.pop("coeff_type", "S") engine = self._engine() self.process_kwargs(engine, kwargs) face = args if not self.fes1.FEColl().Name().startswith('ND'): assert False, "line integration is only implemented for ND" fes1 = self.fes1 info1 = engine.get_fes_info(self.fes1) emesh_idx = info1['emesh_idx'] mesh = engine.emeshes[emesh_idx] if use_parallel: from petram.mesh.find_loop import find_loop_par idx, signs = find_loop_par(mesh, *face) fesize1 = fes1.GetTrueVSize() P = fes1.Dof_TrueDof_Matrix() from mfem.common.parcsr_extra import ToScipyCoo P = ToScipyCoo(P).tocsr() VDoFtoGTDoF = P.indices rstart = fes1.GetMyTDofOffset() else: from petram.mesh.find_loop import find_loop_ser idx, signs = find_loop_ser(mesh, *face) fesize1 = fes1.GetNDofs() map = np.zeros((fesize1,1), dtype=float) w = [] for sign, ie in zip(signs, idx): dofs = fes1.GetEdgeDofs(ie) # don't put this Tr outside the loop.... Tr = mesh.GetEdgeTransformation(ie) weight = Tr.Weight() w.append(Tr.Weight()) for dof in dofs: if use_parallel: dof = VDoFtoGTDoF[dof] - rstart map[dof] = sign #if len(w) > 0: print("weight", w) from mfem.common.chypre import PyVec2PyMat, CHypreVec if use_parallel: v1 = CHypreVec(map.flatten(), None) else: v1 = map.reshape((-1, 1)) v1 = PyVec2PyMat(v1) if not self._transpose: v1 = v1.transpose() return v1
def add_extra_contribution(self, engine, **kwargs): from mfem.common.chypre import LF2PyVec kfes = kwargs.pop('kfes', 0) dprint1("Add Extra contribution" + str(self._sel_index)) self.vt.preprocess_params(self) inc_amp, inc_phase, eps, mur = self.vt.make_value_or_expression(self) Erz, Ephi = self.get_e_coeff_cls() Hrz, Hphi = self.get_h_coeff_cls() fes = engine.get_fes(self.get_root_phys(), kfes) ''' if (kfes == 0 and self.mode == 'TE'): lf1 = engine.new_lf(fes) Ht = Hrz(2, 0.0, self, real = True) Ht = self.restrict_coeff(Ht, engine, vec = True) intg = mfem.VectorFEDomainLFIntegrator(Ht) #intg = mfem.VectorFEBoundaryTangentLFIntegrator(Ht) lf1.AddBoundaryIntegrator(intg) lf1.Assemble() lf1i = engine.new_lf(fes) Ht = Hrz(2, 0.0, self, real = False) Ht = self.restrict_coeff(Ht, engine, vec = True) intg = mfem.VectorFEDomainLFIntegrator(Ht) #intg = mfem.VectorFEBoundaryTangentLFIntegrator(Ht) lf1i.AddBoundaryIntegrator(intg) lf1i.Assemble() from mfem.common.chypre import LF2PyVec v1 = LF2PyVec(lf1, lf1i) v1 *= -1 # output formats of InnerProduct # are slightly different in parallel and serial # in serial numpy returns (1,1) array, while in parallel # MFEM returns a number. np.sum takes care of this. return (v1, None, None, None, False) ''' if (kfes == 1 and self.mode == 'TE'): lf1 = engine.new_lf(fes) Ht = Hphi(0.0, self, real=True, eps=eps, mur=mur) Ht = self.restrict_coeff(Ht, engine) intg = mfem.BoundaryLFIntegrator(Ht) lf1.AddBoundaryIntegrator(intg) lf1.Assemble() lf1i = engine.new_lf(fes) Ht = Hphi(0.0, self, real=False, eps=eps, mur=mur) Ht = self.restrict_coeff(Ht, engine) intg = mfem.BoundaryLFIntegrator(Ht) lf1i.AddBoundaryIntegrator(intg) lf1i.Assemble() from mfem.common.chypre import LF2PyVec, PyVec2PyMat, Array2PyVec, IdentityPyMat v1 = LF2PyVec(lf1, lf1i) v1 *= -1 lf2 = engine.new_lf(fes) Et = Ephi(self, real=True, eps=eps, mur=mur) Et = self.restrict_coeff(Et, engine) intg = mfem.DomainLFIntegrator(Et) lf2.AddBoundaryIntegrator(intg) lf2.Assemble() x = engine.new_gf(fes) x.Assign(0.0) arr = self.get_restriction_array(engine) x.ProjectBdrCoefficient(Et, arr) weight = mfem.InnerProduct(engine.x2X(x), engine.b2B(lf2)) v2 = LF2PyVec(lf2, None, horizontal=True) v2 *= -1 / weight / 2.0 #x = LF2PyVec(x, None) # output formats of InnerProduct # are slightly different in parallel and serial # in serial numpy returns (1,1) array, while in parallel # MFEM returns a number. np.sum takes care of this. #tmp = np.sum(v2.dot(x)) #v2 *= -1/tmp/2. t4 = np.array([[inc_amp * np.exp(1j * inc_phase / 180. * np.pi)]]) # convert to a matrix form v1 = PyVec2PyMat(v1) v2 = PyVec2PyMat(v2.transpose()) t4 = Array2PyVec(t4) t3 = IdentityPyMat(1) v2 = v2.transpose() #return (None, v2, t3, t4, True) return (v1, v2, t3, t4, True)
def add_extra_contribution(self, engine, **kwargs): from mfem.common.chypre import LF2PyVec kfes = kwargs.pop('kfes', 0) if kfes == 0: return dprint1("Add Extra contribution" + str(self._sel_index)) self.vt.preprocess_params(self) inc_amp, inc_phase, eps, mur, ky, kz = self.vt.make_value_or_expression( self) fes = engine.get_fes(self.get_root_phys(), kfes) d = "y" if kfes == 1 else "z" inc_amp0 = (1, 0) if kfes == 1 else (0, 1) lf1 = engine.new_lf(fes) Ht = jwH_port(self, real=True, amp=inc_amp0, eps=eps, mur=mur, ky=ky, kz=kz, direction=d, normalize=True) Ht = self.restrict_coeff(Ht, engine) intg = mfem.BoundaryLFIntegrator(Ht) lf1.AddBoundaryIntegrator(intg) lf1.Assemble() lf1i = engine.new_lf(fes) Ht = jwH_port(self, real=False, amp=inc_amp0, eps=eps, mur=mur, ky=ky, kz=kz, direction=d, normalize=True) Ht = self.restrict_coeff(Ht, engine) intg = mfem.BoundaryLFIntegrator(Ht) lf1i.AddBoundaryIntegrator(intg) lf1i.Assemble() from mfem.common.chypre import LF2PyVec, PyVec2PyMat, Array2PyVec, IdentityPyMat v1 = LF2PyVec(lf1, lf1i) #v1 *= -1 lf2 = engine.new_lf(fes) Et = E_port(self, real=True, amp=inc_amp0, eps=eps, mur=mur, ky=ky, kz=kz, direction=d, normalize=True) Et = self.restrict_coeff(Et, engine) intg = mfem.DomainLFIntegrator(Et) lf2.AddBoundaryIntegrator(intg) lf2.Assemble() x = engine.new_gf(fes) x.Assign(0.0) arr = self.get_restriction_array(engine) x.ProjectBdrCoefficient(Et, arr) v2 = LF2PyVec(lf2, None, horizontal=True) x = LF2PyVec(x, None) # output formats of InnerProduct # are slightly different in parallel and serial # in serial numpy returns (1,1) array, while in parallel # MFEM returns a number. np.sum takes care of this. tmp = np.sum(v2.dot(x)) #v2 *= -1/tmp t4 = np.array( [[inc_amp[kfes - 1] * np.exp(1j * inc_phase / 180. * np.pi)]]) # convert to a matrix form v1 = PyVec2PyMat(v1) v2 = PyVec2PyMat(v2.transpose()) t4 = Array2PyVec(t4) t3 = IdentityPyMat(1) v2 = v2.transpose() #return (None, v2, t3, t4, True) return (v1, v2, t3, t4, True)