ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ProblemBase Class Reference

#include <ERF_ProbCommon.H>

Collaboration diagram for ProblemBase:

Public Member Functions

virtual ~ProblemBase ()=default
 
virtual void erf_init_dens_hse_dry (amrex::MultiFab &, std::unique_ptr< amrex::MultiFab > &, std::unique_ptr< amrex::MultiFab > &, amrex::Geometry const &, const amrex::Vector< amrex::Real > &, bool, bool)
 
virtual void erf_init_const_dens_hse (amrex::MultiFab &)
 
virtual void erf_init_const_dens_and_th_hse (amrex::MultiFab &, amrex::MultiFab &, amrex::MultiFab &, amrex::MultiFab &, amrex::MultiFab &, amrex::Real)
 
virtual void erf_init_const_dens_and_linear_th_hse (amrex::MultiFab &, amrex::MultiFab &, amrex::MultiFab &, amrex::MultiFab &, amrex::MultiFab &, amrex::Real, std::unique_ptr< amrex::MultiFab > &)
 
virtual void erf_init_dens_hse_moist (amrex::MultiFab &, std::unique_ptr< amrex::MultiFab > &, amrex::Geometry const &)
 
virtual void init_custom_pert (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 > const &, amrex::Array4< amrex::Real const > const &, amrex::GeometryData const &, amrex::Array4< amrex::Real const > const &, const SolverChoice &, const int)
 
virtual void init_custom_pert_vels (const amrex::Box &, const amrex::Box &, const amrex::Box &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real const > const &, amrex::GeometryData const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, const SolverChoice &, const int)
 
virtual void update_rhotheta_sources (const double &, amrex::MultiFab *src, const amrex::Geometry &, std::unique_ptr< amrex::MultiFab > &, const amrex::Vector< amrex::Real > &)
 
virtual void update_rhoqt_sources (const double &, amrex::MultiFab *qsrc, const amrex::Geometry &, std::unique_ptr< amrex::MultiFab > &, const amrex::Vector< amrex::Real > &)
 
virtual void update_w_subsidence (const double &, amrex::Vector< amrex::Real > &wbar, amrex::Gpu::DeviceVector< amrex::Real > &d_wbar, const amrex::MultiFab &, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &, const amrex::Vector< amrex::Real > &)
 
virtual void update_geostrophic_profile (const double &, 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 > &, const amrex::Vector< amrex::Real > &)
 
void init_buildings_surface (const amrex::Geometry &geom, amrex::FArrayBox &buildings_fab, const double &time)
 
void init_terrain_surface (const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const double &time)
 
virtual bool terrain_is_specified ()
 
void read_custom_terrain (const std::string &fname, const bool is_usgs, const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const double &)
 
virtual void init_custom_terrain (const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const double &time)
 
virtual void erf_init_rayleigh (amrex::Vector< amrex::Vector< amrex::Real > > &, amrex::Geometry const &, std::unique_ptr< amrex::MultiFab > &, amrex::Real)
 

Protected Member Functions

void init_base_parms (amrex::Real rho_0, amrex::Real T_0)
 
std::string name ()
 

Protected Attributes

ProbParmDefaults base_parms
 

Detailed Description

Class to hold problem-specific routines

Constructor & Destructor Documentation

◆ ~ProblemBase()

virtual ProblemBase::~ProblemBase ( )
virtualdefault

Virtual destructor to avoid data leakage with derived class

Member Function Documentation

◆ erf_init_const_dens_and_linear_th_hse()

virtual void ProblemBase::erf_init_const_dens_and_linear_th_hse ( amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::Real  ,
std::unique_ptr< amrex::MultiFab > &   
)
inlinevirtual
110  {
111  amrex::Error("Should never call this version of erf_init_const_dens_and_linear_th_hse for "+name()+" problem");
112  }
std::string name()
Definition: ERF_ProbCommon.H:1219
Here is the call graph for this function:

◆ erf_init_const_dens_and_th_hse()

virtual void ProblemBase::erf_init_const_dens_and_th_hse ( amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::MultiFab &  ,
amrex::Real   
)
inlinevirtual
101  {
102  amrex::Error("Should never call this version of erf_init_const_dens_and_th_hse for "+name()+" problem");
103  }
Here is the call graph for this function:

◆ erf_init_const_dens_hse()

virtual void ProblemBase::erf_init_const_dens_hse ( amrex::MultiFab &  )
inlinevirtual
93  {
94  amrex::Error("Should never call this version of erf_init_const_dens_hse for "+name()+" problem");
95  }
Here is the call graph for this function:

◆ erf_init_dens_hse_dry()

virtual void ProblemBase::erf_init_dens_hse_dry ( amrex::MultiFab &  ,
std::unique_ptr< amrex::MultiFab > &  ,
std::unique_ptr< amrex::MultiFab > &  ,
amrex::Geometry const &  ,
const amrex::Vector< amrex::Real > &  ,
bool  ,
bool   
)
inlinevirtual

Function to initialize the hydrostatic reference density

Parameters
[out]rho_hsehydrostatic reference density
[in]z_phys_ndheight coordinate at nodes
[in]z_phys_ccheight coordinate at cell centers
[in]geomcontainer for geometric information
83  {
84  amrex::Print() << "Hydrostatically balanced density was NOT set"
85  << " -- an appropriate init_type should probably have been specified"
86  << " (e.g., input_sounding, WRFInput, or Metgrid)"
87  << std::endl;
88  amrex::Error("Should never call this version of erf_init_dens_hse_dry for "+name()+" problem");
89  }
Here is the call graph for this function:

◆ erf_init_dens_hse_moist()

virtual void ProblemBase::erf_init_dens_hse_moist ( amrex::MultiFab &  ,
std::unique_ptr< amrex::MultiFab > &  ,
amrex::Geometry const &   
)
inlinevirtual
118  {
119 
120  }

◆ erf_init_rayleigh()

virtual void ProblemBase::erf_init_rayleigh ( amrex::Vector< amrex::Vector< amrex::Real > > &  ,
amrex::Geometry const &  ,
std::unique_ptr< amrex::MultiFab > &  ,
amrex::Real   
)
inlinevirtual

Function to define the quantities needed to impose Rayleigh damping

Parameters
[out]rayleigh_ptrs= {strength of Rayleigh damping, reference values for xvel/yvel/zvel/theta used to define Rayleigh damping}
[in]geomcontainer for geometric information
[in]z_phys_ccheight coordinate at cell centers
1202  {
1203  // Default which does no harm
1204  }

◆ init_base_parms()

void ProblemBase::init_base_parms ( amrex::Real  rho_0,
amrex::Real  T_0 
)
inlineprotected

Function to update default base parameters, currently only used for init_type == InitType::Uniform

1214  {
1216  base_parms.T_0 = T_0;
1217  }
Real rho_0
Definition: ERF_InitCustomPert_ABL.H:18
Real T_0
Definition: ERF_InitCustomPert_ABL.H:19
ProbParmDefaults base_parms
Definition: ERF_ProbCommon.H:1208
amrex::Real T_0
Definition: ERF_ProbCommon.H:27
amrex::Real rho_0
Definition: ERF_ProbCommon.H:26

◆ init_buildings_surface()

void ProblemBase::init_buildings_surface ( const amrex::Geometry &  geom,
amrex::FArrayBox &  buildings_fab,
const double &  time 
)
inline

Function to perform custom initialization of buildings

Parameters
[in]geomcontainer for geometric information
[out]z_phys_ndheight coordinate at nodes
[in]timecurrent time
344  {
345  // Check if a valid text file exists for the buildings
346  std::string fname;
347  amrex::ParmParse pp("erf");
348  auto valid_fname = pp.queryAdd("buildings_file_name",fname);
349 
350  if (valid_fname) {
351  read_custom_terrain(fname,false,geom,buildings_fab,time);
352  } else {
353  init_my_custom_terrain(geom, buildings_fab, time);
354  }
355  }
ParmParse pp("prob")
void init_my_custom_terrain(const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const double &time)
void read_custom_terrain(const std::string &fname, const bool is_usgs, const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const double &)
Definition: ERF_ProbCommon.H:854
Here is the call graph for this function:

◆ init_custom_pert()

virtual void ProblemBase::init_custom_pert ( 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 > const &  ,
amrex::Array4< amrex::Real const > const &  ,
amrex::GeometryData const &  ,
amrex::Array4< amrex::Real const > const &  ,
const SolverChoice &  ,
const int   
)
inlinevirtual

Function to perform custom initialization of a test problem

