示例#1
0
 def add_custom_hook(self, hook_point, hook, description):
     """
     Add other type of hook, must give a string name for
     the hook name
     """
     verify_key('custom hook point', hook_point, self._custom_hooks)
     self._custom_hooks[hook_point].append((hook, description))
示例#2
0
    def read_input(self, field_inp):
        self.name = field_inp.get_value('name', required_type='string')
        field_name0 = field_inp.get_value('field0', required_type='string')
        field_name1 = field_inp.get_value('field1', required_type='string')
        blend_def = field_inp.get_value('blending_function',
                                        required_type='string')

        verify_key(
            'blending field0',
            field_name0,
            self.simulation.fields,
            'BlendedField %s' % self.name,
        )
        verify_key(
            'blending field1',
            field_name1,
            self.simulation.fields,
            'BlendedField %s' % self.name,
        )
        blend = verify_field_variable_definition(self.simulation, blend_def,
                                                 'BlendedField %s' % self.name)

        self.field0 = self.simulation.fields[field_name0]
        self.field1 = self.simulation.fields[field_name1]
        self.blending_function = blend
示例#3
0
    def read_input(self):
        """
        Read the simulation input
        """
        sim = self.simulation

        # Create linear solvers
        self.velocity_solver = linear_solver_from_input(
            self.simulation, 'solver/u', default_parameters=SOLVER_U_OPTIONS)
        self.pressure_solver = linear_solver_from_input(
            self.simulation, 'solver/p', default_parameters=SOLVER_P_OPTIONS)

        # Lagrange multiplicator or remove null space via PETSc
        self.remove_null_space = True
        self.pressure_null_space = None
        self.use_lagrange_multiplicator = sim.input.get_value(
            'solver/use_lagrange_multiplicator', USE_LAGRANGE_MULTIPLICATOR,
            'bool')
        if self.use_lagrange_multiplicator:
            self.remove_null_space = False

        # No need for special treatment if the pressure is coupled via outlet BCs
        if sim.data['outlet_bcs']:
            self.remove_null_space = False
            self.use_lagrange_multiplicator = False

        # Control the form of the governing equations
        self.use_stress_divergence_form = sim.input.get_value(
            'solver/use_stress_divergence_form', USE_STRESS_DIVERGENCE, 'bool')
        self.use_grad_p_form = sim.input.get_value('solver/use_grad_p_form',
                                                   USE_GRAD_P_FORM, 'bool')
        self.use_grad_q_form = sim.input.get_value('solver/use_grad_q_form',
                                                   USE_GRAD_Q_FORM, 'bool')
        self.incompressibility_flux_type = sim.input.get_value(
            'solver/incompressibility_flux_type', INCOMPRESSIBILITY_FLUX_TYPE,
            'string')
        assert sim.data['Vu'].ufl_element().family(
        ) == 'Discontinuous Lagrange'

        # Velocity post_processing
        self.velocity_postprocessing = sim.input.get_value(
            'solver/velocity_postprocessing', BDM, 'string')
        verify_key('velocity post processing', self.velocity_postprocessing,
                   ('none', BDM), 'SIMPLE solver')

        # Quasi-steady simulation input
        self.steady_velocity_eps = sim.input.get_value(
            'solver/steady_velocity_stopping_criterion', None, 'float')
        self.is_steady = self.steady_velocity_eps is not None

        # How to approximate A_tilde
        self.num_elements_in_block = sim.input.get_value(
            'solver/num_elements_in_A_tilde_block', NUM_ELEMENTS_IN_BLOCK,
            'int')
        self.lump_diagonal = sim.input.get_value(
            'solver/lump_A_tilde_diagonal', LUMP_DIAGONAL, 'bool')
        self.mass_only_A_tilde = sim.input.get_value(
            'solver/A_tilde_is_mass_only', MASS_ONLY_A_TILDE, 'bool')
示例#4
0
    def read_input(self, field_inp):
        self.name = field_inp.get_value('name', required_type='string')
        field_name0 = field_inp.get_value('field0', required_type='string')
        field_name1 = field_inp.get_value('field1', required_type='string')

        verify_key('field0', field_name0, self.simulation.fields,
                   'MinField %s' % self.name)
        verify_key('field1', field_name1, self.simulation.fields,
                   'MinField %s' % self.name)
        self.field0 = self.simulation.fields[field_name0]
        self.field1 = self.simulation.fields[field_name1]
 def setup(self):
     """
     Deferred setup tasks that are run after the Navier-Stokes solver has finished its setup
     """
     if self.probe_name is not None:
         verify_key(
             'surface_probe',
             self.probe_name,
             self.simulation.probes,
             'componentwise slope limiter for %s' % self.vel_name,
         )
         self.surface_probe = self.simulation.probes[self.probe_name]
         self.simulation.log.info(
             'Marking cells for limiting based on probe "%s" for %s' %
             (self.surface_probe.name, self.vel_name))
