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 EXADG_STRUCTURE_SPATIAL_DISCRETIZATION_OPERATOR_H_
23#define 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/operators/navier_stokes_calculators.h>
34#include <exadg/operators/structure_calculators.h>
35#include <exadg/solvers_and_preconditioners/newton/newton_solver.h>
36#include <exadg/solvers_and_preconditioners/preconditioners/preconditioner_base.h>
37#include <exadg/structure/spatial_discretization/interface.h>
38#include <exadg/structure/spatial_discretization/operators/body_force_operator.h>
39#include <exadg/structure/spatial_discretization/operators/linear_operator.h>
40#include <exadg/structure/spatial_discretization/operators/mass_operator.h>
41#include <exadg/structure/spatial_discretization/operators/nonlinear_operator.h>
42#include <exadg/structure/user_interface/boundary_descriptor.h>
43#include <exadg/structure/user_interface/field_functions.h>
44#include <exadg/structure/user_interface/parameters.h>
45
46namespace ExaDG
47{
48namespace Structure
49{
50// forward declarations
51template<int dim, typename Number>
52class Operator;
53
54namespace Interface
55{
56template<typename Number>
57class Operator;
58}
59
60/*
61 * This operator provides the interface required by the non-linear Newton solver.
62 * Requests to evaluate the residual for example are simply handed over to the
63 * operators that implement the physics.
64 */
65template<int dim, typename Number>
66class ResidualOperator
67{
68private:
69 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
70
71 typedef Operator<dim, Number> PDEOperator;
72
73public:
74 ResidualOperator()
75 : pde_operator(nullptr), const_vector(nullptr), scaling_factor_mass(0.0), time(0.0)
76 {
77 }
78
79 void
80 initialize(PDEOperator const & pde_operator)
81 {
82 this->pde_operator = &pde_operator;
83 }
84
85 void
86 update(VectorType const & const_vector, double const scaling_factor_mass, double const time)
87 {
88 this->const_vector = &const_vector;
89 this->scaling_factor_mass = scaling_factor_mass;
90 this->time = time;
91 }
92
93 /*
94 * The implementation of the Newton solver requires a function called
95 * 'evaluate_residual()'.
96 */
97 void
98 evaluate_residual(VectorType & dst, VectorType const & src) const
99 {
100 pde_operator->evaluate_nonlinear_residual(dst, src, *const_vector, scaling_factor_mass, time);
101 }
102
103private:
104 PDEOperator const * pde_operator;
105
106 VectorType const * const_vector;
107
108 double scaling_factor_mass;
109 double time;
110};
111
112/*
113 * This operator implements the interface required by the non-linear Newton solver.
114 * Requests to apply the linearized operator are simply handed over to the
115 * operators that implement the physics.
116 */
117template<int dim, typename Number>
118class LinearizedOperator : public dealii::EnableObserverPointer
119{
120private:
121 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
122
123 typedef Operator<dim, Number> PDEOperator;
124
125public:
126 LinearizedOperator()
127 : dealii::EnableObserverPointer(), pde_operator(nullptr), scaling_factor_mass(0.0), time(0.0)
128 {
129 }
130
131 void
132 initialize(PDEOperator const & pde_operator)
133 {
134 this->pde_operator = &pde_operator;
135 }
136
137 /*
138 * The implementation of the Newton solver requires a function called
139 * 'set_solution_linearization'.
140 */
141 void
142 set_solution_linearization(VectorType const & solution_linearization) const
143 {
144 // note that this function will re-assemble the matrix in case of a matrix-based implementation.
145 pde_operator->set_solution_linearization(solution_linearization);
146 }
147
148 void
149 update(double const scaling_factor_mass, double const time)
150 {
151 this->scaling_factor_mass = scaling_factor_mass;
152 this->time = time;
153
154 pde_operator->update_elasticity_operator(scaling_factor_mass, time);
155 }
156
157private:
158 PDEOperator const * pde_operator;
159
160 double scaling_factor_mass;
161 double time;
162};
163
164template<int dim, typename Number>
165class Operator : public dealii::EnableObserverPointer, public Interface::Operator<Number>
166{
167private:
168 typedef float MultigridNumber;
169
170 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
171
172public:
173 /*
174 * Constructor.
175 */
176 Operator(std::shared_ptr<Grid<dim> const> grid_in,
177 std::shared_ptr<dealii::Mapping<dim> const> mapping_in,
178 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings_in,
179 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor_in,
180 std::shared_ptr<FieldFunctions<dim> const> field_functions_in,
181 std::shared_ptr<MaterialDescriptor const> material_descriptor_in,
182 Parameters const & param_in,
183 std::string const & field_in,
184 bool const setup_scalar_field_in,
185 MPI_Comm const & mpi_comm_in);
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 for vector field.
207 */
208 void
209 initialize_dof_vector(VectorType & src) const final;
210
211 /*
212 * Initialization of DoF vector for scalar field.
213 */
214 void
215 initialize_dof_vector_scalar(VectorType & src) const;
216
217 /*
218 * Prescribe initial conditions using a specified initial solution function.
219 */
220 void
221 prescribe_initial_displacement(VectorType & displacement, double const time) const final;
222
223 void
224 prescribe_initial_velocity(VectorType & velocity, double const time) const final;
225
226 /*
227 * This computes the initial acceleration field by evaluating all PDE terms for the given
228 * initial condition, shifting all terms to the right-hand side of the equations, and solving a
229 * mass matrix system to obtain the initial acceleration.
230 */
231 void
232 compute_initial_acceleration(VectorType & initial_acceleration,
233 VectorType const & initial_displacement,
234 double const time) const final;
235
236 void
237 evaluate_mass_operator(VectorType & dst, VectorType const & src) const final;
238
239 void
240 apply_add_damping_operator(VectorType & dst, VectorType const & src) const final;
241
242 /*
243 * This function evaluates the nonlinear residual which is required by the Newton solver. In order
244 * to evaluate inhomogeneous Dirichlet boundary conditions correctly, inhomogeneous Dirichlet
245 * degrees of freedom need to be set correctly in the src-vector prior to calling this function.
246 */
247 void
248 evaluate_nonlinear_residual(VectorType & dst,
249 VectorType const & src,
250 VectorType const & const_vector,
251 double const factor,
252 double const time) const;
253
254 void
255 set_solution_linearization(VectorType const & vector) const;
256
257 void
258 assemble_matrix_if_matrix_based() const;
259
260 void
261 evaluate_elasticity_operator(VectorType & dst,
262 VectorType const & src,
263 double const factor,
264 double const time) const;
265
266 void
267 update_elasticity_operator(double const factor, double const time) const;
268
269 void
270 apply_elasticity_operator(VectorType & dst, VectorType const & src) const;
271
272 /*
273 * This function solves the system of equations for nonlinear problems. This function needs to
274 * make sure that Dirichlet degrees of freedom are filled correctly with their inhomogeneous
275 * boundary data before calling the nonlinear solver.
276 */
277 std::tuple<unsigned int, unsigned int>
278 solve_nonlinear(VectorType & sol,
279 VectorType const & const_vector,
280 double const scaling_factor_acceleration,
281 double const scaling_factor_velocity,
282 double const time,
283 bool const update_preconditioner) const final;
284
285 /*
286 * This function calculates the right-hand side of the linear system of equations for linear
287 * elasticity problems.
288 */
289 void
290 rhs(VectorType & dst, double const time) const final;
291
292 /*
293 * This function solves the system of equations for linear problems.
294 *
295 * Before calling this function, make sure that the function rhs() has been called.
296 */
297 unsigned int
298 solve_linear(VectorType & sol,
299 VectorType const & rhs,
300 double const scaling_factor_acceleration,
301 double const scaling_factor_velocity,
302 double const time,
303 bool const update_preconditioner) const final;
304
305 /*
306 * Setters and getters.
307 */
308 std::shared_ptr<dealii::MatrixFree<dim, Number> const>
309 get_matrix_free() const;
310
311 dealii::Mapping<dim> const &
312 get_mapping() const;
313
314 dealii::DoFHandler<dim> const &
315 get_dof_handler() const;
316
317 dealii::DoFHandler<dim> const &
318 get_dof_handler_scalar() const;
319
320 dealii::types::global_dof_index
321 get_number_of_dofs() const;
322
323 // Multiphysics coupling via "Cached" boundary conditions
324 std::shared_ptr<ContainerInterfaceData<1, dim, double>>
325 get_container_interface_data_neumann() const;
326
327 std::shared_ptr<ContainerInterfaceData<1, dim, double>>
328 get_container_interface_data_dirichlet() const;
329
330 // TODO: we currently need this function public for precice-based FSI
331 unsigned int
332 get_dof_index() const;
333
334 /*
335 * Computation of derived quantities needed for postprocessing.
336 */
337
338 // displacement magnitude
339 void
340 compute_displacement_magnitude(VectorType & dst_scalar_valued,
341 VectorType const & src_vector_valued) const;
342
343 // compute Jacobian of the displacement field
344 void
345 compute_displacement_jacobian(VectorType & dst_scalar_valued,
346 VectorType const & src_vector_valued) const;
347
348 // compute maximum principal stress
349 void
350 compute_max_principal_stress(VectorType & dst_scalar_valued,
351 VectorType const & src_vector_valued) const;
352
353private:
354 /*
355 * Initializes dealii::DoFHandler.
356 */
357 void
358 initialize_dof_handler_and_constraints();
359
360 std::string
361 get_dof_name() const;
362
363 std::string
364 get_dof_name_periodicity_and_hanging_node_constraints() const;
365
366 std::string
367 get_dof_name_scalar() const;
368
369 std::string
370 get_quad_name() const;
371
372 std::string
373 get_quad_gauss_lobatto_name() const;
374
375 unsigned int
376 get_dof_index_periodicity_and_hanging_node_constraints() const;
377
378 unsigned int
379 get_dof_index_scalar() const;
380
381 unsigned int
382 get_quad_index() const;
383
384 unsigned int
385 get_quad_index_gauss_lobatto() const;
386
391 double
392 compute_scaling_factor_mass(double const scaling_factor_acceleration,
393 double const scaling_factor_velocity) const;
394
398 void
399 setup_coupling_boundary_conditions();
400
404 void
405 setup_operators();
406
410 void
411 setup_calculators_for_derived_quantities();
412
416 void
417 setup_preconditioner();
418
422 void
423 setup_solver();
424
425 /*
426 * Grid
427 */
428 std::shared_ptr<Grid<dim> const> grid;
429
430 /*
431 * Mapping
432 */
433 std::shared_ptr<dealii::Mapping<dim> const> mapping;
434
435 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings;
436
437 /*
438 * User interface.
439 */
440 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor;
441 std::shared_ptr<FieldFunctions<dim> const> field_functions;
442 std::shared_ptr<MaterialDescriptor const> material_descriptor;
443
444 /*
445 * List of parameters.
446 */
447 Parameters const & param;
448
449 std::string const field;
450
451 /*
452 * Basic finite element ingredients.
453 */
454 std::shared_ptr<dealii::FiniteElement<dim>> fe;
455 dealii::DoFHandler<dim> dof_handler;
456
457 bool setup_scalar_field;
458 std::shared_ptr<dealii::FiniteElement<dim>> fe_scalar;
459 std::shared_ptr<dealii::DoFHandler<dim>> dof_handler_scalar;
460
461 // AffineConstraints object as needed by iterative solvers and preconditioners for linear systems
462 // of equations. This constraint object contains additional constraints from Dirichlet boundary
463 // conditions as compared to the constraint object below. Note that the present constraint object
464 // can treat Dirichlet boundaries only in a homogeneous manner.
465 dealii::AffineConstraints<Number> affine_constraints;
466
467 // To treat inhomogeneous Dirichlet BCs correctly in the context of matrix-free operator
468 // evaluation using dealii::MatrixFree/FEEvaluation, we need a separate AffineConstraints
469 // object containing only periodicity and hanging node constraints.
470 // When using the standard AffineConstraints object including Dirichlet boundary conditions,
471 // inhomogeneous boundary data would be ignored by dealii::FEEvaluation::read_dof_values().
472 // While dealii::FEEvaluation::read_dof_values_plain() would take into account inhomogeneous
473 // Dirichlet data using the standard AffineConstraints object, hanging-node constraints would
474 // not be resolved correctly.
475 // The solution/workaround is to use dealii::FEEvaluation::read_dof_values() for a correct
476 // handling of hanging nodes, but to exclude Dirichlet degrees of freedom from the
477 // AffineConstraints object so that it is possible to read inhomogeneous boundary data when
478 // calling dealii::FEEvaluation::read_dof_values(). This inhomogeneous boundary data needs to be
479 // set beforehand in separate routines.
480 dealii::AffineConstraints<Number> affine_constraints_periodicity_and_hanging_nodes;
481
482 // Constraints object for the scalar field containing only periodicity and hanging node
483 // constraints as we do not enforce further Dirichlet boundary conditions on the scalar field.
484 dealii::AffineConstraints<Number> affine_constraints_periodicity_and_hanging_nodes_scalar;
485
486 std::string const dof_index = "dof";
487 std::string const dof_index_periodicity_and_hanging_node_constraints =
488 "dof_periodicity_hanging_nodes";
489 std::string const dof_index_scalar = "dof_scalar";
490
491 std::string const quad_index = "quad";
492 std::string const quad_index_gauss_lobatto = "quad_gauss_lobatto";
493
494 /*
495 * Matrix-free operator evaluation.
496 */
497 std::shared_ptr<dealii::MatrixFree<dim, Number> const> matrix_free;
498 std::shared_ptr<MatrixFreeData<dim, Number> const> matrix_free_data;
499
500 /*
501 * Interface coupling
502 */
503 // TODO: The PDE operator should only have read access to interface data
504 mutable std::shared_ptr<ContainerInterfaceData<1, dim, double>> interface_data_dirichlet_cached;
505 mutable std::shared_ptr<ContainerInterfaceData<1, dim, double>> interface_data_neumann_cached;
506
507 /*
508 * Basic operators.
509 */
510 BodyForceOperator<dim, Number> body_force_operator;
511
512 LinearOperator<dim, Number> elasticity_operator_linear;
513 NonLinearOperator<dim, Number> elasticity_operator_nonlinear;
514 OperatorData<dim> operator_data;
515
516 // The mass operator is only relevant for unsteady problems:
517 // it is used to compute the initial acceleration and to evaluate
518 // the mass operator term applied to a constant vector (independent
519 // of new displacements) appearing on the right-hand side for linear
520 // problems and in the residual for nonlinear problems.
522
523 /*
524 * Solution of nonlinear systems of equations
525 */
526
527 // operators required for Newton solver
528 mutable ResidualOperator<dim, Number> residual_operator;
529 mutable LinearizedOperator<dim, Number> linearized_operator;
530
531 typedef Newton::Solver<VectorType,
535 NewtonSolver;
536
537 std::shared_ptr<NewtonSolver> newton_solver;
538
539 /*
540 * Solution of linear systems of equations
541 */
542 std::shared_ptr<PreconditionerBase<Number>> preconditioner;
543
544 std::shared_ptr<Krylov::SolverBase<VectorType>> linear_solver;
545
546 /*
547 * Inverse mass operators for initial acceleration problem and postprocessing.
548 */
549 InverseMassOperator<dim, dim /* n_components */, Number> inverse_mass;
550 InverseMassOperator<dim, 1 /* n_components */, Number> inverse_mass_scalar;
551
552 /*
553 * Calculators to obtain derived quantities.
554 */
555 MagnitudeCalculator<dim, Number> vector_magnitude_calculator;
556
557 DisplacementJacobianCalculator<dim, Number> displacement_jacobian_calculator;
558
559 MaxPrincipalStressCalculator<dim, Number> max_principal_stress_calculator;
560
561 /*
562 * MPI communicator
563 */
564 MPI_Comm const mpi_comm;
565
566 /*
567 * Output to screen.
568 */
569 dealii::ConditionalOStream pcout;
570};
571
572} // namespace Structure
573} // namespace ExaDG
574
575#endif /* EXADG_STRUCTURE_SPATIAL_DISCRETIZATION_OPERATOR_H_ */
Definition structure_calculators.h:45
Definition grid.h:40
Definition inverse_mass_operator.h:96
Definition iterative_solvers_dealii_wrapper.h:46
Definition navier_stokes_calculators.h:244
Definition structure_calculators.h:100
Definition grid.h:84
Definition newton_solver.h:40
Definition body_force_operator.h:50
Definition interface.h:39
Definition linear_operator.h:34
Definition operator.h:119
Definition mass_operator.h:43
Definition nonlinear_operator.h:34
Definition operator.h:166
void setup()
Definition operator.cpp:396
Definition parameters.h:41
Definition operator.h:67
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:37