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_EXADG_STRUCTURE_SPATIAL_DISCRETIZATION_OPERATOR_H_
23#define INCLUDE_EXADG_STRUCTURE_SPATIAL_DISCRETIZATION_OPERATOR_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>
58class ResidualOperator
59{
60private:
61 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
62
63 typedef Operator<dim, Number> PDEOperator;
64
65public:
66 ResidualOperator()
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
115 typedef Operator<dim, Number> PDEOperator;
116
117public:
118 LinearizedOperator()
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 pde_operator->update_elasticity_operator(scaling_factor_mass, time);
146 }
147
148 /*
149 * The implementation of linear solvers in deal.ii requires that a function called 'vmult' is
150 * provided.
151 */
152 void
153 vmult(VectorType & dst, VectorType const & src) const
154 {
155 pde_operator->apply_linearized_operator(dst, src);
156 }
157
158private:
159 PDEOperator const * pde_operator;
160
161 double scaling_factor_mass;
162 double time;
163};
164
165template<int dim, typename Number>
166class Operator : public dealii::Subscriptor, public Interface::Operator<Number>
167{
168private:
169 typedef float MultigridNumber;
170
171 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
172
173public:
174 /*
175 * Constructor.
176 */
177 Operator(std::shared_ptr<Grid<dim> const> grid,
178 std::shared_ptr<dealii::Mapping<dim> const> mapping,
179 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings,
180 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor,
181 std::shared_ptr<FieldFunctions<dim> const> field_functions,
182 std::shared_ptr<MaterialDescriptor const> material_descriptor,
183 Parameters const & param,
184 std::string const & field,
185 MPI_Comm const & mpi_comm);
186
187 void
188 fill_matrix_free_data(MatrixFreeData<dim, Number> & matrix_free_data) const;
189
193 void
194 setup();
195
201 void
202 setup(std::shared_ptr<dealii::MatrixFree<dim, Number> const> matrix_free,
203 std::shared_ptr<MatrixFreeData<dim, Number> const> matrix_free_data);
204
205 /*
206 * Initialization of dof-vector.
207 */
208 void
209 initialize_dof_vector(VectorType & src) const final;
210
211 /*
212 * Prescribe initial conditions using a specified initial solution function.
213 */
214 void
215 prescribe_initial_displacement(VectorType & displacement, double const time) const final;
216
217 void
218 prescribe_initial_velocity(VectorType & velocity, double const time) const final;
219
220 /*
221 * This computes the initial acceleration field by evaluating all PDE terms for the given
222 * initial condition, shifting all terms to the right-hand side of the equations, and solving a
223 * mass matrix system to obtain the initial acceleration.
224 */
225 void
226 compute_initial_acceleration(VectorType & initial_acceleration,
227 VectorType const & initial_displacement,
228 double const time) const final;
229
230 void
231 evaluate_mass_operator(VectorType & dst, VectorType const & src) const final;
232
233 void
234 apply_add_damping_operator(VectorType & dst, VectorType const & src) const final;
235
236 /*
237 * This function evaluates the nonlinear residual which is required by the Newton solver. In order
238 * to evaluate inhomogeneous Dirichlet boundary conditions correctly, inhomogeneous Dirichlet
239 * degrees of freedom need to be set correctly in the src-vector prior to calling this function.
240 */
241 void
242 evaluate_nonlinear_residual(VectorType & dst,
243 VectorType const & src,
244 VectorType const & const_vector,
245 double const factor,
246 double const time) const;
247
248 void
249 set_solution_linearization(VectorType const & vector) const;
250
251 void
252 assemble_matrix_if_necessary_for_linear_elasticity_operator() const;
253
254 void
255 evaluate_elasticity_operator(VectorType & dst,
256 VectorType const & src,
257 double const factor,
258 double const time) const;
259
260 void
261 update_elasticity_operator(double const factor, double const time) const;
262
263 void
264 apply_elasticity_operator(VectorType & dst, VectorType const & src) const;
265
266 /*
267 * This function solves the system of equations for nonlinear problems. This function needs to
268 * make sure that Dirichlet degrees of freedom are filled correctly with their inhomogeneous
269 * boundary data before calling the nonlinear solver.
270 */
271 std::tuple<unsigned int, unsigned int>
272 solve_nonlinear(VectorType & sol,
273 VectorType const & const_vector,
274 double const scaling_factor_acceleration,
275 double const scaling_factor_velocity,
276 double const time,
277 bool const update_preconditioner) const final;
278
279 /*
280 * This function calculates the right-hand side of the linear system of equations for linear
281 * elasticity problems.
282 */
283 void
284 rhs(VectorType & dst, double const time) const final;
285
286 /*
287 * This function solves the system of equations for linear problems.
288 *
289 * Before calling this function, make sure that the function rhs() has been called.
290 */
291 unsigned int
292 solve_linear(VectorType & sol,
293 VectorType const & rhs,
294 double const scaling_factor_acceleration,
295 double const scaling_factor_velocity,
296 double const time,
297 bool const update_preconditioner) const final;
298
299 /*
300 * Setters and getters.
301 */
302 std::shared_ptr<dealii::MatrixFree<dim, Number> const>
303 get_matrix_free() const;
304
305 dealii::Mapping<dim> const &
306 get_mapping() const;
307
308 dealii::DoFHandler<dim> const &
309 get_dof_handler() const;
310
311 dealii::types::global_dof_index
312 get_number_of_dofs() const;
313
314 // Multiphysics coupling via "Cached" boundary conditions
315 std::shared_ptr<ContainerInterfaceData<1, dim, double>>
316 get_container_interface_data_neumann() const;
317
318 std::shared_ptr<ContainerInterfaceData<1, dim, double>>
319 get_container_interface_data_dirichlet() const;
320
321 // TODO: we currently need this function public for precice-based FSI
322 unsigned int
323 get_dof_index() const;
324
325private:
326 /*
327 * Initializes dealii::DoFHandler.
328 */
329 void
330 initialize_dof_handler_and_constraints();
331
332 std::string
333 get_dof_name() const;
334
335 std::string
336 get_dof_name_periodicity_and_hanging_node_constraints() const;
337
338 std::string
339 get_quad_name() const;
340
341 std::string
342 get_quad_gauss_lobatto_name() const;
343
344 unsigned int
345 get_dof_index_periodicity_and_hanging_node_constraints() const;
346
347 unsigned int
348 get_quad_index() const;
349
350 unsigned int
351 get_quad_index_gauss_lobatto() const;
352
357 double
358 compute_scaling_factor_mass(double const scaling_factor_acceleration,
359 double const scaling_factor_velocity) const;
360
364 void
365 setup_coupling_boundary_conditions();
366
370 void
371 setup_operators();
372
376 void
377 setup_preconditioner();
378
382 void
383 setup_solver();
384
385 /*
386 * Grid
387 */
388 std::shared_ptr<Grid<dim> const> grid;
389
390 /*
391 * Mapping
392 */
393 std::shared_ptr<dealii::Mapping<dim> const> mapping;
394
395 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings;
396
397 /*
398 * User interface.
399 */
400 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor;
401 std::shared_ptr<FieldFunctions<dim> const> field_functions;
402 std::shared_ptr<MaterialDescriptor const> material_descriptor;
403
404 /*
405 * List of parameters.
406 */
407 Parameters const & param;
408
409 std::string const field;
410
411 /*
412 * Basic finite element ingredients.
413 */
414 std::shared_ptr<dealii::FiniteElement<dim>> fe;
415 dealii::DoFHandler<dim> dof_handler;
416
417 // AffineConstraints object as needed by iterative solvers and preconditioners for linear systems
418 // of equations. This constraint object contains additional constraints from Dirichlet boundary
419 // conditions as compared to the constraint object below. Note that the present constraint object
420 // can treat Dirichlet boundaries only in a homogeneous manner.
421 dealii::AffineConstraints<Number> affine_constraints;
422
423 // To treat inhomogeneous Dirichlet BCs correctly in the context of matrix-free operator
424 // evaluation using dealii::MatrixFree/FEEvaluation, we need a separate AffineConstraints
425 // object containing only periodicity and hanging node constraints.
426 // When using the standard AffineConstraints object including Dirichlet boundary conditions,
427 // inhomogeneous boundary data would be ignored by dealii::FEEvaluation::read_dof_values().
428 // While dealii::FEEvaluation::read_dof_values_plain() would take into account inhomogeneous
429 // Dirichlet data using the standard AffineConstraints object, hanging-node constraints would
430 // not be resolved correctly.
431 // The solution/workaround is to use dealii::FEEvaluation::read_dof_values() for a correct
432 // handling of hanging nodes, but to exclude Dirichlet degrees of freedom from the
433 // AffineConstraints object so that it is possible to read inhomogeneous boundary data when
434 // calling dealii::FEEvaluation::read_dof_values(). This inhomogeneous boundary data needs to be
435 // set beforehand in separate routines.
436 dealii::AffineConstraints<Number> affine_constraints_periodicity_and_hanging_nodes;
437
438 std::string const dof_index = "dof";
439 std::string const dof_index_periodicity_and_handing_node_constraints =
440 "dof_periodicity_hanging_nodes";
441
442 std::string const quad_index = "quad";
443 std::string const quad_index_gauss_lobatto = "quad_gauss_lobatto";
444
445 /*
446 * Matrix-free operator evaluation.
447 */
448 std::shared_ptr<dealii::MatrixFree<dim, Number> const> matrix_free;
449 std::shared_ptr<MatrixFreeData<dim, Number> const> matrix_free_data;
450
451 /*
452 * Interface coupling
453 */
454 // TODO: The PDE operator should only have read access to interface data
455 mutable std::shared_ptr<ContainerInterfaceData<1, dim, double>> interface_data_dirichlet_cached;
456 mutable std::shared_ptr<ContainerInterfaceData<1, dim, double>> interface_data_neumann_cached;
457
458 /*
459 * Basic operators.
460 */
461 BodyForceOperator<dim, Number> body_force_operator;
462
463 LinearOperator<dim, Number> elasticity_operator_linear;
464 NonLinearOperator<dim, Number> elasticity_operator_nonlinear;
465 OperatorData<dim> operator_data;
466
467 // The mass operator is only relevant for unsteady problems:
468 // it is used to compute the initial acceleration and to evaluate
469 // the mass operator term applied to a constant vector (independent
470 // of new displacements) appearing on the right-hand side for linear
471 // problems and in the residual for nonlinear problems.
473
474 /*
475 * Solution of nonlinear systems of equations
476 */
477
478 // operators required for Newton solver
479 mutable ResidualOperator<dim, Number> residual_operator;
480 mutable LinearizedOperator<dim, Number> linearized_operator;
481
482 typedef Newton::Solver<VectorType,
486 NewtonSolver;
487
488 std::shared_ptr<NewtonSolver> newton_solver;
489
490 /*
491 * Solution of linear systems of equations
492 */
493 std::shared_ptr<PreconditionerBase<Number>> preconditioner;
494
495 std::shared_ptr<Krylov::SolverBase<VectorType>> linear_solver;
496
497 // mass operator inversion
498 std::shared_ptr<PreconditionerBase<Number>> mass_preconditioner;
499 std::shared_ptr<Krylov::SolverBase<VectorType>> mass_solver;
500
501 /*
502 * MPI communicator
503 */
504 MPI_Comm const mpi_comm;
505
506 /*
507 * Output to screen.
508 */
509 dealii::ConditionalOStream pcout;
510};
511
512} // namespace Structure
513} // namespace ExaDG
514
515#endif /* INCLUDE_EXADG_STRUCTURE_SPATIAL_DISCRETIZATION_OPERATOR_H_ */
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:167
void setup()
Definition operator.cpp:277
Definition parameters.h:41
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