示例#6
0
 def _get_expression(self, name, quad_degree=None):
     keys = list(self._cpp.keys()) + ['u']
     verify_key('variable', name, keys, 'Raschii wave field %r' % self.name)
     if name not in self._expressions:
         degree = self.polydeg if quad_degree is None else None
         expr, updater = OcellarisCppExpression(
             self.simulation,
             self._cpp[name],
             'Raschii wave field %r' % name,
             degree,
             update=False,
             return_updater=True,
             quad_degree=quad_degree,
         )
         self._expressions[name] = expr, updater
     return self._expressions[name][0]
示例#7
0
    def run_custom_hook(self, hook_point, *args, **kwargs):
        """
        Called by the solver at a custom point

        Will run all custom hooks in the reverse order they have
        been added
        """
        verify_key('custom hook point', hook_point, self._custom_hooks)
        with dolfin.Timer('Ocellaris custom hook %s' % hook_point):
            for hook, description in self._custom_hooks[hook_point][::-1]:
                try:
                    hook(*args, **kwargs)
                except Exception:
                    self.simulation.log.error('Got exception in hook: %s' % description)
                    self.simulation.log.error(traceback.format_exc())
                    raise

        # Run any delayed actions
        self._process_call_after()
示例#8
0
    def _get_expression(self, name):
        keys = list(self._cpp.keys()) + ['u', 'uvert']
        verify_key('variable', name, keys, 'Wave outflow field %r' % self.name)

        params = dict(u_above=self.const_speed_above,
                      u_below=self.const_speed_below)

        if name not in self._expressions:
            expr, updater = OcellarisCppExpression(
                self.simulation,
                self._cpp[name],
                'Wave outflow field %r' % name,
                self.polydeg,
                update=False,
                return_updater=True,
                params=params,
            )
            self._expressions[name] = expr, updater
        return self._expressions[name][0]
    def setup(self):
        """
        Deferred setup tasks that are run after the Navier-Stokes solver has finished its setup
        """
        if self.probe_name is not None:
            verify_key(
                'surface_probe',
                self.probe_name,
                self.simulation.probes,
                'solenoidal slope limiter for %s' % self.vel_name,
            )
            self.surface_probe = self.simulation.probes[self.probe_name]
            self.simulation.log.info(
                'Marking cells for limiting based on probe "%s" for %s' %
                (self.surface_probe.name, self.vel_name))

        if self.limit_none:
            self.simulation.log.info('Marking no cells for limiting of %s' %
                                     self.vel_name)
            self.limit_cell[:] = False
            self.surface_probe = None
            self.limit_selected_cells_only = False
示例#10
0
def add_forcing_zone(simulation, fzones, inp):
    """
    Add a penalty forcing zone to the simulation
    """
    name = inp.get_value('name', required_type='string')
    ztype = inp.get_value('type', required_type='string')
    penalty = inp.get_value('penalty', required_type='float')
    zone_vardef = inp.get_value('zone', required_type='string')
    target_vardef = inp.get_value('target', required_type='string')
    plot = inp.get_value('plot', False, required_type='bool')

    zone = verify_field_variable_definition(
        simulation, zone_vardef, 'forcing zone %r zone definition' % name)
    target = verify_field_variable_definition(simulation, target_vardef,
                                              'forcing zone %r target' % name)

    verify_key(
        'forcing zone type',
        ztype,
        ('MomentumForcing', 'ScalarForcing'),
        'penalty forcing zone %s' % name,
    )
    if ztype == 'MomentumForcing':
        varname = inp.get_value('variable', 'u', required_type='string')
    else:
        varname = inp.get_value('variable', required_type='string')

    fzones.setdefault(varname,
                      []).append(ForcingZone(name, zone, target, penalty))

    if plot:
        # Save zone blending function to a plot file for easy verification
        prefix = simulation.input.get_value('output/prefix', '', 'string')
        pfile = prefix + '_blending_zone_%s.pvd' % name
        zone.rename('beta', 'beta')
        dolfin.File(pfile) << zone
