ExaDG
Loading...
Searching...
No Matches
operator.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2023 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_ACOUSTIC_CONSERVATION_EQUATIONS_SPATIAL_DISCRETIZATION_OPERATORS_OPERATOR_H_
23#define EXADG_ACOUSTIC_CONSERVATION_EQUATIONS_SPATIAL_DISCRETIZATION_OPERATORS_OPERATOR_H_
24
25#include <deal.II/lac/la_parallel_block_vector.h>
26
27#include <exadg/acoustic_conservation_equations/spatial_discretization/operators/weak_boundary_conditions.h>
28#include <exadg/acoustic_conservation_equations/user_interface/boundary_descriptor.h>
29#include <exadg/acoustic_conservation_equations/user_interface/enum_types.h>
30#include <exadg/matrix_free/integrators.h>
31#include <exadg/operators/integrator_flags.h>
32#include <exadg/operators/mapping_flags.h>
33
34namespace ExaDG
35{
36namespace Acoustics
37{
38namespace Operators
39{
40template<int dim, typename Number>
41class Kernel
42{
43 using scalar = dealii::VectorizedArray<Number>;
44 using vector = dealii::Tensor<1, dim, dealii::VectorizedArray<Number>>;
45
46 using CellIntegratorP = CellIntegrator<dim, 1, Number>;
47 using CellIntegratorU = CellIntegrator<dim, dim, Number>;
48
49public:
50 static MappingFlags
51 get_mapping_flags()
52 {
53 MappingFlags flags;
54
55 flags.cells = dealii::update_JxW_values | dealii::update_gradients;
56 flags.inner_faces = dealii::update_JxW_values | dealii::update_normal_vectors;
57 flags.boundary_faces =
58 dealii::update_JxW_values | dealii::update_quadrature_points | dealii::update_normal_vectors;
59
60 return flags;
61 }
62
63 /*
64 * Volume flux for the momentum equation, i.e., the term occurring in the volume integral for
65 * weak formulation (performing integration-by-parts)
66 */
67 inline DEAL_II_ALWAYS_INLINE //
68 vector
69 get_volume_flux_weak_momentum(CellIntegratorU const & velocity, unsigned int const q) const
70 {
71 // minus sign due to integration by parts
72 return -velocity.get_value(q);
73 }
74
75 /*
76 * Volume flux for the momentum equation, i.e., the term occurring in the volume integral for
77 * strong formulation (integration-by-parts performed twice)
78 */
79 inline DEAL_II_ALWAYS_INLINE //
80 scalar
81 get_volume_flux_strong_momentum(CellIntegratorU const & velocity, unsigned int const q) const
82 {
83 return velocity.get_divergence(q);
84 }
85
86
87 /*
88 * Volume flux for the mass equation, i.e., the term occurring in the volume integral for
89 * weak formulation (performing integration-by-parts)
90 */
91 inline DEAL_II_ALWAYS_INLINE //
92 scalar
93 get_volume_flux_weak_mass(CellIntegratorP const & pressure, unsigned int const q) const
94 {
95 // minus sign due to integration by parts
96 return -pressure.get_value(q);
97 }
98
99 /*
100 * Volume flux for the mass equation, i.e., the term occurring in the volume integral for
101 * strong formulation (integration-by-parts performed twice)
102 */
103 inline DEAL_II_ALWAYS_INLINE //
104 vector
105 get_volume_flux_strong_mass(CellIntegratorP const & pressure, unsigned int const q) const
106 {
107 return pressure.get_gradient(q);
108 }
109
110 /*
111 * Lax Friedrichs flux for the momentum equation.
112 */
113 inline DEAL_II_ALWAYS_INLINE //
114 vector
115 calculate_lax_friedrichs_flux_momentum(vector const & rho_um,
116 vector const & rho_up,
117 Number const & gamma,
118 scalar const & pm,
119 scalar const & pp,
120 vector const & n) const
121 {
122 return Number{0.5} * (rho_um + rho_up) + gamma * (pm - pp) * n;
123 }
124
125 /*
126 * Lax Friedrichs flux for the mass equation.
127 */
128 inline DEAL_II_ALWAYS_INLINE //
129 scalar
130 calculate_lax_friedrichs_flux_mass(scalar const & pm,
131 scalar const & pp,
132 Number const & tau,
133 vector const & rho_um,
134 vector const & rho_up,
135 vector const & n) const
136 {
137 return Number{0.5} * (pm + pp) + tau * (rho_um - rho_up) * n;
138 }
139};
140
141} // namespace Operators
142
143template<int dim>
145{
147 : dof_index_pressure(0),
148 dof_index_velocity(1),
149 quad_index(0),
150 block_index_pressure(0),
151 block_index_velocity(1),
152 formulation(Formulation::SkewSymmetric),
153 bc(nullptr),
154 speed_of_sound(-1.0)
155 {
156 }
157
158 unsigned int dof_index_pressure;
159 unsigned int dof_index_velocity;
160
161 unsigned int quad_index;
162
163 unsigned int block_index_pressure;
164 unsigned int block_index_velocity;
165
166 Formulation formulation;
167
168 std::shared_ptr<BoundaryDescriptor<dim> const> bc;
169
170 double speed_of_sound;
171};
172
173template<int dim, typename Number>
175{
177
178 using BlockVectorType = dealii::LinearAlgebra::distributed::BlockVector<Number>;
179
180 using scalar = dealii::VectorizedArray<Number>;
181 using vector = dealii::Tensor<1, dim, dealii::VectorizedArray<Number>>;
182
183 using Range = std::pair<unsigned int, unsigned int>;
184
185 using CellIntegratorU = CellIntegrator<dim, dim, Number>;
186 using CellIntegratorP = CellIntegrator<dim, 1, Number>;
187
188 using FaceIntegratorU = FaceIntegrator<dim, dim, Number>;
189 using FaceIntegratorP = FaceIntegrator<dim, 1, Number>;
190
191public:
192 Operator() : evaluation_time(Number{0.0}), tau(Number{0.0}), gamma(Number{0.0})
193 {
194 }
195
196 void
197 initialize(dealii::MatrixFree<dim, Number> const & matrix_free_in,
198 OperatorData<dim> const & data_in)
199 {
200 // Set Matrixfree and OperatorData.
201 matrix_free = &matrix_free_in;
202 data = data_in;
203
204 // Precompute numbers that are needed in kernels.
205 tau = (Number)(0.5 * data_in.speed_of_sound);
206 gamma = (Number)(0.5 / data_in.speed_of_sound);
207
208 // Set integration flags.
209 if(data_in.formulation == Formulation::Weak)
210 {
211 integrator_flags_p.cell_evaluate = dealii::EvaluationFlags::values;
212 integrator_flags_p.cell_integrate = dealii::EvaluationFlags::gradients;
213 integrator_flags_p.face_evaluate = dealii::EvaluationFlags::values;
214 integrator_flags_p.face_integrate = dealii::EvaluationFlags::values;
215
216 integrator_flags_u.cell_evaluate = dealii::EvaluationFlags::values;
217 integrator_flags_u.cell_integrate = dealii::EvaluationFlags::gradients;
218 integrator_flags_u.face_evaluate = dealii::EvaluationFlags::values;
219 integrator_flags_u.face_integrate = dealii::EvaluationFlags::values;
220 }
221 else if(data_in.formulation == Formulation::Strong)
222 {
223 integrator_flags_p.cell_evaluate = dealii::EvaluationFlags::gradients;
224 integrator_flags_p.cell_integrate = dealii::EvaluationFlags::values;
225 integrator_flags_p.face_evaluate = dealii::EvaluationFlags::values;
226 integrator_flags_p.face_integrate = dealii::EvaluationFlags::values;
227
228 integrator_flags_u.cell_evaluate = dealii::EvaluationFlags::gradients;
229 integrator_flags_u.cell_integrate = dealii::EvaluationFlags::values;
230 integrator_flags_u.face_evaluate = dealii::EvaluationFlags::values;
231 integrator_flags_u.face_integrate = dealii::EvaluationFlags::values;
232 }
233 else if(data_in.formulation == Formulation::SkewSymmetric)
234 {
235 integrator_flags_p.cell_evaluate = dealii::EvaluationFlags::gradients;
236 integrator_flags_p.cell_integrate = dealii::EvaluationFlags::gradients;
237 integrator_flags_p.face_evaluate = dealii::EvaluationFlags::values;
238 integrator_flags_p.face_integrate = dealii::EvaluationFlags::values;
239
240 integrator_flags_u.cell_evaluate = dealii::EvaluationFlags::values;
241 integrator_flags_u.cell_integrate = dealii::EvaluationFlags::values;
242 integrator_flags_u.face_evaluate = dealii::EvaluationFlags::values;
243 integrator_flags_u.face_integrate = dealii::EvaluationFlags::values;
244 }
245 else
246 {
247 AssertThrow(false, dealii::ExcMessage("Not implemented."));
248 }
249 }
250
251 void
252 evaluate(BlockVectorType & dst, BlockVectorType const & src, double const time) const
253 {
254 do_evaluate(dst, src, time, true);
255 }
256
257 void
258 evaluate_add(BlockVectorType & dst, BlockVectorType const & src, double const time) const
259 {
260 do_evaluate(dst, src, time, true);
261 }
262
263private:
264 void
265 do_evaluate(BlockVectorType & dst,
266 BlockVectorType const & src,
267 double const time,
268 bool const zero_dst_vector) const
269 {
270 evaluation_time = (Number)time;
271
272 matrix_free->loop(&This::cell_loop,
273 &This::face_loop,
274 &This::boundary_face_loop,
275 this,
276 dst,
277 src,
278 zero_dst_vector,
279 dealii::MatrixFree<dim, Number>::DataAccessOnFaces::values,
280 dealii::MatrixFree<dim, Number>::DataAccessOnFaces::values);
281 }
282
283 void
284 do_cell_integral(CellIntegratorP & pressure, CellIntegratorU & velocity) const
285 {
286 if(data.formulation == Formulation::Weak)
287 {
288 for(unsigned int q : pressure.quadrature_point_indices())
289 {
290 vector const flux_momentum = kernel.get_volume_flux_weak_momentum(velocity, q);
291 scalar const flux_mass = kernel.get_volume_flux_weak_mass(pressure, q);
292
293 pressure.submit_gradient(flux_momentum, q);
294 velocity.submit_divergence(flux_mass, q);
295 }
296 }
297 else if(data.formulation == Formulation::Strong)
298 {
299 for(unsigned int q : pressure.quadrature_point_indices())
300 {
301 scalar const flux_momentum = kernel.get_volume_flux_strong_momentum(velocity, q);
302 vector const flux_mass = kernel.get_volume_flux_strong_mass(pressure, q);
303
304 pressure.submit_value(flux_momentum, q);
305 velocity.submit_value(flux_mass, q);
306 }
307 }
308 else if(data.formulation == Formulation::SkewSymmetric)
309 {
310 for(unsigned int q : pressure.quadrature_point_indices())
311 {
312 vector const flux_momentum = kernel.get_volume_flux_weak_momentum(velocity, q);
313 vector const flux_mass = kernel.get_volume_flux_strong_mass(pressure, q);
314
315 pressure.submit_gradient(flux_momentum, q);
316 velocity.submit_value(flux_mass, q);
317 }
318 }
319 else
320 {
321 AssertThrow(false, dealii::ExcMessage("Not implemented."));
322 }
323 }
324
325
326 template<bool weight_neighbor, // = false for cell centric loops and boundary loops
327 typename ExteriorFaceIntegratorP,
328 typename ExteriorFaceIntegratorU>
329 void
330 do_face_integral(FaceIntegratorP & pressure_m,
331 ExteriorFaceIntegratorP & pressure_p,
332 FaceIntegratorU & velocity_m,
333 ExteriorFaceIntegratorU & velocity_p) const
334 {
335 for(unsigned int q : pressure_m.quadrature_point_indices())
336 {
337 scalar const pm = pressure_m.get_value(q);
338 scalar const pp = pressure_p.get_value(q);
339 vector const rho_um = velocity_m.get_value(q);
340 vector const rho_up = velocity_p.get_value(q);
341 vector const n = pressure_m.normal_vector(q);
342
343 vector const flux_momentum =
344 kernel.calculate_lax_friedrichs_flux_momentum(rho_um, rho_up, gamma, pm, pp, n);
345
346 scalar const flux_mass =
347 kernel.calculate_lax_friedrichs_flux_mass(pm, pp, tau, rho_um, rho_up, n);
348
349 if(data.formulation == Formulation::Weak)
350 {
351 scalar const flux_momentum_weak = flux_momentum * n;
352 vector const flux_mass_weak = flux_mass * n;
353
354 pressure_m.submit_value(flux_momentum_weak, q);
355 velocity_m.submit_value(flux_mass_weak, q);
356
357 if constexpr(weight_neighbor)
358 {
359 // minus signs since n⁺ = - n⁻
360 pressure_p.submit_value(-flux_momentum_weak, q);
361 velocity_p.submit_value(-flux_mass_weak, q);
362 }
363 }
364 else if(data.formulation == Formulation::Strong)
365 {
366 pressure_m.submit_value((flux_momentum - rho_um) * n, q);
367 velocity_m.submit_value((flux_mass - pm) * n, q);
368
369 if constexpr(weight_neighbor)
370 {
371 // minus signs since n⁺ = - n⁻
372 pressure_p.submit_value((rho_up - flux_momentum) * n, q);
373 velocity_p.submit_value((pp - flux_mass) * n, q);
374 }
375 }
376 else if(data.formulation == Formulation::SkewSymmetric)
377 {
378 scalar const flux_momentum_weak = flux_momentum * n;
379
380 pressure_m.submit_value(flux_momentum_weak, q);
381 velocity_m.submit_value((flux_mass - pm) * n, q);
382
383 if constexpr(weight_neighbor)
384 {
385 // minus signs since n⁺ = - n⁻
386 pressure_p.submit_value(-flux_momentum_weak, q);
387 velocity_p.submit_value((pp - flux_mass) * n, q);
388 }
389 }
390 else
391 {
392 AssertThrow(false, dealii::ExcMessage("Not implemented."));
393 }
394 }
395 }
396
397 void
398 cell_loop(dealii::MatrixFree<dim, Number> const & matrix_free_in,
399 BlockVectorType & dst,
400 BlockVectorType const & src,
401 Range const & cell_range) const
402 {
403 CellIntegratorP pressure(matrix_free_in, data.dof_index_pressure, data.quad_index);
404 CellIntegratorU velocity(matrix_free_in, data.dof_index_velocity, data.quad_index);
405
406 for(unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
407 {
408 pressure.reinit(cell);
409 pressure.gather_evaluate(src.block(data.block_index_pressure),
410 integrator_flags_p.cell_evaluate);
411
412 velocity.reinit(cell);
413 velocity.gather_evaluate(src.block(data.block_index_velocity),
414 integrator_flags_u.cell_evaluate);
415
416 do_cell_integral(pressure, velocity);
417
418 pressure.integrate_scatter(integrator_flags_p.cell_integrate,
419 dst.block(data.block_index_pressure));
420 velocity.integrate_scatter(integrator_flags_u.cell_integrate,
421 dst.block(data.block_index_velocity));
422 }
423 }
424
425 void
426 face_loop(dealii::MatrixFree<dim, Number> const & matrix_free_in,
427 BlockVectorType & dst,
428 BlockVectorType const & src,
429 Range const & face_range) const
430 {
431 FaceIntegratorP pressure_m(matrix_free_in, true, data.dof_index_pressure, data.quad_index);
432 FaceIntegratorP pressure_p(matrix_free_in, false, data.dof_index_pressure, data.quad_index);
433
434 FaceIntegratorU velocity_m(matrix_free_in, true, data.dof_index_velocity, data.quad_index);
435 FaceIntegratorU velocity_p(matrix_free_in, false, data.dof_index_velocity, data.quad_index);
436
437 for(unsigned int face = face_range.first; face < face_range.second; face++)
438 {
439 pressure_m.reinit(face);
440 pressure_m.gather_evaluate(src.block(data.block_index_pressure),
441 integrator_flags_p.face_evaluate);
442 pressure_p.reinit(face);
443 pressure_p.gather_evaluate(src.block(data.block_index_pressure),
444 integrator_flags_p.face_evaluate);
445
446 velocity_m.reinit(face);
447 velocity_m.gather_evaluate(src.block(data.block_index_velocity),
448 integrator_flags_u.face_evaluate);
449 velocity_p.reinit(face);
450 velocity_p.gather_evaluate(src.block(data.block_index_velocity),
451 integrator_flags_u.face_evaluate);
452
453 do_face_integral<true>(pressure_m, pressure_p, velocity_m, velocity_p);
454
455 pressure_m.integrate_scatter(integrator_flags_p.face_integrate,
456 dst.block(data.block_index_pressure));
457 pressure_p.integrate_scatter(integrator_flags_p.face_integrate,
458 dst.block(data.block_index_pressure));
459
460 velocity_m.integrate_scatter(integrator_flags_u.face_integrate,
461 dst.block(data.block_index_velocity));
462 velocity_p.integrate_scatter(integrator_flags_u.face_integrate,
463 dst.block(data.block_index_velocity));
464 }
465 }
466
467 void
468 boundary_face_loop(dealii::MatrixFree<dim, Number> const & matrix_free_in,
469 BlockVectorType & dst,
470 BlockVectorType const & src,
471 Range const & face_range) const
472 {
473 FaceIntegratorP pressure_m(matrix_free_in, true, data.dof_index_pressure, data.quad_index);
474 BoundaryFaceIntegratorP<dim, Number> pressure_p(pressure_m, *data.bc);
475
476 FaceIntegratorU velocity_m(matrix_free_in, true, data.dof_index_velocity, data.quad_index);
477 BoundaryFaceIntegratorU<dim, Number> velocity_p(velocity_m,
478 pressure_m,
479 data.speed_of_sound,
480 *data.bc);
481
482 for(unsigned int face = face_range.first; face < face_range.second; face++)
483 {
484 pressure_m.reinit(face);
485 pressure_m.gather_evaluate(src.block(data.block_index_pressure),
486 integrator_flags_p.face_evaluate);
487 pressure_p.reinit(face, evaluation_time);
488
489 velocity_m.reinit(face);
490 velocity_m.gather_evaluate(src.block(data.block_index_velocity),
491 integrator_flags_u.face_evaluate);
492 velocity_p.reinit(face, evaluation_time);
493
494 do_face_integral<false>(pressure_m, pressure_p, velocity_m, velocity_p);
495
496 pressure_m.integrate_scatter(integrator_flags_p.face_integrate,
497 dst.block(data.block_index_pressure));
498 velocity_m.integrate_scatter(integrator_flags_u.face_integrate,
499 dst.block(data.block_index_velocity));
500 }
501 }
502
504
505 mutable Number evaluation_time;
506
507 dealii::SmartPointer<dealii::MatrixFree<dim, Number> const> matrix_free;
509
510 Number tau;
511 Number gamma;
512
513 IntegratorFlags integrator_flags_p;
514 IntegratorFlags integrator_flags_u;
515};
516
517} // namespace Acoustics
518} // namespace ExaDG
519
520
521#endif /*EXADG_ACOUSTIC_CONSERVATION_EQUATIONS_SPATIAL_DISCRETIZATION_OPERATORS_OPERATOR_H_*/
Definition weak_boundary_conditions.h:121
Definition weak_boundary_conditions.h:154
Definition operator.h:175
Definition operator.h:42
Definition driver.cpp:33
Definition operator.h:145
Definition integrator_flags.h:30
Definition mapping_flags.h:31