示例#1
0
    def update(self):
        if not self.active:
            return

        with Timer('Ocellaris update hydrostatic pressure'):
            A = self.tensor_lhs
            b = assemble(self.form_rhs)

            if self.null_space is None:
                # Create vector that spans the null space, and normalize
                null_space_vector = b.copy()
                null_space_vector[:] = sqrt(1.0 / null_space_vector.size())

                # Create null space basis object and attach to PETSc matrix
                self.null_space = VectorSpaceBasis([null_space_vector])
                as_backend_type(A).set_nullspace(self.null_space)

            self.null_space.orthogonalize(b)
            self.solver.solve(A, self.func.vector(), b)

        if not self.every_timestep:
            # Give initial values for p, but do not continuously compute p_hydrostatic
            sim = self.simulation
            p = sim.data['p']
            if p.vector().max() == p.vector().min() == 0.0:
                sim.log.info(
                    'Initial pressure field is identically zero, initializing to hydrostatic'
                )
                p.interpolate(self.func)

            # Disable further hydrostatic pressure calculations
            self.func.vector().zero()
            del sim.data['p_hydrostatic']
            del self.func
            self.active = False
示例#2
0
    def build_pressure_null_space(self):
        # Prepare function used to correct pressure values
        null_fcn = Function(self.subspace("p"))
        null_fcn.vector()[:] = 1.0

        # Create vector that spans the null space and normalize
        null_vec = Vector(null_fcn.vector())
        null_vec *= 1.0 / null_vec.norm("l2")
        # FIXME: Check what are relevant norms for different Krylov methods

        # Create null space basis object
        null_space = VectorSpaceBasis([null_vec])

        return (null_space, null_fcn)
示例#3
0
    def build_pressure_null_space(self):
        # Prepare function used to correct pressure values
        W_ns = self.function_spaces()[1]
        # NOTE: The following works only for nodal elements
        # null_fcn = Function(W_ns)
        # W_ns.sub(1).dofmap().set(null_fcn.vector(), 1.0)
        null_fcn = self._get_constant_pressure(W_ns)

        # Create vector that spans the null space and normalize
        null_vec = Vector(null_fcn.vector())
        null_vec *= 1.0 / null_vec.norm("l2")
        # FIXME: Check what are relevant norms for different Krylov methods

        # Create null space basis object
        null_space = VectorSpaceBasis([null_vec])

        return (null_space, null_fcn)
示例#4
0
class HydrostaticPressure:
    def __init__(self, simulation, every_timestep):
        """
        Calculate the hydrostatic pressure
        """
        self.simulation = simulation
        self.active = True
        self.every_timestep = every_timestep
        rho = simulation.data['rho']
        g = simulation.data['g']
        ph = simulation.data['p_hydrostatic']

        # Define the weak form
        Vp = ph.function_space()
        p = TrialFunction(Vp)
        q = TestFunction(Vp)
        a = dot(grad(p), grad(q)) * dx
        L = rho * dot(g, grad(q)) * dx

        self.func = ph
        self.tensor_lhs = assemble(a)
        self.form_rhs = Form(L)
        self.null_space = None
        self.solver = linear_solver_from_input(
            simulation,
            'solver/p_hydrostatic',
            default_parameters=DEFAULT_SOLVER_CONFIGURATION,
        )

    def update(self):
        if not self.active:
            return

        with Timer('Ocellaris update hydrostatic pressure'):
            A = self.tensor_lhs
            b = assemble(self.form_rhs)

            if self.null_space is None:
                # Create vector that spans the null space, and normalize
                null_space_vector = b.copy()
                null_space_vector[:] = sqrt(1.0 / null_space_vector.size())

                # Create null space basis object and attach to PETSc matrix
                self.null_space = VectorSpaceBasis([null_space_vector])
                as_backend_type(A).set_nullspace(self.null_space)

            self.null_space.orthogonalize(b)
            self.solver.solve(A, self.func.vector(), b)

        if not self.every_timestep:
            # Give initial values for p, but do not continuously compute p_hydrostatic
            sim = self.simulation
            p = sim.data['p']
            if p.vector().max() == p.vector().min() == 0.0:
                sim.log.info(
                    'Initial pressure field is identically zero, initializing to hydrostatic'
                )
                p.interpolate(self.func)

            # Disable further hydrostatic pressure calculations
            self.func.vector().zero()
            del sim.data['p_hydrostatic']
            del self.func
            self.active = False