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)) fes = engine.get_fes(self.get_root_phys(), 0) x, y, s = self.vt.make_value_or_expression(self) from mfem.common.chypre import LF2PyVec, EmptySquarePyMat, HStackPyVec from mfem.common.chypre import Array2PyVec vecs = [] for x0, y0, s0 in zip(x, y, s): lf1 = engine.new_lf(fes) d = mfem.DeltaCoefficient(x0, y0, 1.0) itg = mfem.DomainLFIntegrator(d) lf1.AddDomainIntegrator(itg) lf1.Assemble() vecs.append(LF2PyVec(lf1)) t3 = EmptySquarePyMat(len(x)) v1 = HStackPyVec(vecs) v2 = v1 t4 = Array2PyVec(np.array(s)) return (v1, v2, t3, t4, True)
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() rhs = RhsCoefficient() integ = mfem.DiffusionIntegrator(one) a.AddDomainIntegrator(integ) b.AddDomainIntegrator(mfem.DomainLFIntegrator(rhs)) # 8. The solution vector x and the associated finite element grid function # will be maintained over the AMR iterations. x = mfem.ParGridFunction(fespace) # 9. Connect to GLVis. if visualization: sout = mfem.socketstream("localhost", 19916) sout.precision(8) # 10. As in Example 6p, we set up a Zienkiewicz-Zhu estimator that will be # used to obtain element error indicators. The integrator needs to # provide the method ComputeElementFlux. We supply an L2 space for the # discontinuous flux and an H(div) space for the smoothed flux. flux_fec = mfem.L2_FECollection(order, dim)
if myid == 0: print('\n'.join([ "nNumber of Unknowns", " Trial space, X0 : " + str(glob_true_s0) + " (order " + str(trial_order) + ")", " Interface space, Xhat : " + str(glob_true_s1) + " (order " + str(trace_order) + ")", " Test space, Y : " + str(glob_true_s_test) + " (order " + str(test_order) + ")" ])) # 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)
def EvalValue(self, x): l2 = np.sum(x**2) return 7. * x[0] * x[1] / l2 class analytic_solution(mfem.PyCoefficient): def EvalValue(self, x): l2 = np.sum(x**2) return x[0] * x[1] / l2 b = mfem.ParLinearForm(fespace) one = mfem.ConstantCoefficient(1.0) rhs_coef = analytic_rhs() sol_coef = analytic_solution() b.AddDomainIntegrator(mfem.DomainLFIntegrator(rhs_coef)) b.Assemble() # 6. Define the solution vector x as a finite element grid function # corresponding to fespace. Initialize x with initial guess of zero. x = mfem.ParGridFunction(fespace) x.Assign(0.0) # 7. Set up the bilinear form a(.,.) on the finite element space # 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.
rhs = mfem.BlockVector(block_offsets) trueX = mfem.BlockVector(block_trueOffsets) trueRhs = mfem.BlockVector(block_trueOffsets) fform = mfem.ParLinearForm() fform.Update(R_space, rhs.GetBlock(0), 0) fform.AddDomainIntegrator(mfem.VectorFEDomainLFIntegrator(fcoeff)) fform.AddBoundaryIntegrator(mfem.VectorFEBoundaryFluxLFIntegrator(fnatcoeff)) fform.Assemble() fform.ParallelAssemble(trueRhs.GetBlock(0)) gform = mfem.ParLinearForm() gform.Update(W_space, rhs.GetBlock(1), 0) gform.AddDomainIntegrator(mfem.DomainLFIntegrator(gcoeff)) gform.Assemble() gform.ParallelAssemble(trueRhs.GetBlock(1)) mVarf = mfem.ParBilinearForm(R_space) bVarf = mfem.ParMixedBilinearForm(R_space, W_space) mVarf.AddDomainIntegrator(mfem.VectorFEMassIntegrator(k)) mVarf.Assemble() mVarf.Finalize() M = mVarf.ParallelAssemble() bVarf.AddDomainIntegrator(mfem.VectorFEDivergenceIntegrator()) bVarf.Assemble() bVarf.Finalize() B = bVarf.ParallelAssemble()
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)
def run(order = 1, static_cond = False, meshfile = def_meshfile, visualization = 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() prinr( "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())) 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); a.RecoverFEMSolution(X, b, x) smyid = '{:0>6d}'.format(myid) mesh_name = "mesh."+smyid sol_name = "sol."+smyid pmesh.PrintToFile(mesh_name, 8) x.SaveToFile(sol_name, 8)
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 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 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
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)