Пример #1
0
    def __init__(self, nspts, cfg):
        self.nspts = nspts
        self.cfg = cfg
        self.order = cfg.getint('solver', 'order')

        self.antialias = cfg.get('solver', 'anti-alias', 'none')
        self.antialias = {s.strip() for s in self.antialias.split(',')}
        self.antialias.discard('none')
        if self.antialias - {'flux', 'div-flux', 'surf-flux'}:
            raise ValueError('Invalid anti-alias options')

        self.ubasis = get_polybasis(self.name, self.order + 1, self.upts)

        if nspts:
            self.nsptsord = nsptord = self.order_from_nspts(nspts)
            self.sbasis = get_polybasis(self.name, nsptord, self.spts)

            # Basis for free-stream metric
            # We need p-th order pseudo grid points, which includes
            # p-th order points on faces.
            # It guarantees th q-th order collocation projection on the face
            # on the both adjacent cells.
            # Ref. 1 JCP 281, 28-54, Sec 4.2
            # Ref. 2 JSC 26(3), 301-327, Definition 1
            self.mbasis = get_polybasis(self.name, self.order + 1, self.mpts)
Пример #2
0
    def __init__(self, nspts, cfg):
        self.nspts = nspts
        self.cfg = cfg
        self.order = cfg.getint('solver', 'order')

        self.antialias = cfg.get('solver', 'anti-alias', 'none')
        self.antialias = {s.strip() for s in self.antialias.split(',')}
        self.antialias.discard('none')
        if self.antialias - {'flux', 'surf-flux'}:
            raise ValueError('Invalid anti-alias options')

        self.ubasis = get_polybasis(self.name, self.order + 1, self.upts)

        if nspts:
            self.nsptsord = nsptord = self.order_from_nspts(nspts)
            self.sbasis = get_polybasis(self.name, nsptord, self.spts)

            # Basis for free-stream metric
            # We need p-th order pseudo grid points, which includes
            # p-th order points on faces.
            # It guarantees th q-th order collocation projection on the face
            # on the both adjacent cells.
            # Ref. 1 JCP 281, 28-54, Sec 4.2
            # Ref. 2 JSC 26(3), 301-327, Definition 1
            self.mbasis = get_polybasis(self.name, max(self.order + 1, 2),
                                        self.mpts)
Пример #3
0
    def __init__(self, nspts, cfg):
        self._nspts = nspts
        self._cfg = cfg
        self._order = cfg.getint('solver', 'order')

        self.ubasis = get_polybasis(self.name, self._order + 1, self.upts)

        if nspts:
            self._nsptsord = nsptord = self.order_from_nspts(nspts)
            self.sbasis = get_polybasis(self.name, nsptord, self.spts)
Пример #4
0
def _find_curved_eles(etype, eles, tol=1e-5):
    nspts, neles, ndims = eles.shape

    shape = subclass_where(BaseShape, name=etype)
    order = shape.order_from_nspts(nspts)
    basis = get_polybasis(etype, order, shape.std_ele(order - 1))

    lmodes = get_polybasis(etype, 2).degrees
    hmodes = [i for i, j in enumerate(basis.degrees) if j not in lmodes]

    ehmodes = basis.invvdm.T[hmodes] @ eles.reshape(nspts, -1)
    ehmodes = ehmodes.reshape(-1, neles, ndims)

    return np.any(np.abs(ehmodes) > tol, axis=(0, 2))
Пример #5
0
    def __init__(self, nspts, cfg):
        self.nspts = nspts
        self.cfg = cfg
        self.order = cfg.getint('solver', 'order')

        self.antialias = cfg.get('solver', 'anti-alias', 'none')
        self.antialias = {s.strip() for s in self.antialias.split(',')}
        self.antialias.discard('none')
        if self.antialias - {'flux', 'div-flux', 'surf-flux'}:
            raise ValueError('Invalid anti-alias options')

        self.ubasis = get_polybasis(self.name, self.order + 1, self.upts)

        if nspts:
            self.nsptsord = nsptord = self.order_from_nspts(nspts)
            self.sbasis = get_polybasis(self.name, nsptord, self.spts)
