Ejemplo n.º 1
0
 def set_point(self, T, ip, g, l, t=None):
     self.x = T.Transform(ip)
     self.t = t
     T.SetIntPoint(ip)
     nor = mfem.Vector(self.sdim)
     mfem.CalcOrtho(T.Jacobian(), nor)
     self.nor = nor.GetDataArray().copy()
Ejemplo n.º 2
0
    def ncface_values(self,
                      ifaces=None,
                      irs=None,
                      gtypes=None,
                      locs=None,
                      mesh=None,
                      **kwargs):

        size = len(locs)
        ret = np.zeros((size, self.sdim))
        if ifaces is None: return

        nor = mfem.Vector(self.sdim)

        if mesh.Dimension() == 3:
            m = mesh.GetFaceTransformation
        elif mesh.Dimension() == 2:
            m = mesh.GetElementTransformation
        idx = 0
        for i, gtype, in zip(ifaces, gtypes):
            ir = irs[gtype]
            nv = ir.GetNPoints()
            T = m(i)
            for j in range(nv):
                T.SetIntPoint(ir.IntPoint(i))
                mfem.CalcOrtho(T.Jacobian(), nor)
                ret[idx, :] = nor.GetDataArray().copy()
                idx = idx + 1

        from petram.helper.right_broadcast import div

        ret = div(ret, np.sqrt(np.sum(ret**2, -1)))
        if self.comp == -1: return ret
        return ret[:, self.comp - 1]
Ejemplo n.º 3
0
    def nodal_values(self, ibele=None, mesh=None, iverts_f=None, **kwargs):
        # iele = None, elattr = None, el2v = None,
        # wverts = None, locs = None, g = None

        g = mfem.Geometry()
        size = len(iverts_f)
        #wverts = np.zeros(size)
        ret = np.zeros((size, self.sdim))
        if ibele is None: return

        ibe = ibele[0]
        el = mesh.GetBdrElement(ibe)
        rule = g.GetVertices(el.GetGeometryType())
        nv = rule.GetNPoints()

        for ibe in ibele:
            T = mesh.GetBdrElementTransformation(ibe)
            bverts = mesh.GetBdrElement(ibe).GetVerticesArray()

            for i in range(nv):
                nor = mfem.Vector(self.sdim)
                T.SetIntPoint(rule.IntPoint(i))
                mfem.CalcOrtho(T.Jacobian(), nor)
                idx = np.searchsorted(iverts_f, bverts[i])

                ret[idx, :] += nor.GetDataArray().copy()
                #wverts[idx] = wverts[idx] + 1

        #for i in range(self.sdim): ret[:,i] /= wvert
        # normalize to length one.
        ret = ret / np.sqrt(np.sum(ret**2, 1)).reshape(-1, 1)

        if self.comp == -1: return ret
        return ret[:, self.comp - 1]
