Exemplo n.º 1
0
def get_integrator(backend, systemcls, rallocs, mesh, initsoln, cfg):
    form = cfg.get('solver-time-integrator', 'formulation', 'std')

    if form == 'std':
        cn = cfg.get('solver-time-integrator', 'controller')
        sn = cfg.get('solver-time-integrator', 'scheme')

        cc = subclass_where(BaseStdController, controller_name=cn)
        sc = subclass_where(BaseStdStepper, stepper_name=sn)
    elif form == 'dual':
        cn = cfg.get('solver-time-integrator', 'controller')
        sn = cfg.get('solver-time-integrator', 'scheme')

        cc = subclass_where(BaseDualController, controller_name=cn)
        sc = subclass_where(BaseDualStepper, stepper_name=sn)
    else:
        raise ValueError('Invalid integrator formulation')

    # Determine the integrator name
    name = '_'.join([form, cn, sn, 'integrator'])
    name = re.sub('(?:^|_|-)([a-z])', lambda m: m.group(1).upper(), name)

    # Composite the base classes together to form a new type
    integrator = type(name, (cc, sc), dict(name=name))

    # Construct and return an instance of this new integrator class
    return integrator(backend, systemcls, rallocs, mesh, initsoln, cfg)
Exemplo n.º 2
0
Arquivo: vtk.py Projeto: uberstig/PyFR
    def _write_data(self, vtuf, mk, sk):
        name = self.mesh_inf[mk][0]
        mesh = self.mesh[mk]
        soln = self.soln[sk]

        # Get the shape and sub division classes
        shapecls = subclass_where(BaseShape, name=name)
        subdvcls = subclass_where(BaseShapeSubDiv, name=name)

        # Dimensions
        nspts, neles = mesh.shape[:2]

        # Sub divison points inside of a standard element
        svpts = shapecls.std_ele(self.divisor)
        nsvpts = len(svpts)

        # Shape
        soln_b = shapecls(nspts, self.cfg)

        # Generate the operator matrices
        mesh_vtu_op = soln_b.sbasis.nodal_basis_at(svpts)
        soln_vtu_op = soln_b.ubasis.nodal_basis_at(svpts)

        # Calculate node locations of vtu elements
        vpts = np.dot(mesh_vtu_op, mesh.reshape(nspts, -1))
        vpts = vpts.reshape(nsvpts, -1, self.ndims)

        # Calculate solution at node locations of vtu elements
        vsol = np.dot(soln_vtu_op, soln.reshape(-1, self.nvars*neles))
        vsol = vsol.reshape(nsvpts, self.nvars, -1).swapaxes(0, 1)

        # Append dummy z dimension for points in 2D
        if self.ndims == 2:
            vpts = np.pad(vpts, [(0, 0), (0, 0), (0, 1)], 'constant')

        # Write element node locations to file
        self._write_darray(vpts.swapaxes(0, 1), vtuf, self.dtype)

        # Perform the sub division
        nodes = subdvcls.subnodes(self.divisor)

        # Prepare vtu cell arrays
        vtu_con = np.tile(nodes, (neles, 1))
        vtu_con += (np.arange(neles)*nsvpts)[:, None]

        # Generate offset into the connectivity array
        vtu_off = np.tile(subdvcls.subcelloffs(self.divisor), (neles, 1))
        vtu_off += (np.arange(neles)*len(nodes))[:, None]

        # Tile vtu cell type numbers
        vtu_typ = np.tile(subdvcls.subcelltypes(self.divisor), neles)

        # Write vtu node connectivity, connectivity offsets and cell types
        self._write_darray(vtu_con, vtuf, np.int32)
        self._write_darray(vtu_off, vtuf, np.int32)
        self._write_darray(vtu_typ, vtuf, np.uint8)

        # Process and write out the various fields
        for arr in self._proc_fields(vsol):
            self._write_darray(arr.T, vtuf, self.dtype)
Exemplo n.º 3
0
def _write_vtu_header(args, vtuf, m_inf, s_inf, off):
    # Set vtk name for float, set size in bytes
    if args.precision == 'single':
        flt = ['Float32', 4]
    else:
        flt = ['Float64', 8]

    # Get the shape and sub division classes
    shapecls = subclass_where(BaseShape, name=m_inf[0])
    subdvcls = subclass_where(BaseShapeSubDiv, name=m_inf[0])

    npts = shapecls.nspts_from_order(args.divisor + 1) * m_inf[1][1]

    cells = subdvcls.subcells(args.divisor)
    nodes = subdvcls.subnodes(args.divisor)

    ncells = len(cells) * m_inf[1][1]
    nnodes = len(nodes) * m_inf[1][1]

    # Standard template for vtk DataArray string
    darray = '<DataArray Name="%s" type="%s" NumberOfComponents="%s" '\
             'format="appended" offset="%d"/>\n'

    # Write headers for vtu elements
    vtuf.write('<Piece NumberOfPoints="%s" NumberOfCells="%s">\n<Points>\n' %
               (npts, ncells))

    # Lists of DataArray "names", "types" and "NumberOfComponents"
    nams = [
        '', 'connectivity', 'offsets', 'types', 'Density', 'Velocity',
        'Pressure'
    ]
    typs = [flt[0], 'Int32', 'Int32', 'UInt8'] + [flt[0]] * 3
    ncom = ['3', '', '', '', '1', str(m_inf[1][2]), '1']

    # Calculate size of described DataArrays (in bytes)
    offs = np.array([0, 3, 4 * nnodes, 4 * ncells, ncells, 1, m_inf[1][2], 1])
    offs[[1, 5, 6, 7]] *= flt[1] * npts

    # Write vtk DaraArray headers
    for i in xrange(len(nams)):
        vtuf.write(
            darray %
            (nams[i], typs[i], ncom[i], sum(offs[:i + 1]) + i * 4 + off))

        # Write ends/starts of vtk file objects
        if i == 0:
            vtuf.write('</Points>\n<Cells>\n')
        elif i == 3:
            vtuf.write('</Cells>\n<PointData>\n')

    # Write end of vtk element data
    vtuf.write('</PointData>\n</Piece>\n')

    # Return the number of bytes appended
    return sum(offs) + 4 * len(nams)
Exemplo n.º 4
0
def get_pseudo_stepper_cls(name, porder):
    for p in range(porder, -1, -1):
        try:
            return subclass_where(BaseDualPseudoStepper,
                                  pseudo_stepper_name=name,
                                  pseudo_stepper_porder=p)
        except KeyError:
            pass

    return subclass_where(BaseDualPseudoStepper, pseudo_stepper_name=name)
Exemplo n.º 5
0
    def _get_npts_ncells_nnodes(self, sk):
        etype, neles = self.soln_inf[sk][0], self.soln_inf[sk][1][2]

        # Get the shape and sub division classes
        shapecls = subclass_where(BaseShape, name=etype)
        subdvcls = subclass_where(BaseShapeSubDiv, name=etype)

        # Number of vis points
        npts = shapecls.nspts_from_order(self.divisor + 1)*neles

        # Number of sub cells and nodes
        ncells = len(subdvcls.subcells(self.divisor))*neles
        nnodes = len(subdvcls.subnodes(self.divisor))*neles

        return npts, ncells, nnodes
