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