ExaDG
Loading...
Searching...
No Matches
sound_energy_calculator.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_POSTPROCESSOR_SOUND_ENERGY_CALCULATOR_H_
23#define EXADG_ACOUSTIC_CONSERVATION_EQUATIONS_POSTPROCESSOR_SOUND_ENERGY_CALCULATOR_H_
24
25// deal.II
26#include <deal.II/matrix_free/matrix_free.h>
27
28// ExaDG
29#include <exadg/matrix_free/integrators.h>
30#include <exadg/utilities/create_directories.h>
31#include <exadg/utilities/print_functions.h>
32
33// C/C++
34#include <fstream>
35
36namespace ExaDG
37{
38namespace Acoustics
39{
40struct SoundEnergyCalculatorData
41{
42 SoundEnergyCalculatorData()
43 : directory("output/"),
44 filename("sound_energy.csv"),
45 clear_file(true),
46 density(-1.0),
47 speed_of_sound(-1.0)
48 {
49 }
50
51 void
52 print(dealii::ConditionalOStream & pcout)
53 {
54 if(time_control_data.is_active)
55 {
56 pcout << std::endl << " Calculate sound energy:" << std::endl;
57
58 // only implemented for unsteady problem
59 time_control_data.print(pcout, true /*unsteady*/);
60
61 print_parameter(pcout, "Directory of output files", directory);
62 print_parameter(pcout, "Filename", filename);
63 }
64 }
65
66 TimeControlData time_control_data;
67
68 // directory and filename
69 std::string directory;
70 std::string filename;
71 bool clear_file;
72
73 double density;
74 double speed_of_sound;
75};
76
77template<int dim, typename Number>
78class SoundEnergyCalculator
79{
80 using This = SoundEnergyCalculator<dim, Number>;
81
82 using VectorType = dealii::LinearAlgebra::distributed::Vector<Number>;
83
84 using scalar = dealii::VectorizedArray<Number>;
85 using vector = dealii::Tensor<1, dim, scalar>;
86
87 using CellIntegratorU = CellIntegrator<dim, dim, Number>;
88 using CellIntegratorP = CellIntegrator<dim, 1, Number>;
89
90public:
91 SoundEnergyCalculator(MPI_Comm const & comm)
92 : mpi_comm(comm),
93 clear_files(true),
94 matrix_free(nullptr),
95 dof_index_pressure(0),
96 dof_index_velocity(1),
97 quad_index(0)
98 {
99 }
100
101 void
102 setup(dealii::MatrixFree<dim, Number> const & matrix_free_in,
103 SoundEnergyCalculatorData const & data_in,
104 unsigned int const dof_index_pressure_in,
105 unsigned int const dof_index_velocity_in,
106 unsigned int const quad_index_in)
107 {
108 time_control.setup(data_in.time_control_data);
109
110 matrix_free = &matrix_free_in;
111 data = data_in;
112
113 dof_index_pressure = dof_index_pressure_in;
114 dof_index_velocity = dof_index_velocity_in;
115 quad_index = quad_index_in;
116
117 clear_files = data_in.clear_file;
118
119 if(data_in.time_control_data.is_active)
120 {
121 AssertThrow(data_in.density > 0.0 && data_in.speed_of_sound > 0.0,
122 dealii::ExcMessage("Material parameters not set in SoundEnergyCalculatorData."));
123
124 create_directories(data_in.directory, mpi_comm);
125 }
126 }
127
128 void
129 evaluate(VectorType const & pressure,
130 VectorType const & velocity,
131 double const & time,
132 bool const unsteady)
133 {
134 AssertThrow(unsteady,
135 dealii::ExcMessage(
136 "This postprocessing tool can only be used for unsteady problems."));
137
138 do_evaluate(pressure, velocity, time);
139 }
140
141 TimeControl time_control;
142
143private:
144 void
145 do_evaluate(VectorType const & pressure, VectorType const & velocity, double const time)
146 {
147 double sound_energy = calculate_sound_energy(pressure, velocity);
148
149 // write output file
150 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
151 {
152 std::ostringstream filename;
153 filename << data.directory + data.filename;
154
155 std::ofstream f;
156 if(clear_files == true)
157 {
158 f.open(filename.str().c_str(), std::ios::trunc);
159 f << "Time, Sound energy: E = (1,p*p/(2*rho*c*c)+rho*u*u/2)_Omega" << std::endl;
160 f << "c = " << data.speed_of_sound << std::endl;
161 f << "rho = " << data.density << std::endl;
162 clear_files = false;
163 }
164 else
165 {
166 f.open(filename.str().c_str(), std::ios::app);
167 }
168
169 unsigned int precision = 12;
170 f << std::scientific << std::setprecision(precision) << std::setw(precision + 8) << time
171 << ", " << std::setw(precision + 8) << sound_energy << std::endl;
172 }
173 }
174
175
176 /*
177 * This function calculates the sound energy
178 *
179 * Sound energy: E = (1,p*p/(2*rho*c*c)+rho*u*u/2)_Omega
180 *
181 */
182 double
183 calculate_sound_energy(VectorType const & pressure, VectorType const & velocity) const
184 {
185 Number energy = 0.;
186
187 std::pair<VectorType const *, VectorType const *> const pressure_velocity{
188 std::make_pair(&pressure, &velocity)};
189
190 matrix_free->cell_loop(&This::cell_loop, this, energy, pressure_velocity);
191
192 // sum over all MPI processes
193 double const sound_energy = dealii::Utilities::MPI::sum(energy, mpi_comm);
194
195 return sound_energy;
196 }
197
198 void
199 cell_loop(dealii::MatrixFree<dim, Number> const & matrix_free_in,
200 Number & dst,
201 std::pair<VectorType const *, VectorType const *> const & src_pressure_velocity,
202 std::pair<unsigned int, unsigned int> const & cell_range) const
203 {
204 CellIntegratorP pressure(matrix_free_in, dof_index_pressure, quad_index);
205 CellIntegratorU velocity(matrix_free_in, dof_index_velocity, quad_index);
206
207 Number const rho_inv = static_cast<Number>(1.0 / data.density);
208 Number const rhocc_inv =
209 static_cast<Number>(1.0 / (data.density * data.speed_of_sound * data.speed_of_sound));
210
211 Number energy = 0.0;
212
213 // Loop over all elements
214 for(unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
215 {
216 pressure.reinit(cell);
217 velocity.reinit(cell);
218 pressure.read_dof_values(*src_pressure_velocity.first);
219 velocity.read_dof_values(*src_pressure_velocity.second);
220 pressure.evaluate(dealii::EvaluationFlags::values);
221 velocity.evaluate(dealii::EvaluationFlags::values);
222
223 scalar energy_batch = dealii::make_vectorized_array<Number>(0.);
224
225 for(unsigned int q = 0; q < pressure.n_q_points; ++q)
226 {
227 vector rho_u = velocity.get_value(q);
228 scalar p = pressure.get_value(q);
229
230 // We solve for the scaled velocity (rho * u).
231 // 0.5 * rho * u * u = 0.5 / rho * (rho * u) * (rho * u).
232 energy_batch += Number{0.5} * rho_inv * rho_u * rho_u * velocity.JxW(q);
233
234 energy_batch += Number{0.5} * rhocc_inv * p * p * pressure.JxW(q);
235 }
236
237 // sum over active entries of dealii::VectorizedArray
238 for(unsigned int v = 0; v < matrix_free_in.n_active_entries_per_cell_batch(cell); ++v)
239 energy += energy_batch[v];
240 }
241
242 dst += energy;
243 }
244
245 MPI_Comm const mpi_comm;
246
247 bool clear_files;
248
249 dealii::MatrixFree<dim, Number> const * matrix_free;
251
252 unsigned int dof_index_pressure;
253 unsigned int dof_index_velocity;
254 unsigned int quad_index;
255};
256
257} // namespace Acoustics
258} // namespace ExaDG
259
260#endif /* EXADG_ACOUSTIC_CONSERVATION_EQUATIONS_POSTPROCESSOR_SOUND_ENERGY_CALCULATOR_H_ */
Definition time_control.h:64
Definition driver.cpp:33
void create_directories(std::string const &directory, MPI_Comm const &mpi_comm)
Definition create_directories.h:35
Definition sound_energy_calculator.h:41
Definition time_control.h:40