Exemplo n.º 6
0
    def _get_npts_ncells_nnodes(self, mk):
        m_inf = self.mesh_inf[mk]

        # Get the shape and sub division classes
        shapecls = subclass_where(BaseShape, name=m_inf[0])
        subdvcls = subclass_where(BaseShapeSubDiv, name=m_inf[0])

        # Number of vis points
        npts = shapecls.nspts_from_order(self.divisor + 1) * m_inf[1][1]

        # Number of sub cells and nodes
        ncells = len(subdvcls.subcells(self.divisor)) * m_inf[1][1]
        nnodes = len(subdvcls.subnodes(self.divisor)) * m_inf[1][1]

        return npts, ncells, nnodes
Exemplo n.º 7
0
    def _get_npts_ncells_nnodes(self, mk):
        m_inf = self.mesh_inf[mk]

        # Get the shape and sub division classes
        shapecls = subclass_where(BaseShape, name=m_inf[0])
        subdvcls = subclass_where(BaseShapeSubDiv, name=m_inf[0])

        # Number of vis points
        npts = shapecls.nspts_from_order(self.divisor + 1)*m_inf[1][1]

        # Number of sub cells and nodes
        ncells = len(subdvcls.subcells(self.divisor))*m_inf[1][1]
        nnodes = len(subdvcls.subnodes(self.divisor))*m_inf[1][1]

        return npts, ncells, nnodes
Exemplo n.º 8
0
    def __init__(self, args):
        from pyfr.solvers.base import BaseSystem

        self.outf = args.outf

        # Load the mesh and solution files
        self.soln = NativeReader(args.solnf)
        self.mesh = NativeReader(args.meshf)

        # Check solution and mesh are compatible
        if self.mesh['mesh_uuid'] != self.soln['mesh_uuid']:
            raise RuntimeError('Solution "%s" was not computed on mesh "%s"' %
                               (args.solnf, args.meshf))

        # Load the configuration and stats files
        self.cfg = Inifile(self.soln['config'])
        self.stats = Inifile(self.soln['stats'])

        # Data file prefix (defaults to soln for backwards compatibility)
        self.dataprefix = self.stats.get('data', 'prefix', 'soln')

        # Get element types and array shapes
        self.mesh_inf = self.mesh.array_info('spt')
        self.soln_inf = self.soln.array_info(self.dataprefix)

        # Dimensions
        self.ndims = next(iter(self.mesh_inf.values()))[1][2]
        self.nvars = next(iter(self.soln_inf.values()))[1][1]

        # System and elements classes
        self.systemscls = subclass_where(BaseSystem,
                                         name=self.cfg.get('solver', 'system'))
        self.elementscls = self.systemscls.elementscls
Exemplo n.º 9
0
    def _pre_proc_fields_grad(self, name, mesh, soln):
        # Call the reference pre-processor
        soln = self._pre_proc_fields_ref(name, mesh, soln)

        # Dimensions
        nvars, nupts = soln.shape[:2]

        # Get the shape class
        basiscls = subclass_where(BaseShape, name=name)

        # Construct an instance of the relevant elements class
        eles = self.elementscls(basiscls, mesh, self.cfg)

        # Get the smats and |J|^-1 to untransform the gradient
        smat = eles.smat_at_np('upts').transpose(2, 0, 1, 3)
        rcpdjac = eles.rcpdjac_at_np('upts')

        # Gradient operator
        gradop = eles.basis.m4.astype(self.dtype)

        # Evaluate the transformed gradient of the solution
        gradsoln = np.dot(gradop, soln.swapaxes(0, 1).reshape(nupts, -1))
        gradsoln = gradsoln.reshape(self.ndims, nupts, nvars, -1)

        # Untransform
        gradsoln = np.einsum('ijkl,jkml->mikl',
                             smat * rcpdjac,
                             gradsoln,
                             dtype=self.dtype,
                             casting='same_kind')
        gradsoln = gradsoln.reshape(nvars * self.ndims, nupts, -1)

        return np.vstack([soln, gradsoln])
Exemplo n.º 10
0
    def _pre_proc_fields_grad(self, name, mesh, soln):
        # Call the reference pre-processor
        soln = self._pre_proc_fields_ref(name, mesh, soln)

        # Dimensions
        nvars, nupts = soln.shape[:2]

        # Get the shape class
        basiscls = subclass_where(BaseShape, name=name)

        # Construct an instance of the relevant elements class
        eles = self.elementscls(basiscls, mesh, self.cfg)

        # Get the smats and |J|^-1 to untransform the gradient
        smat = eles.smat_at_np('upts').transpose(2, 0, 1, 3)
        rcpdjac = eles.rcpdjac_at_np('upts')

        # Gradient operator
        gradop = eles.basis.m4.astype(self.dtype)

        # Evaluate the transformed gradient of the solution
        gradsoln = np.dot(gradop, soln.swapaxes(0, 1).reshape(nupts, -1))
        gradsoln = gradsoln.reshape(self.ndims, nupts, nvars, -1)

        # Untransform
        gradsoln = np.einsum('ijkl,jkml->mikl', smat*rcpdjac, gradsoln,
                             dtype=self.dtype, casting='same_kind')
        gradsoln = gradsoln.reshape(nvars*self.ndims, nupts, -1)

        return np.vstack([soln, gradsoln])
Exemplo n.º 11
0
    def __init__(self, args):
        from pyfr.solvers.base import BaseSystem

        self.outf = args.outf

        # Load the mesh and solution files
        self.soln = NativeReader(args.solnf)
        self.mesh = NativeReader(args.meshf)

        # Check solution and mesh are compatible
        if self.mesh['mesh_uuid'] != self.soln['mesh_uuid']:
            raise RuntimeError('Solution "%s" was not computed on mesh "%s"' %
                               (args.solnf, args.meshf))

        # Load the configuration and stats files
        self.cfg = Inifile(self.soln['config'])
        self.stats = Inifile(self.soln['stats'])

        # Data file prefix (defaults to soln for backwards compatibility)
        self.dataprefix = self.stats.get('data', 'prefix', 'soln')

        # Get element types and array shapes
        self.mesh_inf = self.mesh.array_info('spt')
        self.soln_inf = self.soln.array_info(self.dataprefix)

        # Dimensions
        self.ndims = next(iter(self.mesh_inf.values()))[1][2]
        self.nvars = next(iter(self.soln_inf.values()))[1][1]

        # System and elements classes
        self.systemscls = subclass_where(
            BaseSystem, name=self.cfg.get('solver', 'system')
        )
        self.elementscls = self.systemscls.elementscls
Exemplo n.º 12
0
def get_pseudo_integrator(backend, systemcls, rallocs, mesh,
                          initsoln, cfg, tcoeffs, dt):
    register_tabulated_pseudo_steppers()

    # A new type of integrator allowing multip convergence acceleration
    if 'solver-dual-time-integrator-multip' in cfg.sections():
        return DualMultiPIntegrator(backend, systemcls, rallocs, mesh,
                                    initsoln, cfg, tcoeffs, dt)
    else:
        cn = cfg.get('solver-time-integrator', 'pseudo-controller')
        pn = cfg.get('solver-time-integrator', 'pseudo-scheme')
        porder = cfg.getint('solver', 'order')

        cc = subclass_where(BaseDualPseudoController,
                            pseudo_controller_name=cn)
        pc = get_pseudo_stepper_cls(pn, porder)

        # Determine the integrator name
        name = '_'.join(['dual', cn, pn, 'pseudointegrator'])
        name = re.sub('(?:^|_|-)([a-z])', lambda m: m.group(1).upper(), name)

        pseudointegrator = type(name, (cc, pc), dict(name=name))

        # Construct and return an instance of this new integrator class
        return pseudointegrator(backend, systemcls, rallocs, mesh,
                                initsoln, cfg, tcoeffs, dt)
