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