Ejemplo n.º 4
0
    def preprocess_params(self, engine):
        ### find normal (outward) vector...
        mesh = engine.get_emesh(mm=self)
        fespace = engine.fespaces[self.get_root_phys().dep_vars[0]]
        nbe = mesh.GetNBE()
        ibe = np.array([
            i for i in range(nbe)
            if mesh.GetBdrElement(i).GetAttribute() == self._sel_index[0]
        ])
        dprint1("idb", ibe)
        el = mesh.GetBdrElement(ibe[0])
        Tr = fespace.GetBdrElementTransformation(ibe[0])
        rules = mfem.IntegrationRules()
        ir = rules.Get(el.GetGeometryType(), 1)
        Tr.SetIntPoint(ir.IntPoint(0))
        nor = mfem.Vector(2)
        mfem.CalcOrtho(Tr.Jacobian(), nor)

        self.norm = nor.GetDataArray().copy()
        self.norm = self.norm / np.sqrt(np.sum(self.norm**2))

        dprint1("Normal Vector " + list(self.norm).__repr__())

        ### find rectangular shape

        edges = np.array([mesh.GetBdrElementEdges(i)[0]
                          for i in ibe]).flatten()
        d = {}
        for x in edges:
            d[x] = x in d
        edges = [x for x in d.keys() if not d[x]]
        ivert = [mesh.GetEdgeVertices(x) for x in edges]
        ivert = connect_pairs2(ivert)[0]

        vv = np.vstack([mesh.GetVertexArray(i) for i in ivert])
        self.ctr = (vv[0] + vv[-1]) / 2.0
        dprint1("Center " + list(self.ctr).__repr__())

        ### rectangular port
        self.a_vec = (vv[0] - vv[-1])
        self.a = np.sqrt(np.sum(self.a_vec**2))
        self.a_vec /= self.a
        self.c = vv[-1]
        dprint1("Cornor " + self.c.__repr__())
        dprint1("Edge  " + self.a.__repr__())
        dprint1("Edge Vec." + list(self.a_vec).__repr__())

        Erz, Ephi = self.get_e_coeff_cls()
        Hrz, Hphi = self.get_h_coeff_cls()

        if self.mode == 'TE':
            dprint1("E field pattern")
            c1 = Ephi(self, real=True)
            c2 = Hphi(0.0, self, real=False)
            for p in vv:
                dprint1(p.__repr__() + ' : ' + c1.EvalValue(p).__repr__())
            dprint1("H field pattern")
            for p in vv:
                dprint1(p.__repr__() + ' : ' + c2.EvalValue(p).__repr__())