Exemplo n.º 13
0
def get_quadrule(eletype, rule, npts):
    eletype_map = {
        'line': BaseLineQuadRule,
        'hex': BaseHexQuadRule,
        'pri': BasePriQuadRule,
        'quad': BaseQuadQuadRule,
        'tet': BaseTetQuadRule,
        'tri': BaseTriQuadRule
    }

    # Obtain the base quadrature rule class for this element type
    basecls = eletype_map[eletype]

    # See if rule looks like the name of a scheme
    if re.match(r'[a-zA-Z0-9\-+*_]+$', rule):
        return subclass_where(basecls, name=rule)(npts)
    # Otherwise see if it looks like a tabulation
    elif 'PTS' in rule.upper():
        # Create a suitable subclass
        rulecls = type(eletype, (basecls, BaseTabulatedQuadRule), {})

        # Instantiate and validate
        r = rulecls(rule)
        if len(r.points) != npts:
            raise ValueError('Invalid number of points for quad rule')

        return r
    # Invalid
    else:
        raise ValueError('Invalid quadrature rule')
Exemplo n.º 14
0
def get_integrator(backend, systemcls, rallocs, mesh, initsoln, cfg):
    # Look-up the controller, stepper and writer names
    c = cfg.get('solver-time-integrator', 'controller')
    s = cfg.get('solver-time-integrator', 'scheme')

    controller = subclass_where(BaseController, controller_name=c)
    stepper = subclass_where(BaseStepper, stepper_name=s)

    # Determine the integrator name
    name = '_'.join([c, s])
    name = re.sub('(?:^|_|-)([a-z])', lambda m: m.group(1).upper(), name)

    # Composite the classes together to form a new type
    integrator = type(name, (controller, stepper), dict(name=name))

    # Construct and return an instance of this new integrator class
    return integrator(backend, systemcls, rallocs, mesh, initsoln, cfg)
Exemplo n.º 15
0
    def _write_data(self, vtuf, mk, sk):
        name = self.mesh_inf[mk][0]
        mesh = self.mesh[mk].astype(self.dtype)
        soln = self.soln[sk].swapaxes(0, 1).astype(self.dtype)

        # Dimensions
        nspts, neles = mesh.shape[:2]

        # Sub divison points inside of a standard element
        svpts = self._get_std_ele(name, nspts)
        nsvpts = len(svpts)

        # Generate the operator matrices
        mesh_vtu_op = self._get_mesh_op(name, nspts, svpts)
        soln_vtu_op = self._get_soln_op(name, nspts, svpts)

        # Calculate node locations of VTU elements
        vpts = np.dot(mesh_vtu_op, mesh.reshape(nspts, -1))
        vpts = vpts.reshape(nsvpts, -1, self.ndims)

        # Pre-process the solution
        soln = self._pre_proc_fields(name, mesh, soln).swapaxes(0, 1)

        # Interpolate the solution to the vis points
        vsoln = np.dot(soln_vtu_op, soln.reshape(len(soln), -1))
        vsoln = vsoln.reshape(nsvpts, -1, neles).swapaxes(0, 1)

        # Append dummy z dimension for points in 2D
        if self.ndims == 2:
            vpts = np.pad(vpts, [(0, 0), (0, 0), (0, 1)], 'constant')

        # Write element node locations to file
        self._write_darray(vpts.swapaxes(0, 1), vtuf, self.dtype)

        # Perform the sub division
        subdvcls = subclass_where(BaseShapeSubDiv, name=name)
        nodes = subdvcls.subnodes(self.divisor)

        # Prepare VTU cell arrays
        vtu_con = np.tile(nodes, (neles, 1))
        vtu_con += (np.arange(neles)*nsvpts)[:, None]

        # Generate offset into the connectivity array
        vtu_off = np.tile(subdvcls.subcelloffs(self.divisor), (neles, 1))
        vtu_off += (np.arange(neles)*len(nodes))[:, None]

        # Tile VTU cell type numbers
        vtu_typ = np.tile(subdvcls.subcelltypes(self.divisor), neles)

        # Write VTU node connectivity, connectivity offsets and cell types
        self._write_darray(vtu_con, vtuf, np.int32)
        self._write_darray(vtu_off, vtuf, np.int32)
        self._write_darray(vtu_typ, vtuf, np.uint8)

        # Process and write out the various fields
        for arr in self._post_proc_fields(vsoln):
            self._write_darray(arr.T, vtuf, self.dtype)
Exemplo n.º 16
0
    def _write_data(self, vtuf, mk, sk):
        name = self.mesh_inf[mk][0]
        mesh = self.mesh[mk].astype(self.dtype)
        soln = self.soln[sk].swapaxes(0, 1).astype(self.dtype)

        # Dimensions
        nspts, neles = mesh.shape[:2]

        # Sub divison points inside of a standard element
        svpts = self._get_std_ele(name, nspts)
        nsvpts = len(svpts)

        # Generate the operator matrices
        mesh_vtu_op = self._get_mesh_op(name, nspts, svpts)
        soln_vtu_op = self._get_soln_op(name, nspts, svpts)

        # Calculate node locations of VTU elements
        vpts = np.dot(mesh_vtu_op, mesh.reshape(nspts, -1))
        vpts = vpts.reshape(nsvpts, -1, self.ndims)

        # Pre-process the solution
        soln = self._pre_proc_fields(name, mesh, soln).swapaxes(0, 1)

        # Interpolate the solution to the vis points
        vsoln = np.dot(soln_vtu_op, soln.reshape(len(soln), -1))
        vsoln = vsoln.reshape(nsvpts, -1, neles).swapaxes(0, 1)

        # Append dummy z dimension for points in 2D
        if self.ndims == 2:
            vpts = np.pad(vpts, [(0, 0), (0, 0), (0, 1)], 'constant')

        # Write element node locations to file
        self._write_darray(vpts.swapaxes(0, 1), vtuf, self.dtype)

        # Perform the sub division
        subdvcls = subclass_where(BaseShapeSubDiv, name=name)
        nodes = subdvcls.subnodes(self.divisor)

        # Prepare VTU cell arrays
        vtu_con = np.tile(nodes, (neles, 1))
        vtu_con += (np.arange(neles) * nsvpts)[:, None]

        # Generate offset into the connectivity array
        vtu_off = np.tile(subdvcls.subcelloffs(self.divisor), (neles, 1))
        vtu_off += (np.arange(neles) * len(nodes))[:, None]

        # Tile VTU cell type numbers
        vtu_typ = np.tile(subdvcls.subcelltypes(self.divisor), neles)

        # Write VTU node connectivity, connectivity offsets and cell types
        self._write_darray(vtu_con, vtuf, np.int32)
        self._write_darray(vtu_off, vtuf, np.int32)
        self._write_darray(vtu_typ, vtuf, np.uint8)

        # Process and write out the various fields
        for arr in self._post_proc_fields(vsoln):
            self._write_darray(arr.T, vtuf, self.dtype)