Пример #6
0
    def _fbasis_coeffs_for(self, ftype, fproj, fdjacs, nffpts):
        # Suitable quadrature rules for various face types
        qrule_map = {
            'line': ('gauss-legendre', self._order + 1),
            'quad': ('gauss-legendre', (self._order + 1)**2),
            'tri': ('williams-shunn', 36)
        }

        # Obtain a quadrature rule for integrating on the face
        qrule = get_quadrule(ftype, *qrule_map[ftype])

        # Project the rule points onto the various faces
        proj = fproj(*np.atleast_2d(qrule.np_points.T))
        qfacepts = np.vstack(list(np.broadcast(*p)) for p in proj)

        # Obtain a nodal basis on the reference face
        fname = self._cfg.get('solver-interfaces-' + ftype, 'flux-pts')
        ffpts = get_quadrule(ftype, fname, nffpts)
        nodeb = get_polybasis(ftype, self._order + 1, ffpts.np_points)

        L = nodeb.nodal_basis_at(qrule.np_points)

        M = self.ubasis.ortho_basis_at(qfacepts)
        M = M.reshape(-1, len(proj), len(qrule.np_points))

        # Do the quadrature
        S = np.einsum('i...,ik,jli->lkj', qrule.np_weights, L, M)

        # Account for differing face areas
        S *= np.asanyarray(fdjacs)[:,None,None]

        return S.reshape(-1, self.nupts)
Пример #7
0
    def __init__(self, nspts, cfg):
        self.nspts = nspts
        self.cfg = cfg
        self.order = cfg.getint('solver', 'order')

        self.antialias = cfg.get('solver', 'anti-alias', 'none')
        self.antialias = {s.strip() for s in self.antialias.split(',')}
        self.antialias.discard('none')
        if self.antialias - {'flux', 'div-flux', 'surf-flux'}:
            raise ValueError('Invalid anti-alias options')

        self.ubasis = get_polybasis(self.name, self.order + 1, self.upts)

        if nspts:
            self.nsptsord = nsptord = self.order_from_nspts(nspts)
            self.sbasis = get_polybasis(self.name, nsptord, self.spts)
Пример #8
0
    def _linearise_eles(self, lintol):
        lidx = {}

        for etype, pent in self._elenodes:
            if pent != self._felespent:
                continue

            # Elements and type information
            elesix = self._elenodes[etype, pent]
            petype, nnodes = self._etype_map[etype]

            # Obtain the dimensionality of the element type
            ndim = self._petype_ndim[petype]

            # Node maps between input and PyFR orderings
            itop = self._nodemaps[petype, nnodes]
            ptoi = np.argsort(itop)

            # Construct the element array
            eles = self._nodepts[elesix[:, itop], :ndim].swapaxes(0, 1)

            # Generate the associated polynomial bases
            shape = subclass_where(BaseShape, name=petype)
            order = shape.order_from_nspts(nnodes)
            hbasis = get_polybasis(petype, order, shape.std_ele(order - 1))
            lbasis = get_polybasis(petype, 2, shape.std_ele(1))

            htol = hbasis.nodal_basis_at(lbasis.pts)
            ltoh = lbasis.nodal_basis_at(hbasis.pts)

            leles = (ltoh @ htol) @ eles.reshape(nnodes, -1)
            leles = leles.reshape(nnodes, -1, ndim)

            # Use this to determine which elements are linear
            num = np.max(np.abs(eles - leles), axis=0)
            den = np.max(eles, axis=0) - np.min(eles, axis=0)
            lin = lidx[petype] = np.any(num / den < lintol, axis=1)

            for ix in np.nonzero(lin)[0]:
                self._nodepts[elesix[ix], :ndim] = leles[ptoi, ix]

        return lidx
Пример #9
0
    def facebases(self):
        fb = {}

        for kind in {k for k, p, n, a in self.faces}:
            rule = self.cfg.get('solver-interfaces-' + kind, 'flux-pts')
            npts = self.npts_for_face[kind](self.order)

            pts = get_quadrule(kind, rule, npts).pts

            fb[kind] = get_polybasis(kind, self.order + 1, pts)

        return fb
