ExaDG
Loading...
Searching...
No Matches
operator.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef INCLUDE_CONVECTION_DIFFUSION_DG_CONVECTION_DIFFUSION_OPERATION_H_
23#define INCLUDE_CONVECTION_DIFFUSION_DG_CONVECTION_DIFFUSION_OPERATION_H_
24
25// deal.II
26#include <deal.II/fe/fe_system.h>
27
28// ExaDG
29#include <exadg/grid/grid.h>
30#include <exadg/matrix_free/matrix_free_data.h>
31#include <exadg/operators/inverse_mass_operator.h>
32#include <exadg/operators/mass_operator.h>
33#include <exadg/solvers_and_preconditioners/newton/newton_solver.h>
34#include <exadg/solvers_and_preconditioners/preconditioners/preconditioner_base.h>
35#include <exadg/structure/spatial_discretization/interface.h>
36#include <exadg/structure/spatial_discretization/operators/body_force_operator.h>
37#include <exadg/structure/spatial_discretization/operators/linear_operator.h>
38#include <exadg/structure/spatial_discretization/operators/mass_operator.h>
39#include <exadg/structure/spatial_discretization/operators/nonlinear_operator.h>
40#include <exadg/structure/user_interface/boundary_descriptor.h>
41#include <exadg/structure/user_interface/field_functions.h>
42#include <exadg/structure/user_interface/parameters.h>
43
44namespace ExaDG
45{
46namespace Structure
47{
48// forward declaration
49template<int dim, typename Number>
50class Operator;
51
52/*
53 * This operator provides the interface required by the non-linear Newton solver.
54 * Requests to evaluate the residual for example are simply handed over to the
55 * operators that implement the physics.
56 */
57template<int dim, typename Number>
59{
60private:
61 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
62
64
65public:
67 : pde_operator(nullptr), const_vector(nullptr), scaling_factor_mass(0.0), time(0.0)
68 {
69 }
70
71 void
72 initialize(PDEOperator const & pde_operator)
73 {
74 this->pde_operator = &pde_operator;
75 }
76
77 void
78 update(VectorType const & const_vector, double const scaling_factor_mass, double const time)
79 {
80 this->const_vector = &const_vector;
81 this->scaling_factor_mass = scaling_factor_mass;
82 this->time = time;
83 }
84
85 /*
86 * The implementation of the Newton solver requires a function called
87 * 'evaluate_residual'.
88 */
89 void
90 evaluate_residual(VectorType & dst, VectorType const & src) const
91 {
92 pde_operator->evaluate_nonlinear_residual(dst, src, *const_vector, scaling_factor_mass, time);
93 }
94
95private:
96 PDEOperator const * pde_operator;
97
98 VectorType const * const_vector;
99
100 double scaling_factor_mass;
101 double time;
102};
103
104/*
105 * This operator implements the interface required by the non-linear Newton solver.
106 * Requests to apply the linearized operator are simply handed over to the
107 * operators that implement the physics.
108 */
109template<int dim, typename Number>
110class LinearizedOperator : public dealii::Subscriptor
111{
112private:
113 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
114
116
117public:
119 : dealii::Subscriptor(), pde_operator(nullptr), scaling_factor_mass(0.0), time(0.0)
120 {
121 }
122
123 void
124 initialize(PDEOperator const & pde_operator)
125 {
126 this->pde_operator = &pde_operator;
127 }
128
129 /*
130 * The implementation of the Newton solver requires a function called
131 * 'set_solution_linearization'.
132 */
133 void
134 set_solution_linearization(VectorType const & solution_linearization) const
135 {
136 pde_operator->set_solution_linearization(solution_linearization);
137 }
138
139 void
140 update(double const scaling_factor_mass, double const time)
141 {
142 this->scaling_factor_mass = scaling_factor_mass;
143 this->time = time;
144 }
145
146 /*
147 * The implementation of linear solvers in deal.ii requires that a function called 'vmult' is
148 * provided.
149 */
150 void
151 vmult(VectorType & dst, VectorType const & src) const
152 {
153 pde_operator->apply_linearized_operator(dst, src, scaling_factor_mass, time);
154 }
155
156private:
157 PDEOperator const * pde_operator;
158
159 double scaling_factor_mass;
160 double time;
161};
162
163template<int dim, typename Number>
164class Operator : public dealii::Subscriptor, public Interface::Operator<Number>
165{
166private:
167 typedef float MultigridNumber;
168
169 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
170
171public:
172 /*
173 * Constructor.
174 */
175 Operator(std::shared_ptr<Grid<dim> const> grid,
176 std::shared_ptr<dealii::Mapping<dim> const> mapping,
177 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings,
178 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor,
179 std::shared_ptr<FieldFunctions<dim> const> field_functions,
180 std::shared_ptr<MaterialDescriptor const> material_descriptor,
181 Parameters const & param,
182 std::string const & field,
183 MPI_Comm const & mpi_comm);
184
185 void
186 fill_matrix_free_data(MatrixFreeData<dim, Number> & matrix_free_data) const;
187
191 void
192 setup();
193
199 void
200 setup(std::shared_ptr<dealii::MatrixFree<dim, Number> const> matrix_free,
201 std::shared_ptr<MatrixFreeData<dim, Number> const> matrix_free_data);
202
203 /*
204 * Initialization of dof-vector.
205 */
206 void
207 initialize_dof_vector(VectorType & src) const final;
208
209 /*
210 * Prescribe initial conditions using a specified initial solution function.
211 */
212 void
213 prescribe_initial_displacement(VectorType & displacement, double const time) const final;
214
215 void
216 prescribe_initial_velocity(VectorType & velocity, double const time) const final;
217
218 /*
219 * This computes the initial acceleration field by evaluating all PDE terms for the given
220 * initial condition, shifting all terms to the right-hand side of the equations, and solving a
221 * mass matrix system to obtain the initial acceleration.
222 */
223 void
224 compute_initial_acceleration(VectorType & initial_acceleration,
225 VectorType const & initial_displacement,
226 double const time) const final;
227
228 void
229 evaluate_mass_operator(VectorType & dst, VectorType const & src) const final;
230
231 void
232 apply_add_damping_operator(VectorType & dst, VectorType const & src) const final;
233
234 /*
235 * This function evaluates the nonlinear residual which is required by the Newton solver. In order
236 * to evaluate inhomogeneous Dirichlet boundary conditions correctly, inhomogeneous Dirichlet
237 * degrees of freedom need to be set correctly in the src-vector prior to calling this function.
238 */
239 void
240 evaluate_nonlinear_residual(VectorType & dst,
241 VectorType const & src,
242 VectorType const & const_vector,
243 double const factor,
244 double const time) const;
245
246 void
247 set_solution_linearization(VectorType const & vector) const;
248
249 void
250 apply_linearized_operator(VectorType & dst,
251 VectorType const & src,
252 double const factor,
253 double const time) const;
254
255 void
256 evaluate_elasticity_operator(VectorType & dst,
257 VectorType const & src,
258 double const factor,
259 double const time) const;
260
261 void
262 apply_elasticity_operator(VectorType & dst,
263 VectorType const & src,
264 VectorType const & linearization,
265 double const factor,
266 double const time) const;
267
268 /*
269 * This function solves the system of equations for nonlinear problems. This function needs to
270 * make sure that Dirichlet degrees of freedom are filled correctly with their inhomogeneous
271 * boundary data before calling the nonlinear solver.
272 */
273 std::tuple<unsigned int, unsigned int>
274 solve_nonlinear(VectorType & sol,
275 VectorType const & const_vector,
276 double const scaling_factor_acceleration,
277 double const scaling_factor_velocity,
278 double const time,
279 bool const update_preconditioner) const final;
280
281 /*
282 * This function calculates the right-hand side of the linear system of equations for linear
283 * elasticity problems.
284 */
285 void
286 rhs(VectorType & dst, double const time) const final;
287
288 /*
289 * This function solves the system of equations for linear problems.
290 *
291 * Before calling this function, make sure that the function rhs() has been called.
292 */
293 unsigned int
294 solve_linear(VectorType & sol,
295 VectorType const & rhs,
296 double const scaling_factor_acceleration,
297 double const scaling_factor_velocity,
298 double const time,
299 bool const update_preconditioner) const final;
300
301 /*
302 * Setters and getters.
303 */
304 std::shared_ptr<dealii::MatrixFree<dim, Number> const>
305 get_matrix_free() const;
306
307 dealii::Mapping<dim> const &
308 get_mapping() const;
309
310 dealii::DoFHandler<dim> const &
311 get_dof_handler() const;
312
313 dealii::types::global_dof_index
314 get_number_of_dofs() const;
315
316 // Multiphysics coupling via "Cached" boundary conditions
317 std::shared_ptr<ContainerInterfaceData<1, dim, double>>
318 get_container_interface_data_neumann() const;
319
320 std::shared_ptr<ContainerInterfaceData<1, dim, double>>
321 get_container_interface_data_dirichlet() const;
322
323 // TODO: we currently need this function public for precice-based FSI
324 unsigned int
325 get_dof_index() const;
326
327private:
328 /*
329 * Initializes dealii::DoFHandler.
330 */
331 void
332 initialize_dof_handler_and_constraints();
333
334 std::string
335 get_dof_name() const;
336
337 std::string
338 get_dof_name_periodicity_and_hanging_node_constraints() const;
339
340 std::string
341 get_quad_name() const;
342
343 std::string
344 get_quad_gauss_lobatto_name() const;
345
346 unsigned int
347 get_dof_index_periodicity_and_hanging_node_constraints() const;
348
349 unsigned int
350 get_quad_index() const;
351
352 unsigned int
353 get_quad_index_gauss_lobatto() const;
354
359 double
360 compute_scaling_factor_mass(double const scaling_factor_acceleration,
361 double const scaling_factor_velocity) const;
362
366 void
367 setup_coupling_boundary_conditions();
368
372 void
373 setup_operators();
374
378 void
379 setup_preconditioner();
380
384 void
385 setup_solver();
386
387 /*
388 * Grid
389 */
390 std::shared_ptr<Grid<dim> const> grid;
391
392 /*
393 * Mapping
394 */
395 std::shared_ptr<dealii::Mapping<dim> const> mapping;
396
397 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings;
398
399 /*
400 * User interface.
401 */
402 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor;
403 std::shared_ptr<FieldFunctions<dim> const> field_functions;
404 std::shared_ptr<MaterialDescriptor const> material_descriptor;
405
406 /*
407 * List of parameters.
408 */
409 Parameters const & param;
410
411 std::string const field;
412
413 /*
414 * Basic finite element ingredients.
415 */
416 std::shared_ptr<dealii::FiniteElement<dim>> fe;
417 dealii::DoFHandler<dim> dof_handler;
418
419 // AffineConstraints object as needed by iterative solvers and preconditioners for linear systems
420 // of equations. This constraint object contains additional constraints from Dirichlet boundary
421 // conditions as compared to the constraint object below. Note that the present constraint object
422 // can treat Dirichlet boundaries only in a homogeneous manner.
423 dealii::AffineConstraints<Number> affine_constraints;
424
425 // To treat inhomogeneous Dirichlet BCs correctly in the context of matrix-free operator
426 // evaluation using dealii::MatrixFree/FEEvaluation, we need a separate AffineConstraints
427 // object containing only periodicity and hanging node constraints.
428 // When using the standard AffineConstraints object including Dirichlet boundary conditions,
429 // inhomogeneous boundary data would be ignored by dealii::FEEvaluation::read_dof_values().
430 // While dealii::FEEvaluation::read_dof_values_plain() would take into account inhomogeneous
431 // Dirichlet data using the standard AffineConstraints object, hanging-node constraints would
432 // not be resolved correctly.
433 // The solution/workaround is to use dealii::FEEvaluation::read_dof_values() for a correct
434 // handling of hanging nodes, but to exclude Dirichlet degrees of freedom from the
435 // AffineConstraints object so that it is possible to read inhomogeneous boundary data when
436 // calling dealii::FEEvaluation::read_dof_values(). This inhomogeneous boundary data needs to be
437 // set beforehand in separate routines.
438 dealii::AffineConstraints<Number> affine_constraints_periodicity_and_hanging_nodes;
439
440 std::string const dof_index = "dof";
441 std::string const dof_index_periodicity_and_handing_node_constraints =
442 "dof_periodicity_hanging_nodes";
443
444 std::string const quad_index = "quad";
445 std::string const quad_index_gauss_lobatto = "quad_gauss_lobatto";
446
447 /*
448 * Matrix-free operator evaluation.
449 */
450 std::shared_ptr<dealii::MatrixFree<dim, Number> const> matrix_free;
451 std::shared_ptr<MatrixFreeData<dim, Number> const> matrix_free_data;
452
453 /*
454 * Interface coupling
455 */
456 // TODO: The PDE operator should only have read access to interface data
457 mutable std::shared_ptr<ContainerInterfaceData<1, dim, double>> interface_data_dirichlet_cached;
458 mutable std::shared_ptr<ContainerInterfaceData<1, dim, double>> interface_data_neumann_cached;
459
460 /*
461 * Basic operators.
462 */
463 BodyForceOperator<dim, Number> body_force_operator;
464
465 LinearOperator<dim, Number> elasticity_operator_linear;
466 NonLinearOperator<dim, Number> elasticity_operator_nonlinear;
467 OperatorData<dim> operator_data;
468
469 // The mass operator is only relevant for unsteady problems:
470 // it is used to compute the initial acceleration and to evaluate
471 // the mass operator term applied to a constant vector (independent
472 // of new displacements) appearing on the right-hand side for linear
473 // problems and in the residual for nonlinear problems.
475
476 /*
477 * Solution of nonlinear systems of equations
478 */
479
480 // operators required for Newton solver
481 mutable ResidualOperator<dim, Number> residual_operator;
482 mutable LinearizedOperator<dim, Number> linearized_operator;
483
484 typedef Newton::Solver<VectorType,
489
490 std::shared_ptr<NewtonSolver> newton_solver;
491
492 /*
493 * Solution of linear systems of equations
494 */
495 std::shared_ptr<PreconditionerBase<Number>> preconditioner;
496
497 std::shared_ptr<Krylov::SolverBase<VectorType>> linear_solver;
498
499 // mass operator inversion
500 std::shared_ptr<PreconditionerBase<Number>> mass_preconditioner;
501 std::shared_ptr<Krylov::SolverBase<VectorType>> mass_solver;
502
503 /*
504 * MPI communicator
505 */
506 MPI_Comm const mpi_comm;
507
508 /*
509 * Output to screen.
510 */
511 dealii::ConditionalOStream pcout;
512};
513
514} // namespace Structure
515} // namespace ExaDG
516
517#endif
Definition grid.h:40
Definition iterative_solvers_dealii_wrapper.h:40
Definition grid.h:84
Definition newton_solver.h:40
Definition body_force_operator.h:50
Definition interface.h:36
Definition linear_operator.h:33
Definition operator.h:111
Definition mass_operator.h:43
Definition nonlinear_operator.h:33
Definition operator.h:165
void setup()
Definition operator.cpp:276
Definition parameters.h:40
Definition operator.h:59
Definition driver.cpp:33
Definition matrix_free_data.h:40
Definition boundary_descriptor.h:48
Definition field_functions.h:32
Definition elasticity_operator_base.h:36