示例#11
0
def load_mesh(simulation):
    """
    Get the mesh from the simulation input

    Returns the facet regions contained in the mesh data
    or None if these do not exist
    """
    inp = simulation.input
    mesh_type = inp.get_value('mesh/type', required_type='string')
    mesh_facet_regions = None

    # For testing COMM_SELF may be specified
    comm_type = inp.get_value('mesh/mpi_comm', 'WORLD', required_type='string')
    verify_key('mesh/mpi_comm', comm_type, ('SELF', 'WORLD'))
    if comm_type == 'WORLD':
        comm = dolfin.MPI.comm_world
    else:
        comm = dolfin.MPI.comm_self

    if mesh_type == 'Rectangle':
        simulation.log.info('Creating rectangular mesh')

        startx = inp.get_value('mesh/startx', 0, 'float')
        starty = inp.get_value('mesh/starty', 0, 'float')
        start = dolfin.Point(startx, starty)
        endx = inp.get_value('mesh/endx', 1, 'float')
        endy = inp.get_value('mesh/endy', 1, 'float')
        end = dolfin.Point(endx, endy)
        Nx = inp.get_value('mesh/Nx', required_type='int')
        Ny = inp.get_value('mesh/Ny', required_type='int')
        diagonal = inp.get_value('mesh/diagonal',
                                 'right',
                                 required_type='string')

        mesh = dolfin.RectangleMesh(comm, start, end, Nx, Ny, diagonal)

    elif mesh_type == 'Box':
        simulation.log.info('Creating box mesh')

        startx = inp.get_value('mesh/startx', 0, 'float')
        starty = inp.get_value('mesh/starty', 0, 'float')
        startz = inp.get_value('mesh/startz', 0, 'float')
        start = dolfin.Point(startx, starty, startz)
        endx = inp.get_value('mesh/endx', 1, 'float')
        endy = inp.get_value('mesh/endy', 1, 'float')
        endz = inp.get_value('mesh/endz', 1, 'float')
        end = dolfin.Point(endx, endy, endz)
        Nx = inp.get_value('mesh/Nx', required_type='int')
        Ny = inp.get_value('mesh/Ny', required_type='int')
        Nz = inp.get_value('mesh/Nz', required_type='int')

        mesh = dolfin.BoxMesh(comm, start, end, Nx, Ny, Nz)

    elif mesh_type == 'UnitDisc':
        simulation.log.info('Creating circular mesh')

        N = inp.get_value('mesh/N', required_type='int')
        degree = inp.get_value('mesh/degree', 1, required_type='int')
        gdim = inp.get_value('mesh/gdim', 2, required_type='int')

        mesh = dolfin.UnitDiscMesh(comm, N, degree, gdim)

        if degree > 1 and dolfin.parameters['form_compiler'][
                'representation'] != 'uflacs':
            simulation.log.warning(
                'Using isoparametric elements without uflacs!')

    elif mesh_type == 'XML':
        simulation.log.info('Creating mesh from XML file')
        simulation.log.warning('(deprecated, please use meshio reader)')

        mesh_file = inp.get_value('mesh/mesh_file', required_type='string')
        facet_region_file = inp.get_value('mesh/facet_region_file',
                                          None,
                                          required_type='string')

        # Load the mesh from file
        pth = inp.get_input_file_path(mesh_file)
        mesh = dolfin.Mesh(comm, pth)

        # Load the facet regions if available
        if facet_region_file is not None:
            pth = inp.get_input_file_path(facet_region_file)
            mesh_facet_regions = dolfin.MeshFunction('size_t', mesh, pth)
        else:
            mesh_facet_regions = None

    elif mesh_type == 'XDMF':
        simulation.log.info('Creating mesh from XDMF file')
        simulation.log.warning('(deprecated, please use meshio reader)')

        mesh_file = inp.get_value('mesh/mesh_file', required_type='string')

        # Load the mesh from file
        pth = inp.get_input_file_path(mesh_file)
        mesh = dolfin.Mesh(comm)
        with dolfin.XDMFFile(comm, pth) as xdmf:
            xdmf.read(mesh, False)

    elif mesh_type == 'HDF5':
        simulation.log.info('Creating mesh from DOLFIN HDF5 file')
        h5_file_name = inp.get_value('mesh/mesh_file', required_type='string')

        with dolfin.HDF5File(comm, h5_file_name, 'r') as h5:
            # Read mesh
            mesh = dolfin.Mesh(comm)
            h5.read(mesh, '/mesh', False)

            # Read facet regions
            if h5.has_dataset('/mesh_facet_regions'):
                mesh_facet_regions = dolfin.FacetFunction('size_t', mesh)
                h5.read(mesh_facet_regions, '/mesh_facet_regions')
            else:
                mesh_facet_regions = None

    elif mesh_type == 'meshio':
        simulation.log.info('Creating mesh with meshio reader')
        file_name = inp.get_value('mesh/mesh_file', required_type='string')
        file_type = inp.get_value('mesh/meshio_type',
                                  None,
                                  required_type='string')
        sort_order = inp.get_value('mesh/sort_order',
                                   None,
                                   required_type='list(int)')

        if sort_order:
            simulation.log.info('    Ordering mesh elements by ' +
                                ', then '.join('xyz'[i] for i in sort_order))

        # Read mesh on rank 0
        t1 = time.time()
        mesh = dolfin.Mesh(comm)
        if comm.rank == 0:
            # Read a mesh file by use of meshio
            physical_regions = load_meshio_mesh(mesh, file_name, file_type,
                                                sort_order)
            simulation.log.info('    Read mesh with %d cells in %.2f seconds' %
                                (mesh.num_cells(), time.time() - t1))
        else:
            physical_regions = None

        # Distribute the mesh
        if comm.size > 1:
            physical_regions = comm.bcast(physical_regions)
            t1 = time.time()
            simulation.log.info('    Distributing mesh to %d processors' %
                                comm.size)
            build_distributed_mesh(mesh)
            simulation.log.info('    Distributed mesh in %.2f seconds' %
                                (time.time() - t1))
    else:
        ocellaris_error('Unknown mesh type',
                        'Mesh type %r is not supported' % mesh_type)

    # Optionally move the mesh (for simple grading etc)
    move = inp.get_value('mesh/move', None, required_type='list(string)')
    if move is not None:
        simulation.log.info('    Moving mesh')
        if len(move) != mesh.geometry().dim():
            ocellaris_error(
                'Mesh move not correct',
                'Length of move field is %d while geometric dimension is %r' %
                (len(move), mesh.geometry().dim()),
            )
        e_move = dolfin.Expression(move, degree=1)
        V_move = dolfin.VectorFunctionSpace(mesh, 'CG', 1)
        f_move = dolfin.interpolate(e_move, V_move)
        dolfin.ALE.move(mesh, f_move)
        mesh.bounding_box_tree().build(mesh)

    # Update the simulation
    simulation.set_mesh(mesh, mesh_facet_regions)

    # Load meshio facet regions
    if mesh_type == 'meshio' and physical_regions:
        mfr = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
        conn_FV = simulation.data['connectivity_FV']
        vcoords = mesh.coordinates()
        for ifacet in range(mfr.size()):
            facet_vertices = conn_FV(ifacet)
            key = sorted([tuple(vcoords[vidx]) for vidx in facet_vertices])
            number = physical_regions.get(tuple(key), 0)
            mfr[ifacet] = number
        # Store the loaded regions
        simulation.data['mesh_facet_regions'] = mfr
        mesh_facet_regions = mfr

    # Optionally plot mesh right after loading (for debugging)
    if simulation.input.get_value('output/plot_mesh', False, 'bool'):
        prefix = simulation.input.get_value('output/prefix', '', 'string')
        pfile = prefix + '_mesh.xdmf'
        simulation.log.info(
            '    Plotting mesh with current MPI ranks to XDMF file %r' % pfile)
        V0 = dolfin.FunctionSpace(mesh, 'DG', 0)
        ranks = dolfin.Function(V0)
        ranks.vector().set_local(ranks.vector().get_local() * 0 + comm.rank)
        ranks.vector().apply('insert')
        ranks.rename('MPI_rank', 'MPI_rank')
        with dolfin.XDMFFile(comm, pfile) as xdmf:
            xdmf.write(ranks)

    # Optionally plot facet regions to file
    if simulation.input.get_value('output/plot_facet_regions', False, 'bool'):
        prefix = simulation.input.get_value('output/prefix', '', 'string')
        pfile = prefix + '_input_facet_regions.xdmf'
        simulation.log.info(
            '    Plotting input mesh facet regions to XDMF file %r' % pfile)
        if mesh_facet_regions is None:
            simulation.log.warning(
                'Cannot plot mesh facet regions, no regions found!')
        else:
            with dolfin.XDMFFile(comm, pfile) as xdmf:
                xdmf.write(mesh_facet_regions)
    def __init__(self, simulation, vel_u, vel_name, vel_w, use_cpp=True):
        """
        Use a solenoidal polynomial slope limiter on the convecting velocity field
        w and and use a prelimiter to limit the convected velocity u and set the
        target for the convecting velocity w
        """
        from solenoidal import SolenoidalLimiter, COST_FUNCTIONS

        inp = simulation.input.get_value('slope_limiter/%s' % vel_name,
                                         required_type='Input')
        self.additional_plot_funcs = []

        # Verify input
        V = vel_u[0].function_space()
        mesh = V.mesh()
        family = V.ufl_element().family()
        degree = V.ufl_element().degree()
        dim, = vel_u.ufl_shape
        cost_func = simulation.input.get_value('slope_limiter/cost_function',
                                               DEFAULT_LIMITER_W, 'string')
        loc = 'SolenoidalSlopeLimiterVelocity'
        verify_key('slope limited function', family,
                   ['Discontinuous Lagrange'], loc)
        verify_key('slope limited degree', degree, (2, ), loc)
        verify_key('function dim', dim, (2, ), loc)
        verify_key('topological dimension', mesh.topology().dim(), [2], loc)
        verify_key('cost function', cost_func, COST_FUNCTIONS, loc)

        # We expect the convecting velocity as vel2 and the convected as vel
        assert vel_w is not None

        # Limit all cells regardless of location?
        self.limit_none = inp.get_value('limit_no_cells', False, 'bool')

        # Get the IsoSurface probe used to locate the free surface
        self.probe_name = inp.get_value('surface_probe', None, 'string')
        self.surface_probe = None
        self.limit_selected_cells_only = self.probe_name is not None

        # Use prelimiter to set (possibly) extended valid bounds and to avoid excessive
        # limiting of the convecting velocity w. The prelimiter is also used for slope
        # limiting the convected velocity u. This is not treated with the solenoidal limiter
        # since we cannot guarantee that all Gibbs oscillations are removed
        prelimiter_method = inp.get_value('prelimiter', DEFAULT_LIMITER_U,
                                          'string')
        simulation.log.info(
            '        Using prelimiter %r for %s and for solenoidal targets' %
            (prelimiter_method, vel_name))
        self.prelimiters = create_component_limiters(simulation, vel_name,
                                                     vel_u, prelimiter_method)

        # Cost function options
        cf_options = {}
        cf_option_keys = ('out_of_bounds_penalty_fac',
                          'out_of_bounds_penalty_const')
        for key in cf_option_keys:
            if key in inp:
                cf_options[key] = inp.get_value(key, required_type='float')

        # Maximum allowed cost for solenoidal limiting of w
        max_cost = inp.get_value('max_cost', 1e100, 'float')

        # Maximum allowed cost for solenoidal limiting of u
        # Normally this is zero and u in only prelimited which
        # is typically done by a stable Componentwise limter
        max_cost_u = inp.get_value('max_cost_u', 0.0, 'float')

        # Store input
        self.simulation = simulation
        self.vel_u = vel_u
        self.vel_w = vel_w
        self.vel_name = vel_name
        self.degree = degree
        self.mesh = mesh
        self.use_cpp = use_cpp
        self.cf_options = cf_options
        self.max_cost = max_cost
        self.max_cost_u = max_cost_u

        # Create slope limiter
        self.sollim = SolenoidalLimiter(V,
                                        cost_function=cost_func,
                                        use_cpp=use_cpp,
                                        cf_options=cf_options)
        self.limit_cell = self.sollim.limit_cell

        # Create plot output functions
        V0 = dolfin.FunctionSpace(self.mesh, 'DG', 0)

        # Final cost from minimizer per cell
        self.cell_cost = dolfin.Function(V0)
        cname = 'SolenoidalCostFunc_%s' % self.vel_name
        self.cell_cost.rename(cname, cname)
        self.additional_plot_funcs.append(self.cell_cost)

        self.active_cells = None
        if self.limit_selected_cells_only:
            self.active_cells = dolfin.Function(V0)
            aname = 'SolenoidalActiveCells_%s' % self.vel_name
            self.active_cells.rename(aname, aname)
            self.additional_plot_funcs.append(self.active_cells)

        # Cell dofs
        tdim = self.mesh.topology().dim()
        Ncells = self.mesh.topology().ghost_offset(tdim)
        dm0 = V0.dofmap()
        self.cell_dofs_V0 = numpy.array(
            [int(dm0.cell_dofs(i)) for i in range(Ncells)], int)

        # Boundary cells where we do not fully trust the prelimiter targets (we trust BCs more)
        self.skip_target_cells = mark_cell_layers(simulation, V, layers=0)

        simulation.hooks.add_pre_simulation_hook(
            self.setup, 'SolenoidalSlopeLimiterVelocity - setup')