Exemplo n.º 17
0
    def __init__(self, npts):
        roots = mp.polyroots([1, 1, 0, -2*npts])
        roots = [int(x) for x in roots if mp.isint(x) and x > 0]

        if not roots:
            raise ValueError('Invalid number of points for quad rule')

        tname, lname = self.name.split('*')

        trulecls = subclass_where(BaseTriQuadRule, name=tname)
        trule = trulecls(roots[0]*(roots[0] + 1) // 2)

        lrulecls = subclass_where(BaseLineQuadRule, name=lname)
        lrule = lrulecls[lname](roots[0])

        self.points = [(t[0], t[1], l)
                       for l in lrule.points for t in trule.points]

        if hasattr(trule, 'weights') and hasattr(lrule, 'weights'):
            self.weights = [i*j for j in lrule.weights for i in trule.weights]
Exemplo n.º 18
0
    def __init__(self, npts):
        if not mp.isint(mp.sqrt(npts)):
            raise ValueError('Invalid number of points for quad rule')

        rulecls = subclass_where(BaseLineQuadRule, name=self.name)
        rule = rulecls(int(mp.sqrt(npts)))

        self.points = [(i, j) for j in rule.points for i in rule.points]

        if hasattr(rule, 'weights'):
            self.weights = [i*j for j in rule.weights for i in rule.weights]
Exemplo n.º 19
0
def get_std_ele_by_name(name, order):
    """ Gets the shape points of a standard element of name and order

    :param name: Name of PyFR element type
    :param order: Shape order of element
    :type name: string
    :type order: integer
    :rtype: np.ndarray

    """
    return subclass_where(BaseBasis, name=name).std_ele(order)
Exemplo n.º 20
0
def get_pseudo_integrator(backend, systemcls, rallocs, mesh,
                          initsoln, cfg, tcoeffs, dt):
    # A new type of integrator allowing multip convergence acceleration
    if 'solver-dual-time-integrator-multip' in cfg.sections():
        return DualMultiPIntegrator(backend, systemcls, rallocs, mesh,
                                    initsoln, cfg, tcoeffs, dt)
    else:
        cn = cfg.get('solver-time-integrator', 'pseudo-controller')
        pn = cfg.get('solver-time-integrator', 'pseudo-scheme')

        cc = subclass_where(BaseDualPseudoController, pseudo_controller_name=cn)
        pc = subclass_where(BaseDualPseudoStepper, pseudo_stepper_name=pn)

        # Determine the integrator name
        name = '_'.join(['dual', cn, pn, 'pseudointegrator'])
        name = re.sub('(?:^|_|-)([a-z])', lambda m: m.group(1).upper(), name)

        pseudointegrator = type(name, (cc, pc), dict(name=name))

        # Construct and return an instance of this new integrator class
        return pseudointegrator(backend, systemcls, rallocs, mesh,
                                initsoln, cfg, tcoeffs, dt)
Exemplo n.º 21
0
    def _get_npts_ncells_nnodes_ho(self, sk):
        etype, neles = self.soln_inf[sk][0], self.soln_inf[sk][1][2]

        # Fallback to subdivision for pyramids
        if etype == 'pyr':
            return self._get_npts_ncells_nnodes_lin(sk)

        # Get the shape and sub division classes
        shapecls = subclass_where(BaseShape, name=etype)

        # Total number of vis points
        npts = neles*shapecls.nspts_from_order(self.etypes_div[etype] + 1)

        return npts, neles, npts
Exemplo n.º 22
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))
Exemplo n.º 23
0
def get_integrator(backend, systemcls, rallocs, mesh, initsoln, cfg):
    form = cfg.get('solver-time-integrator', 'formulation', 'std')

    if form == 'std':
        cn = cfg.get('solver-time-integrator', 'controller')
        sn = cfg.get('solver-time-integrator', 'scheme')

        cc = subclass_where(BaseStdController, controller_name=cn)
        sc = subclass_where(BaseStdStepper, stepper_name=sn)

        bases = [(cn, cc), (sn, sc)]
    elif form == 'dual':
        cn = cfg.get('solver-time-integrator', 'controller')
        pn = cfg.get('solver-time-integrator', 'pseudo-scheme')
        sn = cfg.get('solver-time-integrator', 'scheme')

        cc = subclass_where(BaseDualController, controller_name=cn)
        pc = subclass_where(BaseDualPseudoStepper, pseudo_stepper_name=pn)
        sc = subclass_where(BaseDualStepper, stepper_name=sn)

        bases = [(cn, cc), (pn, pc), (sn, sc)]

        if 'solver-dual-time-integrator-multip' in cfg.sections():
            bases.insert(0, ('multip', DualMultiPIntegrator))
    else:
        raise ValueError('Invalid integrator formulation')

    # Determine the integrator name
    name = '_'.join([form] + list(bn for bn, bc in bases) + ['integrator'])
    name = re.sub('(?:^|_|-)([a-z])', lambda m: m.group(1).upper(), name)

    # Composite the base classes together to form a new type
    integrator = type(name, tuple(bc for bn, bc in bases), dict(name=name))

    # Construct and return an instance of this new integrator class
    return integrator(backend, systemcls, rallocs, mesh, initsoln, cfg)
Exemplo n.º 24
0
    def _get_npts_ncells_nnodes_ho(self, sk):
        etype, neles = self.soln_inf[sk][0], self.soln_inf[sk][1][2]

        if etype == 'pyr':
            # No Lagrange pyr cells in VTK
            # Therefore, rely on sub-division with
            # linear cells
            return self._get_npts_ncells_nnodes_lin(sk)

        # Get the shape and sub division classes
        shapecls = subclass_where(BaseShape, name=etype)

        # Number of vis points
        # which coincides with the number of
        # nodes of the vtkLagrange* correspondent
        # objects
        npts = shapecls.nspts_from_order(self.etypes_div[etype] + 1) * neles

        return npts, neles, npts
Exemplo n.º 25
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
Exemplo n.º 26
0
    def __init__(self, args):
        """Loads PyFR mesh and solution files

        A check is made to ensure the solution was computed on the mesh.

        :param args: Command line arguments passed from scripts/postp.py
        :type args: class 'argparse.Namespace'

        """
        self.outf = args.outf

        # Load mesh and solution files
        self.soln = read_pyfr_data(args.solnf)
        self.mesh = read_pyfr_data(args.meshf)

        # Get element types and array shapes
        self.mesh_inf = self.mesh.array_info
        self.soln_inf = self.soln.array_info

        # Dimensions
        self.ndims = next(iter(self.mesh_inf.values()))[1][2]
        self.nvars = next(iter(self.soln_inf.values()))[1][1]

        # Check solution and mesh are compatible
        if self.mesh['mesh_uuid'] != self.soln['mesh_uuid']:
            raise RuntimeError('Solution "%s" was not computed on mesh "%s"' %
                               (args.solnf, args.meshf))

        # Load the config file
        self.cfg = Inifile(self.soln['config'])

        # System and elements classs
        self.systemscls = subclass_where(
            BaseSystem, name=self.cfg.get('solver', 'system')
        )
        self.elementscls = self.systemscls.elementscls
