ExaDG
Loading...
Searching...
No Matches
source_term_calculator.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2025 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_AERO_ACOUSTIC_CALCULATORS_SOURCE_TERM_CALCULATOR_H_
23#define EXADG_AERO_ACOUSTIC_CALCULATORS_SOURCE_TERM_CALCULATOR_H_
24
25// ExaDG
26#include <exadg/matrix_free/integrators.h>
27#include <exadg/utilities/lazy_ptr.h>
28
29namespace ExaDG
30{
31namespace AeroAcoustic
32{
33template<int dim>
35{
36 unsigned int dof_index_pressure;
37 unsigned int dof_index_velocity;
38 unsigned int quad_index;
39
40 // density of the underlying fluid.
41 double density;
42
43 // use material or partial temporal derivative of pressure as source term.
44 bool consider_convection;
45
46 // function if blend in is required.
47 bool blend_in;
48 std::shared_ptr<Utilities::SpatialAwareFunction<dim>> blend_in_function;
49};
50
61template<int dim, typename Number>
62class SourceTermCalculator
63{
64 using This = SourceTermCalculator<dim, Number>;
65 using VectorType = dealii::LinearAlgebra::distributed::Vector<Number>;
66
67 using CellIntegratorScalar = CellIntegrator<dim, 1, Number>;
68 using CellIntegratorVector = CellIntegrator<dim, dim, Number>;
69
70 using scalar = dealii::VectorizedArray<Number>;
71 using qpoint = dealii::Point<dim, dealii::VectorizedArray<Number>>;
72
73public:
74 SourceTermCalculator() : matrix_free(nullptr), time(std::numeric_limits<double>::min())
75 {
76 }
77
78 void
79 setup(dealii::MatrixFree<dim, Number> const & matrix_free_in,
80 SourceTermCalculatorData<dim> const & data_in)
81 {
82 matrix_free = &matrix_free_in;
83 data = data_in;
84 }
85
86 void
87 evaluate_integrate(VectorType & dst,
88 dealii::Function<dim> & analytical_source_term,
89 double const evaluation_time)
90 {
91 time = evaluation_time;
92
93 dst.zero_out_ghost_values();
94
95 analytical_source_term.set_time(time);
96
97 matrix_free->cell_loop(&This::compute_source_term, this, dst, analytical_source_term, true);
98 }
99
100
101 void
102 evaluate_integrate(VectorType & dst,
103 VectorType const & velocity_cfd_in,
104 VectorType const & pressure_cfd_in,
105 VectorType const & pressure_cfd_time_derivative_in,
106 double const evaluation_time)
107 {
108 time = evaluation_time;
109
110 dst.zero_out_ghost_values();
111
112 if(data.consider_convection)
113 {
114 velocity_cfd.reset(velocity_cfd_in);
115 velocity_cfd->update_ghost_values();
116
117 pressure_cfd.reset(pressure_cfd_in);
118 pressure_cfd->update_ghost_values();
119 }
120
121 matrix_free->cell_loop(
122 &This::compute_source_term, this, dst, pressure_cfd_time_derivative_in, true);
123 }
124
125private:
126 void
127 compute_source_term(dealii::MatrixFree<dim, Number> const & matrix_free_in,
128 VectorType & dst,
129 VectorType const & dp_cfd_dt,
130 std::pair<unsigned int, unsigned int> const & cell_range) const
131 {
132 CellIntegratorScalar dpdt(matrix_free_in, data.dof_index_pressure, data.quad_index);
133 CellIntegratorScalar p(matrix_free_in, data.dof_index_pressure, data.quad_index);
134 CellIntegratorVector u(matrix_free_in, data.dof_index_velocity, data.quad_index);
135
136 Number rho = static_cast<Number>(data.density);
137
138 auto get_scaling_factor = get_scaling_function();
139
140 for(unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
141 {
142 dpdt.reinit(cell);
143 dpdt.gather_evaluate(dp_cfd_dt, dealii::EvaluationFlags::values);
144
145 if(data.consider_convection)
146 {
147 p.reinit(cell);
148 p.gather_evaluate(*pressure_cfd, dealii::EvaluationFlags::gradients);
149 u.reinit(cell);
150 u.gather_evaluate(*velocity_cfd, dealii::EvaluationFlags::values);
151
152 for(unsigned int q = 0; q < dpdt.n_q_points; ++q)
153 {
154 scalar flux = -rho * dpdt.get_value(q) + u.get_value(q) * p.get_gradient(q);
155
156 if(data.blend_in)
157 flux *= get_scaling_factor(dpdt.quadrature_point(q));
158
159 dpdt.submit_value(flux, q);
160 }
161 }
162 else
163 {
164 for(unsigned int q = 0; q < dpdt.n_q_points; ++q)
165 {
166 scalar flux = -rho * dpdt.get_value(q);
167
168 if(data.blend_in)
169 flux *= get_scaling_factor(dpdt.quadrature_point(q));
170
171 dpdt.submit_value(flux, q);
172 }
173 }
174
175 dpdt.integrate_scatter(dealii::EvaluationFlags::values, dst);
176 }
177 }
178
179 void
180 compute_source_term(dealii::MatrixFree<dim, Number> const & matrix_free_in,
181 VectorType & dst,
182 dealii::Function<dim> const & analytical_source_term,
183 std::pair<unsigned int, unsigned int> const & cell_range) const
184 {
185 CellIntegratorScalar dpdt(matrix_free_in, data.dof_index_pressure, data.quad_index);
186
187 Number rho = static_cast<Number>(data.density);
188
189 auto get_scaling_factor = get_scaling_function();
190
191 for(unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
192 {
193 dpdt.reinit(cell);
194
195 for(unsigned int q = 0; q < dpdt.n_q_points; ++q)
196 {
197 scalar flux = -rho * FunctionEvaluator<0, dim, Number>::value(analytical_source_term,
198 dpdt.quadrature_point(q));
199
200 if(data.blend_in)
201 flux *= get_scaling_factor(dpdt.quadrature_point(q));
202
203 dpdt.submit_value(flux, q);
204 }
205
206 dpdt.integrate_scatter(dealii::EvaluationFlags::values, dst);
207 }
208 }
209
210 std::function<scalar(qpoint const &)>
211 get_scaling_function() const
212 {
213 // In case we blend in the source term, we check if the scaling is space dependent. Only in that
214 // case we have to evaluate the function in every equadrature point. Otherwise the scaling
215 // is purely temporal and constant during this function.
216 if(data.blend_in)
217 {
218 AssertThrow(data.blend_in_function != nullptr,
219 dealii::ExcMessage("No blend-in function provided."));
220 }
221
222 bool const space_dependent_scaling =
223 data.blend_in_function != nullptr ? data.blend_in_function->varies_in_space(time) : false;
224 Number const pure_temporal_scaling_factor =
225 (not space_dependent_scaling) ? data.blend_in_function->compute_time_factor(time) : 1.0;
226
227 if(space_dependent_scaling)
228 {
229 return [&](qpoint const & q) {
230 return FunctionEvaluator<0, dim, Number>::value(*data.blend_in_function, q, time);
231 };
232 }
233 else
234 {
235 // capture scaling factor by copy
236 return
237 [pure_temporal_scaling_factor](qpoint const &) { return pure_temporal_scaling_factor; };
238 }
239 }
240
241
242 dealii::MatrixFree<dim, Number> const * matrix_free;
243
245
246 lazy_ptr<VectorType> velocity_cfd;
247 lazy_ptr<VectorType> pressure_cfd;
248
249 double time;
250};
251
252} // namespace AeroAcoustic
253} // namespace ExaDG
254
255#endif /*EXADG_AERO_ACOUSTIC_CALCULATORS_SOURCE_TERM_CALCULATOR_H_*/
Definition lazy_ptr.h:29
Definition driver.cpp:33
Definition source_term_calculator.h:35