REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_Tagging.cpp
Go to the documentation of this file.
1#include <REMORA.H>
2#include <REMORA_Derive.H>
3
4using namespace amrex;
5
6namespace {
7/**
8 * Copy mf's topmost and bottommost valid z-planes into its z-ghost planes.
9 *
10 * Several of the fields ErrorEst tags on live in MultiFabs with no ghost cells in z
11 * (zvel_new, vec_mskr3d), and the vorticity branch only ever computes valid cells, so
12 * mf's k = klo-1 and k = khi+1 planes would otherwise be read uninitialized by the GRAD
13 * (adjacent_difference_greater) test, which unconditionally differences k+-1. There is
14 * no data below k=0 or above k=N to copy, so impose a zero vertical gradient: GRAD then
15 * sees no vertical difference at the surface and bottom cells instead of garbage.
16 *
17 * @param[inout] mf single-component MultiFab with at least one ghost cell in z
18 */
19void
20fill_z_ghost_planes (MultiFab& mf)
21{
22 AMREX_ALWAYS_ASSERT(mf.nComp() == 1 && mf.nGrowVect()[2] >= 1);
23
24 // Not tiled: each iteration writes the two z-planes of a whole column, so tiling in
25 // z would have several tiles writing the same cell.
26#ifdef _OPENMP
27#pragma omp parallel if (Gpu::notInLaunchRegion())
28#endif
29 for (MFIter mfi(mf); mfi.isValid(); ++mfi)
30 {
31 const Box& vbx = mfi.validbox();
32 const int klo = vbx.smallEnd(2);
33 const int khi = vbx.bigEnd(2);
34
35 // Laterally grown as well, so the ghost columns get their z-planes too --
36 // GRAD reads i+-1 and j+-1 in those columns as well as k+-1.
37 const Box& gbx = mfi.fabbox();
38 auto arr = mf.array(mfi);
39
40 ParallelFor(makeSlab(gbx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept
41 {
42 arr(i,j,klo-1) = arr(i,j,klo);
43 arr(i,j,khi+1) = arr(i,j,khi);
44 });
45 }
46}
47
48/**
49 * Fill mf's lateral ghost cells from the nearest valid cell of the same box.
50 *
51 * Call this *before* FillBoundary: FillBoundary reads only valid regions, so it
52 * overwrites every ghost cell backed by a real same-level or periodic neighbor and
53 * leaves only the physical-boundary and coarse/fine ghosts holding the zero-gradient
54 * value written here. That keeps the GRAD test's i+-1 / j+-1 reads defined and
55 * deterministic everywhere without tagging on a jump we invented.
56 *
57 * @param[inout] mf single-component MultiFab
58 */
59void
61{
62 AMREX_ALWAYS_ASSERT(mf.nComp() == 1);
63 const IntVect ng = mf.nGrowVect();
64
65#ifdef _OPENMP
66#pragma omp parallel if (Gpu::notInLaunchRegion())
67#endif
68 for (MFIter mfi(mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
69 {
70 const Box& vbx = mfi.validbox();
71 const Box gbx = mfi.growntilebox(IntVect(ng[0],ng[1],0));
72 auto arr = mf.array(mfi);
73
74 const int ilo = vbx.smallEnd(0); const int ihi = vbx.bigEnd(0);
75 const int jlo = vbx.smallEnd(1); const int jhi = vbx.bigEnd(1);
76
77 ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
78 {
80 arr(i,j,k) = arr(amrex::min(amrex::max(i,ilo),ihi),
81 amrex::min(amrex::max(j,jlo),jhi), k);
82 }
83 });
84 }
85}
86} // namespace
87
88/**
89 * Function to tag cells for refinement -- this overrides the pure virtual function in AmrCore
90 *
91 * @param[in] levc level of refinement (0 is coarsest level)
92 * @param[out] tags array of tagged cells
93 * @param[in] time current time
94 * @param[in] ngrow number of grow cells
95*/
96void
97REMORA::ErrorEst (int levc, TagBoxArray& tags, Real time, int /*ngrow*/)
98{
99 const int clearval = TagBox::CLEAR;
100 const int tagval = TagBox::SET;
101
102 //
103 // This mf must have ghost cells because we may take differences between adjacent values
104 //
105 std::unique_ptr<MultiFab> mf = std::make_unique<MultiFab>(grids[levc], dmap[levc], 1, 1);
106
107 // Any cell-centered tracer may drive refinement, named as it is elsewhere: "temp",
108 // "salt", "tracer", "tracer_1", or a biology tracer such as "NO3".
109 auto cons_comp_for_field = [this] (const std::string& field) {
110 for (int icomp = 0; icomp < ncons; ++icomp) {
111 if (cons_names[icomp] == field) { return icomp; }
112 }
113 return -1;
114 };
115
116 for (int j=0; j < ref_tags.size(); ++j)
117 {
119
120 if (cons_comp >= 0) {
122 0,true,false);
123 }
124 // This allows dynamic refinement based on the value of a tracer
125 if (cons_comp >= 0)
126 {
127 MultiFab::Copy(*mf,*cons_new[levc],cons_comp,0,1,1);
128 } else if (ref_tags[j].Field() == "x_velocity") {
130 MultiFab::Copy(*mf,*xvel_new[levc],0,0,1,1);
131 } else if (ref_tags[j].Field() == "y_velocity") {
133 MultiFab::Copy(*mf,*yvel_new[levc],0,0,1,1);
134 } else if (ref_tags[j].Field() == "z_velocity") {
136 // zvel_new has no ghost cells in z, so we can only ask the copy for lateral ones
137 MultiFab::Copy(*mf,*zvel_new[levc],0,0,1,IntVect(1,1,0));
139 } else if (ref_tags[j].Field() == "vorticity") {
140 // Fill the ghost cells of the face-based velocities -- including at
141 // coarse/fine boundaries, which is what FillPatch's FillPatchTwoLevels
142 // interpolates -- since the cell-centered velocities in those ghost cells
143 // are read when computing vorticity below
147
148 // Vorticity needs no vertical neighbor, and zvel_new has no z ghost cells
149 // to average from, so only grow laterally
150 MultiFab mf_cc_vel(grids[levc],dmap[levc],3,IntVect(1,1,0));
153 yvel_new[levc],
154 zvel_new[levc]},
155 IntVect(1,1,0));
156 // Impose bc's at domain boundaries at all levels
158
159#ifdef _OPENMP
160#pragma omp parallel if (Gpu::notInLaunchRegion())
161#endif
162 for (MFIter mfi(*mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
163 {
164 const Box& bx = mfi.tilebox();
165 auto& dfab = (*mf)[mfi];
166 auto& sfab = mf_cc_vel[mfi];
167 auto pm = vec_pm[levc]->const_array(mfi);
168 auto pn = vec_pn[levc]->const_array(mfi);
169 auto maskr = vec_mskr[levc]->const_array(mfi);
170 derived::remora_dervort(bx, dfab, 0, 1, sfab, pm, pn, maskr, Geom(levc), time, nullptr, levc);
171 } // mfi
172
173 // remora_dervort only writes valid cells, so fill mf's own ghosts before the
174 // tagging criteria difference across them. The zero-gradient pass goes first;
175 // FillBoundary then replaces every ghost that has a real same-level or periodic
176 // neighbor, leaving only the physical-boundary and coarse/fine ghosts extrapolated.
178 mf->FillBoundary(geom[levc].periodicity());
180
181 } else if (ref_tags[j].Field() == "mask") {
182 // vec_mskr3d has no z ghost cells, so this copy leaves mf's top and bottom
183 // ghost planes unwritten while the GRAD test differences in z. The mask is
184 // constant down a column, so the zero vertical gradient imposed here is exact.
185 MultiFab::Copy(*mf,*vec_mskr3d[levc],0,0,1,IntVect(1,1,0));
187#ifdef REMORA_USE_PARTICLES
188 } else {
189 //
190 // This allows dynamic refinement based on the number of particles per cell
191 //
192 // Note that we must count all the particles in levels both at and above the current,
193 // since otherwise, e.g., if the particles are all at level 1, counting particles at
194 // level 0 will not trigger refinement when regridding so level 1 will disappear,
195 // then come back at the next regridding
196 //
197 const auto& particles_namelist( particleData.getNames() );
198 mf->setVal(zero);
199 bool matched_particle_count = false;
200 for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++)
201 {
202 std::string tmp_string(particles_namelist[i]+"_count");
203 IntVect rr = IntVect::TheUnitVector();
204 if (ref_tags[j].Field() == tmp_string) {
206 for (int lev = levc; lev <= finest_level; lev++)
207 {
208 MultiFab temp_dat(grids[lev], dmap[lev], 1, 0); temp_dat.setVal(0);
209 particleData[particles_namelist[i]]->IncrementWithTotal(temp_dat, lev);
210
211 MultiFab temp_dat_crse(grids[levc], dmap[levc], 1, 0); temp_dat_crse.setVal(0);
212
213 if (lev == levc) {
214 MultiFab::Copy(*mf, temp_dat, 0, 0, 1, 0);
215 } else {
216 for (int d = 0; d < AMREX_SPACEDIM; d++) {
217 rr[d] *= ref_ratio[levc][d];
218 }
220 MultiFab::Add(*mf, temp_dat_crse, 0, 0, 1, 0);
221 }
222 }
223 }
224 }
225
226 // A box-only indicator carries no field name and tags geometrically, so it
227 // never reads mf; only a named field that matched nothing is an error.
229 amrex::Abort("Unknown refinement field '" + ref_tags[j].Field() +
230 "'. Use a tracer name, x_velocity, y_velocity, z_velocity, "
231 "vorticity, mask, or <particle>_count.");
232 }
233#else
234 } else if (!ref_tags[j].Field().empty()) {
235 // mf is uninitialized until something writes it, so an unrecognized named
236 // field would otherwise tag on garbage. A box-only indicator has no field
237 // name, tags geometrically, and never reads mf.
238 amrex::Abort("Unknown refinement field '" + ref_tags[j].Field() +
239 "'. Use a tracer name, x_velocity, y_velocity, z_velocity, "
240 "vorticity, or mask.");
241#endif
242 }
243
245 }
246
247 // Promote any tagged cell to a full local z-column.
248 for (MFIter mfi(tags, TilingIfNotGPU()); mfi.isValid(); ++mfi)
249 {
250 const Box& bx = mfi.validbox();
251 auto const& tag = tags.array(mfi);
252
253 const int klo = bx.smallEnd(2);
254 const int khi = bx.bigEnd(2);
255
256 amrex::ParallelFor(makeSlab(bx, 2, 0),
257 [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept
258 {
259 bool refine_col = false;
260 for (int k = klo; k <= khi; ++k) {
261 refine_col = refine_col || (tag(i,j,k) != TagBox::CLEAR);
262 }
263
264 if (refine_col) {
265 for (int k = klo; k <= khi; ++k) {
266 tag(i,j,k) = TagBox::SET;
267 }
268 }
269 });
270 }
271}
272
273/**
274 * Function to define the refinement criteria based on user input
275*/
276void
278{
279 if (max_level > 0)
280 {
282 Vector<std::string> refinement_indicators;
283 pp.queryarr("refinement_indicators",refinement_indicators,0,pp.countval("refinement_indicators"));
284 for (int i=0; i<refinement_indicators.size(); ++i)
285 {
286 std::string ref_prefix = pp_prefix + "." + refinement_indicators[i];
287
290 int lev_for_box;
291
292 int num_real_lo = ppr.countval("in_box_lo");
293 int num_indx_lo = ppr.countval("in_box_lo_indices");
294 int num_indx_lo_crse = ppr.countval("in_box_lo_indices_crse");
295
296 int num_real_hi = ppr.countval("in_box_hi");
297 int num_indx_hi = ppr.countval("in_box_hi_indices");
298 int num_indx_hi_crse = ppr.countval("in_box_hi_indices_crse");
299
303
304 // Problem low and high (in real not index space) are the same at all levels
305 if ( !((num_real_lo >= AMREX_SPACEDIM-1 && num_indx_lo == 0 && num_indx_lo_crse == 0) ||
307 (num_indx_lo == 0 && num_real_lo == 0 && num_indx_lo_crse == 0) ||
309 ) )
310 {
311 amrex::Abort("Must only specify box for refinement using real OR index space with fine/coarse grid indices");
312 }
313
314 if (num_real_lo > 0) {
315 std::vector<Real> box_lo(3), box_hi(3);
316 ppr.get("max_level",lev_for_box);
317 if (lev_for_box > 0 && lev_for_box <= max_level)
318 {
319 ppr.getarr("in_box_lo",box_lo,0,2);
320 ppr.getarr("in_box_hi",box_hi,0,2);
321 box_lo[2] = geom[0].ProbLo(2);
322 box_hi[2] = geom[0].ProbHi(2);
323 realbox = RealBox(&(box_lo[0]),&(box_hi[0]));
324
325 amrex::Print() << "Reading " << realbox << " at level " << lev_for_box << std::endl;
327
328 const auto* dx = geom[lev_for_box].CellSize();
329 const Real* plo = geom[lev_for_box].ProbLo();
330
331 int ilo = static_cast<int>((box_lo[0] - plo[0])/dx[0]);
332 int jlo = static_cast<int>((box_lo[1] - plo[1])/dx[1]);
333 int klo = static_cast<int>((box_lo[2] - plo[2])/dx[2]);
334 int ihi = static_cast<int>((box_hi[0] - plo[0])/dx[0]-1);
335 int jhi = static_cast<int>((box_hi[1] - plo[1])/dx[1]-1);
336 int khi = static_cast<int>((box_hi[2] - plo[2])/dx[2]-1);
337
338 Box bx_old(IntVect(ilo,jlo,klo),IntVect(ihi,jhi,khi));
339
340 int mod_ilo = ilo%ref_ratio[lev_for_box-1][0];
341 int mod_jlo = jlo%ref_ratio[lev_for_box-1][1];
342
343 int mod_ihi = (ihi+1)%ref_ratio[lev_for_box-1][0];
344 int mod_jhi = (jhi+1)%ref_ratio[lev_for_box-1][1];
345
346 if (mod_ilo != 0) {
347 ilo -= mod_ilo;
348 }
349 if (mod_jlo != 0) {
350 jlo -= mod_jlo;
351 }
352 if (mod_ihi != 0) {
353 ihi += ref_ratio[lev_for_box-1][0] - mod_ihi;
354 }
355 if (mod_jhi != 0) {
356 jhi += ref_ratio[lev_for_box-1][1] - mod_jhi;
357 }
358 Box bx(IntVect(ilo,jlo,klo),IntVect(ihi,jhi,khi));
359 if (mod_ilo !=0 || mod_jlo !=0 || mod_ihi != 0 || mod_jhi != 0) {
360 amrex::Print() << "Fine box on level " << lev_for_box << " adjusted from " << bx_old << " to " << bx << " to make it valid for refinement." << std::endl;
361 }
362 boxes_at_level[lev_for_box].push_back(bx);
363 amrex::Print() << "Saving in 'boxes at level' as " << bx << std::endl;
364 } // lev
365
366 } else if (num_indx_lo > 0) {
367
368 std::vector<int> box_lo(3), box_hi(3);
369 ppr.get("max_level",lev_for_box);
370 if (lev_for_box > 0 && lev_for_box <= max_level)
371 {
372 if (n_error_buf[0] != IntVect::TheZeroVector()) {
373 amrex::Abort("Don't use n_error_buf > 0 when setting the box explicitly");
374 }
375
376 ppr.getarr("in_box_lo_indices",box_lo,0,num_indx_lo);
377 ppr.getarr("in_box_hi_indices",box_hi,0,num_indx_hi);
378
380 box_lo[2] = geom[lev_for_box].Domain().smallEnd(2);
381 box_hi[2] = geom[lev_for_box].Domain().bigEnd(2);
382 }
383
384 Box bx(IntVect(box_lo[0],box_lo[1],box_lo[2]),IntVect(box_hi[0],box_hi[1],box_hi[2]));
385 const Box& domain = geom[lev_for_box].Domain();
386
387 if (!domain.contains(bx)) {
388 amrex::Print() << "\n";
389 amrex::Print() << "Box specified is " << bx << std::endl;
390 amrex::Print() << "But domain at level is " << domain << std::endl;
391 amrex::Error("Specified box doesn't fit in the domain");
392 }
393
394 const auto* dx = geom[lev_for_box].CellSize();
395 const Real* plo = geom[lev_for_box].ProbLo();
396 realbox = RealBox(plo[0]+ box_lo[0] *dx[0], plo[1]+ box_lo[1] *dx[1], plo[2]+ box_lo[2] *dx[2],
397 plo[0]+(box_hi[0]+1)*dx[0], plo[1]+(box_hi[1]+1)*dx[1], plo[2]+(box_hi[2]+1)*dx[2]);
398
399 Print() << "Reading " << bx << " at level " << lev_for_box << std::endl;
401
402 if(box_lo[0]%ref_ratio[lev_for_box-1][0] != 0){
403 amrex::Print()<< "Requested ilo in x-direction : " << box_lo[0] << std::endl;
404 amrex::Print() << "ilo = " << box_lo[0] << " is not divisible by ref_ratio in x direction = " <<
405 ref_ratio[lev_for_box-1][0] << std::endl;
406 amrex::Error("Adjust in_box_lo_indices in x-direction to be divisible by ref_ratio and try again");
407 }
408 if((box_hi[0]+1)%ref_ratio[lev_for_box-1][0] != 0){
409 amrex::Print()<< "Requested ihi in x-direction : " << box_hi[0] << std::endl;
410 amrex::Print() << "ihi+1 = " << box_hi[0]+1 << " is not divisible by ref_ratio in x direction = " <<
411 ref_ratio[lev_for_box-1][0] << std::endl;
412 amrex::Error("Adjust in_box_hi_indices in x-direction to be divisible by ref_ratio and try again");
413 }
414 if(box_lo[1]%ref_ratio[lev_for_box-1][1] != 0){
415 amrex::Print()<< "Requested jlo in y-direction : " << box_lo[1] << std::endl;
416 amrex::Print() << "jlo = " << box_lo[1] << " is not divisible by ref_ratio in y direction = " <<
417 ref_ratio[lev_for_box-1][1] << std::endl;
418 amrex::Error("Adjust in_box_lo_indices in y-direction to be divisible by ref_ratio and try again");
419 }
420 if((box_hi[1]+1)%ref_ratio[lev_for_box-1][1] != 0){
421 amrex::Print()<< "Requested jhi in y-direction : " << box_hi[1] << std::endl;
422 amrex::Print() << "jhi+1 = " << box_hi[1]+1 << " is not divisible by ref_ratio in y direction = " <<
423 ref_ratio[lev_for_box-1][1] << std::endl;
424 amrex::Error("Adjust in_box_hi_indices in y-direction to be divisible by ref_ratio and try again");
425 }
426 if(box_lo[2]%ref_ratio[lev_for_box-1][2] != 0){
427 amrex::Print()<< "Requested klo in z-direction : " << box_lo[2] << std::endl;
428 amrex::Print() << "klo = " << box_lo[2] << " is not divisible by ref_ratio in z direction = " <<
429 ref_ratio[lev_for_box-1][2] << std::endl;
430 amrex::Error("Adjust in_box_lo_indices in z-direction to be divisible by ref_ratio and try again");
431 }
432 if((box_hi[2]+1)%ref_ratio[lev_for_box-1][2] != 0){
433 amrex::Print()<< "Requested khi in z-direction : " << box_hi[2] << std::endl;
434 amrex::Print() << "khi+1 = " << box_hi[2]+1 << " is not divisible by ref_ratio in z direction = " <<
435 ref_ratio[lev_for_box-1][2] << std::endl;
436 amrex::Error("Adjust in_box_hi_indices in z-direction to be divisible by ref_ratio and try again");
437 }
438
439 boxes_at_level[lev_for_box].push_back(bx);
440 Print() << "Saving in 'boxes at level' as " << bx << std::endl;
441 } // lev
442
443 } else if (num_indx_lo_crse > 0) {
444
445 std::vector<int> box_lo(3), box_hi(3);
446 ppr.get("max_level",lev_for_box);
447 if (lev_for_box > 0 && lev_for_box <= max_level)
448 {
449 if (n_error_buf[0] != IntVect::TheZeroVector()) {
450 amrex::Abort("Don't use n_error_buf > 0 when setting the box explicitly");
451 }
452
453 ppr.getarr("in_box_lo_indices_crse",box_lo,0,num_indx_lo_crse);
454 ppr.getarr("in_box_hi_indices_crse",box_hi,0,num_indx_hi_crse);
455
457 box_lo[2] = geom[lev_for_box-1].Domain().smallEnd(2);
458 box_hi[2] = geom[lev_for_box-1].Domain().bigEnd(2);
459 }
460
461 Box bx(IntVect(box_lo[0],box_lo[1],box_lo[2]),IntVect(box_hi[0],box_hi[1],box_hi[2]));
462
463 if (!geom[lev_for_box-1].Domain().contains(bx)) {
464 amrex::Print() << "\n";
465 amrex::Print() << "(Coarse) Box specified is " << bx << std::endl;
466 amrex::Print() << "But (coarse) domain at level is " << geom[lev_for_box-1].Domain() << std::endl;
467 amrex::Error("Specified box doesn't fit in the domain");
468 }
469
470 bx.refine(ref_ratio[lev_for_box-1]);
471
472 const auto* dx = geom[lev_for_box-1].CellSize();
473
474 const Real* plo = geom[lev_for_box].ProbLo();
475 realbox = RealBox(plo[0]+ box_lo[0] *dx[0], plo[1]+ box_lo[1] *dx[1], plo[2]+ box_lo[2] *dx[2],
476 plo[0]+(box_hi[0]+1)*dx[0], plo[1]+(box_hi[1]+1)*dx[1], plo[2]+(box_hi[2]+1)*dx[2]);
477
478 Print() << "Reading " << bx << " at level " << lev_for_box << std::endl;
480
481 boxes_at_level[lev_for_box].push_back(bx);
482 Print() << "Saving in 'boxes at level' as " << bx << std::endl;
483 } // lev
484 }
485
487
488 if (realbox.ok()) {
489 info.SetRealBox(realbox);
490 }
491 if (ppr.countval("start_time") > 0) {
492 Real ref_min_time; ppr.get("start_time",ref_min_time);
493 info.SetMinTime(ref_min_time);
494 }
495 if (ppr.countval("end_time") > 0) {
496 Real ref_max_time; ppr.get("end_time",ref_max_time);
497 info.SetMaxTime(ref_max_time);
498 }
499 if (ppr.countval("max_level") > 0) {
500 int ref_max_level; ppr.get("max_level",ref_max_level);
501 info.SetMaxLevel(ref_max_level);
502 }
503
504 if (ppr.countval("value_greater")) {
505 int num_val = ppr.countval("value_greater");
507 ppr.getarr("value_greater",value,0,num_val);
508 std::string field; ppr.get("field_name",field);
509 ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::GREATER,field,info));
510 }
511 else if (ppr.countval("value_less")) {
512 int num_val = ppr.countval("value_less");
514 ppr.getarr("value_less",value,0,num_val);
515 std::string field; ppr.get("field_name",field);
516 ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::LESS,field,info));
517 }
518 else if (ppr.countval("adjacent_difference_greater")) {
519 int num_val = ppr.countval("adjacent_difference_greater");
521 ppr.getarr("adjacent_difference_greater",value,0,num_val);
522 std::string field; ppr.get("field_name",field);
523 ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::GRAD,field,info));
524 }
525 else if (realbox.ok())
526 {
527 ref_tags.push_back(AMRErrorTag(info));
528 } else {
529 Abort(std::string("Unrecognized refinement indicator for " + refinement_indicators[i]).c_str());
530 }
531 } // loop over criteria
532 {
533 // Untag anywhere we have masks
535 info.SetDerefine(1);
536 Real value = Real(0.5);
537 ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::LESS,"mask",info));
538 }
539 {
540 // Also untag at mask-water boundaries
542 info.SetDerefine(1);
543 Real value = Real(0.5);
544 ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::GRAD,"mask",info));
545 }
546 } // if max_level > 0
547}
constexpr amrex::Real zero
mf_h setVal(geomdata.ProbHi(2))
AMREX_ALWAYS_ASSERT(!NSPeriodic||!EWPeriodic)
int ncons
Number of conserved scalars in the state (temperature + salt + passive scalars + biology tracers)
Definition REMORA.H:1644
int zvel_bc() const noexcept
Definition REMORA.H:1315
int xvel_bc() const noexcept
Definition REMORA.H:1313
amrex::Vector< std::string > cons_names
Names of scalars for plotfile output.
Definition REMORA.H:1709
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:568
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:386
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:557
int yvel_bc() const noexcept
Definition REMORA.H:1314
amrex::Vector< amrex::MultiFab * > zvel_new
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:392
amrex::Vector< amrex::Vector< amrex::Box > > boxes_at_level
the boxes specified at each level by tagging criteria
Definition REMORA.H:1549
static amrex::Vector< amrex::AMRErrorTag > ref_tags
Holds info for dynamically generated tagging criteria.
Definition REMORA.H:1831
amrex::Vector< amrex::MultiFab * > yvel_new
multilevel data container for current step's y velocities (v in ROMS)
Definition REMORA.H:390
amrex::Vector< int > num_boxes_at_level
how many boxes specified at each level by tagging criteria
Definition REMORA.H:1545
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:388
void refinement_criteria_setup()
Set refinement criteria.
virtual void ErrorEst(int lev, amrex::TagBoxArray &tags, amrex::Real time, int ngrow) override
Tag cells for refinement.
void FillBdyCCVels(int lev, amrex::MultiFab &mf_cc_vel)
Fill the physical boundary conditions for cell-centered velocity (diagnostic only)
std::string pp_prefix
default prefix for input file parameters
Definition REMORA.H:374
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=false, const int n_not_fill=0, const int icomp_calc=0, const amrex::Real dt=zero, const amrex::MultiFab &mf_calc=amrex::MultiFab())
Fill a new MultiFab by copying in phi from valid region and filling ghost cells.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:570
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr3d
land/sea mask at cell centers, copied to all z levels (3D)
Definition REMORA.H:565
static constexpr int cons_bc
static constexpr int t
cons component Temp_comp
static constexpr int u
static constexpr int v
static constexpr int null
void remora_dervort(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Array4< const amrex::Real > &pm, const amrex::Array4< const amrex::Real > &pn, const amrex::Array4< const amrex::Real > &, const amrex::Geometry &, amrex::Real, const int *, const int)