Exemplo n.º 27
0
def _write_vtu_data(args, vtuf, cfg, mesh, m_inf, soln, s_inf):
    """ Writes mesh and solution data for appended (binary) data .vtu files

    :param args: pyfr-postp command line arguments from argparse
    :param vtuf: .vtu output file
    :param cfg: PyFR config file used in the respective simulation
    :param mesh: Single PyFR mesh array (corresponding to soln)
    :param m_inf: Tuple of element type and array shape of mesh
    :param soln: Single PyFR solution array (corresponding to mesh)
    :param s_inf: Tuple of element type and array shape of soln
    :type args: class 'argparse.Namespace'
    :type vtuf: file
    :type cfg: class 'pyfr.inifile.Inifile'
    :type mesh: numpy.ndarray
    :type m_inf: tuple
    :type soln: numpy.ndrayy
    :type s_inf: tuple

    """
    # Set numpy name for float; set size in bytes
    if args.precision == 'single':
        flt = ['float32', 4]
    else:
        flt = ['float64', 8]

    # Get the basis class
    basiscls = subclass_where(BaseShape, name=m_inf[0])
    ndims = m_inf[1][2]

    # Set npts for divide/append cases
    if args.divisor is not None:
        npts = _npts_from_order(args.divisor, m_inf, total=False)
    else:
        npts = ParaviewWriter.vtk_to_pyfr[m_inf[0]][2]

    # Generate basis objects for solution and vtu output
    soln_b = basiscls(m_inf[1][0], cfg)
    vtu_b = basiscls(npts, cfg)

    # Generate operator matrices to move points and solutions to vtu nodes
    mesh_vtu_op = soln_b.sbasis.nodal_basis_at(vtu_b.spts)
    soln_vtu_op = soln_b.ubasis.nodal_basis_at(vtu_b.spts)

    # Calculate node locations of vtu elements
    pts = np.dot(mesh_vtu_op, mesh.reshape(m_inf[1][0],
                                           -1)).reshape(npts, -1, ndims)
    # Calculate solution at node locations of vtu elements
    sol = np.dot(soln_vtu_op, soln.reshape(s_inf[1][0],
                                           -1)).reshape(npts, s_inf[1][1], -1)

    # Append dummy z dimension for points in 2-d (required by Paraview)
    if ndims == 2:
        pts = np.append(pts, np.zeros(pts.shape[:-1])[...,None], axis=2)

    # Write element node locations to file
    _write_vtk_darray(pts.swapaxes(0,1), vtuf, flt[0])

    # Prepare vtu cell arrays (connectivity, offsets, types):
    # Generate and extend vtu sub-cell node connectivity across all elements
    vtu_con = np.tile(_base_con(m_inf[0], args.divisor),
                      (m_inf[1][1], 1))
    vtu_con += (np.arange(m_inf[1][1]) * npts)[:, None]

    # Generate offset into the connectivity array for the end of each element
    vtu_off = np.arange(_ncells_after_subdiv(m_inf, args.divisor)) + 1
    vtu_off *= ParaviewWriter.vtk_to_pyfr[m_inf[0]][2]

    # Tile vtu cell type numbers
    vtu_typ = np.tile(ParaviewWriter.vtk_to_pyfr[m_inf[0]][0],
                      _ncells_after_subdiv(m_inf, args.divisor))

    # Write vtu node connectivity, connectivity offsets and cell types
    _write_vtk_darray(vtu_con, vtuf, 'int32')
    _write_vtk_darray(vtu_off, vtuf, 'int32')
    _write_vtk_darray(vtu_typ, vtuf, 'uint8')

    # Convert rhou, rhov, [rhow] to u, v, [w] and energy to pressure
    _component_to_physical_soln(sol, cfg.getfloat('constants', 'gamma'))

    # Write Density, Velocity and Pressure
    _write_vtk_darray(sol[:,0].T, vtuf, flt[0])
    _write_vtk_darray(sol[:,1:-1].transpose(2, 0, 1), vtuf, flt[0])
    _write_vtk_darray(sol[:,-1].T, vtuf, flt[0])

    # Append high-order data as CellData if not dividing cells
    if args.divisor is None:
        # Calculate number of points written as low-order, and left to append
        nlpts = ParaviewWriter.vtk_to_pyfr[s_inf[0]][2]
        nhpts = s_inf[1][0] - nlpts

        # Generate basis objects for mesh, solution and vtu output
        mesh_b = basiscls(m_inf[1][0], cfg)

        # Get location of spts in standard element of solution order
        uord = cfg.getint('solver', 'order')
        ele_spts = subclass_where(BaseShape, name=m_inf[0]).std_ele(uord)

        # Generate operator matrices to move points and solutions to vtu nodes
        mesh_hpts_op = mesh_b.sbasis.nodal_basis_at(ele_spts)
        soln_hpts_op = mesh_b.ubasis.nodal_basis_at(ele_spts)

        # Calculate node locations of vtu elements
        pts = np.dot(mesh_hpts_op, mesh.reshape(m_inf[1][0], -1))
        pts = pts.reshape((-1,) + m_inf[1][1:])

        # Append dummy z dimension to 2-d points (required by Paraview)
        if ndims == 2:
            pts = np.append(pts, np.zeros(pts.shape[:-1])[...,None], axis=2)

        # Calculate solution at node locations
        sol = np.dot(soln_hpts_op, soln.reshape(s_inf[1][0], -1))
        sol = sol.reshape((-1,) + s_inf[1][1:])

        # Convert rhou, rhov, [rhow] to u, v, [w] and energy to pressure
        _component_to_physical_soln(sol, cfg.getfloat('constants', 'gamma'))

        # Write data arrays, one set of high order points at a time
        for gmshpt in xrange(nhpts):
            # Convert Gmsh node number to equivalent in PyFR
            pt = GmshNodeMaps.to_pyfr[s_inf[0], s_inf[1][0]][gmshpt + nlpts]

            # Write node locations, density, velocity and pressure
            _write_vtk_darray(pts[pt], vtuf, flt[0])
            _write_vtk_darray(sol[pt,0], vtuf, flt[0])
            _write_vtk_darray(sol[pt,1:-1].T, vtuf, flt[0])
            _write_vtk_darray(sol[pt,-1], vtuf, flt[0])
