예제 #1
0
    def _update_plots(self):
        """
        Update plots requested in input (reporting/reports_to_show)
        """
        if self.simulation.rank != 0:
            return  # Do not plot on non root processes

        for report_name in self.figures:
            if not report_name in self.timestep_xy_reports:
                ocellaris_error(
                    'Unknown report name: "%s"' % report_name,
                    'Cannot plot this report, it does not exist',
                )

            abscissa = self.timesteps
            ordinate = self.timestep_xy_reports[report_name]

            if len(abscissa) != len(ordinate):
                ocellaris_error(
                    'Malformed report data: "%s"' % report_name,
                    'Length of t is %d while report is %d' %
                    (len(abscissa), len(ordinate)),
                )

            fig, ax, line = self.figures[report_name]
            line.set_xdata(abscissa)
            line.set_ydata(ordinate)
            ax.relim()
            ax.autoscale_view()
            fig.canvas.draw()
            fig.canvas.flush_events()
예제 #2
0
파일: hric.py 프로젝트: jakobes/Ocellaris
    def update(self, dt, velocity):
        """
        Update the values of the blending function beta at the facets
        according to the HRIC algorithm. Several versions of HRIC
        are implemented
        """
        degree_b = self.blending_function.ufl_element().degree()
        degree_u = velocity[0].ufl_element().degree()
        assert degree_b == 0, (
            'Only facetwise constant blending factors are supported! Got order %d'
            % degree_b)
        assert degree_u == 0, (
            'VelocityDGT0Projector must be enabled! Got order %d' % degree_u)

        # Check that the input is supported by the C++ code
        degree_a = self.alpha_function.ufl_element().degree()
        if degree_a != 0:
            ocellaris_error(
                'HRIC scalar field order must be 0',
                'HRIC implementation does not support order %d fields' %
                degree_a,
            )

        with dolfin.Timer('Ocellaris update HRIC'):
            if self.use_cpp:
                Co_max = self.update_cpp(dt, velocity)
            else:
                Co_max = self.update_python(dt, velocity)

        Co_max = dolfin.MPI.max(self.mesh.mpi_comm(), Co_max)
        self.simulation.reporting.report_timestep_value('Cof_max', Co_max)
예제 #3
0
 def get_variable(self, name):
     if not name == self.var_name:
         ocellaris_error(
             'Sharp field does not define %r' % name,
             'This sharp field defines %r' % self.var_name,
         )
     return self.func
예제 #4
0
def morph_mesh(simulation, columns, fs_vert_velocity):
    """
    Move the mesh. Each column is given a velocity in the
    vertical direction. All vertices in this column is moved
    according to the
    """
    assert len(columns) == len(fs_vert_velocity)
    dt = simulation.dt
    u_mesh = simulation.data['u_mesh1']

    for col, vel in zip(columns, fs_vert_velocity):
        y_fs = col.free_surface_pos
        for _vid, coords, dof in col.vertices:
            y_vtx = coords[1]
            if y_vtx > y_fs:
                fac = (col.top - y_vtx) / (col.top - y_fs)
            else:
                fac = (y_vtx - col.bottom) / (y_fs - col.bottom)
            u_mesh.vector()[dof] = vel * fac
        col.free_surface_pos = y_fs + vel * dt

        if col.free_surface_pos >= col.top:
            ocellaris_error(
                'HeightFunctionALE morphing error',
                'Free surface is above top of column in column %r' % col,
            )

    simulation.mesh_morpher.morph_mesh()
