1 #ifndef ERF_CLOUD_CHAMBER_BUDGET_H_
2 #define ERF_CLOUD_CHAMBER_BUDGET_H_
4 #include <AMReX_Geometry.H>
5 #include <AMReX_MultiFab.H>
6 #include <AMReX_ParallelDescriptor.H>
34 static constexpr
int NumFaces = 2 * AMREX_SPACEDIM;
42 if (cloudy && scalar ==
RhoTheta) {
return "UNSUPPORTED_SOURCE"; }
43 return closes ?
"PASS" :
"FAIL";
52 bool due (
int step)
const noexcept {
65 const amrex::Geometry& geom,
70 const amrex::Real volume = geom.CellSize(0) * geom.CellSize(1) * geom.CellSize(2);
95 const amrex::MultiFab& xflux,
96 const amrex::MultiFab& yflux,
97 const amrex::MultiFab& zflux,
98 const amrex::Geometry& geom,
100 bool trapezoidal =
true)
103 std::array<amrex::Real, NumFaces> current{};
104 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
105 amrex::Box low = geom.Domain();
106 amrex::Box high = low;
107 low.surroundingNodes(d);
108 high.surroundingNodes(d);
109 low.setSmall(d, geom.Domain().smallEnd(d));
110 low.setBig(d, geom.Domain().smallEnd(d));
111 high.setSmall(d, geom.Domain().bigEnd(d)+1);
112 high.setBig(d, geom.Domain().bigEnd(d)+1);
113 const amrex::MultiFab* flux = (d == 0) ? &xflux : ((d == 1) ? &yflux : &zflux);
114 const amrex::Real area = (d == 0) ? geom.CellSize(1)*geom.CellSize(2) :
115 ((d == 1) ? geom.CellSize(0)*geom.CellSize(2) :
116 geom.CellSize(0)*geom.CellSize(1));
117 current[2*d] = flux->sum(low, flux_comp,
true) * area * dt;
118 current[2*d+1] = flux->sum(high, flux_comp,
true) * area * dt;
125 for (
int face = 0; face <
NumFaces; ++face) {
130 }
else if (nrk == 0) {
134 for (
int face = 0; face <
NumFaces; ++face) {
142 std::array<amrex::Real, NumScalars>
144 const amrex::Geometry& geom)
const
146 const amrex::Real volume = geom.CellSize(0) * geom.CellSize(1) * geom.CellSize(2);
147 std::array<amrex::Real, NumScalars> result{};
161 const std::array<amrex::Real, NumScalars>& after)
177 void report (
int step,
double time,
const amrex::MultiFab&
cons,
178 const amrex::Geometry& geom,
bool cloudy)
182 std::array<amrex::Real, NumScalars*NumFaces + NumScalars*3> packed{};
188 for (
int s = 0; s <
NumScalars; ++s) { packed[index++] = current[s]; }
190 amrex::ParallelDescriptor::ReduceRealSum(packed.data(),
static_cast<int>(packed.size()));
192 std::array<std::array<amrex::Real, NumFaces>,
NumScalars> global_faces{};
195 for (
int f = 0; f <
NumFaces; ++f) { global_faces[s][f] = packed[index++]; }
197 std::array<amrex::Real, NumScalars> initial{};
198 std::array<amrex::Real, NumScalars> global_current{};
200 for (
int s = 0; s <
NumScalars; ++s) { initial[s] = packed[index++]; }
201 for (
int s = 0; s <
NumScalars; ++s) { global_current[s] = packed[index++]; }
202 std::array<amrex::Real, NumScalars> global_internal{};
203 for (
int s = 0; s <
NumScalars; ++s) { global_internal[s] = packed[index++]; }
205 if (amrex::ParallelDescriptor::IOProcessor()) {
206 std::ofstream out(
"cloud_chamber_budget.dat", std::ios::app);
207 if (out.tellp() == std::streampos(0)) {
208 out <<
"# start_step start_time end_step end_time scalar units "
209 "xlo xhi ylo yhi zlo zhi net_boundary volume_change "
210 "internal_source residual tolerance status\n";
212 out << std::setprecision(17);
213 const char* names[
NumScalars] = {
"rhoTheta",
"water_vapor",
"cloud_water"};
214 const char*
units[
NumScalars] = {
"conserved_scalar",
"mixing_ratio_density",
"mixing_ratio_density"};
216 std::array<amrex::Real, NumFaces> faces = global_faces[s];
217 amrex::Real net = faces[0] - faces[1] + faces[2] - faces[3] + faces[4] - faces[5];
218 const amrex::Real change = global_current[s] - initial[s];
220 const amrex::Real residual = change - net -
internal;
222 std::abs(initial[s]), std::abs(global_current[s]),
223 std::abs(net), std::abs(
internal)});
228 for (
const auto value : faces) { boundary_scale += std::abs(value); }
231 (effective_operations * scale + boundary_scale + std::abs(
internal));
232 const bool status = std::abs(residual) <= tolerance;
234 static_cast<Scalar>(s), cloudy, status);
236 << step <<
' ' << time <<
' ' << names[s] <<
' ' <<
units[s];
237 for (
const auto value : faces) { out <<
' ' << value; }
238 out <<
' ' << net <<
' ' << change <<
' ' <<
internal <<
' '
239 << residual <<
' ' << tolerance <<
' ' << status_text <<
'\n';
241 std::array<amrex::Real, NumFaces> total_faces{};
242 for (
int f = 0; f <
NumFaces; ++f) {
243 total_faces[f] = global_faces[
RhoQv][f] + global_faces[
RhoQc][f];
245 const amrex::Real total_net = total_faces[0] - total_faces[1] +
246 total_faces[2] - total_faces[3] + total_faces[4] - total_faces[5];
250 const amrex::Real total_residual = total_change - total_net - total_internal;
252 std::abs(total_net), std::abs(total_internal)});
254 for (
const auto value : total_faces) { total_boundary_scale += std::abs(value); }
258 total_boundary_scale + std::abs(total_internal));
259 const bool total_status = std::abs(total_residual) <= total_tolerance;
261 << step <<
' ' << time <<
" total_nonprecipitating_water mixing_ratio_density";
262 for (
const auto value : total_faces) { out <<
' ' << value; }
263 out <<
' ' << total_net <<
' ' << total_change <<
' ' << total_internal <<
' '
264 << total_residual <<
' ' << total_tolerance <<
' '
265 << (total_status ?
"PASS" :
"FAIL") <<
'\n';
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:40
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:46
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:45
std::string units
Definition: ERF_Plotfile2DCatalog.cpp:103
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_CloudChamberBudget.H:31
void capture_stage(int scalar, int nrk, amrex::Real dt, const amrex::MultiFab &xflux, const amrex::MultiFab &yflux, const amrex::MultiFab &zflux, const amrex::Geometry &geom, int flux_comp=0, bool trapezoidal=true)
Definition: ERF_CloudChamberBudget.H:94
bool enabled() const noexcept
Definition: ERF_CloudChamberBudget.H:38
void report(int step, double time, const amrex::MultiFab &cons, const amrex::Geometry &geom, bool cloudy)
Definition: ERF_CloudChamberBudget.H:177
std::array< std::array< amrex::Real, NumFaces >, NumScalars > m_stage0
Definition: ERF_CloudChamberBudget.H:288
std::array< amrex::Real, NumScalars > m_initial_state
Definition: ERF_CloudChamberBudget.H:286
double m_interval_start_time
Definition: ERF_CloudChamberBudget.H:283
std::array< amrex::Real, NumScalars > state_integrals(const amrex::MultiFab &cons, const amrex::Geometry &geom) const
Definition: ERF_CloudChamberBudget.H:143
void set_initial_state(const amrex::MultiFab &cons, const amrex::Geometry &geom, int step=0, double time=0.0)
Definition: ERF_CloudChamberBudget.H:64
CloudChamberBudget(int interval)
Definition: ERF_CloudChamberBudget.H:36
bool m_have_initial
Definition: ERF_CloudChamberBudget.H:284
Scalar
Definition: ERF_CloudChamberBudget.H:33
@ RhoTheta
Definition: ERF_CloudChamberBudget.H:33
@ RhoQv
Definition: ERF_CloudChamberBudget.H:33
@ NumScalars
Definition: ERF_CloudChamberBudget.H:33
@ RhoQc
Definition: ERF_CloudChamberBudget.H:33
std::array< bool, NumScalars > m_have_stage0
Definition: ERF_CloudChamberBudget.H:285
int m_interval
Definition: ERF_CloudChamberBudget.H:281
std::array< amrex::Real, NumScalars > m_internal_source
Definition: ERF_CloudChamberBudget.H:287
static constexpr int NumFaces
Definition: ERF_CloudChamberBudget.H:34
std::array< std::array< amrex::Real, NumFaces >, NumScalars > m_cumulative
Definition: ERF_CloudChamberBudget.H:289
static const char * row_status(Scalar scalar, bool cloudy, bool closes) noexcept
Definition: ERF_CloudChamberBudget.H:40
int m_interval_start_step
Definition: ERF_CloudChamberBudget.H:282
bool due(int step) const noexcept
Definition: ERF_CloudChamberBudget.H:52
void record_internal_source(const std::array< amrex::Real, NumScalars > &before, const std::array< amrex::Real, NumScalars > &after)
Definition: ERF_CloudChamberBudget.H:160
@ cons
Definition: ERF_IndexDefines.H:214
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12