Parameters
[in]bxcell-centered box on which to initialize scalars
[out]statecell-centered variables to be filled in this routine
[out]r_hsehydrostatic reference density
[out]p_hsehydrostatic reference pressure
[in]z_ndheight coordinate at nodes
[in]z_ccheight coordinate at cell centers
[in]mf_mmap factor on cell centers
[in]mf_umap factor on x-faces
[in]mf_vmap factor on y-faces
[in]scSolverChoice structure that carries parameters
[in]levAMR level
148  {
149  amrex::Print() << "No perturbation to background fields supplied for "
150  << name() << " problem" << std::endl;
151  }
Here is the call graph for this function:

◆ init_custom_pert_vels()

virtual void ProblemBase::init_custom_pert_vels ( const amrex::Box &  ,
const amrex::Box &  ,
const amrex::Box &  ,
amrex::Array4< amrex::Real > const &  ,
amrex::Array4< amrex::Real > const &  ,
amrex::Array4< amrex::Real > const &  ,
amrex::Array4< amrex::Real const > const &  ,
amrex::GeometryData const &  ,
amrex::Array4< amrex::Real const > const &  ,
amrex::Array4< amrex::Real const > const &  ,
const SolverChoice &  ,
const int   
)
inlinevirtual

Function to perform custom initialization of the velocities

Parameters
[in]xbxbox on which to initialize x_vel_pert
[in]ybxbox on which to initialize y_vel_pert
[in]zbxbox on which to initialize z_vel_pert
[out]x_vel_pertx-component of velocity perturbation to be filled in this routine
[out]y_vel_perty-component of velocity perturbation to be filled in this routine
[out]z_vel_pertz-component of velocity perturbation to be filled in this routine
[in]z_ndheight coordinate at nodes
[in]mf_mmap factor on cell centers
[in]mf_umap factor on x-faces
[in]mf_vmap factor on y-faces
[in]scSolverChoice structure that carries parameters
[in]levAMR level
181  {
182  amrex::Print() << "No perturbation velocities supplied for " << name() << " problem" << std::endl;
183  }
Here is the call graph for this function:

◆ init_custom_terrain()

virtual void ProblemBase::init_custom_terrain ( const amrex::Geometry &  geom,
amrex::FArrayBox &  terrain_fab,
const double &  time 
)
inlinevirtual

Function to perform custom initialization of terrain

Note: Terrain functionality can also be used to provide grid stretching.

Parameters
[in]geomcontainer for geometric information
[out]terrain_mfheight coordinate at nodes
[in]timecurrent time
1163  {
1164  std::string custom_terrain_type = "None";
1165  amrex::ParmParse pp_prob("prob"); pp_prob.queryAdd("custom_terrain_type",custom_terrain_type);
1166 
1167  if (custom_terrain_type != "None")
1168  {
1169  amrex::Print() << "Calling custom terrain initialization" << std::endl;
1170  init_my_custom_terrain(geom,terrain_fab,time);
1171 
1172  } else {
1173  amrex::Print() << "Initializing flat terrain" << std::endl;
1174  terrain_fab.template setVal<amrex::RunOn::Device>(0);
1175 
1176  if (SolverChoice::mesh_type == MeshType::VariableDz) {
1177  SolverChoice::set_mesh_type(MeshType::StretchedDz);
1178  amrex::Print() << "Resetting mesh type to StretchedDz" << std::endl;
1179  }
1180  }
1181  }
ParmParse pp_prob("prob")
static MeshType mesh_type
Vertical mesh representation.
Definition: ERF_DataStruct.H:2236
static void set_mesh_type(MeshType new_mesh_type)
Override the globally selected mesh type.
Definition: ERF_DataStruct.H:2243
Here is the call graph for this function:

◆ init_terrain_surface()

void ProblemBase::init_terrain_surface ( const amrex::Geometry &  geom,
amrex::FArrayBox &  terrain_fab,
const double &  time 
)
inline

Function to perform custom initialization of terrain

Parameters
[in]geomcontainer for geometric information
[out]z_phys_ndheight coordinate at nodes
[in]timecurrent time
369  {
370  amrex::ParmParse pp("erf");
371 
372  // NetCDF terrain file takes priority
373  std::string fname_nc;
374  auto valid_fname_nc = pp.query("terrain_file_name_nc", fname_nc);
375 
376  std::string fname, fname_usgs;
377  auto valid_fname = pp.query("terrain_file_name", fname);
378  auto valid_fname_USGS = pp.query("terrain_file_name_USGS", fname_usgs);
379 
380  if (valid_fname_nc) {
381 #ifdef ERF_USE_NETCDF
382  read_terrain_netcdf(fname_nc, geom, terrain_fab, time);
383 #else
384  amrex::Abort("ERF must be compiled with NetCDF support to use terrain_file_name_nc");
385 #endif
386  } else if (valid_fname) {
387  read_custom_terrain(fname, false, geom, terrain_fab, time);
388 
389  } else if (valid_fname_USGS) {
390  read_custom_terrain(fname_usgs, true, geom, terrain_fab, time);
391 
392  } else {
393  init_my_custom_terrain (geom, terrain_fab, time);
394  }
395  }

