Пример #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
Пример #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
Пример #3
0
    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)
Пример #4
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
Пример #5
0
    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
Пример #6
0
    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
Пример #7
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)
Пример #8
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)