Ejemplo n.º 5
0
def hcurln(fes1,
           fes2,
           coeff,
           is_complex=False,
           bdr='all',
           orderinc=1,
           verbose=False):

    mat, rstart = get_empty_map(fes2, fes1, is_complex=is_complex)
    mat2, rstart = get_empty_map(fes2, fes1, is_complex=is_complex)

    from petram.helper.element_map import map_element

    name_fes1 = fes1.FEColl().Name()[:2]
    name_fes2 = fes2.FEColl().Name()[:2]

    if verbose:
        if myid == 0:
            dprint1("fes", name_fes1, name_fes2)

    mesh1 = fes1.GetMesh()
    mesh2 = fes2.GetMesh()

    mesh2.Print("/home/shiraiwa/part.mesh")

    if verbose:
        if myid == 0:
            dprint1("NE", mesh1.GetNE(), mesh2.GetNE())
    elmap, elmap_r = map_element(mesh1, mesh2, bdr, map_bdr=True)

    sdim1 = mesh1.SpaceDimension()
    sdim2 = mesh1.SpaceDimension()
    dim1 = mesh1.Dimension()
    dim2 = mesh2.Dimension()

    shape1 = mfem.DenseMatrix()
    shape2 = mfem.Vector()
    ip = mfem.IntegrationPoint()
    nor = mfem.Vector(sdim1)

    if USE_PARALLEL:
        # this is global TrueDoF (offset is not subtracted)
        P = fes1.Dof_TrueDof_Matrix()
        P1mat = ToScipyCoo(P).tocsr()
        #VDoFtoGTDoF1 = P.indices
        #P = fes2.Dof_TrueDof_Matrix()
        #P = ToScipyCoo(P).tocsr()
        #VDoFtoGTDoF2 = P.indices
        #P2mat = P

    vdofs1_senddata = []

    shared_data = []

    el2_2_node = {}
    el2_2_el1 = {}

    for d in elmap_r:
        for x in list(elmap_r[d]):
            el2_2_node[x] = d
        for x in list(elmap_r[d]):
            el2_2_el1[x] = elmap_r[d][x]

    # working for fes2
    # find boundary element on mesh1 using mesh2 boundary
    el2_arr = [list() for x in range(nprc)]
    el1_arr = [list() for x in range(nprc)]
    fe2o_arr = [list() for x in range(nprc)]
    for i_el in range(fes2.GetNE()):
        attr = fes2.GetAttribute(i_el)
        if bdr != 'all' and not attr in bdr:
            continue
        el1_arr[el2_2_node[i_el]].append(el2_2_el1[i_el])
        el2_arr[el2_2_node[i_el]].append(i_el)
        fe2 = fes2.GetFE(i_el)
        fe2o_arr[el2_2_node[i_el]].append(fe2.GetOrder())

    if USE_PARALLEL:
        el1_arr = alltoall_vector(el1_arr, int)  # transfer to mesh1 owners

    # working for fes1
    # find elemet order on mesh1
    fe1o_arr = [list() for x in range(nprc)]
    i_fe1_arr = [list() for x in range(nprc)]
    rank = 0
    for rank, i_bdrs in enumerate(el1_arr):
        for i_bdr in i_bdrs:
            iface = mesh1.GetBdrElementEdgeIndex(i_bdr)
            transs = mesh1.GetFaceElementTransformations(iface)
            i_el1 = transs.Elem1No
            assert transs.Elem2No == -1, "boundary must be exterior for this operator"
            fe1 = fes1.GetFE(i_el1)
            fe1o_arr[rank].append(fe1.GetOrder())
            i_fe1_arr[rank].append(i_el1)
        rank = rank + 1

    if USE_PARALLEL:
        fe1o_arr = alltoall_vector(fe1o_arr, int)  # transfer to mesh2

    # working for fes2
    locnor_arr = [list() for x in range(nprc)]
    data2_arr = [list() for x in range(nprc)]
    verbose1 = verbose
    for rank, i_el2s in enumerate(el2_arr):
        for i_el2, fe1o in zip(i_el2s, fe1o_arr[rank]):
            eltrans = fes2.GetElementTransformation(i_el2)
            fe2 = fes2.GetFE(i_el2)
            nd2 = fe2.GetDof()
            ir = get_rule(fe1o,
                          fe2,
                          eltrans,
                          orderinc=orderinc,
                          verbose=verbose1)
            verbose1 = False
            shape2.SetSize(nd2)
            data2 = []
            locnors = []
            for jj in range(ir.GetNPoints()):
                ip1 = ir.IntPoint(jj)
                eltrans.SetIntPoint(ip1)
                w = eltrans.Weight() * ip1.weight
                mfem.CalcOrtho(eltrans.Jacobian(), nor)
                nor2 = nor.GetDataArray() / np.linalg.norm(nor.GetDataArray())
                fe2.CalcShape(ip1, shape2)

                if dim2 == 1:
                    d = np.array([ip1.x] + list(eltrans.Transform(ip1)) +
                                 list(nor2))
                    locnors.append(d)
                elif dim2 == 2:
                    d = np.array([ip1.x, ip1.y] +
                                 list(eltrans.Transform(ip1)) + list(nor2))

                    locnors.append(d)
                else:
                    assert False, "boundary mesh must be dim=1 or 2"
                data2.append(w * shape2.GetDataArray().copy())

            #   np.vstack(locnors).shape = (#Npoints, dim2+sdim2*2)
            #   np.vstack(data2).shape = (#Npoints, #NDoF2)
            #print("size here", np.vstack(locnors).shape, np.vstack(data2).shape)

            locnor_arr[rank].append(np.vstack(locnors))
            data2_arr[rank].append(np.vstack(data2))

    if USE_PARALLEL:
        locnor_arr = alltoall_vectorv(locnor_arr, float)  # transfer to mesh1

    ll = dim2 + 2 * sdim2

    vdofs1_arr = [list() for x in range(nprc)]
    data1_arr = [list() for x in range(nprc)]

    # space to compute the coefficient
    MV = [mfem.Vector(sdim1), mfem.DenseMatrix(sdim1, sdim1)]

    max_misalignment = -np.inf
    for rank, i_fe1s in enumerate(i_fe1_arr):
        locnorss = locnor_arr[rank]

        sign_dict = {}

        for k, i_fe1 in enumerate(i_fe1s):
            fe1 = fes1.GetFE(i_fe1)
            nd1 = fe1.GetDof()
            eltrans = fes1.GetElementTransformation(i_fe1)
            doftrans = fes1.GetElementDofTransformation(i_fe1)
            #ctr = eval_element_center(fe1, eltrans)

            locnors2 = locnorss[k]
            shape1.SetSize(nd1, sdim1)
            vdofs1 = fes1.GetElementVDofs(i_fe1)

            dof_sign1 = np.array([
                [1 if vv >= 0 else -1 for vv in vdofs1],
            ])
            vdofs1 = [-1 - x if x < 0 else x for x in vdofs1]

            mat_doftrans = get_inv_doftrans(doftrans, dof_sign1)

            if USE_PARALLEL:
                #  After DofTransformation is introduced we can not use GetGlobalTDofNumber, because
                #  element local DoF could be linked with two TrueDoFs in neighber processes
                #  We construct submatrix of Prolongation to construct element matrix
                #  in TrueDof space

                vv1 = [
                    P1mat.indices[P1mat.indptr[ii]:P1mat.indptr[ii + 1]]
                    for ii in vdofs1
                ]
                vv3 = [
                    P1mat.data[P1mat.indptr[ii]:P1mat.indptr[ii + 1]]
                    for ii in vdofs1
                ]
                ngtof = np.sum([len(x) for x in vv3])
                sub_p = np.zeros((nd1, ngtof))
                k1 = 0
                k2 = 0
                for gtofs, weights in zip(vv1, vv3):
                    for g, w in zip(gtofs, weights):
                        sub_p[k1, k2] = w
                        k2 = k2 + 1
                    k1 = k1 + 1

                vdofs1 = np.hstack(vv1).flatten()
                mat_doftrans = mat_doftrans.dot(sub_p)

            res, misalignment = map_ir(fe1, eltrans, coeff, shape1, dim2,
                                       sdim2, locnors2, dof_sign1,
                                       mat_doftrans, MV)

            vdofs1_arr[rank].append(np.array(vdofs1))
            data1_arr[rank].append(res)

            max_misalignment = np.max([max_misalignment, np.max(misalignment)])
            # res.shape = (#Npoints, #DoF1)

    if USE_PARALLEL:
        vdofs1_arr = alltoall_vectorv(vdofs1_arr, int)  # transfer to mesh2
        if is_complex:
            data1_arr = alltoall_vectorv(data1_arr,
                                         complex)  # transfer to mesh2
        else:
            data1_arr = alltoall_vectorv(data1_arr, float)  # transfer to mesh2
        max_misalignment = np.max(
            MPI.COMM_WORLD.gather(max_misalignment, root=0))
    dprint1("Max misalignment: ", max_misalignment)

    shared_data = []

    for rank, i_el2s in enumerate(el2_arr):
        for k, i_el2 in enumerate(i_el2s):
            vdofs1 = vdofs1_arr[rank][k]

            fe2 = fes2.GetFE(i_el2)
            eltrans2 = fes2.GetElementTransformation(i_el2)
            vdofs2 = fes2.GetElementVDofs(i_el2)
            vdofs2 = [-1 - x if x < 0 else x for x in vdofs2]

            d1 = data1_arr[rank][k]
            d2 = data2_arr[rank][k]

            mm = d2.transpose().dot(d1)

            if USE_PARALLEL:
                # prepare data for not-owned DoFs, which will be shared later
                vdofs22 = [fes2.GetLocalTDofNumber(ii) for ii in vdofs2]
                vdofs22g = [fes2.GetGlobalTDofNumber(ii) for ii in vdofs2]

                kkk = 0
                for v2, v2g in zip(vdofs22, vdofs22g):
                    if v2 < 0:
                        shared_data.append([v2g, mm[kkk, :], vdofs1])
                    kkk = kkk + 1
            else:
                vdofs22 = vdofs2

            for i, ltdof2 in enumerate(vdofs22):
                if ltdof2 < 0:
                    continue
                for j, gtdof1 in enumerate(vdofs1):
                    mat[ltdof2, gtdof1] = mat[ltdof2, gtdof1] + mm[i, j]

    if USE_PARALLEL:
        #nicePrint("shared data", shared_data)
        for source_id in range(nprc):
            data = comm.bcast(shared_data, root=source_id)
            myoffset = fes2.GetMyTDofOffset()
            for v2g, elmat, vdofs1 in data:
                if v2g >= myoffset and v2g < myoffset + mat.shape[0]:
                    i = v2g - myoffset
                    for j, gtdof1 in enumerate(vdofs1):
                        mat[i, gtdof1] = mat[i, gtdof1] + elmat[j]
                    #mat[i, vdofs1] = mat[i, vdofs1] + elmat

    from scipy.sparse import coo_matrix, csr_matrix

    if USE_PARALLEL:
        if is_complex:
            m1 = csr_matrix(mat.real, dtype=float)
            m2 = csr_matrix(mat.imag, dtype=float)
        else:
            m1 = csr_matrix(mat.real, dtype=float)
            m2 = None
        from mfem.common.chypre import CHypreMat

        start_col = fes1.GetMyTDofOffset()
        end_col = fes1.GetMyTDofOffset() + fes1.GetTrueVSize()
        col_starts = [start_col, end_col, mat.shape[1]]
        M = CHypreMat(m1, m2, col_starts=col_starts)
    else:
        from petram.helper.block_matrix import convert_to_ScipyCoo
        M = convert_to_ScipyCoo(coo_matrix(mat, dtype=mat.dtype))

    return M