Referenced by fill_terrain_surface_slab().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ name()

std::string ProblemBase::name ( )
inlineprotected
1219  {
1220  std::string prob_name;
1221  amrex::ParmParse pp("erf");
1222  pp.get("prob_name",prob_name); return prob_name;
1223  }

Referenced by erf_init_const_dens_and_linear_th_hse(), erf_init_const_dens_and_th_hse(), erf_init_const_dens_hse(), erf_init_dens_hse_dry(), init_custom_pert(), init_custom_pert_vels(), update_geostrophic_profile(), update_rhoqt_sources(), update_rhotheta_sources(), and update_w_subsidence().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_custom_terrain()

void ProblemBase::read_custom_terrain ( const std::string &  fname,
const bool  is_usgs,
const amrex::Geometry &  geom,
amrex::FArrayBox &  terrain_fab,
const double &   
)
inline
859  {
860  amrex::Vector<amrex::Real> m_xterrain,m_yterrain,m_zterrain;
861 
862  int nx = 0; int ny = 0;
863 
864  if (amrex::ParallelDescriptor::IOProcessor()) {
865  // Read terrain file
866  amrex::Print()<<"Reading terrain file: "<< fname<< std::endl;
867  std::ifstream file(fname);
868 
869  if (!file.is_open()) {
870  amrex::Abort("Error: Could not open the file " + fname+ "\n");
871  }
872 
873  // Check if file is empty
874  if (file.peek() == std::ifstream::traits_type::eof()) {
875  amrex::Abort("Error: The file " + fname+ " is empty.\n");
876  }
877 
878  amrex::Real value1,value2,value3;
879 
880  if (is_usgs) {
881  amrex::Real lat_min, lon_min;
882 
883  file >> lon_min >> lat_min;
884  if(std::fabs(lon_min) > amrex::Real(180.0)) {
885  amrex::Error("The value of longitude for entry in the first line in " + fname
886  + " should not exceed amrex::Real(180.) It is " + std::to_string(lon_min));
887  }
888  if(std::fabs(lat_min) > amrex::Real(90.0)) {
889  amrex::Error("The value of latitude for entry in the first line in " + fname
890  + " should not exceed amrex::Real(90.) It is " + std::to_string(lat_min));
891  }
892 
893  file >> nx >> ny;
894 
895  int counter = 0;
896  while (file >> value1 >> value2 >> value3) {
897  m_xterrain.push_back(value1);
898  if(counter%nx==0) {
899  m_yterrain.push_back(value2);
900  }
901  m_zterrain.push_back(value3);
902  counter += 1;
903  }
904  AMREX_ASSERT(m_xterrain.size() == static_cast<long int>(nx*ny));
905  AMREX_ASSERT(m_yterrain.size() == static_cast<long int>(ny));
906  AMREX_ASSERT(m_zterrain.size() == static_cast<long int>(nx*ny));
907 
908  } else {
909  int cnt = 1;
910  nx = erf_get_single_value<int>(file,cnt); cnt++;
911  ny = erf_get_single_value<int>(file,cnt); cnt++;
912  amrex::Print()<<"Expecting " << nx << " values of x, " <<
913  ny << " values of y, and " <<
914  nx*ny << " values of z" << std::endl;
915  AMREX_ALWAYS_ASSERT(nx > 0);
916  AMREX_ALWAYS_ASSERT(ny > 0);
917  m_xterrain.resize(nx);
918  m_yterrain.resize(ny);
919  m_zterrain.resize(nx * ny);
920  for (int n = 0; n < nx; n++) {
921  m_xterrain[n] = erf_get_single_value<amrex::Real>(file,cnt);
922  cnt++;
923  }
924  for (int n = 0; n < ny; n++) {
925  m_yterrain[n] = erf_get_single_value<amrex::Real>(file,cnt);
926  cnt++;
927  }
928  for (int n = 0; n < nx * ny; n++) {
929  m_zterrain[n] = erf_get_single_value<amrex::Real>(file,cnt);
930  cnt++;
931  }
932  }
933 
934  // Close the file after reading
935  file.close();
936  }
937 
938  amrex::ParallelDescriptor::Bcast(&nx,1,amrex::ParallelDescriptor::IOProcessorNumber());
939  amrex::ParallelDescriptor::Bcast(&ny,1,amrex::ParallelDescriptor::IOProcessorNumber());
940 
941  AMREX_ALWAYS_ASSERT(nx > 0 && ny > 0);
942  if (is_usgs) {
943  // The usgs branch below always uses a full 2x2 stencil
945  "USGS terrain file must have at least two points in each direction");
946  }
947 
948  int nz = nx * ny;
949  int nx_vals = is_usgs ? (nx * ny) : nx;
950 
951  m_xterrain.resize(nx_vals);
952  m_yterrain.resize(ny);
953  m_zterrain.resize(nz);
954 
955  amrex::ParallelDescriptor::Bcast(m_xterrain.data(),nx_vals,amrex::ParallelDescriptor::IOProcessorNumber());
956  amrex::ParallelDescriptor::Bcast(m_yterrain.data(),ny,amrex::ParallelDescriptor::IOProcessorNumber());
957  amrex::ParallelDescriptor::Bcast(m_zterrain.data(),nz,amrex::ParallelDescriptor::IOProcessorNumber());
958 
959  // Copy data to the GPU
960  amrex::Gpu::DeviceVector<amrex::Real> d_xterrain(nx_vals),d_yterrain(ny),d_zterrain(nz);
961  amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_xterrain.begin(), m_xterrain.end(), d_xterrain.begin());
962  amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_yterrain.begin(), m_yterrain.end(), d_yterrain.begin());
963  amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_zterrain.begin(), m_zterrain.end(), d_zterrain.begin());
964 
965  amrex::Real* d_xt = d_xterrain.data();
966  amrex::Real* d_yt = d_yterrain.data();
967  amrex::Real* d_zt = d_zterrain.data();
968 
969  auto dx = geom.CellSizeArray();
970  auto ProbLoArr = geom.ProbLoArray();
971 
972  int ilo = geom.Domain().smallEnd(0);
973  int jlo = geom.Domain().smallEnd(1);
974  int klo = geom.Domain().smallEnd(2);
975  int ihi = geom.Domain().bigEnd(0) + 1;
976  int jhi = geom.Domain().bigEnd(1) + 1;
977 
978  amrex::Box zbx = terrain_fab.box();
979  amrex::Array4<amrex::Real> const& z_arr = terrain_fab.array();
980 
981  amrex::ParallelFor(zbx, [=] AMREX_GPU_DEVICE (int i, int j, int /*k*/)
982  {
983  // Clip indices for ghost cells
984  int ii = amrex::min(amrex::max(i,ilo),ihi);
985  int jj = amrex::min(amrex::max(j,jlo),jhi);
986 
987  // Location of nodes
988  amrex::Real x = ProbLoArr[0] + ii * dx[0] + amrex::Real(1e-3);
989  amrex::Real y = ProbLoArr[1] + jj * dx[1] + amrex::Real(1e-3);
990 
991  int ind11, ind12, ind21, ind22;
992  amrex::Real x1, x2, y1, y2;
993 
994  int iindex_terrain=-1;
995  int jindex_terrain=-1;
996  // *******************************************************************
997  // NOTE: usgs-format is contiguous in x
998  // *******************************************************************
999  if (is_usgs) {
1000 
1001  // NOTE: the searches below must distinguish "the node is below the first
1002  // table value" (bracket index -1) from "no table value exceeds the
1003  // node" (search never triggered), so we can not use the initial
1004  // value of -1 as the not-found flag
1005  bool jfound = false;
1006  for (int it = 0; it < ny && !jfound; it++) {
1007  if (d_yt[it] > y) {
1008  jindex_terrain = it-1; jfound = true;
1009  }
1010  }
1011  if (!jfound) {
1012  jindex_terrain = ny-1;
1013  }
1014  // Keep the 2x2 stencil inside the table
1015  jindex_terrain = amrex::min(amrex::max(jindex_terrain,0), ny-2);
1016 
1017  int gstart = (jindex_terrain )*nx;
1018  int gend = (jindex_terrain+1)*nx-1;
1019  bool ifound = false;
1020  for (int it = gstart; it <= gend && !ifound; it++) {
1021  if (d_xt[it] > x) {
1022  iindex_terrain = it-gstart-1; ifound = true;
1023  }
1024  }
1025  if (!ifound) {
1026  iindex_terrain = nx-1;
1027  }
1028  // Keep the 2x2 stencil inside the table
1029  iindex_terrain = amrex::min(amrex::max(iindex_terrain,0), nx-2);
1030 
1031  // Define the four values to interpolate between
1032  ind11 = jindex_terrain*nx + iindex_terrain; // (x1,y1)
1033  ind12 = ind11+nx; // (x1,y2)
1034  ind21 = ind11+1; // (x2,y1)
1035  ind22 = ind12+1; // (x2,y2)
1036 
1037  x1 = d_xt[ind11];
1038  x2 = d_xt[ind21];
1039  y1 = d_yt[jindex_terrain];
1040  y2 = d_yt[jindex_terrain+1];
1041 
1042  amrex::Real denom = (x2-x1)*(y2-y1);
1043 
1044  if (denom == amrex::Real(0.0)) {
1045  // Degenerate cell (repeated x or y in the table) -- use the corner value
1046  z_arr(i,j,klo) = d_zt[ind11];
1047  } else {
1048  amrex::Real w_11 = (x2-x)*(y2-y)/denom; // (x1,y1)
1049  amrex::Real w_12 = (x2-x)*(y-y1)/denom; // (x1,y2)
1050  amrex::Real w_21 = (x-x1)*(y2-y)/denom; // (x2,y1)
1051  amrex::Real w_22 = (x-x1)*(y-y1)/denom; // (x2,y2)
1052 
1053  // Do bilinear interpolation
1054  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];
1055  }
1056 
1057  } else {
1058 
1059  bool jfound = false;
1060  for (int it = 0; it < ny && !jfound; it++) {
1061  if (d_yt[it] > y) {
1062  jindex_terrain = it-1; jfound = true;
1063  }
1064  }
1065  if (!jfound) {
1066  // No table value exceeds y -- fall back to the last row
1067  jindex_terrain = ny-1;
1068  }
1069  jindex_terrain = amrex::max(jindex_terrain,0);
1070 
1071  bool ifound = false;
1072  for (int it = 0; it < nx && !ifound; it++) {
1073  if (d_xt[it] > x) {
1074  iindex_terrain = it-1; ifound = true;
1075  }
1076  }
1077  if (!ifound) {
1078  // No table value exceeds x -- fall back to the last column
1079  iindex_terrain = nx-1;
1080  }
1081  iindex_terrain = amrex::max(iindex_terrain,0);
1082 
1083  // NOTE: these must be clamped since the fallbacks above can leave
1084  // iindex_terrain = nx-1 (jindex_terrain = ny-1)
1085  int ip1 = amrex::min(iindex_terrain+1,nx-1);
1086  int jp1 = amrex::min(jindex_terrain+1,ny-1);
1087 
1088  // Define the four values to interpolate between
1089  x1 = d_xt[iindex_terrain];
1090  x2 = d_xt[ip1];
1091  y1 = d_yt[jindex_terrain];
1092  y2 = d_yt[jp1];
1093 
1094 #if 1
1095  // *******************************************************************
1096  // NOTE: this format is contiguous in y to match the AMR-Wind read
1097  // *******************************************************************
1098  ind11 = iindex_terrain * ny + jindex_terrain; // (x1,y1)
1099  ind21 = ip1 * ny + jindex_terrain; // (x2,y1)
1100 
1101  ind12 = iindex_terrain * ny + jp1; // (x1,y2)
1102  ind22 = ip1 * ny + jp1; // (x2,y2)
1103 #else
1104  // *******************************************************************
1105  // NOTE: this format is contiguous in x as an alternative
1106  // *******************************************************************
1107 
1108  ind11 = jindex_terrain * nx + iindex_terrain; // (x1,y1)
1109  ind12 = jp1 * nx + iindex_terrain; // (x1,y2)
1110 
1111  ind21 = jindex_terrain * nx + ip1; // (x2,y1)
1112  ind22 = jp1 * nx + ip1; // (x2,y2)
1113 #endif
1114 
1115  // Only interpolate in a direction if we have a non-degenerate interval there
1116  bool interp_x = (ip1 != iindex_terrain) && (x2 != x1);
1117  bool interp_y = (jp1 != jindex_terrain) && (y2 != y1);
1118 
1119  if (!interp_x && !interp_y)
1120  {
1121  z_arr(i,j,klo) = d_zt[ind11];
1122  }
1123  else if (interp_x && !interp_y)
1124  {
1125  amrex::Real w_11 = (x2-x); // (x1,y1)
1126  amrex::Real w_21 = (x-x1); // (x2,y1)
1127  amrex::Real denom = (x2-x1);
1128  z_arr(i,j,klo) = (w_11*d_zt[ind11] + w_21*d_zt[ind21])/denom;
1129  }
1130  else if (!interp_x && interp_y)
1131  {
1132  amrex::Real w_11 = (y2-y); // (x1,y1)
1133  amrex::Real w_12 = (y-y1); // (x1,y2)
1134  amrex::Real denom = (y2-y1);
1135  z_arr(i,j,klo) = (w_11*d_zt[ind11] + w_12*d_zt[ind12])/denom;
1136  }
1137  else
1138  {
1139  amrex::Real w_11 = (x2-x)*(y2-y); // (x1,y1)
1140  amrex::Real w_21 = (x-x1)*(y2-y); // (x2,y1)
1141  amrex::Real w_12 = (x2-x)*(y-y1); // (x1,y2)
1142  amrex::Real w_22 = (x-x1)*(y-y1); // (x2,y2)
1143  amrex::Real denom = (x2-x1)*(y2-y1);
1144  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]) / denom;
1145  }
1146  } // usgs?
1147  });
1148  }
const int nx
Definition: ERF_InitCustomPertVels_CloudChamber.H:14
const int ny
Definition: ERF_InitCustomPertVels_CloudChamber.H:15
const int klo
Definition: ERF_InitCustomPert_ABL.H:75
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19

