REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_Plotfile.cpp
Go to the documentation of this file.
1#include <REMORA.H>
2#include "AMReX_Interp_3D_C.H"
3#include "AMReX_PlotFileUtil.H"
4
5using namespace amrex;
6
8
9template<typename V, typename T>
10bool containerHasElement(const V& iterable, const T& query) {
11 return std::find(iterable.begin(), iterable.end(), query) != iterable.end();
12}
13
14// Write plotfile to disk
15void
17{
18#ifndef REMORA_USE_NETCDF
19 amrex::ignore_unused(istep_for_plot);
20#endif
21 Vector<std::string> varnames_3d;
22 varnames_3d.insert(varnames_3d.end(), plot_var_names_3d.begin(), plot_var_names_3d.end());
23
24 Vector<std::string> varnames_2d;
25 varnames_2d.insert(varnames_2d.end(), plot_var_names_2d.begin(), plot_var_names_2d.end());
26
27 Vector<std::string> varnames_2d_rho;
28 Vector<std::string> varnames_2d_u;
29 Vector<std::string> varnames_2d_v;
30
31 const int ncomp_mf_3d = varnames_3d.size();
32 const auto ngrow_vars = IntVect(NGROW-1,NGROW-1,0);
33
34 // These are the ncomp for the 2D cell-centered, x-face-based, y-face-based MultiFabs respectively
35 int ncomp_mf_2d_rho = 0;
36 int ncomp_mf_2d_u = 0;
37 int ncomp_mf_2d_v = 0;
38
39 // Check to see if we found all the requested variables
40 for (auto plot_name : varnames_2d) {
41 {
42 if (plot_name == "zeta" ) {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
43 if (plot_name == "h" ) {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
44 if (plot_name == "f" ) {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
45 if (plot_name == "visc2") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
46 for (int n = 0; n < ncons; ++n) {
47 const std::string diff2_name = std::string("diff2_") + cons_names[n];
48 if (plot_name == diff2_name) {
49 varnames_2d_rho.push_back(plot_name);
51 }
52 }
53 for (int n = 0; n < ncons; ++n) {
54 const std::string stflux_name = std::string("stflux_") + cons_names[n];
55 if (plot_name == stflux_name) {
56 varnames_2d_rho.push_back(plot_name);
58 }
59 }
60 if (plot_name == "lrflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
61 if (plot_name == "lhflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
62 if (plot_name == "srflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
63 if (plot_name == "shflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
64 if (plot_name == "mask_rho") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
65 if (plot_name == "ubar" ) {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
66 if (plot_name == "sustr") {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
67 if (plot_name == "bustr") {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
68 if (plot_name == "mask_u") {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
69 if (plot_name == "vbar" ) {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
70 if (plot_name == "svstr") {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
71 if (plot_name == "bvstr") {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
72 if (plot_name == "mask_v") {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
73 }
74 }
75
76 // We fillpatch here because some of the derived quantities require derivatives
77 // which require ghost cells to be filled. Don't fill the boundary, though.
78 for (int lev = 0; lev <= finest_level; ++lev) {
85 }
86
88 for (int lev = 0; lev <= finest_level; ++lev) {
90 }
91 } else if (plotfile_type == PlotfileType::netcdf) {
92 for (int lev = 0; lev <= finest_level; ++lev) {
94 }
95 } else {
96 amrex::Abort("Don't know this plotfile type");
97 }
98
99 // Array of 3D MultiFabs to hold the plotfile data
101 for (int lev = 0; lev <= finest_level; ++lev) {
103 plotMF[lev].setVal(1.234e20);
104 }
105
106 // Array of 2D MultiFabs to hold the plotfile data
110 for (int lev = 0; lev <= finest_level; ++lev) {
111 BoxArray ba(grids[lev]);
112 BoxList bl2d = ba.boxList();
113 for (auto& b : bl2d) {
114 b.setRange(2,0);
115 }
116 BoxArray ba2d(std::move(bl2d));
117 mf_2d_rho[lev].define(ba2d, dmap[lev], ncomp_mf_2d_rho, IntVect(0,0,0));
118 mf_2d_u[lev].define(ba2d, dmap[lev], ncomp_mf_2d_u , IntVect(0,0,0));
119 mf_2d_v[lev].define(ba2d, dmap[lev], ncomp_mf_2d_v , IntVect(0,0,0));
120 }
121
122
123 // Array of MultiFabs for nodal data
125 if (plot_nodal_data) {
126 for (int lev = 0; lev <= finest_level; ++lev) {
127 BoxArray nodal_grids(grids[lev]); nodal_grids.surroundingNodes();
129 mf_nd[lev].setVal(zero);
130 }
131 }
132
133 // Vector of MultiFabs for face-centered velocity
138 for (int lev = 0; lev <= finest_level; ++lev) {
139 BoxArray grid_stag_u(grids[lev]); grid_stag_u.surroundingNodes(0);
140 BoxArray grid_stag_v(grids[lev]); grid_stag_v.surroundingNodes(1);
141 BoxArray grid_stag_w(grids[lev]); grid_stag_w.surroundingNodes(2);
142 mf_u[lev].define(grid_stag_u, dmap[lev], 1, 0);
143 mf_v[lev].define(grid_stag_v, dmap[lev], 1, 0);
144 mf_w[lev].define(grid_stag_w, dmap[lev], 1, 0);
145 MultiFab::Copy(mf_u[lev],*xvel_new[lev],0,0,1,0);
146 MultiFab::Copy(mf_v[lev],*yvel_new[lev],0,0,1,0);
147 MultiFab::Copy(mf_w[lev],*zvel_new[lev],0,0,1,0);
148 }
149 }
150
151 // Array of MultiFabs for cell-centered velocity
153
154 if (containerHasElement(plot_var_names_3d, "x_velocity") ||
155 containerHasElement(plot_var_names_3d, "y_velocity") ||
156 containerHasElement(plot_var_names_3d, "z_velocity") ||
157 containerHasElement(plot_var_names_3d, "vorticity") ) {
158
159 for (int lev = 0; lev <= finest_level; ++lev) {
160 mf_cc_vel[lev].define(grids[lev], dmap[lev], AMREX_SPACEDIM, IntVect(1,1,0));
161 mf_cc_vel[lev].setVal(zero); // FillBdyCCVels below leaves corners alone
164 mf_cc_vel[lev].FillBoundary(geom[lev].periodicity());
165 } // lev
166
167 // Fill level 0 before the interpolation below carries its ghost cells onto
168 // the finer levels. Matches the fill the vorticity tagging criterion uses.
170
171 // We need ghost cells if computing vorticity
172 amrex::Interpolater* mapper = &cell_cons_interp;
173 if ( containerHasElement(plot_var_names_3d, "vorticity") ) {
174 for (int lev = 1; lev <= finest_level; ++lev) {
179
180 MultiFab mf_to_fill;
181 amrex::FillPatchTwoLevels(mf_cc_vel[lev], mf_cc_vel[lev].nGrowVect(), IntVect(0,0,0),
182 t_new[lev], cmf, ctime, fmf, ftime,
183 0, 0, mf_cc_vel[lev].nComp(), geom[lev-1], geom[lev],
185
186 // Redo the reflections foextrap just overwrote at the domain boundary
188 } // lev
189 } // if
190 } // if
191
192 int icomp_rho = 0;
193 for (auto plot_name : varnames_2d_rho)
194 {
195 if (plot_name == "zeta" ) {
196 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_Zt_avg1[lev],0,icomp_rho,1,0); }
197 icomp_rho++;
198 }
199 if (plot_name == "h" ) {
200 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_h[lev],0,icomp_rho,1,0); }
201 icomp_rho++;
202 }
203 if (plot_name == "f" ) {
204 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_fcor[lev],0,icomp_rho,1,0); }
205 icomp_rho++;
206 }
207 if (plot_name == "visc2" ) {
208 for (int lev = 0; lev <= finest_level; ++lev) {
209 if (vec_visc2_r[lev]->contains_nan(0, 1, 0, true) || vec_visc2_r[lev]->contains_inf(0, 1, 0, true)) {
210 amrex::Abort("Found while writing output: visc2 contains nan or inf");
211 }
212 for (MFIter mfi(mf_2d_rho[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
213 const Box& bx = mfi.validbox();
214 const int K = mfi.index();
215 auto dst = mf_2d_rho[lev].array(mfi, icomp_rho);
216 auto src = vec_visc2_r[lev]->const_array(K);
217 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept {
218 dst(i,j,0) = src(i,j,0);
219 });
220 }
221 }
222 icomp_rho++;
223 }
224 for (int n = 0; n < ncons; ++n) {
225 const std::string diff2_name = std::string("diff2_") + cons_names[n];
226 if (plot_name == diff2_name) {
227 for (int lev = 0; lev <= finest_level; ++lev) {
228 for (MFIter mfi(mf_2d_rho[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
229 const Box& bx = mfi.validbox();
230 const int K = mfi.index();
231 auto dst = mf_2d_rho[lev].array(mfi, icomp_rho);
232 auto src = vec_diff2[lev]->const_array(K);
233 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept {
234 dst(i,j,0) = src(i,j,0,n);
235 });
236 }
237 }
238 icomp_rho++;
239 }
240 }
241 for (int n = 0; n < ncons; ++n) {
242 const std::string stflux_name = std::string("stflux_") + cons_names[n];
243 if (plot_name == stflux_name) {
244 for (int lev = 0; lev <= finest_level; ++lev) {
245 MultiFab::Copy(mf_2d_rho[lev],*vec_stflux[lev],n,icomp_rho,1,0);
246 }
247 icomp_rho++;
248 }
249 }
250 if (plot_name == "lrflux" ) {
252 amrex::Abort("Attempting to write longwave radiation flux to plotfile. Variable not allocated when bulk_fluxes turned off");
253 }
254 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_lrflx[lev],0,icomp_rho,1,0); }
255 icomp_rho++;
256 }
257 if (plot_name == "lhflux" ) {
259 amrex::Abort("Attempting to write latent heat flux to plotfile. Variable not allocated when bulk_fluxes turned off");
260 }
261 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_lhflx[lev],0,icomp_rho,1,0); }
262 icomp_rho++;
263 }
264 if (plot_name == "srflux" ) {
266 amrex::Abort("Attempting to write shortwave radiation flux to plotfile. Variable not allocated when bulk_fluxes turned off");
267 }
268 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_srflx[lev],0,icomp_rho,1,0); }
269 icomp_rho++;
270 }
271 if (plot_name == "shflux" ) {
273 amrex::Abort("Attempting to write sensible heat flux to plotfile. Variable not allocated when bulk_fluxes turned off");
274 }
275 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_shflx[lev],0,icomp_rho,1,0); }
276 icomp_rho++;
277 }
278 if (plot_name == "mask_rho" ) {
279 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_mskr[lev],0,icomp_rho,1,0); }
280 icomp_rho++;
281 }
282 }
283
284 int icomp_u = 0;
285 for (auto plot_name : varnames_2d_u)
286 {
287 if (plot_name == "ubar" ) {
288 for (int lev = 0; lev <= finest_level; ++lev) {
289 MultiFab::Copy(mf_2d_u[lev],*vec_ubar[lev],0,icomp_u,1,0);
290 }
291 icomp_u++;
292 }
293 if (plot_name == "sustr" ) {
294 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_u[lev],*vec_sustr[lev],0,icomp_u,1,0); }
295 icomp_u++;
296 }
297 if (plot_name == "bustr" ) {
298 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_u[lev],*vec_bustr[lev],0,icomp_u,1,0); }
299 icomp_u++;
300 }
301 if (plot_name == "mask_u" ) {
302 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_u[lev],*vec_msku[lev],0,icomp_u,1,0); }
303 icomp_u++;
304 }
305 }
306
307 int icomp_v = 0;
308 for (auto plot_name : varnames_2d_v)
309 {
310 if (plot_name == "vbar" ) {
311 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_vbar[lev],0,icomp_v,1,0); }
312 icomp_v++;
313 }
314 if (plot_name == "svstr" ) {
315 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_svstr[lev],0,icomp_v,1,0); }
316 icomp_v++;
317 }
318 if (plot_name == "bvstr" ) {
319 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_bvstr[lev],0,icomp_v,1,0); }
320 icomp_v++;
321 }
322 if (plot_name == "mask_v" ) {
323 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_mskv[lev],0,icomp_v,1,0); }
324 icomp_v++;
325 }
326 }
327
328 for (int lev = 0; lev <= finest_level; ++lev)
329 {
330 int mf_comp = 0;
331
333
334 // Check each tracer we are about to write, so the abort can name the offender.
335 // One pass per component, rather than an all-component scan repeated once for
336 // every variable in the plot list. nGrowVect() keeps the ghost-cell coverage the
337 // previous no-argument contains_nan() had.
338 for (int i = 0; i < ncons; ++i) {
340 const IntVect ng = cons_new[lev]->nGrowVect();
342 amrex::Abort("Found while writing output: " + cons_names[i] +
343 " contains nan or inf");
344 }
345 }
346
347 // First, copy any of the conserved state variables into the output plotfile
348 for (int i = 0; i < ncons; ++i) {
350 MultiFab::Copy(plotMF[lev],*cons_new[lev],i,mf_comp,1,ngrow_vars);
351 mf_comp++;
352 }
353 } // ncons
354
355 // Next, check for velocities
356 if (containerHasElement(plot_var_names_3d, "x_velocity")) {
357 if (mf_cc_vel[lev].contains_nan(0,1) || mf_cc_vel[lev].contains_inf(0,1)) {
358 amrex::Abort("Found while writing output: u velocity contains nan or inf");
359 }
360 MultiFab::Copy(plotMF[lev], mf_cc_vel[lev], 0, mf_comp, 1, 0);
361 mf_comp += 1;
362 }
363 if (containerHasElement(plot_var_names_3d, "y_velocity")) {
364 if (mf_cc_vel[lev].contains_nan(1,1) || mf_cc_vel[lev].contains_inf(1,1)) {
365 amrex::Abort("Found while writing output: v velocity contains nan or inf");
366 }
367 MultiFab::Copy(plotMF[lev], mf_cc_vel[lev], 1, mf_comp, 1, 0);
368 mf_comp += 1;
369 }
370 if (containerHasElement(plot_var_names_3d, "z_velocity")) {
371 if (mf_cc_vel[lev].contains_nan(2,1) || mf_cc_vel[lev].contains_inf(2,1)) {
372 amrex::Abort("Found while writing output: z velocity contains nan or inf");
373 }
374 MultiFab::Copy(plotMF[lev], mf_cc_vel[lev], 2, mf_comp, 1, 0);
375 mf_comp += 1;
376 }
377
378 // Fill cell-centered location
379 Real dx = Geom()[lev].CellSizeArray()[0];
380 Real dy = Geom()[lev].CellSizeArray()[1];
381
382 // Next, check for location names -- if we write one we write all
383 // Note: the locations must be filled before the derived variables, to match
384 // the order of the names built in set3DPlotVariables
388 {
390#ifdef _OPENMP
391#pragma omp parallel if (Gpu::notInLaunchRegion())
392#endif
393 for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
394 const Box& bx = mfi.tilebox();
395 const Array4<Real> loc_arr = dmf.array(mfi);
396 const Array4<Real const> zp_arr = vec_z_phys_nd[lev]->const_array(mfi);
397
398 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
399 loc_arr(i,j,k,0) = (i+Real(0.5)) * dx;
400 loc_arr(i,j,k,1) = (j+Real(0.5)) * dy;
401 loc_arr(i,j,k,2) = Real(0.125) * (zp_arr(i,j ,k ) + zp_arr(i+1,j ,k ) +
402 zp_arr(i,j+1,k ) + zp_arr(i+1,j+1,k ) +
403 zp_arr(i,j ,k+1) + zp_arr(i+1,j ,k+1) +
404 zp_arr(i,j+1,k+1) + zp_arr(i+1,j+1,k+1) );
405 });
406 } // mfi
408 } // if containerHasElement
409
410 // Define standard process for calling the functions in Derive.cpp
411 auto calculate_derived = [&](const std::string& der_name,
413 {
415 MultiFab dmf(plotMF[lev], make_alias, mf_comp, 1);
416#ifdef _OPENMP
417#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
418#endif
419 for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
420 {
421 const Box& bx = mfi.tilebox();
422 auto& dfab = dmf[mfi];
423
424 if (der_name == "vorticity") {
425 auto const& sfab = mf_cc_vel[lev][mfi];
427 } else {
428 auto const& sfab = (*cons_new[lev])[mfi];
430 }
431 }
432
433 mf_comp++;
434 }
435 };
436
437 // Note: All derived variables must be computed in order of "derived_names" defined in REMORA.H
439
440#ifdef REMORA_USE_PARTICLES
441 const auto& particles_namelist( particleData.getNames() );
442 for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++) {
443 if (containerHasElement(plot_var_names_3d, std::string(particles_namelist[i]+"_count")))
444 {
445 MultiFab temp_dat(plotMF[lev].boxArray(), plotMF[lev].DistributionMap(), 1, 0);
446 temp_dat.setVal(0);
448 MultiFab::Copy(plotMF[lev], temp_dat, 0, mf_comp, 1, 0);
449 mf_comp += 1;
450 }
451 }
452
453 Vector<std::string> particle_mesh_plot_names(0);
454 particleData.GetMeshPlotVarNames( particle_mesh_plot_names );
455 for (int i = 0; i < particle_mesh_plot_names.size(); i++) {
458 MultiFab temp_dat(plotMF[lev].boxArray(), plotMF[lev].DistributionMap(), 1, 1);
459 temp_dat.setVal(0);
460 particleData.GetMeshPlotVar(plot_var_name, temp_dat, lev);
461 MultiFab::Copy(plotMF[lev], temp_dat, 0, mf_comp, 1, 0);
462 mf_comp += 1;
463 }
464 }
465#endif
466
467 if (plot_nodal_data) {
468 MultiFab::Copy(mf_nd[lev],*vec_z_phys_nd[lev],0,2,1,0);
469 Real dz = Geom()[lev].CellSizeArray()[2];
470 int N = Geom()[lev].Domain().size()[2];
471
472#ifdef _OPENMP
473#pragma omp parallel if (Gpu::notInLaunchRegion())
474#endif
475 for (MFIter mfi(mf_nd[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
476 {
477 const Box& bx = mfi.tilebox();
478 Array4<Real> mf_arr = mf_nd[lev].array(mfi);
479 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
480 mf_arr(i,j,k,2) = mf_arr(i,j,k,2) + (N-k) * dz;
481 });
482 } // mfi
483 }
484 } // lev
485
487 {
488
490
491 if (finest_level == 0)
492 {
494 amrex::Print() << "Writing plotfile " << plotfilename << "\n";
506 Geom(),
507 t_new[0], istep, refRatio());
509
510#ifdef REMORA_USE_PARTICLES
511 particleData.Checkpoint(plotfilename);
512#endif
513
514 }
515
516 } else { // multilevel
518 amrex::Print() << "Writing plotfile " << plotfilename << "\n";
519 int lev0 = 0;
520 [[maybe_unused]] int desired_ratio = std::max(std::max(ref_ratio[lev0][0],ref_ratio[lev0][1]),ref_ratio[lev0][2]);
521 bool any_ratio_one = ( ( (ref_ratio[lev0][0] == 1) || (ref_ratio[lev0][1] == 1) ) ||
522 (ref_ratio[lev0][2] == 1) );
523 for (int lev = 1; lev < finest_level; lev++) {
525 ( ( (ref_ratio[lev][0] == 1) || (ref_ratio[lev][1] == 1) ) ||
526 (ref_ratio[lev][2] == 1) );
527 }
532
533 mf2[0].define(grids[0], dmap[0], ncomp_mf_3d, 0);
534
535 // Copy level 0 as is
536 MultiFab::Copy(mf2[0],plotMF[0],0,0,plotMF[0].nComp(),0);
537
538 // Define a new multi-level array of Geometry's so that we pass the new "domain" at lev > 0
540 {Geom()[0].isPeriodic(0),Geom()[0].isPeriodic(1),Geom()[0].isPeriodic(2)};
541 g2[0].define(Geom()[0].Domain(),&(Geom()[0].ProbDomain()),0,periodicity.data());
542
543 r2[0] = IntVect(1,1,ref_ratio[0][0]);
544 for (int lev = 1; lev <= finest_level; ++lev) {
545 if (lev > 1) {
546 r2[lev-1][0] = 1;
547 r2[lev-1][1] = 1;
548 r2[lev-1][2] = r2[lev-2][2] * ref_ratio[lev-1][0];
549 }
550
551 mf2[lev].define(refine(grids[lev],r2[lev-1]), dmap[lev], ncomp_mf_3d, 0);
552
553 // Set the new problem domain
554 Box d2(Geom()[lev].Domain());
555 d2.refine(r2[lev-1]);
556
557 g2[lev].define(d2,&(Geom()[lev].ProbDomain()),0,periodicity.data());
558 }
559
560 // Make a vector of BCRec with default values so we can use it here -- note the values
561 // aren't actually used because we do PCInterp
562 amrex::Vector<amrex::BCRec> null_dom_bcs;
563 null_dom_bcs.resize(mf2[0].nComp());
564 for (int n = 0; n < mf2[0].nComp(); n++) {
565 for (int dir = 0; dir < AMREX_SPACEDIM; dir++) {
568 }
569 }
570
571 // Do piecewise interpolation of mf into mf2
572 for (int lev = 1; lev <= finest_level; ++lev) {
575 0, 0, mf2[lev].nComp(),
576 geom[lev], g2[lev],
578 r2[lev-1], mapper_c, null_dom_bcs, 0);
579 }
580
581 // Define an effective ref_ratio which is isotropic to be passed into WriteMultiLevelPlotfile
583 for (int lev = 0; lev < finest_level; ++lev) {
584 rr[lev] = IntVect(ref_ratio[lev][0],ref_ratio[lev][1],ref_ratio[lev][0]);
585 }
586
598 g2,
599 t_new[0], istep, rr);
601
602#ifdef REMORA_USE_PARTICLES
603 particleData.Checkpoint(plotfilename);
604#endif
605 } else {
617 Geom(),
618 t_new[0], istep, ref_ratio);
620#ifdef REMORA_USE_PARTICLES
621 particleData.Checkpoint(plotfilename);
622#endif
623 }
624 }
625 } // end multi-level
626
627 }
628#ifdef REMORA_USE_NETCDF
630 {
631 // Currently this is hard-coded to plot only level 0
633 int lev = 0;
634 plotMF[0].FillBoundary(geom[lev].periodicity());
636 } // end if plotfile_type == netcdf
637#endif
639 for (int lev = 0; lev <= finest_level; ++lev) {
641 }
642 } else if (plotfile_type == PlotfileType::netcdf) {
643 for (int lev = 0; lev <= finest_level; ++lev) {
645 }
646 } else {
647 amrex::Abort("Don't know this plotfile type");
648 }
649}
650
651/**
652 * @param plotfilename name of plotfile to write to
653 * @param nlevels number of levels to write out
654 * @param mf MultiFab of data to write out
655 * @param mf_nd Multifab of nodal data to write out
656 * @param varnames_3d 3D variable names to write out
657 * @param varnames_2d_rho 2D cell-centered variable names to write out
658 * @param varnames_2d_u 2D x-face-based variable names to write out
659 * @param varnames_2d_v 2D y-face-based variable names to write out
660 * @param my_geom geometry to use for writing plotfile
661 * @param time time at which to output
662 * @param level_steps vector over level of iterations
663 * @param rr refinement ratio to use for writing plotfile
664 * @param versionName version string for VisIt
665 * @param levelPrefix string to prepend to level number
666 * @param mfPrefix subdirectory for multifab data
667 * @param extra_dirs additional subdirectories within plotfile
668 */
669 void
679 const Vector<std::string>& varnames_3d,
680 const Vector<std::string>& varnames_2d_rho,
681 const Vector<std::string>& varnames_2d_u,
682 const Vector<std::string>& varnames_2d_v,
684 Real time,
685 const Vector<int>& level_steps,
686 const Vector<IntVect>& rr,
687 const std::string &versionName,
688 const std::string &levelPrefix,
689 const std::string &mfPrefix,
690 const Vector<std::string>& extra_dirs) const
691{
692 BL_PROFILE("WriteMultiLevelPlotfileWithBathymetry()");
693
694 AMREX_ASSERT(nlevels <= mf.size());
695 AMREX_ASSERT(nlevels <= ref_ratio.size()+1);
697
698 AMREX_ASSERT(mf[0]->nComp() == varnames_3d.size());
699
700 bool callBarrier(false);
702 if (!extra_dirs.empty()) {
703 for (const auto& d : extra_dirs) {
704 const std::string ed = plotfilename+"/"+d;
706 }
707 }
708 ParallelDescriptor::Barrier();
709
710 if (ParallelDescriptor::MyProc() == ParallelDescriptor::NProcs()-1) {
712 for(int level(0); level < boxArrays.size(); ++level) {
713 boxArrays[level] = mf[level]->boxArray();
714 }
715
716 auto f = [this, plotfilename, nlevels, boxArrays, varnames_3d,
719 VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size);
720 std::string HeaderFileName(plotfilename + "/Header");
721 std::ofstream HeaderFile;
722 HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size());
723 HeaderFile.open(HeaderFileName.c_str(), std::ofstream::out |
724 std::ofstream::trunc |
725 std::ofstream::binary);
731 };
732
733 if (AsyncOut::UseAsyncOut()) {
734 AsyncOut::Submit(std::move(f));
735 } else {
736 f();
737 }
738 }
739
740 std::string mf_nodal_prefix = "Nu_nd";
741 std::string mf_uface_prefix = "UFace";
742 std::string mf_vface_prefix = "VFace";
743 std::string mf_wface_prefix = "WFace";
744 std::string mf_2d_rho_prefix = "rho2d";
745 std::string mf_2d_u_prefix = "u2d";
746 std::string mf_2d_v_prefix = "v2d";
747
748 for (int level = 0; level <= finest_level; ++level)
749 {
750 if (AsyncOut::UseAsyncOut()) {
751 VisMF::AsyncWrite(*mf[level],
753 true);
754 if (plot_nodal_data) {
755 VisMF::AsyncWrite(*mf_nd[level],
757 true);
758 }
760 VisMF::AsyncWrite(*mf_u[level],
762 true);
763 VisMF::AsyncWrite(*mf_v[level],
765 true);
766 VisMF::AsyncWrite(*mf_w[level],
768 true);
769 }
770 if (mf_2d_rho[level]->nComp() > 0) {
771 VisMF::AsyncWrite(*mf_2d_rho[level],
773 true);
774 }
775 if (mf_2d_u[level]->nComp() > 0) {
776 VisMF::AsyncWrite(*mf_2d_u[level],
778 true);
779 }
780 if (mf_2d_v[level]->nComp() > 0) {
781 VisMF::AsyncWrite(*mf_2d_v[level],
783 true);
784 }
785 } else {
786 const MultiFab* data;
787 std::unique_ptr<MultiFab> mf_tmp;
788 if (mf[level]->nGrowVect() != 0) {
789 mf_tmp = std::make_unique<MultiFab>(mf[level]->boxArray(),
791 mf[level]->nComp(), 0, MFInfo(),
792 mf[level]->Factory());
793 MultiFab::Copy(*mf_tmp, *mf[level], 0, 0, mf[level]->nComp(), 0);
794 data = mf_tmp.get();
795 } else {
796 data = mf[level];
797 }
799 if (plot_nodal_data) {
801 }
806 }
807 if (mf_2d_rho[level]->nComp() > 0) {
809 }
810 if (mf_2d_u[level]->nComp() > 0) {
812 }
813 if (mf_2d_v[level]->nComp() > 0) {
815 }
816 }
817 } // level
818}
819
820/**
821 * @param HeaderFile output stream for header
822 * @param nlevels number of levels to write out
823 * @param bArray vector over levels of BoxArrays
824 * @param varnames_3d 3D variable names to write out
825 * @param varnames_2d 2D variable names to write out
826 * @param my_geom geometry to use for writing plotfile
827 * @param time time at which to output
828 * @param level_steps vector over level of iterations
829 * @param my_ref_ratio refinement ratio to use for writing plotfile
830 * @param versionName version string for VisIt
831 * @param levelPrefix string to prepend to level number
832 * @param mfPrefix subdirectory for multifab data
833 */
834void
836 [[maybe_unused]] int nlevels,
838 const Vector<std::string> &varnames_3d,
839 const Vector<std::string> &varnames_2d_rho,
840 const Vector<std::string> &varnames_2d_u,
841 const Vector<std::string> &varnames_2d_v,
843 Real time,
844 const Vector<int> &level_steps,
846 const std::string &versionName,
847 const std::string &levelPrefix,
848 const std::string &mfPrefix) const
849{
850 AMREX_ASSERT(nlevels <= bArray.size());
851 AMREX_ASSERT(nlevels <= ref_ratio.size()+1);
853
854 int num_extra_mfs = plot_nodal_data ? 1 : 0; // for nodal, if it is written
856 num_extra_mfs += 3; // for nodal, which is always on
857 }
858
859 HeaderFile.precision(17);
860
861 // ---- this is the generic plot file type name
862 HeaderFile << versionName << '\n';
863
864 HeaderFile << varnames_3d.size() << '\n';
865
866 for (int ivar = 0; ivar < varnames_3d.size(); ++ivar) {
867 HeaderFile << varnames_3d[ivar] << "\n";
868 }
869 HeaderFile << AMREX_SPACEDIM << '\n';
870 HeaderFile << time << '\n';
871 HeaderFile << finest_level << '\n';
872 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
873 HeaderFile << my_geom[0].ProbLo(i) << ' ';
874 }
875 HeaderFile << '\n';
876 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
877 HeaderFile << my_geom[0].ProbHi(i) << ' ';
878 }
879 HeaderFile << '\n';
880 for (int i = 0; i < finest_level; ++i) {
881 HeaderFile << my_ref_ratio[i][0] << ' ';
882 }
883 HeaderFile << '\n';
884 for (int i = 0; i <= finest_level; ++i) {
885 HeaderFile << my_geom[i].Domain() << ' ';
886 }
887 HeaderFile << '\n';
888 for (int i = 0; i <= finest_level; ++i) {
889 HeaderFile << level_steps[i] << ' ';
890 }
891 HeaderFile << '\n';
892 for (int i = 0; i <= finest_level; ++i) {
893 for (int k = 0; k < AMREX_SPACEDIM; ++k) {
894 HeaderFile << my_geom[i].CellSize()[k] << ' ';
895 }
896 HeaderFile << '\n';
897 }
898 HeaderFile << (int) my_geom[0].Coord() << '\n';
899 HeaderFile << "0\n";
900
901 for (int level = 0; level <= finest_level; ++level) {
902 HeaderFile << level << ' ' << bArray[level].size() << ' ' << time << '\n';
903 HeaderFile << level_steps[level] << '\n';
904
905 const IntVect& domain_lo = my_geom[level].Domain().smallEnd();
906 for (int i = 0; i < bArray[level].size(); ++i)
907 {
908 // Need to shift because the RealBox ctor we call takes the
909 // physical location of index (0,0,0). This does not affect
910 // the usual cases where the domain index starts with 0.
911 const Box& b = shift(bArray[level][i], -domain_lo);
913 for (int n = 0; n < AMREX_SPACEDIM; ++n) {
914 HeaderFile << loc.lo(n) << ' ' << loc.hi(n) << '\n';
915 }
916 }
917
919 }
920 HeaderFile << num_extra_mfs << "\n";
921 if (plot_nodal_data) {
922 HeaderFile << "3" << "\n";
923 HeaderFile << "amrexvec_nu_x" << "\n";
924 HeaderFile << "amrexvec_nu_y" << "\n";
925 HeaderFile << "amrexvec_nu_z" << "\n";
926 std::string mf_nodal_prefix = "Nu_nd";
927 for (int level = 0; level <= finest_level; ++level) {
929 }
930 }
932 HeaderFile << "1" << "\n"; // number of components in the multifab
933 HeaderFile << "u_vel" << "\n";
934 std::string mf_uface_prefix = "UFace";
935 for (int level = 0; level <= finest_level; ++level) {
937 }
938 HeaderFile << "1" << "\n";
939 HeaderFile << "v_vel" << "\n";
940 std::string mf_vface_prefix = "VFace";
941 for (int level = 0; level <= finest_level; ++level) {
943 }
944 HeaderFile << "1" << "\n";
945 HeaderFile << "w_vel" << "\n";
946 std::string mf_wface_prefix = "WFace";
947 for (int level = 0; level <= finest_level; ++level) {
949 }
950 }
951
952 if (varnames_2d_rho.size() > 0) {
953 HeaderFile << varnames_2d_rho.size() << "\n"; // number of components in the 2D rho multifab
954 for (int ivar = 0; ivar < varnames_2d_rho.size(); ++ivar) {
955 HeaderFile << varnames_2d_rho[ivar] << "\n";
956 }
957 std::string mf_2d_rho_prefix = "rho2d";
958 for (int level = 0; level <= finest_level; ++level) {
960 }
961 }
962
963 if (varnames_2d_u.size() > 0) {
964 HeaderFile << varnames_2d_u.size() << "\n"; // number of components in the 2D rho multifab
965 for (int ivar = 0; ivar < varnames_2d_u.size(); ++ivar) {
966 HeaderFile << varnames_2d_u[ivar] << "\n";
967 }
968 std::string mf_2d_u_prefix = "u2d";
969 for (int level = 0; level <= finest_level; ++level) {
971 }
972 }
973
974 if (varnames_2d_v.size() > 0) {
975 HeaderFile << varnames_2d_v.size() << "\n"; // number of components in the 2D v multifab
976 for (int ivar = 0; ivar < varnames_2d_v.size(); ++ivar) {
977 HeaderFile << varnames_2d_v[ivar] << "\n";
978 }
979 std::string mf_2d_v_prefix = "v2d";
980 for (int level = 0; level <= finest_level; ++level) {
982 }
983 }
984}
985
986/**
987 * @param lev level to mask
988 * @param fill_value fill value to mask with
989 * @param fill_where value at cells where we will apply the mask. This is necessary because rivers
990 */
991void
993{
994 for (MFIter mfi(*cons_new[lev],false); mfi.isValid(); ++mfi) {
995 Box gbx1 = mfi.growntilebox(IntVect(NGROW+1,NGROW+1,0));
996 Box gbx_coeff = mfi.growntilebox(IntVect(NGROW,NGROW,0));
997 Box ubx = mfi.grownnodaltilebox(0,IntVect(NGROW,NGROW,0));
998 Box vbx = mfi.grownnodaltilebox(1,IntVect(NGROW,NGROW,0));
999
1000 Array4<Real> const& Zt_avg1 = vec_Zt_avg1[lev]->array(mfi);
1001 Array4<Real> const& ubar = vec_ubar[lev]->array(mfi);
1002 Array4<Real> const& vbar = vec_vbar[lev]->array(mfi);
1003 Array4<Real> const& xvel = xvel_new[lev]->array(mfi);
1004 Array4<Real> const& yvel = yvel_new[lev]->array(mfi);
1005 Array4<Real> const& visc2 = vec_visc2_r[lev]->array(mfi);
1006 Array4<Real> const& diff2 = vec_diff2[lev]->array(mfi);
1007 Array4<Real> const& temp = cons_new[lev]->array(mfi,Temp_comp);
1008 Array4<Real> const& salt = cons_new[lev]->array(mfi,Salt_comp);
1009
1010 Array4<Real const> const& mskr = vec_mskr[lev]->array(mfi);
1011 Array4<Real const> const& msku = vec_msku[lev]->array(mfi);
1012 Array4<Real const> const& mskv = vec_mskv[lev]->array(mfi);
1013 const int ncons_local = ncons;
1014
1015 ParallelFor(makeSlab(gbx1,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int )
1016 {
1017 if (mskr(i,j,0) == zero) { // Explicitly compare to 0.0
1018 Zt_avg1(i,j,0) = fill_value;
1019 }
1020 });
1021 ParallelFor(gbx1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1022 {
1023 if (mskr(i,j,0) == zero) { // Explicitly compare to 0.0
1024 temp(i,j,k) = fill_value;
1025 salt(i,j,k) = fill_value;
1026 }
1027 });
1028 ParallelFor(makeSlab(gbx_coeff,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int )
1029 {
1030 if (mskr(i,j,0) == zero) { // Explicitly compare to 0.0
1031 visc2(i,j,0) = fill_value;
1032 for (int n = 0; n < ncons_local; ++n) {
1033 diff2(i,j,0,n) = fill_value;
1034 }
1035 }
1036 });
1037 ParallelFor(makeSlab(ubx,2,0), 3, [=] AMREX_GPU_DEVICE (int i, int j, int , int n)
1038 {
1039 if (msku(i,j,0) == zero && ubar(i,j,0)==fill_where) { // Explicitly compare to 0.0
1040 ubar(i,j,0,n) = fill_value;
1041 }
1042 });
1043 ParallelFor(makeSlab(vbx,2,0), 3, [=] AMREX_GPU_DEVICE (int i, int j, int , int n)
1044 {
1045 if (mskv(i,j,0) == zero && vbar(i,j,0)==fill_where) { // Explicitly compare to 0.0
1046 vbar(i,j,0,n) = fill_value;
1047 }
1048 });
1049 ParallelFor(ubx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1050 {
1051 if (msku(i,j,0) == zero && xvel(i,j,k)==fill_where) { // Explicitly compare to 0.0
1052 xvel(i,j,k) = fill_value;
1053 }
1054 });
1055 ParallelFor(vbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1056 {
1057 if (mskv(i,j,0) == zero && yvel(i,j,k)==fill_where) { // Explicitly compare to 0.0
1058 yvel(i,j,k) = fill_value;
1059 }
1060 });
1061 } // mfi
1062 Gpu::streamSynchronize();
1063}
constexpr amrex::Real zero
Coord
Coordinates.
#define NGROW
#define Temp_comp
#define Salt_comp
mf_h setVal(geomdata.ProbHi(2))
AMREX_ALWAYS_ASSERT(!NSPeriodic||!EWPeriodic)
pp_prob query("traditional", traditional)
bool containerHasElement(const V &iterable, const T &query)
static PhysBCFunctNoOp null_bc_for_fill
static PlotfileType plotfile_type
Native or NetCDF plotfile output.
Definition REMORA.H:1770
int ncons
Number of conserved scalars in the state (temperature + salt + passive scalars + biology tracers)
Definition REMORA.H:1644
static bool plot_staggered_vels
Whether to write the staggered velocities (not averaged to cell centers)
Definition REMORA.H:1764
amrex::Vector< amrex::BCRec > domain_bcs_type
vector (over BCVars) of BCRecs
Definition REMORA.H:1578
amrex::Vector< std::string > cons_names
Names of scalars for plotfile output.
Definition REMORA.H:1709
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_fcor
coriolis factor (2D)
Definition REMORA.H:577
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_h
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:406
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:568
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_lrflx
longwave radiation
Definition REMORA.H:485
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:386
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:557
amrex::Real plotfile_fill_value
fill value for masked arrays in amrex plotfiles
Definition REMORA.H:1723
void writeJobInfo(const std::string &dir) const
Write job info to stdout.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_sustr
Surface stress in the u direction.
Definition REMORA.H:467
amrex::Vector< amrex::MultiFab * > zvel_new
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:392
int foextrap_bc() const noexcept
Definition REMORA.H:1321
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:559
amrex::Vector< amrex::MultiFab * > yvel_new
multilevel data container for current step's y velocities (v in ROMS)
Definition REMORA.H:390
static bool plot_nodal_data
Whether to write nodal data (Nu_nd) to plotfiles.
Definition REMORA.H:1767
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_shflx
sensible heat flux
Definition REMORA.H:491
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:388
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_lhflx
latent heat flux
Definition REMORA.H:489
void FillPatchNoBC(int lev, amrex::Real time, amrex::MultiFab &mf_to_be_filled, amrex::Vector< amrex::MultiFab * > const &mfs, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const bool fill_set=false)
Fill a new MultiFab by copying in phi from valid region and filling ghost cells without applying boun...
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:561
amrex::Vector< int > istep
which step?
Definition REMORA.H:1552
void WriteMultiLevelPlotfileWithBathymetry(const std::string &plotfilename, int nlevels, const amrex::Vector< const amrex::MultiFab * > &mf, const amrex::Vector< const amrex::MultiFab * > &mf_nd, const amrex::Vector< const amrex::MultiFab * > &mf_u, const amrex::Vector< const amrex::MultiFab * > &mf_v, const amrex::Vector< const amrex::MultiFab * > &mf_w, const amrex::Vector< const amrex::MultiFab * > &mf_2d_rho, const amrex::Vector< const amrex::MultiFab * > &mf_2d_u, const amrex::Vector< const amrex::MultiFab * > &mf_2d_v, const amrex::Vector< std::string > &varnames_3d, const amrex::Vector< std::string > &varnames_2d_rho, const amrex::Vector< std::string > &varnames_2d_u, const amrex::Vector< std::string > &varnames_2d_v, const amrex::Vector< amrex::Geometry > &my_geom, amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &rr, const std::string &versionName="HyperCLaw-V1.1", const std::string &levelPrefix="Level_", const std::string &mfPrefix="Cell", const amrex::Vector< std::string > &extra_dirs=amrex::Vector< std::string >()) const
write out particular data to an AMReX plotfile
void mask_arrays_for_write(int lev, amrex::Real fill_value, amrex::Real fill_where)
Mask data arrays before writing output.
static int file_min_digits
Minimum number of digits in plotfile name or chunked history file.
Definition REMORA.H:1761
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_visc2_r
Harmonic viscosity defined on the rho points (centers)
Definition REMORA.H:436
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_svstr
Surface stress in the v direction.
Definition REMORA.H:469
void FillBdyCCVels(int lev, amrex::MultiFab &mf_cc_vel)
Fill the physical boundary conditions for cell-centered velocity (diagnostic only)
void WriteNCPlotFile(int istep, amrex::MultiFab const *plotMF)
Write plotfile using NetCDF (wrapper)
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1556
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1717
void WriteGenericPlotfileHeaderWithBathymetry(std::ostream &HeaderFile, int nlevels, const amrex::Vector< amrex::BoxArray > &bArray, const amrex::Vector< std::string > &varnames_3d, const amrex::Vector< std::string > &varnames_2d_rho, const amrex::Vector< std::string > &varnames_2d_u, const amrex::Vector< std::string > &varnames_2d_v, const amrex::Vector< amrex::Geometry > &my_geom, amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &rr, const std::string &versionName, const std::string &levelPrefix, const std::string &mfPrefix) const
write out header data for an AMReX plotfile
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_vbar
barotropic y velocity (2D)
Definition REMORA.H:549
bool expand_plotvars_to_unif_rr
whether plotfile variables should be expanded to a uniform refinement ratio
Definition REMORA.H:1720
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_ubar
barotropic x velocity (2D)
Definition REMORA.H:547
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_bustr
Bottom stress in the u direction.
Definition REMORA.H:528
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_bvstr
Bottom stress in the v direction.
Definition REMORA.H:530
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_z_phys_nd
z coordinates at psi points (cell nodes)
Definition REMORA.H:461
amrex::Real netcdf_fill_value
fill value for masked arrays in netcdf output
Definition REMORA.H:1725
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:570
amrex::Vector< std::string > plot_var_names_3d
Names of 3D variables to output to AMReX plotfile.
Definition REMORA.H:1705
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_stflux
Surface tracer flux; input arrays.
Definition REMORA.H:496
std::string plot_file_name
Plotfile prefix.
Definition REMORA.H:1685
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Zt_avg1
Average of the free surface, zeta (2D)
Definition REMORA.H:464
void WritePlotFile(int istep)
main driver for writing AMReX plotfiles
amrex::Vector< std::string > plot_var_names_2d
Names of 2D variables to output to AMReX plotfile.
Definition REMORA.H:1707
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_srflx
Shortwave radiation flux [W/m²], defined at rho-points.
Definition REMORA.H:483
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_diff2
Harmonic diffusivity for temperature / salinity.
Definition REMORA.H:438
static constexpr int t
cons component Temp_comp
static constexpr int u
static constexpr int v
static constexpr int null
void remora_dervort(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Array4< const amrex::Real > &pm, const amrex::Array4< const amrex::Real > &pn, const amrex::Array4< const amrex::Real > &, const amrex::Geometry &, amrex::Real, const int *, const int)
void remora_dernull(const amrex::Box &, amrex::FArrayBox &, int, int, const amrex::FArrayBox &, const amrex::Array4< const amrex::Real > &, const amrex::Array4< const amrex::Real > &, const amrex::Array4< const amrex::Real > &, const amrex::Geometry &, amrex::Real, const int *, const int)