示例#13
0
    def read_input(self):
        """
        Read the simulation input
        """
        sim = self.simulation

        # Representation of velocity
        Vu_family = sim.data['Vu'].ufl_element().family()
        self.vel_is_discontinuous = Vu_family == 'Discontinuous Lagrange'

        # Create linear solvers
        self.velocity_solver = linear_solver_from_input(
            self.simulation, 'solver/u', default_parameters=SOLVER_U_OPTIONS)
        self.pressure_solver = linear_solver_from_input(
            self.simulation, 'solver/p', default_parameters=SOLVER_P_OPTIONS)

        # Velocity update can be performed with local solver for DG velocities
        self.use_local_solver_for_update = sim.input.get_value(
            'solver/u_upd_local', self.vel_is_discontinuous, 'bool')
        if self.use_local_solver_for_update:
            self.u_upd_solver = None  # Will be set when LHS is ready
        else:
            self.u_upd_solver = linear_solver_from_input(
                self.simulation,
                'solver/u_upd',
                default_parameters=SOLVER_U_OPTIONS)

        # Get the class to be used for the equation system assembly
        self.equation_subtype = sim.input.get_value('solver/equation_subtype',
                                                    EQUATION_SUBTYPE, 'string')
        verify_key('equation sub-type', self.equation_subtype,
                   EQUATION_SUBTYPES, 'ipcs solver')

        # Lagrange multiplicator or remove null space via PETSc
        self.remove_null_space = True
        self.pressure_null_space = None
        self.use_lagrange_multiplicator = sim.input.get_value(
            'solver/use_lagrange_multiplicator', USE_LAGRANGE_MULTIPLICATOR,
            'bool')
        has_dirichlet = self.simulation.data['dirichlet_bcs'].get(
            'p', []) or sim.data['outlet_bcs']
        if self.use_lagrange_multiplicator or has_dirichlet:
            self.remove_null_space = False

        # No need for special treatment if the pressure is set via Dirichlet conditions somewhere
        if has_dirichlet:
            self.use_lagrange_multiplicator = False
            self.remove_null_space = False

        # Control the form of the governing equations
        self.use_stress_divergence_form = sim.input.get_value(
            'solver/use_stress_divergence_form', USE_STRESS_DIVERGENCE, 'bool')
        self.use_grad_p_form = sim.input.get_value('solver/use_grad_p_form',
                                                   USE_GRAD_P_FORM, 'bool')
        self.incompressibility_flux_type = sim.input.get_value(
            'solver/incompressibility_flux_type', INCOMPRESSIBILITY_FLUX_TYPE,
            'string')

        # Velocity post_processing
        default_postprocessing = BDM if self.vel_is_discontinuous else None
        self.velocity_postprocessing = sim.input.get_value(
            'solver/velocity_postprocessing', default_postprocessing, 'string')
        verify_key('velocity post processing', self.velocity_postprocessing,
                   (None, BDM), 'ipcs solver')

        # Quasi-steady simulation input
        self.steady_velocity_eps = sim.input.get_value(
            'solver/steady_velocity_stopping_criterion', None, 'float')
        self.is_steady = self.steady_velocity_eps is not None
