Ejemplo n.º 1
0
 def nullspace(self):
     """Inform solver that pressure solution is not unique.
     
     It is only defined up to adding an arbitrary constant.
     """
     W = self.solution_space
     
     return fe.MixedVectorSpaceBasis(
         W, [W.sub(0), fe.VectorSpaceBasis(constant=True)])            
Ejemplo n.º 2
0
 def nullspace(self):
     """Inform solver that pressure solution is not unique.
     
     It is only defined up to adding an arbitrary constant.
     """
     return fe.MixedVectorSpaceBasis(
         self.solution_space,
         (fe.VectorSpaceBasis(constant=True),
          self.solution_subspaces["u"]))
     
Ejemplo n.º 3
0
    def initialize(self, init_solution):
        self.solution_old.assign(init_solution)
        u, p = firedrake.split(self.solution)
        u_old, p_old = self.solution_old.split()
        u_star_theta = (1-self.theta)*u_old + self.theta*self.u_star
        u_theta = (1-self.theta)*u_old + self.theta*u
        p_theta = (1-self.theta_p)*p_old + self.theta_p*p
        u_lag, p_lag = self.solution_lag.split()
        u_lag_theta = (1-self.theta)*u_old + self.theta*u_lag
        p_lag_theta = (1-self.theta_p)*p_old + self.theta_p*p_lag

        # setup predictor solve, this solves for u_start only using a fixed p_lag_theta for pressure
        self.fields_star = self.fields.copy()
        self.fields_star['pressure'] = p_lag_theta

        self.Fstar = self.equations[0].mass_term(self.u_star_test, self.u_star-u_old)
        self.Fstar -= self.dt_const*self.equations[0].residual(self.u_star_test, u_star_theta, u_lag_theta, self.fields_star, bcs=self.bcs)
        self.predictor_problem = firedrake.NonlinearVariationalProblem(self.Fstar, self.u_star)
        self.predictor_solver = firedrake.NonlinearVariationalSolver(self.predictor_problem,
                                                                     solver_parameters=self.predictor_solver_parameters,
                                                                     options_prefix='predictor_momentum')

        # the correction solve, solving the coupled system:
        #   u1 = u* - dt*G ( p_theta - p_lag_theta)
        #   div(u1) = 0
        self.F = self.equations[0].mass_term(self.u_test, u-self.u_star)

        pg_term = [term for term in self.equations[0]._terms if isinstance(term, PressureGradientTerm)][0]
        pg_fields = self.fields.copy()
        # note that p_theta-p_lag_theta = theta_p*(p1-p_lag)
        pg_fields['pressure'] = self.theta_p * (p - p_lag)
        self.F -= self.dt_const*pg_term.residual(self.u_test, u_theta, u_lag_theta, pg_fields, bcs=self.bcs)

        div_term = [term for term in self.equations[1]._terms if isinstance(term, DivergenceTerm)][0]
        div_fields = self.fields.copy()
        div_fields['velocity'] = u
        self.F -= self.dt_const*div_term.residual(self.p_test, p_theta, p_lag_theta, div_fields, bcs=self.bcs)

        W = self.solution.function_space()
        if self.pressure_nullspace is None:
            mixed_nullspace = None
        else:
            mixed_nullspace = firedrake.MixedVectorSpaceBasis(W, [W.sub(0), self.pressure_nullspace])

        self.problem = firedrake.NonlinearVariationalProblem(self.F, self.solution)
        self.solver = firedrake.NonlinearVariationalSolver(self.problem,
                                                           solver_parameters=self.solver_parameters,
                                                           appctx={'a': firedrake.derivative(self.F, self.solution),
                                                                   'schur_nullspace': self.pressure_nullspace,
                                                                   'dt': self.dt_const, 'dx': self.equations[1].dx,
                                                                   'ds': self.equations[1].ds, 'bcs': self.bcs, 'n': div_term.n},
                                                           nullspace=mixed_nullspace, transpose_nullspace=mixed_nullspace,
                                                           options_prefix=self.name)

        self._initialized = True
Ejemplo n.º 4
0
    def get_nullspace(self):
        """Specify nullspace of state/adjoint equation."""

        if len(self.outflow_bids) > 0:
            # If the pressure is fixed (anywhere) by a Dirichlet bc, nsp = None
            nsp = None
        else:
            nsp = fd.MixedVectorSpaceBasis(
                self.V, [self.V.sub(0),
                         fd.VectorSpaceBasis(constant=True)])
        return nsp
Ejemplo n.º 5
0
def coarsen_mixedvectorspacebasis(mspbasis, self, coefficient_mapping=None):
    coarse_V = self(mspbasis._function_space,
                    self,
                    coefficient_mapping=coefficient_mapping)
    coarse_bases = []

    for basis in mspbasis._bases:
        if isinstance(basis, firedrake.VectorSpaceBasis):
            coarse_bases.append(
                self(basis, self, coefficient_mapping=coefficient_mapping))
        elif basis.index is not None:
            coarse_bases.append(coarse_V.sub(basis.index))
        else:
            raise RuntimeError(
                "MixedVectorSpaceBasis can only contain vector space bases or indexed function spaces"
            )

    return firedrake.MixedVectorSpaceBasis(coarse_V, coarse_bases)