Пример #10
0
    def facebases(self):
        fb = {}

        for kind in {k for k, p, n in self.faces}:
            rule = self.cfg.get(f'solver-interfaces-{kind}', 'flux-pts')
            npts = self.npts_for_face[kind](self.order)

            pts = get_quadrule(kind, rule, npts).pts

            fb[kind] = get_polybasis(kind, self.order + 1, pts)

        return fb
Пример #11
0
    def fbasis_coeffs(self):
        coeffs = []
        rcache = {}

        # Suitable quadrature rules for various face types
        qrule_map = {
            'line': ('gauss-legendre', self.order + 1),
            'quad': ('gauss-legendre', (self.order + 1)**2),
            'tri': ('williams-shunn', 36)
        }

        for kind, proj, norm, area in self.faces:
            # Obtain a quadrature rule for integrating on the reference face
            # and evaluate this rule at the nodal basis defined by the flux
            # points
            try:
                qr, L = rcache[kind]
            except KeyError:
                qr = get_quadrule(kind, *qrule_map[kind])

                rule = self.cfg.get('solver-interfaces-' + kind, 'flux-pts')
                npts = self.npts_for_face[kind](self.order)

                pts = get_quadrule(kind, rule, npts).np_points
                ppb = get_polybasis(kind, self.order + 1, pts)

                L = ppb.nodal_basis_at(qr.np_points)

                rcache[kind] = (qr, L)

            # Do the quadrature
            M = self.ubasis.ortho_basis_at(_proj_rule_pts(proj, qr))
            S = np.einsum('i...,ik,ji->kj', area*qr.np_weights, L, M)

            coeffs.append(S)

        return np.vstack(coeffs)
Пример #12
0
    def fbasis_coeffs(self):
        coeffs = []
        rcache = {}

        # Suitable quadrature rules for various face types
        qrule_map = {
            'line': ('gauss-legendre', self.order + 1),
            'quad': ('gauss-legendre', (self.order + 1)**2),
            'tri': ('williams-shunn', 36)
        }

        for kind, proj, norm, area in self.faces:
            # Obtain a quadrature rule for integrating on the reference face
            # and evaluate this rule at the nodal basis defined by the flux
            # points
            try:
                qr, L = rcache[kind]
            except KeyError:
                qr = get_quadrule(kind, *qrule_map[kind])

                rule = self.cfg.get('solver-interfaces-' + kind, 'flux-pts')
                npts = self.npts_for_face[kind](self.order)

                pts = get_quadrule(kind, rule, npts).np_points
                ppb = get_polybasis(kind, self.order + 1, pts)

                L = ppb.nodal_basis_at(qr.np_points)

                rcache[kind] = (qr, L)

            # Do the quadrature
            M = self.ubasis.ortho_basis_at(_proj_rule_pts(proj, qr))
            S = np.einsum('i...,ik,ji->kj', area * qr.np_weights, L, M)

            coeffs.append(S)

        return np.vstack(coeffs)
