69class InverseMassOperator
72 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
74 typedef InverseMassOperator<dim, n_components, Number> This;
76 typedef CellIntegrator<dim, n_components, Number> Integrator;
79 typedef dealii::MatrixFreeOperators::CellwiseInverseMassMatrix<dim, -1, n_components, Number>
80 InverseMassAsMatrixFreeOperator;
82 typedef std::pair<unsigned int, unsigned int> Range;
85 InverseMassOperator() : matrix_free(
nullptr), dof_index(0), quad_index(0)
90 initialize(dealii::MatrixFree<dim, Number>
const & matrix_free_in,
92 dealii::AffineConstraints<Number>
const * constraints =
nullptr)
94 this->matrix_free = &matrix_free_in;
95 dof_index = inverse_mass_operator_data.dof_index;
96 quad_index = inverse_mass_operator_data.quad_index;
98 data = inverse_mass_operator_data.parameters;
100 coefficient_is_variable = inverse_mass_operator_data.coefficient_is_variable;
101 consider_inverse_coefficient = inverse_mass_operator_data.consider_inverse_coefficient;
102 variable_coefficients = inverse_mass_operator_data.variable_coefficients;
105 AssertThrow(not coefficient_is_variable or variable_coefficients !=
nullptr,
106 dealii::ExcMessage(
"Pointer to variable coefficients not set properly."));
108 dealii::FiniteElement<dim>
const & fe = matrix_free->get_dof_handler(dof_index).get_fe();
113 if(data.implementation_type == InverseMassType::MatrixfreeOperator)
116 fe.base_element(0).dofs_per_cell == dealii::Utilities::pow(fe.degree + 1, dim),
118 "The matrix-free cell-wise inverse mass operator is currently only available for isotropic tensor-product elements."));
121 this->matrix_free->get_shape_info(0, quad_index).data[0].n_q_points_1d == fe.degree + 1,
123 "The matrix-free cell-wise inverse mass operator is currently only available if n_q_points_1d = n_nodes_1d."));
126 fe.conforms(dealii::FiniteElementData<dim>::L2),
128 "The matrix-free cell-wise inverse mass operator is only available for L2-conforming elements."));
135 mass_operator_data.dof_index = dof_index;
136 mass_operator_data.quad_index = quad_index;
137 mass_operator_data.coefficient_is_variable = coefficient_is_variable;
138 mass_operator_data.variable_coefficients = variable_coefficients;
139 mass_operator_data.consider_inverse_coefficient = consider_inverse_coefficient;
141 if(data.implementation_type == InverseMassType::ElementwiseKrylovSolver)
143 mass_operator_data.implement_block_diagonal_preconditioner_matrix_free =
true;
144 mass_operator_data.solver_block_diagonal = Elementwise::Solver::CG;
145 if(inverse_mass_operator_data.parameters.preconditioner == PreconditionerMass::None)
147 mass_operator_data.preconditioner_block_diagonal = Elementwise::Preconditioner::None;
149 else if(inverse_mass_operator_data.parameters.preconditioner ==
150 PreconditionerMass::PointJacobi)
152 mass_operator_data.preconditioner_block_diagonal =
153 Elementwise::Preconditioner::PointJacobi;
155 mass_operator_data.solver_data_block_diagonal =
156 inverse_mass_operator_data.parameters.solver_data;
160 if(constraints ==
nullptr)
162 dealii::AffineConstraints<Number> dummy_constraints;
163 dummy_constraints.close();
164 mass_operator.initialize(*matrix_free, dummy_constraints, mass_operator_data);
168 mass_operator.initialize(*matrix_free, *constraints, mass_operator_data);
171 if(data.implementation_type == InverseMassType::ElementwiseKrylovSolver or
172 data.implementation_type == InverseMassType::BlockMatrices)
177 fe.conforms(dealii::FiniteElementData<dim>::L2),
179 "The cell-wise inverse mass operator is only available for L2-conforming elements."));
181 block_jacobi_preconditioner =
182 std::make_shared<BlockJacobiPreconditioner<MassOperator<dim, n_components, Number>>>(
183 mass_operator,
true );
185 else if(data.implementation_type == InverseMassType::GlobalKrylovSolver)
188 solver_data.max_iter = inverse_mass_operator_data.parameters.solver_data.max_iter;
189 solver_data.solver_tolerance_abs =
190 inverse_mass_operator_data.parameters.solver_data.abs_tol;
191 solver_data.solver_tolerance_rel =
192 inverse_mass_operator_data.parameters.solver_data.rel_tol;
194 solver_data.use_preconditioner =
195 inverse_mass_operator_data.parameters.preconditioner != PreconditionerMass::None;
196 if(inverse_mass_operator_data.parameters.preconditioner == PreconditionerMass::None)
200 else if(inverse_mass_operator_data.parameters.preconditioner ==
201 PreconditionerMass::PointJacobi)
203 global_preconditioner =
204 std::make_shared<JacobiPreconditioner<MassOperator<dim, n_components, Number>>>(
205 mass_operator,
true );
207 else if(inverse_mass_operator_data.parameters.preconditioner ==
208 PreconditionerMass::BlockJacobi)
210 global_preconditioner =
211 std::make_shared<BlockJacobiPreconditioner<MassOperator<dim, n_components, Number>>>(
212 mass_operator,
true );
216 AssertThrow(
false, dealii::ExcMessage(
"This `PreconditionerMass` is not implemented."));
219 global_solver = std::make_shared<Krylov::SolverCG<MassOperator<dim, n_components, Number>,
221 VectorType>>(mass_operator,
222 *global_preconditioner,
228 dealii::ExcMessage(
"The specified `InverseMassType` is not implemented."));
240 if(data.implementation_type == InverseMassType::MatrixfreeOperator)
245 else if(data.implementation_type == InverseMassType::ElementwiseKrylovSolver or
246 data.implementation_type == InverseMassType::BlockMatrices)
252 block_jacobi_preconditioner->update();
254 else if(data.implementation_type == InverseMassType::GlobalKrylovSolver)
256 global_preconditioner->update();
260 AssertThrow(
false, dealii::ExcMessage(
"The specified InverseMassType is not implemented."));
283 if(data.implementation_type == InverseMassType::GlobalKrylovSolver)
285 AssertThrow(global_solver.get() != 0,
286 dealii::ExcMessage(
"Global mass solver has not been initialized."));
287 global_solver->solve(dst, *src_ptr);
291 dst.zero_out_ghost_values();
293 if(data.implementation_type == InverseMassType::MatrixfreeOperator)
295 matrix_free->cell_loop(&This::cell_loop_matrix_free_operator,
this, dst, *src_ptr);
299 AssertThrow(block_jacobi_preconditioner.get() != 0,
301 "Cell-wise iterative/direct block-Jacobi solver has not been initialized."));
302 block_jacobi_preconditioner->vmult(dst, *src_ptr);
309 apply_scale(VectorType & dst,
double const scaling_factor, VectorType
const & src)
const
311 if(data.implementation_type == InverseMassType::MatrixfreeOperator)
317 dst.zero_out_ghost_values();
319 matrix_free->cell_loop(
320 &This::cell_loop_matrix_free_operator,
325 [&](
const unsigned int start_range,
const unsigned int end_range) {
326 for(
unsigned int i = start_range; i < end_range; ++i)
327 dst.local_element(i) *= scaling_factor;
334 dst *= scaling_factor;
341 cell_loop_matrix_free_operator(dealii::MatrixFree<dim, Number>
const &,
343 VectorType
const & src,
344 Range
const & cell_range)
const
346 Integrator integrator(*matrix_free, dof_index, quad_index);
347 InverseMassAsMatrixFreeOperator inverse_mass(integrator);
349 if(coefficient_is_variable)
351 for(
unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
353 integrator.reinit(cell);
354 integrator.read_dof_values(src, 0);
356 dealii::AlignedVector<dealii::VectorizedArray<Number>> inverse_JxW_times_coefficient(
357 this->matrix_free->get_dofs_per_cell(dof_index));
358 inverse_mass.fill_inverse_JxW_values(inverse_JxW_times_coefficient);
360 if(consider_inverse_coefficient)
365 for(
unsigned int q = 0; q < integrator.n_q_points; ++q)
367 inverse_JxW_times_coefficient[q] *=
368 this->variable_coefficients->get_coefficient_cell(cell, q);
376 for(
unsigned int q = 0; q < integrator.n_q_points; ++q)
378 inverse_JxW_times_coefficient[q] /=
379 this->variable_coefficients->get_coefficient_cell(cell, q);
383 inverse_mass.apply(inverse_JxW_times_coefficient,
385 integrator.begin_dof_values(),
386 integrator.begin_dof_values());
388 integrator.set_dof_values(dst, 0);
393 for(
unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
395 integrator.reinit(cell);
396 integrator.read_dof_values(src, 0);
398 inverse_mass.apply(integrator.begin_dof_values(), integrator.begin_dof_values());
400 integrator.set_dof_values(dst, 0);
405 dealii::MatrixFree<dim, Number>
const * matrix_free;
407 unsigned int dof_index, quad_index;
409 InverseMassParameters data;
412 bool coefficient_is_variable;
413 bool consider_inverse_coefficient;
415 VariableCoefficients<dealii::VectorizedArray<Number>>
const * variable_coefficients;
419 std::shared_ptr<PreconditionerBase<Number>> global_preconditioner;
420 std::shared_ptr<Krylov::SolverBase<VectorType>> global_solver;
426 std::shared_ptr<BlockJacobiPreconditioner<MassOperator<dim, n_components, Number>>>
427 block_jacobi_preconditioner;
430 MassOperator<dim, n_components, Number> mass_operator;