Perform global reduction and write the budget report to file.
160 std::array<amrex::Real, NumScalars*NumFaces + NumScalars*3> packed{};
166 for (
int s = 0; s <
NumScalars; ++s) { packed[index++] = current[s]; }
168 amrex::ParallelDescriptor::ReduceRealSum(packed.data(),
static_cast<int>(packed.size()));
170 std::array<std::array<amrex::Real, NumFaces>,
NumScalars> global_faces{};
173 for (
int f = 0; f <
NumFaces; ++f) { global_faces[s][f] = packed[index++]; }
175 std::array<amrex::Real, NumScalars> initial{};
176 std::array<amrex::Real, NumScalars> global_current{};
178 for (
int s = 0; s <
NumScalars; ++s) { initial[s] = packed[index++]; }
179 for (
int s = 0; s <
NumScalars; ++s) { global_current[s] = packed[index++]; }
180 std::array<amrex::Real, NumScalars> global_internal{};
181 for (
int s = 0; s <
NumScalars; ++s) { global_internal[s] = packed[index++]; }
183 if (amrex::ParallelDescriptor::IOProcessor()) {
184 std::ofstream out(
"cloud_chamber_budget.dat", std::ios::app);
185 if (out.tellp() == std::streampos(0)) {
186 out <<
"# start_step start_time end_step end_time scalar units "
187 "xlo xhi ylo yhi zlo zhi net_boundary volume_change "
188 "internal_source residual tolerance status\n";
190 out << std::setprecision(17);
191 const char* names[
NumScalars] = {
"rhoTheta",
"water_vapor",
"cloud_water"};
192 const char*
units[
NumScalars] = {
"conserved_scalar",
"mixing_ratio_density",
"mixing_ratio_density"};
194 std::array<amrex::Real, NumFaces> faces = global_faces[s];
195 amrex::Real net = faces[0] - faces[1] + faces[2] - faces[3] + faces[4] - faces[5];
196 const amrex::Real change = global_current[s] - initial[s];
198 const amrex::Real residual = change - net -
internal;
200 std::abs(initial[s]), std::abs(global_current[s]),
201 std::abs(net), std::abs(
internal)});
206 for (
const auto value : faces) { boundary_scale += std::abs(value); }
209 (effective_operations * scale + boundary_scale + std::abs(
internal));
210 const bool status = std::abs(residual) <= tolerance;
211 const char* status_text = status ?
"PASS" :
212 (cloudy && s ==
RhoTheta ?
"UNSUPPORTED_SOURCE" :
"FAIL");
214 << step <<
' ' << time <<
' ' << names[s] <<
' ' <<
units[s];
215 for (
const auto value : faces) { out <<
' ' << value; }
216 out <<
' ' << net <<
' ' << change <<
' ' <<
internal <<
' '
217 << residual <<
' ' << tolerance <<
' ' << status_text <<
'\n';
219 std::array<amrex::Real, NumFaces> total_faces{};
220 for (
int f = 0; f <
NumFaces; ++f) {
221 total_faces[f] = global_faces[
RhoQv][f] + global_faces[
RhoQc][f];
223 const amrex::Real total_net = total_faces[0] - total_faces[1] +
224 total_faces[2] - total_faces[3] + total_faces[4] - total_faces[5];
228 const amrex::Real total_residual = total_change - total_net - total_internal;
230 std::abs(total_net), std::abs(total_internal)});
232 for (
const auto value : total_faces) { total_boundary_scale += std::abs(value); }
236 total_boundary_scale + std::abs(total_internal));
237 const bool total_status = std::abs(total_residual) <= total_tolerance;
239 << step <<
' ' << time <<
" total_nonprecipitating_water mixing_ratio_density";
240 for (
const auto value : total_faces) { out <<
' ' << value; }
241 out <<
' ' << total_net <<
' ' << total_change <<
' ' << total_internal <<
' '
242 << total_residual <<
' ' << total_tolerance <<
' '
243 << (total_status ?
"PASS" :
"FAIL") <<
'\n';
std::string units
Definition: ERF_Plotfile2DCatalog.cpp:103
std::array< amrex::Real, NumScalars > m_initial_state
Definition: ERF_CloudChamberBudget.H:264
double m_interval_start_time
Definition: ERF_CloudChamberBudget.H:261
std::array< amrex::Real, NumScalars > state_integrals(const amrex::MultiFab &cons, const amrex::Geometry &geom) const
Definition: ERF_CloudChamberBudget.H:121
bool m_have_initial
Definition: ERF_CloudChamberBudget.H:262
int m_interval_start_step
Definition: ERF_CloudChamberBudget.H:260
bool due(int step) const noexcept
Definition: ERF_CloudChamberBudget.H:42
@ cons
Definition: ERF_IndexDefines.H:214
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12