示例#14
0
    def __init__(self, simulation, phi_name, phi, skip_cells,
                 boundary_conditions, limiter_input):
        """
        Limit the slope of the given scalar to obtain boundedness
        """
        # Verify input
        V = phi.function_space()
        mesh = V.mesh()
        family = V.ufl_element().family()
        degree = V.ufl_element().degree()
        tdim = mesh.topology().dim()
        gdim = mesh.geometry().dim()
        loc = 'HierarchalTaylor slope limiter'
        verify_key('slope limited function', family,
                   ['Discontinuous Lagrange'], loc)
        verify_key('slope limited degree', degree, (0, 1, 2), loc)
        verify_key('function shape', phi.ufl_shape, [()], loc)
        verify_key('topological dimension', mesh.topology().dim(), [2, 3], loc)
        assert gdim == tdim, (
            'HierarchalTaylor slope limiter requires that '
            'topological and geometrical dimensions are identical')

        # Read input
        use_cpp = limiter_input.get_value('use_cpp', True, 'bool')
        enforce_bounds = limiter_input.get_value('enforce_bounds', False,
                                                 'bool')
        enforce_bcs = limiter_input.get_value('enforce_bcs', True, 'bool')
        use_weak_bcs = limiter_input.get_value('use_weak_bcs', True, 'bool')
        trust_robin_dval = limiter_input.get_value('trust_robin_dval', True,
                                                   'bool')
        simulation.log.info('        Enforce global bounds: %r' %
                            enforce_bounds)
        simulation.log.info('        Enforcing BCs: %r' % enforce_bcs)
        simulation.log.info('        Using weak BCs: %r' % use_weak_bcs)

        # Store input
        self.phi_name = phi_name
        self.phi = phi
        self.degree = degree
        self.mesh = mesh
        self.boundary_conditions = boundary_conditions
        self.use_cpp = use_cpp
        self.enforce_global_bounds = enforce_bounds
        self.enforce_boundary_conditions = enforce_bcs
        self.use_weak_bcs = use_weak_bcs
        self.num_cells_owned = mesh.topology().ghost_offset(tdim)
        self.ndim = gdim

        # No limiter needed for piecewice constant functions
        if self.degree == 0:
            self.additional_plot_funcs = []
            return

        # Alpha factors are secondary outputs
        V0 = df.FunctionSpace(self.mesh, 'DG', 0)
        self.alpha_funcs = []
        for i in range(degree):
            func = df.Function(V0)
            name = 'SlopeLimiterAlpha%d_%s' % (i + 1, phi_name)
            func.rename(name, name)
            self.alpha_funcs.append(func)
        self.additional_plot_funcs = self.alpha_funcs

        # Intermediate DG Taylor function space
        self.taylor = df.Function(V)
        self.taylor_old = df.Function(V)

        # Remove given cells from limiter
        self.limit_cell = numpy.ones(self.num_cells_owned, numpy.intc)
        if skip_cells is not None:
            for cid in skip_cells:
                self.limit_cell[cid] = 0

        self.input = SlopeLimiterInput(mesh,
                                       V,
                                       V0,
                                       use_cpp=use_cpp,
                                       trust_robin_dval=trust_robin_dval)
        if use_cpp:
            self.cpp_mod = self.input.get_cpp_mod()