Ejemplo n.º 6
0
 def set_point(self, T, ip, g, l, t=None):
     nor = mfem.Vector(self.sdim)
     mfem.CalcOrtho(T.Jacobian(), nor)
     self.nor = nor.GetDataArray().copy()
Ejemplo n.º 7
0
    def preprocess_params(self, engine):
        ### find normal (outward) vector...
        mesh = engine.get_emesh(mm=self)  ###

        fespace = engine.fespaces[self.get_root_phys().dep_vars[0]]

        nbe = mesh.GetNBE()
        ibe = np.array([
            i for i in range(nbe)
            if mesh.GetBdrElement(i).GetAttribute() == self._sel_index[0]
        ])
        dprint1("idb", ibe)
        el = mesh.GetBdrElement(ibe[0])
        Tr = fespace.GetBdrElementTransformation(ibe[0])
        rules = mfem.IntegrationRules()
        ir = rules.Get(el.GetGeometryType(), 1)
        Tr.SetIntPoint(ir.IntPoint(0))
        nor = mfem.Vector(3)
        mfem.CalcOrtho(Tr.Jacobian(), nor)

        self.norm = nor.GetDataArray().copy()
        self.norm = self.norm / np.sqrt(np.sum(self.norm**2))

        #freq = self._global_ns["freq"]
        #self.omega = freq * 2 * np.pi
        #dprint1("Frequency " + (freq).__repr__())
        dprint1("Normal Vector " + list(self.norm).__repr__())

        ### find rectangular shape
        if str(self.mode).upper().strip() in ['TE', 'TM', 'TEM']:
            edges = np.array([mesh.GetBdrElementEdges(i)[0]
                              for i in ibe]).flatten()
            d = {}
            for x in edges:
                d[x] = x in d
            edges = [x for x in d.keys() if not d[x]]
            ivert = [mesh.GetEdgeVertices(x) for x in edges]
            ivert = connect_pairs(ivert)
            vv = np.vstack([mesh.GetVertexArray(i) for i in ivert])

            self.ctr = (np.max(vv, 0) + np.min(vv, 0)) / 2.0
            dprint1("Center " + list(self.ctr).__repr__())

            ### rectangular port
            #idx = np.argsort(np.sqrt(np.sum((vv - self.ctr)**2,1)))
            #corners = vv[idx[-4:],:]
            # since vv is cyclic I need to omit last one element here..
            idx = np.argsort(np.sqrt(np.sum((vv[:-1] - self.ctr)**2, 1)))
            corners = vv[:-1][idx[-4:], :]
            for i in range(4):
                dprint1("Corner " + list(corners[i]).__repr__())
            tmp = np.sort(np.sqrt(np.sum((corners - corners[0, :])**2, 1)))
            self.b = tmp[1]
            self.a = tmp[2]
            tmp = np.argsort(np.sqrt(np.sum((corners - corners[0, :])**2, 1)))
            self.c = corners[0]  # corner
            self.b_vec = corners[tmp[1]] - corners[0]
            self.a_vec = np.cross(self.b_vec, self.norm)
            #            self.a_vec = corners[tmp[2]]-corners[0]
            self.b_vec = self.b_vec / np.sqrt(np.sum(self.b_vec**2))
            self.a_vec = self.a_vec / np.sqrt(np.sum(self.a_vec**2))
            if np.sum(np.cross(self.a_vec, self.b_vec) * self.norm) > 0:
                self.a_vec = -self.a_vec

            if self.mode == 'TEM':
                '''
               special handling
               set a vector along PEC-like edge, regardless the actual
               length of edges
               '''
                for i in range(nbe):
                    if (edges[0] in mesh.GetBdrElementEdges(i)[0]
                            and self._sel_index[0] != mesh.GetBdrAttribute(i)):
                        dprint1("Checking surface :", mesh.GetBdrAttribute(i))
                        attr = mesh.GetBdrAttribute(i)
                        break
                for node in self.get_root_phys().walk():
                    if not isinstance(node, Bdry): continue
                    if not node.enabled: continue
                    if attr in node._sel_index:
                        break
                from petram.model import Pair
                ivert = mesh.GetEdgeVertices(edges[0])
                vect = mesh.GetVertexArray(ivert[0]) - mesh.GetVertexArray(
                    ivert[1])
                vect = vect / np.sqrt(np.sum(vect**2))
                do_swap = False
                if (isinstance(node, Pair)
                        and np.abs(np.sum(self.a_vec * vect)) > 0.9):
                    do_swap = True
                if (not isinstance(node, Pair)
                        and np.abs(np.sum(self.a_vec * vect)) < 0.001):
                    do_swap = True
                if do_swap:
                    dprint1("swapping port edges")
                    tmp = self.a_vec
                    self.a_vec = -self.b_vec
                    self.b_vec = tmp
                    # - sign is to keep a \times b direction.
                    tmp = self.a
                    self.a = self.b
                    self.b = tmp
            if self.a_vec[np.argmax(np.abs(self.a_vec))] < 0:
                self.a_vec = -self.a_vec
                self.b_vec = -self.b_vec
            dprint1("Long Edge  " + self.a.__repr__())
            dprint1("Long Edge Vec." + list(self.a_vec).__repr__())
            dprint1("Short Edge  " + self.b.__repr__())
            dprint1("Short Edge Vec." + list(self.b_vec).__repr__())
        elif self.mode == 'Coax(TEM)':
            edges = np.array([mesh.GetBdrElementEdges(i)[0]
                              for i in ibe]).flatten()
            d = {}
            for x in edges:
                d[x] = x in d
            edges = [x for x in d.keys() if not d[x]]
            ivert = [mesh.GetEdgeVertices(x) for x in edges]
            iv1, iv2 = connect_pairs(ivert)  # index of outer/inner circles
            vv1 = np.vstack([mesh.GetVertexArray(i) for i in iv1])
            vv2 = np.vstack([mesh.GetVertexArray(i) for i in iv2])
            ctr1, a1 = find_circle_center_radius(vv1, self.norm)
            ctr2, b1 = find_circle_center_radius(vv2, self.norm)
            self.ctr = np.mean((ctr1, ctr2), 0)
            self.a = a1 if a1 < b1 else b1
            self.b = a1 if a1 > b1 else b1
            dprint1("Big R:  " + self.b.__repr__())
            dprint1("Small R: " + self.a.__repr__())
            dprint1("Center:  " + self.ctr.__repr__())
            vv = vv1
        C_Et, C_jwHt = self.get_coeff_cls()

        self.vt.preprocess_params(self)
        inc_amp, inc_phase, eps, mur = self.vt.make_value_or_expression(self)
        dprint1("E field pattern", eps, mur)
        Et = C_Et(3, self, real=True, eps=eps, mur=mur)
        for p in vv:
            dprint1(p.__repr__() + ' : ' + Et.EvalValue(p).__repr__())
        dprint1("H field pattern")
        Ht = C_jwHt(3, 0.0, self, real=False, eps=eps, mur=mur)
        for p in vv:
            dprint1(p.__repr__() + ' : ' + Ht.EvalValue(p).__repr__())