예제 #5
0
    def report(self, create_report=True):
        """
        Compute and report the solution properties
        """
        if not self.active:
            return

        sim = self.simulation
        reports = []

        Co_max = self.courant_number().vector().max()
        Pe_max = self.peclet_number().vector().max()
        div_dS_f, div_dx_f = self.divergences()
        div_dS = div_dS_f.vector().max()
        div_dx = div_dx_f.vector().max()
        mass = self.total_mass()
        Ek, Ep = self.total_energy()
        reports.append(('Co', Co_max))
        reports.append(('Pe', Pe_max))
        reports.append(('div', div_dx + div_dS))
        reports.append(('mass', mass))
        reports.append(('Ek', Ek))
        reports.append(('Ep', Ep))

        if self.has_div_conv:
            # Convecting and convected velocities are separate
            div_conv_dS_f, div_conv_dx_f = self.divergences('u_conv')
            div_conv_dS = div_conv_dS_f.vector().max()
            div_conv_dx = div_conv_dx_f.vector().max()
            reports.append(('div_conv', div_conv_dx + div_conv_dS))

            # Difference between the convective and the convected velocity
            ucdiff = velocity_change(u1=sim.data['up'],
                                     u2=sim.data['up_conv'],
                                     ui_tmp=sim.data['ui_tmp'])
            reports.append(('uconv_diff', ucdiff))

        if create_report:
            # Add computed solution properties to the timestep reports
            for name, value in reports:
                sim.reporting.report_timestep_value(name, value)
        else:
            # Log solution properties instead of adding to the timestep reports.
            # Done to avoid variable length time step report time series which
            # will be generated when calling this method at a different time
            # than at the end of a time step
            info = ['%s = %10g' % (name, value) for name, value in reports]
            sim.log.info(
                'Solution properties for timestep = %5d, time = %10.4f, %s' %
                (sim.timestep, sim.time, ', '.join(info)))

        Co_lim = sim.input.get_value('simulation/Co_lim', CO_LIM, 'float')
        if Co_lim > 0 and Co_max > Co_lim:
            ocellaris_error('Courant number exceeded limit',
                            'Found Co = %g > %g' % (Co_max, Co_lim))
        elif not numpy.isfinite(Co_max):
            ocellaris_error('Non finite Courant number',
                            'Found Co = %g' % Co_max)
예제 #6
0
def taylor_to_lagrange(t, u):
    """
    Convert a DG Taylor function space function into a Lagrange
    function space function. The results are stored in u which
    should be a function space with an appropriate number of dofs
    per cell (u in DG2 if t in DG2 etc)
    """
    V = u.function_space()
    mesh = V.mesh()
    degree = V.ufl_element().degree()
    ndim = mesh.geometry().dim()

    if 'mesh_hash' not in CACHE or CACHE['mesh_hash'] != mesh.hash():
        CACHE.clear()
        CACHE['mesh'] = mesh
        CACHE['mesh_hash'] = mesh.hash()

    # Get cached conversion matrices
    key = ('taylor_to_lagrange_matrices', degree)
    if key not in CACHE:
        if degree == 1 and ndim == 2:
            CACHE[key] = taylor_to_DG1_matrix_2D(V)
        elif degree == 1 and ndim == 3:
            CACHE[key] = taylor_to_DG1_matrix_3D(V)
        elif degree == 2 and ndim == 2:
            CACHE[key] = taylor_to_DG2_matrix_2D(V)
        elif degree == 2 and ndim == 3:
            CACHE[key] = taylor_to_DG2_matrix_3D(V)
        else:
            ocellaris_error(
                'DG Taylor to DG Lagrange converter error',
                'Polynomial degree %d not supported' % degree,
            )
    taylor_to_lagrange_matrices = CACHE[key]
    Ncells = taylor_to_lagrange_matrices.shape[0]

    # Get cached cell dofs
    key2 = ('cell_dofs', degree)
    if key2 not in CACHE:
        dm = V.dofmap()
        cell_dofs = [dm.cell_dofs(i) for i in range(Ncells)]
        CACHE[key2] = numpy.array(cell_dofs, int)
    cell_dofs = CACHE[key2]

    # Apply the conversion matrices for all cells by use of the stacked dot
    # behaviour of matmul (slightly faster than einsum 'ijk,ik->ij')
    all_vals_taylor = t.vector().get_local()
    taylor_vectors = all_vals_taylor.take(cell_dofs)
    res = numpy.matmul(
        taylor_to_lagrange_matrices, taylor_vectors[:, :, None]
    ).squeeze()

    # Put the results into the right indices in the Taylor function's vector
    all_vals_lagrange = numpy.zeros_like(all_vals_taylor)
    all_vals_lagrange[cell_dofs] = res
    u.vector().set_local(all_vals_lagrange)
    u.vector().apply('insert')