示例#15
0
    def read_input(self):
        """
        Read the simulation input
        """
        sim = self.simulation

        # PISO mode switch
        self.solver_type = sim.input.get_value('solver/type',
                                               required_type='string')

        # Create linear solvers
        self.velocity_solver = linear_solver_from_input(
            self.simulation, 'solver/u', default_parameters=SOLVER_U_OPTIONS)
        self.pressure_solver = linear_solver_from_input(
            self.simulation, 'solver/p', default_parameters=SOLVER_P_OPTIONS)

        # Get the class to be used for the equation system assembly
        self.equation_subtype = sim.input.get_value('solver/equation_subtype',
                                                    EQUATION_SUBTYPE, 'string')
        verify_key(
            'equation sub-type',
            self.equation_subtype,
            EQUATION_SUBTYPES,
            'SIMPLE solver',
        )

        # Lagrange multiplicator or remove null space via PETSc
        self.remove_null_space = True
        self.pressure_null_space = None
        self.use_lagrange_multiplicator = sim.input.get_value(
            'solver/use_lagrange_multiplicator', USE_LAGRANGE_MULTIPLICATOR,
            'bool')
        if self.use_lagrange_multiplicator:
            self.remove_null_space = False

        # No need for special treatment if the pressure is set via Dirichlet conditions somewhere
        # No need for any tricks if the pressure is set via Dirichlet conditions somewhere
        if sim.data['dirichlet_bcs'].get('p', []) or sim.data['outlet_bcs']:
            self.remove_null_space = False
            self.use_lagrange_multiplicator = False

        # Control the form of the governing equations
        self.use_stress_divergence_form = sim.input.get_value(
            'solver/use_stress_divergence_form', USE_STRESS_DIVERGENCE, 'bool')
        self.use_grad_p_form = sim.input.get_value('solver/use_grad_p_form',
                                                   USE_GRAD_P_FORM, 'bool')
        self.use_grad_q_form = sim.input.get_value('solver/use_grad_q_form',
                                                   USE_GRAD_Q_FORM, 'bool')
        self.incompressibility_flux_type = sim.input.get_value(
            'solver/incompressibility_flux_type', INCOMPRESSIBILITY_FLUX_TYPE,
            'string')

        # Representation of velocity
        Vu_family = sim.data['Vu'].ufl_element().family()
        self.vel_is_discontinuous = Vu_family == 'Discontinuous Lagrange'

        # Velocity post_processing
        default_postprocessing = BDM if self.vel_is_discontinuous else None
        self.velocity_postprocessing = sim.input.get_value(
            'solver/velocity_postprocessing', default_postprocessing, 'string')
        self.project_rhs = sim.input.get_value('solver/project_rhs',
                                               PROJECT_RHS, 'bool')
        verify_key(
            'velocity post processing',
            self.velocity_postprocessing,
            ('none', BDM),
            'SIMPLE solver',
        )

        # Quasi-steady simulation input
        self.steady_velocity_eps = sim.input.get_value(
            'solver/steady_velocity_stopping_criterion', None, 'float')
        self.is_steady = self.steady_velocity_eps is not None

        # How to approximate A_tilde
        self.num_elements_in_block = sim.input.get_value(
            'solver/num_elements_in_A_tilde_block', NUM_ELEMENTS_IN_BLOCK,
            'int')
        self.lump_diagonal = sim.input.get_value(
            'solver/lump_A_tilde_diagonal', LUMP_DIAGONAL, 'bool')