Пример #13
0
    def set_backend(self, backend, nscalupts, nonce, linoff):
        super().set_backend(backend, nscalupts, nonce, linoff)

        kernel = self._be.kernel
        kprefix = 'pyfr.solvers.baseadvecdiff.kernels'
        slicem = self._slice_mat

        # Register our pointwise kernels
        self._be.pointwise.register(f'{kprefix}.gradcoru')
        self._be.pointwise.register(f'{kprefix}.gradcorulin')

        # Mesh regions
        regions = self._mesh_regions

        self.kernels['_copy_fpts'] = lambda: kernel(
            'copy', self._vect_fpts.slice(0, self.nfpts), self._scal_fpts)
        self.kernels['tgradpcoru_upts'] = lambda uin: kernel(
            'mul',
            self.opmat('M4 - M6*M0'),
            self.scal_upts[uin],
            out=self._vect_upts)
        self.kernels['tgradcoru_upts'] = lambda: kernel('mul',
                                                        self.opmat('M6'),
                                                        self._vect_fpts.slice(
                                                            0, self.nfpts),
                                                        out=self._vect_upts,
                                                        beta=1.0)

        # Template arguments for the physical gradient kernel
        tplargs = {
            'ndims': self.ndims,
            'nvars': self.nvars,
            'nverts': len(self.basis.linspts),
            'jac_exprs': self.basis.jac_exprs
        }

        if 'curved' in regions:
            self.kernels['gradcoru_upts_curved'] = lambda: kernel(
                'gradcoru',
                tplargs=tplargs,
                dims=[self.nupts, regions['curved']],
                gradu=slicem(self._vect_upts, 'curved'),
                smats=self.smat_at('upts', 'curved'),
                rcpdjac=self.rcpdjac_at('upts', 'curved'))

        if 'linear' in regions:
            self.kernels['gradcoru_upts_linear'] = lambda: kernel(
                'gradcorulin',
                tplargs=tplargs,
                dims=[self.nupts, regions['linear']],
                gradu=slicem(self._vect_upts, 'linear'),
                upts=self.upts,
                verts=self.ploc_at('linspts', 'linear'))

        def gradcoru_fpts():
            nupts, nfpts = self.nupts, self.nfpts
            vupts, vfpts = self._vect_upts, self._vect_fpts

            # Exploit the block-diagonal form of the operator
            muls = [
                kernel('mul', self.opmat('M0'),
                       vupts.slice(i * nupts, (i + 1) * nupts),
                       vfpts.slice(i * nfpts, (i + 1) * nfpts))
                for i in range(self.ndims)
            ]

            return MetaKernel(muls)

        self.kernels['gradcoru_fpts'] = gradcoru_fpts

        if 'flux' in self.antialias:

            def gradcoru_qpts():
                nupts, nqpts = self.nupts, self.nqpts
                vupts, vqpts = self._vect_upts, self._vect_qpts

                # Exploit the block-diagonal form of the operator
                muls = [
                    self._be.kernel('mul', self.opmat('M7'),
                                    vupts.slice(i * nupts, (i + 1) * nupts),
                                    vqpts.slice(i * nqpts, (i + 1) * nqpts))
                    for i in range(self.ndims)
                ]

                return MetaKernel(muls)

            self.kernels['gradcoru_qpts'] = gradcoru_qpts

        # Shock capturing
        shock_capturing = self.cfg.get('solver', 'shock-capturing', 'none')
        if shock_capturing == 'artificial-viscosity':
            tags = {'align'}

            # Register the kernels
            self._be.pointwise.register(
                'pyfr.solvers.baseadvecdiff.kernels.shocksensor')

            # Obtain the scalar variable to be used for shock sensing
            shockvar = self.convarmap[self.ndims].index(self.shockvar)

            # Obtain the name, degrees, and order of our solution basis
            ubname = self.basis.ubasis.name
            ubdegs = self.basis.ubasis.degrees
            uborder = self.basis.ubasis.order

            # Obtain the degrees of a basis whose order is one lower
            lubdegs = get_polybasis(ubname, max(0, uborder - 1)).degrees

            # Compute the intersection
            ind_modes = [d not in lubdegs for d in ubdegs]

            # Template arguments
            tplargs_artvisc = dict(nvars=self.nvars,
                                   nupts=self.nupts,
                                   svar=shockvar,
                                   c=self.cfg.items_as(
                                       'solver-artificial-viscosity', float),
                                   order=self.basis.order,
                                   ind_modes=ind_modes,
                                   invvdm=self.basis.ubasis.invvdm.T)

            # Allocate space for the artificial viscosity vector
            self.artvisc = self._be.matrix((1, self.neles),
                                           extent=nonce + 'artvisc',
                                           tags=tags)

            # Apply the sensor to estimate the required artificial viscosity
            self.kernels['shocksensor'] = lambda uin: self._be.kernel(
                'shocksensor',
                tplargs=tplargs_artvisc,
                dims=[self.neles],
                u=self.scal_upts[uin],
                artvisc=self.artvisc)
        elif shock_capturing == 'none':
            self.artvisc = None
        else:
            raise ValueError('Invalid shock capturing scheme')