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)])
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"]))
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
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
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)