示例#16
0
    def read_input(self):
        """
        Read the simulation input
        """
        sim = self.simulation

        # Create linear solvers
        self.velocity_solver = linear_solver_from_input(
            self.simulation, 'solver/u', default_parameters=SOLVER_U_OPTIONS)
        self.pressure_solver = linear_solver_from_input(
            self.simulation, 'solver/p', default_parameters=SOLVER_P_OPTIONS)

        # Lagrange multiplicator or remove null space via PETSc
        self.remove_null_space = True
        self.pressure_null_space = None
        self.use_lagrange_multiplicator = sim.input.get_value(
            'solver/use_lagrange_multiplicator', USE_LAGRANGE_MULTIPLICATOR,
            'bool')
        if self.use_lagrange_multiplicator:
            self.remove_null_space = False

        # No need for special treatment if the pressure is coupled via outlet BCs
        if sim.data['outlet_bcs']:
            self.remove_null_space = False
            self.use_lagrange_multiplicator = False

        # Control the form of the governing equations
        self.use_stress_divergence_form = sim.input.get_value(
            'solver/use_stress_divergence_form', USE_STRESS_DIVERGENCE, 'bool')
        self.use_grad_p_form = sim.input.get_value('solver/use_grad_p_form',
                                                   USE_GRAD_P_FORM, 'bool')
        self.use_grad_q_form = sim.input.get_value('solver/use_grad_q_form',
                                                   USE_GRAD_Q_FORM, 'bool')
        self.incompressibility_flux_type = sim.input.get_value(
            'solver/incompressibility_flux_type', INCOMPRESSIBILITY_FLUX_TYPE,
            'string')

        # Representation of velocity
        Vu_family = sim.data['Vu'].ufl_element().family()
        self.vel_is_discontinuous = Vu_family == 'Discontinuous Lagrange'

        # Velocity post_processing
        default_postprocessing = BDM if self.vel_is_discontinuous else 'none'
        self.velocity_postprocessing = sim.input.get_value(
            'solver/velocity_postprocessing', default_postprocessing, 'string')
        verify_key('velocity post processing', self.velocity_postprocessing,
                   ('none', BDM), 'IPCS-A solver')

        # What types of mass matrices to produce
        self.project_initial_velocity = sim.input.get_value(
            'solver/project_initial_velocity', False, 'bool')
        self.splitting_approximation = sim.input.get_value(
            'solver/splitting_approximation', SPLIT_APPROX_DEFAULT, 'string')
        verify_key(
            'solver/mass_approximation',
            self.splitting_approximation,
            (
                SPLIT_APPROX_MASS_WITH_RHO,
                SPLIT_APPROX_MASS_UNSCALED,
                SPLIT_APPROX_MASS_MIN_RHO,
                SPLIT_APPROX_BLOCK_DIAG_MA,
            ),
            'IPCS-A solver',
        )
        self.make_unscaled_M = (self.project_initial_velocity
                                or self.splitting_approximation
                                == SPLIT_APPROX_MASS_UNSCALED)

        # Quasi-steady simulation input
        self.steady_velocity_eps = sim.input.get_value(
            'solver/steady_velocity_stopping_criterion', None, 'float')
        self.is_steady = self.steady_velocity_eps is not None