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 land-sea masks from netcdf */
28void
29read_masks_from_netcdf (int /*lev*/, const Box& domain, const std::string& fname,
30 FArrayBox& NC_mskr_fab, FArrayBox& NC_msku_fab,
31 FArrayBox& NC_mskv_fab);
32
33/** \brief helper function for reading boundary data from netcdf */
34Real
35read_bdry_from_netcdf (const Box& domain, const std::string& fname,
36 Vector<Vector<FArrayBox>>& bdy_data_xlo,
37 Vector<Vector<FArrayBox>>& bdy_data_xhi,
38 Vector<Vector<FArrayBox>>& bdy_data_ylo,
39 Vector<Vector<FArrayBox>>& bdy_data_yhi,
40 int& width, amrex::Real& start_bdy_time,
41 std::string bdry_time_varname,
42 amrex::GpuArray<amrex::GpuArray<bool, AMREX_SPACEDIM*2>,BdyVars::NumTypes+1>&);
43
44/** \brief helper function to initialize state from netcdf */
45void
47 FArrayBox& temp_fab, FArrayBox& salt_fab,
48 FArrayBox& x_vel_fab, FArrayBox& y_vel_fab,
49 const Vector<FArrayBox>& NC_temp_fab,
50 const Vector<FArrayBox>& NC_salt_fab,
51 const Vector<FArrayBox>& NC_xvel_fab,
52 const Vector<FArrayBox>& NC_yvel_fab);
53
54/** \brief helper function to read bathymetry from netcdf */
55void
56read_bathymetry_from_netcdf (int lev, const Box& domain, const std::string& fname,
57 FArrayBox& NC_h_fab);
58
59/** \brief helper function to read grid variables from netcdf */
60void
61read_grid_vars_from_netcdf (int lev, const Box& domain, const std::string& fname,
62 FArrayBox& NC_pm_fab, FArrayBox& NC_pn_fab,
63 FArrayBox& NC_xr_fab, FArrayBox& NC_yr_fab,
64 FArrayBox& NC_xu_fab, FArrayBox& NC_yu_fab,
65 FArrayBox& NC_xv_fab, FArrayBox& NC_yv_fab,
66 FArrayBox& NC_xp_fab, FArrayBox& NC_yp_fab);
67
68/** \brief helper function to read optional spherical psi coordinates from netcdf */
69bool
70read_spherical_grid_vars_from_netcdf (int lev, const Box& domain, const std::string& fname,
71 FArrayBox& NC_lonp_fab, FArrayBox& NC_latp_fab);
72
73/** \brief helper function to read full-domain high resolution bathymetry from netcdf */
74void
75read_bathymetry_full_domain_from_netcdf (const Box& domain, const std::string& fname,
76 FArrayBox& NC_h_fab, IntVect ngrow);
77
78/** \brief helper function to read full-domain high resolution grid variables from netcdf */
79void
80read_grid_vars_full_domain_from_netcdf (const Box& domain, const std::string& fname,
81 FArrayBox& NC_pm_fab, FArrayBox& NC_pn_fab,
82 IntVect ngrow);
83
84/** \brief helper function to read coriolis factor from netcdf */
85void
86read_coriolis_from_netcdf (int lev, const Box& domain, const std::string& fname, FArrayBox& NC_fcor_fab);
87
88/** \brief helper function to read sea surface height from netcdf */
89void
90read_zeta_from_netcdf (int lev, const Box& domain, const std::string& fname,
91 FArrayBox& NC_zeta_fab);
92
93/** \brief helper function to read high-resolution full-domain sea surface height from netcdf */
94void
95read_zeta_full_domain_from_netcdf (int lev, const Box& domain, const std::string& fname,
96 FArrayBox& NC_zeta_fab, IntVect ngrow);
97
98/** \brief helper function to read climatology nudging from netcdf */
99void
100read_clim_nudg_coeff_from_netcdf (int lev, const Box& domain, const std::string& fname,
101 bool do_m2_clim_nudg,
102 bool do_m3_clim_nudg,
103 bool do_temp_clim_nudg,
104 bool do_salt_clim_nudg,
105 FArrayBox& NC_M2NC_fab,
106 FArrayBox& NC_M3NC_fab,
107 FArrayBox& NC_TempNC_fab,
108 FArrayBox& NC_SaltNC_fab);
109
110/** \brief helper function to read in vector of data from netcdf */
111void read_vec_from_netcdf (int lev, const amrex::Vector<std::string>& fnames, const std::string& field_name, amrex::Vector<int>& vec_dat);
112
113/**
114 * @param lev Integer specifying the current level
115 */
116void
118{
119 // *** FArrayBox's at this level for holding the INITIAL data
120 Vector<FArrayBox> NC_temp_fab ; NC_temp_fab.resize(num_boxes_at_level[lev]);
121 Vector<FArrayBox> NC_salt_fab ; NC_salt_fab.resize(num_boxes_at_level[lev]);
122 Vector<FArrayBox> NC_xvel_fab ; NC_xvel_fab.resize(num_boxes_at_level[lev]);
123 Vector<FArrayBox> NC_yvel_fab ; NC_yvel_fab.resize(num_boxes_at_level[lev]);
124
125 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
126 {
127 read_data_from_netcdf(lev, boxes_at_level[lev][idx], nc_init_file[lev][idx],
128 NC_temp_fab[idx], NC_salt_fab[idx],
129 NC_xvel_fab[idx], NC_yvel_fab[idx]);
130 }
131
132
133 MultiFab mf_temp(*cons_new[lev], make_alias, Temp_comp, 1);
134 MultiFab mf_salt(*cons_new[lev], make_alias, Salt_comp, 1);
135
136#ifdef _OPENMP
137#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
138#endif
139 {
140 // Don't tile this since we are operating on full FABs in this routine
141 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
142 {
143 // Define fabs for holding the initial data
144 FArrayBox &temp_fab = mf_temp[mfi];
145 FArrayBox &salt_fab = mf_salt[mfi];
146 FArrayBox &xvel_fab = (*xvel_new[lev])[mfi];
147 FArrayBox &yvel_fab = (*yvel_new[lev])[mfi];
148
149 init_state_from_netcdf(lev, temp_fab, salt_fab,
150 xvel_fab, yvel_fab,
151 NC_temp_fab, NC_salt_fab,
152 NC_xvel_fab, NC_yvel_fab);
153 } // mf
154 } // omp
155
156 if (nscalar > 1) {
157 cons_new[lev]->setVal(zero, Tracer_comp + 1, nscalar - 1, cons_new[lev]->nGrowVect());
158 }
159}
160
161void
163{
164 // *** FArrayBox's at this level for holding the INITIAL data
165 Vector<FArrayBox> NC_temp_fab ; NC_temp_fab.resize(1);
166 Vector<FArrayBox> NC_salt_fab ; NC_salt_fab.resize(1);
167 Vector<FArrayBox> NC_xvel_fab ; NC_xvel_fab.resize(1);
168 Vector<FArrayBox> NC_yvel_fab ; NC_yvel_fab.resize(1);
169
171 NC_temp_fab[0], NC_salt_fab[0],
172 NC_xvel_fab[0], NC_yvel_fab[0],
174
175 MultiFab mf_temp(*vec_cons_full_domain[hires_init_level], make_alias, Temp_comp, 1);
176 MultiFab mf_salt(*vec_cons_full_domain[hires_init_level], make_alias, Salt_comp, 1);
177
178#ifdef _OPENMP
179#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
180#endif
181 {
182 // Don't tile this since we are operating on full FABs in this routine
183 for ( MFIter mfi(mf_temp, false); mfi.isValid(); ++mfi )
184 {
185 // Define fabs for holding the initial data
186 FArrayBox &temp_fab = mf_temp[mfi];
187 FArrayBox &salt_fab = mf_salt[mfi];
188 FArrayBox &xvel_fab = (*vec_xvel_full_domain[hires_init_level])[mfi];
189 FArrayBox &yvel_fab = (*vec_yvel_full_domain[hires_init_level])[mfi];
190
191 init_state_from_netcdf(hires_init_level, temp_fab, salt_fab,
192 xvel_fab, yvel_fab,
193 NC_temp_fab, NC_salt_fab,
194 NC_xvel_fab, NC_yvel_fab);
195 } // mf
196 } // omp
197
199 if (nscalar > 1) {
201 }
202
203 // Average down to fill levels below hires_grid_level. Use a special average_down so
204 // grow cells get populated by averaged down fine data
205 for (int lev=hires_init_level-1; lev >= 0; lev--) {
209 }
210}
211
212/**
213 * @param lev Integer specifying the current level
214 */
215void
217{
218 // *** FArrayBox's at this level for holding the INITIAL data
219 Vector<FArrayBox> NC_zeta_fab ; NC_zeta_fab.resize(num_boxes_at_level[lev]);
220
221 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
222 {
223 read_zeta_from_netcdf(lev,boxes_at_level[lev][idx], nc_init_file[lev][idx],
224 NC_zeta_fab[idx]);
225
226#ifdef _OPENMP
227#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
228#endif
229 {
230 // Don't tile this since we are operating on full FABs in this routine
231 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
232 {
233 FArrayBox &zeta_fab = (*vec_zeta[lev])[mfi];
234
235 //
236 // FArrayBox to FArrayBox copy does "copy on intersection"
237 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
238 //
239
240 zeta_fab.template copy<RunOn::Device>(NC_zeta_fab[idx],0,0,1);
241 } // mf
242 } // omp
243 } // idx
244
245 vec_zeta[lev]->FillBoundary(geom[lev].periodicity());
246 (*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]);
247// (*physbcs[lev])(*vec_zeta[lev],*vec_mskr[lev].get(),1,1,vec_zeta[lev]->nGrowVect(),t_new[lev],BCVars::zeta_bc);
248// (*physbcs[lev])(*vec_zeta[lev],*vec_mskr[lev].get(),2,1,vec_zeta[lev]->nGrowVect(),t_new[lev],BCVars::zeta_bc);
249
251 Real told = t_new[lev];
252 fill_from_bdyfiles(lev, *vec_zeta[lev], *vec_mskr[lev], told, zeta_bc(),BdyVars::zeta,0,0,
253 *vec_zeta[lev]);
254 }
255 if (lev>0) {
256 FillPatch(lev, t_old[lev], *vec_zeta[lev], GetVecOfPtrs(vec_zeta), zeta_bc(), BdyVars::zeta,
257 0, false,false,0,0,zero,*vec_zeta[lev]);
258 }
259// fill_from_bdyfiles(lev, *vec_zeta[lev], *vec_mskr[lev], told, BCVars::zeta_bc,BdyVars::zeta,1,1);
260// fill_from_bdyfiles(lev, *vec_zeta[lev], *vec_mskr[lev], told, BCVars::zeta_bc,BdyVars::zeta,2,2);
261}
262
263void
265{
266 // *** FArrayBox's at this level for holding the INITIAL data
267 Vector<FArrayBox> NC_zeta_fab ; NC_zeta_fab.resize(1);
268
270 NC_zeta_fab[0], cum_ref_ratios[hires_init_level]);
271
272#ifdef _OPENMP
273#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
274#endif
275 {
276 // Don't tile this since we are operating on full FABs in this routine
277 for ( MFIter mfi(*vec_zeta_full_domain[hires_init_level], false); mfi.isValid(); ++mfi )
278 {
279 FArrayBox &zeta_fab = (*vec_zeta_full_domain[hires_init_level])[mfi];
280
281 //
282 // FArrayBox to FArrayBox copy does "copy on intersection"
283 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
284 //
285
286 zeta_fab.template copy<RunOn::Device>(NC_zeta_fab[0],0,0,1);
287 } // mf
288 } // omp
289
290 // Average down to fill levels below hires_grid_level. Use a special average_down so
291 // grow cells get populated by averaged down fine data
292 for (int lev=hires_init_level-1; lev >= 0; lev--) {
294 }
295}
296
297
298/**
299 * @param lev Integer specifying the current level
300 */
301void
303{
304 // *** FArrayBox's at this level for holding the INITIAL data
305 Vector<FArrayBox> NC_pm_fab ; NC_pm_fab.resize(num_boxes_at_level[lev]);
306 Vector<FArrayBox> NC_pn_fab ; NC_pn_fab.resize(num_boxes_at_level[lev]);
307
308 Vector<FArrayBox> NC_xr_fab ; NC_xr_fab.resize(num_boxes_at_level[lev]);
309 Vector<FArrayBox> NC_yr_fab ; NC_yr_fab.resize(num_boxes_at_level[lev]);
310 Vector<FArrayBox> NC_xu_fab ; NC_xu_fab.resize(num_boxes_at_level[lev]);
311 Vector<FArrayBox> NC_yu_fab ; NC_yu_fab.resize(num_boxes_at_level[lev]);
312 Vector<FArrayBox> NC_xv_fab ; NC_xv_fab.resize(num_boxes_at_level[lev]);
313 Vector<FArrayBox> NC_yv_fab ; NC_yv_fab.resize(num_boxes_at_level[lev]);
314 Vector<FArrayBox> NC_xp_fab ; NC_xp_fab.resize(num_boxes_at_level[lev]);
315 Vector<FArrayBox> NC_yp_fab ; NC_yp_fab.resize(num_boxes_at_level[lev]);
316
317 // Optional spherical psi coordinates (see read_spherical_grid_vars_from_netcdf)
318 Vector<FArrayBox> NC_lonp_fab ; NC_lonp_fab.resize(num_boxes_at_level[lev]);
319 Vector<FArrayBox> NC_latp_fab ; NC_latp_fab.resize(num_boxes_at_level[lev]);
320 bool have_spherical_psi = true;
321
322 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
323 {
325 NC_pm_fab[idx], NC_pn_fab[idx],
326 NC_xr_fab[idx], NC_yr_fab[idx],
327 NC_xu_fab[idx], NC_yu_fab[idx],
328 NC_xv_fab[idx], NC_yv_fab[idx],
329 NC_xp_fab[idx], NC_yp_fab[idx]);
330
331 // All boxes at this level must agree: a partial set would leave holes in
332 // the corner mesh that a conservative remap cannot detect.
333 have_spherical_psi = read_spherical_grid_vars_from_netcdf(
334 lev, boxes_at_level[lev][idx], nc_grid_file[lev][idx],
335 NC_lonp_fab[idx], NC_latp_fab[idx]) && have_spherical_psi;
336
337 // Mirror vec_xp exactly: same nodal psi BoxArray, DistributionMap and ngrow.
338 if (have_spherical_psi && vec_lonp[lev] == nullptr) {
339 vec_lonp[lev].reset(new MultiFab(vec_xp[lev]->boxArray(), vec_xp[lev]->DistributionMap(),
340 1, vec_xp[lev]->nGrowVect()));
341 vec_latp[lev].reset(new MultiFab(vec_xp[lev]->boxArray(), vec_xp[lev]->DistributionMap(),
342 1, vec_xp[lev]->nGrowVect()));
343 }
344
345#ifdef _OPENMP
346#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
347#endif
348 {
349 // Don't tile this since we are operating on full FABs in this routine
350 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
351 {
352 FArrayBox &pm_fab = (*vec_pm[lev])[mfi];
353 FArrayBox &pn_fab = (*vec_pn[lev])[mfi];
354 FArrayBox &xr_fab = (*vec_xr[lev])[mfi];
355 FArrayBox &yr_fab = (*vec_yr[lev])[mfi];
356 FArrayBox &xu_fab = (*vec_xu[lev])[mfi];
357 FArrayBox &yu_fab = (*vec_yu[lev])[mfi];
358 FArrayBox &xv_fab = (*vec_xv[lev])[mfi];
359 FArrayBox &yv_fab = (*vec_yv[lev])[mfi];
360 FArrayBox &xp_fab = (*vec_xp[lev])[mfi];
361 FArrayBox &yp_fab = (*vec_yp[lev])[mfi];
362
363 //
364 // FArrayBox to FArrayBox copy does "copy on intersection"
365 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
366 //
367
368 pm_fab.template copy<RunOn::Device>(NC_pm_fab[idx]);
369 pn_fab.template copy<RunOn::Device>(NC_pn_fab[idx]);
370
371 xr_fab.template copy<RunOn::Device>(NC_xr_fab[idx]);
372 yr_fab.template copy<RunOn::Device>(NC_yr_fab[idx]);
373 xu_fab.template copy<RunOn::Device>(NC_xu_fab[idx]);
374 yu_fab.template copy<RunOn::Device>(NC_yu_fab[idx]);
375 xv_fab.template copy<RunOn::Device>(NC_xv_fab[idx]);
376 yv_fab.template copy<RunOn::Device>(NC_yv_fab[idx]);
377 xp_fab.template copy<RunOn::Device>(NC_xp_fab[idx]);
378 yp_fab.template copy<RunOn::Device>(NC_yp_fab[idx]);
379
380 if (have_spherical_psi) {
381 (*vec_lonp[lev])[mfi].template copy<RunOn::Device>(NC_lonp_fab[idx]);
382 (*vec_latp[lev])[mfi].template copy<RunOn::Device>(NC_latp_fab[idx]);
383 }
384 } // mf
385 } // omp
386 } // idx
387
388 // Drop any partial allocation so the getter's null contract stays honest.
389 if (!have_spherical_psi) {
390 vec_lonp[lev].reset();
391 vec_latp[lev].reset();
392 }
393
394 Real dummy_time = zero;
395 if (lev > 0) {
396 FillPatch(lev,dummy_time,*vec_pm[lev],GetVecOfPtrs(vec_pm),
398 BdyVars::null,0,false);
399 FillPatch(lev,dummy_time,*vec_pn[lev],GetVecOfPtrs(vec_pn),
401 BdyVars::null,0,false);
402 }
403
404
405 int ng = vec_pm[lev]->nGrow();
406
407 const auto& dom_lo = amrex::lbound(geom[lev].Domain());
408 const auto& dom_hi = amrex::ubound(geom[lev].Domain());
409
410 //
411 // We need values of pm and pn outside the domain so we fill
412 // them here with foextrap
413 //
414 // We first fill interior ghost cells because we will need to extrapolate
415 // from ghost cells inside the domain to ghost cells outside the domain
416 //
417 vec_pm[lev]->FillBoundary(geom[lev].periodicity());
418 vec_pn[lev]->FillBoundary(geom[lev].periodicity());
419
420 vec_xr[lev]->FillBoundary(geom[lev].periodicity());
421 vec_yr[lev]->FillBoundary(geom[lev].periodicity());
422 vec_xu[lev]->FillBoundary(geom[lev].periodicity());
423 vec_yu[lev]->FillBoundary(geom[lev].periodicity());
424 vec_xv[lev]->FillBoundary(geom[lev].periodicity());
425 vec_yv[lev]->FillBoundary(geom[lev].periodicity());
426 vec_xp[lev]->FillBoundary(geom[lev].periodicity());
427 vec_yp[lev]->FillBoundary(geom[lev].periodicity());
428 if (vec_lonp[lev] != nullptr) {
429 vec_lonp[lev]->FillBoundary(geom[lev].periodicity());
430 vec_latp[lev]->FillBoundary(geom[lev].periodicity());
431 }
432
435}
436
437/**
438 * @param lev Integer specifying the current level
439 */
440void
442{
443 // *** FArrayBox's at this level for holding the INITIAL data
444 Vector<FArrayBox> NC_h_fab ; NC_h_fab.resize(num_boxes_at_level[lev]);
445 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
446 {
448 NC_h_fab[idx]);
449
450#ifdef _OPENMP
451#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
452#endif
453 {
454 // Don't tile this since we are operating on full FABs in this routine
455 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
456 {
457 FArrayBox &h_fab = (*vec_h[lev])[mfi];
458
459 //
460 // FArrayBox to FArrayBox copy does "copy on intersection"
461 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
462 //
463
464 // Copy into both components of h
465 h_fab.template copy<RunOn::Device>(NC_h_fab[idx],0,0,1);
466 h_fab.template copy<RunOn::Device>(NC_h_fab[idx],0,1,1);
467 } // mf
468 } // omp
469 } // idx
470
471 const double dummy_time = zero;
472 // Unconditional foextrap will overwrite periodicity, but EnforcePeriodicity will
473 // be called on h afterwards
474 FillPatch(lev,dummy_time,*vec_h[lev],GetVecOfPtrs(vec_h),
476 BdyVars::null,0,false,false,1);
477 FillPatch(lev,dummy_time,*vec_h[lev],GetVecOfPtrs(vec_h),
479 BdyVars::null,1,false,false,1);
480
481 vec_h[lev]->FillBoundary(geom[lev].periodicity());
482}
483
484/**
485 * @param lev Integer specifying the current level
486 */
487void
489{
490 // *** FArrayBox's at this level for holding the INITIAL data
491 Vector<FArrayBox> NC_fcor_fab ; NC_fcor_fab.resize(num_boxes_at_level[lev]);
492
493 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
494 {
496 NC_fcor_fab[idx]);
497
498#ifdef _OPENMP
499#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
500#endif
501 {
502 // Don't tile this since we are operating on full FABs in this routine
503 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
504 {
505 FArrayBox &fcor_fab = (*vec_fcor[lev])[mfi];
506
507 //
508 // FArrayBox to FArrayBox copy does "copy on intersection"
509 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
510 //
511
512 fcor_fab.template copy<RunOn::Device>(NC_fcor_fab[idx]);
513 } // mf
514 } // omp
515 } // idx
516 vec_fcor[lev]->FillBoundary(geom[lev].periodicity());
517}
518
519/**
520 * @param lev Integer specifying the current level
521 */
522void
524{
525 // *** FArrayBox's at this level for holding the INITIAL data
526 Vector<FArrayBox> NC_mskr_fab ; NC_mskr_fab.resize(num_boxes_at_level[lev]);
527 Vector<FArrayBox> NC_msku_fab ; NC_msku_fab.resize(num_boxes_at_level[lev]);
528 Vector<FArrayBox> NC_mskv_fab ; NC_mskv_fab.resize(num_boxes_at_level[lev]);
529
530 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
531 {
532 read_masks_from_netcdf(lev,boxes_at_level[lev][idx], nc_grid_file[lev][idx],
533 NC_mskr_fab[idx],NC_msku_fab[idx],
534 NC_mskv_fab[idx]);
535
536#ifdef _OPENMP
537#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
538#endif
539 {
540 // Don't tile this since we are operating on full FABs in this routine
541 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
542 {
543 FArrayBox &mskr_fab = (*vec_mskr[lev])[mfi];
544 FArrayBox &msku_fab = (*vec_msku[lev])[mfi];
545 FArrayBox &mskv_fab = (*vec_mskv[lev])[mfi];
546
547 //
548 // FArrayBox to FArrayBox copy does "copy on intersection"
549 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
550 //
551
552 mskr_fab.template copy<RunOn::Device>(NC_mskr_fab[idx]);
553 msku_fab.template copy<RunOn::Device>(NC_msku_fab[idx]);
554 mskv_fab.template copy<RunOn::Device>(NC_mskv_fab[idx]);
555 } // mf
556 } // omp
557 } // idx
558
559 update_mskp(lev);
560 vec_mskr[lev]->FillBoundary(geom[lev].periodicity());
561 vec_msku[lev]->FillBoundary(geom[lev].periodicity());
562 vec_mskv[lev]->FillBoundary(geom[lev].periodicity());
563 vec_mskp[lev]->FillBoundary(geom[lev].periodicity());
564}
565
566/**
567 * @param lev Integer specifying the current level
568 */
569void
571{
572 if (nc_bdry_file.empty() || nc_bdry_file[0].empty()) {
573 amrex::Error("NetCDF boundary file name must be provided via input");
574 }
575
576 amrex::Vector<std::string> field_name = {"u", "v", "temp", "salt", "ubar", "vbar", "zeta"};
577 amrex::Vector<IntVect > index_types = {IntVect(1,0,0), IntVect(0,1,0),
578 IntVect(0,0,0), IntVect(0,0,0),
579 IntVect(1,0,0), IntVect(0,1,0),
580 IntVect(0,0,0)};
581 std::vector<bool > is_2d = {false, false, false, false, true, true, true};
582
583 amrex::Print() << "DOING INIT AT LEVEL " << lev << std::endl;
584 int rx = 1; int ry = 1;
585 if (lev > 0) {
586 for (int k = lev-1; k >= 0; k--) {
587 rx *= ref_ratio[k][0];
588 ry *= ref_ratio[k][1];
589 }
590 }
591 for (int ivar = 0; ivar < BdyVars::NumTypes; ivar++) {
592 boundary_series[lev].push_back(std::unique_ptr<NCTimeSeriesBoundary>(new NCTimeSeriesBoundary(lev, geom, nc_bdry_file, field_name[ivar],
594 index_types[ivar],
595 &phys_bc_need_data[ivar], is_2d[ivar], rx, ry)));
596 boundary_series[lev][ivar]->Initialize();
597 }
598}
599
600/**
601 * \brief Helper function to initialize state and velocity data in a Fab.
602 *
603 * @param lev Integer specifying current level
604 * @param state_fab FArrayBox object holding the state data we initialize
605 * @param temp_fab FArrayBox object holding the temperature data we initialize
606 * @param salt_fab FArrayBox object holding the salt data we initialize
607 * @param x_vel_fab FArrayBox object holding the x-velocity data we initialize
608 * @param y_vel_fab FArrayBox object holding the y-velocity data we initialize
609 * @param NC_temp_fab Vector of FArrayBox objects with the REMORA dataset specifying temperature
610 * @param NC_salt_fab Vector of FArrayBox objects with the REMORA dataset specifying salinity
611 * @param NC_xvel_fab Vector of FArrayBox objects with the REMORA dataset specifying x-velocity
612 * @param NC_yvel_fab Vector of FArrayBox objects with the REMORA dataset specifying y-velocity
613 */
614void
616 FArrayBox& temp_fab, FArrayBox& salt_fab,
617 FArrayBox& x_vel_fab, FArrayBox& y_vel_fab,
618 const Vector<FArrayBox>& NC_temp_fab,
619 const Vector<FArrayBox>& NC_salt_fab,
620 const Vector<FArrayBox>& NC_xvel_fab,
621 const Vector<FArrayBox>& NC_yvel_fab)
622{
623 int nboxes = NC_xvel_fab.size();
624 for (int idx = 0; idx < nboxes; idx++)
625 {
626 //
627 // FArrayBox to FArrayBox copy does "copy on intersection"
628 // This only works here because we have broadcast the FArrayBox of data from the netcdf file to all ranks
629 //
630 temp_fab.template copy<RunOn::Device>(NC_temp_fab[idx]);
631 salt_fab.template copy<RunOn::Device>(NC_salt_fab[idx]);
632 x_vel_fab.template copy<RunOn::Device>(NC_xvel_fab[idx]);
633 y_vel_fab.template copy<RunOn::Device>(NC_yvel_fab[idx]);
634 } // idx
635}
636
637/**
638 * @param lev Integer specifying the current level
639 */
640void
642{
643 // *** FArrayBox's at this level for holding the INITIAL data
644 Vector<FArrayBox> NC_M2NC_fab ; NC_M2NC_fab.resize(num_boxes_at_level[lev]);
645 Vector<FArrayBox> NC_M3NC_fab ; NC_M3NC_fab.resize(num_boxes_at_level[lev]);
646 Vector<FArrayBox> NC_TempNC_fab ; NC_TempNC_fab.resize(num_boxes_at_level[lev]);
647 Vector<FArrayBox> NC_SaltNC_fab ; NC_SaltNC_fab.resize(num_boxes_at_level[lev]);
648
649 for (int idx = 0; idx < num_boxes_at_level[lev]; idx++)
650 {
656 NC_M2NC_fab[idx],NC_M3NC_fab[idx],
657 NC_TempNC_fab[idx],NC_SaltNC_fab[idx]);
658
659#ifdef _OPENMP
660#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
661#endif
662 {
663 // Don't tile this since we are operating on full FABs in this routine
664 for ( MFIter mfi(*cons_new[lev], false); mfi.isValid(); ++mfi )
665 {
667 FArrayBox &ubarNC_fab = (*vec_nudg_coeff[BdyVars::ubar][lev])[mfi];
668 ubarNC_fab.template copy<RunOn::Device>(NC_M2NC_fab[idx]);
669 FArrayBox &vbarNC_fab = (*vec_nudg_coeff[BdyVars::vbar][lev])[mfi];
670 vbarNC_fab.template copy<RunOn::Device>(NC_M2NC_fab[idx]);
671 }
673 FArrayBox &uNC_fab = (*vec_nudg_coeff[BdyVars::u][lev])[mfi];
674 uNC_fab.template copy<RunOn::Device>(NC_M3NC_fab[idx]);
675 FArrayBox &vNC_fab = (*vec_nudg_coeff[BdyVars::v][lev])[mfi];
676 vNC_fab.template copy<RunOn::Device>(NC_M3NC_fab[idx]);
677 }
679 FArrayBox &TempNC_fab = (*vec_nudg_coeff[BdyVars::t][lev])[mfi];
680 TempNC_fab.template copy<RunOn::Device>(NC_TempNC_fab[idx]);
681 }
683 FArrayBox &SaltNC_fab = (*vec_nudg_coeff[BdyVars::s][lev])[mfi];
684 SaltNC_fab.template copy<RunOn::Device>(NC_SaltNC_fab[idx]);
685 }
686
687 } // mf
688 } // omp
689 } // idx
690
692 vec_nudg_coeff[BdyVars::ubar][lev]->FillBoundary(geom[lev].periodicity());
693 vec_nudg_coeff[BdyVars::vbar][lev]->FillBoundary(geom[lev].periodicity());
696 }
698 vec_nudg_coeff[BdyVars::u][lev]->FillBoundary(geom[lev].periodicity());
699 vec_nudg_coeff[BdyVars::v][lev]->FillBoundary(geom[lev].periodicity());
702 }
704 vec_nudg_coeff[BdyVars::t][lev]->FillBoundary(geom[lev].periodicity());
706 }
708 vec_nudg_coeff[BdyVars::s][lev]->FillBoundary(geom[lev].periodicity());
710 }
711}
712
713/**
714 * @param[in ] lev level to read in river data
715 */
716void
718{
719 amrex::Vector<int> river_pos_x;
720 amrex::Vector<int> river_pos_y;
721 amrex::Vector<int> river_direction_tmp;
722
723 std::string river_x_name = "river_Xposition";
724 std::string river_y_name = "river_Eposition";
725 std::string river_dir_name = "river_direction";
726
727 read_vec_from_netcdf(lev, nc_riv_file, river_x_name, river_pos_x);
728 read_vec_from_netcdf(lev, nc_riv_file, river_y_name, river_pos_y);
729 read_vec_from_netcdf(lev, nc_riv_file, river_dir_name, river_direction_tmp);
730
731 if (river_pos_x.empty() ||
732 river_pos_y.size() != river_pos_x.size() ||
733 river_direction_tmp.size() != river_pos_x.size())
734 {
735 amrex::Abort("River metadata arrays must be nonempty and have matching lengths: " +
736 river_x_name + "=" + std::to_string(river_pos_x.size()) + ", " +
737 river_y_name + "=" + std::to_string(river_pos_y.size()) + ", " +
738 river_dir_name + "=" + std::to_string(river_direction_tmp.size()));
739 }
740
741 int nriv = river_pos_x.size();
742 amrex::Gpu::DeviceVector<int> xpos_d(nriv);
743 amrex::Gpu::DeviceVector<int> ypos_d(nriv);
744 river_direction.resize(nriv);
745
746 int rrx = (lev > 0) ? cum_ref_ratios[lev][0] : 1;
747 int rry = (lev > 0) ? cum_ref_ratios[lev][1] : 1;
748
749 // Map river source indices to the target AMR level while keeping one source
750 // point per river so total prescribed transport is unchanged.
751 amrex::Vector<int> river_pos_x_lev(nriv);
752 amrex::Vector<int> river_pos_y_lev(nriv);
753 for (int iriv = 0; iriv < nriv; ++iriv) {
754 int x0 = river_pos_x[iriv] - 1;
755 int y0 = river_pos_y[iriv] - 1;
756
757 if (river_direction_tmp[iriv] == 0) {
758 // u-face aligned in x, centered in y within the refined coarse cell.
759 river_pos_x_lev[iriv] = x0 * rrx;
760 river_pos_y_lev[iriv] = y0 * rry + (rry - 1) / 2;
761 } else {
762 // v-face aligned in y, centered in x within the refined coarse cell.
763 river_pos_x_lev[iriv] = x0 * rrx + (rrx - 1) / 2;
764 river_pos_y_lev[iriv] = y0 * rry;
765 }
766 }
767#ifdef AMREX_USE_GPU
768 Gpu::htod_memcpy(xpos_d.data(), river_pos_x_lev.data(), sizeof(int)*nriv);
769 Gpu::htod_memcpy(ypos_d.data(), river_pos_y_lev.data(), sizeof(int)*nriv);
770 Gpu::htod_memcpy(river_direction.data(), river_direction_tmp.data(), sizeof(int)*nriv);
771#else
772 std::memcpy(xpos_d.data(), river_pos_x_lev.data(), sizeof(int)*nriv);
773 std::memcpy(ypos_d.data(), river_pos_y_lev.data(), sizeof(int)*nriv);
774 std::memcpy(river_direction.data(), river_direction_tmp.data(), sizeof(int)*nriv);
775#endif
776 const int* xpos_ptr = xpos_d.data();
777 const int* ypos_ptr = ypos_d.data();
778
779 for (amrex::MFIter mfi(*(vec_river_position[lev]).get(),true); mfi.isValid(); ++mfi) {
780 amrex::Box bx = mfi.growntilebox(amrex::IntVect(NGROW,NGROW,0));
781 auto river_pos = vec_river_position[lev]->array(mfi);
782 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int ) {
783 for (int iriv=0; iriv < nriv; iriv++) {
784 int xriv = xpos_ptr[iriv];
785 int yriv = ypos_ptr[iriv];
786 if (i==xriv && j==yriv) {
787 river_pos(i,j,0) = iriv;
788 }
789 }
790 });
791 }
792
793 if (verbose) {
794 amrex::Print() << "[river-debug] lev=" << lev
795 << " ref_ratio=(" << rrx << "," << rry << ")"
796 << " nriv=" << nriv << '\n';
797 for (int iriv = 0; iriv < nriv; ++iriv) {
798 amrex::Print() << "[river-debug] river " << iriv
799 << " dir=" << river_direction_tmp[iriv]
800 << " nc=(" << river_pos_x[iriv] << "," << river_pos_y[iriv] << ")"
801 << " lev=(" << river_pos_x_lev[iriv] + 1 << "," << river_pos_y_lev[iriv] + 1 << ")"
802 << '\n';
803 }
804 }
805}
806
807/**
808 * @param[inout] mf multifab of data to convert
809 */
810void
812 Real inv_days_to_inv_s = one / (Real(3600.0) * Real(24.0));
813
814 for ( MFIter mfi(*mf, TilingIfNotGPU()); mfi.isValid(); ++mfi )
815 {
816 Array4<Real> const& arr = mf->array(mfi);
817 Box bx = mfi.growntilebox(IntVect(NGROW,NGROW,0));
818 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
819 arr(i,j,k) *= inv_days_to_inv_s;
820 });
821 }
822
823}
824
825void
827{
828 if (nc_grid_file_hires.empty()) {
829 Abort("Must specify high-resolution grid file when initializing from NetCDF and hires_grid_level > 0");
830 }
831 Vector<FArrayBox> NC_h_fab ; NC_h_fab.resize(1);
833
834 // Don't tile this since we are operating on full FABs in this routine
835 for ( MFIter mfi(*vec_h_full_domain[hires_grid_level], false); mfi.isValid(); ++mfi )
836 {
837 FArrayBox &h_fab = (*vec_h_full_domain[hires_grid_level])[mfi];
838 h_fab.template copy<RunOn::Device>(NC_h_fab[0]);
839 }
840
841 // Average down to fill levels below hires_grid_level. Use a special average_down so
842 // grow cells get populated by averaged down fine data
843 for (int lev=hires_grid_level-1; lev >= 0; lev--) {
845 }
846}
847
848void
850{
851 if (nc_grid_file_hires.empty()) {
852 Abort("Must specify high-resolution grid file when initializing from NetCDF and hires_grid_level > 0");
853 }
854 Vector<FArrayBox> NC_pm_fab ; NC_pm_fab.resize(1);
855 Vector<FArrayBox> NC_pn_fab ; NC_pn_fab.resize(1);
856
858 NC_pm_fab[0], NC_pn_fab[0],
860
861 // Don't tile this since we are operating on full FABs in this routine
862 for ( MFIter mfi(*vec_h_full_domain[hires_grid_level], false); mfi.isValid(); ++mfi )
863 {
864 FArrayBox &pm_fab = (*vec_pm_full_domain[hires_grid_level])[mfi];
865 FArrayBox &pn_fab = (*vec_pn_full_domain[hires_grid_level])[mfi];
866 pm_fab.template copy<RunOn::Device>(NC_pm_fab[0]);
867 pn_fab.template copy<RunOn::Device>(NC_pn_fab[0]);
868 }
869
870 // Average down to fill levels below hires_grid_level. Use a special average_down so
871 // grow cells get populated by averaged down fine data
872 for (int lev=hires_grid_level-1; lev >= 0; lev--) {
875
876 int rrx = ref_ratio[lev][0];
877 int rry = ref_ratio[lev][1];
878 // pm and pn need to be rescaled by the refinement ratio
879 for ( MFIter mfi(*vec_h_full_domain[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi )
880 {
881 Array4<Real> const& pm = vec_pm_full_domain[lev]->array(mfi);
882 Array4<Real> const& pn = vec_pn_full_domain[lev]->array(mfi);
883 Box ubx = mfi.growntilebox(cum_ref_ratios[lev] - IntVect(1,0,0));;
884 Box vbx = mfi.growntilebox(cum_ref_ratios[lev] - IntVect(0,1,0));;
885 ParallelFor(makeSlab(ubx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
886 pm(i,j,0) = pm(i,j,0) / Real(rrx);
887 });
888 ParallelFor(makeSlab(vbx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int ) {
889 pn(i,j,0) = pn(i,j,0) / Real(rry);
890 });
891 }
892 }
893
894 for (int lev=0; lev<=hires_grid_level; lev++) {
897 }
898}
899
900/**
901 * @param[inout] mf multifab of data to extrapolate on
902 * @param[in ] geom geometry
903 */
904void
905REMORA::extrapolate_metric_to_physical_boundaries (MultiFab& mf, const Geometry& geom)
906{
907 const IntVect ng = mf.nGrowVect();
908
909 const auto& dom_lo = amrex::lbound(geom.Domain());
910 const auto& dom_hi = amrex::ubound(geom.Domain());
911
912 for ( MFIter mfi(mf); mfi.isValid(); ++mfi )
913 {
914 Box bx = mfi.tilebox();
915
916 auto mf_arr = mf.array(mfi);
917
918 Box gbx_lox = adjCellLo(bx,0,ng[0]); gbx_lox.grow(1,ng[1]); gbx_lox.setBig (0,dom_lo.x-2);
919 Box gbx_hix = adjCellHi(bx,0,ng[0]); gbx_hix.grow(1,ng[1]); gbx_hix.setSmall(0,dom_hi.x+2);
920 Box gbx_loy = adjCellLo(bx,1,ng[1]); gbx_loy.grow(0,ng[0]); gbx_loy.setBig (1,dom_lo.y-2);
921 Box gbx_hiy = adjCellHi(bx,1,ng[1]); gbx_hiy.grow(0,ng[0]); gbx_hiy.setSmall(1,dom_hi.y+2);
922
923 if (gbx_lox.ok()) {
924 ParallelFor(gbx_lox, [=] AMREX_GPU_DEVICE (int i, int j, int k)
925 {
926 mf_arr(i,j,k,0) = mf_arr(dom_lo.x-1,j,k,0);
927 });
928 }
929 if (gbx_hix.ok()) {
930 ParallelFor(gbx_hix, [=] AMREX_GPU_DEVICE (int i, int j, int k)
931 {
932 mf_arr(i,j,k,0) = mf_arr(dom_hi.x+1,j,k,0);
933 });
934 }
935 if (gbx_loy.ok()) {
936 ParallelFor(gbx_loy, [=] AMREX_GPU_DEVICE (int i, int j, int k)
937 {
938 mf_arr(i,j,k,0) = mf_arr(i,dom_lo.y-1,k,0);
939 });
940 }
941 if (gbx_hiy.ok()) {
942 ParallelFor(gbx_hiy, [=] AMREX_GPU_DEVICE (int i, int j, int k)
943 {
944 mf_arr(i,j,k,0) = mf_arr(i,dom_hi.y+1,k,0);
945 });
946 }
947 } // mfi
948}
949
950#endif // REMORA_USE_NETCDF
constexpr amrex::Real one
constexpr amrex::Real zero
#define NGROW
#define Temp_comp
#define Tracer_comp
#define Salt_comp
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
Real read_bdry_from_netcdf(const Box &domain, const std::string &fname, Vector< Vector< FArrayBox > > &bdy_data_xlo, Vector< Vector< FArrayBox > > &bdy_data_xhi, Vector< Vector< FArrayBox > > &bdy_data_ylo, Vector< Vector< FArrayBox > > &bdy_data_yhi, int &width, amrex::Real &start_bdy_time, std::string bdry_time_varname, amrex::GpuArray< amrex::GpuArray< bool, AMREX_SPACEDIM *2 >, BdyVars::NumTypes+1 > &)
helper function for reading boundary data 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_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 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 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_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
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, bool do_temp_clim_nudg, bool do_salt_clim_nudg, FArrayBox &NC_M2NC_fab, FArrayBox &NC_M3NC_fab, FArrayBox &NC_TempNC_fab, FArrayBox &NC_SaltNC_fab)
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:1668
amrex::Vector< std::string > nc_riv_file
NetCDF river file(s)
Definition REMORA.H:1685
int foextrap_periodic_bc() const noexcept
Definition REMORA.H:1254
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_zeta_full_domain
high resolution initial free surface height (2D)
Definition REMORA.H:536
std::string nc_init_file_hires
Init file for high resolution.
Definition REMORA.H:1675
void init_bathymetry_from_netcdf(int lev)
Bathymetry data initialization from NetCDF file.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_fcor
coriolis factor (2D)
Definition REMORA.H:559
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:379
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:388
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:550
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:574
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:368
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:539
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:579
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xr
x_grid on rho points (2D)
Definition REMORA.H:562
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xv
x_grid on v-points (2D)
Definition REMORA.H:572
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:1466
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:541
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:554
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:372
amrex::Box nc_hires_init_box
Box for the full domain at nc_hires_init_level.
Definition REMORA.H:1677
int zeta_bc() const noexcept
Definition REMORA.H:1252
amrex::Vector< amrex::IntVect > cum_ref_ratios
Cumulative refinement ratio between level 0 and level i.
Definition REMORA.H:1680
amrex::Vector< int > num_boxes_at_level
how many boxes specified at each level by tagging criteria
Definition REMORA.H:1462
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:370
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskp
land/sea mask at cell corners (2D)
Definition REMORA.H:545
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:583
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:543
amrex::Vector< std::unique_ptr< REMORAPhysBCFunct > > physbcs
Vector (over level) of functors to apply physical boundary conditions.
Definition REMORA.H:1483
std::string nc_clim_coeff_file
NetCDF climatology coefficient file.
Definition REMORA.H:1690
amrex::Vector< std::string > bdry_time_name_byvar
Name of time fields for boundary data.
Definition REMORA.H:1695
void init_riv_pos_from_netcdf(int lev)
static amrex::Vector< std::string > nc_bdry_file
NetCDF boundary data.
Definition REMORA.H:54
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:381
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:391
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:1673
int nscalar
Number of passive scalars carried in the state.
Definition REMORA.H:1544
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:1907
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1473
void init_bdry_from_netcdf(int lev)
Boundary data initialization from NetCDF file.
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1603
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > vec_river_position
iMultiFab for river positions; contents are indices of rivers
Definition REMORA.H:1411
amrex::Vector< amrex::Vector< std::unique_ptr< NCTimeSeriesBoundary > > > boundary_series
Vector over BdyVars of boundary series data containers.
Definition REMORA.H:1407
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_xp
x_grid on psi-points (2D)
Definition REMORA.H:577
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_zeta
free surface height (2D)
Definition REMORA.H:533
amrex::Gpu::DeviceVector< int > river_direction
Vector over rivers of river direction: 0: u-face; 1: v-face; 2: w-face.
Definition REMORA.H:1413
amrex::Box nc_hires_grid_box
Box for the full domain at nc_hires_grid_level.
Definition REMORA.H:1670
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:377
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:569
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:567
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn_full_domain
horizontal scaling factor: 1 / dy (2D) on whole domain
Definition REMORA.H:556
amrex::GpuArray< amrex::GpuArray< bool, AMREX_SPACEDIM *2 >, BdyVars::NumTypes+1 > phys_bc_need_data
These are flags that indicate whether we need to read in boundary data from file.
Definition REMORA.H:1509
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > vec_nudg_coeff
Climatology nudging coefficients.
Definition REMORA.H:625
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:552
static int verbose
Verbosity level of output.
Definition REMORA.H:1639
static amrex::Vector< amrex::Vector< std::string > > nc_init_file
NetCDF initialization file.
Definition REMORA.H:55
amrex::Vector< amrex::Real > t_old
old time at each level
Definition REMORA.H:1475
int hires_grid_level
Which level the high resolution bathymetry is at.
Definition REMORA.H:1666
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:564
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:586