Esempio n. 1
0
    def lhs(self):
        l = self.residual.label_map(
            lambda t: t.has_label(time_derivative),
            map_if_true=replace_subject(self.dq, self.idx),
            map_if_false=drop)

        return l.form
Esempio n. 2
0
    def rhs(self):
        r = self.residual.label_map(
            all_terms,
            map_if_true=replace_subject(self.q1, self.idx))
        r = r.label_map(lambda t: t.has_label(time_derivative),
                        map_if_false=lambda t: -(1-self.theta)*self.dt*t)

        return r.form
Esempio n. 3
0
    def lhs(self):
        l = self.residual.label_map(
            all_terms,
            map_if_true=replace_subject(self.dq, self.idx))
        l = l.label_map(lambda t: t.has_label(time_derivative),
                        map_if_false=lambda t: self.theta*self.dt*t)

        return l.form
Esempio n. 4
0
    def hydrostatic_projection(self, t):

        # TODO: make this more general, i.e. should work on the sphere
        assert not self.state.on_sphere, "the hydrostatic projection is not yet implemented for spherical geometry"
        k = Constant((*self.state.k, 0, 0))
        X = t.get(subject)

        new_subj = X - k * inner(X, k)
        return replace_subject(new_subj)(t)
Esempio n. 5
0
    def generate_linear_terms(self, residual, terms_to_linearise):
        """
        Generates linear forms for each of the terms in the equation set
        (unless specified otherwise). The linear forms are then added to the
        terms through a `linearisation` :class:`Label`.

        Linear forms are currently generated by replacing the `subject` with its
        corresponding `TrialFunction`, however the intention in the future is to
        use the `ufl.derivative` to obtain the linear forms.

        Terms that already have a `linearisation` label will be left.

        :arg residual:           The residual of the equation set. A
                                 :class:`LabelledForm` containing all the terms
                                 of the equation set.
        :arg terms_to_linearise: A dictionary describing the terms which should
                                 be linearised.
        """

        # TODO: Neaten up the `terms_to_linearise` variable. This should not be
        # a dictionary, it should be a filter of some sort

        # Loop through prognostic variables and linearise any specified terms
        for field in self.field_names:
            residual = residual.label_map(
                # Extract all terms to be linearised for this field's equation that haven't already been
                lambda t: (not t.has_label(linearisation) and
                           (t.get(prognostic) == field) and any(
                               t.has_label(*terms_to_linearise[field],
                                           return_tuple=True))),
                lambda t: linearisation(
                    t,
                    LabelledForm(t).label_map(
                        all_terms, replace_subject(self.trials)).terms[0]))

        return residual
Esempio n. 6
0
    def __init__(self, equation, alpha):

        self.field_name = equation.field_name
        implicit_terms = ["incompressibility", "sponge"]
        dt = equation.state.dt

        W = equation.function_space
        self.x0 = Function(W)
        self.xF = Function(W)

        # set up boundary conditions on the u subspace of W
        bcs = [
            DirichletBC(W.sub(0), bc.function_arg, bc.sub_domain)
            for bc in equation.bcs['u']
        ]

        # drop terms relating to transport and diffusion
        residual = equation.residual.label_map(
            lambda t: any(t.has_label(transport, diffusion, return_tuple=True)
                          ), drop)

        # the lhs of both of the explicit and implicit solvers is just
        # the time derivative form
        trials = TrialFunctions(W)
        a = residual.label_map(lambda t: t.has_label(time_derivative),
                               replace_subject(trials),
                               map_if_false=drop)

        # the explicit forms are multiplied by (1-alpha) and moved to the rhs
        L_explicit = -(1 - alpha) * dt * residual.label_map(
            lambda t: t.has_label(time_derivative) or t.get(name) in
            implicit_terms or t.get(name) == "hydrostatic_form", drop,
            replace_subject(self.x0))

        # the implicit forms are multiplied by alpha and moved to the rhs
        L_implicit = -alpha * dt * residual.label_map(
            lambda t: t.has_label(time_derivative) or t.get(name) in
            implicit_terms or t.get(name) == "hydrostatic_form", drop,
            replace_subject(self.x0))

        # now add the terms that are always fully implicit
        if any(t.get(name) in implicit_terms for t in residual):
            L_implicit -= dt * residual.label_map(
                lambda t: t.get(name) in implicit_terms,
                replace_subject(self.x0), drop)

        # the hydrostatic equations require some additional forms:
        if any([t.has_label(hydrostatic) for t in residual]):

            L_explicit += residual.label_map(
                lambda t: t.get(name) == "hydrostatic_form",
                replace_subject(self.x0), drop)

            L_implicit -= residual.label_map(
                lambda t: t.get(name) == "hydrostatic_form",
                replace_subject(self.x0), drop)

        # now we can set up the explicit and implicit problems
        explicit_forcing_problem = LinearVariationalProblem(a.form,
                                                            L_explicit.form,
                                                            self.xF,
                                                            bcs=bcs)

        implicit_forcing_problem = LinearVariationalProblem(a.form,
                                                            L_implicit.form,
                                                            self.xF,
                                                            bcs=bcs)

        solver_parameters = {}
        if logger.isEnabledFor(DEBUG):
            solver_parameters["ksp_monitor_true_residual"] = None

        self.solvers = {}
        self.solvers["explicit"] = LinearVariationalSolver(
            explicit_forcing_problem,
            solver_parameters=solver_parameters,
            options_prefix="ExplicitForcingSolver")
        self.solvers["implicit"] = LinearVariationalSolver(
            implicit_forcing_problem,
            solver_parameters=solver_parameters,
            options_prefix="ImplicitForcingSolver")