REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_init_from_netcdf.cpp
Go to the documentation of this file.
1/**
2 * \file REMORA_init_from_netcdf.cpp
3 */
4
5#include <REMORA.H>
6#include <REMORA_Constants.H>
8#include <REMORA_DataStruct.H>
9
10using namespace amrex;
11
12#ifdef REMORA_USE_NETCDF
13
14/** \brief helper function for reading in initial state data from netcdf */
15void
16read_data_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
17 FArrayBox& NC_temp_fab, FArrayBox& NC_salt_fab,
18 FArrayBox& NC_xvel_fab, FArrayBox& NC_yvel_fab);
19
20/** \brief helper function for reading in full domain high-resolution initial state data from netcdf */
21void
22read_data_full_domain_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
23 FArrayBox& NC_temp_fab, FArrayBox& NC_salt_fab,
24 FArrayBox& NC_xvel_fab, FArrayBox& NC_yvel_fab,
25 IntVect ngrow);
26
27/** \brief helper function for reading in initial biology data from netcdf */
28void
29read_biology_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
30 const Vector<std::string>& biology_names,
32
33/** \brief helper function for reading in full domain high-resolution initial biology data from netcdf */
34void
35read_biology_full_domain_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
36 const Vector<std::string>& biology_names,
38
39/** \brief helper function for reading in initial passive (dye) scalar data from netcdf */
40void
41read_scalars_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
42 const Vector<std::string>& scalar_names,
44 Vector<int>& scalar_in_file);
45
46/** \brief helper function for reading in full domain high-resolution initial passive (dye) scalar data from netcdf */
47void
48read_scalars_full_domain_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
49 const Vector<std::string>& scalar_names,
51 Vector<int>& scalar_in_file, IntVect ngrow);
52
53/** \brief helper function checking that a high-resolution file covers the refined domain plus grow cells */
54void
55check_hires_dims_from_netcdf (const std::string& fname, const std::string& var_name,
56 const Box& domain, const IntVect& ngrow);
57
58/** \brief helper function for reading in land-sea masks from netcdf */
59void
60read_masks_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
61 FArrayBox& NC_mskr_fab, FArrayBox& NC_msku_fab,
62 FArrayBox& NC_mskv_fab);
63
64/** \brief helper function to initialize state from netcdf */
65void
67 FArrayBox& temp_fab, FArrayBox& salt_fab,
68 FArrayBox& x_vel_fab, FArrayBox& y_vel_fab,
73
74/** \brief helper function to initialize biology tracer state from netcdf */
75void
78
79/** \brief helper function to initialize passive (dye) scalar state from netcdf */
80void
83 const Vector<Vector<int>>& scalar_in_file);
84
85/** \brief helper function to read bathymetry from netcdf */
86void
87read_bathymetry_from_netcdf (int lev, const Box& domain, const std::string& fname,
88 FArrayBox& NC_h_fab);
89
90/** \brief helper function to read grid variables from netcdf */
91void
92read_grid_vars_from_netcdf (int lev, const Box& domain, const std::string& fname,
93 FArrayBox& NC_pm_fab, FArrayBox& NC_pn_fab,
94 FArrayBox& NC_xr_fab, FArrayBox& NC_yr_fab,
95 FArrayBox& NC_xu_fab, FArrayBox& NC_yu_fab,
96 FArrayBox& NC_xv_fab, FArrayBox& NC_yv_fab,
97 FArrayBox& NC_xp_fab, FArrayBox& NC_yp_fab);
98
99/** \brief helper function to read optional spherical psi coordinates from netcdf */
100bool
101read_spherical_grid_vars_from_netcdf (int lev, const Box& domain, const std::string& fname,
102 FArrayBox& NC_lonp_fab, FArrayBox& NC_latp_fab);
103
104/** \brief helper function to read full-domain high resolution bathymetry from netcdf */
105void
106read_bathymetry_full_domain_from_netcdf (const Box& domain, const std::string& fname,
107 FArrayBox& NC_h_fab, IntVect ngrow);
108
109/** \brief helper function to read full-domain high resolution grid variables from netcdf */
110void
111read_grid_vars_full_domain_from_netcdf (const Box& domain, const std::string& fname,
112 FArrayBox& NC_pm_fab, FArrayBox& NC_pn_fab,
113 IntVect ngrow);
114
115/** \brief helper function to read coriolis factor from netcdf */
116void
117read_coriolis_from_netcdf (int lev, const Box& domain, const std::string& fname, FArrayBox& NC_fcor_fab);
118
119/** \brief helper function to read sea surface height from netcdf */
120void
121read_zeta_from_netcdf (int lev, const Box& domain, const std::string& fname,
122 FArrayBox& NC_zeta_fab);
123
124/** \brief helper function to read high-resolution full-domain sea surface height from netcdf */
125void
126read_zeta_full_domain_from_netcdf (int lev, const Box& domain, const std::string& fname,
127 FArrayBox& NC_zeta_fab, IntVect ngrow);
128
129/** \brief helper function to read climatology nudging from netcdf */
130void
131read_clim_nudg_coeff_from_netcdf (int lev, const Box& domain, const std::string& fname,
132 bool do_m2_clim_nudg,
133 bool do_m3_clim_nudg,
134 const amrex::Vector<int>& do_cons_clim_nudg,
135 const amrex::Vector<std::string>& cons_names,
136 FArrayBox& NC_M2NC_fab,
137 FArrayBox& NC_M3NC_fab,
138 amrex::Vector<FArrayBox>& NC_ConsNC_fab,
139 amrex::Vector<int>& cons_coeff_in_file);
140
141/** \brief helper function to read in vector of data from netcdf */
142void read_vec_from_netcdf (int lev, const amrex::Vector<std::string>& fnames, const std::string& field_name, amrex::Vector<int>& vec_dat);
143
144/**
145 * @param lev Integer specifying the current level
146 */
147void
149{
150 // *** FArrayBox's at this level for holding the INITIAL data
155
156 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
157 {
161 }
162
163
164 MultiFab mf_temp(*cons_new[lev], make_alias, Temp_comp, 1);
165 MultiFab mf_salt(*cons_new[lev], make_alias, Salt_comp, 1);
166
167#ifdef _OPENMP
168#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
169#endif
170 {
171 // Don't tile this since we are operating on full FABs in this routine
172 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
173 {
174 // Define fabs for holding the initial data
175 FArrayBox &temp_fab = mf_temp[mfi];
176 FArrayBox &salt_fab = mf_salt[mfi];
177 FArrayBox &xvel_fab = (*xvel_new[lev])[mfi];
178 FArrayBox &yvel_fab = (*yvel_new[lev])[mfi];
179
184 } // mf
185 } // omp
186
187 // Zero every tracer past salinity. This is the starting point for the passive
188 // scalars, which the read below overwrites for each dye the file carries; the
189 // biology block is overwritten by init_biology_ic immediately after, so zeroing it
190 // here only guards against a partially filled biology IC.
192
193 // Passive scalars come from the same file, and from the same remora.ic_type that
194 // brought us here, so they are read here rather than through a source flag of
195 // their own the way biology is.
197}
198
199/**
200 * \brief Initialize the passive (dye) scalars from the initial NetCDF file.
201 *
202 * Unlike biology, dye has no initialization-source flag of its own: it follows
203 * remora.ic_type along with temperature, salinity, and velocity, so this is called
204 * from init_data_from_netcdf rather than from a dispatcher. Each dye whose variable
205 * the file carries is read into its own component; the rest keep the zero written
206 * just before the call.
207 *
208 * @param lev Integer specifying the current level
209 */
210void
212{
213 if (nscalar == 0) {
214 return;
215 }
216
217 Vector<std::string> scalar_names;
218 scalar_names.reserve(nscalar);
219 for (int icomp = Tracer_comp; icomp < Bio_comp; ++icomp) {
220 scalar_names.push_back(cons_names[icomp]);
221 }
222
223 // One FAB and one presence flag per dye per box
226 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
227 {
228 NC_scalar_fab[idx].resize(scalar_names.size());
231 }
232
234
235#ifdef _OPENMP
236#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
237#endif
238 {
239 // Don't tile this since we are operating on full FABs in this routine
240 for (MFIter mfi(mf_scalar, false); mfi.isValid(); ++mfi)
241 {
242 FArrayBox& scalar_fab = mf_scalar[mfi];
244 }
245 }
246}
247
248/**
249 * \brief Initialize the biological tracers from the initial NetCDF file.
250 *
251 * Called from init_biology_ic, which chooses between this and the analytic
252 * profile on remora.biology_ic_type rather than on remora.ic_type.
253 *
254 * @param lev Integer specifying the current level
255 */
256void
258{
260 return;
261 }
262
263 Vector<std::string> biology_names;
264 biology_names.reserve(nbio);
265 for (int icomp = Bio_comp; icomp < ncons; ++icomp) {
266 biology_names.push_back(cons_names[icomp]);
267 }
268
271 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
272 {
273 NC_biology_fab[idx].resize(biology_names.size());
276 }
277
279
280#ifdef _OPENMP
281#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
282#endif
283 {
284 // Dont tile this since we are operating on full FABs in this routine
285 for (MFIter mfi(mf_biology, false); mfi.isValid(); ++mfi)
286 {
287 FArrayBox& biology_fab = mf_biology[mfi];
289 }
290 }
291}
292
293void
295{
296 if (nc_init_file_hires.empty()) {
297 Abort("Must specify high-resolution initial file when initializing from NetCDF and hires_init_level > 0");
298 }
301
302 // *** FArrayBox's at this level for holding the INITIAL data
307
312
315
316#ifdef _OPENMP
317#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
318#endif
319 {
320 // Don't tile this since we are operating on full FABs in this routine
321 for ( MFIter mfi(mf_temp, false); mfi.isValid(); ++mfi )
322 {
323 // Define fabs for holding the initial data
324 FArrayBox &temp_fab = mf_temp[mfi];
325 FArrayBox &salt_fab = mf_salt[mfi];
328
333 } // mf
334 } // omp
335
337
338 // Passive scalars, before the average down below carries this level's data to the
339 // levels beneath it. Biology is filled separately by init_biology_ic_full_domain,
340 // which does its own average down.
342
343 // Average down to fill levels below hires_grid_level. Use a special average_down so
344 // grow cells get populated by averaged down fine data
345 for (int lev=hires_init_level-1; lev >= 0; lev--) {
349 }
350}
351
352/**
353 * \brief Full-domain counterpart of init_scalars_from_netcdf, for the hires_init_level
354 * average-down path. Called from init_data_full_domain_from_netcdf before that
355 * routine averages vec_cons_full_domain down, so no average down is needed here.
356 */
357void
359{
360 if (nscalar == 0) {
361 return;
362 }
363
364 Vector<std::string> scalar_names;
365 scalar_names.reserve(nscalar);
366 for (int icomp = Tracer_comp; icomp < Bio_comp; ++icomp) {
367 scalar_names.push_back(cons_names[icomp]);
368 }
369
372 NC_scalar_fab[0].resize(scalar_names.size());
373
377
379
380#ifdef _OPENMP
381#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
382#endif
383 {
384 // Don't tile this since we are operating on full FABs in this routine
385 for (MFIter mfi(mf_scalar, false); mfi.isValid(); ++mfi)
386 {
387 FArrayBox& scalar_fab = mf_scalar[mfi];
389 }
390 }
391}
392
393/** \brief Biology initialization from full-domain NetCDF file */
394void
396{
398 return;
399 }
400
401 Vector<std::string> biology_names;
402 biology_names.reserve(nbio);
403 for (int icomp = Bio_comp; icomp < ncons; ++icomp) {
404 biology_names.push_back(cons_names[icomp]);
405 }
406
408 NC_biology_fab.resize(1);
409 NC_biology_fab[0].resize(biology_names.size());
410
414
416
417#ifdef _OPENMP
418#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
419#endif
420 {
421 // Dont tile this since we are operating on full FABs in this routine
422 for (MFIter mfi(mf_biology, false); mfi.isValid(); ++mfi)
423 {
424 FArrayBox& biology_fab = mf_biology[mfi];
426 }
427 }
428
429 // The average-down lives in init_biology_ic_full_domain, which owns both sources.
430}
431
432/**
433 * @param lev Integer specifying the current level
434 */
435void
437{
438 // *** FArrayBox's at this level for holding the INITIAL data
440
441 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
442 {
445
446#ifdef _OPENMP
447#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
448#endif
449 {
450 // Don't tile this since we are operating on full FABs in this routine
451 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
452 {
453 FArrayBox &zeta_fab = (*vec_zeta[lev])[mfi];
454
455 //
456 // FArrayBox to FArrayBox copy does "copy on intersection"
457 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
458 //
459
461 } // mf
462 } // omp
463 } // idx
464
465 vec_zeta[lev]->FillBoundary(geom[lev].periodicity());
466 (*physbcs[lev])(*vec_zeta[lev],*vec_mskr[lev].get(),0,1,vec_zeta[lev]->nGrowVect(),t_new[lev],zeta_bc(),0,*vec_zeta[lev],*vec_msku[lev],*vec_mskv[lev]);
467// (*physbcs[lev])(*vec_zeta[lev],*vec_mskr[lev].get(),1,1,vec_zeta[lev]->nGrowVect(),t_new[lev],BCVars::zeta_bc);
468// (*physbcs[lev])(*vec_zeta[lev],*vec_mskr[lev].get(),2,1,vec_zeta[lev]->nGrowVect(),t_new[lev],BCVars::zeta_bc);
469
471 Real told = t_new[lev];
473 *vec_zeta[lev]);
474 }
475 if (lev>0) {
477 0, false,false,0,0,zero,*vec_zeta[lev]);
478 }
479}
480
481void
483{
484 if (nc_init_file_hires.empty()) {
485 Abort("Must specify high-resolution initial file when initializing from NetCDF and hires_init_level > 0");
486 }
489
490 // *** FArrayBox's at this level for holding the INITIAL data
492
495
496#ifdef _OPENMP
497#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
498#endif
499 {
500 // Don't tile this since we are operating on full FABs in this routine
501 for ( MFIter mfi(*vec_zeta_full_domain[hires_init_level], false); mfi.isValid(); ++mfi )
502 {
504
505 //
506 // FArrayBox to FArrayBox copy does "copy on intersection"
507 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
508 //
509
510 zeta_fab.template copy<RunOn::Device>(NC_zeta_fab[0],0,0,1);
511 } // mf
512 } // omp
513
514 // Average down to fill levels below hires_grid_level. Use a special average_down so
515 // grow cells get populated by averaged down fine data
516 for (int lev=hires_init_level-1; lev >= 0; lev--) {
518 }
519}
520
521
522/**
523 * @param lev Integer specifying the current level
524 */
525void
527{
528 // *** FArrayBox's at this level for holding the INITIAL data
531
540
541 // Optional spherical psi coordinates (see read_spherical_grid_vars_from_netcdf)
544 bool have_spherical_psi = true;
545
546 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
547 {
554
555 // All boxes at this level must agree: a partial set would leave holes in
556 // the corner mesh that a conservative remap cannot detect.
560
561 // Mirror vec_xp exactly: same nodal psi BoxArray, DistributionMap and ngrow.
562 if (have_spherical_psi && vec_lonp[lev] == nullptr) {
563 vec_lonp[lev].reset(new MultiFab(vec_xp[lev]->boxArray(), vec_xp[lev]->DistributionMap(),
564 1, vec_xp[lev]->nGrowVect()));
565 vec_latp[lev].reset(new MultiFab(vec_xp[lev]->boxArray(), vec_xp[lev]->DistributionMap(),
566 1, vec_xp[lev]->nGrowVect()));
567 }
568
569#ifdef _OPENMP
570#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
571#endif
572 {
573 // Don't tile this since we are operating on full FABs in this routine
574 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
575 {
576 FArrayBox &pm_fab = (*vec_pm[lev])[mfi];
577 FArrayBox &pn_fab = (*vec_pn[lev])[mfi];
578 FArrayBox &xr_fab = (*vec_xr[lev])[mfi];
579 FArrayBox &yr_fab = (*vec_yr[lev])[mfi];
580 FArrayBox &xu_fab = (*vec_xu[lev])[mfi];
581 FArrayBox &yu_fab = (*vec_yu[lev])[mfi];
582 FArrayBox &xv_fab = (*vec_xv[lev])[mfi];
583 FArrayBox &yv_fab = (*vec_yv[lev])[mfi];
584 FArrayBox &xp_fab = (*vec_xp[lev])[mfi];
585 FArrayBox &yp_fab = (*vec_yp[lev])[mfi];
586
587 //
588 // FArrayBox to FArrayBox copy does "copy on intersection"
589 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
590 //
591
594
603
604 if (have_spherical_psi) {
607 }
608 } // mf
609 } // omp
610 } // idx
611
612 // Drop any partial allocation so the getter's null contract stays honest.
613 if (!have_spherical_psi) {
614 vec_lonp[lev].reset();
615 vec_latp[lev].reset();
616 }
617
618 Real dummy_time = zero;
619 if (lev > 0) {
622 BdyVars::null,0,false);
625 BdyVars::null,0,false);
626 }
627
628
629 int ng = vec_pm[lev]->nGrow();
630
631 const auto& dom_lo = amrex::lbound(geom[lev].Domain());
632 const auto& dom_hi = amrex::ubound(geom[lev].Domain());
633
634 //
635 // We need values of pm and pn outside the domain so we fill
636 // them here with foextrap
637 //
638 // We first fill interior ghost cells because we will need to extrapolate
639 // from ghost cells inside the domain to ghost cells outside the domain
640 //
641 vec_pm[lev]->FillBoundary(geom[lev].periodicity());
642 vec_pn[lev]->FillBoundary(geom[lev].periodicity());
643
644 vec_xr[lev]->FillBoundary(geom[lev].periodicity());
645 vec_yr[lev]->FillBoundary(geom[lev].periodicity());
646 vec_xu[lev]->FillBoundary(geom[lev].periodicity());
647 vec_yu[lev]->FillBoundary(geom[lev].periodicity());
648 vec_xv[lev]->FillBoundary(geom[lev].periodicity());
649 vec_yv[lev]->FillBoundary(geom[lev].periodicity());
650 vec_xp[lev]->FillBoundary(geom[lev].periodicity());
651 vec_yp[lev]->FillBoundary(geom[lev].periodicity());
652 if (vec_lonp[lev] != nullptr) {
653 vec_lonp[lev]->FillBoundary(geom[lev].periodicity());
654 vec_latp[lev]->FillBoundary(geom[lev].periodicity());
655 }
656
659}
660
661/**
662 * @param lev Integer specifying the current level
663 */
664void
666{
667 // *** FArrayBox's at this level for holding the INITIAL data
669 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
670 {
672 NC_h_fab[idx]);
673
674#ifdef _OPENMP
675#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
676#endif
677 {
678 // Don't tile this since we are operating on full FABs in this routine
679 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
680 {
681 FArrayBox &h_fab = (*vec_h[lev])[mfi];
682
683 //
684 // FArrayBox to FArrayBox copy does "copy on intersection"
685 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
686 //
687
688 // Copy into both components of h
689 h_fab.template copy<RunOn::Device>(NC_h_fab[idx],0,0,1);
690 h_fab.template copy<RunOn::Device>(NC_h_fab[idx],0,1,1);
691 } // mf
692 } // omp
693 } // idx
694
695 const double dummy_time = zero;
696 // Unconditional foextrap will overwrite periodicity, but EnforcePeriodicity will
697 // be called on h afterwards
700 BdyVars::null,0,false,false,1);
703 BdyVars::null,1,false,false,1);
704
705 vec_h[lev]->FillBoundary(geom[lev].periodicity());
706}
707
708/**
709 * @param lev Integer specifying the current level
710 */
711void
713{
714 // *** FArrayBox's at this level for holding the INITIAL data
716
717 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
718 {
721
722#ifdef _OPENMP
723#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
724#endif
725 {
726 // Don't tile this since we are operating on full FABs in this routine
727 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
728 {
729 FArrayBox &fcor_fab = (*vec_fcor[lev])[mfi];
730
731 //
732 // FArrayBox to FArrayBox copy does "copy on intersection"
733 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
734 //
735
737 } // mf
738 } // omp
739 } // idx
740 vec_fcor[lev]->FillBoundary(geom[lev].periodicity());
741}
742
743/**
744 * @param lev Integer specifying the current level
745 */
746void
748{
749 // *** FArrayBox's at this level for holding the INITIAL data
753
754 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
755 {
759
760#ifdef _OPENMP
761#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
762#endif
763 {
764 // Don't tile this since we are operating on full FABs in this routine
765 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
766 {
767 FArrayBox &mskr_fab = (*vec_mskr[lev])[mfi];
768 FArrayBox &msku_fab = (*vec_msku[lev])[mfi];
769 FArrayBox &mskv_fab = (*vec_mskv[lev])[mfi];
770
771 //
772 // FArrayBox to FArrayBox copy does "copy on intersection"
773 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
774 //
775
779 } // mf
780 } // omp
781 } // idx
782
784 vec_mskr[lev]->FillBoundary(geom[lev].periodicity());
785 vec_msku[lev]->FillBoundary(geom[lev].periodicity());
786 vec_mskv[lev]->FillBoundary(geom[lev].periodicity());
787 vec_mskp[lev]->FillBoundary(geom[lev].periodicity());
788}
789
790/**
791 * @param lev Integer specifying the current level
792 */
793void
795{
796 if (nc_bdry_file.empty() || nc_bdry_file[0].empty()) {
797 amrex::Error("NetCDF boundary file name must be provided via input");
798 }
799
800 // One boundary series per BdyVars slot. Every cell-centered tracer gets one, named
801 // for the variable itself ("temp", "salt", "NO3", ...), so the file is expected to
802 // hold e.g. NO3_west following the same convention ROMS uses. A series whose
803 // variable needs no boundary data reads nothing -- NCTimeSeriesBoundary only asks
804 // for the sides flagged in phys_bc_need_data -- so tracers left on a local BC do
805 // not require the file to contain anything for them.
806 amrex::Vector<std::string> field_name (num_bdy_vars());
807 amrex::Vector<IntVect > index_types(num_bdy_vars());
808 std::vector<bool > is_2d (num_bdy_vars());
809
810 field_name[BdyVars::u] = "u"; index_types[BdyVars::u] = IntVect(1,0,0); is_2d[BdyVars::u] = false;
811 field_name[BdyVars::v] = "v"; index_types[BdyVars::v] = IntVect(0,1,0); is_2d[BdyVars::v] = false;
812 for (int icomp = 0; icomp < ncons; ++icomp) {
813 const int ibdy = BdyVars::cons(icomp);
814 field_name[ibdy] = cons_names[icomp];
815 index_types[ibdy] = IntVect(0,0,0);
816 is_2d[ibdy] = false;
817 }
818 field_name[bdy_ubar()] = "ubar"; index_types[bdy_ubar()] = IntVect(1,0,0); is_2d[bdy_ubar()] = true;
819 field_name[bdy_vbar()] = "vbar"; index_types[bdy_vbar()] = IntVect(0,1,0); is_2d[bdy_vbar()] = true;
820 field_name[bdy_zeta()] = "zeta"; index_types[bdy_zeta()] = IntVect(0,0,0); is_2d[bdy_zeta()] = true;
821
822 amrex::Print() << "DOING INIT AT LEVEL " << lev << std::endl;
823 int rx = 1; int ry = 1;
824 if (lev > 0) {
825 for (int k = lev-1; k >= 0; k--) {
826 rx *= ref_ratio[k][0];
827 ry *= ref_ratio[k][1];
828 }
829 }
830 for (int ivar = 0; ivar < num_bdy_vars(); ivar++) {
831 boundary_series[lev].push_back(std::unique_ptr<NCTimeSeriesBoundary>(new NCTimeSeriesBoundary(lev, geom, nc_bdry_file, field_name[ivar],
835 boundary_series[lev][ivar]->Initialize();
836 }
837}
838
839/**
840 * \brief Helper function to initialize state and velocity data in a Fab.
841 *
842 * @param lev Integer specifying current level
843 * @param state_fab FArrayBox object holding the state data we initialize
844 * @param temp_fab FArrayBox object holding the temperature data we initialize
845 * @param salt_fab FArrayBox object holding the salt data we initialize
846 * @param x_vel_fab FArrayBox object holding the x-velocity data we initialize
847 * @param y_vel_fab FArrayBox object holding the y-velocity data we initialize
848 * @param NC_temp_fab Vector of FArrayBox objects with the REMORA dataset specifying temperature
849 * @param NC_salt_fab Vector of FArrayBox objects with the REMORA dataset specifying salinity
850 * @param NC_xvel_fab Vector of FArrayBox objects with the REMORA dataset specifying x-velocity
851 * @param NC_yvel_fab Vector of FArrayBox objects with the REMORA dataset specifying y-velocity
852 */
853void
855 FArrayBox& temp_fab, FArrayBox& salt_fab,
856 FArrayBox& x_vel_fab, FArrayBox& y_vel_fab,
861{
862 int nboxes = NC_xvel_fab.size();
863 for (int idx = 0; idx < nboxes; idx++)
864 {
865 //
866 // FArrayBox to FArrayBox copy does "copy on intersection"
867 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
868 //
873 } // idx
874}
875
876/**
877 * @param lev Integer specifying current level
878 * @param biology_fab FArrayBox object holding the biology components we initialize
879 * @param NC_biology_fab Vector of FArrayBox objects with the REMORA dataset specifying
880 * each biological tracer, one per component per box
881 */
882void
885{
886 int nboxes = NC_biology_fab.size();
887 for (int idx = 0; idx < nboxes; idx++)
888 {
889 AMREX_ALWAYS_ASSERT(static_cast<int>(NC_biology_fab[idx].size()) == biology_fab.nComp());
890 for (int ibio = 0; ibio < biology_fab.nComp(); ++ibio) {
892 }
893 }
894}
895
896/**
897 * @param lev Integer specifying current level
898 * @param scalar_fab FArrayBox object holding the passive scalar components we initialize
899 * @param NC_scalar_fab Vector of FArrayBox objects with the REMORA dataset specifying
900 * each dye, one per component per box
901 * @param scalar_in_file Per box and component, whether the file carried that dye; a dye
902 * the file omits keeps the zero written before the read
903 */
904void
907 const Vector<Vector<int>>& scalar_in_file)
908{
909 int nboxes = NC_scalar_fab.size();
910 for (int idx = 0; idx < nboxes; idx++)
911 {
912 AMREX_ALWAYS_ASSERT(static_cast<int>(NC_scalar_fab[idx].size()) == scalar_fab.nComp());
913 AMREX_ALWAYS_ASSERT(static_cast<int>(scalar_in_file[idx].size()) == scalar_fab.nComp());
914 for (int iscal = 0; iscal < scalar_fab.nComp(); ++iscal) {
915 // A dye the file does not carry has no FAB built for it, so leave the zero
916 // that was written before the read.
917 if (!scalar_in_file[idx][iscal]) { continue; }
919 }
920 }
921}
922
923/**
924 * @param lev Integer specifying the current level
925 */
926void
928{
929 // *** FArrayBox's at this level for holding the INITIAL data
932 // One coefficient FAB per cons component per box
934 // Per box, whether each tracer's coefficient was actually present in the file
936 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++) {
937 NC_ConsNC_fab[idx].resize(ncons);
938 cons_coeff_in_file[idx].assign(ncons, 0);
939 }
940 // Aggregated over boxes: whether each tracer's coefficient came from the file
941 Vector<int> cons_coeff_read(ncons, 0);
942
943 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
944 {
952
953#ifdef _OPENMP
954#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
955#endif
956 {
957 // Don't tile this since we are operating on full FABs in this routine
958 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
959 {
961 FArrayBox &ubarNC_fab = (*vec_nudg_coeff[bdy_ubar()][lev])[mfi];
963 FArrayBox &vbarNC_fab = (*vec_nudg_coeff[bdy_vbar()][lev])[mfi];
965 }
967 FArrayBox &uNC_fab = (*vec_nudg_coeff[BdyVars::u][lev])[mfi];
969 FArrayBox &vNC_fab = (*vec_nudg_coeff[BdyVars::v][lev])[mfi];
971 }
972 for (int icomp = 0; icomp < ncons; ++icomp) {
973 if (!cons_coeff_in_file[idx][icomp]) { continue; }
976 }
977
978 } // mf
979 } // omp
980
981 for (int icomp = 0; icomp < ncons; ++icomp) {
983 }
984 } // idx
985
987 vec_nudg_coeff[bdy_ubar()][lev]->FillBoundary(geom[lev].periodicity());
988 vec_nudg_coeff[bdy_vbar()][lev]->FillBoundary(geom[lev].periodicity());
991 }
993 vec_nudg_coeff[BdyVars::u][lev]->FillBoundary(geom[lev].periodicity());
994 vec_nudg_coeff[BdyVars::v][lev]->FillBoundary(geom[lev].periodicity());
997 }
998 // Only convert the tracers whose coefficient actually came from the file: the rest
999 // still hold the constant set by init_clim_nudg_coeff, which is already in 1/s.
1000 for (int icomp = 0; icomp < ncons; ++icomp) {
1001 if (!cons_coeff_read[icomp]) { continue; }
1004 }
1005}
1006
1007/**
1008 * @param[in ] lev level to read in river data
1009 */
1010void
1012{
1013 amrex::Vector<int> river_pos_x;
1014 amrex::Vector<int> river_pos_y;
1015 amrex::Vector<int> river_direction_tmp;
1016
1017 std::string river_x_name = "river_Xposition";
1018 std::string river_y_name = "river_Eposition";
1019 std::string river_dir_name = "river_direction";
1020
1024
1025 if (river_pos_x.empty() ||
1026 river_pos_y.size() != river_pos_x.size() ||
1027 river_direction_tmp.size() != river_pos_x.size())
1028 {
1029 amrex::Abort("River metadata arrays must be nonempty and have matching lengths: " +
1030 river_x_name + "=" + std::to_string(river_pos_x.size()) + ", " +
1031 river_y_name + "=" + std::to_string(river_pos_y.size()) + ", " +
1032 river_dir_name + "=" + std::to_string(river_direction_tmp.size()));
1033 }
1034
1035 int nriv = river_pos_x.size();
1036 amrex::Gpu::DeviceVector<int> xpos_d(nriv);
1037 amrex::Gpu::DeviceVector<int> ypos_d(nriv);
1038 river_direction.resize(nriv);
1039
1040 int rrx = (lev > 0) ? cum_ref_ratios[lev][0] : 1;
1041 int rry = (lev > 0) ? cum_ref_ratios[lev][1] : 1;
1042
1043 // Map river source indices to the target AMR level while keeping one source
1044 // point per river so total prescribed transport is unchanged.
1045 amrex::Vector<int> river_pos_x_lev(nriv);
1046 amrex::Vector<int> river_pos_y_lev(nriv);
1047 for (int iriv = 0; iriv < nriv; ++iriv) {
1048 int x0 = river_pos_x[iriv] - 1;
1049 int y0 = river_pos_y[iriv] - 1;
1050
1051 if (river_direction_tmp[iriv] == 0) {
1052 // u-face aligned in x, centered in y within the refined coarse cell.
1054 river_pos_y_lev[iriv] = y0 * rry + (rry - 1) / 2;
1055 } else {
1056 // v-face aligned in y, centered in x within the refined coarse cell.
1057 river_pos_x_lev[iriv] = x0 * rrx + (rrx - 1) / 2;
1059 }
1060 }
1061#ifdef AMREX_USE_GPU
1062 Gpu::htod_memcpy(xpos_d.data(), river_pos_x_lev.data(), sizeof(int)*nriv);
1063 Gpu::htod_memcpy(ypos_d.data(), river_pos_y_lev.data(), sizeof(int)*nriv);
1064 Gpu::htod_memcpy(river_direction.data(), river_direction_tmp.data(), sizeof(int)*nriv);
1065#else
1066 std::memcpy(xpos_d.data(), river_pos_x_lev.data(), sizeof(int)*nriv);
1067 std::memcpy(ypos_d.data(), river_pos_y_lev.data(), sizeof(int)*nriv);
1068 std::memcpy(river_direction.data(), river_direction_tmp.data(), sizeof(int)*nriv);
1069#endif
1070 const int* xpos_ptr = xpos_d.data();
1071 const int* ypos_ptr = ypos_d.data();
1072
1073 for (amrex::MFIter mfi(*(vec_river_position[lev]).get(),true); mfi.isValid(); ++mfi) {
1074 amrex::Box bx = mfi.growntilebox(amrex::IntVect(NGROW,NGROW,0));
1075 auto river_pos = vec_river_position[lev]->array(mfi);
1076 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int ) {
1077 for (int iriv=0; iriv < nriv; iriv++) {
1078 int xriv = xpos_ptr[iriv];
1079 int yriv = ypos_ptr[iriv];
1080 if (i==xriv && j==yriv) {
1081 river_pos(i,j,0) = iriv;
1082 }
1083 }
1084 });
1085 }
1086
1087 if (verbose) {
1088 amrex::Print() << "[river-debug] lev=" << lev
1089 << " ref_ratio=(" << rrx << "," << rry << ")"
1090 << " nriv=" << nriv << '\n';
1091 for (int iriv = 0; iriv < nriv; ++iriv) {
1092 amrex::Print() << "[river-debug] river " << iriv
1093 << " dir=" << river_direction_tmp[iriv]
1094 << " nc=(" << river_pos_x[iriv] << "," << river_pos_y[iriv] << ")"
1095 << " lev=(" << river_pos_x_lev[iriv] + 1 << "," << river_pos_y_lev[iriv] + 1 << ")"
1096 << '\n';
1097 }
1098 }
1099}
1100
1101/**
1102 * @param[inout] mf multifab of data to convert
1103 */
1104void
1106 Real inv_days_to_inv_s = one / (Real(3600.0) * Real(24.0));
1107
1108 for ( MFIter mfi(*mf, TilingIfNotGPU()); mfi.isValid(); ++mfi )
1109 {
1110 Array4<Real> const& arr = mf->array(mfi);
1111 Box bx = mfi.growntilebox(IntVect(NGROW,NGROW,0));
1112 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
1114 });
1115 }
1116
1117}
1118
1119void
1121{
1122 if (nc_grid_file_hires.empty()) {
1123 Abort("Must specify high-resolution grid file when initializing from NetCDF and hires_grid_level > 0");
1124 }
1127
1130
1131 // Don't tile this since we are operating on full FABs in this routine
1132 for ( MFIter mfi(*vec_h_full_domain[hires_grid_level], false); mfi.isValid(); ++mfi )
1133 {
1134 FArrayBox &h_fab = (*vec_h_full_domain[hires_grid_level])[mfi];
1135 h_fab.template copy<RunOn::Device>(NC_h_fab[0]);
1136 }
1137
1138 // Average down to fill levels below hires_grid_level. Use a special average_down so
1139 // grow cells get populated by averaged down fine data
1140 for (int lev=hires_grid_level-1; lev >= 0; lev--) {
1142 }
1143}
1144
1145void
1147{
1148 if (nc_grid_file_hires.empty()) {
1149 Abort("Must specify high-resolution grid file when initializing from NetCDF and hires_grid_level > 0");
1150 }
1153
1156
1158 NC_pm_fab[0], NC_pn_fab[0],
1160
1161 // Don't tile this since we are operating on full FABs in this routine
1162 for ( MFIter mfi(*vec_h_full_domain[hires_grid_level], false); mfi.isValid(); ++mfi )
1163 {
1168 }
1169
1170 // Average down to fill levels below hires_grid_level. Use a special average_down so
1171 // grow cells get populated by averaged down fine data
1172 for (int lev=hires_grid_level-1; lev >= 0; lev--) {
1175
1176 int rrx = ref_ratio[lev][0];
1177 int rry = ref_ratio[lev][1];
1178 // pm and pn need to be rescaled by the refinement ratio
1179 for ( MFIter mfi(*vec_h_full_domain[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi )
1180 {
1181 Array4<Real> const& pm = vec_pm_full_domain[lev]->array(mfi);
1182 Array4<Real> const& pn = vec_pn_full_domain[lev]->array(mfi);
1183 Box ubx = mfi.growntilebox(cum_ref_ratios[lev] - IntVect(1,0,0));;
1184 Box vbx = mfi.growntilebox(cum_ref_ratios[lev] - IntVect(0,1,0));;
1185 ParallelFor(makeSlab(ubx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
1186 pm(i,j,0) = pm(i,j,0) / Real(rrx);
1187 });
1188 ParallelFor(makeSlab(vbx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
1189 pn(i,j,0) = pn(i,j,0) / Real(rry);
1190 });
1191 }
1192 }
1193
1194 for (int lev=0; lev<=hires_grid_level; lev++) {
1197 }
1198}
1199
1200/**
1201 * @param[inout] mf multifab of data to extrapolate on
1202 * @param[in ] geom geometry
1203 */
1204void
1206{
1207 const IntVect ng = mf.nGrowVect();
1208
1209 const auto& dom_lo = amrex::lbound(geom.Domain());
1210 const auto& dom_hi = amrex::ubound(geom.Domain());
1211
1212 for ( MFIter mfi(mf); mfi.isValid(); ++mfi )
1213 {
1214 Box bx = mfi.tilebox();
1215
1216 auto mf_arr = mf.array(mfi);
1217
1218 Box gbx_lox = adjCellLo(bx,0,ng[0]); gbx_lox.grow(1,ng[1]); gbx_lox.setBig (0,dom_lo.x-2);
1219 Box gbx_hix = adjCellHi(bx,0,ng[0]); gbx_hix.grow(1,ng[1]); gbx_hix.setSmall(0,dom_hi.x+2);
1220 Box gbx_loy = adjCellLo(bx,1,ng[1]); gbx_loy.grow(0,ng[0]); gbx_loy.setBig (1,dom_lo.y-2);
1221 Box gbx_hiy = adjCellHi(bx,1,ng[1]); gbx_hiy.grow(0,ng[0]); gbx_hiy.setSmall(1,dom_hi.y+2);
1222
1223 if (gbx_lox.ok()) {
1224 ParallelFor(gbx_lox, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1225 {
1226 mf_arr(i,j,k,0) = mf_arr(dom_lo.x-1,j,k,0);
1227 });
1228 }
1229 if (gbx_hix.ok()) {
1230 ParallelFor(gbx_hix, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1231 {
1232 mf_arr(i,j,k,0) = mf_arr(dom_hi.x+1,j,k,0);
1233 });
1234 }
1235 if (gbx_loy.ok()) {
1236 ParallelFor(gbx_loy, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1237 {
1238 mf_arr(i,j,k,0) = mf_arr(i,dom_lo.y-1,k,0);
1239 });
1240 }
1241 if (gbx_hiy.ok()) {
1242 ParallelFor(gbx_hiy, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1243 {
1244 mf_arr(i,j,k,0) = mf_arr(i,dom_hi.y+1,k,0);
1245 });
1246 }
1247 } // mfi
1248}
1249
1250#endif // REMORA_USE_NETCDF
constexpr amrex::Real one
constexpr amrex::Real zero
#define NGROW
#define Temp_comp
#define Tracer_comp
#define Salt_comp
mf_h setVal(geomdata.ProbHi(2))
AMREX_ALWAYS_ASSERT(!NSPeriodic||!EWPeriodic)
void read_vec_from_netcdf(int lev, const amrex::Vector< std::string > &fnames, const std::string &field_name, amrex::Vector< int > &vec_dat)
helper function to read in vector of data from netcdf
void read_coriolis_from_netcdf(int lev, const Box &domain, const std::string &fname, FArrayBox &NC_fcor_fab)
helper function to read coriolis factor from netcdf
void read_grid_vars_from_netcdf(int lev, const Box &domain, const std::string &fname, FArrayBox &NC_pm_fab, FArrayBox &NC_pn_fab, FArrayBox &NC_xr_fab, FArrayBox &NC_yr_fab, FArrayBox &NC_xu_fab, FArrayBox &NC_yu_fab, FArrayBox &NC_xv_fab, FArrayBox &NC_yv_fab, FArrayBox &NC_xp_fab, FArrayBox &NC_yp_fab)
helper function to read grid variables from netcdf
void read_zeta_from_netcdf(int lev, const Box &domain, const std::string &fname, FArrayBox &NC_zeta_fab)
helper function to read sea surface height from netcdf
void read_bathymetry_from_netcdf(int lev, const Box &domain, const std::string &fname, FArrayBox &NC_h_fab)
helper function to read bathymetry from netcdf
void read_scalars_full_domain_from_netcdf(int, const Box &domain, const std::string &fname, const Vector< std::string > &scalar_names, Vector< FArrayBox > &NC_scalar_fab, Vector< int > &scalar_in_file, IntVect ngrow)
helper function for reading in full domain high-resolution initial passive (dye) scalar data from net...
void read_data_full_domain_from_netcdf(int, const Box &domain, const std::string &fname, FArrayBox &NC_temp_fab, FArrayBox &NC_salt_fab, FArrayBox &NC_xvel_fab, FArrayBox &NC_yvel_fab, IntVect ngrow)
helper function for reading in full domain high-resolution initial state data from netcdf
void init_state_from_netcdf(int lev, FArrayBox &temp_fab, FArrayBox &salt_fab, FArrayBox &x_vel_fab, FArrayBox &y_vel_fab, const Vector< FArrayBox > &NC_temp_fab, const Vector< FArrayBox > &NC_salt_fab, const Vector< FArrayBox > &NC_xvel_fab, const Vector< FArrayBox > &NC_yvel_fab)
helper function to initialize state from netcdf
void check_hires_dims_from_netcdf(const std::string &fname, const std::string &var_name, const Box &domain, const IntVect &ngrow)
helper function checking that a high-resolution file covers the refined domain plus grow cells
void read_biology_from_netcdf(int, const Box &domain, const std::string &fname, const Vector< std::string > &biology_names, Vector< FArrayBox > &NC_biology_fab)
helper function for reading in initial biology data from netcdf
void read_bathymetry_full_domain_from_netcdf(const Box &domain, const std::string &fname, FArrayBox &NC_h_fab, IntVect ngrow)
helper function to read full-domain high resolution bathymetry from netcdf
void init_biology_state_from_netcdf(int lev, FArrayBox &biology_fab, const Vector< Vector< FArrayBox > > &NC_biology_fab)
helper function to initialize biology tracer state from netcdf
void read_masks_from_netcdf(int, const Box &domain, const std::string &fname, FArrayBox &NC_mskr_fab, FArrayBox &NC_msku_fab, FArrayBox &NC_mskv_fab)
helper function for reading in land-sea masks from netcdf
void read_biology_full_domain_from_netcdf(int, const Box &domain, const std::string &fname, const Vector< std::string > &biology_names, Vector< FArrayBox > &NC_biology_fab, IntVect ngrow)
helper function for reading in full domain high-resolution initial biology data from netcdf
void read_data_from_netcdf(int, const Box &domain, const std::string &fname, FArrayBox &NC_temp_fab, FArrayBox &NC_salt_fab, FArrayBox &NC_xvel_fab, FArrayBox &NC_yvel_fab)
helper function for reading in initial state data from netcdf
void read_zeta_full_domain_from_netcdf(int lev, const Box &domain, const std::string &fname, FArrayBox &NC_zeta_fab, IntVect ngrow)
helper function to read high-resolution full-domain sea surface height from netcdf
void read_scalars_from_netcdf(int, const Box &domain, const std::string &fname, const Vector< std::string > &scalar_names, Vector< FArrayBox > &NC_scalar_fab, Vector< int > &scalar_in_file)
helper function for reading in initial passive (dye) scalar data from netcdf
void init_scalar_state_from_netcdf(int lev, FArrayBox &scalar_fab, const Vector< Vector< FArrayBox > > &NC_scalar_fab, const Vector< Vector< int > > &scalar_in_file)
helper function to initialize passive (dye) scalar state from netcdf
bool read_spherical_grid_vars_from_netcdf(int lev, const Box &domain, const std::string &fname, FArrayBox &NC_lonp_fab, FArrayBox &NC_latp_fab)
helper function to read optional spherical psi coordinates from netcdf
void read_grid_vars_full_domain_from_netcdf(const Box &domain, const std::string &fname, FArrayBox &NC_pm_fab, FArrayBox &NC_pn_fab, IntVect ngrow)
helper function to read full-domain high resolution grid variables from netcdf
void read_clim_nudg_coeff_from_netcdf(int lev, const Box &domain, const std::string &fname, bool do_m2_clim_nudg, bool do_m3_clim_nudg, const amrex::Vector< int > &do_cons_clim_nudg, const amrex::Vector< std::string > &cons_names, FArrayBox &NC_M2NC_fab, FArrayBox &NC_M3NC_fab, amrex::Vector< FArrayBox > &NC_ConsNC_fab, amrex::Vector< int > &cons_coeff_in_file)
helper function to read climatology nudging from netcdf
A class to hold and interpolate time series data read from a NetCDF file.
std::string nc_grid_file_hires
Grid file for high resolution bathymetry.
Definition REMORA.H:1782
amrex::Vector< std::string > nc_riv_file
NetCDF river file(s)
Definition REMORA.H:1799
int foextrap_periodic_bc() const noexcept
Definition REMORA.H:1320
int ncons
Number of conserved scalars in the state (temperature + salt + passive scalars + biology tracers)
Definition REMORA.H:1644
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_zeta_full_domain
high resolution initial free surface height (2D)
Definition REMORA.H:554
std::string nc_init_file_hires
Init file for high resolution.
Definition REMORA.H:1789
void init_bathymetry_from_netcdf(int lev)
Bathymetry data initialization from NetCDF file.
amrex::Vector< std::string > cons_names
Names of scalars for plotfile output.
Definition REMORA.H:1709
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_fcor
coriolis factor (2D)
Definition REMORA.H:577
void init_biology_from_netcdf(int lev)
Biology initialization from NetCDF file.
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:397
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_h
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:406
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:568
void init_zeta_full_domain_from_netcdf()
Full-domain high res sea-surface height data initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_yv
y_grid on v-points (2D)
Definition REMORA.H:592
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:386
REMORABiology::BiologyModel biology_model
Active biology package.
Definition REMORA.H:1646
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:557
void init_grid_vars_from_netcdf(int lev)
Grid variable initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_yp
y_grid on psi-points (2D)
Definition REMORA.H:597
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xr
x_grid on rho points (2D)
Definition REMORA.H:580
void init_biology_full_domain_from_netcdf()
Full-domain high-res biology initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xv
x_grid on v-points (2D)
Definition REMORA.H:590
void fill_from_bdyfiles(int lev, amrex::MultiFab &mf_to_fill, const amrex::MultiFab &mf_mask, const amrex::Real time, const int bccomp, const int bdy_var_type, const int icomp_to_fill, const int icomp_calc=0, const amrex::MultiFab &mf_calc=amrex::MultiFab(), const amrex::Real=zero)
Fill boundary data from netcdf file.
amrex::Vector< amrex::Vector< amrex::Box > > boxes_at_level
the boxes specified at each level by tagging criteria
Definition REMORA.H:1549
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:559
void extrapolate_metric_to_physical_boundaries(amrex::MultiFab &mf, const amrex::Geometry &geom)
Extrapolate grid metrics to edge of MultiFab.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm_full_domain
horizontal scaling factor: 1 / dx (2D) on whole domain
Definition REMORA.H:572
void init_scalars_full_domain_from_netcdf()
Full-domain high-res passive (dye) scalar initialization from NetCDF file.
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:390
amrex::Box nc_hires_init_box
Box for the full domain at nc_hires_init_level.
Definition REMORA.H:1791
int zeta_bc() const noexcept
Definition REMORA.H:1318
int num_bdy_vars() const noexcept
Definition REMORA.H:1332
amrex::Vector< amrex::IntVect > cum_ref_ratios
Cumulative refinement ratio between level 0 and level i.
Definition REMORA.H:1794
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 init_scalars_from_netcdf(int lev)
Passive (dye) scalar initialization from NetCDF file. Called from init_data_from_netcdf: dye follows ...
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskp
land/sea mask at cell corners (2D)
Definition REMORA.H:563
int Bio_comp
First cons component of the biology block, i.e. Tracer_comp + nscalar. The state is laid out as temp,...
Definition REMORA.H:1641
int bdy_zeta() const noexcept
Definition REMORA.H:1331
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_lonp
longitude on psi-points (2D, degrees east); only filled when the grid NetCDF file carries lon_psi
Definition REMORA.H:601
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:561
amrex::Vector< std::unique_ptr< REMORAPhysBCFunct > > physbcs
Vector (over level) of functors to apply physical boundary conditions.
Definition REMORA.H:1566
int nbio
Number of biology tracers, set by the active biology model. Zero when no biology model is active.
Definition REMORA.H:1638
std::string nc_clim_coeff_file
NetCDF climatology coefficient file.
Definition REMORA.H:1804
amrex::Vector< std::string > bdry_time_name_byvar
Name of time fields for boundary data.
Definition REMORA.H:1809
void init_riv_pos_from_netcdf(int lev)
static amrex::Vector< std::string > nc_bdry_file
NetCDF boundary data.
Definition REMORA.H:57
void update_mskp(int lev)
Set psi-point mask to be consistent with rho-point mask.
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:399
void init_zeta_from_netcdf(int lev)
Sea-surface height data initialization from NetCDF file.
void init_coriolis_from_netcdf(int lev)
Coriolis parameter data initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_h_full_domain
Bathymetry data on the whole domain at each potential level.
Definition REMORA.H:409
void init_data_full_domain_from_netcdf()
High resolution roblem initialization from NetCDF file.
int hires_init_level
Which level the high resolution initialization data is at.
Definition REMORA.H:1787
int bdy_vbar() const noexcept
Definition REMORA.H:1330
int nscalar
Number of passive (dye) scalars carried in the state, beyond temperature and salinity....
Definition REMORA.H:1635
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:2079
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1556
void init_bdry_from_netcdf(int lev)
Boundary data initialization from NetCDF file.
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1717
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > vec_river_position
iMultiFab for river positions; contents are indices of rivers
Definition REMORA.H:1494
amrex::Vector< amrex::Vector< std::unique_ptr< NCTimeSeriesBoundary > > > boundary_series
Vector over BdyVars of boundary series data containers.
Definition REMORA.H:1490
int bdy_ubar() const noexcept
Definition REMORA.H:1329
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xp
x_grid on psi-points (2D)
Definition REMORA.H:595
static amrex::Vector< amrex::Vector< std::string > > nc_grid_file
NetCDF grid file.
Definition REMORA.H:59
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_zeta
free surface height (2D)
Definition REMORA.H:551
amrex::Gpu::DeviceVector< int > river_direction
Vector over rivers of river direction: 0: u-face; 1: v-face; 2: w-face.
Definition REMORA.H:1496
amrex::Box nc_hires_grid_box
Box for the full domain at nc_hires_grid_level.
Definition REMORA.H:1784
void init_clim_nudg_coeff_from_netcdf(int lev)
Climatology nudging coefficient initialization from NetCDF file.
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:395
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.
void init_bathymetry_full_domain_from_netcdf()
Full domain high-res bathymetry data initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_yu
y_grid on u-points (2D)
Definition REMORA.H:587
void init_grid_vars_full_domain_from_netcdf()
Full domain high-res grid variable initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xu
x_grid on u-points (2D)
Definition REMORA.H:585
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn_full_domain
horizontal scaling factor: 1 / dy (2D) on whole domain
Definition REMORA.H:574
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > vec_nudg_coeff
Climatology nudging coefficients.
Definition REMORA.H:643
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:570
amrex::Vector< amrex::GpuArray< bool, AMREX_SPACEDIM *2 > > phys_bc_need_data
These are flags that indicate whether we need to read in boundary data from file.
Definition REMORA.H:1596
static int verbose
Verbosity level of output.
Definition REMORA.H:1753
static amrex::Vector< amrex::Vector< std::string > > nc_init_file
NetCDF initialization file.
Definition REMORA.H:58
amrex::Vector< amrex::Real > t_old
old time at each level
Definition REMORA.H:1558
int hires_grid_level
Which level the high resolution bathymetry is at.
Definition REMORA.H:1780
void convert_inv_days_to_inv_s(amrex::MultiFab *)
Convert data in a multifab from inverse days to inverse seconds.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_yr
y_grid on rho points (2D)
Definition REMORA.H:582
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_latp
latitude on psi-points (2D, degrees north); only filled when the grid NetCDF file carries lat_psi
Definition REMORA.H:604
static constexpr int u
static constexpr int v
int cons(int icomp) noexcept
static constexpr int null
bool has_biology(BiologyModel model) noexcept
amrex::Vector< int > do_cons_clim_nudg