Exemplo n.º 28
0
    def _write_data(self, vtuf, mk, sk):
        name = self.mesh_inf[mk][0]
        mesh = self.mesh[mk].astype(self.dtype)
        soln = self.soln[sk].swapaxes(0, 1).astype(self.dtype)

        # Handle the case of partial solution files
        if soln.shape[2] != mesh.shape[1]:
            skpre, skpost = sk.rsplit('_', 1)

            mesh = mesh[:, self.soln[f'{skpre}_idxs_{skpost}'], :]

        # Dimensions
        nspts, neles = mesh.shape[:2]

        # Sub divison points inside of a standard element
        svpts = self._get_std_ele(name, nspts)
        nsvpts = len(svpts)

        if name != 'pyr' and self.ho_output:
            # Transform PyFR to VTK9 points
            # See nodemaps.py for more information on
            # why VTK9 maps are chosen over those of VTK8
            # High order `pyr` elements are not currently
            # supported in VTK
            svpts = np.array(svpts)[VTKHONodeMaps.to_pyfr[name, nsvpts]]

        # Generate the operator matrices
        mesh_vtu_op = self._get_mesh_op(name, nspts, svpts)
        soln_vtu_op = self._get_soln_op(name, nspts, svpts)

        # Calculate node locations of VTU elements
        vpts = mesh_vtu_op @ mesh.reshape(nspts, -1)
        vpts = vpts.reshape(nsvpts, -1, self.ndims)

        # Pre-process the solution
        soln = self._pre_proc_fields(name, mesh, soln).swapaxes(0, 1)

        # Interpolate the solution to the vis points
        vsoln = soln_vtu_op @ soln.reshape(len(soln), -1)
        vsoln = vsoln.reshape(nsvpts, -1, neles).swapaxes(0, 1)

        # Append dummy z dimension for points in 2D
        if self.ndims == 2:
            vpts = np.pad(vpts, [(0, 0), (0, 0), (0, 1)], 'constant')

        # Write element node locations to file
        self._write_darray(vpts.swapaxes(0, 1), vtuf, self.dtype)

        # Perform the sub division
        if name != 'pyr' and self.ho_output:
            nodes = np.arange(nsvpts)
            subcellsoff = nsvpts
            types = self.vtk_types_ho[name]
        else:
            subdvcls = subclass_where(BaseShapeSubDiv, name=name)
            nodes = subdvcls.subnodes(self.etypes_div[name])
            subcellsoff = subdvcls.subcelloffs(self.etypes_div[name])
            types = subdvcls.subcelltypes(self.etypes_div[name])

        # Prepare VTU cell arrays
        vtu_con = np.tile(nodes, (neles, 1))
        vtu_con += (np.arange(neles) * nsvpts)[:, None]

        # Generate offset into the connectivity array
        vtu_off = np.tile(subcellsoff, (neles, 1))
        vtu_off += (np.arange(neles) * len(nodes))[:, None]

        # Tile VTU cell type numbers
        vtu_typ = np.tile(types, neles)

        # Write VTU node connectivity, connectivity offsets and cell types
        self._write_darray(vtu_con, vtuf, np.int32)
        self._write_darray(vtu_off, vtuf, np.int32)
        self._write_darray(vtu_typ, vtuf, np.uint8)

        # Process and write out the various fields
        for arr in self._post_proc_fields(vsoln):
            self._write_darray(arr.T, vtuf, self.dtype)
Exemplo n.º 29
0
 def _get_shape(self, name, nspts):
     shapecls = subclass_where(BaseShape, name=name)
     return shapecls(nspts, self.cfg)
Exemplo n.º 30
0
def get_rank_allocation(mesh, cfg):
    name = cfg.get('backend', 'rank-allocator', 'linear')

    return subclass_where(BaseRankAllocator, name=name)(mesh, cfg)
Exemplo n.º 31
0
    def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg,
                 tcoeffs, dt):
        self.backend = backend

        sect = 'solver-time-integrator'
        mgsect = 'solver-dual-time-integrator-multip'

        # Get the solver order and set the initial multigrid level
        self._order = self.level = order = cfg.getint('solver', 'order')

        # Get the multigrid cycle
        self.cycle, self.csteps = zip(*cfg.getliteral(mgsect, 'cycle'))
        self.levels = sorted(set(self.cycle), reverse=True)

        if max(self.cycle) > self._order:
            raise ValueError('The multigrid level orders cannot exceed '
                             'the solution order')

        if any(abs(i - j) > 1 for i, j in zip(self.cycle, self.cycle[1:])):
            raise ValueError('The orders of consecutive multigrid levels can '
                             'only change by one')

        if self.cycle[0] != self._order or self.cycle[-1] != self._order:
            raise ValueError('The multigrid cycle needs to start end with the '
                             'highest (solution) order ')

        # Initialise the number of cycles
        self.npmgcycles = 0

        # Multigrid pseudo-time steps
        dtau = cfg.getfloat(sect, 'pseudo-dt')
        self.dtauf = cfg.getfloat(mgsect, 'pseudo-dt-fact', 1.0)

        self._maxniters = cfg.getint(sect, 'pseudo-niters-max', 0)
        self._minniters = cfg.getint(sect, 'pseudo-niters-min', 0)

        # Get the multigrid pseudostepper and pseudocontroller classes
        pn = cfg.get(sect, 'pseudo-scheme')
        cn = cfg.get(sect, 'pseudo-controller')

        cc = subclass_where(BaseDualPseudoController,
                            pseudo_controller_name=cn)
        cc_none = subclass_where(BaseDualPseudoController,
                                 pseudo_controller_name='none')

        # Construct a pseudo-integrator for each level
        from pyfr.integrators.dual.pseudo import get_pseudo_stepper_cls

        self.pintgs = {}
        for l in self.levels:
            pc = get_pseudo_stepper_cls(pn, l)

            if l == order:
                bases = [cc, pc]
                mcfg = cfg
            else:
                bases = [cc_none, pc]

                mcfg = Inifile(cfg.tostr())
                mcfg.set('solver', 'order', l)
                mcfg.set(sect, 'pseudo-dt', dtau * self.dtauf**(order - l))

                for s in cfg.sections():
                    m = re.match(f'solver-(.*)-mg-p{l}$', s)
                    if m:
                        mcfg.rename_section(s, f'solver-{m.group(1)}')

            # A class that bypasses pseudo-controller methods within a cycle
            class lpsint(*bases):
                name = 'MultiPPseudoIntegrator' + str(l)
                aux_nregs = 2 if l != self._order else 0

                @property
                def _aux_regidx(iself):
                    if iself.aux_nregs != 0:
                        return iself._regidx[-2:]

                @property
                def ntotiters(iself):
                    return self.npmgcycles

                def convmon(iself, *args, **kwargs):
                    pass

                def finalise_pseudo_advance(iself, *args, **kwargs):
                    pass

                def _rhs_with_dts(iself, t, uin, fout):
                    # Compute -∇·f
                    iself.system.rhs(t, uin, fout)

                    # Coefficients for the physical stepper
                    svals = [sc / iself._dt for sc in iself._stepper_coeffs]

                    # Physical stepper source addition -∇·f - dQ/dt
                    axnpby = iself._get_axnpby_kerns(len(svals) + 1,
                                                     subdims=iself._subdims)
                    iself._prepare_reg_banks(fout, iself._idxcurr,
                                             *iself._stepper_regidx)
                    iself._queue.enqueue_and_run(axnpby, 1, *svals)

                    # Multigrid r addition
                    if iself._aux_regidx:
                        axnpby = iself._get_axnpby_kerns(2)
                        iself._prepare_reg_banks(fout, iself._aux_regidx[0])
                        iself._queue.enqueue_and_run(axnpby, 1, -1)

            self.pintgs[l] = lpsint(backend, systemcls, rallocs, mesh,
                                    initsoln, mcfg, tcoeffs, dt)

        # Get the highest p system from plugins
        self.system = self.pintgs[self._order].system

        # Get the convergence monitoring method
        self.mg_convmon = cc.convmon

        # Initialise the restriction and prolongation matrices
        self._init_proj_mats()

        # Delete remaining elements maps from multigrid systems
        for l in self.levels[1:]:
            del self.pintgs[l].system.ele_map
Exemplo n.º 32
0
def get_writer_by_name(name, *args, **kwargs):
    return subclass_where(BaseWriter, name=name)(*args, **kwargs)
Exemplo n.º 33
0
 def _get_shape(self, name, nspts):
     shapecls = subclass_where(BaseShape, name=name)
     return shapecls(nspts, self.cfg)
Exemplo n.º 34
0
def get_writer_by_name(name, *args, **kwargs):
    return subclass_where(BaseWriter, name=name)(*args, **kwargs)
Exemplo n.º 35
0
def get_plugin(name, *args, **kwargs):
    return subclass_where(BasePlugin, name=name)(*args, **kwargs)
