def InnerProductComplex(A, B): import mfem.par as mfem R_A, I_A = A R_B, I_B = B if I_A is None and I_B is None: return mfem.InnerProduct(R_A, R_B) elif I_A is None: r = mfem.InnerProduct(R_A, R_B) i = mfem.InnerProduct(R_A, I_B) elif I_B is None: r = mfem.InnerProduct(R_A, R_B) i = mfem.InnerProduct(I_A, R_B) else: r = mfem.InnerProduct(R_A, R_B) - mfem.InnerProduct(I_A, I_B) i = mfem.InnerProduct(R_A, I_B) + mfem.InnerProduct(I_A, R_B) return r + 1j * i
pcg = mfem.CGSolver(MPI.COMM_WORLD) pcg.SetOperator(A) pcg.SetPreconditioner(P) pcg.SetRelTol(1e-6) pcg.SetMaxIter(200) pcg.SetPrintLevel(1) pcg.Mult(b, x) LSres = mfem.HypreParVector(test_space) tmp = mfem.HypreParVector(test_space) B.Mult(x, LSres) LSres -= trueF matSinv.Mult(LSres, tmp) res = sqrt(mfem.InnerProduct(LSres, tmp)) if (myid == 0): print("\n|| B0*x0 + Bhat*xhat - F ||_{S^-1} = " + str(res)) x0.Distribute(x.GetBlock(x0_var)) # 13. Save the refined mesh and the solution in parallel. This output can # be viewed later using GLVis: "glvis -np <np> -m mesh -g sol". smyid = '{:0>6d}'.format(myid) mesh_name = "mesh." + smyid sol_name = "sol." + smyid pmesh.PrintToFile(mesh_name, 8) x0.SaveToFile(sol_name, 8) # 14. Send the solution by socket to a GLVis server.
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): 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 do_integration(expr, solvars, phys, mesh, kind, attrs, order, num): from petram.helper.variables import (Variable, var_g, NativeCoefficientGenBase, CoefficientVariable) from petram.phys.coefficient import SCoeff st = parser.expr(expr) code= st.compile('<string>') names = code.co_names g = {} #print solvars.keys() for key in phys._global_ns.keys(): g[key] = phys._global_ns[key] for key in solvars.keys(): g[key] = solvars[key] l = var_g.copy() ind_vars = ','.join(phys.get_independent_variables()) if kind == 'Domain': size = max(max(mesh.attributes.ToList()), max(attrs)) else: size = max(max(mesh.bdr_attributes.ToList()), max(attrs)) arr = [0]*(size) for k in attrs: arr[k-1] = 1 flag = mfem.intArray(arr) s = SCoeff(expr, ind_vars, l, g, return_complex=False) ## note L2 does not work for boundary....:D if kind == 'Domain': fec = mfem.L2_FECollection(order, mesh.Dimension()) else: fec = mfem.H1_FECollection(order, mesh.Dimension()) fes = mfem.FiniteElementSpace(mesh, fec) one = mfem.ConstantCoefficient(1) gf = mfem.GridFunction(fes) gf.Assign(0.0) if kind == 'Domain': gf.ProjectCoefficient(mfem.RestrictedCoefficient(s, flag)) else: gf.ProjectBdrCoefficient(mfem.RestrictedCoefficient(s, flag), flag) b = mfem.LinearForm(fes) one = mfem.ConstantCoefficient(1) if kind == 'Domain': itg = mfem.DomainLFIntegrator(one) b.AddDomainIntegrator(itg) else: itg = mfem.BoundaryLFIntegrator(one) b.AddBoundaryIntegrator(itg) b.Assemble() from petram.engine import SerialEngine en = SerialEngine() ans = mfem.InnerProduct(en.x2X(gf), en.b2B(b)) if not np.isfinite(ans): print("not finite", ans, arr) print(size, mesh.bdr_attributes.ToList()) from mfem.common.chypre import LF2PyVec, PyVec2PyMat, Array2PyVec, IdentityPyMat #print(list(gf.GetDataArray())) print(len(gf.GetDataArray()), np.sum(gf.GetDataArray())) print(np.sum(list(b.GetDataArray()))) return ans