Referenced by init_buildings_surface(), and init_terrain_surface().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ terrain_is_specified()

virtual bool ProblemBase::terrain_is_specified ( )
inlinevirtual

Function to report whether the user has actually specified a terrain surface, i.e. whether init_terrain_surface will do anything other than return flat terrain.

This mirrors the source precedence in init_terrain_surface, and is deliberately kept next to it so that the two cannot drift apart. A problem that overrides the terrain unconditionally, rather than keying off prob.custom_terrain_type, should override this to return true.

408  {
409  amrex::ParmParse pp("erf");
410  std::string fname;
411  if (pp.query("terrain_file_name_nc", fname) ||
412  pp.query("terrain_file_name", fname) ||
413  pp.query("terrain_file_name_USGS", fname)) {
414  return true;
415  }
416 
417  std::string custom_terrain_type = "None";
418  amrex::ParmParse pp_prob("prob");
419  pp_prob.query("custom_terrain_type", custom_terrain_type);
420  return (custom_terrain_type != "None");
421  }
Here is the call graph for this function:

◆ update_geostrophic_profile()

virtual void ProblemBase::update_geostrophic_profile ( const double &  ,
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 > &  ,
const amrex::Vector< amrex::Real > &   
)
inlinevirtual

Function to update user-specified geostrophic wind profile.