예제 #7
0
 def get_variable(self, name):
     if not name == self.var_name:
         ocellaris_error(
             'Scalar field does not define %r' % name,
             'This scalar field defines %r' % self.var_name,
         )
     if self.func is None:
         expr = self._get_expression()
         func = dolfin.Function(self.V)
         func.interpolate(expr)
         self.func = func
     return self.func
예제 #8
0
    def _interp(self, name, expr=None, func=None):
        """
        Interpolate the expression into the given function
        """
        sim = self.simulation

        # Determine the function space
        V = self.V
        quad_degree = None
        if name == 'c' and self.colour_projection_degree >= 0:
            # Perform projection for c instead of interpolation to better
            # capture the discontinuous nature of the colour field
            if 'Vc' not in sim.data:
                ocellaris_error(
                    'Error in wave field %r input' % self.name,
                    'Cannot specify colour_to_dg_degree when c is '
                    'not used in the multiphase_solver.',
                )
            V = sim.data['Vc']
            quad_degree = self.colour_projection_degree

        # Get the expression
        if expr is None:
            expr = self._get_expression(name, quad_degree)

        # Get the function
        if func is None:
            if name not in self._functions:
                self._functions[name] = dolfin.Function(V)
            func = self._functions[name]

        if quad_degree is not None:
            if self.colour_projection_form is None:
                # Ensure that we can use the DG0 trick of dividing by the mass
                # matrix diagonal to get the projected value
                if V.ufl_element().degree() != 0:
                    ocellaris_error(
                        'Error in wave field %r input' % self.name,
                        'The colour_to_dg_degree projection is '
                        'currently only implemented when c is DG0',
                    )
                v = dolfin.TestFunction(V)
                dx = dolfin.dx(metadata={'quadrature_degree': quad_degree})
                d = dolfin.CellVolume(V.mesh())  # mass matrix diagonal
                form = expr * v / d * dx
                self.colour_projection_form = dolfin.Form(form)

            # Perform projection by assembly (DG0 only!)
            dolfin.assemble(self.colour_projection_form, tensor=func.vector())
        else:
            # Perform standard interpolation
            func.interpolate(expr)
예제 #9
0
def get_probe(name):
    """
    Return a postprocessing probe by name
    """
    try:
        return _PROBES[name]
    except KeyError:
        ocellaris_error(
            'Postprocessing probe "%s" not found' % name,
            'Available probe:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_PROBES.items())),
        )
        raise
예제 #10
0
 def get_variable(self, name):
     if not name == self.var_name:
         ocellaris_error(
             'Vector field does not define %r' % name,
             'This vector field defines %r' % self.var_name,
         )
     if self.funcs is None:
         funcs = []
         for e in self._get_expressions():
             func = dolfin.Function(self.V)
             func.interpolate(e)
             funcs.append(func)
         self.funcs = dolfin.as_vector(funcs)
     return self.funcs
예제 #11
0
def get_convection_scheme(name):
    """
    Return a convection scheme by name
    """
    try:
        return _CONVECTION_SCHEMES[name]
    except KeyError:
        ocellaris_error(
            'Convection scheme "%s" not found' % name,
            'Available convection schemes:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_CONVECTION_SCHEMES.items())),
        )
        raise
예제 #12
0
def get_multi_phase_model(name):
    """
    Return a multi phase model by name
    """
    try:
        return _MULTI_PHASE_MODELS[name]
    except KeyError:
        ocellaris_error(
            'Multi phase model "%s" not found' % name,
            'Available models:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_MULTI_PHASE_MODELS.items())),
        )
        raise
예제 #13
0
    def get_variable(self, name):
        if not name == self.var_name:
            ocellaris_error(
                'Scalar field does not define %r' % name,
                'This scalar field defines %r' % self.var_name,
            )

        if self.func is not None:
            return self.func

        if self.colour_projection_degree >= 0:
            quad_degree = self.colour_projection_degree
            degree = None
        else:
            quad_degree = None
            degree = self.polydeg

        expr = OcellarisCppExpression(
            self.simulation,
            self.cpp_code,
            'Scalar field %r' % self.name,
            degree=degree,
            update=False,
            quad_degree=quad_degree,
        )
        self.func = dolfin.Function(self.V)

        if quad_degree is not None:

            # Ensure that we can use the DG0 trick of dividing by the mass
            # matrix diagonal to get the projected value
            if self.V.ufl_element().degree() != 0:
                ocellaris_error(
                    'Error in wave field %r input' % self.name,
                    'The colour_to_dg_degree projection is '
                    'currently only implemented when c is DG0',
                )
            v = dolfin.TestFunction(self.V)
            dx = dolfin.dx(metadata={'quadrature_degree': quad_degree})
            d = dolfin.CellVolume(self.V.mesh())  # mass matrix diagonal
            form = expr * v / d * dx
            compiled_form = dolfin.Form(form)

            # Perform projection by assembly (DG0 only!)
            dolfin.assemble(compiled_form, tensor=self.func.vector())
        else:
            # Perform standard interpolation
            self.func.interpolate(expr)

        return self.func
예제 #14
0
        def check_isinstance(value, classes):
            """
            Give error if the input data is not of the required type
            """
            value = eval_python_expression(self.simulation, value, pathstr,
                                           safe_mode)

            if not isinstance(value, classes):
                ocellaris_error(
                    'Malformed data on input file',
                    'Parameter %s should be of type %s,\nfound %r %r' %
                    (pathstr, required_type, value, type(value)),
                )
            return value
예제 #15
0
def get_slope_limiter(name):
    """
    Return a slope limiter by name
    """
    try:
        return _SLOPE_LIMITERS[name]
    except KeyError:
        ocellaris_error(
            'Slope limiter "%s" not found' % name,
            'Available slope limiters:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_SLOPE_LIMITERS.items())),
        )
        raise
예제 #16
0
def get_known_field(name):
    """
    Return a known field by name
    """
    try:
        return _KNOWN_FIELDS[name]
    except KeyError:
        ocellaris_error(
            'Field type "%s" not found' % name,
            'Available field types:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_KNOWN_FIELDS.items())),
        )
        raise
예제 #17
0
def get_solver(name):
    """
    Return a Navier-Stokes solver by name
    """
    try:
        return _SOLVERS[name]
    except KeyError:
        ocellaris_error(
            'Navier-Stokes solver "%s" not found' % name,
            'Available solvers:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_SOLVERS.items())),
        )
        raise
예제 #18
0
def get_boundary_condition(name):
    """
    Return a boundary condition by name
    """
    try:
        return _BOUNDARY_CONDITIONS[name]
    except KeyError:
        ocellaris_error(
            'Boundary condition "%s" not found' % name,
            'Available boundary conditions:\n' +
            '\n'.join('  %-20s - %s' % (n, s.description)
                      for n, s in sorted(_BOUNDARY_CONDITIONS.items())),
        )
        raise
예제 #19
0
    def read_input(self, field_inp):
        sim = self.simulation
        self.wave_model = field_inp.get_value('wave_model', 'Fenton', 'string')
        self.air_model = field_inp.get_value('air_model', 'FentonAir',
                                             'string')
        self.order = field_inp.get_value('model_order', 5, 'int')

        # Get global physical constants
        g = abs(sim.data['g'].values()[-1])
        if g == 0:
            ocellaris_error('Waves require gravity',
                            'The vertical component of gravity is 0')
        h = field_inp.get_value('depth', required_type='float')
        if h <= 0:
            ocellaris_error('Waves require a still water depth',
                            'The still water depth is %r' % h)
        self.wave_length = field_inp.get_value('wave_length',
                                               required_type='float')
        self.wave_height = field_inp.get_value('wave_height',
                                               required_type='float')
        self.stationary = self.wave_height == 0
        self.ramp_time = field_inp.get_value('ramp_time',
                                             0,
                                             required_type='float')

        self.still_water_pos = field_inp.get_value('still_water_position',
                                                   required_type='float')
        self.current_speed = field_inp.get_value('current_speed',
                                                 0,
                                                 required_type='float')
        self.wind_speed = field_inp.get_value('wind_speed',
                                              0,
                                              required_type='float')
        self.polydeg = field_inp.get_value('polynomial_degree',
                                           DEFAULT_POLYDEG,
                                           required_type='int')
        self.g = g
        self.h = h
        h_above = 3 * self.wave_height
        self.h_above = field_inp.get_value('depth_above',
                                           h_above,
                                           required_type='float')
        self.blending_height = field_inp.get_value('blending_height', None,
                                                   'float')

        # Project the colour function to DG0 (set degree to -1 to prevent this)
        self.colour_projection_degree = field_inp.get_value(
            'colour_projection_degree', COLOUR_PROJECTION_DEGREE, 'int')
        self.colour_projection_form = None
예제 #20
0
    def read_input(self):
        """
        Read the simulation input
        """
        sim = self.simulation

        # Solver for the coupled system
        default_lu_solver = LU_SOLVER_1CPU if sim.ncpu == 1 else LU_SOLVER_NCPU
        self.coupled_solver = linear_solver_from_input(
            sim, 'solver/coupled', 'lu', None, default_lu_solver, LU_PARAMETERS
        )

        # Give warning if using iterative solver
        if isinstance(self.coupled_solver, dolfin.PETScKrylovSolver):
            sim.log.warning(
                'WARNING: Using a Krylov solver for the coupled NS equations is not a good idea'
            )
        else:
            # Removed in DOLFIN 2018.1
            # self.coupled_solver.set_parameter('same_nonzero_pattern', True)
            pass

        # Deal with pressure null space
        self.fix_pressure_dof = sim.input.get_value(
            'solver/fix_pressure_dof', FIX_PRESSURE_DOF, 'bool'
        )
        # No need for any tricks if the pressure is set via Dirichlet conditions somewhere
        if self.simulation.data['dirichlet_bcs'].get('p', []):
            self.fix_pressure_dof = False

        # Representation of velocity
        Vu_family = sim.data['Vu'].ufl_element().family()
        Vp_family = sim.data['Vp'].ufl_element().family()
        if not Vu_family == Vp_family == 'Discontinuous Lagrange':
            ocellaris_error(
                'Must use DG function spaces',
                'LDG solver requires DG spaces for velocity and pressure',
            )

        # Local DG velocity postprocessing
        self.velocity_postprocessing_method = sim.input.get_value(
            'solver/velocity_postprocessing', BDM, 'string'
        )

        # 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
예제 #21
0
파일: setup.py 프로젝트: jakobes/Ocellaris
def setup_fenics(simulation):
    """
    Setup FEniCS parameters like linear algebra backend
    """
    # Test for PETSc linear algebra backend
    if not dolfin.has_linear_algebra_backend("PETSc"):
        ocellaris_error(
            'Missing PETSc',
            'DOLFIN has not been configured with PETSc ' 'which is needed by Ocellaris.',
        )
    dolfin.parameters['linear_algebra_backend'] = 'PETSc'

    # Form compiler "uflacs" needed for isoparametric elements
    form_compiler = simulation.input.get_value('solver/form_compiler', 'auto', 'string')
    dolfin.parameters['form_compiler']['representation'] = form_compiler
예제 #22
0
        def check_list(d, valtype):
            """
            Check list and eval any python expressions in the values
            """
            d = check_isinstance(d, list)
            d_new = []
            for val in d:
                d_new.append(check_isinstance(val, valtype))

            if required_length is not None and len(d_new) != required_length:
                ocellaris_error(
                    'Malformed data on input file',
                    'Parameter %s should be length %r found %r' %
                    (pathstr, required_length, len(d_new)),
                )
            return d_new
예제 #23
0
def calc_wave_number(g, h, omega, relax=0.5, eps=1e-15):
    """
    Relaxed Picard iterations to find k when omega is known
    """
    k0 = omega ** 2 / g
    for _ in range(100):
        k1 = omega ** 2 / g / tanh(k0 * h)
        if abs(k1 - k0) < eps:
            break
        k0 = k1 * relax + k0 * (1 - relax)
    else:
        ocellaris_error(
            'calc_wave_number did not converge',
            'Input g=%r h=%r omega=%r, tolerance=%e' % (g, h, omega, eps),
        )
    return k1
예제 #24
0
def eval_python_expression(simulation, value, pathstr, safe_mode=False):
    """
    We run eval with the math functions and user constants available on string
    values that are prefixed with "py$" indicating that they are dynamic
    expressions and not just static strings
    """
    if not isinstance(value, str) or not value.startswith('py$'):
        return value

    if safe_mode:
        ocellaris_error(
            'Cannot have Python expression here',
            'Not allowed to have Python expression here:  %s' % pathstr,
        )

    # remove "py$" prefix
    expr = value[3:]

    # Build dictionary of locals for evaluating the expression
    eval_locals = {}

    import math

    for name in dir(math):
        if not name.startswith('_'):
            eval_locals[name] = getattr(math, name)

    global_inp = simulation.input
    user_constants = global_inp.get_value('user_code/constants', {},
                                          'dict(string:basic)',
                                          safe_mode=True)
    for name, const_value in user_constants.items():
        eval_locals[name] = const_value

    eval_locals['simulation'] = simulation
    eval_locals['t'] = eval_locals['time'] = simulation.time
    eval_locals['it'] = eval_locals['timestep'] = simulation.timestep
    eval_locals['dt'] = simulation.dt
    eval_locals['ndim'] = simulation.ndim

    try:
        value = eval(expr, globals(), eval_locals)
    except Exception:
        simulation.log.error('Cannot evaluate python code for %s' % pathstr)
        simulation.log.error('Python code is %s' % expr)
        raise
    return value
예제 #25
0
파일: setup.py 프로젝트: jakobes/Ocellaris
def setup_known_fields(simulation):
    """
    Setup known fields like incoming waves etc
    """
    simulation.log.info('Creating known fields')
    Nfields = len(simulation.input.get_value('fields', [], 'list(dict)'))
    for i in range(Nfields):
        field_inp = simulation.input.get_value('fields/%d' % i, required_type='Input')
        name = field_inp.get_value('name', required_type='string')
        field_type = field_inp.get_value('type', required_type='string')
        if name in simulation.fields:
            ocellaris_error(
                'Field %s is defined multiple times' % name,
                'Input file contains multiple fields with the same name',
            )
        field_class = get_known_field(field_type)
        simulation.fields[name] = field_class(simulation, field_inp)
예제 #26
0
 def read_input(self, field_inp):
     self.name = field_inp.get_value('name', required_type='string')
     self.var_name = field_inp.get_value('variable_name',
                                         'phi',
                                         required_type='string')
     self.stationary = field_inp.get_value('stationary',
                                           False,
                                           required_type='bool')
     self.polydeg = field_inp.get_value('polynomial_degree',
                                        DEFAULT_POLYDEG,
                                        required_type='int')
     self.cpp_code = field_inp.get_value('cpp_code',
                                         required_type='list(string)')
     if len(self.cpp_code) != self.simulation.ndim:
         ocellaris_error(
             'Wrong number of dimensions in cpp code for field %r' %
             self.name,
             'Simulation has %d dimensions, cpp_code length is %d' %
             (self.simulation.ndim, len(self.cpp_code)),
         )
예제 #27
0
    def get_input_file_path(self, file_name):
        """
        Serch first relative to the current working dir and then
        relative to the input file dir
        """
        # Check if the path is absolute or relative to the
        # working directory
        if os.path.exists(file_name):
            return file_name
        self.simulation.log.debug('File does not exist: %s' % file_name)

        # Check if the path is relative to the input file dir
        inp_file_dir = os.path.dirname(self.file_name)
        pth2 = os.path.join(inp_file_dir, file_name)
        if os.path.exists(pth2):
            return pth2
        self.simulation.log.debug('File does not exist: %s' % pth2)

        ocellaris_error('File not found',
                        'The specified file "%s" was not found' % file_name)
예제 #28
0
    def read_metadata(self, h5_file_name, function_details=False):
        """
        Read HDF5 restart file metadata
        """
        # Check file format and read metadata
        with h5py.File(h5_file_name, 'r') as hdf:
            if not 'ocellaris' in hdf:
                ocellaris_error(
                    'Error reading restart file',
                    'Restart file %r does not contain Ocellaris meta data' %
                    h5_file_name,
                )

            meta = hdf['ocellaris']
            restart_file_version = meta.attrs['restart_file_format']
            if restart_file_version != 2:
                ocellaris_error(
                    'Error reading restart file',
                    'Restart file version is %d, this version of Ocellaris only '
                    % restart_file_version + 'supports version 2',
                )

            t = float(meta.attrs['time'])
            it = int(meta.attrs['iteration'])
            dt = float(meta.attrs['dt'])
            inpdata = meta['input_file'].value
            funcnames = list(meta['function_names'])

            # Read function signatures
            if function_details:
                signatures = {}
                for fname in funcnames:
                    signatures[fname] = hdf[fname].attrs['signature']

        if function_details:
            return funcnames, signatures
        else:
            return t, it, dt, inpdata, funcnames
예제 #29
0
    def create_periodic_boundary_conditions(self):
        """
        Create periodic boundary conditions for this region

        This is separated from the normal boundary conditions
        because Dirichlet boundary conditions depend on having
        function spaces created, while the function spaces themselves
        are dependent on the definition of periodic boundaries.
        """
        sim = self.simulation
        if 'map_code' in self.input:
            sim.log.info('Applying periodic boundary conditions on %s' %
                         self.name)

            if self.simulation.data['constrained_domain'] is not None:
                ocellaris_error(
                    'Error in specification of periodic boundary conditions',
                    'There can only be one periodic boundary region in the domain. '
                    'Found more than one periodic region when processing boundary conditions',
                )

            self.selector.set_map_code(self.input['map_code'], self.name)
            self.simulation.data['constrained_domain'] = self.selector
    def __init__(self, simulation, vel_u, vel_name, vel_w=None, use_cpp=True):
        """
        Use a standard slope limiter on each component of the velocity field
        """
        self.simulation = simulation
        self.vel_name = vel_name
        inp = simulation.input.get_value('slope_limiter/%s' % vel_name, {}, 'Input')
        comp_method = inp.get_value('comp_method', required_type='string')

        self.vel_u = vel_u
        self.vel_w = vel_w
        self.limit_conv = inp.get_value('limit_conv', 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

        # Create slope limiters
        dim, = vel_u.ufl_shape
        self.limiters = create_component_limiters(
            simulation, vel_name, vel_u, comp_method
        )

        # Check that we can limit only certain cells
        if self.limit_selected_cells_only:
            for lim in self.limiters:
                if not hasattr(lim, 'limit_cell'):
                    ocellaris_error(
                        'Cannot limit only selected cells for %s' % vel_name,
                        'Limiter %r does not support limiting only selected cells'
                        % type(lim).__name__,
                    )

        simulation.hooks.add_pre_simulation_hook(
            self.setup, 'ComponentwiseSlopeLimiterVelocity - setup'
        )