Example #1
0
    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
Example #2
0
    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)
Example #4
0
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)
Example #5
0
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)
Example #6
0
    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.
Example #7
0
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()
Example #8
0
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)
Example #9
0
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)
Example #10
0
    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
Example #11
0
    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)
Example #12
0
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
Example #13
0
    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)