Parameters
[in]timecurrent time
[out]u_geosgeostrophic wind profile
[out]v_geosgeostrophic wind profile
[in]geomcontainer for geometric information
[in]z_phys_ccheight coordinate at cell centers
[in]zlevels_stagnominal heights of the z faces of this level
312  {
313  if (u_geos.empty()) return;
314 
315  amrex::Warning("Geostrophic wind profile not defined for "+name()+" problem");
316 
317  const int khi = geom.Domain().bigEnd()[2];
318  // const amrex::Real* prob_lo = geom.ProbLo();
319  // const auto dx = geom.CellSize();
320  for (int k = 0; k <= khi; k++)
321  {
322  // const amrex::Real z_cc = prob_lo[2] + (k+myhalf)* dx[2];
323  // set RHS term of RhoTheta equation based on time, z_cc here
324  u_geos[k] = zero;
325  v_geos[k] = zero;
326  }
327 
328  // Copy from host version to device version
329  amrex::Gpu::copy(amrex::Gpu::hostToDevice, u_geos.begin(), u_geos.end(), d_u_geos.begin());
330  amrex::Gpu::copy(amrex::Gpu::hostToDevice, v_geos.begin(), v_geos.end(), d_v_geos.begin());
331  }
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
Here is the call graph for this function:

◆ update_rhoqt_sources()

virtual void ProblemBase::update_rhoqt_sources ( const double &  ,
amrex::MultiFab *  qsrc,
const amrex::Geometry &  ,
std::unique_ptr< amrex::MultiFab > &  ,
const amrex::Vector< amrex::Real > &   
)
inlinevirtual

Function to update user-specified moisture source terms that can vary with time and height.

Parameters
[in]timecurrent time
[out]rhoqt_sourcemoisture forcing profile
[in]geomcontainer for geometric information
[in]z_phys_ccheight coordinate at cell centers
[in]zlevels_stagnominal heights of the z faces of this level
235  {
236  if (qsrc->empty()) return;
237 
238  amrex::Warning("Moisture forcing not defined for "+name()+" problem");
239  for ( amrex::MFIter mfi(*qsrc, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
240  {
241  const auto &box = mfi.tilebox();
242  const amrex::Array4<amrex::Real>& qsrc_arr = qsrc->array(mfi);
243  // src is a spatial function if erf.spatial_moisture_forcing = true
244  // otherwise, qsrc_arr is defined only in over Z (box x and y dimensions are 1)
245  ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
246  // const amrex::Real z_cc = prob_lo[2] + (k+myhalf)* dx[2];
247  // set RHS term of RhoQ1 equation based on time, z_cc here
248  qsrc_arr(i, j, k) = zero;
249  });
250  }
251  }
Here is the call graph for this function:

◆ update_rhotheta_sources()

virtual void ProblemBase::update_rhotheta_sources ( const double &  ,
amrex::MultiFab *  src,
const amrex::Geometry &  ,
std::unique_ptr< amrex::MultiFab > &  ,
const amrex::Vector< amrex::Real > &   
)
inlinevirtual

Function to update user-specified temperature source terms that can vary with time and height.

Parameters
[in]timecurrent time
[out]rhotheta_sourceforcing profile
[in]geomcontainer for geometric information
[in]z_phys_ccheight coordinate at cell centers
[in]zlevels_stagnominal heights of the z faces of this level
201  {
202  if (src->empty()) return;
203 
204  amrex::Warning("Temperature forcing not defined for "+name()+" problem");
205  for ( amrex::MFIter mfi(*src, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
206  {
207  const auto &box = mfi.tilebox();
208  const amrex::Array4<amrex::Real>& src_arr = src->array(mfi);
209  // src is a spatial function if erf.spatial_rhotheta_forcing = true
210  // otherwise, qsrc_arr is defined only in over Z (box x and y dimensions are 1)
211  ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
212  // const amrex::Real z_cc = prob_lo[2] + (k+myhalf)* dx[2];
213  // set RHS term of RhoTheta equation based on time, z_cc here
214  src_arr(i, j, k) = zero;
215  });
216  }
217  }
Here is the call graph for this function:

◆ update_w_subsidence()

virtual void ProblemBase::update_w_subsidence ( const double &  ,
amrex::Vector< amrex::Real > &  wbar,
amrex::Gpu::DeviceVector< amrex::Real > &  d_wbar,
const amrex::MultiFab &  ,
const amrex::Geometry &  geom,
std::unique_ptr< amrex::MultiFab > &  ,
const amrex::Vector< amrex::Real > &   
)
inlinevirtual

Function to update the vertical velocity profile, used to add subsidence source terms for x-mom, y-mom, rho*theta, rho*Q1, and rho*Q2.

TODO: Currently, this is only called by InitData, so there is no time dependence.

Parameters
[in]timecurrent time
[out]wbarw vel forcing profile
[in]geomcontainer for geometric information
[in]z_phys_ccheight coordinate at cell centers
[in]zlevels_stagnominal heights of the z faces of this level
274  {
275  if (wbar.empty()) return;
276 
277  amrex::Warning("Moisture forcing not defined for "+name()+" problem");
278 
279  const int khi = geom.Domain().bigEnd()[2];
280  // const amrex::Real* prob_lo = geom.ProbLo();
281  // const auto dx = geom.CellSize();
282  for (int k = 0; k <= khi; k++)
283  {
284  // const amrex::Real z_cc = prob_lo[2] + (k+myhalf)* dx[2];
285  // set vertical velocity profile based on time, z_cc here
286  wbar[k] = zero;
287  }
288 
289  // Copy from host version to device version
290  amrex::Gpu::copy(amrex::Gpu::hostToDevice, wbar.begin(), wbar.end(), d_wbar.begin());
291  }
@ wbar
Definition: ERF_DataStruct.H:194
Here is the call graph for this function:

Member Data Documentation

◆ base_parms

ProbParmDefaults ProblemBase::base_parms
protected

Referenced by init_base_parms().


The documentation for this class was generated from the following file: