REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_SumIQ.cpp
Go to the documentation of this file.
1#include <iomanip>
2
3#include "REMORA.H"
4#include "AMReX_MultiFab.H"
5
6using namespace amrex;
7/**
8 * @param[in ] time current time
9 */
10void
12{
13 BL_PROFILE("REMORA::sum_integrated_quantities()");
14
15 if (verbose <= 0)
16 return;
17
18 int datwidth = 14;
19 int datprecision = 6;
20 bool local = true;
21
22 Real scalar_ml = zero;
23 Real kineng_ml = zero;
24 Real volume_ml = zero;
25 Real max_vel_ml = zero;
26
27 Real scalar_sl = zero;
28 Real kineng_sl = zero;
29 Real volume_sl = zero;
30 Real max_vel_sl = zero;
31
32 scalar_sl = volWgtSumMF(0,*cons_new[0],Tracer_comp ,local,false);
33
34 for (int lev = 0; lev <= finest_level; lev++)
35 {
36 MultiFab kineng_mf(grids[lev], dmap[lev], 1, 0);
37 MultiFab ones_mf(grids[lev], dmap[lev], 1, 0);
38 ones_mf.setVal(one);
39
40#ifdef _OPENMP
41#pragma omp parallel if (Gpu::notInLaunchRegion())
42#endif
43 for (MFIter mfi(*cons_new[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
44 const Box& bx = mfi.tilebox();
45 const Array4< Real> kineng_arr = kineng_mf.array(mfi);
46 const Array4<const Real> xvel_u_arr = xvel_new[lev]->const_array(mfi);
47 const Array4<const Real> yvel_v_arr = yvel_new[lev]->const_array(mfi);
48 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
49 {
50 // This is the same expression for kinetic energy that is used in ROMS
51 kineng_arr(i,j,k) = fourth * ( xvel_u_arr(i,j,k)*xvel_u_arr(i,j,k) + xvel_u_arr(i+1,j,k)*xvel_u_arr(i+1,j,k) +
52 yvel_v_arr(i,j,k)*yvel_v_arr(i,j,k) + yvel_v_arr(i ,j+1,k)*yvel_v_arr(i,j+1,k));
53 });
54 } // mfi
55
56 const int icomp = 0;
57 Real max_vel_local = std::sqrt(two * kineng_mf.max(icomp));
58
59 if (lev==0) {
60 kineng_sl = volWgtSumMF(lev,kineng_mf,0,local,false);
61 volume_sl = volWgtSumMF(lev,ones_mf ,0,local,false);
62 max_vel_sl = max_vel_local;
63 }
64
65 scalar_ml += volWgtSumMF(lev,*cons_new[lev],Tracer_comp ,local,true);
66 kineng_ml += volWgtSumMF(lev,kineng_mf , 0,local,true);
67 volume_ml += volWgtSumMF(lev,ones_mf , 0,local,true);
68 max_vel_ml = std::max(max_vel_ml, max_vel_local);
69 }
70
71 if (verbose > 0) {
72 const int n_sum_vars = 6;
73 Real sum_vars[n_sum_vars] = {scalar_sl,kineng_sl,volume_sl,scalar_ml,kineng_ml,volume_ml};
74
75 const int n_max_vars = 2;
76 Real max_vars[n_max_vars] = {max_vel_sl, max_vel_ml};
77#ifdef AMREX_LAZY
78 Lazy::QueueReduction([=]() mutable {
79#endif
80 ParallelDescriptor::ReduceRealSum(
81 sum_vars, n_sum_vars, ParallelDescriptor::IOProcessorNumber());
82 ParallelDescriptor::ReduceRealMax(
83 max_vars, n_max_vars, ParallelDescriptor::IOProcessorNumber());
84
85 if (ParallelDescriptor::IOProcessor()) {
86 int i = 0;
87 scalar_sl = sum_vars[i++];
88 kineng_sl = sum_vars[i++];
89 volume_sl = sum_vars[i++];
90 scalar_ml = sum_vars[i++];
91 kineng_ml = sum_vars[i++];
92 volume_ml = sum_vars[i++];
93 int j = 0;
94 max_vel_sl = max_vars[j++];
95 max_vel_ml = max_vars[j++];
96
97 if (finest_level == 0) {
98 amrex::Print() << '\n';
99 amrex::Print() << "TIME = " << std::setw(datwidth) << std::setprecision(datprecision) << time << '\n';
100 amrex::Print() << "SCALAR = " << std::setw(datwidth) << std::setprecision(datprecision) << scalar_sl << '\n';
101 amrex::Print() << "KIN. ENG. = " << std::setw(datwidth) << std::setprecision(datprecision) << kineng_sl << '\n';
102 amrex::Print() << "VOLUME = " << std::setw(datwidth) << std::setprecision(datprecision) << volume_sl << '\n';
103 amrex::Print() << "MAX. VEL. = " << std::setw(datwidth) << std::setprecision(datprecision) << max_vel_sl << '\n';
104 } else {
105 amrex::Print() << '\n';
106 amrex::Print() << "TIME = " << std::setw(datwidth) << std::setprecision(datprecision) << time << '\n';
107 amrex::Print() << "SCALAR SL/ML = " << std::setw(datwidth) << std::setprecision(datprecision) << scalar_sl << ' '
108 << std::setw(datwidth) << std::setprecision(datprecision) << scalar_ml << '\n';
109 amrex::Print() << "KIN. ENG. SL/ML = " << std::setw(datwidth) << std::setprecision(datprecision) << kineng_sl << ' '
110 << std::setw(datwidth) << std::setprecision(datprecision) << kineng_ml << '\n';
111 amrex::Print() << "VOLUME SL/ML = " << std::setw(datwidth) << std::setprecision(datprecision) << volume_sl << ' '
112 << std::setw(datwidth) << std::setprecision(datprecision) << volume_ml << '\n';
113 amrex::Print() << "MAX. VEL. SL/ML = " << std::setw(datwidth) << std::setprecision(datprecision) << max_vel_sl << ' '
114 << std::setw(datwidth) << std::setprecision(datprecision) << max_vel_ml << '\n';
115
116// amrex::Print() << "TIME= " << time << " SCALAR SL/ML = " << scalar_sl << " " << scalar_ml << '\n';
117// amrex::Print() << "TIME= " << time << " KIN. ENG. SL/ML = " << kineng_sl << " " << kineng_ml << '\n';
118// amrex::Print() << "TIME= " << time << " VOLUME SL/ML = " << volume_sl << " " << volume_ml << '\n';
119// amrex::Print() << "TIME= " << time << " MAX. VEL. SL/ML = " << max_vel_sl << " " << max_vel_ml << '\n';
120 }
121
122 if (NumDataLogs() > 0) {
123 std::ostream& data_log1 = DataLog(0);
124 if (data_log1.good()) {
125 if (time == zero) {
126 data_log1 << std::setw(datwidth) << " time";
127 data_log1 << std::setw(datwidth) << " scalar";
128 data_log1 << std::setw(datwidth) << " kineng";
129 data_log1 << std::setw(datwidth) << " volume";
130 data_log1 << std::setw(datwidth) << " max_vel";
131 data_log1 << std::endl;
132 }
133
134 // Write the quantities at this time
135 data_log1 << std::setw(datwidth) << time;
136 data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
137 << scalar_ml;
138 data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
139 << kineng_ml;
140 data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
141 << volume_ml;
142 data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
143 << max_vel_ml;
144 data_log1 << std::endl;
145 }
146 }
147 }
148#ifdef AMREX_LAZY
149 });
150#endif
151 }
152}
153
154/**
155 * @param[in ] lev level to calculate on
156 * @param[in ] mf data to sum over
157 * @param[in ] comp component on which to calculate sum
158 * @param[in ] local whether to do the sum locally
159 * @param[in ] finemask whether to mask fine level
160 */
161Real
162REMORA::volWgtSumMF(int lev, const MultiFab& mf, int comp, bool local, bool finemask)
163{
164 BL_PROFILE("REMORA::volWgtSumMF()");
165
166 Real sum = zero;
167 MultiFab tmp(grids[lev], dmap[lev], 1, 0);
168 MultiFab::Copy(tmp, mf, comp, 0, 1, 0);
169
170 if (lev < finest_level && finemask) {
171 const MultiFab& mask = build_fine_mask(lev+1);
172 MultiFab::Multiply(tmp, mask, 0, 0, 1, 0);
173 }
174
175 MultiFab volume(grids[lev], dmap[lev], 1, 0);
176#ifdef _OPENMP
177#pragma omp parallel if (Gpu::notInLaunchRegion())
178#endif
179 for (MFIter mfi(*cons_new[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
180 const Box& bx = mfi.tilebox();
181 const Array4< Real> vol_arr = volume.array(mfi);
182 const Array4<const Real> Hz = vec_Hz[lev]->const_array(mfi);
183 const Array4<const Real> pm = vec_pm[lev]->const_array(mfi);
184 const Array4<const Real> pn = vec_pn[lev]->const_array(mfi);
185 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
186 {
187 vol_arr(i,j,k) = Hz(i,j,k) / (pm(i,j,0) * pn(i,j,0));
188 });
189 } // mfi
190
191 sum = MultiFab::Dot(tmp, 0, volume, 0, 1, 0, local);
192
193 if (!local)
194 ParallelDescriptor::ReduceRealSum(sum);
195
196 return sum;
197}
198
199/**
200 * @param[in ] lev level to calculate on
201 */
202MultiFab&
204{
205 // Mask for zeroing covered cells
206 AMREX_ASSERT(level > 0);
207
208 const BoxArray& cba = grids[level-1];
209 const DistributionMapping& cdm = dmap[level-1];
210
211 // TODO -- we should make a vector of these a member of REMORA class
212 fine_mask.define(cba, cdm, 1, 0, MFInfo());
213 fine_mask.setVal(one);
214
215 BoxArray fba = grids[level];
216 iMultiFab ifine_mask = makeFineMask(cba, cdm, fba, ref_ratio[level-1], 1, 0);
217
218 const auto fma = fine_mask.arrays();
219 const auto ifma = ifine_mask.arrays();
220 ParallelFor(fine_mask, [=] AMREX_GPU_DEVICE(int bno, int i, int j, int k) noexcept
221 {
222 fma[bno](i,j,k) = ifma[bno](i,j,k);
223 });
224
225 Gpu::synchronize();
226
227 return fine_mask;
228}
229
230/**
231 * @param[in ] nstep what step we're on
232 * @param[in ] lev level to calculate on
233 * @param[in ] dtlev time step for this level
234 * @param[in ] action_interval number of time steps between actions
235 * @param[in ] action_per time interval between actions
236 */
237bool
238REMORA::is_it_time_for_action(int nstep, Real time, Real dtlev, int action_interval, Real action_per)
239{
240 bool int_test = (action_interval > 0 && nstep % action_interval == 0);
241
242 bool per_test = false;
243 if (action_per > zero) {
244 const int num_per_old = static_cast<int>(amrex::Math::floor((time - dtlev) / action_per));
245 const int num_per_new = static_cast<int>(amrex::Math::floor((time) / action_per));
246
247 if (num_per_old != num_per_new) {
248 per_test = true;
249 }
250 }
251
252 return int_test || per_test;
253}
constexpr amrex::Real two
constexpr amrex::Real one
constexpr amrex::Real fourth
constexpr amrex::Real zero
#define Tracer_comp
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:550
amrex::MultiFab fine_mask
Mask that zeroes out values on a coarse level underlying grids on the next finest level.
Definition REMORA.H:1721
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:368
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Hz
Width of cells in the vertical (z-) direction (3D, Hz in ROMS)
Definition REMORA.H:394
amrex::Vector< amrex::MultiFab * > yvel_new
multilevel data container for current step's y velocities (v in ROMS)
Definition REMORA.H:372
amrex::MultiFab & build_fine_mask(int lev)
Make mask to zero out covered cells (for mesh refinement)
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:370
void sum_integrated_quantities(amrex::Real time)
Integrate conserved quantities for diagnostics.
AMREX_FORCE_INLINE int NumDataLogs() noexcept
Definition REMORA.H:1761
amrex::Real volWgtSumMF(int lev, const amrex::MultiFab &mf, int comp, bool local, bool finemask)
Perform the volume-weighted sum.
bool is_it_time_for_action(int nstep, amrex::Real time, amrex::Real dt, int action_interval, amrex::Real action_per)
Decide if it is time to take an action.
AMREX_FORCE_INLINE std::ostream & DataLog(int i)
Helper function for IO stream.
Definition REMORA.H:1754
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:552
static int verbose
Verbosity level of output.
Definition REMORA.H:1639