28 template <
int dim,
class LacType>
33 , constants(
"/Stokes/Constants", {
"eta"}, {1.0}, {
"Viscosity"})
34 , schur_preconditioner(
"/Stokes/Solver/Schur preconditioner")
35 , schur_solver(
"/Stokes/Solver/Schur solver",
43 this->add_constraints_call_back.connect([&]() {
45 if (this->mpi_rank == 0)
47 unsigned int first_pressure_dof = 0;
48 for (
unsigned int i = 0; i < this->finite_element().dofs_per_cell;
51 if (this->finite_element().system_to_component_index(i).first ==
54 first_pressure_dof = i;
58 std::vector<types::global_dof_index> dof_indices(
59 this->finite_element().dofs_per_cell);
60 for (
const auto &cell : this->dof_handler.active_cell_iterators())
61 if (cell->is_locally_owned())
63 cell->get_dof_indices(dof_indices);
64 this->constraints.add_line(dof_indices[first_pressure_dof]);
73 template <
int dim,
class LacType>
80 auto &cell_matrix = copy.matrices[0];
81 auto &cell_rhs = copy.vectors[0];
83 cell->get_dof_indices(copy.local_dof_indices[0]);
85 const auto &fe_values = scratch.
reinit(cell);
89 for (
const unsigned int q_index : fe_values.quadrature_point_indices())
91 for (
const unsigned int i : fe_values.dof_indices())
94 fe_values[velocity].symmetric_gradient(i, q_index);
95 const auto &div_v = fe_values[velocity].divergence(i, q_index);
96 const auto &q = fe_values[pressure].value(i, q_index);
98 for (
const unsigned int j : fe_values.dof_indices())
101 fe_values[velocity].symmetric_gradient(j, q_index);
102 const auto &div_u = fe_values[velocity].divergence(j, q_index);
103 const auto &p = fe_values[pressure].value(j, q_index);
107 (constants[
"eta"] * scalar_product(eps_v, eps_u) - div_v * p -
108 div_u * q + p * q / constants[
"eta"]) *
109 fe_values.JxW(q_index);
113 (fe_values.shape_value(i, q_index) *
114 this->forcing_term.value(fe_values.quadrature_point(q_index),
115 this->finite_element()
116 .system_to_component_index(i)
118 fe_values.JxW(q_index));
125 template <
int dim,
class LacType>
131 using BVec =
typename LacType::BlockVector;
132 using Vec =
typename BVec::BlockType;
136 const auto &m = this->matrix;
138 const auto A = linear_operator<Vec>(m.block(0, 0));
139 const auto Bt = linear_operator<Vec>(m.block(0, 1));
140 const auto B = linear_operator<Vec>(m.block(1, 0));
141 const auto Mp = linear_operator<Vec>(m.block(1, 1));
142 const auto Zero = Mp * 0.0;
145 auto AA = block_operator<2, 2, BVec>({{{{A, Bt}}, {{B, Zero}}}});
147 if constexpr (std::is_same<LacType, LAC::LATrilinos>::value)
149 std::vector<std::vector<bool>> constant_modes;
151 this->finite_element().component_mask(
154 this->preconditioner.set_constant_modes(constant_modes);
155 const auto n_modes = std::count_if(constant_modes[0].begin(),
156 constant_modes[0].end(),
157 [](
const bool &
b) {
return b; });
158 deallog <<
"Constant modes: " << n_modes <<
"/"
159 << constant_modes[0].size() << std::endl;
165 this->preconditioner.initialize(m.block(0, 0));
166 schur_preconditioner.initialize(m.block(1, 1));
168 auto precA = linear_operator<Vec>(A, this->preconditioner);
170 const auto S = -1.0 * B * precA * Bt;
171 auto precM = linear_operator<Vec>(Mp, schur_preconditioner);
173 auto precS = schur_solver(Mp, precM);
175 std::array<LinOp, 2> diag_ops = {{precA, precS}};
176 auto diagprecAA = block_diagonal_operator<2, BVec>(diag_ops);
178 deallog <<
"Preconditioners initialized" << std::endl;
186 this->solution = inv * this->rhs;
191 this->solution = inv * this->rhs;
194 this->constraints.distribute(this->solution);
195 this->locally_relevant_solution = this->solution;
void reinit(const Triangulation< dim, spacedim > &tria)
Construct a LinearProblem.
Solve the Stokes problem, in parallel.
virtual void solve() override
Make sure we initialize the right type of linear solver.
typename LinearProblem< dim, dim, LacType >::CopyData CopyData
virtual void assemble_system_one_cell(const typename DoFHandler< dim >::active_cell_iterator &cell, ScratchData &scratch, CopyData ©) override
Explicitly assemble the Stokes problem on a single cell.
typename LinearProblem< dim, dim, LacType >::ScratchData ScratchData
LinearOperator< Domain, Range, typename BlockPayload::BlockType > block_forward_substitution(const BlockLinearOperator< Range, Domain, BlockPayload > &block_operator, const BlockLinearOperator< Domain, Range, BlockPayload > &diagonal_inverse)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
PDEs::Stokes< dim, LAC::LAPETSc > Stokes
We collect in this namespace all PDEs that are relevant to Fluid Structure Interaction Problems.
@ iteration_number
Use IterationNumberControl.