1 #ifndef ERF_PROBCOMMON_H_
2 #define ERF_PROBCOMMON_H_
4 #include <AMReX_ParmParse.H>
5 #include <AMReX_Geometry.H>
6 #include <AMReX_FArrayBox.H>
7 #include <AMReX_MultiFab.H>
16 amrex::Real
T_0 = 300.0;
41 std::unique_ptr<amrex::MultiFab>& ,
42 std::unique_ptr<amrex::MultiFab>& ,
43 amrex::Geometry
const& )
45 amrex::Print() <<
"Hydrostatically balanced density was NOT set"
46 <<
" -- an appropriate init_type should probably have been specified"
47 <<
" (e.g., input_sounding, ideal, real, or metgrid)"
49 amrex::Error(
"Should never call erf_init_dens_hse for "+
name()+
" problem");
54 std::unique_ptr<amrex::MultiFab>& ,
55 amrex::Geometry
const& )
88 amrex::Array4<amrex::Real const>
const& ,
89 amrex::Array4<amrex::Real >
const& ,
90 amrex::Array4<amrex::Real >
const& ,
91 amrex::Array4<amrex::Real >
const& ,
92 amrex::Array4<amrex::Real >
const& ,
93 amrex::Array4<amrex::Real >
const& ,
94 amrex::Array4<amrex::Real >
const& ,
95 amrex::Array4<amrex::Real const>
const& ,
96 amrex::Array4<amrex::Real const>
const& ,
97 amrex::GeometryData
const& ,
98 amrex::Array4<amrex::Real const>
const& ,
99 amrex::Array4<amrex::Real const>
const& ,
100 amrex::Array4<amrex::Real const>
const& ,
103 amrex::Print() <<
"No perturbation to background fields supplied for "
104 <<
name() <<
" problem" << std::endl;
118 amrex::Vector<amrex::Real>& src,
119 amrex::Gpu::DeviceVector<amrex::Real>& d_src,
120 const amrex::Geometry& geom,
121 std::unique_ptr<amrex::MultiFab>& z_phys_cc)
123 if (src.empty())
return;
127 amrex::Error(
"Temperature forcing not defined for "+
name()+
" problem with terrain");
129 const int khi = geom.Domain().bigEnd()[2];
132 for (
int k = 0; k <= khi; k++)
141 amrex::Gpu::copy(amrex::Gpu::hostToDevice, src.begin(), src.end(), d_src.begin());
155 amrex::Vector<amrex::Real>& qsrc,
156 amrex::Gpu::DeviceVector<amrex::Real>& d_qsrc,
157 const amrex::Geometry& geom,
158 std::unique_ptr<amrex::MultiFab>& z_phys_cc)
160 if (qsrc.empty())
return;
164 amrex::Error(
"Moisture forcing not defined for "+
name()+
" problem with terrain");
166 const int khi = geom.Domain().bigEnd()[2];
169 for (
int k = 0; k <= khi; k++)
178 amrex::Gpu::copy(amrex::Gpu::hostToDevice, qsrc.begin(), qsrc.end(), d_qsrc.begin());
195 amrex::Vector<amrex::Real>&
wbar,
196 amrex::Gpu::DeviceVector<amrex::Real>& d_wbar,
197 const amrex::Geometry& geom,
198 std::unique_ptr<amrex::MultiFab>& z_phys_cc)
200 if (
wbar.empty())
return;
204 amrex::Error(
"Moisture forcing not defined for "+
name()+
" problem with terrain");
206 const int khi = geom.Domain().bigEnd()[2];
209 for (
int k = 0; k <= khi; k++)
218 amrex::Gpu::copy(amrex::Gpu::hostToDevice,
wbar.begin(),
wbar.end(), d_wbar.begin());
232 amrex::Vector<amrex::Real>& u_geos,
233 amrex::Gpu::DeviceVector<amrex::Real>& d_u_geos,
234 amrex::Vector<amrex::Real>& v_geos,
235 amrex::Gpu::DeviceVector<amrex::Real>& d_v_geos,
236 const amrex::Geometry& geom,
237 std::unique_ptr<amrex::MultiFab>& z_phys_cc)
239 if (u_geos.empty())
return;
243 amrex::Error(
"Geostrophic wind profile not defined for "+
name()+
" problem with terrain");
245 const int khi = geom.Domain().bigEnd()[2];
248 for (
int k = 0; k <= khi; k++)
258 amrex::Gpu::copy(amrex::Gpu::hostToDevice, u_geos.begin(), u_geos.end(), d_u_geos.begin());
259 amrex::Gpu::copy(amrex::Gpu::hostToDevice, v_geos.begin(), v_geos.end(), d_v_geos.begin());
273 amrex::MultiFab& z_phys_nd,
274 const amrex::Real& time)
277 std::string fname, fname_usgs, ftype;
278 amrex::ParmParse
pp(
"erf");
279 auto valid_fname =
pp.query(
"terrain_file_name",fname);
280 auto valid_fname_USGS =
pp.query(
"terrain_file_name_USGS",fname_usgs);
283 }
else if(valid_fname_USGS) {
287 amrex::Print() <<
"Initializing flat terrain at z=0" << std::endl;
290 int ngrow = z_phys_nd.nGrow();
295 for ( amrex::MFIter mfi(z_phys_nd, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
297 amrex::Box zbx = mfi.nodaltilebox(2);
298 if (zbx.smallEnd(2) <= 0) {
300 amrex::Box xybx = mfi.growntilebox(ngrow);
303 amrex::Array4<amrex::Real>
const& z_arr = z_phys_nd.array(mfi);
305 ParallelFor(xybx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int) {
323 amrex::FArrayBox& z_phys_nd,
327 amrex::Print() <<
"Initializing flat terrain at z=0" << std::endl;
333 amrex::Box bx = z_phys_nd.box();
334 amrex::Array4<amrex::Real>
const& z_arr = z_phys_nd.array();
336 ParallelFor(bx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int) {
354 const amrex::Geometry& geom,
355 amrex::MultiFab& z_phys_nd,
359 amrex::Print()<<
"Reading terrain file: "<< fname << std::endl;
360 std::ifstream file(fname);
361 amrex::Gpu::HostVector<amrex::Real> m_xterrain,m_yterrain,m_zterrain;
362 amrex::Real value1,value2,value3;
363 while(file>>value1>>value2>>value3){
364 m_xterrain.push_back(value1);
365 m_yterrain.push_back(value2);
366 m_zterrain.push_back(value3);
371 int nnode = m_xterrain.size();
372 amrex::Gpu::DeviceVector<amrex::Real> d_xterrain(nnode),d_yterrain(nnode),d_zterrain(nnode);
373 amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_xterrain.begin(), m_xterrain.end(), d_xterrain.begin());
374 amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_yterrain.begin(), m_yterrain.end(), d_yterrain.begin());
375 amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_zterrain.begin(), m_zterrain.end(), d_zterrain.begin());
376 amrex::Real* d_xt = d_xterrain.data();
377 amrex::Real* d_yt = d_yterrain.data();
378 amrex::Real* d_zt = d_zterrain.data();
381 amrex::Real tol = 1.0e-4;
382 int ngrow = z_phys_nd.nGrow();
383 auto dx = geom.CellSizeArray();
384 auto ProbLoArr = geom.ProbLoArray();
385 int ilo = geom.Domain().smallEnd(0);
386 int jlo = geom.Domain().smallEnd(1);
387 int klo = geom.Domain().smallEnd(2);
388 int ihi = geom.Domain().bigEnd(0) + 1;
389 int jhi = geom.Domain().bigEnd(1) + 1;
390 for (amrex::MFIter mfi(z_phys_nd,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
393 amrex::Box xybx = mfi.growntilebox(ngrow);
396 amrex::Array4<amrex::Real>
const& z_arr = z_phys_nd.array(mfi);
397 amrex::ParallelFor(xybx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int )
400 int ii = amrex::min(amrex::max(i,ilo),ihi);
401 int jj = amrex::min(amrex::max(j,jlo),jhi);
404 amrex::Real
x = ProbLoArr[0] + ii * dx[0];
405 amrex::Real
y = ProbLoArr[1] + jj * dx[1];
406 int inode = ii + jj * (ihi-ilo+2);
407 if (std::sqrt(std::pow(
x-d_xt[inode],2)+std::pow(
y-d_yt[inode],2)) < tol) {
408 z_arr(i,j,klo) = d_zt[inode];
411 amrex::Real zloc = 0.0;
413 for (
int n=0; n<nnode; ++n)
415 amrex::Real delta=std::sqrt(std::pow(
x-d_xt[n],2)+std::pow(
y-d_yt[n],2));
422 AMREX_ASSERT_WITH_MESSAGE(found,
"Location read from terrain file does not match the grid!");
423 amrex::ignore_unused(found);
424 z_arr(i,j,klo) = zloc;
432 const amrex::Geometry& geom,
433 amrex::MultiFab& z_phys_nd,
437 amrex::Print()<<
"Reading terrain file: "<< fname_usgs << std::endl;
438 std::ifstream file(fname_usgs);
440 if (!file.is_open()) {
441 amrex::Abort(
"Error: Could not open the file " + fname_usgs +
"\n");
445 if (file.peek() == std::ifstream::traits_type::eof()) {
446 amrex::Abort(
"Error: The file " + fname_usgs +
" is empty.\n");
449 amrex::Gpu::HostVector<amrex::Real> m_xterrain,m_yterrain,m_zterrain;
450 amrex::Real value1,value2,value3;
451 amrex::Real lat_min, lon_min;
454 file >> lon_min >> lat_min;
455 if(std::fabs(lon_min) > 180.0) {
456 amrex::Error(
"The value of longitude for entry in the first line in " + fname_usgs
457 +
" should not exceed 180. It is " + std::to_string(lon_min));
459 if(std::fabs(lat_min) > 90.0) {
460 amrex::Error(
"The value of latitude for entry in the first line in " + fname_usgs
461 +
" should not exceed 90. It is " + std::to_string(lat_min));
464 file >> nlons >> nlats;
467 while(file >> value1 >> value2 >> value3){
468 m_xterrain.push_back(value1);
469 if(counter%nlons==0) {
470 m_yterrain.push_back(value2);
472 m_zterrain.push_back(value3);
477 AMREX_ASSERT(m_xterrain.size() ==
static_cast<long unsigned int>(nlons*nlats));
478 AMREX_ASSERT(m_yterrain.size() ==
static_cast<long unsigned int>(nlats));
479 AMREX_ASSERT(m_zterrain.size() ==
static_cast<long unsigned int>(nlons*nlats));
484 amrex::ParmParse
pp(
"erf");
485 amrex::Real x_shift, y_shift;
486 pp.query(
"windfarm_x_shift",x_shift);
487 pp.query(
"windfarm_x_shift",y_shift);
490 for(
auto& v : m_xterrain){
493 for(
auto& v : m_yterrain){
497 if (m_xterrain.empty()) {
498 amrex::Abort(
"Error: m_xterrain is empty!\n");
501 auto index = std::max_element(m_xterrain.begin(), m_xterrain.end());
502 amrex::Real xmax_terrain = *index;
503 index = std::max_element(m_yterrain.begin(), m_yterrain.end());
504 amrex::Real ymax_terrain = *index;
506 index = std::min_element(m_zterrain.begin(), m_zterrain.end());
507 amrex::Real zmin_terrain = *index;
509 for(
auto& v : m_zterrain){
514 int nnode = nlons*nlats;
515 amrex::Gpu::DeviceVector<amrex::Real> d_xterrain(nnode),d_yterrain(nlats),d_zterrain(nnode);
516 amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_xterrain.begin(), m_xterrain.end(), d_xterrain.begin());
517 amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_yterrain.begin(), m_yterrain.end(), d_yterrain.begin());
518 amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_zterrain.begin(), m_zterrain.end(), d_zterrain.begin());
519 amrex::Real* d_xt = d_xterrain.data();
520 amrex::Real* d_yt = d_yterrain.data();
521 amrex::Real* d_zt = d_zterrain.data();
524 int ngrow = z_phys_nd.nGrow();
525 auto dx = geom.CellSizeArray();
526 auto ProbLoArr = geom.ProbLoArray();
527 int ilo = geom.Domain().smallEnd(0);
528 int jlo = geom.Domain().smallEnd(1);
529 int klo = geom.Domain().smallEnd(2);
530 int ihi = geom.Domain().bigEnd(0) + 1;
531 int jhi = geom.Domain().bigEnd(1) + 1;
533 for (amrex::MFIter mfi(z_phys_nd,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
536 amrex::Box xybx = mfi.growntilebox(ngrow);
539 amrex::Array4<amrex::Real>
const& z_arr = z_phys_nd.array(mfi);
540 amrex::ParallelFor(xybx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int )
543 int ii = amrex::min(amrex::max(i,ilo),ihi);
544 int jj = amrex::min(amrex::max(j,jlo),jhi);
547 amrex::Real
x = ProbLoArr[0] + ii * dx[0] + 1e-3;
548 amrex::Real
y = ProbLoArr[1] + jj * dx[1] + 1e-3;
550 if(x < x_shift or x > xmax_terrain or
551 y < y_shift or y > ymax_terrain) {
552 z_arr(i,j,klo) = 0.0;
554 int jindex_terrain = -1;
555 for (
int it = 0; it < nlats && jindex_terrain == -1; it++) {
557 jindex_terrain = it-1;
565 int iindex_terrain=-1;
566 int gstart = jindex_terrain*nlons;
567 int gend = (jindex_terrain+1)*nlons-1;
568 for (
int it = gstart; it <= gend && iindex_terrain == -1; it++) {
570 iindex_terrain = it-gstart;
578 int ind11, ind12, ind21, ind22;
579 ind11 = jindex_terrain*nlons + iindex_terrain;
583 amrex::Real x1 = d_xt[ind11];
584 amrex::Real x2 = d_xt[ind21];
585 amrex::Real y1 = d_yt[jindex_terrain];
586 amrex::Real y2 = d_yt[jindex_terrain+1];
588 amrex::Real denom = (x2-x1)*(y2-y1);
589 amrex::Real w_11 = (x2-
x)*(y2-
y)/denom;
590 amrex::Real w_12 = (x2-
x)*(
y-y1)/denom;
591 amrex::Real w_21 = (
x-x1)*(y2-
y)/denom;
592 amrex::Real w_22 = (
x-x1)*(
y-y1)/denom;
594 z_arr(i,j,klo) = w_11*d_zt[ind11] + w_12*d_zt[ind12] + w_21*d_zt[ind21] + w_22*d_zt[ind22];
611 #ifdef ERF_USE_TERRAIN_VELOCITY
612 virtual amrex::Real compute_terrain_velocity(
const amrex::Real )
614 amrex::Error(
"Should never call compute_terrain_velocity for "+
name()+
" problem");
627 amrex::Geometry
const& ,
628 std::unique_ptr<amrex::MultiFab>& ,
631 amrex::Error(
"Should never call erf_init_rayleigh for "+
name()+
" problem");
638 init_uniform (
const amrex::Box& bx, amrex::Array4<amrex::Real>
const& state)
642 amrex::Print() <<
"Initializing uniform fields"
643 <<
" rho=" << rho_0 <<
" theta=" << T_0
646 ParallelFor(bx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept
667 virtual std::string
name () = 0;
676 const amrex_real* probhi) AMREX_ATTRIBUTE_WEAK;
@ wbar
Definition: ERF_DataStruct.H:70
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:219
std::unique_ptr< ProblemBase > amrex_probinit(const amrex_real *problo, const amrex_real *probhi) AMREX_ATTRIBUTE_WEAK
Definition: ERF_ProbCommon.H:23
virtual void init_custom_pert(const amrex::Box &, const amrex::Box &, const amrex::Box &, const amrex::Box &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, amrex::GeometryData const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, const SolverChoice &)
Definition: ERF_ProbCommon.H:84
virtual std::string name()=0
virtual void init_custom_terrain(const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, const amrex::Real &time)
Definition: ERF_ProbCommon.H:272
void init_uniform(const amrex::Box &bx, amrex::Array4< amrex::Real > const &state)
Definition: ERF_ProbCommon.H:638
virtual void read_custom_terrain(const std::string &fname, const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, const amrex::Real &)
Definition: ERF_ProbCommon.H:353
virtual void update_geostrophic_profile(const amrex::Real &, amrex::Vector< amrex::Real > &u_geos, amrex::Gpu::DeviceVector< amrex::Real > &d_u_geos, amrex::Vector< amrex::Real > &v_geos, amrex::Gpu::DeviceVector< amrex::Real > &d_v_geos, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
Definition: ERF_ProbCommon.H:231
virtual void update_rhoqt_sources(const amrex::Real &, amrex::Vector< amrex::Real > &qsrc, amrex::Gpu::DeviceVector< amrex::Real > &d_qsrc, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
Definition: ERF_ProbCommon.H:154
virtual void erf_init_rayleigh(amrex::Vector< amrex::Vector< amrex::Real > > &, amrex::Geometry const &, std::unique_ptr< amrex::MultiFab > &, amrex::Real)
Definition: ERF_ProbCommon.H:626
void init_base_parms(amrex::Real rho_0, amrex::Real T_0)
Definition: ERF_ProbCommon.H:661
virtual ~ProblemBase()=default
virtual void erf_init_dens_hse_moist(amrex::MultiFab &, std::unique_ptr< amrex::MultiFab > &, amrex::Geometry const &)
Definition: ERF_ProbCommon.H:53
virtual void update_rhotheta_sources(const amrex::Real &, amrex::Vector< amrex::Real > &src, amrex::Gpu::DeviceVector< amrex::Real > &d_src, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
Definition: ERF_ProbCommon.H:117
ProbParmDefaults base_parms
Definition: ERF_ProbCommon.H:655
virtual void read_custom_terrain_USGS(const std::string &fname_usgs, const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, const amrex::Real &)
Definition: ERF_ProbCommon.H:431
virtual void update_w_subsidence(const amrex::Real &, amrex::Vector< amrex::Real > &wbar, amrex::Gpu::DeviceVector< amrex::Real > &d_wbar, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
Definition: ERF_ProbCommon.H:194
virtual void erf_init_dens_hse(amrex::MultiFab &, std::unique_ptr< amrex::MultiFab > &, std::unique_ptr< amrex::MultiFab > &, amrex::Geometry const &)
Definition: ERF_ProbCommon.H:40
virtual void init_custom_terrain(const amrex::Geometry &, amrex::FArrayBox &z_phys_nd, const amrex::Real &)
Definition: ERF_ProbCommon.H:322
Definition: ERF_ProbCommon.H:14
amrex::Real T_0
Definition: ERF_ProbCommon.H:16
amrex::Real rho_0
Definition: ERF_ProbCommon.H:15
Definition: ERF_DataStruct.H:82
static void set_flat_terrain_flag()
Definition: ERF_DataStruct.H:573