REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA.cpp
Go to the documentation of this file.
1/**
2 * \file REMORA.cpp
3 */
4
6#include <REMORA.H>
7
8#include <AMReX_buildInfo.H>
9
10using namespace amrex;
11
12amrex::Real REMORA::startCPUTime = 0.0_rt;
13amrex::Real REMORA::previousCPUTimeUsed = 0.0_rt;
14
15Vector<AMRErrorTag> REMORA::ref_tags;
16
18
19// Time step control
20amrex::Real REMORA::cfl = 0.8_rt;
21amrex::Real REMORA::fixed_dt = -1.0_rt;
22amrex::Real REMORA::fixed_fast_dt = -1.0_rt;
23amrex::Real REMORA::change_max = 1.1_rt;
24
26
27// Dictate verbosity in screen output
28int REMORA::verbose = 0;
29
30// Frequency of diagnostic output
32amrex::Real REMORA::sum_per = -1.0_rt;
33
34// Minimum number of digits in plotfile name
36
37// Do we include staggered velocities in the plotfile?
39
40// Native AMReX vs NetCDF
42
43#ifdef REMORA_USE_NETCDF
44
46
47// Do we write one file per timestep (false) or one file for all timesteps (true)
49
50// NetCDF initialization file
51amrex::Vector<std::string> REMORA::nc_bdry_file = {""}; // Must provide via input
52amrex::Vector<amrex::Vector<std::string>> REMORA::nc_init_file = {{""}}; // Must provide via input
53amrex::Vector<amrex::Vector<std::string>> REMORA::nc_grid_file = {{""}}; // Must provide via input
54#endif
55
56/**
57 * constructor:
58 * - reads in parameters from inputs file
59 * - sizes multilevel arrays and data structures
60 * - initializes BCRec boundary condition object
61 */
63{
64 BL_PROFILE("REMORA::REMORA()");
65
66 if (ParallelDescriptor::IOProcessor()) {
67 const char* remora_hash = amrex::buildInfoGetGitHash(1);
68 const char* amrex_hash = amrex::buildInfoGetGitHash(2);
69 const char* buildgithash = amrex::buildInfoGetBuildGitHash();
70 const char* buildgitname = amrex::buildInfoGetBuildGitName();
71
72 if (strlen(remora_hash) > 0) {
73 amrex::Print() << "\n"
74 << "REMORA git hash: " << remora_hash << "\n";
75 }
76 if (strlen(amrex_hash) > 0) {
77 amrex::Print() << "AMReX git hash: " << amrex_hash << "\n";
78 }
79 if (strlen(buildgithash) > 0) {
80 amrex::Print() << buildgitname << " git hash: " << buildgithash << "\n";
81 }
82
83 amrex::Print() << "\n";
84 }
85
87
88 const std::string& pv3d = "plot_vars_3d"; set3DPlotVariables(pv3d);
89 const std::string& pv2d = "plot_vars_2d"; set2DPlotVariables(pv2d);
90
91 prob = amrex_probinit(geom[0].ProbLo(),geom[0].ProbHi());
92
93 // Geometry on all levels has been defined already.
94
95 // No valid BoxArray and DistributionMapping have been defined.
96 // But the arrays for them have been resized.
97
98 int nlevs_max = max_level + 1;
99
100 istep.resize(nlevs_max, 0);
101 nsubsteps.resize(nlevs_max, 1);
102 for (int lev = 1; lev <= max_level; ++lev) {
103 nsubsteps[lev] = do_substep ? MaxRefRatio(lev-1) : 1;
104 }
105
106 physbcs.resize(nlevs_max);
107
108 t_new.resize(nlevs_max, 0.0_rt);
109 t_old.resize(nlevs_max, -1.e100_rt);
110 dt.resize(nlevs_max, 1.e100_rt);
111
112 cons_new.resize(nlevs_max);
113 cons_old.resize(nlevs_max);
114 xvel_new.resize(nlevs_max);
115 xvel_old.resize(nlevs_max);
116 yvel_new.resize(nlevs_max);
117 yvel_old.resize(nlevs_max);
118 zvel_new.resize(nlevs_max);
119 zvel_old.resize(nlevs_max);
120
121 advflux_reg.resize(nlevs_max);
122
123 // Initialize tagging criteria for mesh refinement
125
126 // We have already read in the ref_Ratio (via amr.ref_ratio =) but we need to enforce
127 // that there is no refinement in the vertical so we test on that here.
128 for (int lev = 0; lev < max_level; ++lev)
129 {
130 amrex::Print() << "Refinement ratio at level " << lev << " set to be " <<
131 ref_ratio[lev][0] << " " << ref_ratio[lev][1] << " " << ref_ratio[lev][2] << std::endl;
132
133 if (ref_ratio[lev][2] != 1)
134 {
135 amrex::Print() << "********************************************************************************" << std::endl;
136 amrex::Print() << "We don't allow refinement in the vertical -- make sure to set ref_ratio = 1 in z" << std::endl;
137 amrex::Print() << "It's possible you set amr.ref_ratio when you meant to set amr.ref_ratio_vect " << std::endl;
138 amrex::Print() << "********************************************************************************" << std::endl;
139 amrex::Abort();
140 }
141 }
142}
143
144REMORA::REMORA (const amrex::RealBox& rb, int max_level_in, const amrex::Vector<int>& n_cell_in, int coord, const amrex::Vector<amrex::IntVect>& ref_ratio_in, const amrex::Array<int,AMREX_SPACEDIM>& is_per, std::string prefix)
145 : amrex::AmrCore (rb, max_level_in, n_cell_in, coord, ref_ratio_in, is_per)
146{
147 BL_PROFILE("REMORA::REMORA(explicit)");
148 pp_prefix = prefix;
149
150 if (ParallelDescriptor::IOProcessor()) {
151 const char* remora_hash = amrex::buildInfoGetGitHash(1);
152 const char* amrex_hash = amrex::buildInfoGetGitHash(2);
153 const char* buildgithash = amrex::buildInfoGetBuildGitHash();
154 const char* buildgitname = amrex::buildInfoGetBuildGitName();
155
156 if (strlen(remora_hash) > 0) {
157 amrex::Print() << "\n"
158 << "REMORA git hash: " << remora_hash << "\n";
159 }
160 if (strlen(amrex_hash) > 0) {
161 amrex::Print() << "AMReX git hash: " << amrex_hash << "\n";
162 }
163 if (strlen(buildgithash) > 0) {
164 amrex::Print() << buildgitname << " git hash: " << buildgithash << "\n";
165 }
166
167 amrex::Print() << "\n";
168 }
169
171
172 const std::string& pv3d = "plot_vars_3d"; set3DPlotVariables(pv3d);
173 const std::string& pv2d = "plot_vars_2d"; set2DPlotVariables(pv2d);
174
175 prob = amrex_probinit(geom[0].ProbLo(),geom[0].ProbHi());
176
177 int nlevs_max = max_level + 1;
178
179 istep.resize(nlevs_max, 0);
180 nsubsteps.resize(nlevs_max, 1);
181 for (int lev = 1; lev <= max_level; ++lev) {
182 nsubsteps[lev] = do_substep ? MaxRefRatio(lev-1) : 1;
183 }
184
185 physbcs.resize(nlevs_max);
186
187 t_new.resize(nlevs_max, 0.0_rt);
188 t_old.resize(nlevs_max, -1.e100_rt);
189 dt.resize(nlevs_max, 1.e100_rt);
190
191 cons_new.resize(nlevs_max);
192 cons_old.resize(nlevs_max);
193 xvel_new.resize(nlevs_max);
194 xvel_old.resize(nlevs_max);
195 yvel_new.resize(nlevs_max);
196 yvel_old.resize(nlevs_max);
197 zvel_new.resize(nlevs_max);
198 zvel_old.resize(nlevs_max);
199
200 advflux_reg.resize(nlevs_max);
201
203
204 for (int lev = 0; lev < max_level; ++lev)
205 {
206 amrex::Print() << "Refinement ratio at level " << lev << " set to be " <<
207 ref_ratio[lev][0] << " " << ref_ratio[lev][1] << " " << ref_ratio[lev][2] << std::endl;
208
209 if (ref_ratio[lev][2] != 1)
210 {
211 amrex::Print() << "********************************************************************************" << std::endl;
212 amrex::Print() << "We don't allow refinement in the vertical -- make sure to set ref_ratio = 1 in z" << std::endl;
213 amrex::Print() << "It's possible you set amr.ref_ratio when you meant to set amr.ref_ratio_vect " << std::endl;
214 amrex::Print() << "********************************************************************************" << std::endl;
215 amrex::Abort();
216 }
217 }
218}
219
221{
222}
223
224void
226{
227 cons_names.clear();
228 cons_names.reserve(ncons);
229 cons_names.emplace_back("temp");
230 cons_names.emplace_back("salt");
231 cons_names.emplace_back("tracer");
232 for (int i = 1; i < nscalar; ++i) {
233 cons_names.emplace_back("tracer_" + std::to_string(i));
234 }
235}
236
237void
239{
240 BL_PROFILE("REMORA::Evolve()");
241 Real cur_time = t_new[0];
242
243 // Take one coarse timestep by calling timeStep -- which recursively calls timeStep
244 // for finer levels (with or without subcycling)
245 for (int step = istep[0]; step < max_step && cur_time < stop_time; ++step)
246 {
247 amrex::Print() << "\nCoarse STEP " << step+1 << " starts ..." << std::endl;
248
249 ComputeDt();
250
251 int lev = 0;
252 int iteration = 1;
253 auto dEvolveTime0 = amrex::second();
254
255 if (max_level == 0) {
256 timeStep(lev, cur_time, iteration);
257 }
258 else {
259 timeStepML(cur_time, iteration);
260 }
261
262 cur_time += dt[0];
263
264 amrex::Print() << "Coarse STEP " << step+1 << " ends." << " TIME = " << cur_time
265 << " DT = " << dt[0] << std::endl;
266
267 if (verbose > 0)
268 {
269 auto dEvolveTime = amrex::second() - dEvolveTime0;
270 ParallelDescriptor::ReduceRealMax(dEvolveTime,ParallelDescriptor::IOProcessorNumber());
271 amrex::Print() << "Timestep time = " << dEvolveTime << " seconds." << '\n';
272 }
273
274 if ( (plot_int > 0 && (step+1 - last_plot_file_step) == plot_int ) ||
275 (plot_int_time > 0 && (cur_time >= (last_plot_file_time + plot_int_time))) )
276 {
277 last_plot_file_step = step+1;
278 last_plot_file_time = cur_time;
279 WritePlotFile(step+1);
281 }
282
283 if ((check_int > 0 && (step+1 - last_check_file_step) == check_int)
284 || (check_int_time > 0 && cur_time >= (last_check_file_time + check_int_time))) {
285 last_check_file_step = step+1;
286 last_check_file_time = cur_time;
288 }
289
290 post_timestep(step, cur_time, dt[0]);
291
292#ifdef AMREX_MEM_PROFILING
293 {
294 std::ostringstream ss;
295 ss << "[STEP " << step+1 << "]";
296 MemProfiler::report(ss.str());
297 }
298#endif
299
300 if (cur_time >= stop_time - 1.e-6*dt[0]) break;
301 }
302
303 if ( (plot_int > 0 || plot_int_time > 0.0) && istep[0] > last_plot_file_step)
304 {
307 }
308
309 if ((check_int > 0 || check_int_time > 0.0) && istep[0] > last_check_file_step) {
311 }
312}
313
314/**
315 * @param[in ] nstep which step we're on
316 * @param[in ] time current time
317 * @param[in ] dt_lev0 time step on level 0
318 */
319void
320REMORA::post_timestep (int nstep, Real time, Real dt_lev0)
321{
322 BL_PROFILE("REMORA::post_timestep()");
323
324#ifdef REMORA_USE_PARTICLES
325 particleData.Redistribute();
326#endif
327
329 {
330 for (int lev = finest_level-1; lev >= 0; lev--)
331 {
332 // This call refluxes from the lev/lev+1 interface onto lev
333 //getAdvFluxReg(lev+1)->Reflux(*cons_new[lev], 0, 0, NCONS);
334
335 // We need to do this before anything else because refluxing changes the
336 // values of coarse cells underneath fine grids with the assumption they'll
337 // be over-written by averaging down
338 //
339 AverageDownTo(lev);
340 }
341 }
342
343 if (is_it_time_for_action(nstep, time, dt_lev0, sum_interval, sum_per)) {
345 }
346}
347
348/**
349 * This is called from main.cpp and handles all initialization, whether from start or restart
350 */
351void
353{
354 BL_PROFILE("REMORA::InitData()");
355 // Initialize the start time for our CPU-time tracker
356 startCPUTime = Real(ParallelDescriptor::second());
357
358 // Map the words in the inputs file to BC types, then translate
359 // those types into what they mean for each variable
360 init_bcs();
361
362 // Init vertical stretching coeffs
364
367 last_plot_file_time = -1.0_rt;
368 last_check_file_time = -1.0_rt;
369
370 if (restart_chkfile == "") {
371 // start simulation from the beginning
372
373 InitFromScratch(start_time);
374
376 AverageDown();
377 }
378
379 } else { // Restart from a checkpoint
380
381 restart();
382
383 }
384#ifdef REMORA_USE_MOAB
385 InitMOABMesh();
386#endif
387 // Initialize flux registers (whether we start from scratch or restart)
389 advflux_reg[0] = nullptr;
390 for (int lev = 1; lev <= finest_level; lev++)
391 {
392 advflux_reg[lev].reset( new YAFluxRegister(grids[lev], grids[lev-1],
393 dmap[lev], dmap[lev-1],
394 geom[lev], geom[lev-1],
395 ref_ratio[lev-1], lev, ncons));
396 }
397 }
398
399 // Fill ghost cells/faces
400 for (int lev = 0; lev <= finest_level; ++lev)
401 {
402 if (lev > 0 && cf_width >= 0) {
404 }
405
406 if (restart_chkfile == "") {
407 FillPatch(lev, t_new[lev], *cons_new[lev], cons_new, BCVars::cons_bc, BdyVars::t, 0, true, false,0,0,0.0,*cons_new[lev]);
408 FillPatch(lev, t_new[lev], *xvel_new[lev], xvel_new, xvel_bc(), BdyVars::u, 0, true, false,0,0,0.0,*xvel_new[lev]);
409 FillPatch(lev, t_new[lev], *yvel_new[lev], yvel_new, yvel_bc(), BdyVars::v, 0, true, false,0,0,0.0,*yvel_new[lev]);
410 FillPatch(lev, t_new[lev], *zvel_new[lev], zvel_new, zvel_bc(), BdyVars::null, 0, true, false);
411
412 // Copy from new into old just in case when initializing from scratch
413 int ngs = cons_new[lev]->nGrow();
414 int ngvel = xvel_new[lev]->nGrow();
415 MultiFab::Copy(*cons_old[lev],*cons_new[lev],0,0,ncons,ngs);
416 MultiFab::Copy(*xvel_old[lev],*xvel_new[lev],0,0,1,ngvel);
417 MultiFab::Copy(*yvel_old[lev],*yvel_new[lev],0,0,1,ngvel);
418 MultiFab::Copy(*zvel_old[lev],*zvel_new[lev],0,0,1,IntVect(ngvel,ngvel,0));
419 }
420 } // lev
421
422 // Check for additional plotting variables that are available after
423 // particle containers are setup.
424 const std::string& pv3d = "plot_vars_3d"; append3DPlotVariables(pv3d);
425 const std::string& pv2d = "plot_vars_2d"; append2DPlotVariables(pv2d);
426
427 if (restart_chkfile == "" && (check_int > 0 || check_int_time > 0.0_rt))
428 {
431 }
432
433 if ( (restart_chkfile == "") ||
435 {
436 if (plot_int > 0 || plot_int_time > 0.0)
437 {
438 int step0 = 0;
439 WritePlotFile(step0);
442 }
443 }
444
447 }
448
449 ComputeDt();
450
451}
452
453/**
454 * @param[in ] lev level to operate on
455 */
456void
458{
459 BL_PROFILE("REMORA::Construct_REMORAFillPatchers()");
460 amrex::Print() << ":::Construct_REMORAFillPatchers " << lev << std::endl;
461
462 auto& ba_fine = cons_new[lev ]->boxArray();
463 auto& ba_crse = cons_new[lev-1]->boxArray();
464 auto& dm_fine = cons_new[lev ]->DistributionMap();
465 auto& dm_crse = cons_new[lev-1]->DistributionMap();
466
467 BoxList bl2d_fine = ba_fine.boxList();
468 for (auto& b : bl2d_fine) {
469 b.setRange(2,0);
470 }
471 BoxArray ba2d_fine(std::move(bl2d_fine));
472
473 BoxList bl2d_crse = ba_crse.boxList();
474 for (auto& b : bl2d_crse) {
475 b.setRange(2,0);
476 }
477 BoxArray ba2d_crse(std::move(bl2d_crse));
478
479 int ncomp = cons_new[lev]->nComp();
480
481 FPr_c.emplace_back(ba_fine, dm_fine, geom[lev] ,
482 ba_crse, dm_crse, geom[lev-1],
483 -cf_width, -cf_set_width, ncomp, &cell_cons_interp);
484 FPr_u.emplace_back(convert(ba_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
485 convert(ba_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
486 -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
487 FPr_v.emplace_back(convert(ba_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
488 convert(ba_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
489 -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
490 FPr_w.emplace_back(convert(ba_fine, IntVect(0,0,1)), dm_fine, geom[lev] ,
491 convert(ba_crse, IntVect(0,0,1)), dm_crse, geom[lev-1],
492 -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
493
494 FPr_ubar.emplace_back(convert(ba2d_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
495 convert(ba2d_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
496 -cf_width, -cf_set_width, 3, &face_cons_linear_interp);
497 FPr_vbar.emplace_back(convert(ba2d_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
498 convert(ba2d_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
499 -cf_width, -cf_set_width, 3, &face_cons_linear_interp);
500}
501
502/**
503 * @param[in ] lev level to operate on
504 */
505void
507{
508 BL_PROFILE("REMORA::Define_REMORAFillPatchers()");
509 amrex::Print() << ":::Define_REMORAFillPatchers " << lev << std::endl;
510
511 auto& ba_fine = cons_new[lev ]->boxArray();
512 auto& ba_crse = cons_new[lev-1]->boxArray();
513 auto& dm_fine = cons_new[lev ]->DistributionMap();
514 auto& dm_crse = cons_new[lev-1]->DistributionMap();
515
516 BoxList bl2d_fine = ba_fine.boxList();
517 for (auto& b : bl2d_fine) {
518 b.setRange(2,0);
519 }
520 BoxArray ba2d_fine(std::move(bl2d_fine));
521
522 BoxList bl2d_crse = ba_crse.boxList();
523 for (auto& b : bl2d_crse) {
524 b.setRange(2,0);
525 }
526 BoxArray ba2d_crse(std::move(bl2d_crse));
527
528
529 int ncomp = cons_new[lev]->nComp();
530
531 FPr_c[lev-1].Define(ba_fine, dm_fine, geom[lev] ,
532 ba_crse, dm_crse, geom[lev-1],
533 -cf_width, -cf_set_width, ncomp, &cell_cons_interp);
534 FPr_u[lev-1].Define(convert(ba_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
535 convert(ba_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
536 -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
537 FPr_v[lev-1].Define(convert(ba_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
538 convert(ba_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
539 -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
540 FPr_w[lev-1].Define(convert(ba_fine, IntVect(0,0,1)), dm_fine, geom[lev] ,
541 convert(ba_crse, IntVect(0,0,1)), dm_crse, geom[lev-1],
542 -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
543
544 FPr_ubar[lev-1].Define(convert(ba2d_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
545 convert(ba2d_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
546 -cf_width, -cf_set_width, 3, &face_cons_linear_interp);
547 FPr_vbar[lev-1].Define(convert(ba2d_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
548 convert(ba2d_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
549 -cf_width, -cf_set_width, 3, &face_cons_linear_interp);
550}
551
552void
554{
555 BL_PROFILE("REMORA::restart()");
557
558 // We set this here so that we don't over-write the checkpoint file we just started from
560}
561
562/**
563 * @param[in ] lev level to operate on
564 */
565void
567{
568 BL_PROFILE("REMORA::set_zeta()");
570 prob->init_analytic_zeta(lev, geom[lev], solverChoice, *this, *vec_zeta[lev]);
571
572#ifdef REMORA_USE_NETCDF
573 } else if (solverChoice.ic_type == IC_Type::netcdf) {
574 if (lev == 0) {
575 amrex::Print() << "Calling init_zeta_from_netcdf on level " << lev << std::endl;
577 amrex::Print() << "Sea surface height loaded from netcdf file \n " << std::endl;
578 } else {
579 Real dummy_time = 0.0_rt;
580 FillCoarsePatch(lev,dummy_time,vec_zeta[lev].get(), vec_zeta[lev-1].get(),BCVars::cons_bc);
581 }
582#endif
583 } else {
584 Abort("Don't know this ic_type!");
585 }
586 vec_zeta[lev]->FillBoundary(geom[lev].periodicity());
587 set_zeta_average(lev);
588}
589
590/**
591 * @param[in ] lev level to operate on
592 */
593void
595{
596 BL_PROFILE("REMORA::bathymetry()");
597 // Only set bathymetry on level 0, and interpolate for finer levels
598 if (lev==0) {
601 // If grid data is not defined on a level > 0 (negative level) then
602 // initialize from low-resolution grid normally. Otherwise use high-resolution
603 // grid data averaged down to level 0
604 } else if (hires_grid_level < 0) {
606 prob->init_analytic_bathymetry(lev, geom[lev], solverChoice, *this, *vec_h[lev]);
607 } else if (solverChoice.ic_type == IC_Type::netcdf) {
608#ifdef REMORA_USE_NETCDF
609 amrex::Print() << "Calling init_bathymetry_from_netcdf " << std::endl;
611 amrex::Print() << "Bathymetry loaded from netcdf file \n " << std::endl;
612 amrex::Print() << "Calling init_grid_vars_from_netcdf " << std::endl;
614 amrex::Print() << "Grid variables loaded from netcdf file \n " << std::endl;
615#endif
616 } else {
617 amrex::Abort("Unknown IC_Type");
618 }
619 } else {
622 }
623 // Need FillBoundary to fill at grid-grid boundaries, and EnforcePeriodicity
624 // to make sure ghost cells in the domain corners are consistent.
625 vec_h[lev]->FillBoundary(geom[lev].periodicity());
626 vec_h[lev]->EnforcePeriodicity(geom[lev].periodicity());
627 } else {
628 // If our level is higher than the high resolution grid or initialization
629 // is analytic, interpolate from level below. Otherwise, copy over the bathymetry
630 // data that has been averaged down
631 if (lev > hires_grid_level) {
632 Real dummy_time = 0.0_rt;
633 FillCoarsePatch(lev,dummy_time,vec_h[lev].get(), vec_h[lev-1].get(),BCVars::cons_bc);
634 } else {
636 vec_h[lev]->FillBoundary(geom[lev].periodicity());
637 vec_h[lev]->EnforcePeriodicity(geom[lev].periodicity());
638 }
639 }
640 set_grid_scale(lev);
641}
642
643/**
644 * @param[in ] lev level to operate on
645 */
646void
648 Real dummy_time = 0.0_rt;
649 // Note: don't understand why the grow vector args aren't vec_h and then vec_h_full_domain
650 ParallelCopy(*vec_h[lev].get(), *vec_h_full_domain[lev].get(), 0, 0, 1,vec_h_full_domain[lev]->nGrowVect(),vec_h[lev]->nGrowVect());
651 ParallelCopy(*vec_h[lev].get(), *vec_h_full_domain[lev].get(), 0, 1, 1,vec_h_full_domain[lev]->nGrowVect(),vec_h[lev]->nGrowVect());
652 FillPatch(lev,dummy_time,*vec_h[lev],GetVecOfPtrs(vec_h),
654 BdyVars::null,0,false,true,1);
655 FillPatch(lev,dummy_time,*vec_h[lev],GetVecOfPtrs(vec_h),
657 BdyVars::null,1,false,true,1);
658}
659
660/**
661 * @param[in ] lev level to operate on
662 */
663void
665 Real dummy_time = 0.0_rt;
666 ParallelCopy(*vec_pm[lev].get(), *vec_pm_full_domain[lev].get(), 0, 0, 1,
667 vec_pm_full_domain[lev]->nGrowVect(),vec_pm[lev]->nGrowVect());
668 ParallelCopy(*vec_pn[lev].get(), *vec_pn_full_domain[lev].get(), 0, 0, 1,
669 vec_pn_full_domain[lev]->nGrowVect(),vec_pn[lev]->nGrowVect());
670 FillPatch(lev,dummy_time,*vec_pm[lev],GetVecOfPtrs(vec_pm),
672 BdyVars::null,0,false,true);
673 FillPatch(lev,dummy_time,*vec_pn[lev],GetVecOfPtrs(vec_pn),
675 BdyVars::null,0,false,true);
676}
677
678/**
679 * @param[in ] lev level to operate on
680 */
681void
683 BL_PROFILE("REMORA::set_coriolis()");
686 prob->init_analytic_coriolis(lev, geom[lev], solverChoice, *this, *vec_fcor[lev]);
689#ifdef REMORA_USE_NETCDF
691 if (lev == 0) {
692 amrex::Print() << "Calling init_coriolis_from_netcdf " << std::endl;
694 amrex::Print() << "Coriolis loaded from netcdf file \n" << std::endl;
695 } else {
696 Real dummy_time = 0.0_rt;
697 FillCoarsePatch(lev,dummy_time,vec_fcor[lev].get(), vec_fcor[lev-1].get(),BCVars::cons_bc);
698 }
699#endif
700 } else {
701 Abort("Don't know this coriolis_type!");
702 }
703
704 Real time = 0.0_rt;
705 FillPatch(lev, time, *vec_fcor[lev], GetVecOfPtrs(vec_fcor), foextrap_bc());
706 vec_fcor[lev]->EnforcePeriodicity(geom[lev].periodicity());
707 }
708}
709
710void
712 BL_PROFILE("REMORA::init_set_vmix()");
717 // The GLS initialization just sets the multifab to a value, so there's
718 // no need to call FillPatch here
719 } else {
720 Abort("Don't know this vertical mixing type");
721 }
722}
723
724/**
725 * @param[in ] lev level to operate on
726 */
727void
729 BL_PROFILE("REMORA::set_analytic_vmix()");
730 Real time = 0.0_rt;
731 vec_Akv[lev]->setVal(solverChoice.Akv_bak);
732 vec_Akt[lev]->setVal(solverChoice.Akt_bak);
733 prob->init_analytic_vmix(lev, geom[lev], solverChoice, *this,*vec_Akv[lev], *vec_Akt[lev]);
734 FillPatch(lev, time, *vec_Akv[lev], GetVecOfPtrs(vec_Akv), zvel_bc(), BdyVars::null,0,true,false);
735 for (int n = 0; n < ncons; n++) {
736 FillPatch(lev, time, *vec_Akt[lev], GetVecOfPtrs(vec_Akt), zvel_bc(), BdyVars::null,n,false,false);
737 }
738}
739
740/**
741 * @param[in ] lev level to operate on
742 */
743void
745{
747 prob->init_analytic_masks(lev,geom[lev], solverChoice, *this, *vec_mskr[lev]);
750#ifdef REMORA_USE_NETCDF
751 if (lev == 0) {
752 amrex::Print() << "Calling init_masks_from_netcdf level " << lev << std::endl;
754 amrex::Print() << "Masks loaded from netcdf file \n " << std::endl;
755 } else {
756 Real dummy_time = 0.0_rt;
757 FillCoarsePatchPC(lev, dummy_time, vec_mskr[lev].get(), vec_mskr[lev-1].get(),
758 foextrap_bc());
760 }
761#endif
762 }
763 fill_3d_masks(lev);
764}
765
766/**
767 * @param[in ] lev level to operate on
768 */
769void
771{
772 BL_PROFILE("REMORA::set_hmixcoef()");
773
774 // Optional AMR scaling: decrease coefficients on refined levels linearly
775 // with grid size (i.e., proportional to sqrt(cell area)). For a horizontal
776 // refinement ratio rx x ry, the effective scale factor is 1/sqrt(rx*ry).
777 Real lev_scale = 1.0_rt;
779 Real rf = 1.0_rt;
780 for (int l = 0; l < lev; ++l) {
781 rf *= std::sqrt(static_cast<Real>(ref_ratio[l][0]) * static_cast<Real>(ref_ratio[l][1]));
782 }
783 lev_scale = 1.0_rt / rf;
784 }
785
787 prob->init_analytic_hmix(lev, geom[lev], solverChoice,
788 *this, *vec_visc2_p[lev], *vec_visc2_r[lev], *vec_diff2[lev]);
789
791 vec_visc2_p[lev]->setVal(solverChoice.visc2 * lev_scale);
792 vec_visc2_r[lev]->setVal(solverChoice.visc2 * lev_scale);
793 for (int n = 0; n < ncons; n++) {
794 vec_diff2[lev]->setVal(solverChoice.tnu2[n] * lev_scale, n, 1);
795 }
796
797 // Scale harmonic viscosity and diffusivity by the grid size as ROMS
798 // does in Utility/ini_hmixcoef.F. Intended for curvilinear grids.
799 //
800 // Define the ROMS grid factor (grdscl):
801 // G(i,j) = sqrt( 1 / (pm(i,j) * pn(i,j)) )
802 // = sqrt(cell area)
803 // Gmax = max over grid of G(i,j)
804 //
805 // Then horizontal harmonic mixing coefficients are scaled as:
806 // nu(i,j) = nu0 * G(i,j) / Gmax
807 // kappa_n(i,j) = kappa0 * G(i,j) / Gmax
808 //
809 // where:
810 // nu0 = solverChoice.visc2
811 // kappa0 = solverChoice.tnu2[n]
812 //
813 // This makes mixing strongest where grid spacing is largest.
814 //
815 // NOTE: The normalization (Gmax) is computed over the entire grid (ignoring masks).
816 // Therefore, if the largest cell area occurs over land, the maximum over *wet* cells
817 // (or in masked output files) may be smaller than the user-specified value.
818
820
821 // ------------------------------------------------------------
822 // Step 1: Compute grdmax over entire grid
823 // ------------------------------------------------------------
824 vec_visc2_r[lev]->setVal(solverChoice.visc2);
825 vec_visc2_p[lev]->setVal(solverChoice.visc2);
826 for (int n = 0; n < ncons; n++) {
827 vec_diff2[lev]->setVal(solverChoice.tnu2[n], n, 1);
828 }
829
830 // NOTE: This must be GPU-safe. Do not dereference MultiFab data on host.
831 // Force the reduction to run in the GPU launch region if GPUs are enabled.
832 // (If the launch region is disabled at runtime, ReduceMax may fall back to
833 // a host path that can try to read device-only data.)
834 amrex::Gpu::LaunchSafeGuard lsg(true);
835 Real denom_min = amrex::ReduceMin(*vec_pm[lev], *vec_pn[lev], 0,
836 [=] AMREX_GPU_HOST_DEVICE (Box const& bx,
837 Array4<Real const> const& pm,
838 Array4<Real const> const& pn) -> Real
839 {
840 Real local_min = 1.0e200_rt;
841 amrex::Loop(bx, [=,&local_min] (int i, int j, int) noexcept
842 {
843 local_min = amrex::min(local_min, pm(i,j,0) * pn(i,j,0));
844 });
845 return local_min;
846 });
847
848 ParallelDescriptor::ReduceRealMin(denom_min);
849 if (denom_min <= 0.0_rt) {
850 Abort("scaled_to_grid: found non-positive pm*pn (grid metrics must be > 0)");
851 }
852
853 Real grdmax = amrex::ReduceMax(*vec_pm[lev], *vec_pn[lev], 0,
854 [=] AMREX_GPU_HOST_DEVICE (Box const& bx,
855 Array4<Real const> const& pm,
856 Array4<Real const> const& pn) -> Real
857 {
858 Real local_max = 0.0_rt;
859 amrex::Loop(bx, [=,&local_max] (int i, int j, int) noexcept
860 {
861 Real denom = pm(i,j,0) * pn(i,j,0);
862 if (denom > 0.0_rt) {
863 Real G = std::sqrt(1.0_rt / denom);
864 local_max = amrex::max(local_max, G);
865 }
866 });
867 return local_max;
868 });
869
870 ParallelDescriptor::ReduceRealMax(grdmax);
871 if (grdmax <= 0.0_rt) {
872 Abort("scaled_to_grid: grdmax <= 0");
873 }
874
875 // Optional AMR scaling: decrease coefficients on refined levels linearly
876 // with grid size (i.e., proportional to sqrt(cell area)). For a horizontal
877 // refinement ratio rx x ry, the effective scale factor is 1/sqrt(rx*ry).
878 lev_scale = 1.0_rt;
880 Real rf = 1.0_rt;
881 for (int l = 0; l < lev; ++l) {
882 rf *= std::sqrt(static_cast<Real>(ref_ratio[l][0]) * static_cast<Real>(ref_ratio[l][1]));
883 }
884 lev_scale = 1.0_rt / rf;
885 }
886
887 Real visc0 = solverChoice.visc2 * lev_scale;
888 Real cff = visc0 / grdmax;
889
890 // ------------------------------------------------------------
891 // Step 2: Set rho coefficients everywhere
892 // ------------------------------------------------------------
893 amrex::Gpu::DeviceVector<Real> diff0_d(ncons);
894 amrex::Gpu::copy(amrex::Gpu::hostToDevice,
895 solverChoice.tnu2.begin(), solverChoice.tnu2.begin() + ncons,
896 diff0_d.begin());
897 Real const* diff0_ptr = diff0_d.data();
898
899 for (MFIter mfi(*vec_visc2_r[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
900 {
901 const Box& bx = mfi.validbox();
902 auto pm = vec_pm[lev]->const_array(mfi);
903 auto pn = vec_pn[lev]->const_array(mfi);
904 auto visc2_r = vec_visc2_r[lev]->array(mfi);
905 auto diff2 = vec_diff2[lev]->array(mfi);
906
907 int ncons_local = ncons;
908 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept
909 {
910 Real denom = pm(i,j,0) * pn(i,j,0);
911 Real grdscl = (denom > 0.0_rt) ? std::sqrt(1.0_rt / denom) : 0.0_rt;
912 visc2_r(i,j,0) = cff * grdscl;
913
914 for (int n = 0; n < ncons_local; n++) {
915 diff2(i,j,0,n) = ((diff0_ptr[n] * lev_scale) / grdmax) * grdscl;
916 }
917 });
918 }
919
920 // Fill ghost cells for rho coefficients BEFORE psi averaging
921 Real time = 0.0_rt;
922 FillPatch(lev, time, *vec_visc2_r[lev], GetVecOfPtrs(vec_visc2_r), foextrap_periodic_bc());
923
924 // ------------------------------------------------------------
925 // Step 3: Psi coefficients = average of 4 surrounding rho
926 // ------------------------------------------------------------
927 for (MFIter mfi(*vec_visc2_p[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
928 {
929 const Box& bx = mfi.validbox();
930 auto visc2_p = vec_visc2_p[lev]->array(mfi);
931 auto visc2_r = vec_visc2_r[lev]->const_array(mfi);
932
933 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept
934 {
935 visc2_p(i,j,0) = 0.25_rt * (
936 visc2_r(i-1,j-1,0) +
937 visc2_r(i ,j-1,0) +
938 visc2_r(i-1,j ,0) +
939 visc2_r(i ,j ,0)
940 );
941 });
942 }
943
944 FillPatch(lev, time, *vec_visc2_p[lev], GetVecOfPtrs(vec_visc2_p), foextrap_periodic_bc());
945
946 // Diagnostics
947 // NOTE: coefficients are computed everywhere (including land). Output routines may later
948 // mask land points (e.g., to FillValue in NetCDF/plotfiles), and analysis tools may
949 // additionally apply mask_rho (setting land to 0). Report both conventions.
950 //
951 // Global (MPI-reduced) extrema over all valid cells (no ghost).
952 Real visc_min_all = vec_visc2_r[lev]->min(0,0,false);
953 Real visc_max_all = vec_visc2_r[lev]->max(0,0,false);
954
955 // Global extrema over *wet* rho points only, k=0.
956 amrex::Gpu::LaunchSafeGuard lsg_diag(true);
957 Real visc_min_wet = amrex::ReduceMin(*vec_visc2_r[lev], *vec_mskr[lev], 0,
958 [=] AMREX_GPU_HOST_DEVICE (Box const& bx,
959 Array4<Real const> const& visc2,
960 Array4<Real const> const& mskr) -> Real
961 {
962 Real local_min = 1.0e200_rt;
963 amrex::Loop(bx, [=,&local_min] (int i, int j, int) noexcept
964 {
965 if (mskr(i,j,0) > 0.0_rt) {
966 local_min = amrex::min(local_min, visc2(i,j,0));
967 }
968 });
969 return local_min;
970 });
971 ParallelDescriptor::ReduceRealMin(visc_min_wet);
972
973 Real visc_max_wet = amrex::ReduceMax(*vec_visc2_r[lev], *vec_mskr[lev], 0,
974 [=] AMREX_GPU_HOST_DEVICE (Box const& bx,
975 Array4<Real const> const& visc2,
976 Array4<Real const> const& mskr) -> Real
977 {
978 Real local_max = -1.0e200_rt;
979 amrex::Loop(bx, [=,&local_max] (int i, int j, int) noexcept
980 {
981 if (mskr(i,j,0) > 0.0_rt) {
982 local_max = amrex::max(local_max, visc2(i,j,0));
983 }
984 });
985 return local_max;
986 });
987 ParallelDescriptor::ReduceRealMax(visc_max_wet);
988
989 // Mimic "apply mask_rho" convention (dry -> 0).
990 Real visc_min_mask0 = amrex::ReduceMin(*vec_visc2_r[lev], *vec_mskr[lev], 0,
991 [=] AMREX_GPU_HOST_DEVICE (Box const& bx,
992 Array4<Real const> const& visc2,
993 Array4<Real const> const& mskr) -> Real
994 {
995 Real local_min = 1.0e200_rt;
996 amrex::Loop(bx, [=,&local_min] (int i, int j, int) noexcept
997 {
998 const Real v = (mskr(i,j,0) > 0.0_rt) ? visc2(i,j,0) : 0.0_rt;
999 local_min = amrex::min(local_min, v);
1000 });
1001 return local_min;
1002 });
1003 ParallelDescriptor::ReduceRealMin(visc_min_mask0);
1004
1005 Real visc_max_mask0 = amrex::ReduceMax(*vec_visc2_r[lev], *vec_mskr[lev], 0,
1006 [=] AMREX_GPU_HOST_DEVICE (Box const& bx,
1007 Array4<Real const> const& visc2,
1008 Array4<Real const> const& mskr) -> Real
1009 {
1010 Real local_max = -1.0e200_rt;
1011 amrex::Loop(bx, [=,&local_max] (int i, int j, int) noexcept
1012 {
1013 const Real v = (mskr(i,j,0) > 0.0_rt) ? visc2(i,j,0) : 0.0_rt;
1014 local_max = amrex::max(local_max, v);
1015 });
1016 return local_max;
1017 });
1018 ParallelDescriptor::ReduceRealMax(visc_max_mask0);
1019 if (ParallelDescriptor::IOProcessor() && lev == 0)
1020 {
1021 Print() << "\nHorizontal mixing scaled by grid metric\n";
1022 Print() << "grdmax = " << grdmax << "\n";
1024 Print() << "AMR scaling (linear) lev_scale = " << lev_scale << "\n";
1025 }
1026 Print() << "visc2(all) min/max = "
1027 << visc_min_all << " / "
1028 << visc_max_all << "\n";
1029 Print() << "visc2(wet,k=0) min/max = "
1030 << visc_min_wet << " / "
1031 << visc_max_wet << "\n";
1032 Print() << "visc2(mask->0) min/max = "
1033 << visc_min_mask0 << " / "
1034 << visc_max_mask0 << "\n";
1035 }
1036
1037 } else {
1038 Abort("Don't know this horizontal mixing type");
1039 }
1040
1041 // Final FillPatch for all fields
1042 Real time = 0.0_rt;
1043 FillPatch(lev, time, *vec_visc2_p[lev], GetVecOfPtrs(vec_visc2_p), foextrap_periodic_bc());
1044 FillPatch(lev, time, *vec_visc2_r[lev], GetVecOfPtrs(vec_visc2_r), foextrap_periodic_bc());
1045 for (int n = 0; n < ncons; n++) {
1046 FillPatch(lev, time, *vec_diff2[lev], GetVecOfPtrs(vec_diff2),
1047 foextrap_periodic_bc(), BdyVars::null, n, false);
1048 }
1049}
1050
1051/**
1052 * @param[in ] lev level to operate on
1053 */
1054void
1056{
1057 BL_PROFILE("REMORA::init_flat_bathymetry()");
1058 vec_h[lev]->setVal(-geom[0].ProbLo()[2]);
1059}
1060
1061/**
1062 * @param[in ] lev level to operate on
1063 */
1064void
1066{
1067 BL_PROFILE("REMORA::set_smflux()");
1069 prob->init_analytic_smflux(lev, geom[lev], solverChoice, *this,*vec_sustr[lev], *vec_svstr[lev]);
1071#ifdef REMORA_USE_NETCDF
1072 sustr_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_sustr[lev].get(), geom, ref_ratio);
1073 svstr_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_svstr[lev].get(), geom, ref_ratio);
1074 FillPatch(lev, t_old[lev], *vec_sustr[lev], GetVecOfPtrs(vec_sustr), foextrap_periodic_bc(), BdyVars::null,0,false);
1075 FillPatch(lev, t_old[lev], *vec_svstr[lev], GetVecOfPtrs(vec_svstr), foextrap_periodic_bc(), BdyVars::null,0,false);
1076#endif
1077 }
1078}
1079
1080/**
1081 * @param[in ] lev level to operate on
1082 */
1083void
1085{
1086 BL_PROFILE("REMORA::set_wind()");
1087 const bool driver_has_uwind = driver_atmos_state_from_driver[0];
1088 const bool driver_has_vwind = driver_atmos_state_from_driver[1];
1089
1091 // The analytic wind initializer writes both components together, so only
1092 // invoke it when the driver has not already provided the wind pair.
1093 if (!(driver_has_uwind && driver_has_vwind)) {
1094 prob->init_analytic_wind(lev,geom[lev], solverChoice, *this, *vec_uwind[lev], *vec_vwind[lev]);
1095 }
1096 if (vec_uwind[lev] != nullptr) { vec_uwind[lev]->FillBoundary(geom[lev].periodicity()); }
1097 if (vec_vwind[lev] != nullptr) { vec_vwind[lev]->FillBoundary(geom[lev].periodicity()); }
1098 } else if (solverChoice.wind_type == WindType::netcdf) {
1099#ifdef REMORA_USE_NETCDF
1100 if (!driver_has_uwind) {
1101 Uwind_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_uwind[lev].get(), geom, ref_ratio);
1102 FillPatch(lev, t_old[lev], *vec_uwind[lev], GetVecOfPtrs(vec_uwind),
1104 } else {
1105 if (vec_uwind[lev] != nullptr) { vec_uwind[lev]->FillBoundary(geom[lev].periodicity()); }
1106 }
1107 if (!driver_has_vwind) {
1108 Vwind_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_vwind[lev].get(), geom, ref_ratio);
1109 FillPatch(lev, t_old[lev], *vec_vwind[lev], GetVecOfPtrs(vec_vwind),
1111 } else {
1112 if (vec_vwind[lev] != nullptr) { vec_vwind[lev]->FillBoundary(geom[lev].periodicity()); }
1113 }
1114
1115 // Conditionally update atmospheric fields if loaded from NetCDF
1117 Tair_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_Tair[lev].get(), geom, ref_ratio);
1118 FillPatch(lev, t_old[lev], *vec_Tair[lev], GetVecOfPtrs(vec_Tair),
1120 } else if (vec_Tair[lev]) {
1121 vec_Tair[lev]->FillBoundary(geom[lev].periodicity());
1122 }
1124 qair_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_qair[lev].get(), geom, ref_ratio);
1125 FillPatch(lev, t_old[lev], *vec_qair[lev], GetVecOfPtrs(vec_qair),
1127
1128 // Convert qair from percentage (0-100) to specific humidity (0-1) if needed
1130 vec_qair[lev]->mult(0.01);
1131
1132 // Update ghost cells after modification
1133 vec_qair[lev]->FillBoundary(geom[lev].periodicity());
1134 }
1135 } else if (vec_qair[lev]) {
1136 vec_qair[lev]->FillBoundary(geom[lev].periodicity());
1137 }
1139 Pair_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_Pair[lev].get(), geom, ref_ratio);
1140 FillPatch(lev, t_old[lev], *vec_Pair[lev], GetVecOfPtrs(vec_Pair),
1142 } else if (vec_Pair[lev]) {
1143 vec_Pair[lev]->FillBoundary(geom[lev].periodicity());
1144 }
1146 srflx_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_srflx[lev].get(), geom, ref_ratio);
1147 FillPatch(lev, t_old[lev], *vec_srflx[lev], GetVecOfPtrs(vec_srflx),
1149 } else if (vec_srflx[lev]) {
1150 vec_srflx[lev]->FillBoundary(geom[lev].periodicity());
1151 }
1153 longwave_down_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_longwave_down[lev].get(), geom, ref_ratio);
1154 FillPatch(lev, t_old[lev], *vec_longwave_down[lev], GetVecOfPtrs(vec_longwave_down),
1156 } else if (vec_longwave_down[lev]) {
1157 vec_longwave_down[lev]->FillBoundary(geom[lev].periodicity());
1158 }
1160 rain_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_rain[lev].get(), geom, ref_ratio);
1161 FillPatch(lev, t_old[lev], *vec_rain[lev], GetVecOfPtrs(vec_rain),
1163 } else if (vec_rain[lev]) {
1164 vec_rain[lev]->FillBoundary(geom[lev].periodicity());
1165 }
1167 cloud_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_cloud[lev].get(), geom, ref_ratio);
1168 FillPatch(lev, t_old[lev], *vec_cloud[lev], GetVecOfPtrs(vec_cloud),
1170 } else if (vec_cloud[lev]) {
1171 vec_cloud[lev]->FillBoundary(geom[lev].periodicity());
1172 }
1174 EminusP_data_from_file->update_interpolated_to_time(t_old[lev], lev, vec_EminusP[lev].get(), geom, ref_ratio);
1175 FillPatch(lev, t_old[lev], *vec_EminusP[lev], GetVecOfPtrs(vec_EminusP),
1177 } else if (vec_EminusP[lev]) {
1178 vec_EminusP[lev]->FillBoundary(geom[lev].periodicity());
1179 }
1180#endif
1181 } else {
1182 amrex::Abort("Unknown wind_type in REMORA::set_wind()");
1183 }
1184}
1185
1186/**
1187 * @param[in ] lev level to operate on
1188 * @param[in ] time current time for initialization
1189 */
1190void
1191REMORA::init_only (int lev, Real time)
1192{
1193 BL_PROFILE("REMORA::init_only()");
1194 t_new[lev] = time;
1195 t_old[lev] = time - 1.e200_rt;
1196
1197 cons_new[lev]->setVal(0.0_rt);
1198 xvel_new[lev]->setVal(0.0_rt);
1199 yvel_new[lev]->setVal(0.0_rt);
1200 zvel_new[lev]->setVal(0.0_rt);
1201
1202 xvel_old[lev]->setVal(0.0_rt);
1203 yvel_old[lev]->setVal(0.0_rt);
1204 zvel_old[lev]->setVal(0.0_rt);
1205
1206 vec_ru[lev]->setVal(0.0_rt);
1207 vec_rv[lev]->setVal(0.0_rt);
1208
1209 vec_ru2d[lev]->setVal(0.0_rt);
1210 vec_rv2d[lev]->setVal(0.0_rt);
1211
1213 set_grid_scale(lev);
1214 }
1215 set_masks(lev);
1216
1217#ifdef REMORA_USE_NETCDF
1220
1221 if (solverChoice.do_any_clim_nudg && lev == 0) {
1222 if (nc_clim_his_file.empty() || nc_clim_his_file[0].empty()) {
1223 amrex::Error("NetCDF climatology file name must be provided via input");
1224 }
1227 clim_ubar_time_varname, geom[lev].Domain(),vec_ubar[lev].get(),true,true));
1229 clim_ubar_time_varname, geom[lev].Domain(),vec_vbar[lev].get(),true,true));
1230 ubar_clim_data_from_file->Initialize();
1231 vbar_clim_data_from_file->Initialize();
1232 }
1234 u_clim_data_from_file.reset(new NCTimeSeries(nc_clim_his_file, "u", clim_u_time_varname, geom[lev].Domain(),xvel_new[lev],false,true));
1235 v_clim_data_from_file.reset(new NCTimeSeries(nc_clim_his_file, "v", clim_v_time_varname, geom[lev].Domain(),yvel_new[lev],false,true));
1236 u_clim_data_from_file->Initialize();
1237 v_clim_data_from_file->Initialize();
1238 }
1239 // Since the NCTimeSeries object isn't filling the cons_new MultiFab directly, we don't have to specify a component.
1240 // It just needs to know the shape of the MultiFab
1242 temp_clim_data_from_file.reset(new NCTimeSeries(nc_clim_his_file, "temp", clim_temp_time_varname,geom[lev].Domain(),cons_new[lev],false,true));
1243 temp_clim_data_from_file->Initialize();
1244 }
1246 salt_clim_data_from_file.reset(new NCTimeSeries(nc_clim_his_file, "salt", clim_salt_time_varname,geom[lev].Domain(),cons_new[lev],false,true));
1247 salt_clim_data_from_file->Initialize();
1248 }
1249 }
1250 }
1251
1253 amrex::Print() << "Calling init_bdry_from_netcdf at level " << lev << std::endl;
1255 amrex::Print() << "Boundary data loaded from netcdf file \n " << std::endl;
1256 }
1257
1258 // This will be a non-op if forcings specified analytically
1260 if (lev==0) {
1261 if (nc_frc_file.empty() || nc_frc_file[0].empty()) {
1262 amrex::Error("NetCDF forcing file name must be provided via input for winds");
1263 }
1264 Uwind_data_from_file.reset(new NCTimeSeries(nc_frc_file, "Uwind", frc_time_varname, geom[lev].Domain(),vec_uwind[lev].get(), true, false));
1265 Vwind_data_from_file.reset(new NCTimeSeries(nc_frc_file, "Vwind", frc_time_varname, geom[lev].Domain(),vec_vwind[lev].get(), true, false));
1266 Uwind_data_from_file->Initialize();
1267 Vwind_data_from_file->Initialize();
1268 } else {
1269 FillCoarsePatch(lev, time, vec_uwind[lev].get(), vec_uwind[lev-1].get(), foextrap_bc());
1270 FillCoarsePatch(lev, time, vec_vwind[lev].get(), vec_vwind[lev-1].get(), foextrap_bc());
1271 }
1273 if (lev==0) {
1274 if (nc_frc_file.empty() || nc_frc_file[0].empty()) {
1275 amrex::Error("NetCDF forcing file name must be provided via input for surface momentum fluxes");
1276 }
1277 sustr_data_from_file.reset(new NCTimeSeries(nc_frc_file, "sustr", frc_time_varname, geom[lev].Domain(),vec_sustr[lev].get(), true, false));
1278 svstr_data_from_file.reset(new NCTimeSeries(nc_frc_file, "svstr", frc_time_varname, geom[lev].Domain(),vec_svstr[lev].get(), true, false));
1279 sustr_data_from_file->Initialize();
1280 svstr_data_from_file->Initialize();
1281 } else {
1282 FillCoarsePatch(lev, time, vec_sustr[lev].get(), vec_sustr[lev-1].get(), foextrap_bc());
1283 FillCoarsePatch(lev, time, vec_svstr[lev].get(), vec_svstr[lev-1].get(), foextrap_bc());
1284 }
1285 }
1286
1287 // Conditionally load atmospheric forcing fields from NetCDF based on user flags
1288 if (lev==0) {
1290 Tair_data_from_file.reset(new NCTimeSeries(nc_frc_file, "Tair", frc_time_varname, geom[lev].Domain(),vec_Tair[lev].get(), true, false));
1291 Tair_data_from_file->Initialize();
1292 }
1294 qair_data_from_file.reset(new NCTimeSeries(nc_frc_file, "qair", frc_time_varname, geom[lev].Domain(),vec_qair[lev].get(), true, false));
1295 qair_data_from_file->Initialize();
1296 }
1298 Pair_data_from_file.reset(new NCTimeSeries(nc_frc_file, "Pair", frc_time_varname, geom[lev].Domain(),vec_Pair[lev].get(), true, false));
1299 Pair_data_from_file->Initialize();
1300 }
1302 srflx_data_from_file.reset(new NCTimeSeries(nc_frc_file, "swrad", frc_time_varname, geom[lev].Domain(),vec_srflx[lev].get(), true, false));
1303 srflx_data_from_file->Initialize();
1304 }
1306 rain_data_from_file.reset(new NCTimeSeries(nc_frc_file, "rain", frc_time_varname, geom[lev].Domain(),vec_rain[lev].get(), true, false));
1307 rain_data_from_file->Initialize();
1308 }
1310 cloud_data_from_file.reset(new NCTimeSeries(nc_frc_file, "cloud", frc_time_varname, geom[lev].Domain(),vec_cloud[lev].get(), true, false));
1311 cloud_data_from_file->Initialize();
1312 }
1314 EminusP_data_from_file.reset(new NCTimeSeries(nc_frc_file, "EminusP", frc_time_varname, geom[lev].Domain(),vec_EminusP[lev].get(), true, false));
1315 EminusP_data_from_file->Initialize();
1316 }
1317 } else {
1319 FillCoarsePatch(lev, time, vec_Tair[lev].get(), vec_Tair[lev-1].get(), foextrap_bc());
1320 }
1322 FillCoarsePatch(lev, time, vec_qair[lev].get(), vec_qair[lev-1].get(), foextrap_bc());
1323 }
1325 FillCoarsePatch(lev, time, vec_Pair[lev].get(), vec_Pair[lev-1].get(), foextrap_bc());
1326 }
1328 FillCoarsePatch(lev, time, vec_srflx[lev].get(), vec_srflx[lev-1].get(), foextrap_bc());
1329 }
1331 FillCoarsePatch(lev, time, vec_rain[lev].get(), vec_rain[lev-1].get(), foextrap_bc());
1332 }
1334 FillCoarsePatch(lev, time, vec_cloud[lev].get(), vec_cloud[lev-1].get(), foextrap_bc());
1335 }
1337 FillCoarsePatch(lev, time, vec_EminusP[lev].get(), vec_EminusP[lev-1].get(), foextrap_bc());
1338 }
1339 }
1341 if (lev==0) {
1342 if (nc_frc_file.empty() || nc_frc_file[0].empty()) {
1343 amrex::Error("NetCDF forcing file name must be provided via input for longwave radiation");
1344 }
1346 geom[lev].Domain(), vec_longwave_down[lev].get(), true, false));
1347 longwave_down_data_from_file->Initialize();
1348 } else {
1349 FillCoarsePatch(lev, time, vec_longwave_down[lev].get(), vec_longwave_down[lev-1].get(), foextrap_bc());
1350 }
1351 }
1352
1353 // Only need to read in rivers on level 0
1354 // Will need to be on higher levels eventually
1355 if (solverChoice.do_rivers) {
1356 if (nc_riv_file.empty() || nc_riv_file[0].empty()) {
1357 amrex::Error("NetCDF river file name must be provided via input for rivers");
1358 }
1359 auto dom = geom[0].Domain();
1360 int nz = dom.length(2);
1361 river_source_cons.resize(ncons);
1364 river_source_cons[Salt_comp]->Initialize();
1365 }
1368 river_source_cons[Temp_comp]->Initialize();
1369 }
1372 river_source_cons[Tracer_comp]->Initialize();
1373 }
1374 river_source_transport.reset(new NCTimeSeriesRiver(nc_riv_file, "river_transport", riv_time_varname, nz));
1375 river_source_transport->Initialize();
1376 river_source_transportbar.reset(new NCTimeSeriesRiver(nc_riv_file, "river_transport", riv_time_varname, nz, 1));
1377 river_source_transportbar->Initialize();
1379 }
1380
1381 if (lev==0 and hires_grid_level > 0 and solverChoice.ic_type == IC_Type::netcdf) {
1382 amrex::Print() << "Reading high resolution bathymetry and grid data" << std::endl;
1386 amrex::Print() << "Done reading in high resolution bathymetry and grid data" << std::endl;
1387 }
1388#else
1390 Abort("Not compiled with NetCDF, but selected boundary conditions require NetCDF");
1391 }
1392 if (solverChoice.do_rivers) {
1393 Abort("Not compiled with NetCDF, but using river sources requires NetCDF");
1394 }
1395#endif
1396
1397 if (lev==0 and hires_grid_level > 0 and solverChoice.ic_type == IC_Type::analytic) {
1400 }
1401
1402 set_bathymetry(lev);
1403 set_zeta(lev);
1404 stretch_transform(lev);
1405
1407 if (lev==0) {
1409 {
1410 init_analytic(lev);
1411#ifdef REMORA_USE_NETCDF
1412 } else if (solverChoice.ic_type == IC_Type::netcdf) {
1413 amrex::Print() << "Calling init_data_from_netcdf " << std::endl;
1415 set_zeta_to_Ztavg(lev);
1416 amrex::Print() << "Initial data loaded from netcdf file \n " << std::endl;
1417
1418#endif
1419 } else {
1420 Abort("Need to specify ic_type");
1421 }
1422 } else {
1424 FillCoarsePatch(lev, time, xvel_new[lev], xvel_new[lev-1], xvel_bc(), BdyVars::u);
1425 FillCoarsePatch(lev, time, yvel_new[lev], yvel_new[lev-1], yvel_bc(), BdyVars::v);
1426 FillCoarsePatch(lev, time, zvel_new[lev], zvel_new[lev-1], zvel_bc(), BdyVars::null);
1427 }
1430 {
1431 init_analytic(lev);
1432#ifdef REMORA_USE_NETCDF
1433 } else if (solverChoice.ic_type == IC_Type::netcdf) {
1434 amrex::Print() << "Calling init_data_from_netcdf on level " << lev << std::endl;
1436 set_zeta_to_Ztavg(lev);
1437 amrex::Print() << "Initial data loaded from netcdf file on level " << lev << std::endl;
1438
1439#endif
1440 } else {
1441 Abort("Need to specify ic_type");
1442 }
1443 } else {
1444 amrex::Abort("Need to specify T init procedure");
1445 }
1446
1447 // Ensure that the face-based data are the same on both sides of a periodic domain.
1448 // The data associated with the lower grid ID is considered the correct value.
1449 xvel_new[lev]->OverrideSync(geom[lev].periodicity());
1450 yvel_new[lev]->OverrideSync(geom[lev].periodicity());
1451 zvel_new[lev]->OverrideSync(geom[lev].periodicity());
1452
1453 set_2darrays(lev);
1454
1455 init_set_vmix(lev);
1456 set_hmixcoef(lev);
1457 set_coriolis(lev);
1458
1459 // Previously set smflux here with OverrideSync:
1460// set_smflux(lev);
1461// prob->init_analytic_smflux(lev, geom[lev], solverChoice, *this, *vec_sustr[lev], *vec_svstr[lev]);
1462// vec_sustr[lev]->OverrideSync(geom[lev].periodicity());
1463// vec_svstr[lev]->OverrideSync(geom[lev].periodicity());
1464
1465}
1466
1467void
1469{
1470 BL_PROFILE("REMORA::ReadParameters()");
1471 {
1472 ParmParse pp; // Traditionally, max_step and stop_time do not have prefix, so allow it for now.
1473 bool noprefix_max_step = pp.queryAdd("max_step", max_step);
1474 bool noprefix_stop_time = pp.queryAdd("stop_time", stop_time);
1475 bool remora_max_step = pp.queryAdd("remora.max_step", max_step);
1476 bool remora_stop_time = pp.queryAdd("remora.stop_time", stop_time);
1477 if (remora_max_step and noprefix_max_step) {
1478 Abort("remora.max_step and max_step are both specified. Please use only one!");
1479 }
1480 if (remora_stop_time and noprefix_stop_time) {
1481 Abort("remora.stop_time and stop_time are both specified. Please use only one!");
1482 }
1483 }
1484
1485 ParmParse pp(pp_prefix);
1486
1487 // Common physics and simulation parameters
1488 pp.queryAdd("nscalar", nscalar);
1489 if (nscalar < 1) {
1490 amrex::Abort("remora.nscalar must be at least 1");
1491 }
1494
1495 pp.queryAdd("check_file", check_file);
1496 pp.queryAdd("check_int", check_int);
1497 pp.queryAdd("check_int_time", check_int_time);
1498 pp.queryAdd("expand_plotvars_to_unif_rr", expand_plotvars_to_unif_rr);
1499 pp.query("plotfile_fill_value", plotfile_fill_value);
1500 pp.query("netcdf_fill_value", netcdf_fill_value);
1501 pp.queryAdd("restart", restart_chkfile);
1502 pp.queryAdd("start_time", start_time);
1503
1504 if (pp.contains("data_log")) {
1505 int num_datalogs = pp.countval("data_log");
1506 datalog.resize(num_datalogs);
1507 datalogname.resize(num_datalogs);
1508 pp.queryarr("data_log", datalogname, 0, num_datalogs);
1509 for (int i = 0; i < num_datalogs; i++)
1511 }
1512
1513 pp.queryAdd("v", verbose);
1514 pp.queryAdd("sum_interval", sum_interval);
1515 pp.queryAdd("sum_period", sum_per);
1516 pp.queryAdd("file_min_digits", file_min_digits);
1517
1518 if (file_min_digits < 0) {
1519 amrex::Abort("remora.file_min_digits must be non-negative");
1520 }
1521
1522 pp.queryAdd("cfl", cfl);
1523 pp.queryAdd("change_max", change_max);
1524 pp.queryAdd("fixed_dt", fixed_dt);
1525 pp.queryAdd("fixed_fast_dt", fixed_fast_dt);
1526 pp.queryAdd("fixed_ndtfast_ratio", fixed_ndtfast_ratio);
1527
1528 if (fixed_dt > 0. && fixed_fast_dt > 0. && fixed_ndtfast_ratio > 0) {
1530 amrex::Abort("Dt is over-specfied");
1531 }
1532 } else if (fixed_dt > 0. && fixed_fast_dt > 0. && fixed_ndtfast_ratio <= 0) {
1533 fixed_ndtfast_ratio = static_cast<int>(fixed_dt / fixed_fast_dt);
1534 }
1535 AMREX_ASSERT(cfl > 0. || fixed_dt > 0.);
1536
1537 pp.queryAdd("plot_file", plot_file_name);
1538 pp.queryAdd("plot_int", plot_int);
1539 pp.queryAdd("plot_int_time", plot_int_time);
1540 pp.queryAdd("plot_staggered_vels", plot_staggered_vels);
1541
1542 std::string plotfile_type_str = "amrex";
1543 pp.queryAdd("plotfile_type", plotfile_type_str);
1544 if (plotfile_type_str == "amrex") {
1546 } else if (plotfile_type_str == "netcdf" || plotfile_type_str == "NetCDF") {
1548#ifdef REMORA_USE_NETCDF
1549 pp.queryAdd("write_history_file",write_history_file);
1550 pp.queryAdd("chunk_history_file",chunk_history_file);
1551 pp.queryAdd("steps_per_history_file",steps_per_history_file);
1552 // Estimate size of domain for one timestep of netcdf
1553 auto dom = geom[0].Domain();
1554 int nx = dom.length(0) + 2;
1555 int ny = dom.length(1) + 2;
1556 int nz = dom.length(2);
1558 // Estimate number of steps that will fit into a 2GB file.
1559 steps_per_history_file = int((1.6e10 - NCH2D * nx * ny * 64.0_rt)
1560 / (nx * ny * 64.0_rt * (NC3D*nz + NC2D)));
1561 // If we calculate that a single step will exceed 2GB and the user has
1562 // requested automatic history file sizing, warn about a possible impending
1563 // error, and set steps_per_history_file = 1 to attempt output anyway.
1564 if (steps_per_history_file == 0) {
1565 amrex::Warning("NetCDF output for a single timestep appears to exceed 2GB. NetCDF output may not work. See Documentation for information about tested MPICH versions.");
1567 }
1568 } else if (write_history_file and !chunk_history_file) {
1569 // Estimate number of output steps we'll need
1570 int nt_out = int((max_step) / plot_int) + 1;
1571 Real est_hist_file_size = NCH2D * nx * ny * 64.0_rt + nt_out * nx * ny * 64.0_rt * (NC3D*nz + NC2D);
1572 if (est_hist_file_size > 1.6e10) {
1573 amrex::Warning("WARNING: NetCDF history file may be larger than 2GB limit. Consider setting remora.chunk_history_file=true");
1574 }
1575 }
1577 Print() << "NetCDF history files will have " << steps_per_history_file << " steps per file." << std::endl;
1578 }
1579#endif
1580 } else {
1581 amrex::Print() << "User selected plotfile_type = " << plotfile_type_str << std::endl;
1582 amrex::Abort("Dont know this plotfile_type");
1583 }
1584#ifndef REMORA_USE_NETCDF
1586 {
1587 amrex::Abort("Please compile with NetCDF in order to enable NetCDF plotfiles");
1588 }
1589
1590#endif
1591#ifdef REMORA_USE_NETCDF
1592 nc_init_file.resize(max_level+1);
1593 nc_grid_file.resize(max_level+1);
1594
1595 boundary_series.resize(max_level+1);
1596
1597 // NetCDF initialization files -- possibly multiple files at each of multiple levels
1598 // but we always have exactly one file at level 0
1599 for (int lev = 0; lev <= max_level; lev++)
1600 {
1601 const std::string nc_file_names = amrex::Concatenate("nc_init_file_",lev,1);
1602 const std::string nc_bathy_file_names = amrex::Concatenate("nc_grid_file_",lev,1);
1603
1604 if (pp.contains(nc_file_names.c_str()))
1605 {
1606 int num_files = pp.countval(nc_file_names.c_str());
1607 int num_bathy_files = pp.countval(nc_bathy_file_names.c_str());
1608 if (num_files != num_bathy_files) {
1609 amrex::Error("Must have same number of netcdf files for grid info as for solution");
1610 }
1611
1612 num_files_at_level[lev] = num_files;
1613 nc_init_file[lev].resize(num_files);
1614 nc_grid_file[lev].resize(num_files);
1615
1616 pp.queryarr(nc_file_names.c_str() , nc_init_file[lev] ,0,num_files);
1617 pp.queryarr(nc_bathy_file_names.c_str(), nc_grid_file[lev],0,num_files);
1618 }
1619 }
1620
1621 pp.queryAdd("nc_grid_file_hires", nc_grid_file_hires);
1622
1623 // We only read boundary data at level 0
1624 pp.queryarr("nc_bdry_file", nc_bdry_file);
1625
1626 // Also only read forcings at level 0 (for now)
1627 if (pp.contains("nc_frc_file")) {
1628 int num_files = pp.countval("nc_frc_file");
1629 nc_frc_file.resize(num_files);
1630 pp.queryarr("nc_frc_file", nc_frc_file, 0, num_files);
1631 }
1632
1633 // Get river file
1634 if (pp.contains("nc_river_file")) {
1635 int num_files = pp.countval("nc_river_file");
1636 nc_riv_file.resize(num_files);
1637 pp.queryarr("nc_river_file", nc_riv_file, 0, num_files);
1638 }
1639
1640 // Read in file names for climatology history and nudging weights
1641 if (pp.contains("nc_clim_his_file")) {
1642 int num_files = pp.countval("nc_clim_his_file");
1643 nc_clim_his_file.resize(num_files);
1644 pp.queryarr("nc_clim_his_file", nc_clim_his_file, 0, num_files);
1645 }
1646 pp.queryAdd("nc_clim_coeff_file", nc_clim_coeff_file);
1647
1648 for (int i=0; i<BdyVars::NumTypes; i++) {
1649 bdry_time_name_byvar.push_back("");
1650 }
1651 pp.queryAdd("bdy_time_varname",bdry_time_varname);
1652 pp.queryAdd("bdy_temp_time_varname",bdry_time_name_byvar[BdyVars::t]);
1653 pp.queryAdd("bdy_salt_time_varname",bdry_time_name_byvar[BdyVars::s]);
1654 pp.queryAdd("bdy_u_time_varname",bdry_time_name_byvar[BdyVars::u]);
1655 pp.queryAdd("bdy_v_time_varname",bdry_time_name_byvar[BdyVars::v]);
1656 pp.queryAdd("bdy_ubar_time_varname",bdry_time_name_byvar[BdyVars::ubar]);
1657 pp.queryAdd("bdy_vbar_time_varname",bdry_time_name_byvar[BdyVars::vbar]);
1658 pp.queryAdd("bdy_zeta_time_varname",bdry_time_name_byvar[BdyVars::zeta]);
1659
1660 // If not specified per variable, populate with the default
1661 for (int i=0; i<BdyVars::NumTypes; i++) {
1662 if (bdry_time_name_byvar[i] == "") {
1664 }
1665 }
1666
1667 pp.queryAdd("frc_time_varname",frc_time_varname);
1668
1669 pp.queryAdd("riv_time_varname",riv_time_varname);
1670
1671 pp.queryAdd("clim_ubar_time_varname",clim_ubar_time_varname);
1672 pp.queryAdd("clim_vbar_time_varname",clim_vbar_time_varname);
1673 pp.queryAdd("clim_u_time_varname",clim_u_time_varname);
1674 pp.queryAdd("clim_v_time_varname",clim_v_time_varname);
1675 pp.queryAdd("clim_salt_time_varname",clim_salt_time_varname);
1676 pp.queryAdd("clim_temp_time_varname",clim_temp_time_varname);
1677
1678#endif
1679 pp.queryAdd("hires_grid_level", hires_grid_level);
1680 if (hires_grid_level > max_level) {
1681 amrex::Abort("hires_grid_level must be less than or equal to amr.max_level");
1682 }
1683
1684#ifdef REMORA_USE_PARTICLES
1685 readTracersParams();
1686#endif
1687
1688 {
1689 ParmParse pp_amr("amr");
1690 pp_amr.queryAdd("regrid_int", regrid_int);
1691 pp_amr.queryAdd("check_int", check_int);
1692 pp_amr.queryAdd("check_int_time", check_int_time);
1693 pp_amr.queryAdd("restart", restart_chkfile);
1694 pp_amr.queryAdd("do_substep", do_substep);
1695 if (do_substep) {
1696 amrex::Abort("Time substepping is not yet implemented. amr.do_substep must be 0");
1697 }
1698
1699 num_files_at_level.resize(max_level + 1, 0);
1700 num_boxes_at_level.resize(max_level + 1, 0);
1701 boxes_at_level.resize(max_level + 1);
1702 num_boxes_at_level[0] = 1;
1703 boxes_at_level[0].resize(1);
1704 boxes_at_level[0][0] = geom[0].Domain();
1705 }
1706
1708}
1709
1710
1711void
1713{
1714 BL_PROFILE("REMORA::AverageDown()");
1715 for (int lev = finest_level-1; lev >= 0; --lev)
1716 {
1717 AverageDownTo(lev);
1718 }
1719}
1720
1721/**
1722 * @param[in ] crse_lev level to average down to
1723 */
1724void
1726{
1727 BL_PROFILE("REMORA::AverageDownTo()");
1728 average_down(*cons_new[crse_lev+1], *cons_new[crse_lev],
1729 0, cons_new[crse_lev]->nComp(), refRatio(crse_lev));
1730 average_down(*vec_Zt_avg1[crse_lev+1].get(), *vec_Zt_avg1[crse_lev].get(),
1731 0, vec_Zt_avg1[crse_lev]->nComp(), refRatio(crse_lev));
1732
1733 Array<MultiFab*,AMREX_SPACEDIM> faces_crse;
1734 Array<MultiFab*,AMREX_SPACEDIM> faces_fine;
1735 faces_crse[0] = xvel_new[crse_lev];
1736 faces_crse[1] = yvel_new[crse_lev];
1737 faces_crse[2] = zvel_new[crse_lev];
1738
1739 faces_fine[0] = xvel_new[crse_lev+1];
1740 faces_fine[1] = yvel_new[crse_lev+1];
1741 faces_fine[2] = zvel_new[crse_lev+1];
1742
1743 average_down_faces(GetArrOfConstPtrs(faces_fine), faces_crse,
1744 refRatio(crse_lev),geom[crse_lev]);
1745 stretch_transform(crse_lev);
1746}
1747
1748/**
1749 * @param[in ] crse_lev level to average data down to
1750 * @param[inout] vec_mf vector over levels of multifabs containing data to average
1751 */
1752void
1753REMORA::average_down_with_grow_cells(int crse_lev, Vector<std::unique_ptr<MultiFab>>& vec_mf)
1754{
1755 auto const& crsema = vec_mf[crse_lev]->arrays();
1756 auto const& finema = vec_mf[crse_lev+1]->const_arrays();
1757 auto ref_ratio_crse = refRatio(crse_lev);
1758 auto index_type = (vec_mf[crse_lev]->boxArray().ixType()).toIntVect();
1759 auto nghost_crse = cum_ref_ratios[crse_lev] - index_type;
1760 if (index_type[0]==0 and index_type[1]==0) {
1761 ParallelFor(*vec_mf[crse_lev], nghost_crse, 1,
1762 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1763 {
1764 amrex_avgdown(i,j,k,n,crsema[box_no],finema[box_no],0,0,ref_ratio_crse);
1765 });
1766 } else if (index_type[0]==1 and index_type[1]==0) {
1767 ParallelFor(*vec_mf[crse_lev], nghost_crse, 1,
1768 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1769 {
1770 amrex_avgdown_faces(i,j,k,n,crsema[box_no],finema[box_no],0,0,ref_ratio_crse,0);
1771 });
1772 } else if (index_type[0]==0 and index_type[1]==1) {
1773 ParallelFor(*vec_mf[crse_lev], nghost_crse, 1,
1774 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1775 {
1776 amrex_avgdown_faces(i,j,k,n,crsema[box_no],finema[box_no],0,0,ref_ratio_crse,1);
1777 });
1778 } else {
1779 amrex::Abort("Unexpected nodality in average_down_with_grow_cells");
1780 }
1781 Gpu::streamSynchronize();
1782}
1783
1784/**
1785 * @param[in ] lev level at which to get time
1786 */
1787amrex::Real REMORA::get_t_old(int lev) const
1788{
1789 return t_old[lev];
1790}
PlotfileType
plotfile format
#define Temp_comp
#define NC3D
#define Tracer_comp
#define Salt_comp
#define NC2D
#define NCH2D
std::unique_ptr< ProblemBase > amrex_probinit(const amrex_real *problo, const amrex_real *probhi) AMREX_ATTRIBUTE_WEAK
Function to init the physical bounds of the domain and instantiate a Problem derived from ProblemBase...
A class to hold and interpolate time series data read from a NetCDF file.
static PlotfileType plotfile_type
Native or NetCDF plotfile output.
Definition REMORA.H:1517
std::string nc_grid_file_hires
Grid file for high resolution bathymetry.
Definition REMORA.H:1529
void FillCoarsePatchPC(int lev, amrex::Real time, amrex::MultiFab *mf_fine, amrex::MultiFab *mf_crse, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=amrex::Real(0.0), const amrex::MultiFab &mf_calc=amrex::MultiFab())
fill an entire multifab by interpolating from the coarser level using the piecewise constant interpol...
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_EminusP
evaporation minus precipitation [kg/m^2/s], defined at rho-points
Definition REMORA.H:409
amrex::Vector< std::string > nc_riv_file
NetCDF river file(s)
Definition REMORA.H:1538
void set_grid_vars_averaged_down(int lev)
Set pm/pn by averaging down from higher-resolution grid.
Definition REMORA.cpp:664
std::string riv_time_varname
Name of time field for river time.
Definition REMORA.H:1563
int foextrap_periodic_bc() const noexcept
Definition REMORA.H:1123
amrex::Vector< std::string > nc_clim_his_file
NetCDF climatology history file(s)
Definition REMORA.H:1541
int ncons
Number of conserved scalars in the state (temperature + salt + passive scalars)
Definition REMORA.H:1410
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_rv2d
v velocity RHS (2D, includes horizontal and vertical advection)
Definition REMORA.H:324
static amrex::Real fixed_dt
User specified fixed baroclinic time step.
Definition REMORA.H:1418
amrex::Real last_plot_file_time
Simulation time when we last output a plotfile.
Definition REMORA.H:1384
int zvel_bc() const noexcept
Definition REMORA.H:1118
void init_bathymetry_from_netcdf(int lev)
Bathymetry data initialization from NetCDF file.
void init_bcs()
Read in boundary parameters from input file and set up data structures.
int xvel_bc() const noexcept
Definition REMORA.H:1116
void calculate_nodal_masks(int lev)
Calculate u-, v-, and psi-point masks based on rho-point masks after analytic initialization.
std::unique_ptr< NCTimeSeries > qair_data_from_file
Data container for specific humidity read from file.
Definition REMORA.H:1236
static amrex::Real previousCPUTimeUsed
Accumulator variable for CPU time used thusfar.
Definition REMORA.H:1622
amrex::Vector< std::string > cons_names
Names of scalars for plotfile output.
Definition REMORA.H:1461
amrex::Vector< std::unique_ptr< amrex::YAFluxRegister > > advflux_reg
array of flux registers for refluxing in multilevel
Definition REMORA.H:1350
std::unique_ptr< NCTimeSeries > sustr_data_from_file
Data container for u-component surface momentum flux read from file.
Definition REMORA.H:1226
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_fcor
coriolis factor (2D)
Definition REMORA.H:469
void init_gls_vmix(int lev, SolverChoice solver_choice)
Initialize GLS variables.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_h
Bathymetry data (2D, positive valued, h in ROMS)
Definition REMORA.H:306
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:459
void set2DPlotVariables(const std::string &pp_plot_var_names_2d)
amrex::Vector< REMORAFillPatcher > FPr_v
Vector over levels of FillPatchers for v (3D)
Definition REMORA.H:1294
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:294
static bool write_history_file
Whether to output NetCDF files as a single history file with several time steps.
Definition REMORA.H:1223
void FillCoarsePatch(int lev, amrex::Real time, amrex::MultiFab *mf_fine, amrex::MultiFab *mf_crse, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=amrex::Real(0.0), const amrex::MultiFab &mf_calc=amrex::MultiFab())
fill an entire multifab by interpolating from the coarser level
void stretch_transform(int lev)
Calculate vertical stretched coordinates.
std::unique_ptr< NCTimeSeries > rain_data_from_file
Data container for precipitation rate read from file.
Definition REMORA.H:1244
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_vwind
Wind in the v direction, defined at rho-points.
Definition REMORA.H:374
std::unique_ptr< ProblemBase > prob
Pointer to container of analytical functions for problem definition.
Definition REMORA.H:1323
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:448
void Construct_REMORAFillPatchers(int lev)
Construct FillPatchers.
Definition REMORA.cpp:457
void init_grid_vars_from_netcdf(int lev)
Grid variable initialization from NetCDF file.
static int sum_interval
Diagnostic sum output interval in number of steps.
Definition REMORA.H:1506
int history_count
Counter for which time index we are writing to in the netcdf history file.
Definition REMORA.H:1454
amrex::Real stop_time
Time to stop.
Definition REMORA.H:1399
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_rain
precipitation rate [kg/m^2/s]
Definition REMORA.H:403
int do_substep
Whether to substep fine levels in time.
Definition REMORA.H:1427
void Evolve()
Advance solution to final time.
Definition REMORA.cpp:238
std::string bdry_time_varname
Default name of time field for boundary data.
Definition REMORA.H:1546
amrex::Real plotfile_fill_value
fill value for masked arrays in amrex plotfiles
Definition REMORA.H:1473
void ReadCheckpointFile()
read checkpoint file from disk
bool chunk_history_file
Whether to chunk netcdf history file.
Definition REMORA.H:1447
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_sustr
Surface stress in the u direction.
Definition REMORA.H:367
amrex::Real get_t_old(int lev) const
Accessor method for t_old to expose to outside classes.
Definition REMORA.cpp:1787
int yvel_bc() const noexcept
Definition REMORA.H:1117
std::unique_ptr< NCTimeSeries > longwave_down_data_from_file
Data container for downward longwave radiation flux read from file.
Definition REMORA.H:1242
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_ru2d
u velocity RHS (2D, includes horizontal and vertical advection)
Definition REMORA.H:322
amrex::Vector< std::string > datalogname
Definition REMORA.H:1654
amrex::Vector< amrex::MultiFab * > zvel_new
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:300
void init_only(int lev, amrex::Real time)
Init (NOT restart or regrid)
Definition REMORA.cpp:1191
void init_set_vmix(int lev)
Initialize vertical mixing coefficients from file or analytic.
Definition REMORA.cpp:711
std::unique_ptr< NCTimeSeries > v_clim_data_from_file
Data container for v-velocity climatology data read from file.
Definition REMORA.H:1257
std::string clim_u_time_varname
Name of time field for u climatology data.
Definition REMORA.H:1555
void set_grid_scale(int lev)
Set pm and pn arrays and x/y coords on level lev.
void set_coriolis(int lev)
Initialize Coriolis factor from file or analytic.
Definition REMORA.cpp:682
int foextrap_bc() const noexcept
Definition REMORA.H:1124
amrex::Vector< REMORAFillPatcher > FPr_u
Vector over levels of FillPatchers for u (3D)
Definition REMORA.H:1292
std::string clim_temp_time_varname
Name of time field for temperature climatology data.
Definition REMORA.H:1561
amrex::Vector< amrex::Vector< amrex::Box > > boxes_at_level
the boxes specified at each level by tagging criteria
Definition REMORA.H:1330
static amrex::Vector< amrex::AMRErrorTag > ref_tags
Holds info for dynamically generated tagging criteria.
Definition REMORA.H:1571
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Akt
Vertical diffusion coefficient (3D)
Definition REMORA.H:332
std::unique_ptr< NCTimeSeriesRiver > river_source_transportbar
Data container for vertically integrated momentum transport in rivers.
Definition REMORA.H:1268
std::array< bool, AtmosState::NumTypes > driver_atmos_state_from_driver
provenance flags for driver-supplied atmospheric forcing lanes
Definition REMORA.H:412
std::string clim_ubar_time_varname
Name of time field for ubar climatology data.
Definition REMORA.H:1551
std::unique_ptr< NCTimeSeries > u_clim_data_from_file
Data container for u-velocity climatology data read from file.
Definition REMORA.H:1255
std::string check_file
Checkpoint file prefix.
Definition REMORA.H:1440
static amrex::Real startCPUTime
Variable for CPU timing.
Definition REMORA.H:1620
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm_full_domain
horizontal scaling factor: 1 / dx (2D) on whole domain
Definition REMORA.H:463
amrex::Vector< amrex::MultiFab * > xvel_old
multilevel data container for last step's x velocities (u in ROMS)
Definition REMORA.H:287
amrex::Real start_time
Time of the start of the simulation, in seconds.
Definition REMORA.H:1402
void init_data_from_netcdf(int lev)
Problem initialization from NetCDF file.
void init_masks_from_netcdf(int lev)
Mask data initialization from NetCDF file.
amrex::Vector< amrex::MultiFab * > yvel_new
multilevel data container for current step's y velocities (v in ROMS)
Definition REMORA.H:298
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_uwind
Wind in the u direction, defined at rho-points.
Definition REMORA.H:372
static amrex::Real fixed_fast_dt
User specified fixed barotropic time step.
Definition REMORA.H:1420
int regrid_int
how often each level regrids the higher levels of refinement (after a level advances that many time s...
Definition REMORA.H:1430
amrex::Real check_int_time
Checkpoint output interval in seconds.
Definition REMORA.H:1444
void init_scalar_metadata()
Build runtime scalar names after nscalar is known.
Definition REMORA.cpp:225
void Define_REMORAFillPatchers(int lev)
Define FillPatchers.
Definition REMORA.cpp:506
amrex::Vector< amrex::IntVect > cum_ref_ratios
Cumulative refinement ratio between level 0 and level i.
Definition REMORA.H:1533
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_visc2_p
Harmonic viscosity defined on the psi points (corners of horizontal grid cells)
Definition REMORA.H:334
amrex::Real plot_int_time
Plotfile output interval in seconds.
Definition REMORA.H:1438
amrex::Vector< int > num_files_at_level
how many netcdf input files specified at each level
Definition REMORA.H:1328
amrex::Vector< REMORAFillPatcher > FPr_vbar
Vector over levels of FillPatchers for vbar (2D)
Definition REMORA.H:1302
void AverageDownTo(int crse_lev)
more flexible version of AverageDown() that lets you average down across multiple levels
Definition REMORA.cpp:1725
int steps_per_history_file
Number of time steps per netcdf history file.
Definition REMORA.H:1452
void post_timestep(int nstep, amrex::Real time, amrex::Real dt_lev)
Called after every level 0 timestep.
Definition REMORA.cpp:320
int max_step
maximum number of steps
Definition REMORA.H:1397
amrex::Vector< amrex::MultiFab * > zvel_old
multilevel data container for last step's z velocities (largely unused; W stored separately)
Definition REMORA.H:291
std::unique_ptr< NCTimeSeries > svstr_data_from_file
Data container for v-component surface momentum flux read from file.
Definition REMORA.H:1228
amrex::Vector< std::string > nc_frc_file
NetCDF forcing file(s)
Definition REMORA.H:1536
amrex::Vector< int > num_boxes_at_level
how many boxes specified at each level by tagging criteria
Definition REMORA.H:1326
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:296
void refinement_criteria_setup()
Set refinement criteria.
int last_check_file_step
Step when we last output a checkpoint file.
Definition REMORA.H:1387
void init_beta_plane_coriolis(int lev)
Calculate Coriolis parameters from beta plane parametrization.
std::string clim_vbar_time_varname
Name of time field for vbar climatology data.
Definition REMORA.H:1553
amrex::Vector< int > nsubsteps
How many substeps on each level?
Definition REMORA.H:1335
amrex::Vector< std::unique_ptr< REMORAPhysBCFunct > > physbcs
Vector (over level) of functors to apply physical boundary conditions.
Definition REMORA.H:1347
void ComputeDt()
a wrapper for estTimeStep()
void fill_3d_masks(int lev)
Copy maskr to all z levels.
std::unique_ptr< NCTimeSeries > EminusP_data_from_file
Data container for evaporation minus precipitation read from file.
Definition REMORA.H:1248
int plot_int
Plotfile output interval in iterations.
Definition REMORA.H:1436
void FillPatch(int lev, amrex::Real time, amrex::MultiFab &mf_to_be_filled, amrex::Vector< amrex::MultiFab * > const &mfs, const int bccomp, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const bool fill_set=true, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=amrex::Real(0.0), const amrex::MultiFab &mf_calc=amrex::MultiFab())
Fill a new MultiFab by copying in phi from valid region and filling ghost cells.
std::unique_ptr< NCTimeSeries > cloud_data_from_file
Data container for cloud cover fraction read from file.
Definition REMORA.H:1246
void InitData()
Initialize multilevel data.
Definition REMORA.cpp:352
void set3DPlotVariables(const std::string &pp_plot_var_names_3d)
amrex::Vector< int > istep
which step?
Definition REMORA.H:1333
void WriteCheckpointFile()
write checkpoint file to disk
std::string nc_clim_coeff_file
NetCDF climatology coefficient file.
Definition REMORA.H:1543
void setRecordDataInfo(int i, const std::string &filename)
Definition REMORA.H:1640
void set_analytic_vmix(int lev)
Set vertical mixing coefficients from analytic.
Definition REMORA.cpp:728
void init_flat_bathymetry(int lev)
Initialize flat bathymetry to value from problo.
Definition REMORA.cpp:1055
std::unique_ptr< NCTimeSeries > temp_clim_data_from_file
Data container for temperature climatology data read from file.
Definition REMORA.H:1259
amrex::Vector< std::string > bdry_time_name_byvar
Name of time fields for boundary data.
Definition REMORA.H:1548
static int file_min_digits
Minimum number of digits in plotfile name or chunked history file.
Definition REMORA.H:1511
void init_riv_pos_from_netcdf(int lev)
static amrex::Vector< std::string > nc_bdry_file
NetCDF boundary data.
Definition REMORA.H:51
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_visc2_r
Harmonic viscosity defined on the rho points (centers)
Definition REMORA.H:336
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_svstr
Surface stress in the v direction.
Definition REMORA.H:369
std::unique_ptr< NCTimeSeries > srflx_data_from_file
Data container for shortwave radiation flux read from file.
Definition REMORA.H:1240
REMORA()
Definition REMORA.cpp:62
void set_zeta(int lev)
Initialize zeta from file or analytic.
Definition REMORA.cpp:566
static amrex::Real change_max
Fraction maximum change in subsequent time steps.
Definition REMORA.H:1416
void init_zeta_from_netcdf(int lev)
Sea-surface height data initialization from NetCDF file.
void set_zeta_average(int lev)
Set Zt_avg1 to zeta.
void init_coriolis_from_netcdf(int lev)
Coriolis parameter data initialization from NetCDF file.
std::string pp_prefix
default prefix for input file parameters
Definition REMORA.H:282
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_h_full_domain
Bathymetry data on the whole domain at each potential level.
Definition REMORA.H:309
void set_bathymetry(int lev)
Initialize bathymetry from file or analytic.
Definition REMORA.cpp:594
amrex::Vector< amrex::MultiFab * > yvel_old
multilevel data container for last step's y velocities (v in ROMS)
Definition REMORA.H:289
std::unique_ptr< NCTimeSeries > ubar_clim_data_from_file
Data container for ubar climatology data read from file.
Definition REMORA.H:1251
amrex::Vector< REMORAFillPatcher > FPr_c
Vector over levels of FillPatchers for scalars.
Definition REMORA.H:1290
std::unique_ptr< NCTimeSeries > Tair_data_from_file
Data container for air temperature read from file.
Definition REMORA.H:1234
int nscalar
Number of passive scalars carried in the state.
Definition REMORA.H:1408
std::string clim_v_time_varname
Name of time field for v climatology data.
Definition REMORA.H:1557
amrex::Vector< REMORAFillPatcher > FPr_w
Vector over levels of FillPatchers for w.
Definition REMORA.H:1296
void average_down_with_grow_cells(int lev, amrex::Vector< std::unique_ptr< amrex::MultiFab > > &mf)
Average down from level lev+1 to lev in mf, including grow cells.
Definition REMORA.cpp:1753
std::string clim_salt_time_varname
Name of time field for salinity climatology data.
Definition REMORA.H:1559
std::unique_ptr< NCTimeSeries > Uwind_data_from_file
Data container for u-direction wind read from file.
Definition REMORA.H:1230
std::unique_ptr< NCTimeSeries > Pair_data_from_file
Data container for air pressure read from file.
Definition REMORA.H:1238
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1337
void init_stretch_coeffs()
initialize and calculate stretch coefficients
void init_bdry_from_netcdf(int lev)
Boundary data initialization from NetCDF file.
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1467
void set_masks(int lev)
Initialize land-sea masks from file or analytic.
Definition REMORA.cpp:744
amrex::Vector< amrex::Vector< std::unique_ptr< NCTimeSeriesBoundary > > > boundary_series
Vector over BdyVars of boundary series data containers.
Definition REMORA.H:1271
int cf_set_width
Width for fixing values at coarse-fine interface.
Definition REMORA.H:1287
void ReadParameters()
read in some parameters from inputs file
Definition REMORA.cpp:1468
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_ru
u velocity RHS (3D, includes horizontal and vertical advection)
Definition REMORA.H:318
void sum_integrated_quantities(amrex::Real time)
Integrate conserved quantities for diagnostics.
static int total_nc_plot_file_step
Definition REMORA.H:1131
static int plot_staggered_vels
Whether to write the staggered velocities (not averaged to cell centers)
Definition REMORA.H:1514
static amrex::Vector< amrex::Vector< std::string > > nc_grid_file
NetCDF grid file.
Definition REMORA.H:53
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_longwave_down
Downward longwave radiation.
Definition REMORA.H:387
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_zeta
free surface height (2D)
Definition REMORA.H:445
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_vbar
barotropic y velocity (2D)
Definition REMORA.H:443
void set_zeta_to_Ztavg(int lev)
Set zeta components to be equal to time-averaged Zt_avg1.
bool expand_plotvars_to_unif_rr
whether plotfile variables should be expanded to a uniform refinement ratio
Definition REMORA.H:1470
int plot_file_on_restart
Whether to output a plotfile on restart from checkpoint.
Definition REMORA.H:1391
void set_2darrays(int lev)
Set 2D momentum arrays from 3D momentum.
void init_analytic(int lev)
Initialize initial problem data from analytic functions.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_ubar
barotropic x velocity (2D)
Definition REMORA.H:441
amrex::Vector< amrex::MultiFab * > cons_old
multilevel data container for last step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:285
std::string frc_time_varname
Name of time field for forcing data.
Definition REMORA.H:1565
void set_wind(int lev)
Initialize or calculate wind speed from file or analytic.
Definition REMORA.cpp:1084
amrex::Vector< REMORAFillPatcher > FPr_ubar
Vector over levels of FillPatchers for ubar (2D)
Definition REMORA.H:1300
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.
std::unique_ptr< NCTimeSeries > Vwind_data_from_file
Data container for v-direction wind read from file.
Definition REMORA.H:1232
void init_bathymetry_full_domain_from_netcdf()
Full domain high-res bathymetry data initialization from NetCDF file.
void set_hmixcoef(int lev)
Initialize horizontal mixing coefficients.
Definition REMORA.cpp:770
amrex::Vector< std::unique_ptr< NCTimeSeriesRiver > > river_source_cons
Vector of data containers for scalar data in rivers.
Definition REMORA.H:1264
void timeStep(int lev, amrex::Real time, int iteration)
advance a level by dt, includes a recursive call for finer levels
std::unique_ptr< NCTimeSeriesRiver > river_source_transport
Data container for momentum transport in rivers.
Definition REMORA.H:1266
void init_grid_vars_full_domain_from_netcdf()
Full domain high-res grid variable initialization from NetCDF file.
void AverageDown()
set covered coarse cells to be the average of overlying fine cells
Definition REMORA.cpp:1712
static int fixed_ndtfast_ratio
User specified, number of barotropic steps per baroclinic step.
Definition REMORA.H:1422
amrex::Real netcdf_fill_value
fill value for masked arrays in netcdf output
Definition REMORA.H:1475
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn_full_domain
horizontal scaling factor: 1 / dy (2D) on whole domain
Definition REMORA.H:465
void timeStepML(amrex::Real time, int iteration)
advance all levels by dt, loops over finer levels
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:461
amrex::Vector< std::unique_ptr< std::fstream > > datalog
Definition REMORA.H:1653
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Akv
Vertical viscosity coefficient (3D)
Definition REMORA.H:330
static amrex::Real cfl
CFL condition.
Definition REMORA.H:1414
void append3DPlotVariables(const std::string &pp_plot_var_names_3d)
void allocate_bathymetry_grid_vars_full_domain()
Allocate multifabs for storing full-domain bathymetry and grid vars data.
static int verbose
Verbosity level of output.
Definition REMORA.H:1503
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_cloud
cloud cover fraction [0-1], defined at rho-points
Definition REMORA.H:407
std::string plot_file_name
Plotfile prefix.
Definition REMORA.H:1434
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Zt_avg1
Average of the free surface, zeta (2D)
Definition REMORA.H:364
std::unique_ptr< NCTimeSeries > salt_clim_data_from_file
Data container for salinity climatology data read from file.
Definition REMORA.H:1261
int check_int
Checkpoint output interval in iterations.
Definition REMORA.H:1442
void set_smflux(int lev)
Initialize or calculate surface momentum flux from file or analytic.
Definition REMORA.cpp:1065
void WritePlotFile(int istep)
main driver for writing AMReX plotfiles
std::string restart_chkfile
If set, restart from this checkpoint file.
Definition REMORA.H:1405
void init_clim_nudg_coeff(int lev)
Wrapper to initialize climatology nudging coefficient.
void init_bathymetry_full_domain_from_analytic()
Full domain bathymetry data initialization from analytic.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_rv
v velocity RHS (3D, includes horizontal and vertical advection)
Definition REMORA.H:320
int cf_width
Nudging width at coarse-fine interface.
Definition REMORA.H:1285
static amrex::Vector< amrex::Vector< std::string > > nc_init_file
NetCDF initialization file.
Definition REMORA.H:52
int last_plot_file_step
Step when we last output a plotfile.
Definition REMORA.H:1382
amrex::Vector< amrex::Real > t_old
old time at each level
Definition REMORA.H:1339
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_srflx
Shortwave radiation flux [W/m²], defined at rho-points.
Definition REMORA.H:383
amrex::Real last_check_file_time
Simulation time when we last output a checkpoint file.
Definition REMORA.H:1389
void append2DPlotVariables(const std::string &pp_plot_var_names_2d)
void set_bathymetry_averaged_down(int lev)
Copy over bathymetry data that has been averaged down from high resolution input netcdf file.
Definition REMORA.cpp:647
amrex::Vector< amrex::Real > dt
time step at each level
Definition REMORA.H:1341
static amrex::Real sum_per
Diagnostic sum output interval in time.
Definition REMORA.H:1508
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Pair
Air pressure [mb], defined at rho-points.
Definition REMORA.H:380
virtual ~REMORA()
Definition REMORA.cpp:220
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_qair
Specific humidity [kg/kg], defined at rho-points.
Definition REMORA.H:378
int hires_grid_level
Which level the high resolution bathymetry is at.
Definition REMORA.H:1527
void restart()
Definition REMORA.cpp:553
std::unique_ptr< NCTimeSeries > vbar_clim_data_from_file
Data container for vbar climatology data read from file.
Definition REMORA.H:1253
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Tair
Air temperature [°C], defined at rho-points.
Definition REMORA.H:376
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_diff2
Harmonic diffusivity for temperature / salinity.
Definition REMORA.H:338
static constexpr int cons_bc
static constexpr int Temp_bc_comp
const char * buildInfoGetGitHash(int i)
HorizMixingType horiz_mixing_type
amrex::Real Akv_bak
amrex::Vector< amrex::Real > tnu2
std::string longwave_netcdf_varname
amrex::Vector< int > do_rivers_cons
ScaledToGridAMRScaling scaled_to_grid_amr_scaling
amrex::Real Akt_bak
amrex::Real visc2
void init_params(int ncons)
read in and initialize parameters
SMFluxType smflux_type
VertMixingType vert_mixing_type
CouplingType coupling_type