Exemplo n.º 36
0
def _write_vtu_data(args, vtuf, cfg, mesh, m_inf, soln, s_inf):
    dtype = 'float32' if args.precision == 'single' else 'float64'

    # Get the shape and sub division classes
    shapecls = subclass_where(BaseShape, name=m_inf[0])
    subdvcls = subclass_where(BaseShapeSubDiv, name=m_inf[0])

    nspts, neles, ndims = m_inf[1]
    nvpts = shapecls.nspts_from_order(args.divisor + 1)

    # Generate basis objects for solution and vtu output
    soln_b = shapecls(nspts, cfg)
    vtu_b = shapecls(nvpts, cfg)

    # Generate operator matrices to move points and solutions to vtu nodes
    mesh_vtu_op = soln_b.sbasis.nodal_basis_at(vtu_b.spts)
    soln_vtu_op = soln_b.ubasis.nodal_basis_at(vtu_b.spts)

    # Calculate node locations of vtu elements
    pts = np.dot(mesh_vtu_op, mesh.reshape(nspts, -1))
    pts = pts.reshape(nvpts, -1, ndims)

    # Calculate solution at node locations of vtu elements
    sol = np.dot(soln_vtu_op, soln.reshape(s_inf[1][0], -1))
    sol = sol.reshape(nvpts, s_inf[1][1], -1)

    # Append dummy z dimension for points in 2-d (required by Paraview)
    if ndims == 2:
        pts = np.append(pts, np.zeros(pts.shape[:-1])[..., None], axis=2)

    # Write element node locations to file
    _write_vtk_darray(pts.swapaxes(0, 1), vtuf, dtype)

    # Perform the sub division
    cells = subdvcls.subcells(args.divisor)
    nodes = subdvcls.subnodes(args.divisor)

    # Prepare vtu cell arrays (connectivity, offsets, types):
    # Generate and extend vtu sub-cell node connectivity across all elements
    vtu_con = np.tile(nodes, (neles, 1))
    vtu_con += (np.arange(neles) * nvpts)[:, None]

    # Generate offset into the connectivity array for the end of each element
    vtu_off = np.tile(subdvcls.subcelloffs(args.divisor), (neles, 1))
    vtu_off += (np.arange(neles) * len(nodes))[:, None]

    # Tile vtu cell type numbers
    vtu_typ = np.tile(subdvcls.subcelltypes(args.divisor), neles)

    # Write vtu node connectivity, connectivity offsets and cell types
    _write_vtk_darray(vtu_con, vtuf, 'int32')
    _write_vtk_darray(vtu_off, vtuf, 'int32')
    _write_vtk_darray(vtu_typ, vtuf, 'uint8')

    # Convert rhou, rhov, [rhow] to u, v, [w] and energy to pressure
    _component_to_physical_soln(sol, cfg.getfloat('constants', 'gamma'))

    # Write Density, Velocity and Pressure
    _write_vtk_darray(sol[:, 0].T, vtuf, dtype)
    _write_vtk_darray(sol[:, 1:-1].transpose(2, 0, 1), vtuf, dtype)
    _write_vtk_darray(sol[:, -1].T, vtuf, dtype)
Exemplo n.º 37
0
Arquivo: polys.py Projeto: yifanb/PyFR
def get_polybasis(name, order, pts=[]):
    return subclass_where(BasePolyBasis, name=name)(order, pts)
Exemplo n.º 38
0
def get_backend(name, cfg):
    return subclass_where(BaseBackend, name=name.lower())(cfg)
Exemplo n.º 39
0
def get_solver(backend, rallocs, mesh, initsoln, cfg):
    systemcls = subclass_where(BaseSystem, name=cfg.get('solver', 'system'))

    # Combine with an integrator to yield the solver
    return get_integrator(backend, systemcls, rallocs, mesh, initsoln, cfg)
Exemplo n.º 40
0
    def __init__(self, backend, systemcls, rallocs, mesh, initsoln, cfg,
                 stp_nregs, stg_nregs, dt):
        self.backend = backend

        sect = 'solver-time-integrator'
        mgsect = 'solver-dual-time-integrator-multip'

        # Get the solver order and set the initial multigrid level
        self._order = self.level = order = cfg.getint('solver', 'order')

        # Get the multigrid cycle
        self.cycle, self.csteps = zip(*cfg.getliteral(mgsect, 'cycle'))
        self.levels = sorted(set(self.cycle), reverse=True)

        if max(self.cycle) > self._order:
            raise ValueError('The multigrid level orders cannot exceed '
                             'the solution order')

        if any(abs(i - j) > 1 for i, j in zip(self.cycle, self.cycle[1:])):
            raise ValueError('The orders of consecutive multigrid levels can '
                             'only change by one')

        if self.cycle[0] != self._order or self.cycle[-1] != self._order:
            raise ValueError('The multigrid cycle needs to start end with the '
                             'highest (solution) order ')

        # Initialise the number of cycles
        self.npmgcycles = 0

        # Multigrid pseudo-time steps
        dtau = cfg.getfloat(sect, 'pseudo-dt')
        self.dtauf = cfg.getfloat(mgsect, 'pseudo-dt-fact', 1.0)

        self._maxniters = cfg.getint(sect, 'pseudo-niters-max', 0)
        self._minniters = cfg.getint(sect, 'pseudo-niters-min', 0)

        # Get the multigrid pseudostepper and pseudocontroller classes
        pn = cfg.get(sect, 'pseudo-scheme')
        cn = cfg.get(sect, 'pseudo-controller')

        cc = subclass_where(BaseDualPseudoController,
                            pseudo_controller_name=cn)
        cc_none = subclass_where(BaseDualPseudoController,
                                 pseudo_controller_name='none')

        # Construct a pseudo-integrator for each level
        from pyfr.integrators.dual.pseudo import get_pseudo_stepper_cls

        self.pintgs = {}
        for l in self.levels:
            pc = get_pseudo_stepper_cls(pn, l)

            if l == order:
                bases = [cc, pc]
                mcfg = cfg
            else:
                bases = [cc_none, pc]

                mcfg = Inifile(cfg.tostr())
                mcfg.set('solver', 'order', l)
                mcfg.set(sect, 'pseudo-dt', dtau * self.dtauf**(order - l))

                for s in cfg.sections():
                    if (m := re.match(f'solver-(.*)-mg-p{l}$', s)):
                        mcfg.rename_section(s, f'solver-{m.group(1)}')

            # A class that bypasses pseudo-controller methods within a cycle
            class lpsint(*bases):
                name = 'MultiPPseudoIntegrator' + str(l)
                aux_nregs = 2 if l != self._order else 0
                stepper_nregs = stp_nregs if l == self._order else 0
                stage_nregs = stg_nregs if l == self._order else 0

                @property
                def _aux_regidx(iself):
                    if iself.aux_nregs != 0:
                        return iself._regidx[-2:]

                @property
                def ntotiters(iself):
                    return self.npmgcycles

                def convmon(iself, *args, **kwargs):
                    pass

                def _rhs_with_dts(iself, t, uin, fout, mg_add=True):
                    # Compute -∇·f
                    iself.system.rhs(t, uin, fout)

                    if iself.stage_nregs > 1:
                        iself._add(0, self._stage_regidx[iself.currstg], 1,
                                   fout)

                    # Registers
                    vals = iself.stepper_coeffs[:2] + [1]
                    regs = [fout, iself._idxcurr, iself._source_regidx]

                    # Physical stepper source addition -∇·f - dQ/dt
                    iself._addv(vals, regs, subdims=iself._subdims)

                    # Multigrid r addition
                    if mg_add and iself._aux_regidx:
                        iself._add(1, fout, -1, iself._aux_regidx[0])

            self.pintgs[l] = lpsint(backend, systemcls, rallocs, mesh,
                                    initsoln, mcfg, stp_nregs, stg_nregs, dt)
Exemplo n.º 41
0
def get_reader_by_name(name, *args, **kwargs):
    return subclass_where(BaseReader, name=name)(*args, **kwargs)
Exemplo n.º 42
0
def get_rank_allocation(mesh, cfg):
    name = cfg.get("backend", "rank-allocator", "linear")

    return subclass_where(BaseRankAllocator, name=name)(mesh, cfg)
Exemplo n.º 43
0
def get_polybasis(name, order, pts=[]):
    return subclass_where(BasePolyBasis, name=name)(order, pts)
Exemplo n.º 44
0
def get_partitioner(name, *args, **kwargs):
    return subclass_where(BasePartitioner, name=name)(*args, **kwargs)
Exemplo n.º 45
0
def get_reader_by_name(name, *args, **kwargs):
    return subclass_where(BaseReader, name=name)(*args, **kwargs)
Exemplo n.º 46
0
def _write_vtu_data(args, vtuf, cfg, mesh, m_inf, soln, s_inf):
    """ Writes mesh and solution data for appended (binary) data .vtu files

    :param args: pyfr-postp command line arguments from argparse
    :param vtuf: .vtu output file
    :param cfg: PyFR config file used in the respective simulation
    :param mesh: Single PyFR mesh array (corresponding to soln)
    :param m_inf: Tuple of element type and array shape of mesh
    :param soln: Single PyFR solution array (corresponding to mesh)
    :param s_inf: Tuple of element type and array shape of soln
    :type args: class 'argparse.Namespace'
    :type vtuf: file
    :type cfg: class 'pyfr.inifile.Inifile'
    :type mesh: numpy.ndarray
    :type m_inf: tuple
    :type soln: numpy.ndrayy
    :type s_inf: tuple

    """
    # Set numpy name for float; set size in bytes
    if args.precision == 'single':
        flt = ['float32', 4]
    else:
        flt = ['float64', 8]

    # Get the basis class
    basiscls = subclass_where(BaseBasis, name=m_inf[0])
    ndims = m_inf[1][2]

    # Set npts for divide/append cases
    if args.divisor is not None:
        npts = _npts_from_order(args.divisor, m_inf, total=False)
    else:
        npts = ParaviewWriter.vtk_to_pyfr[m_inf[0]][2]

    # Generate basis objects for solution and vtu output
    soln_b = basiscls(m_inf[1][0], cfg)
    vtu_b = basiscls(npts, cfg)

    # Generate operator matrices to move points and solutions to vtu nodes
    mesh_vtu_op = np.array(soln_b.sbasis_at(vtu_b.spts), dtype=float)
    soln_vtu_op = np.array(soln_b.ubasis_at(vtu_b.spts), dtype=float)

    # Calculate node locations of vtu elements
    pts = np.dot(mesh_vtu_op, mesh.reshape(m_inf[1][0],
                                           -1)).reshape(npts, -1, ndims)
    # Calculate solution at node locations of vtu elements
    sol = np.dot(soln_vtu_op, soln.reshape(s_inf[1][0],
                                           -1)).reshape(npts, s_inf[1][1], -1)

    # Append dummy z dimension for points in 2-d (required by Paraview)
    if ndims == 2:
        pts = np.append(pts, np.zeros(pts.shape[:-1])[...,None], axis=2)

    # Write element node locations to file
    _write_vtk_darray(pts.swapaxes(0,1), vtuf, flt[0])

    # Prepare vtu cell arrays (connectivity, offsets, types):
    # Generate and extend vtu sub-cell node connectivity across all elements
    vtu_con = np.tile(_base_con(m_inf[0], args.divisor),
                      (m_inf[1][1], 1))
    vtu_con += (np.arange(m_inf[1][1]) * npts)[:, None]

    # Generate offset into the connectivity array for the end of each element
    vtu_off = np.arange(_ncells_after_subdiv(m_inf, args.divisor)) + 1
    vtu_off *= ParaviewWriter.vtk_to_pyfr[m_inf[0]][2]

    # Tile vtu cell type numbers
    vtu_typ = np.tile(ParaviewWriter.vtk_to_pyfr[m_inf[0]][0],
                      _ncells_after_subdiv(m_inf, args.divisor))

    # Write vtu node connectivity, connectivity offsets and cell types
    _write_vtk_darray(vtu_con, vtuf, 'int32')
    _write_vtk_darray(vtu_off, vtuf, 'int32')
    _write_vtk_darray(vtu_typ, vtuf, 'uint8')

    # Convert rhou, rhov, [rhow] to u, v, [w] and energy to pressure
    _component_to_physical_soln(sol, cfg.getfloat('constants', 'gamma'))

    # Write Density, Velocity and Pressure
    _write_vtk_darray(sol[:,0].T, vtuf, flt[0])
    _write_vtk_darray(sol[:,1:-1].transpose(2, 0, 1), vtuf, flt[0])
    _write_vtk_darray(sol[:,-1].T, vtuf, flt[0])

    # Append high-order data as CellData if not dividing cells
    if args.divisor is None:
        # Calculate number of points written as low-order, and left to append
        nlpts = ParaviewWriter.vtk_to_pyfr[s_inf[0]][2]
        nhpts = s_inf[1][0] - nlpts

        # Generate basis objects for mesh, solution and vtu output
        mesh_b = basiscls(m_inf[1][0], cfg)

        # Get location of spts in standard element of solution order
        uord = cfg.getint('solver', 'order')
        ele_spts = get_std_ele_by_name(m_inf[0], uord)

        # Generate operator matrices to move points and solutions to vtu nodes
        mesh_hpts_op = np.array(mesh_b.sbasis_at(ele_spts), dtype=float)
        soln_hpts_op = np.array(mesh_b.ubasis_at(ele_spts), dtype=float)

        # Calculate node locations of vtu elements
        pts = np.dot(mesh_hpts_op, mesh.reshape(m_inf[1][0], -1))
        pts = pts.reshape((-1,) + m_inf[1][1:])

        # Append dummy z dimension to 2-d points (required by Paraview)
        if ndims == 2:
            pts = np.append(pts, np.zeros(pts.shape[:-1])[...,None], axis=2)

        # Calculate solution at node locations
        sol = np.dot(soln_hpts_op, soln.reshape(s_inf[1][0], -1))
        sol = sol.reshape((-1,) + s_inf[1][1:])

        # Convert rhou, rhov, [rhow] to u, v, [w] and energy to pressure
        _component_to_physical_soln(sol, cfg.getfloat('constants', 'gamma'))

        # Write data arrays, one set of high order points at a time
        for gmshpt in xrange(nhpts):
            # Convert Gmsh node number to equivalent in PyFR
            pt = GmshNodeMaps.to_pyfr[s_inf[0], s_inf[1][0]][gmshpt + nlpts]

            # Write node locations, density, velocity and pressure
            _write_vtk_darray(pts[pt], vtuf, flt[0])
            _write_vtk_darray(sol[pt,0], vtuf, flt[0])
            _write_vtk_darray(sol[pt,1:-1].T, vtuf, flt[0])
            _write_vtk_darray(sol[pt,-1], vtuf, flt[0])