ExaDG
Loading...
Searching...
No Matches
operator_coupled.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_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATOR_COUPLED_H_
23#define EXADG_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATOR_COUPLED_H_
24
25// ExaDG
26#include <exadg/convection_diffusion/spatial_discretization/operators/combined_operator.h>
27#include <exadg/incompressible_navier_stokes/spatial_discretization/spatial_operator_base.h>
28#include <exadg/solvers_and_preconditioners/newton/newton_solver.h>
29
30namespace ExaDG
31{
32namespace IncNS
33{
34// forward declaration
35template<int dim, typename Number>
36class OperatorCoupled;
37
38template<int dim, typename Number>
39class NonlinearOperatorCoupled
40{
41private:
42 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
43 typedef dealii::LinearAlgebra::distributed::BlockVector<Number> BlockVectorType;
44
45 typedef OperatorCoupled<dim, Number> PDEOperator;
46
47public:
48 NonlinearOperatorCoupled()
49 : pde_operator(nullptr), rhs_vector(nullptr), time(0.0), scaling_factor_mass(1.0)
50 {
51 }
52
53 void
54 initialize(PDEOperator const & pde_operator)
55 {
56 this->pde_operator = &pde_operator;
57 }
58
59 void
60 update(VectorType const & rhs_vector, double const & time, double const & scaling_factor)
61 {
62 this->rhs_vector = &rhs_vector;
63 this->time = time;
64 this->scaling_factor_mass = scaling_factor;
65 }
66
67 /*
68 * The implementation of the Newton solver requires a function called
69 * 'evaluate_residual'.
70 */
71 void
72 evaluate_residual(BlockVectorType & dst, BlockVectorType const & src) const
73 {
74 pde_operator->evaluate_nonlinear_residual(dst, src, rhs_vector, time, scaling_factor_mass);
75 }
76
77private:
78 PDEOperator const * pde_operator;
79
80 VectorType const * rhs_vector;
81 double time;
82 double scaling_factor_mass;
83};
84
85template<int dim, typename Number>
86class LinearOperatorCoupled : public dealii::EnableObserverPointer
87{
88private:
89 typedef dealii::LinearAlgebra::distributed::BlockVector<Number> BlockVectorType;
90
91 typedef OperatorCoupled<dim, Number> PDEOperator;
92
93public:
94 LinearOperatorCoupled() : dealii::EnableObserverPointer(), pde_operator(nullptr)
95 {
96 }
97
98 void
99 initialize(PDEOperator const & pde_operator)
100 {
101 this->pde_operator = &pde_operator;
102 }
103
104 /*
105 * The implementation of the Newton solver requires a function called
106 * 'set_solution_linearization'.
107 */
108 void
109 set_solution_linearization(BlockVectorType const & solution_linearization) const
110 {
111 pde_operator->set_velocity_ptr(solution_linearization.block(0));
112 }
113
114
115 /*
116 * The implementation of linear solvers in deal.ii requires that a function called 'vmult' is
117 * provided.
118 */
119 void
120 vmult(BlockVectorType & dst, BlockVectorType const & src) const
121 {
122 pde_operator->apply_linearized_problem(dst, src);
123 }
124
125private:
126 PDEOperator const * pde_operator;
127};
128
129template<int dim, typename Number>
130class BlockPreconditioner
131{
132private:
133 typedef dealii::LinearAlgebra::distributed::BlockVector<Number> BlockVectorType;
134
135 typedef OperatorCoupled<dim, Number> PDEOperator;
136
137public:
138 BlockPreconditioner() : update_needed(true), pde_operator(nullptr)
139 {
140 }
141
142 void
143 initialize(PDEOperator * pde_operator_in)
144 {
145 pde_operator = pde_operator_in;
146 }
147
148 void
149 update()
150 {
151 pde_operator->update_block_preconditioner();
152
153 this->update_needed = false;
154 }
155
156 bool
157 needs_update() const
158 {
159 return update_needed;
160 }
161
162 void
163 vmult(BlockVectorType & dst, BlockVectorType const & src) const
164 {
165 AssertThrow(this->update_needed == false,
166 dealii::ExcMessage(
167 "BlockPreconditioner can not be applied because it is not up-to-date."));
168
169 pde_operator->apply_block_preconditioner(dst, src);
170 }
171
172 std::shared_ptr<TimerTree>
173 get_timings() const
174 {
175 AssertThrow(false,
176 dealii::ExcMessage(
177 "Function get_timings() is not implemented for BlockPreconditioner."));
178
179 return std::make_shared<TimerTree>();
180 }
181
182private:
183 bool update_needed;
184
185 PDEOperator * pde_operator;
186};
187
188template<int dim, typename Number = double>
189class OperatorCoupled : public SpatialOperatorBase<dim, Number>
190{
191private:
192 typedef SpatialOperatorBase<dim, Number> Base;
193 typedef OperatorCoupled<dim, Number> This;
194
195 typedef typename Base::MultigridPoisson MultigridPoisson;
196
197 typedef typename Base::VectorType VectorType;
198
199 typedef typename Base::BlockVectorType BlockVectorType;
200
201public:
202 /*
203 * Constructor.
204 */
205 OperatorCoupled(std::shared_ptr<Grid<dim> const> grid,
206 std::shared_ptr<dealii::Mapping<dim> const> mapping,
207 std::shared_ptr<MultigridMappings<dim, Number>> const multigrid_mappings,
208 std::shared_ptr<BoundaryDescriptor<dim> const> boundary_descriptor,
209 std::shared_ptr<FieldFunctions<dim> const> field_functions,
210 Parameters const & parameters,
211 std::string const & field,
212 MPI_Comm const & mpi_comm);
213
214 /*
215 * Destructor.
216 */
217 virtual ~OperatorCoupled();
218
219private:
220 void
221 setup_derived() final;
222
223 void
224 setup_preconditioners_and_solvers() final;
225
226public:
227 /*
228 * Update divergence penalty operator by recalculating the penalty parameter
229 * which depends on the current velocity field
230 */
231 void
232 update_divergence_penalty_operator(VectorType const & velocity);
233
234 /*
235 * Update continuity penalty operator by recalculating the penalty parameter
236 * which depends on the current velocity field
237 */
238 void
239 update_continuity_penalty_operator(VectorType const & velocity);
240
241 /*
242 * Setters and getters.
243 */
244
245 /*
246 * This function sets the variable scaling_factor_continuity, and also the related scaling factor
247 * for the pressure gradient operator.
248 */
249 void
250 set_scaling_factor_continuity(double const scaling_factor);
251
252 /*
253 * Stokes equations or convective term treated explicitly: solve linear system of equations
254 */
255
256 /*
257 * This function solves the linear Stokes problem (Stokes equations or Navier-Stokes
258 * equations with an explicit treatment of the convective term). The parameter
259 * scaling_factor_mass has to be specified for unsteady problem and
260 * can be omitted for steady problems.
261 */
262 unsigned int
263 solve_linear_problem(BlockVectorType & dst,
264 BlockVectorType const & src,
265 VectorType const & transport_velocity,
266 bool const & update_preconditioner,
267 double const & scaling_factor_mass = 1.0);
268
269 /*
270 * Convective term treated implicitly: solve non-linear system of equations
271 */
272
273 /*
274 * This function solves the nonlinear problem.
275 */
276 std::tuple<unsigned int, unsigned int>
277 solve_nonlinear_problem(BlockVectorType & dst,
278 VectorType const & rhs_vector,
279 bool const & update_preconditioner,
280 double const & time = 0.0,
281 double const & scaling_factor_mass = 1.0);
282
283
284 /*
285 * This function evaluates the nonlinear residual.
286 */
287 void
288 evaluate_nonlinear_residual(BlockVectorType & dst,
289 BlockVectorType const & src,
290 VectorType const * rhs_vector,
291 double const & time,
292 double const & scaling_factor_mass) const;
293
294 /*
295 * This function computes the rhs of the linearized problem residual
296 */
297 void
298 rhs_residual_linearized_problem(BlockVectorType & dst, double const & time) const;
299
300 /*
301 * This function evaluates the linearized residual.
302 */
303 void
304 evaluate_linearized_residual(BlockVectorType & dst,
305 BlockVectorType const & src,
306 VectorType const & transport_velocity,
307 BlockVectorType const & rhs_vector,
308 double const & time,
309 double const & scaling_factor_mass);
310
311 /*
312 * This function evaluates the nonlinear residual of the steady Navier-Stokes equations.
313 * This function has to be implemented separately (for example, the convective term will be
314 * evaluated in case of the Navier-Stokes equations and the time-derivative term is never
315 * evaluated).
316 */
317 void
318 evaluate_nonlinear_residual_steady(BlockVectorType & dst,
319 BlockVectorType const & src,
320 double const & time) const;
321
322 /*
323 * This function calculates the matrix-vector product for the linear(ized) problem.
324 */
325 void
326 apply_linearized_problem(BlockVectorType & dst, BlockVectorType const & src) const;
327
328 /*
329 * This function calculates the right-hand side of the steady Stokes problem, or unsteady Stokes
330 * problem, or unsteady Navier-Stokes problem with explicit treatment of the convective term. The
331 * parameter 'time' has to be specified for unsteady problems and can be omitted for steady
332 * problems.
333 */
334 void
335 rhs_linear_problem(BlockVectorType & dst,
336 VectorType const & transport_velocity,
337 double const & time = 0.0) const;
338
339 /*
340 * Block preconditioner
341 */
342 void
343 update_block_preconditioner();
344
345 void
346 apply_block_preconditioner(BlockVectorType & dst, BlockVectorType const & src) const;
347
348private:
349 void
350 setup_solver_coupled();
351
352 /*
353 * Block preconditioner
354 */
355 void
356 setup_block_preconditioner();
357
358 void
359 initialize_vectors();
360
361 void
362 initialize_preconditioner_velocity_block();
363
364 void
365 setup_multigrid_preconditioner_momentum();
366
367 void
368 setup_iterative_solver_momentum();
369
370 void
371 initialize_preconditioner_pressure_block();
372
373 void
374 setup_multigrid_preconditioner_schur_complement();
375
376 void
377 setup_iterative_solver_schur_complement();
378
379 void
380 setup_pressure_convection_diffusion_operator();
381
382 void
383 apply_preconditioner_velocity_block(VectorType & dst, VectorType const & src) const;
384
385 void
386 apply_preconditioner_pressure_block(VectorType & dst, VectorType const & src) const;
387
388 void
389 apply_inverse_negative_laplace_operator(VectorType & dst, VectorType const & src) const;
390
391 /*
392 * Newton-Krylov solver for (non-)linear problem
393 */
394
395 // temporary vector needed to evaluate both the nonlinear residual and the linearized operator
396 VectorType mutable temp_vector;
397
398 double scaling_factor_continuity;
399
400 // Nonlinear operator
401 NonlinearOperatorCoupled<dim, Number> nonlinear_operator;
402
403 // Newton solver
404 std::shared_ptr<Newton::Solver<BlockVectorType,
408 newton_solver;
409
410 // Linear operator
412
413 // Linear solver
414 std::shared_ptr<Krylov::SolverBase<BlockVectorType>> linear_solver;
415
416 /*
417 * Block preconditioner for linear(ized) problem
418 */
419 typedef BlockPreconditioner<dim, Number> Preconditioner;
420 Preconditioner block_preconditioner;
421
422 // preconditioner velocity/momentum block
423 std::shared_ptr<PreconditionerBase<Number>> preconditioner_momentum;
424
425 std::shared_ptr<Krylov::SolverBase<VectorType>> solver_velocity_block;
426
427 // preconditioner pressure/Schur-complement block
428 std::shared_ptr<PreconditionerBase<Number>> multigrid_preconditioner_schur_complement;
429 std::shared_ptr<PreconditionerBase<Number>> inverse_mass_preconditioner_schur_complement;
430
431 std::shared_ptr<ConvDiff::CombinedOperator<dim, Number>> pressure_conv_diff_operator;
432
433 std::shared_ptr<Poisson::LaplaceOperator<dim, Number, 1>> laplace_operator;
434
435 std::shared_ptr<Krylov::SolverBase<VectorType>> solver_pressure_block;
436
437 // temporary vectors that are necessary when using preconditioners of block-triangular type
438 VectorType mutable vec_tmp_pressure;
439 VectorType mutable vec_tmp_velocity, vec_tmp_velocity_2;
440
441 // temporary vectors that are necessary when applying the Schur-complement preconditioner (scp)
442 VectorType mutable tmp_scp_pressure;
443 VectorType mutable tmp_scp_velocity, tmp_scp_velocity_2;
444};
445
446} // namespace IncNS
447} // namespace ExaDG
448
449#endif /* EXADG_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATOR_COUPLED_H_ \
450 */
Definition grid.h:40
Definition operator_coupled.h:131
Definition operator_coupled.h:87
Definition operator_coupled.h:40
Definition operator_coupled.h:190
Definition parameters.h:46
Definition iterative_solvers_dealii_wrapper.h:40
Definition grid.h:84
Definition newton_solver.h:40
Definition driver.cpp:33
Definition boundary_descriptor.h:240
Definition field_functions.h:31