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

#include <ERF.H>

Inheritance diagram for ERF:
Collaboration diagram for ERF:

Public Member Functions

 ERF ()
 
 ~ERF () override
 
 ERF (ERF &&) noexcept=delete
 
ERFoperator= (ERF &&other) noexcept=delete
 
 ERF (const ERF &other)=delete
 
ERFoperator= (const ERF &other)=delete
 
void Evolve ()
 
void ErrorEst (int lev, amrex::TagBoxArray &tags, amrex::Real time, int ngrow) override
 
void InitData ()
 
void init_only (int lev, amrex::Real time)
 
void restart ()
 
bool writeNow (const amrex::Real cur_time, const amrex::Real dt, const int nstep, const int plot_int, const amrex::Real plot_per)
 
void post_timestep (int nstep, amrex::Real time, amrex::Real dt_lev)
 
void sum_integrated_quantities (amrex::Real time)
 
void write_1D_profiles (amrex::Real time)
 
void write_1D_profiles_stag (amrex::Real time)
 
void FillBdyCCVels (amrex::Vector< amrex::MultiFab > &mf_cc_vel)
 
void sample_points (int lev, amrex::Real time, amrex::IntVect cell, amrex::MultiFab &mf)
 
void sample_lines (int lev, amrex::Real time, amrex::IntVect cell, amrex::MultiFab &mf)
 
void derive_diag_profiles (amrex::Gpu::HostVector< amrex::Real > &h_avg_u, amrex::Gpu::HostVector< amrex::Real > &h_avg_v, amrex::Gpu::HostVector< amrex::Real > &h_avg_w, amrex::Gpu::HostVector< amrex::Real > &h_avg_rho, amrex::Gpu::HostVector< amrex::Real > &h_avg_th, amrex::Gpu::HostVector< amrex::Real > &h_avg_ksgs, amrex::Gpu::HostVector< amrex::Real > &h_avg_qv, amrex::Gpu::HostVector< amrex::Real > &h_avg_qc, amrex::Gpu::HostVector< amrex::Real > &h_avg_qr, amrex::Gpu::HostVector< amrex::Real > &h_avg_wqv, amrex::Gpu::HostVector< amrex::Real > &h_avg_wqc, amrex::Gpu::HostVector< amrex::Real > &h_avg_wqr, amrex::Gpu::HostVector< amrex::Real > &h_avg_uu, amrex::Gpu::HostVector< amrex::Real > &h_avg_uv, amrex::Gpu::HostVector< amrex::Real > &h_avg_uw, amrex::Gpu::HostVector< amrex::Real > &h_avg_vv, amrex::Gpu::HostVector< amrex::Real > &h_avg_vw, amrex::Gpu::HostVector< amrex::Real > &h_avg_ww, amrex::Gpu::HostVector< amrex::Real > &h_avg_uth, amrex::Gpu::HostVector< amrex::Real > &h_avg_vth, amrex::Gpu::HostVector< amrex::Real > &h_avg_wth, amrex::Gpu::HostVector< amrex::Real > &h_avg_thth, amrex::Gpu::HostVector< amrex::Real > &h_avg_ku, amrex::Gpu::HostVector< amrex::Real > &h_avg_kv, amrex::Gpu::HostVector< amrex::Real > &h_avg_kw, amrex::Gpu::HostVector< amrex::Real > &h_avg_p, amrex::Gpu::HostVector< amrex::Real > &h_avg_pu, amrex::Gpu::HostVector< amrex::Real > &h_avg_pv, amrex::Gpu::HostVector< amrex::Real > &h_avg_pw)
 
void derive_diag_profiles_stag (amrex::Gpu::HostVector< amrex::Real > &h_avg_u, amrex::Gpu::HostVector< amrex::Real > &h_avg_v, amrex::Gpu::HostVector< amrex::Real > &h_avg_w, amrex::Gpu::HostVector< amrex::Real > &h_avg_rho, amrex::Gpu::HostVector< amrex::Real > &h_avg_th, amrex::Gpu::HostVector< amrex::Real > &h_avg_ksgs, amrex::Gpu::HostVector< amrex::Real > &h_avg_uu, amrex::Gpu::HostVector< amrex::Real > &h_avg_uv, amrex::Gpu::HostVector< amrex::Real > &h_avg_uw, amrex::Gpu::HostVector< amrex::Real > &h_avg_vv, amrex::Gpu::HostVector< amrex::Real > &h_avg_vw, amrex::Gpu::HostVector< amrex::Real > &h_avg_ww, amrex::Gpu::HostVector< amrex::Real > &h_avg_uth, amrex::Gpu::HostVector< amrex::Real > &h_avg_vth, amrex::Gpu::HostVector< amrex::Real > &h_avg_wth, amrex::Gpu::HostVector< amrex::Real > &h_avg_thth, amrex::Gpu::HostVector< amrex::Real > &h_avg_ku, amrex::Gpu::HostVector< amrex::Real > &h_avg_kv, amrex::Gpu::HostVector< amrex::Real > &h_avg_kw, amrex::Gpu::HostVector< amrex::Real > &h_avg_p, amrex::Gpu::HostVector< amrex::Real > &h_avg_pu, amrex::Gpu::HostVector< amrex::Real > &h_avg_pv, amrex::Gpu::HostVector< amrex::Real > &h_avg_pw)
 
void derive_stress_profiles (amrex::Gpu::HostVector< amrex::Real > &h_avg_tau11, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau12, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau13, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau22, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau23, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau33, amrex::Gpu::HostVector< amrex::Real > &h_avg_hfx3, amrex::Gpu::HostVector< amrex::Real > &h_avg_diss)
 
void derive_stress_profiles_stag (amrex::Gpu::HostVector< amrex::Real > &h_avg_tau11, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau12, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau13, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau22, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau23, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau33, amrex::Gpu::HostVector< amrex::Real > &h_avg_hfx3, amrex::Gpu::HostVector< amrex::Real > &h_avg_diss)
 
amrex::Real volWgtSumMF (int lev, const amrex::MultiFab &mf, int comp, const amrex::MultiFab &mapfac, bool local, bool finemask)
 
void MakeNewLevelFromCoarse (int lev, amrex::Real time, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm) override
 
void RemakeLevel (int lev, amrex::Real time, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm) override
 
void ClearLevel (int lev) override
 
void MakeNewLevelFromScratch (int lev, amrex::Real time, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm) override
 
amrex::Real estTimeStep (int lev, long &dt_fast_ratio) const
 
void advance_dycore (int level, amrex::Vector< amrex::MultiFab > &state_old, amrex::Vector< amrex::MultiFab > &state_new, amrex::MultiFab &xvel_old, amrex::MultiFab &yvel_old, amrex::MultiFab &zvel_old, amrex::MultiFab &xvel_new, amrex::MultiFab &yvel_new, amrex::MultiFab &zvel_new, amrex::MultiFab &source, amrex::MultiFab &xmom_src, amrex::MultiFab &ymom_src, amrex::MultiFab &zmom_src, amrex::Geometry fine_geom, amrex::Real dt, amrex::Real time)
 
void advance_microphysics (int lev, amrex::MultiFab &cons_in, const amrex::Real &dt_advance, const int &iteration, const amrex::Real &time)
 
void advance_lsm (int lev, amrex::MultiFab &, const amrex::Real &dt_advance)
 
amrex::MultiFab & build_fine_mask (int lev)
 
void MakeHorizontalAverages ()
 
void MakeDiagnosticAverage (amrex::Vector< amrex::Real > &h_havg, amrex::MultiFab &S, int n)
 
void derive_upwp (amrex::Vector< amrex::Real > &h_havg)
 
void WritePlotFile (int which, amrex::Vector< std::string > plot_var_names)
 
void WriteMultiLevelPlotfileWithTerrain (const std::string &plotfilename, int nlevels, const amrex::Vector< const amrex::MultiFab * > &mf, const amrex::Vector< const amrex::MultiFab * > &mf_nd, const amrex::Vector< std::string > &varnames, amrex::Real time, const amrex::Vector< int > &level_steps, const std::string &versionName="HyperCLaw-V1.1", const std::string &levelPrefix="Level_", const std::string &mfPrefix="Cell", const amrex::Vector< std::string > &extra_dirs=amrex::Vector< std::string >()) const
 
void WriteGenericPlotfileHeaderWithTerrain (std::ostream &HeaderFile, int nlevels, const amrex::Vector< amrex::BoxArray > &bArray, const amrex::Vector< std::string > &varnames, amrex::Real time, const amrex::Vector< int > &level_steps, const std::string &versionName, const std::string &levelPrefix, const std::string &mfPrefix) const
 
void erf_enforce_hse (int lev, amrex::MultiFab &dens, amrex::MultiFab &pres, amrex::MultiFab &pi, std::unique_ptr< amrex::MultiFab > &z_cc)
 
void init_from_input_sounding (int lev)
 
void input_sponge (int lev)
 
void init_from_hse (int lev)
 
void fill_from_bndryregs (const amrex::Vector< amrex::MultiFab * > &mfs, amrex::Real time)
 
void AverageDownTo (int crse_lev, int scomp, int ncomp)
 
void writeJobInfo (const std::string &dir) const
 

Static Public Member Functions

static bool is_it_time_for_action (int nstep, amrex::Real time, amrex::Real dt, int action_interval, amrex::Real action_per)
 
static void writeBuildInfo (std::ostream &os)
 
static void print_banner (MPI_Comm, std::ostream &)
 
static void print_usage (MPI_Comm, std::ostream &)
 
static void print_error (MPI_Comm, const std::string &msg)
 
static void print_summary (std::ostream &)
 
static void print_tpls (std::ostream &)
 

Public Attributes

std::string pp_prefix {"erf"}
 

Private Member Functions

void ReadParameters ()
 
void AverageDown ()
 
void update_diffusive_arrays (int lev, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm)
 
void update_terrain_arrays (int lev, amrex::Real time)
 
void Construct_ERFFillPatchers (int lev)
 
void Define_ERFFillPatchers (int lev)
 
void init1DArrays ()
 
void init_bcs ()
 
void init_custom (int lev)
 
void init_uniform (int lev)
 
void init_stuff (int lev, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm, amrex::Vector< amrex::MultiFab > &lev_new, amrex::Vector< amrex::MultiFab > &lev_old)
 
void initialize_integrator (int lev, amrex::MultiFab &cons_mf, amrex::MultiFab &vel_mf)
 
void initialize_bcs (int lev)
 
void initializeMicrophysics (const int &)
 
void FillPatch (int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, const amrex::Vector< amrex::MultiFab * > &mfs_mom, bool fillset=true, bool cons_only=false)
 
void FillPatchMoistVars (int lev, amrex::MultiFab &mf)
 
void FillIntermediatePatch (int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, const amrex::Vector< amrex::MultiFab * > &mfs_mom, int ng_cons, int ng_vel, bool cons_only, int icomp_cons, int ncomp_cons, bool allow_most_bcs=true)
 
void FillCoarsePatch (int lev, amrex::Real time)
 
void timeStep (int lev, amrex::Real time, int iteration)
 
void Advance (int lev, amrex::Real time, amrex::Real dt_lev, int iteration, int ncycle)
 
void initHSE ()
 Initialize HSE. More...
 
void initHSE (int lev)
 
void initRayleigh ()
 Initialize Rayleigh damping profiles. More...
 
void initSponge ()
 Initialize sponge profiles. More...
 
void setRayleighRefFromSounding (bool restarting)
 Set Rayleigh mean profiles from input sounding. More...
 
void setSpongeRefFromSounding (bool restarting)
 Set sponge mean profiles from input sounding. More...
 
void ComputeDt ()
 
std::string PlotFileName (int lev) const
 
void setPlotVariables (const std::string &pp_plot_var_names, amrex::Vector< std::string > &plot_var_names)
 
void appendPlotVariables (const std::string &pp_plot_var_names, amrex::Vector< std::string > &plot_var_names)
 
void WriteCheckpointFile () const
 
void ReadCheckpointFile ()
 
void InitializeFromFile ()
 
void InitializeLevelFromData (int lev, const amrex::MultiFab &initial_data)
 
void post_update (amrex::MultiFab &state_mf, amrex::Real time, const amrex::Geometry &geom)
 
void fill_rhs (amrex::MultiFab &rhs_mf, const amrex::MultiFab &state_mf, amrex::Real time, const amrex::Geometry &geom)
 
void refinement_criteria_setup ()
 
AMREX_FORCE_INLINE amrex::YAFluxRegister * getAdvFluxReg (int lev)
 
AMREX_FORCE_INLINE std::ostream & DataLog (int i)
 
AMREX_FORCE_INLINE int NumDataLogs () noexcept
 
AMREX_FORCE_INLINE std::ostream & SamplePointLog (int i)
 
AMREX_FORCE_INLINE int NumSamplePointLogs () noexcept
 
AMREX_FORCE_INLINE std::ostream & SampleLineLog (int i)
 
AMREX_FORCE_INLINE int NumSampleLineLogs () noexcept
 
amrex::IntVect & SamplePoint (int i)
 
AMREX_FORCE_INLINE int NumSamplePoints () noexcept
 
amrex::IntVect & SampleLine (int i)
 
AMREX_FORCE_INLINE int NumSampleLines () noexcept
 
void setRecordDataInfo (int i, const std::string &filename)
 
void setRecordSamplePointInfo (int i, int lev, amrex::IntVect &cell, const std::string &filename)
 
void setRecordSampleLineInfo (int i, int lev, amrex::IntVect &cell, const std::string &filename)
 
std::string DataLogName (int i) const noexcept
 The filename of the ith datalog file. More...
 
std::string SamplePointLogName (int i) const noexcept
 The filename of the ith sampleptlog file. More...
 
std::string SampleLineLogName (int i) const noexcept
 The filename of the ith samplelinelog file. More...
 
amrex::FabFactory< amrex::FArrayBox > const & Factory (int lev) const noexcept
 

Static Private Member Functions

static amrex::Vector< std::string > PlotFileVarNames (amrex::Vector< std::string > plot_var_names)
 
static void GotoNextLine (std::istream &is)
 
static AMREX_FORCE_INLINE int ComputeGhostCells (const AdvChoice &advChoice, bool use_num_diff)
 
static amrex::Real getCPUTime ()
 

Private Attributes

InputSoundingData input_sounding_data
 
InputSpongeData input_sponge_data
 
amrex::Vector< int > min_k_at_level
 
amrex::Vector< int > max_k_at_level
 
std::unique_ptr< ProblemBaseprob = nullptr
 
amrex::Vector< int > num_boxes_at_level
 
amrex::Vector< int > num_files_at_level
 
amrex::Vector< amrex::Vector< amrex::Box > > boxes_at_level
 
amrex::Vector< int > istep
 
amrex::Vector< int > nsubsteps
 
amrex::Vector< amrex::Real > t_new
 
amrex::Vector< amrex::Real > t_old
 
amrex::Vector< amrex::Real > dt
 
amrex::Vector< long > dt_mri_ratio
 
amrex::Vector< amrex::Vector< amrex::MultiFab > > vars_new
 
amrex::Vector< amrex::Vector< amrex::MultiFab > > vars_old
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vel_t_avg
 
amrex::Vector< amrex::Real > t_avg_cnt
 
amrex::Vector< std::unique_ptr< MRISplitIntegrator< amrex::Vector< amrex::MultiFab > > > > mri_integrator_mem
 
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_cons > > physbcs_cons
 
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_u > > physbcs_u
 
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_v > > physbcs_v
 
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_w > > physbcs_w
 
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_w_no_terrain > > physbcs_w_no_terrain
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Theta_prim
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Qv_prim
 
amrex::Vector< amrex::MultiFab > rU_old
 
amrex::Vector< amrex::MultiFab > rU_new
 
amrex::Vector< amrex::MultiFab > rV_old
 
amrex::Vector< amrex::MultiFab > rV_new
 
amrex::Vector< amrex::MultiFab > rW_old
 
amrex::Vector< amrex::MultiFab > rW_new
 
std::unique_ptr< Microphysicsmicro
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > qmoist
 
amrex::Vector< amrex::MultiFab > Nturb
 
amrex::Vector< amrex::MultiFab > vars_fitch
 
amrex::Vector< amrex::MultiFab > vars_ewp
 
amrex::Real hub_height
 
amrex::Real rotor_dia
 
amrex::Real thrust_coeff_standing
 
amrex::Real nominal_power
 
amrex::Vector< amrex::Real > wind_speed
 
amrex::Vector< amrex::Real > thrust_coeff
 
amrex::Vector< amrex::Real > power
 
LandSurface lsm
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > lsm_data
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > lsm_flux
 
int cf_width {0}
 
int cf_set_width {0}
 
amrex::Vector< ERFFillPatcherFPr_c
 
amrex::Vector< ERFFillPatcherFPr_u
 
amrex::Vector< ERFFillPatcherFPr_v
 
amrex::Vector< ERFFillPatcherFPr_w
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau11_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau22_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau33_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau12_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau21_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau13_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau31_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau23_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau32_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > eddyDiffs_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SmnSmn_lev
 
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > sst_lev
 
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::iMultiFab > > > lmask_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx1_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx2_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx3_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_diss_lev
 
amrex::Vector< amrex::Real > zlevels_stag
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_cc
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd_src
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc_src
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax_src
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay_src
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az_src
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd_new
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc_new
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax_new
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay_new
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az_new
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_t_rk
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_m
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_u
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_v
 
amrex::Vector< amrex::MultiFab > base_state
 
amrex::Vector< amrex::MultiFab > base_state_new
 
amrex::Vector< amrex::YAFluxRegister * > advflux_reg
 
amrex::Vector< amrex::BCRec > domain_bcs_type
 
amrex::Gpu::DeviceVector< amrex::BCRec > domain_bcs_type_d
 
amrex::Array< std::string, 2 *AMREX_SPACEDIM > domain_bc_type
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NVAR_maxm_bc_extdir_vals
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NVAR_maxm_bc_neumann_vals
 
amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > phys_bc_type
 
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > xflux_imask
 
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > yflux_imask
 
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > zflux_imask
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_xforce
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_yforce
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_zforce
 
int last_plot_file_step_1
 
int last_plot_file_step_2
 
int last_check_file_step
 
int plot_file_on_restart = 1
 
int max_step = std::numeric_limits<int>::max()
 
amrex::Real start_time = 0.0
 
amrex::Real stop_time = std::numeric_limits<amrex::Real>::max()
 
std::string restart_chkfile = ""
 
int regrid_int = -1
 
std::string plot_file_1 {"plt_1_"}
 
std::string plot_file_2 {"plt_2_"}
 
int m_plot_int_1 = -1
 
int m_plot_int_2 = -1
 
amrex::Real m_plot_per_1 = -1.0
 
amrex::Real m_plot_per_2 = -1.0
 
bool plot_lsm = false
 
int profile_int = -1
 
bool cc_profiles = true
 
std::string check_file {"chk"}
 
std::string check_type {"native"}
 
std::string restart_type {"native"}
 
int m_check_int = -1
 
amrex::Real m_check_per = -1.0
 
amrex::Vector< std::string > plot_var_names_1
 
amrex::Vector< std::string > plot_var_names_2
 
const amrex::Vector< std::string > cons_names
 
const amrex::Vector< std::string > derived_names
 
int real_width {0}
 
int real_set_width {0}
 
amrex::Vector< amrex::Vector< amrex::Real > > h_rhotheta_src
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_rhotheta_src
 
amrex::Vector< amrex::Vector< amrex::Real > > h_rhoqt_src
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_rhoqt_src
 
amrex::Vector< amrex::Vector< amrex::Real > > h_w_subsid
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_w_subsid
 
amrex::Vector< amrex::Vector< amrex::Real > > h_u_geos
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_u_geos
 
amrex::Vector< amrex::Vector< amrex::Real > > h_v_geos
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_v_geos
 
amrex::Vector< amrex::Vector< amrex::Vector< amrex::Real > > > h_rayleigh_ptrs
 
amrex::Vector< amrex::Vector< amrex::Vector< amrex::Real > > > h_sponge_ptrs
 
amrex::Vector< amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > > d_rayleigh_ptrs
 
amrex::Vector< amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > > d_sponge_ptrs
 
amrex::Vector< amrex::Real > h_havg_density
 
amrex::Vector< amrex::Real > h_havg_temperature
 
amrex::Vector< amrex::Real > h_havg_pressure
 
amrex::Vector< amrex::Real > h_havg_qv
 
amrex::Vector< amrex::Real > h_havg_qc
 
amrex::Gpu::DeviceVector< amrex::Real > d_havg_density
 
amrex::Gpu::DeviceVector< amrex::Real > d_havg_temperature
 
amrex::Gpu::DeviceVector< amrex::Real > d_havg_pressure
 
amrex::Gpu::DeviceVector< amrex::Real > d_havg_qv
 
amrex::Gpu::DeviceVector< amrex::Real > d_havg_qc
 
std::unique_ptr< WriteBndryPlanesm_w2d = nullptr
 
std::unique_ptr< ReadBndryPlanesm_r2d = nullptr
 
std::unique_ptr< ABLMostm_most = nullptr
 
amrex::MultiFab fine_mask
 
amrex::Real dz_min
 
amrex::Vector< std::unique_ptr< std::fstream > > datalog
 
amrex::Vector< std::string > datalogname
 
amrex::Vector< std::unique_ptr< std::fstream > > sampleptlog
 
amrex::Vector< std::string > sampleptlogname
 
amrex::Vector< amrex::IntVect > samplepoint
 
amrex::Vector< std::unique_ptr< std::fstream > > samplelinelog
 
amrex::Vector< std::string > samplelinelogname
 
amrex::Vector< amrex::IntVect > sampleline
 
amrex::Vector< std::unique_ptr< amrex::FabFactory< amrex::FArrayBox > > > m_factory
 

Static Private Attributes

static amrex::Real cfl = 0.8
 
static amrex::Real init_shrink = 1.0
 
static amrex::Real change_max = 1.1
 
static amrex::Real fixed_dt = -1.0
 
static amrex::Real fixed_fast_dt = -1.0
 
static int fixed_mri_dt_ratio = 0
 
static SolverChoice solverChoice
 
static int verbose = 0
 
static int sum_interval = -1
 
static amrex::Real sum_per = -1.0
 
static std::string plotfile_type = "amrex"
 
static std::string init_type
 
static std::string sponge_type
 
static bool use_real_bcs
 
static amrex::Vector< amrex::Vector< std::string > > nc_init_file = {{""}}
 
static std::string nc_bdy_file
 
static std::string input_sounding_file = "input_sounding"
 
static std::string input_sponge_file = "input_sponge_file.txt"
 
static bool init_sounding_ideal = false
 
static int output_1d_column = 0
 
static int column_interval = -1
 
static amrex::Real column_per = -1.0
 
static amrex::Real column_loc_x = 0.0
 
static amrex::Real column_loc_y = 0.0
 
static std::string column_file_name = "column_data.nc"
 
static int output_bndry_planes = 0
 
static int bndry_output_planes_interval = -1
 
static amrex::Real bndry_output_planes_per = -1.0
 
static amrex::Real bndry_output_planes_start_time = 0.0
 
static int input_bndry_planes = 0
 
static int ng_dens_hse
 
static int ng_pres_hse
 
static amrex::Vector< amrex::AMRErrorTag > ref_tags
 
static amrex::Real startCPUTime = 0.0
 
static amrex::Real previousCPUTimeUsed = 0.0
 

Detailed Description

Main class in ERF code, instantiated from main.cpp

Constructor & Destructor Documentation

◆ ERF() [1/3]

ERF::ERF ( )
94 {
95  if (ParallelDescriptor::IOProcessor()) {
96  const char* erf_hash = buildInfoGetGitHash(1);
97  const char* amrex_hash = buildInfoGetGitHash(2);
98  const char* buildgithash = buildInfoGetBuildGitHash();
99  const char* buildgitname = buildInfoGetBuildGitName();
100 
101  if (strlen(erf_hash) > 0) {
102  Print() << "\n"
103  << "ERF git hash: " << erf_hash << "\n";
104  }
105  if (strlen(amrex_hash) > 0) {
106  Print() << "AMReX git hash: " << amrex_hash << "\n";
107  }
108  if (strlen(buildgithash) > 0) {
109  Print() << buildgitname << " git hash: " << buildgithash << "\n";
110  }
111 
112  Print() << "\n";
113  }
114 
115  int nlevs_max = max_level + 1;
116 
117 #ifdef ERF_USE_WINDFARM
118  Nturb.resize(nlevs_max);
119  vars_fitch.resize(nlevs_max);
120  vars_ewp.resize(nlevs_max);
121 #endif
122 
123 #if defined(ERF_USE_RRTMGP)
124  qheating_rates.resize(nlevs_max);
125 #endif
126 
127  // NOTE: size lsm before readparams (chooses the model at all levels)
128  lsm.ReSize(nlevs_max);
129  lsm_data.resize(nlevs_max);
130  lsm_flux.resize(nlevs_max);
131 
132  ReadParameters();
133  initializeMicrophysics(nlevs_max);
134 
135  const std::string& pv1 = "plot_vars_1"; setPlotVariables(pv1,plot_var_names_1);
136  const std::string& pv2 = "plot_vars_2"; setPlotVariables(pv2,plot_var_names_2);
137 
138  // Initialize staggered vertical levels for grid stretching or terrain.
139 
142  geom[0],
145  solverChoice.dz0);
146 
147  int nz = geom[0].Domain().length(2) + 1; // staggered
148  if (std::fabs(zlevels_stag[nz-1]-geom[0].ProbHi(2)) > 1.0e-4) {
149  Print() << "WARNING: prob_hi[2]=" << geom[0].ProbHi(2)
150  << " does not match highest requested z level " << zlevels_stag[nz-1]
151  << std::endl;
152  }
153  if (std::fabs(zlevels_stag[0]-geom[0].ProbLo(2)) > 1.0e-4) {
154  Print() << "WARNING: prob_lo[2]=" << geom[0].ProbLo(2)
155  << " does not match lowest requested level " << zlevels_stag[0]
156  << std::endl;
157  }
158 
159  // Redefine the problem domain here?
160  }
161 
162  prob = amrex_probinit(geom[0].ProbLo(),geom[0].ProbHi());
163 
164  // Geometry on all levels has been defined already.
165 
166  // No valid BoxArray and DistributionMapping have been defined.
167  // But the arrays for them have been resized.
168 
169  istep.resize(nlevs_max, 0);
170  nsubsteps.resize(nlevs_max, 1);
171  for (int lev = 1; lev <= max_level; ++lev) {
172  nsubsteps[lev] = MaxRefRatio(lev-1);
173  }
174 
175  t_new.resize(nlevs_max, 0.0);
176  t_old.resize(nlevs_max, -1.e100);
177  dt.resize(nlevs_max, 1.e100);
178  dt_mri_ratio.resize(nlevs_max, 1);
179 
180  vars_new.resize(nlevs_max);
181  vars_old.resize(nlevs_max);
182 
183  rU_new.resize(nlevs_max);
184  rV_new.resize(nlevs_max);
185  rW_new.resize(nlevs_max);
186 
187  rU_old.resize(nlevs_max);
188  rV_old.resize(nlevs_max);
189  rW_old.resize(nlevs_max);
190 
191  for (int lev = 0; lev < nlevs_max; ++lev) {
192  vars_new[lev].resize(Vars::NumTypes);
193  vars_old[lev].resize(Vars::NumTypes);
194  }
195 
196  // Time integrator
197  mri_integrator_mem.resize(nlevs_max);
198 
199  // Physical boundary conditions
200  physbcs_cons.resize(nlevs_max);
201  physbcs_u.resize(nlevs_max);
202  physbcs_v.resize(nlevs_max);
203  physbcs_w.resize(nlevs_max);
204  physbcs_w_no_terrain.resize(nlevs_max);
205 
206  advflux_reg.resize(nlevs_max);
207 
208  // Stresses
209  Tau11_lev.resize(nlevs_max); Tau22_lev.resize(nlevs_max); Tau33_lev.resize(nlevs_max);
210  Tau12_lev.resize(nlevs_max); Tau21_lev.resize(nlevs_max);
211  Tau13_lev.resize(nlevs_max); Tau31_lev.resize(nlevs_max);
212  Tau23_lev.resize(nlevs_max); Tau32_lev.resize(nlevs_max);
213  SFS_hfx1_lev.resize(nlevs_max); SFS_hfx2_lev.resize(nlevs_max); SFS_hfx3_lev.resize(nlevs_max);
214  SFS_diss_lev.resize(nlevs_max);
215  eddyDiffs_lev.resize(nlevs_max);
216  SmnSmn_lev.resize(nlevs_max);
217 
218  // Sea surface temps
219  sst_lev.resize(nlevs_max);
220  lmask_lev.resize(nlevs_max);
221 
222  // Metric terms
223  z_phys_nd.resize(nlevs_max);
224  z_phys_cc.resize(nlevs_max);
225  detJ_cc.resize(nlevs_max);
226  ax.resize(nlevs_max);
227  ay.resize(nlevs_max);
228  az.resize(nlevs_max);
229 
230  z_phys_nd_new.resize(nlevs_max);
231  detJ_cc_new.resize(nlevs_max);
232  ax_new.resize(nlevs_max);
233  ay_new.resize(nlevs_max);
234  az_new.resize(nlevs_max);
235 
236  z_phys_nd_src.resize(nlevs_max);
237  detJ_cc_src.resize(nlevs_max);
238  ax_src.resize(nlevs_max);
239  ay_src.resize(nlevs_max);
240  az_src.resize(nlevs_max);
241 
242  z_t_rk.resize(nlevs_max);
243 
244  // Mapfactors
245  mapfac_m.resize(nlevs_max);
246  mapfac_u.resize(nlevs_max);
247  mapfac_v.resize(nlevs_max);
248 
249  // Thin immersed body
250  xflux_imask.resize(nlevs_max);
251  yflux_imask.resize(nlevs_max);
252  zflux_imask.resize(nlevs_max);
253  //overset_imask.resize(nlevs_max);
254  thin_xforce.resize(nlevs_max);
255  thin_yforce.resize(nlevs_max);
256  thin_zforce.resize(nlevs_max);
257 
258  // Base state
259  base_state.resize(nlevs_max);
260  base_state_new.resize(nlevs_max);
261 
262  // Theta prim for MOST
263  Theta_prim.resize(nlevs_max);
264 
265  // Qv prim for MOST
266  Qv_prim.resize(nlevs_max);
267 
268  // Time averaged velocity field
269  vel_t_avg.resize(nlevs_max);
270  t_avg_cnt.resize(nlevs_max);
271 
272 #ifdef ERF_USE_NETCDF
273  // Size lat long arrays if using netcdf
274  lat_m.resize(nlevs_max);
275  lon_m.resize(nlevs_max);
276 #endif
277 
278  // Initialize tagging criteria for mesh refinement
280 
281  // We have already read in the ref_Ratio (via amr.ref_ratio =) but we need to enforce
282  // that there is no refinement in the vertical so we test on that here.
283  for (int lev = 0; lev < max_level; ++lev)
284  {
285  Print() << "Refinement ratio at level " << lev+1 << " set to be " <<
286  ref_ratio[lev][0] << " " << ref_ratio[lev][1] << " " << ref_ratio[lev][2] << std::endl;
287 
288  if (ref_ratio[lev][2] != 1)
289  {
290  Error("We don't allow refinement in the vertical -- make sure to set ref_ratio = 1 in z");
291  }
292  }
293 
294  // We define m_factory even with no EB
295  m_factory.resize(max_level+1);
296 
297 #ifdef AMREX_USE_EB
298  // We will create each of these in MakeNewLevel.../RemakeLevel
299 
300  // This is needed before initializing level MultiFabs
301  MakeEBGeometry();
302 #endif
303 }
void init_zlevels(Vector< Real > &zlevels_stag, const Geometry &geom, const Real grid_stretching_ratio, const Real zsurf, const Real dz0)
Definition: TerrainMetrics.cpp:9
amrex::Vector< amrex::MultiFab > vars_ewp
Definition: ERF.H:631
amrex::Vector< amrex::MultiFab > rU_new
Definition: ERF.H:619
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau23_lev
Definition: ERF.H:657
amrex::Vector< std::unique_ptr< MRISplitIntegrator< amrex::Vector< amrex::MultiFab > > > > mri_integrator_mem
Definition: ERF.H:604
amrex::Vector< amrex::Vector< amrex::MultiFab > > vars_new
Definition: ERF.H:597
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_yforce
Definition: ERF.H:729
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx3_lev
Definition: ERF.H:666
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_u
Definition: ERF.H:694
void setPlotVariables(const std::string &pp_plot_var_names, amrex::Vector< std::string > &plot_var_names)
Definition: Plotfile.cpp:18
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau31_lev
Definition: ERF.H:656
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_m
Definition: ERF.H:693
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx1_lev
Definition: ERF.H:666
void ReadParameters()
Definition: ERF.cpp:1190
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_cons > > physbcs_cons
Definition: ERF.H:607
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay_new
Definition: ERF.H:688
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd_src
Definition: ERF.H:679
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc
Definition: ERF.H:674
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_cc
Definition: ERF.H:672
amrex::Vector< std::unique_ptr< amrex::MultiFab > > eddyDiffs_lev
Definition: ERF.H:658
static SolverChoice solverChoice
Definition: ERF.H:813
amrex::Vector< amrex::MultiFab > base_state_new
Definition: ERF.H:698
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az
Definition: ERF.H:677
amrex::Vector< long > dt_mri_ratio
Definition: ERF.H:592
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vel_t_avg
Definition: ERF.H:601
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::iMultiFab > > > lmask_lev
Definition: ERF.H:663
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_w > > physbcs_w
Definition: ERF.H:610
amrex::Vector< amrex::MultiFab > vars_fitch
Definition: ERF.H:630
amrex::Vector< amrex::MultiFab > base_state
Definition: ERF.H:697
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_w_no_terrain > > physbcs_w_no_terrain
Definition: ERF.H:611
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd_new
Definition: ERF.H:685
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Qv_prim
Definition: ERF.H:615
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau13_lev
Definition: ERF.H:656
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau21_lev
Definition: ERF.H:655
amrex::Vector< amrex::MultiFab > rV_new
Definition: ERF.H:621
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_zforce
Definition: ERF.H:730
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > sst_lev
Definition: ERF.H:662
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_xforce
Definition: ERF.H:728
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau33_lev
Definition: ERF.H:654
std::unique_ptr< ProblemBase > prob
Definition: ERF.H:579
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_u > > physbcs_u
Definition: ERF.H:608
amrex::Vector< amrex::Real > t_new
Definition: ERF.H:589
amrex::Vector< amrex::Real > t_avg_cnt
Definition: ERF.H:602
amrex::Vector< std::string > plot_var_names_1
Definition: ERF.H:784
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_diss_lev
Definition: ERF.H:667
amrex::Vector< amrex::MultiFab > rU_old
Definition: ERF.H:618
amrex::Vector< amrex::Real > t_old
Definition: ERF.H:590
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Theta_prim
Definition: ERF.H:614
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_t_rk
Definition: ERF.H:691
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_v > > physbcs_v
Definition: ERF.H:609
amrex::Vector< std::string > plot_var_names_2
Definition: ERF.H:785
amrex::Vector< amrex::Real > zlevels_stag
Definition: ERF.H:670
amrex::Vector< amrex::YAFluxRegister * > advflux_reg
Definition: ERF.H:701
amrex::Vector< amrex::MultiFab > Nturb
Definition: ERF.H:629
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax
Definition: ERF.H:675
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd
Definition: ERF.H:671
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc_src
Definition: ERF.H:680
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SmnSmn_lev
Definition: ERF.H:659
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay_src
Definition: ERF.H:682
amrex::Vector< int > nsubsteps
Definition: ERF.H:586
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > yflux_imask
Definition: ERF.H:723
amrex::Vector< amrex::MultiFab > rW_new
Definition: ERF.H:623
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az_new
Definition: ERF.H:689
amrex::Vector< amrex::Vector< amrex::MultiFab * > > lsm_flux
Definition: ERF.H:638
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau32_lev
Definition: ERF.H:657
void refinement_criteria_setup()
Definition: ERF_Tagging.cpp:107
amrex::Vector< std::unique_ptr< amrex::FabFactory< amrex::FArrayBox > > > m_factory
Definition: ERF.H:1151
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax_src
Definition: ERF.H:681
amrex::Vector< amrex::MultiFab > rW_old
Definition: ERF.H:622
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx2_lev
Definition: ERF.H:666
amrex::Vector< amrex::Vector< amrex::MultiFab * > > lsm_data
Definition: ERF.H:637
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az_src
Definition: ERF.H:683
amrex::Vector< amrex::Real > dt
Definition: ERF.H:591
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau12_lev
Definition: ERF.H:655
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > zflux_imask
Definition: ERF.H:724
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay
Definition: ERF.H:676
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax_new
Definition: ERF.H:687
LandSurface lsm
Definition: ERF.H:636
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc_new
Definition: ERF.H:686
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_v
Definition: ERF.H:695
amrex::Vector< amrex::MultiFab > rV_old
Definition: ERF.H:620
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau11_lev
Definition: ERF.H:654
amrex::Vector< int > istep
Definition: ERF.H:585
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > xflux_imask
Definition: ERF.H:722
amrex::Vector< amrex::Vector< amrex::MultiFab > > vars_old
Definition: ERF.H:598
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau22_lev
Definition: ERF.H:654
void initializeMicrophysics(const int &)
Definition: ERF.cpp:1051
void ReSize(const int &nlev)
Definition: LandSurface.H:19
@ NumTypes
Definition: IndexDefines.H:103
const char * buildInfoGetGitHash(int i)
std::unique_ptr< ProblemBase > amrex_probinit(const amrex_real *problo, const amrex_real *probhi)
bool use_terrain
Definition: DataStruct.H:395
amrex::Real dz0
Definition: DataStruct.H:418
amrex::Real grid_stretching_ratio
Definition: DataStruct.H:416
amrex::Real zsurf
Definition: DataStruct.H:417
Here is the call graph for this function:

◆ ~ERF()

ERF::~ERF ( )
overridedefault

◆ ERF() [2/3]

ERF::ERF ( ERF &&  )
deletenoexcept

◆ ERF() [3/3]

ERF::ERF ( const ERF other)
delete

Member Function Documentation

◆ Advance()

void ERF::Advance ( int  lev,
amrex::Real  time,
amrex::Real  dt_lev,
int  iteration,
int  ncycle 
)
private

Function that advances the solution at one level for a single time step – this does some preliminaries then calls erf_advance

Parameters
[in]levlevel of refinement (coarsest level is 0)
[in]timestart time for time advance
[in]dt_levtime step for this time advance
22 {
23  BL_PROFILE("ERF::Advance()");
24 
25  // We must swap the pointers so the previous step's "new" is now this step's "old"
26  std::swap(vars_old[lev], vars_new[lev]);
27 
28  MultiFab& S_old = vars_old[lev][Vars::cons];
29  MultiFab& S_new = vars_new[lev][Vars::cons];
30 
31  MultiFab& U_old = vars_old[lev][Vars::xvel];
32  MultiFab& V_old = vars_old[lev][Vars::yvel];
33  MultiFab& W_old = vars_old[lev][Vars::zvel];
34 
35  MultiFab& U_new = vars_new[lev][Vars::xvel];
36  MultiFab& V_new = vars_new[lev][Vars::yvel];
37  MultiFab& W_new = vars_new[lev][Vars::zvel];
38 
39 
40  // configure ABLMost params if used MostWall boundary condition
41  if (phys_bc_type[Orientation(Direction::z,Orientation::low)] == ERF_BC::MOST) {
42  if (m_most) {
43  IntVect ng = Theta_prim[lev]->nGrowVect();
44  MultiFab::Copy( *Theta_prim[lev], S_old, RhoTheta_comp, 0, 1, ng);
45  MultiFab::Divide(*Theta_prim[lev], S_old, Rho_comp , 0, 1, ng);
47  ng = Qv_prim[lev]->nGrowVect();
48  MultiFab::Copy( *Qv_prim[lev], S_old, RhoQ1_comp, 0, 1, ng);
49  MultiFab::Divide(*Qv_prim[lev], S_old, Rho_comp , 0, 1, ng);
50  }
51  // NOTE: std::swap above causes the field ptrs to be out of date.
52  // Reassign the field ptrs for MAC avg computation.
53  m_most->update_mac_ptrs(lev, vars_old, Theta_prim, Qv_prim);
54  m_most->update_fluxes(lev, time);
55  }
56  }
57 
58  // We need to set these because otherwise in the first call to erf_advance we may
59  // read uninitialized data on ghost values in setting the bc's on the velocities
60  U_new.setVal(1.e34,U_new.nGrowVect());
61  V_new.setVal(1.e34,V_new.nGrowVect());
62  W_new.setVal(1.e34,W_new.nGrowVect());
63 
64  FillPatch(lev, time, {&S_old, &U_old, &V_old, &W_old},
65  {&S_old, &rU_old[lev], &rV_old[lev], &rW_old[lev]});
66 
68  // TODO: This is only qv
69  if (qmoist[lev].size() > 0) FillPatchMoistVars(lev, *(qmoist[lev][0]));
70  }
71 
72 #if defined(ERF_USE_WINDFARM)
73  // Update with the Fitch source terms
75  fitch_advance(lev, Geom(lev), dt_lev, S_old,
76  U_old, V_old, W_old, vars_fitch[lev], Nturb[lev]);
77  }
79  ewp_advance(lev, Geom(lev), dt_lev, S_old,
80  U_old, V_old, W_old, vars_ewp[lev], Nturb[lev]);
81  }
82 
83 #endif
84 
85  const BoxArray& ba = S_old.boxArray();
86  const DistributionMapping& dm = S_old.DistributionMap();
87 
88  int nvars = S_old.nComp();
89 
90  // Source array for conserved cell-centered quantities -- this will be filled
91  // in the call to make_sources in TI_slow_rhs_fun.H
92  MultiFab cc_source(ba,dm,nvars,1); cc_source.setVal(0.0);
93 
94  // Source arrays for momenta -- these will be filled
95  // in the call to make_mom_sources in TI_slow_rhs_fun.H
96  MultiFab xmom_source(ba,dm,nvars,1); xmom_source.setVal(0.0);
97  MultiFab ymom_source(ba,dm,nvars,1); ymom_source.setVal(0.0);
98  MultiFab zmom_source(ba,dm,nvars,1); zmom_source.setVal(0.0);
99 
100  // We don't need to call FillPatch on cons_mf because we have fillpatch'ed S_old above
101  MultiFab cons_mf(ba,dm,nvars,S_old.nGrowVect());
102  MultiFab::Copy(cons_mf,S_old,0,0,S_old.nComp(),S_old.nGrowVect());
103 
104  amrex::Vector<MultiFab> state_old;
105  amrex::Vector<MultiFab> state_new;
106 
107  // **************************************************************************************
108  // Here we define state_old and state_new which are to be advanced
109  // **************************************************************************************
110  // Initial solution
111  // Note that "old" and "new" here are relative to each RK stage.
112  state_old.push_back(MultiFab(cons_mf , amrex::make_alias, 0, nvars)); // cons
113  state_old.push_back(MultiFab(rU_old[lev], amrex::make_alias, 0, 1)); // xmom
114  state_old.push_back(MultiFab(rV_old[lev], amrex::make_alias, 0, 1)); // ymom
115  state_old.push_back(MultiFab(rW_old[lev], amrex::make_alias, 0, 1)); // zmom
116 
117  // Final solution
118  // state_new at the end of the last RK stage holds the t^{n+1} data
119  state_new.push_back(MultiFab(S_new , amrex::make_alias, 0, nvars)); // cons
120  state_new.push_back(MultiFab(rU_new[lev], amrex::make_alias, 0, 1)); // xmom
121  state_new.push_back(MultiFab(rV_new[lev], amrex::make_alias, 0, 1)); // ymom
122  state_new.push_back(MultiFab(rW_new[lev], amrex::make_alias, 0, 1)); // zmom
123 
124  // **************************************************************************************
125  // Update the dycore
126  // **************************************************************************************
127  advance_dycore(lev, state_old, state_new,
128  U_old, V_old, W_old,
129  U_new, V_new, W_new,
130  cc_source, xmom_source, ymom_source, zmom_source,
131  Geom(lev), dt_lev, time);
132 
133  // **************************************************************************************
134  // Update the microphysics (moisture)
135  // **************************************************************************************
136  advance_microphysics(lev, S_new, dt_lev, iteration, time);
137 
138  // **************************************************************************************
139  // Update the land surface model
140  // **************************************************************************************
141  advance_lsm(lev, S_new, dt_lev);
142 
143 #if defined(ERF_USE_RRTMGP)
144  // **************************************************************************************
145  // Update the radiation
146  // **************************************************************************************
147  advance_radiation(lev, S_new, dt_lev);
148 #endif
149 
150 #ifdef ERF_USE_PARTICLES
151  // **************************************************************************************
152  // Update the particle positions
153  // **************************************************************************************
154  evolveTracers( lev, dt_lev, vars_new, z_phys_nd );
155 #endif
156 
157  // **************************************************************************************
158  // Register old and new coarse data if we are at a level less than the finest level
159  // **************************************************************************************
160  if (lev < finest_level)
161  {
162  if (cf_width > 0) {
163  // We must fill the ghost cells of these so that the parallel copy works correctly
164  state_old[IntVars::cons].FillBoundary(geom[lev].periodicity());
165  state_new[IntVars::cons].FillBoundary(geom[lev].periodicity());
166  FPr_c[lev].RegisterCoarseData({&state_old[IntVars::cons], &state_new[IntVars::cons]},
167  {time, time + dt_lev});
168  }
169 
170  if (cf_width >= 0) {
171  // We must fill the ghost cells of these so that the parallel copy works correctly
172  state_old[IntVars::xmom].FillBoundary(geom[lev].periodicity());
173  state_new[IntVars::xmom].FillBoundary(geom[lev].periodicity());
174  FPr_u[lev].RegisterCoarseData({&state_old[IntVars::xmom], &state_new[IntVars::xmom]},
175  {time, time + dt_lev});
176 
177  state_old[IntVars::ymom].FillBoundary(geom[lev].periodicity());
178  state_new[IntVars::ymom].FillBoundary(geom[lev].periodicity());
179  FPr_v[lev].RegisterCoarseData({&state_old[IntVars::ymom], &state_new[IntVars::ymom]},
180  {time, time + dt_lev});
181 
182  state_old[IntVars::zmom].FillBoundary(geom[lev].periodicity());
183  state_new[IntVars::zmom].FillBoundary(geom[lev].periodicity());
184  FPr_w[lev].RegisterCoarseData({&state_old[IntVars::zmom], &state_new[IntVars::zmom]},
185  {time, time + dt_lev});
186  }
187  }
188 
189  // ***********************************************************************************************
190  // Update the time averaged velocities if they are requested
191  // ***********************************************************************************************
193  Time_Avg_Vel_atCC(dt[lev], t_avg_cnt[lev], vel_t_avg[lev].get(), U_new, V_new, W_new);
194  }
195 }
void ewp_advance(int lev, const Geometry &geom, const Real &dt_advance, MultiFab &cons_in, MultiFab &U_old, MultiFab &V_old, MultiFab &W_old, MultiFab &mf_vars_ewp, const amrex::MultiFab &mf_Nturb)
Definition: AdvanceEWP.cpp:9
void fitch_advance(int lev, const Geometry &geom, const Real &dt_advance, MultiFab &cons_in, MultiFab &U_old, MultiFab &V_old, MultiFab &W_old, MultiFab &mf_vars_fitch, const amrex::MultiFab &mf_Nturb)
Definition: AdvanceFitch.cpp:39
@ nvars
Definition: DataStruct.H:52
#define Rho_comp
Definition: IndexDefines.H:12
#define RhoTheta_comp
Definition: IndexDefines.H:13
#define RhoQ1_comp
Definition: IndexDefines.H:17
void Time_Avg_Vel_atCC(const Real &dt, Real &t_avg_cnt, MultiFab *vel_t_avg, MultiFab &xvel, MultiFab &yvel, MultiFab &zvel)
Definition: Time_Avg_Vel.cpp:9
std::unique_ptr< ABLMost > m_most
Definition: ERF.H:938
amrex::Vector< ERFFillPatcher > FPr_u
Definition: ERF.H:649
amrex::Vector< ERFFillPatcher > FPr_v
Definition: ERF.H:650
amrex::Vector< ERFFillPatcher > FPr_c
Definition: ERF.H:648
void FillPatch(int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, const amrex::Vector< amrex::MultiFab * > &mfs_mom, bool fillset=true, bool cons_only=false)
Definition: ERF_FillPatch.cpp:22
void advance_lsm(int lev, amrex::MultiFab &, const amrex::Real &dt_advance)
Definition: ERF_advance_lsm.cpp:5
amrex::Vector< ERFFillPatcher > FPr_w
Definition: ERF.H:651
void advance_microphysics(int lev, amrex::MultiFab &cons_in, const amrex::Real &dt_advance, const int &iteration, const amrex::Real &time)
Definition: ERF_advance_microphysics.cpp:5
int cf_width
Definition: ERF.H:646
amrex::Vector< amrex::Vector< amrex::MultiFab * > > qmoist
Definition: ERF.H:626
amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > phys_bc_type
Definition: ERF.H:719
void advance_dycore(int level, amrex::Vector< amrex::MultiFab > &state_old, amrex::Vector< amrex::MultiFab > &state_new, amrex::MultiFab &xvel_old, amrex::MultiFab &yvel_old, amrex::MultiFab &zvel_old, amrex::MultiFab &xvel_new, amrex::MultiFab &yvel_new, amrex::MultiFab &zvel_new, amrex::MultiFab &source, amrex::MultiFab &xmom_src, amrex::MultiFab &ymom_src, amrex::MultiFab &zmom_src, amrex::Geometry fine_geom, amrex::Real dt, amrex::Real time)
Definition: ERF_advance_dycore.cpp:38
void FillPatchMoistVars(int lev, amrex::MultiFab &mf)
Definition: ERF_FillPatch.cpp:190
@ ymom
Definition: IndexDefines.H:111
@ cons
Definition: IndexDefines.H:109
@ zmom
Definition: IndexDefines.H:112
@ xmom
Definition: IndexDefines.H:110
@ xvel
Definition: IndexDefines.H:100
@ cons
Definition: IndexDefines.H:99
@ zvel
Definition: IndexDefines.H:102
@ yvel
Definition: IndexDefines.H:101
MoistureType moisture_type
Definition: DataStruct.H:445
WindFarmType windfarm_type
Definition: DataStruct.H:446
bool time_avg_vel
Definition: DataStruct.H:437
Here is the call graph for this function:

◆ advance_dycore()

void ERF::advance_dycore ( int  level,
amrex::Vector< amrex::MultiFab > &  state_old,
amrex::Vector< amrex::MultiFab > &  state_new,
amrex::MultiFab &  xvel_old,
amrex::MultiFab &  yvel_old,
amrex::MultiFab &  zvel_old,
amrex::MultiFab &  xvel_new,
amrex::MultiFab &  yvel_new,
amrex::MultiFab &  zvel_new,
amrex::MultiFab &  source,
amrex::MultiFab &  xmom_src,
amrex::MultiFab &  ymom_src,
amrex::MultiFab &  zmom_src,
amrex::Geometry  fine_geom,
amrex::Real  dt,
amrex::Real  time 
)

Function that advances the solution at one level for a single time step – this sets up the multirate time integrator and calls the integrator's advance function

Parameters
[in]levellevel of refinement (coarsest level is 0)
[in]state_oldold-time conserved variables
[in]state_newnew-time conserved variables
[in]xvel_oldold-time x-component of velocity
[in]yvel_oldold-time y-component of velocity
[in]zvel_oldold-time z-component of velocity
[in]xvel_newnew-time x-component of velocity
[in]yvel_newnew-time y-component of velocity
[in]zvel_newnew-time z-component of velocity
[in]cc_srcsource term for conserved variables
[in]xmom_srcsource term for x-momenta
[in]ymom_srcsource term for y-momenta
[in]zmom_srcsource term for z-momenta
[in]fine_geomcontainer for geometry information at current level
[in]dt_advancetime step for this time advance
[in]old_timeold time for this time advance
47 {
48  BL_PROFILE_VAR("erf_advance_dycore()",erf_advance_dycore);
49 
50  const Box& domain = fine_geom.Domain();
51 
55 
56  MultiFab r_hse (base_state[level], make_alias, 0, 1); // r_0 is first component
57  MultiFab p_hse (base_state[level], make_alias, 1, 1); // p_0 is second component
58  MultiFab pi_hse(base_state[level], make_alias, 2, 1); // pi_0 is second component
59 
60  // These pointers are used in the MRI utility functions
61  MultiFab* r0 = &r_hse;
62  MultiFab* p0 = &p_hse;
63  MultiFab* pi0 = &pi_hse;
64 
65  Real* dptr_rhotheta_src = solverChoice.custom_rhotheta_forcing ? d_rhotheta_src[level].data() : nullptr;
66  Real* dptr_rhoqt_src = solverChoice.custom_moisture_forcing ? d_rhoqt_src[level].data() : nullptr;
67  Real* dptr_wbar_sub = solverChoice.custom_w_subsidence ? d_w_subsid[level].data() : nullptr;
68 
69  Vector<Real*> d_rayleigh_ptrs_at_lev;
70  d_rayleigh_ptrs_at_lev.resize(Rayleigh::nvars);
71  bool rayleigh_damp_any = (solverChoice.rayleigh_damp_U ||solverChoice.rayleigh_damp_V ||
73  d_rayleigh_ptrs_at_lev[Rayleigh::tau] = rayleigh_damp_any ? d_rayleigh_ptrs[level][Rayleigh::tau ].data() : nullptr;
74  d_rayleigh_ptrs_at_lev[Rayleigh::ubar] = solverChoice.rayleigh_damp_U ? d_rayleigh_ptrs[level][Rayleigh::ubar].data() : nullptr;
75  d_rayleigh_ptrs_at_lev[Rayleigh::vbar] = solverChoice.rayleigh_damp_V ? d_rayleigh_ptrs[level][Rayleigh::vbar].data() : nullptr;
76  d_rayleigh_ptrs_at_lev[Rayleigh::wbar] = solverChoice.rayleigh_damp_W ? d_rayleigh_ptrs[level][Rayleigh::wbar].data() : nullptr;
77  d_rayleigh_ptrs_at_lev[Rayleigh::thetabar] = solverChoice.rayleigh_damp_T ? d_rayleigh_ptrs[level][Rayleigh::thetabar].data() : nullptr;
78 
79  Vector<Real*> d_sponge_ptrs_at_lev;
80  if(sc.sponge_type=="input_sponge")
81  {
82  d_sponge_ptrs_at_lev.resize(Sponge::nvars_sponge);
83  d_sponge_ptrs_at_lev[Sponge::ubar_sponge] = d_sponge_ptrs[level][Sponge::ubar_sponge].data();
84  d_sponge_ptrs_at_lev[Sponge::vbar_sponge] = d_sponge_ptrs[level][Sponge::vbar_sponge].data();
85  }
86 
87  bool l_use_terrain = solverChoice.use_terrain;
88  bool l_use_diff = ( (dc.molec_diff_type != MolecDiffType::None) ||
89  (tc.les_type != LESType::None) ||
90  (tc.pbl_type != PBLType::None) );
91  bool l_use_kturb = ( (tc.les_type != LESType::None) ||
92  (tc.pbl_type != PBLType::None) );
93 
94  const bool use_most = (m_most != nullptr);
95  amrex::ignore_unused(use_most);
96 
97  const BoxArray& ba = state_old[IntVars::cons].boxArray();
98  const BoxArray& ba_z = zvel_old.boxArray();
99  const DistributionMapping& dm = state_old[IntVars::cons].DistributionMap();
100 
101  int num_prim = state_old[IntVars::cons].nComp() - 1;
102 
103  MultiFab S_prim (ba , dm, num_prim, state_old[IntVars::cons].nGrowVect());
104  MultiFab pi_stage (ba , dm, 1, state_old[IntVars::cons].nGrowVect());
105  MultiFab fast_coeffs(ba_z, dm, 5, 0);
106  MultiFab* eddyDiffs = eddyDiffs_lev[level].get();
107  MultiFab* SmnSmn = SmnSmn_lev[level].get();
108 
109  // **************************************************************************************
110  // Compute strain for use in slow RHS, Smagorinsky model, and MOST
111  // **************************************************************************************
112  {
113  BL_PROFILE("erf_advance_strain");
114  if (l_use_diff) {
115 
116  const BCRec* bc_ptr_h = domain_bcs_type.data();
117  const GpuArray<Real, AMREX_SPACEDIM> dxInv = fine_geom.InvCellSizeArray();
118 
119 #ifdef _OPENMP
120 #pragma omp parallel if (Gpu::notInLaunchRegion())
121 #endif
122  for ( MFIter mfi(state_new[IntVars::cons],TileNoZ()); mfi.isValid(); ++mfi)
123  {
124  Box bxcc = mfi.growntilebox(IntVect(1,1,0));
125  Box tbxxy = mfi.tilebox(IntVect(1,1,0),IntVect(1,1,0));
126  Box tbxxz = mfi.tilebox(IntVect(1,0,1),IntVect(1,1,0));
127  Box tbxyz = mfi.tilebox(IntVect(0,1,1),IntVect(1,1,0));
128 
129  const Array4<const Real> & u = xvel_old.array(mfi);
130  const Array4<const Real> & v = yvel_old.array(mfi);
131  const Array4<const Real> & w = zvel_old.array(mfi);
132 
133  Array4<Real> tau11 = Tau11_lev[level].get()->array(mfi);
134  Array4<Real> tau22 = Tau22_lev[level].get()->array(mfi);
135  Array4<Real> tau33 = Tau33_lev[level].get()->array(mfi);
136  Array4<Real> tau12 = Tau12_lev[level].get()->array(mfi);
137  Array4<Real> tau13 = Tau13_lev[level].get()->array(mfi);
138  Array4<Real> tau23 = Tau23_lev[level].get()->array(mfi);
139 
140  Array4<Real> tau21 = l_use_terrain ? Tau21_lev[level].get()->array(mfi) : Array4<Real>{};
141  Array4<Real> tau31 = l_use_terrain ? Tau31_lev[level].get()->array(mfi) : Array4<Real>{};
142  Array4<Real> tau32 = l_use_terrain ? Tau32_lev[level].get()->array(mfi) : Array4<Real>{};
143  const Array4<const Real>& z_nd = l_use_terrain ? z_phys_nd[level]->const_array(mfi) : Array4<const Real>{};
144 
145  const Array4<const Real> mf_m = mapfac_m[level]->array(mfi);
146  const Array4<const Real> mf_u = mapfac_u[level]->array(mfi);
147  const Array4<const Real> mf_v = mapfac_v[level]->array(mfi);
148 
149  if (l_use_terrain) {
150  ComputeStrain_T(bxcc, tbxxy, tbxxz, tbxyz, domain,
151  u, v, w,
152  tau11, tau22, tau33,
153  tau12, tau13,
154  tau21, tau23,
155  tau31, tau32,
156  z_nd, detJ_cc[level]->const_array(mfi), bc_ptr_h, dxInv,
157  mf_m, mf_u, mf_v);
158  } else {
159  ComputeStrain_N(bxcc, tbxxy, tbxxz, tbxyz, domain,
160  u, v, w,
161  tau11, tau22, tau33,
162  tau12, tau13, tau23,
163  bc_ptr_h, dxInv,
164  mf_m, mf_u, mf_v);
165  }
166  } // mfi
167  } // l_use_diff
168  } // profile
169 
170  MultiFab Omega (state_old[IntVars::zmom].boxArray(),dm,1,1);
171 
172 #include "TI_utils.H"
173 
174  // Additional SFS quantities, calculated once per timestep
175  MultiFab* Hfx1 = SFS_hfx1_lev[level].get();
176  MultiFab* Hfx2 = SFS_hfx2_lev[level].get();
177  MultiFab* Hfx3 = SFS_hfx3_lev[level].get();
178  MultiFab* Diss = SFS_diss_lev[level].get();
179 
180  // *************************************************************************
181  // Calculate cell-centered eddy viscosity & diffusivities
182  //
183  // Notes -- we fill all the data in ghost cells before calling this so
184  // that we can fill the eddy viscosity in the ghost regions and
185  // not have to call a boundary filler on this data itself
186  //
187  // LES - updates both horizontal and vertical eddy viscosity components
188  // PBL - only updates vertical eddy viscosity components so horizontal
189  // components come from the LES model or are left as zero.
190  // *************************************************************************
191  if (l_use_kturb)
192  {
193  // NOTE: state_new transfers to state_old for PBL (due to ptr swap in advance)
194  const BCRec* bc_ptr_d = domain_bcs_type_d.data();
195  ComputeTurbulentViscosity(xvel_old, yvel_old,
196  *Tau11_lev[level].get(), *Tau22_lev[level].get(), *Tau33_lev[level].get(),
197  *Tau12_lev[level].get(), *Tau13_lev[level].get(), *Tau23_lev[level].get(),
198  state_old[IntVars::cons],
199  *eddyDiffs, *Hfx1, *Hfx2, *Hfx3, *Diss, // to be updated
200  fine_geom, *mapfac_u[level], *mapfac_v[level],
201  z_phys_nd[level], tc, solverChoice.gravity,
202  m_most, level, bc_ptr_d);
203  }
204 
205  // ***********************************************************************************************
206  // Update user-defined source terms -- these are defined once per time step (not per RK stage)
207  // ***********************************************************************************************
209  prob->update_rhotheta_sources(old_time,
210  h_rhotheta_src[level], d_rhotheta_src[level],
211  fine_geom, z_phys_cc[level]);
212  }
213 
215  prob->update_rhoqt_sources(old_time,
216  h_rhoqt_src[level], d_rhoqt_src[level],
217  fine_geom, z_phys_cc[level]);
218  }
219 
221  prob->update_geostrophic_profile(old_time,
222  h_u_geos[level], d_u_geos[level],
223  h_v_geos[level], d_v_geos[level],
224  fine_geom, z_phys_cc[level]);
225  }
226 
227  // ***********************************************************************************************
228  // Convert old velocity available on faces to old momentum on faces to be used in time integration
229  // ***********************************************************************************************
230  MultiFab density(state_old[IntVars::cons], make_alias, Rho_comp, 1);
231 
232  //
233  // This is an optimization since we won't need more than one ghost
234  // cell of momentum in the integrator if not using NumDiff
235  //
236  IntVect ngu = (solverChoice.use_NumDiff) ? IntVect(1,1,1) : xvel_old.nGrowVect();
237  IntVect ngv = (solverChoice.use_NumDiff) ? IntVect(1,1,1) : yvel_old.nGrowVect();
238  IntVect ngw = (solverChoice.use_NumDiff) ? IntVect(1,1,0) : zvel_old.nGrowVect();
239  VelocityToMomentum(xvel_old, ngu, yvel_old, ngv, zvel_old, ngw, density,
240  state_old[IntVars::xmom],
241  state_old[IntVars::ymom],
242  state_old[IntVars::zmom],
243  domain, domain_bcs_type);
244 
245  MultiFab::Copy(xvel_new,xvel_old,0,0,1,xvel_old.nGrowVect());
246  MultiFab::Copy(yvel_new,yvel_old,0,0,1,yvel_old.nGrowVect());
247  MultiFab::Copy(zvel_new,zvel_old,0,0,1,zvel_old.nGrowVect());
248 
249  bool fast_only = false;
250  bool vel_and_mom_synced = true;
251 
252  apply_bcs(state_old, old_time,
253  state_old[IntVars::cons].nGrow(), state_old[IntVars::xmom].nGrow(),
254  fast_only, vel_and_mom_synced);
255  cons_to_prim(state_old[IntVars::cons], state_old[IntVars::cons].nGrow());
256 
257 #include "TI_no_substep_fun.H"
258 #include "TI_slow_rhs_fun.H"
259 #include "TI_fast_rhs_fun.H"
260 
261  // ***************************************************************************************
262  // Setup the integrator and integrate for a single timestep
263  // **************************************************************************************
264  MRISplitIntegrator<Vector<MultiFab> >& mri_integrator = *mri_integrator_mem[level];
265 
266  // Define rhs and 'post update' utility function that is called after calculating
267  // any state data (e.g. at RK stages or at the end of a timestep)
268  mri_integrator.set_slow_rhs_pre(slow_rhs_fun_pre);
269  mri_integrator.set_slow_rhs_post(slow_rhs_fun_post);
270  mri_integrator.set_pre_update (pre_update_fun);
271  mri_integrator.set_post_update(post_update_fun);
272 
273 #ifdef ERF_USE_POISSON_SOLVE
275  mri_integrator.set_slow_rhs_inc(slow_rhs_fun_inc);
276  }
277 #endif
278 
279  mri_integrator.set_fast_rhs(fast_rhs_fun);
281  mri_integrator.set_no_substep(no_substep_fun);
282 
283  mri_integrator.advance(state_old, state_new, old_time, dt_advance);
284 
285  if (verbose) Print() << "Done with advance_dycore at level " << level << std::endl;
286 }
void ComputeStrain_N(Box bxcc, Box tbxxy, Box tbxxz, Box tbxyz, Box domain, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, Array4< Real > &tau11, Array4< Real > &tau22, Array4< Real > &tau33, Array4< Real > &tau12, Array4< Real > &tau13, Array4< Real > &tau23, const BCRec *bc_ptr, const GpuArray< Real, AMREX_SPACEDIM > &dxInv, const Array4< const Real > &mf_m, const Array4< const Real > &mf_u, const Array4< const Real > &mf_v)
Definition: ComputeStrain_N.cpp:28
void ComputeStrain_T(Box bxcc, Box tbxxy, Box tbxxz, Box tbxyz, Box domain, const Array4< const Real > &u, const Array4< const Real > &v, const Array4< const Real > &w, Array4< Real > &tau11, Array4< Real > &tau22, Array4< Real > &tau33, Array4< Real > &tau12, Array4< Real > &tau13, Array4< Real > &tau21, Array4< Real > &tau23, Array4< Real > &tau31, Array4< Real > &tau32, const Array4< const Real > &z_nd, const Array4< const Real > &detJ, const BCRec *bc_ptr, const GpuArray< Real, AMREX_SPACEDIM > &dxInv, const Array4< const Real > &, const Array4< const Real > &mf_u, const Array4< const Real > &mf_v)
Definition: ComputeStrain_T.cpp:32
void ComputeTurbulentViscosity(const MultiFab &xvel, const MultiFab &yvel, const MultiFab &Tau11, const MultiFab &Tau22, const MultiFab &Tau33, const MultiFab &Tau12, const MultiFab &Tau13, const MultiFab &Tau23, const MultiFab &cons_in, MultiFab &eddyViscosity, MultiFab &Hfx1, MultiFab &Hfx2, MultiFab &Hfx3, MultiFab &Diss, const Geometry &geom, const MultiFab &mapfac_u, const MultiFab &mapfac_v, const std::unique_ptr< MultiFab > &z_phys_nd, const TurbChoice &turbChoice, const Real const_grav, std::unique_ptr< ABLMost > &most, int level, const BCRec *bc_ptr, bool vert_only)
Definition: ComputeTurbulentViscosity.cpp:405
@ tau
Definition: DataStruct.H:52
@ ubar
Definition: DataStruct.H:52
@ wbar
Definition: DataStruct.H:52
@ vbar
Definition: DataStruct.H:52
@ thetabar
Definition: DataStruct.H:52
@ nvars_sponge
Definition: DataStruct.H:56
@ vbar_sponge
Definition: DataStruct.H:56
@ ubar_sponge
Definition: DataStruct.H:56
auto fast_rhs_fun
Definition: TI_fast_rhs_fun.H:4
auto no_substep_fun
Definition: TI_no_substep_fun.H:4
auto slow_rhs_fun_pre
Definition: TI_slow_rhs_fun.H:6
auto pre_update_fun
Definition: TI_slow_rhs_fun.H:270
auto slow_rhs_fun_post
Definition: TI_slow_rhs_fun.H:287
auto post_update_fun
Definition: TI_slow_rhs_fun.H:278
auto apply_bcs
Definition: TI_utils.H:40
auto cons_to_prim
Definition: TI_utils.H:4
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: TileNoZ.H:11
void VelocityToMomentum(const amrex::MultiFab &xvel_in, const amrex::IntVect &xvel_ngrow, const amrex::MultiFab &yvel_in, const amrex::IntVect &yvel_ngrow, const amrex::MultiFab &zvel_in, const amrex::IntVect &zvel_ngrow, const amrex::MultiFab &cons_in, amrex::MultiFab &xmom_out, amrex::MultiFab &ymom_out, amrex::MultiFab &zmom_out, const amrex::Box &domain, const amrex::Vector< amrex::BCRec > &domain_bcs_type_h)
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_rhotheta_src
Definition: ERF.H:896
amrex::Vector< amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > > d_sponge_ptrs
Definition: ERF.H:920
amrex::Vector< amrex::Vector< amrex::Real > > h_rhoqt_src
Definition: ERF.H:898
static int verbose
Definition: ERF.H:837
amrex::Vector< amrex::BCRec > domain_bcs_type
Definition: ERF.H:706
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_v_geos
Definition: ERF.H:908
amrex::Vector< amrex::Vector< amrex::Real > > h_v_geos
Definition: ERF.H:907
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_rhoqt_src
Definition: ERF.H:899
amrex::Vector< amrex::Vector< amrex::Real > > h_rhotheta_src
Definition: ERF.H:895
amrex::Gpu::DeviceVector< amrex::BCRec > domain_bcs_type_d
Definition: ERF.H:707
amrex::Vector< amrex::Vector< amrex::Real > > h_u_geos
Definition: ERF.H:904
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_u_geos
Definition: ERF.H:905
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_w_subsid
Definition: ERF.H:902
static int fixed_mri_dt_ratio
Definition: ERF.H:757
amrex::Vector< amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > > d_rayleigh_ptrs
Definition: ERF.H:917
Definition: ERF_MRI.H:16
void set_slow_rhs_pre(std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> F)
Definition: ERF_MRI.H:137
amrex::Real advance(T &S_old, T &S_new, amrex::Real time, const amrex::Real time_step) override
Definition: ERF_MRI.H:187
void set_no_substep(std::function< void(T &, T &, T &, amrex::Real, amrex::Real, int)> F)
Definition: ERF_MRI.H:177
void set_slow_rhs_inc(std::function< void(T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> F)
Definition: ERF_MRI.H:141
void set_pre_update(std::function< void(T &, int)> F)
Definition: ERF_MRI.H:167
void set_post_update(std::function< void(T &, amrex::Real, int, int)> F)
Definition: ERF_MRI.H:172
void set_fast_rhs(std::function< void(int, int, int, T &, const T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const amrex::Real)> F)
Definition: ERF_MRI.H:150
void set_slow_fast_timestep_ratio(const int timestep_ratio=1)
Definition: ERF_MRI.H:157
void set_slow_rhs_post(std::function< void(T &, T &, T &, T &, T &, const amrex::Real, const amrex::Real, const amrex::Real, const int)> F)
Definition: ERF_MRI.H:145
Definition: DiffStruct.H:19
MolecDiffType molec_diff_type
Definition: DiffStruct.H:76
bool rayleigh_damp_T
Definition: DataStruct.H:405
bool rayleigh_damp_V
Definition: DataStruct.H:403
DiffChoice diffChoice
Definition: DataStruct.H:376
amrex::Real gravity
Definition: DataStruct.H:411
bool custom_rhotheta_forcing
Definition: DataStruct.H:430
bool custom_w_subsidence
Definition: DataStruct.H:432
bool rayleigh_damp_U
Definition: DataStruct.H:402
bool custom_geostrophic_profile
Definition: DataStruct.H:433
bool use_NumDiff
Definition: DataStruct.H:440
bool custom_moisture_forcing
Definition: DataStruct.H:431
amrex::Vector< TurbChoice > turbChoice
Definition: DataStruct.H:378
bool rayleigh_damp_W
Definition: DataStruct.H:404
SpongeChoice spongeChoice
Definition: DataStruct.H:377
int incompressible
Definition: DataStruct.H:386
Definition: SpongeStruct.H:15
std::string sponge_type
Definition: SpongeStruct.H:61
Definition: TurbStruct.H:16
PBLType pbl_type
Definition: TurbStruct.H:279
LESType les_type
Definition: TurbStruct.H:256
Here is the call graph for this function:

◆ advance_lsm()

void ERF::advance_lsm ( int  lev,
amrex::MultiFab &  ,
const amrex::Real &  dt_advance 
)
8 {
10  lsm.Advance(lev, dt_advance);
11  }
12 }
void Advance(const int &lev, const amrex::Real &dt_advance)
Definition: LandSurface.H:47
LandSurfaceType lsm_type
Definition: DataStruct.H:447

◆ advance_microphysics()

void ERF::advance_microphysics ( int  lev,
amrex::MultiFab &  cons_in,
const amrex::Real &  dt_advance,
const int &  iteration,
const amrex::Real &  time 
)
10 {
12  micro->Update_Micro_Vars_Lev(lev, cons);
13  micro->Advance(lev, dt_advance, iteration, time, solverChoice, vars_new, z_phys_nd);
14  micro->Update_State_Vars_Lev(lev, cons);
15  }
16 }
std::unique_ptr< Microphysics > micro
Definition: ERF.H:625

◆ appendPlotVariables()

void ERF::appendPlotVariables ( const std::string &  pp_plot_var_names,
amrex::Vector< std::string > &  plot_var_names 
)
private
97 {
98  ParmParse pp(pp_prefix);
99 
100  Vector<std::string> plot_var_names(0);
101  if (pp.contains(pp_plot_var_names.c_str())) {
102  std::string nm;
103  int nPltVars = pp.countval(pp_plot_var_names.c_str());
104  for (int i = 0; i < nPltVars; i++) {
105  pp.get(pp_plot_var_names.c_str(), nm, i);
106  // Add the named variable to our list of plot variables
107  // if it is not already in the list
108  if (!containerHasElement(plot_var_names, nm)) {
109  plot_var_names.push_back(nm);
110  }
111  }
112  }
113 
114  Vector<std::string> tmp_plot_names(0);
115 #ifdef ERF_USE_PARTICLES
116  Vector<std::string> particle_mesh_plot_names;
117  particleData.GetMeshPlotVarNames( particle_mesh_plot_names );
118  for (int i = 0; i < particle_mesh_plot_names.size(); i++) {
119  std::string tmp(particle_mesh_plot_names[i]);
120  if (containerHasElement(plot_var_names, tmp) ) {
121  tmp_plot_names.push_back(tmp);
122  }
123  }
124 #endif
125 
126  for (int i = 0; i < tmp_plot_names.size(); i++) {
127  a_plot_var_names.push_back( tmp_plot_names[i] );
128  }
129 
130  // Finally, check to see if we found all the requested variables
131  for (const auto& plot_name : plot_var_names) {
132  if (!containerHasElement(a_plot_var_names, plot_name)) {
133  if (amrex::ParallelDescriptor::IOProcessor()) {
134  Warning("\nWARNING: Requested to plot variable '" + plot_name + "' but it is not available");
135  }
136  }
137  }
138 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: Microphysics_Utils.H:183
bool containerHasElement(const V &iterable, const T &query)
Definition: Plotfile.cpp:13
std::string pp_prefix
Definition: ERF.H:348
Here is the call graph for this function:

◆ AverageDown()

void ERF::AverageDown ( )
private
1589 {
1590  AMREX_ALWAYS_ASSERT(solverChoice.coupling_type == CouplingType::TwoWay);
1591  int src_comp = 0;
1592  int num_comp = vars_new[0][Vars::cons].nComp();
1593  for (int lev = finest_level-1; lev >= 0; --lev)
1594  {
1595  AverageDownTo(lev,src_comp,num_comp);
1596  }
1597 }
void AverageDownTo(int crse_lev, int scomp, int ncomp)
Definition: ERF.cpp:1601
CouplingType coupling_type
Definition: DataStruct.H:443

◆ AverageDownTo()

void ERF::AverageDownTo ( int  crse_lev,
int  scomp,
int  ncomp 
)
1602 {
1603  AMREX_ALWAYS_ASSERT(solverChoice.coupling_type == CouplingType::TwoWay);
1604 
1605  // ******************************************************************************************
1606  // First do cell-centered quantities
1607  // The quantity that is conserved is not (rho S), but rather (rho S / m^2) where
1608  // m is the map scale factor at cell centers
1609  // Here we pre-divide (rho S) by m^2 before average down
1610  // ******************************************************************************************
1611  for (int lev = crse_lev; lev <= crse_lev+1; lev++) {
1612  for (MFIter mfi(vars_new[lev][Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
1613  const Box& bx = mfi.tilebox();
1614  const Array4< Real> cons_arr = vars_new[lev][Vars::cons].array(mfi);
1615  const Array4<const Real> mapfac_arr = mapfac_m[lev]->const_array(mfi);
1616  if (solverChoice.use_terrain) {
1617  const Array4<const Real> detJ_arr = detJ_cc[lev]->const_array(mfi);
1618  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
1619  {
1620  cons_arr(i,j,k,scomp+n) *= detJ_arr(i,j,k) / (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
1621  });
1622  } else {
1623  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
1624  {
1625  cons_arr(i,j,k,scomp+n) /= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
1626  });
1627  }
1628  } // mfi
1629  } // lev
1630 
1631  average_down(vars_new[crse_lev+1][Vars::cons],
1632  vars_new[crse_lev ][Vars::cons],
1633  scomp, ncomp, refRatio(crse_lev));
1634 
1635  // Here we multiply (rho S) by m^2 after average down
1636  for (int lev = crse_lev; lev <= crse_lev+1; lev++) {
1637  for (MFIter mfi(vars_new[lev][Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
1638  const Box& bx = mfi.tilebox();
1639  const Array4< Real> cons_arr = vars_new[lev][Vars::cons].array(mfi);
1640  const Array4<const Real> mapfac_arr = mapfac_m[lev]->const_array(mfi);
1641  if (solverChoice.use_terrain) {
1642  const Array4<const Real> detJ_arr = detJ_cc[lev]->const_array(mfi);
1643  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
1644  {
1645  cons_arr(i,j,k,scomp+n) *= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0)) / detJ_arr(i,j,k);
1646  });
1647  } else {
1648  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
1649  {
1650  cons_arr(i,j,k,scomp+n) *= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
1651  });
1652  }
1653  } // mfi
1654  } // lev
1655 
1656  // ******************************************************************************************
1657  // Now average down momenta.
1658  // Note that vars_new holds velocities not momenta, but we want to do conservative
1659  // averaging so we first convert to momentum, then average down, then convert
1660  // back to velocities -- only on the valid region
1661  // ******************************************************************************************
1662  for (int lev = crse_lev; lev <= crse_lev+1; lev++)
1663  {
1664  // FillBoundary for density so we can go back and forth between velocity and momentum
1665  vars_new[lev][Vars::cons].FillBoundary(geom[lev].periodicity());
1666 
1667  VelocityToMomentum(vars_new[lev][Vars::xvel], IntVect(0,0,0),
1668  vars_new[lev][Vars::yvel], IntVect(0,0,0),
1669  vars_new[lev][Vars::zvel], IntVect(0,0,0),
1670  vars_new[lev][Vars::cons],
1671  rU_new[lev],
1672  rV_new[lev],
1673  rW_new[lev],
1674  Geom(lev).Domain(),
1675  domain_bcs_type);
1676  }
1677 
1678  average_down_faces(rU_new[crse_lev+1], rU_new[crse_lev], refRatio(crse_lev), geom[crse_lev]);
1679  average_down_faces(rV_new[crse_lev+1], rV_new[crse_lev], refRatio(crse_lev), geom[crse_lev]);
1680  average_down_faces(rW_new[crse_lev+1], rW_new[crse_lev], refRatio(crse_lev), geom[crse_lev]);
1681 
1682  for (int lev = crse_lev; lev <= crse_lev+1; lev++) {
1684  vars_new[lev][Vars::yvel],
1685  vars_new[lev][Vars::zvel],
1686  vars_new[lev][Vars::cons],
1687  rU_new[lev],
1688  rV_new[lev],
1689  rW_new[lev],
1690  Geom(lev).Domain(),
1691  domain_bcs_type);
1692  }
1693 }
void MomentumToVelocity(MultiFab &xvel, MultiFab &yvel, MultiFab &zvel, const MultiFab &density, const MultiFab &xmom_in, const MultiFab &ymom_in, const MultiFab &zmom_in, const Box &domain, const Vector< BCRec > &domain_bcs_type_h)
Definition: MomentumToVelocity.cpp:25
Here is the call graph for this function:

◆ build_fine_mask()

MultiFab & ERF::build_fine_mask ( int  level)

Helper function for constructing a fine mask, that is, a MultiFab masking coarser data at a lower level by zeroing out covered cells in the fine mask MultiFab we compute.

Parameters
levelFine level index which masks underlying coarser data
360 {
361  // Mask for zeroing covered cells
362  AMREX_ASSERT(level > 0);
363 
364  const BoxArray& cba = grids[level-1];
365  const DistributionMapping& cdm = dmap[level-1];
366 
367  // TODO -- we should make a vector of these a member of ERF class
368  fine_mask.define(cba, cdm, 1, 0, MFInfo());
369  fine_mask.setVal(1.0);
370 
371  BoxArray fba = grids[level];
372  iMultiFab ifine_mask = makeFineMask(cba, cdm, fba, ref_ratio[level-1], 1, 0);
373 
374  const auto fma = fine_mask.arrays();
375  const auto ifma = ifine_mask.arrays();
376  ParallelFor(fine_mask, [=] AMREX_GPU_DEVICE(int bno, int i, int j, int k) noexcept
377  {
378  fma[bno](i,j,k) = ifma[bno](i,j,k);
379  });
380 
381  return fine_mask;
382 }
amrex::MultiFab fine_mask
Definition: ERF.H:949

◆ ClearLevel()

void ERF::ClearLevel ( int  lev)
override
487 {
488  for (int var_idx = 0; var_idx < Vars::NumTypes; ++var_idx) {
489  vars_new[lev][var_idx].clear();
490  vars_old[lev][var_idx].clear();
491  }
492 
493  base_state[lev].clear();
494 
495  rU_new[lev].clear();
496  rU_old[lev].clear();
497  rV_new[lev].clear();
498  rV_old[lev].clear();
499  rW_new[lev].clear();
500  rW_old[lev].clear();
501 
502  // Clears the integrator memory
503  mri_integrator_mem[lev].reset();
504 
505  // Clears the physical boundary condition routines
506  physbcs_cons[lev].reset();
507  physbcs_u[lev].reset();
508  physbcs_v[lev].reset();
509  physbcs_w[lev].reset();
510  physbcs_w_no_terrain[lev].reset();
511 
512  // Clears the flux register array
513  advflux_reg[lev]->reset();
514 }

◆ ComputeDt()

void ERF::ComputeDt ( )
private

Function that calls estTimeStep for each level

12 {
13  Vector<Real> dt_tmp(finest_level+1);
14 
15  for (int lev = 0; lev <= finest_level; ++lev)
16  {
17  dt_tmp[lev] = estTimeStep(lev, dt_mri_ratio[lev]);
18  }
19 
20  ParallelDescriptor::ReduceRealMin(&dt_tmp[0], dt_tmp.size());
21 
22  Real dt_0 = dt_tmp[0];
23  int n_factor = 1;
24  for (int lev = 0; lev <= finest_level; ++lev) {
25  dt_tmp[lev] = amrex::min(dt_tmp[lev], change_max*dt[lev]);
26  n_factor *= nsubsteps[lev];
27  dt_0 = amrex::min(dt_0, n_factor*dt_tmp[lev]);
28  }
29 
30  // Limit dt's by the value of stop_time.
31  const Real eps = 1.e-3*dt_0;
32  if (t_new[0] + dt_0 > stop_time - eps) {
33  dt_0 = stop_time - t_new[0];
34  }
35 
36  dt[0] = dt_0;
37  for (int lev = 1; lev <= finest_level; ++lev) {
38  dt[lev] = dt[lev-1] / nsubsteps[lev];
39  }
40 }
amrex::Real stop_time
Definition: ERF.H:744
amrex::Real estTimeStep(int lev, long &dt_fast_ratio) const
Definition: ERF_ComputeTimestep.cpp:49
static amrex::Real change_max
Definition: ERF.H:752

◆ ComputeGhostCells()

static AMREX_FORCE_INLINE int ERF::ComputeGhostCells ( const AdvChoice advChoice,
bool  use_num_diff 
)
inlinestaticprivate
956  {
957  if (use_num_diff)
958  {
959  return 3;
960  } else {
961  if (
967  || (advChoice.dryscal_vert_adv_type == AdvType::Centered_6th) )
968  { return 3; }
969  else if (
971  || (advChoice.dycore_vert_adv_type == AdvType::Upwind_5th)
975  || (advChoice.dryscal_vert_adv_type == AdvType::Upwind_5th) )
976  { return 3; }
977  else if (
979  || (advChoice.dryscal_vert_adv_type == AdvType::Weno_5)
980  || (advChoice.moistscal_horiz_adv_type == AdvType::Weno_5)
981  || (advChoice.moistscal_vert_adv_type == AdvType::Weno_5)
983  || (advChoice.moistscal_vert_adv_type == AdvType::Weno_5Z)
984  || (advChoice.dryscal_horiz_adv_type == AdvType::Weno_5Z)
985  || (advChoice.dryscal_vert_adv_type == AdvType::Weno_5Z) )
986  { return 3; }
987  else
988  { return 2; }
989  }
990  }
@ Centered_6th
AdvType moistscal_horiz_adv_type
Definition: AdvStruct.H:287
AdvType dycore_vert_adv_type
Definition: AdvStruct.H:284
AdvType moistscal_vert_adv_type
Definition: AdvStruct.H:288
AdvType dryscal_horiz_adv_type
Definition: AdvStruct.H:285
AdvType dycore_horiz_adv_type
Definition: AdvStruct.H:283
AdvType dryscal_vert_adv_type
Definition: AdvStruct.H:286

◆ Construct_ERFFillPatchers()

void ERF::Construct_ERFFillPatchers ( int  lev)
private
1697 {
1698  auto& fine_new = vars_new[lev];
1699  auto& crse_new = vars_new[lev-1];
1700  auto& ba_fine = fine_new[Vars::cons].boxArray();
1701  auto& ba_crse = crse_new[Vars::cons].boxArray();
1702  auto& dm_fine = fine_new[Vars::cons].DistributionMap();
1703  auto& dm_crse = crse_new[Vars::cons].DistributionMap();
1704 
1705  int ncomp = vars_new[lev][Vars::cons].nComp();
1706 
1707  FPr_c.emplace_back(ba_fine, dm_fine, geom[lev] ,
1708  ba_crse, dm_crse, geom[lev-1],
1709  -cf_width, -cf_set_width, ncomp, &cell_cons_interp);
1710  FPr_u.emplace_back(convert(ba_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
1711  convert(ba_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
1712  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1713  FPr_v.emplace_back(convert(ba_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
1714  convert(ba_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
1715  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1716  FPr_w.emplace_back(convert(ba_fine, IntVect(0,0,1)), dm_fine, geom[lev] ,
1717  convert(ba_crse, IntVect(0,0,1)), dm_crse, geom[lev-1],
1718  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1719 }
int cf_set_width
Definition: ERF.H:647

◆ DataLog()

AMREX_FORCE_INLINE std::ostream& ERF::DataLog ( int  i)
inlineprivate
1001  {
1002  return *datalog[i];
1003  }
amrex::Vector< std::unique_ptr< std::fstream > > datalog
Definition: ERF.H:1131

◆ DataLogName()

std::string ERF::DataLogName ( int  i) const
inlineprivatenoexcept

The filename of the ith datalog file.

1143 { return datalogname[i]; }
amrex::Vector< std::string > datalogname
Definition: ERF.H:1132

◆ Define_ERFFillPatchers()

void ERF::Define_ERFFillPatchers ( int  lev)
private
1723 {
1724  auto& fine_new = vars_new[lev];
1725  auto& crse_new = vars_new[lev-1];
1726  auto& ba_fine = fine_new[Vars::cons].boxArray();
1727  auto& ba_crse = crse_new[Vars::cons].boxArray();
1728  auto& dm_fine = fine_new[Vars::cons].DistributionMap();
1729  auto& dm_crse = crse_new[Vars::cons].DistributionMap();
1730 
1731  int ncomp = fine_new[Vars::cons].nComp();
1732 
1733  FPr_c[lev-1].Define(ba_fine, dm_fine, geom[lev] ,
1734  ba_crse, dm_crse, geom[lev-1],
1735  -cf_width, -cf_set_width, ncomp, &cell_cons_interp);
1736  FPr_u[lev-1].Define(convert(ba_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
1737  convert(ba_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
1738  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1739  FPr_v[lev-1].Define(convert(ba_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
1740  convert(ba_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
1741  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1742  FPr_w[lev-1].Define(convert(ba_fine, IntVect(0,0,1)), dm_fine, geom[lev] ,
1743  convert(ba_crse, IntVect(0,0,1)), dm_crse, geom[lev-1],
1744  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1745 }

◆ derive_diag_profiles()

void ERF::derive_diag_profiles ( amrex::Gpu::HostVector< amrex::Real > &  h_avg_u,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_v,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_w,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_rho,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_th,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_ksgs,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qc,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qr,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wqv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wqc,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wqr,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uu,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uw,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_vv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_vw,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_ww,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_vth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_thth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_ku,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_kv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_kw,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_p,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_pu,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_pv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_pw 
)

Computes the profiles for diagnostic quantities.

Parameters
h_avg_uProfile for x-velocity on Host
h_avg_vProfile for y-velocity on Host
h_avg_wProfile for z-velocity on Host
h_avg_rhoProfile for density on Host
h_avg_thProfile for potential temperature on Host
h_avg_ksgsProfile for Kinetic Energy on Host
h_avg_uuProfile for x-velocity squared on Host
h_avg_uvProfile for x-velocity * y-velocity on Host
h_avg_uwProfile for x-velocity * z-velocity on Host
h_avg_vvProfile for y-velocity squared on Host
h_avg_vwProfile for y-velocity * z-velocity on Host
h_avg_wwProfile for z-velocity squared on Host
h_avg_uthProfile for x-velocity * potential temperature on Host
h_avg_uiuiuProfile for u_i*u_i*u triple product on Host
h_avg_uiuivProfile for u_i*u_i*v triple product on Host
h_avg_uiuiwProfile for u_i*u_i*w triple product on Host
h_avg_pProfile for pressure perturbation on Host
h_avg_puProfile for pressure perturbation * x-velocity on Host
h_avg_pvProfile for pressure perturbation * y-velocity on Host
h_avg_pwProfile for pressure perturbation * z-velocity on Host
180 {
181  // We assume that this is always called at level 0
182  int lev = 0;
183 
184  bool l_use_KE = (solverChoice.turbChoice[lev].les_type == LESType::Deardorff);
185  bool l_use_QKE = solverChoice.turbChoice[lev].use_QKE && solverChoice.turbChoice[lev].advect_QKE;
186 
187  // This will hold rho, theta, ksgs, uu, uv, uw, vv, vw, ww, uth, vth, wth,
188  // 0 1 2 3 4 5 6 7 8 9 10 11
189  // thth, uiuiu, uiuiv, uiuiw, p, pu, pv, pw, qv, qc, qr, wqv, wqc, wqr
190  // 12 13 14 15 16 17 18 19 20 21 22 23 24 25
191  MultiFab mf_out(grids[lev], dmap[lev], 26, 0);
192 
193  MultiFab mf_vels(grids[lev], dmap[lev], AMREX_SPACEDIM, 0);
194 
195  MultiFab u_cc(mf_vels, make_alias, 0, 1); // u at cell centers
196  MultiFab v_cc(mf_vels, make_alias, 1, 1); // v at cell centers
197  MultiFab w_cc(mf_vels, make_alias, 2, 1); // w at cell centers
198 
199  average_face_to_cellcenter(mf_vels,0,
200  Array<const MultiFab*,3>{&vars_new[lev][Vars::xvel],&vars_new[lev][Vars::yvel],&vars_new[lev][Vars::zvel]});
201 
202  int zdir = 2;
203  auto domain = geom[0].Domain();
204 
205  // Sum in the horizontal plane
206  h_avg_u = sumToLine(mf_vels ,0,1,domain,zdir);
207  h_avg_v = sumToLine(mf_vels ,1,1,domain,zdir);
208  h_avg_w = sumToLine(mf_vels ,2,1,domain,zdir);
209 
210  int hu_size = h_avg_u.size();
211 
212  // Divide by the total number of cells we are averaging over
213  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
214  for (int k = 0; k < hu_size; ++k) {
215  h_avg_u[k] /= area_z; h_avg_v[k] /= area_z; h_avg_w[k] /= area_z;
216  }
217 
218  int nvars = vars_new[lev][Vars::cons].nComp();
219  MultiFab mf_cons(vars_new[lev][Vars::cons], make_alias, 0, nvars);
220 
221  MultiFab p_hse (base_state[lev], make_alias, 1, 1); // p_0 is second component
222 
223  bool use_moisture = (solverChoice.moisture_type != MoistureType::None);
224 
225  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
226  {
227  const Box& bx = mfi.tilebox();
228  const Array4<Real>& fab_arr = mf_out.array(mfi);
229  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
230  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
231  const Array4<Real>& w_cc_arr = w_cc.array(mfi);
232  const Array4<Real>& cons_arr = mf_cons.array(mfi);
233  const Array4<Real>& p0_arr = p_hse.array(mfi);
234 
235  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
236  {
237  Real theta = cons_arr(i,j,k,RhoTheta_comp) / cons_arr(i,j,k,Rho_comp);
238  fab_arr(i, j, k, 0) = cons_arr(i,j,k,Rho_comp);
239  fab_arr(i, j, k, 1) = theta;
240  Real ksgs = 0.0;
241  if (l_use_KE)
242  ksgs = cons_arr(i,j,k,RhoKE_comp) / cons_arr(i,j,k,Rho_comp);
243  else if (l_use_QKE)
244  ksgs = cons_arr(i,j,k,RhoQKE_comp) / cons_arr(i,j,k,Rho_comp);
245  fab_arr(i, j, k, 2) = ksgs;
246  fab_arr(i, j, k, 3) = u_cc_arr(i,j,k) * u_cc_arr(i,j,k); // u*u
247  fab_arr(i, j, k, 4) = u_cc_arr(i,j,k) * v_cc_arr(i,j,k); // u*v
248  fab_arr(i, j, k, 5) = u_cc_arr(i,j,k) * w_cc_arr(i,j,k); // u*w
249  fab_arr(i, j, k, 6) = v_cc_arr(i,j,k) * v_cc_arr(i,j,k); // v*v
250  fab_arr(i, j, k, 7) = v_cc_arr(i,j,k) * w_cc_arr(i,j,k); // v*w
251  fab_arr(i, j, k, 8) = w_cc_arr(i,j,k) * w_cc_arr(i,j,k); // w*w
252  fab_arr(i, j, k, 9) = u_cc_arr(i,j,k) * theta; // u*th
253  fab_arr(i, j, k,10) = v_cc_arr(i,j,k) * theta; // v*th
254  fab_arr(i, j, k,11) = w_cc_arr(i,j,k) * theta; // w*th
255  fab_arr(i, j, k,12) = theta * theta; // th*th
256  Real uiui = fab_arr(i,j,k,3) + fab_arr(i,j,k,6) + fab_arr(i,j,k,8);
257  fab_arr(i, j, k,13) = uiui * u_cc_arr(i,j,k); // (ui*ui)*u
258  fab_arr(i, j, k,14) = uiui * v_cc_arr(i,j,k); // (ui*ui)*v
259  fab_arr(i, j, k,15) = uiui * w_cc_arr(i,j,k); // (ui*ui)*w
260 
261  if (!use_moisture) {
262  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp));
263  p -= p0_arr(i,j,k);
264  fab_arr(i, j, k,16) = p; // p'
265  fab_arr(i, j, k,17) = p * u_cc_arr(i,j,k); // p'*u
266  fab_arr(i, j, k,18) = p * v_cc_arr(i,j,k); // p'*v
267  fab_arr(i, j, k,19) = p * w_cc_arr(i,j,k); // p'*w
268  fab_arr(i, j, k,20) = 0.; // qv
269  fab_arr(i, j, k,21) = 0.; // qc
270  fab_arr(i, j, k,22) = 0.; // qr
271  fab_arr(i, j, k,23) = 0.; // w*qv
272  fab_arr(i, j, k,24) = 0.; // w*qc
273  fab_arr(i, j, k,25) = 0.; // w*qr
274  }
275  });
276  } // mfi
277 
278  if (use_moisture)
279  {
280  int RhoQr_comp;
281  int n_qstate = micro->Get_Qstate_Size();
282  if (n_qstate > 3) {
283  RhoQr_comp = RhoQ4_comp;
284  } else {
285  RhoQr_comp = RhoQ3_comp;
286  }
287 
288  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
289  {
290  const Box& bx = mfi.tilebox();
291  const Array4<Real>& fab_arr = mf_out.array(mfi);
292  const Array4<Real>& cons_arr = mf_cons.array(mfi);
293  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
294  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
295  const Array4<Real>& w_cc_arr = w_cc.array(mfi);
296  const Array4<Real>& p0_arr = p_hse.array(mfi);
297  const Array4<Real>& qv_arr = qmoist[0][0]->array(mfi); // TODO: Is this written only on lev 0?
298 
299  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
300  {
301  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_arr(i,j,k));
302 
303  p -= p0_arr(i,j,k);
304  fab_arr(i, j, k,16) = p; // p'
305  fab_arr(i, j, k,17) = p * u_cc_arr(i,j,k); // p'*u
306  fab_arr(i, j, k,18) = p * v_cc_arr(i,j,k); // p'*v
307  fab_arr(i, j, k,19) = p * w_cc_arr(i,j,k); // p'*w
308  fab_arr(i, j, k,20) = cons_arr(i,j,k,RhoQ1_comp) / cons_arr(i,j,k,Rho_comp); // qv
309  fab_arr(i, j, k,21) = cons_arr(i,j,k,RhoQ2_comp) / cons_arr(i,j,k,Rho_comp); // qc
310  fab_arr(i, j, k,22) = cons_arr(i,j,k,RhoQr_comp) / cons_arr(i,j,k,Rho_comp); // qr
311  fab_arr(i, j, k,23) = w_cc_arr(i,j,k) * cons_arr(i,j,k,RhoQ1_comp) / cons_arr(i,j,k,Rho_comp); // w*qv
312  fab_arr(i, j, k,24) = w_cc_arr(i,j,k) * cons_arr(i,j,k,RhoQ2_comp) / cons_arr(i,j,k,Rho_comp); // w*qc
313  fab_arr(i, j, k,25) = w_cc_arr(i,j,k) * cons_arr(i,j,k,RhoQr_comp) / cons_arr(i,j,k,Rho_comp); // w*qr
314  });
315  } // mfi
316  } // use_moisture
317 
318  h_avg_rho = sumToLine(mf_out, 0,1,domain,zdir);
319  h_avg_th = sumToLine(mf_out, 1,1,domain,zdir);
320  h_avg_ksgs = sumToLine(mf_out, 2,1,domain,zdir);
321  h_avg_uu = sumToLine(mf_out, 3,1,domain,zdir);
322  h_avg_uv = sumToLine(mf_out, 4,1,domain,zdir);
323  h_avg_uw = sumToLine(mf_out, 5,1,domain,zdir);
324  h_avg_vv = sumToLine(mf_out, 6,1,domain,zdir);
325  h_avg_vw = sumToLine(mf_out, 7,1,domain,zdir);
326  h_avg_ww = sumToLine(mf_out, 8,1,domain,zdir);
327  h_avg_uth = sumToLine(mf_out, 9,1,domain,zdir);
328  h_avg_vth = sumToLine(mf_out,10,1,domain,zdir);
329  h_avg_wth = sumToLine(mf_out,11,1,domain,zdir);
330  h_avg_thth = sumToLine(mf_out,12,1,domain,zdir);
331  h_avg_uiuiu= sumToLine(mf_out,13,1,domain,zdir);
332  h_avg_uiuiv= sumToLine(mf_out,14,1,domain,zdir);
333  h_avg_uiuiw= sumToLine(mf_out,15,1,domain,zdir);
334  h_avg_p = sumToLine(mf_out,16,1,domain,zdir);
335  h_avg_pu = sumToLine(mf_out,17,1,domain,zdir);
336  h_avg_pv = sumToLine(mf_out,18,1,domain,zdir);
337  h_avg_pw = sumToLine(mf_out,19,1,domain,zdir);
338  h_avg_qv = sumToLine(mf_out,20,1,domain,zdir);
339  h_avg_qc = sumToLine(mf_out,21,1,domain,zdir);
340  h_avg_qr = sumToLine(mf_out,22,1,domain,zdir);
341  h_avg_wqv = sumToLine(mf_out,23,1,domain,zdir);
342  h_avg_wqc = sumToLine(mf_out,24,1,domain,zdir);
343  h_avg_wqr = sumToLine(mf_out,25,1,domain,zdir);
344 
345  // Divide by the total number of cells we are averaging over
346  int h_avg_u_size = static_cast<int>(h_avg_u.size());
347  for (int k = 0; k < h_avg_u_size; ++k) {
348  h_avg_rho[k] /= area_z; h_avg_ksgs[k] /= area_z;
349  h_avg_th[k] /= area_z; h_avg_thth[k] /= area_z;
350  h_avg_uu[k] /= area_z; h_avg_uv[k] /= area_z; h_avg_uw[k] /= area_z;
351  h_avg_vv[k] /= area_z; h_avg_vw[k] /= area_z; h_avg_ww[k] /= area_z;
352  h_avg_uth[k] /= area_z; h_avg_vth[k] /= area_z; h_avg_wth[k] /= area_z;
353  h_avg_uiuiu[k] /= area_z;
354  h_avg_uiuiv[k] /= area_z;
355  h_avg_uiuiw[k] /= area_z;
356  h_avg_p[k] /= area_z;
357  h_avg_pu[k] /= area_z; h_avg_pv[k] /= area_z; h_avg_pw[k] /= area_z;
358  h_avg_qv[k] /= area_z; h_avg_qc[k] /= area_z; h_avg_qr[k] /= area_z;
359  h_avg_wqv[k] /= area_z; h_avg_wqc[k] /= area_z; h_avg_wqr[k] /= area_z;
360  }
361 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=0.)
Definition: EOS.H:62
#define RhoQ4_comp
Definition: IndexDefines.H:20
#define RhoQ2_comp
Definition: IndexDefines.H:18
#define RhoQ3_comp
Definition: IndexDefines.H:19
#define RhoQKE_comp
Definition: IndexDefines.H:15
#define RhoKE_comp
Definition: IndexDefines.H:14
@ theta
Definition: MM5.H:20
Here is the call graph for this function:

◆ derive_diag_profiles_stag()

void ERF::derive_diag_profiles_stag ( amrex::Gpu::HostVector< amrex::Real > &  h_avg_u,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_v,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_w,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_rho,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_th,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_ksgs,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uu,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uw,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_vv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_vw,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_ww,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_uth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_vth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_thth,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_ku,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_kv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_kw,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_p,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_pu,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_pv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_pw 
)

Computes the profiles for diagnostic quantities at staggered heights.

Parameters
h_avg_uProfile for x-velocity on Host
h_avg_vProfile for y-velocity on Host
h_avg_wProfile for z-velocity on Host
h_avg_rhoProfile for density on Host
h_avg_thProfile for potential temperature on Host
h_avg_ksgsProfile for Kinetic Energy on Host
h_avg_uuProfile for x-velocity squared on Host
h_avg_uvProfile for x-velocity * y-velocity on Host
h_avg_uwProfile for x-velocity * z-velocity on Host
h_avg_vvProfile for y-velocity squared on Host
h_avg_vwProfile for y-velocity * z-velocity on Host
h_avg_wwProfile for z-velocity squared on Host
h_avg_uthProfile for x-velocity * potential temperature on Host
h_avg_uiuiuProfile for u_i*u_i*u triple product on Host
h_avg_uiuivProfile for u_i*u_i*v triple product on Host
h_avg_uiuiwProfile for u_i*u_i*w triple product on Host
h_avg_pProfile for pressure perturbation on Host
h_avg_puProfile for pressure perturbation * x-velocity on Host
h_avg_pvProfile for pressure perturbation * y-velocity on Host
h_avg_pwProfile for pressure perturbation * z-velocity on Host
270 {
271  // We assume that this is always called at level 0
272  int lev = 0;
273 
274  bool l_use_KE = (solverChoice.turbChoice[lev].les_type == LESType::Deardorff);
275  bool l_use_QKE = solverChoice.turbChoice[lev].use_QKE && solverChoice.turbChoice[lev].advect_QKE;
276 
277  // This will hold rho, theta, ksgs, uu, uv, vv, uth, vth, thth, uiuiu, uiuiv, p, pu, pv
278  // index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
279  MultiFab mf_out(grids[lev], dmap[lev], 14, 0);
280 
281  // This will hold uw, vw, ww, wth, uiuiw, pw (note: uiui == u_i*u_i = u*u + v*v + w*w)
282  // index: 0 1 2 3 4 5
283  MultiFab mf_out_stag(convert(grids[lev], IntVect(0,0,1)), dmap[lev], 6, 0);
284 
285  // This is only used to average u and v
286  MultiFab mf_vels(grids[lev], dmap[lev], 2, 0);
287 
288  MultiFab u_cc(mf_vels, make_alias, 0, 1); // u at cell centers
289  MultiFab v_cc(mf_vels, make_alias, 1, 1); // v at cell centers
290  MultiFab w_fc(vars_new[lev][Vars::zvel], make_alias, 0, 1); // w at face centers
291 
292  int zdir = 2;
293  auto domain = geom[0].Domain();
294  Box stag_domain = domain;
295  stag_domain.convert(IntVect(0,0,1));
296 
297  int nvars = vars_new[lev][Vars::cons].nComp();
298  MultiFab mf_cons(vars_new[lev][Vars::cons], make_alias, 0, nvars);
299 
300  MultiFab p_hse (base_state[lev], make_alias, 1, 1); // p_0 is second component
301 
302  bool use_moisture = (solverChoice.moisture_type != MoistureType::None);
303 
304  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
305  {
306  const Box& bx = mfi.tilebox();
307  const Array4<Real>& fab_arr = mf_out.array(mfi);
308  const Array4<Real>& fab_arr_stag = mf_out_stag.array(mfi);
309  const Array4<Real>& u_arr = vars_new[lev][Vars::xvel].array(mfi);
310  const Array4<Real>& v_arr = vars_new[lev][Vars::yvel].array(mfi);
311  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
312  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
313  const Array4<Real>& w_fc_arr = w_fc.array(mfi);
314  const Array4<Real>& cons_arr = mf_cons.array(mfi);
315  const Array4<Real>& p0_arr = p_hse.array(mfi);
316 
317  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
318  {
319  u_cc_arr(i,j,k) = 0.5 * (u_arr(i,j,k) + u_arr(i+1,j ,k));
320  v_cc_arr(i,j,k) = 0.5 * (v_arr(i,j,k) + v_arr(i ,j+1,k));
321 
322  Real theta = cons_arr(i,j,k,RhoTheta_comp) / cons_arr(i,j,k,Rho_comp);
323  fab_arr(i, j, k, 0) = cons_arr(i,j,k,Rho_comp);
324  fab_arr(i, j, k, 1) = theta;
325  Real ksgs = 0.0;
326  if (l_use_KE)
327  ksgs = cons_arr(i,j,k,RhoKE_comp) / cons_arr(i,j,k,Rho_comp);
328  else if (l_use_QKE)
329  ksgs = cons_arr(i,j,k,RhoQKE_comp) / cons_arr(i,j,k,Rho_comp);
330  fab_arr(i, j, k, 2) = ksgs;
331  fab_arr(i, j, k, 3) = u_cc_arr(i,j,k) * u_cc_arr(i,j,k); // u*u
332  fab_arr(i, j, k, 4) = u_cc_arr(i,j,k) * v_cc_arr(i,j,k); // u*v
333  fab_arr(i, j, k, 5) = v_cc_arr(i,j,k) * v_cc_arr(i,j,k); // v*v
334  fab_arr(i, j, k, 6) = u_cc_arr(i,j,k) * theta; // u*th
335  fab_arr(i, j, k, 7) = v_cc_arr(i,j,k) * theta; // v*th
336  fab_arr(i, j, k, 8) = theta * theta; // th*th
337 
338  Real wcc = 0.5 * (w_fc_arr(i,j,k) + w_fc_arr(i,j,k+1));
339  Real uiui = fab_arr(i,j,k,3) + fab_arr(i,j,k,5) + wcc*wcc;
340  fab_arr(i, j, k,9 ) = uiui * u_cc_arr(i,j,k); // (ui*ui)*u
341  fab_arr(i, j, k,10) = uiui * v_cc_arr(i,j,k); // (ui*ui)*v
342 
343  if (!use_moisture) {
344  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp));
345  p -= p0_arr(i,j,k);
346  fab_arr(i, j, k,11) = p; // p'
347  fab_arr(i, j, k,12) = p * u_cc_arr(i,j,k); // p'*u
348  fab_arr(i, j, k,13) = p * v_cc_arr(i,j,k); // p'*v
349  }
350  });
351 
352  const Box& zbx = mfi.tilebox(IntVect(0,0,1));
353  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
354  {
355  // average to z faces (first to cell centers, then in z)
356  Real uface = 0.25 * ( u_arr(i ,j,k) + u_arr(i ,j,k-1)
357  + u_arr(i+1,j,k) + u_arr(i+1,j,k-1));
358  Real vface = 0.25 * ( v_arr(i,j ,k) + v_arr(i,j ,k-1)
359  + v_arr(i,j+1,k) + v_arr(i,j+1,k-1));
360  Real theta0 = cons_arr(i,j,k ,RhoTheta_comp) / cons_arr(i,j,k ,Rho_comp);
361  Real theta1 = cons_arr(i,j,k-1,RhoTheta_comp) / cons_arr(i,j,k-1,Rho_comp);
362  Real thface = 0.5*(theta0 + theta1);
363  fab_arr_stag(i,j,k,0) = uface * w_fc_arr(i,j,k); // u*w
364  fab_arr_stag(i,j,k,1) = vface * w_fc_arr(i,j,k); // v*w
365  fab_arr_stag(i,j,k,2) = w_fc_arr(i,j,k) * w_fc_arr(i,j,k); // w*w
366  fab_arr_stag(i,j,k,3) = thface * w_fc_arr(i,j,k); // th*w
367  Real uiui = uface*uface + vface*vface + fab_arr_stag(i,j,k,2);
368  fab_arr_stag(i,j,k,4) = uiui * w_fc_arr(i,j,k); // (ui*ui)*w
369  if (!use_moisture) {
370  Real p0 = getPgivenRTh(cons_arr(i, j, k , RhoTheta_comp)) - p0_arr(i,j,k );
371  Real p1 = getPgivenRTh(cons_arr(i, j, k-1, RhoTheta_comp)) - p0_arr(i,j,k-1);
372  Real pface = 0.5 * (p0 + p1);
373  fab_arr_stag(i,j,k,5) = pface * w_fc_arr(i,j,k); // p'*w
374  }
375  });
376 
377  } // mfi
378 
379  if (use_moisture)
380  {
381  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
382  {
383  const Box& bx = mfi.tilebox();
384  const Array4<Real>& fab_arr = mf_out.array(mfi);
385  const Array4<Real>& fab_arr_stag = mf_out_stag.array(mfi);
386  const Array4<Real>& cons_arr = mf_cons.array(mfi);
387  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
388  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
389  const Array4<Real>& w_fc_arr = w_fc.array(mfi);
390  const Array4<Real>& p0_arr = p_hse.array(mfi);
391  const Array4<Real>& qv_arr = qmoist[0][0]->array(mfi); // TODO: Is this written only on lev 0?
392 
393  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
394  {
395  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_arr(i,j,k));
396  p -= p0_arr(i,j,k);
397  fab_arr(i, j, k,11) = p; // p'
398  fab_arr(i, j, k,12) = p * u_cc_arr(i,j,k); // p'*u
399  fab_arr(i, j, k,13) = p * v_cc_arr(i,j,k); // p'*v
400  });
401 
402  const Box& zbx = mfi.tilebox(IntVect(0,0,1));
403  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
404  {
405  Real p0 = getPgivenRTh(cons_arr(i, j, k , RhoTheta_comp), qv_arr(i,j,k )) - p0_arr(i,j,k );
406  Real p1 = getPgivenRTh(cons_arr(i, j, k-1, RhoTheta_comp), qv_arr(i,j,k-1)) - p0_arr(i,j,k-1);
407  Real pface = 0.5 * (p0 + p1);
408  fab_arr_stag(i,j,k,5) = pface * w_fc_arr(i,j,k); // p'*w
409  });
410  } // mfi
411  } // use_moisture
412 
413  // Sum in the horizontal plane
414  h_avg_u = sumToLine(u_cc,0,1, domain,zdir);
415  h_avg_v = sumToLine(v_cc,0,1, domain,zdir);
416  h_avg_w = sumToLine(w_fc,0,1,stag_domain,zdir);
417 
418  h_avg_rho = sumToLine(mf_out, 0,1,domain,zdir);
419  h_avg_th = sumToLine(mf_out, 1,1,domain,zdir);
420  h_avg_ksgs = sumToLine(mf_out, 2,1,domain,zdir);
421  h_avg_uu = sumToLine(mf_out, 3,1,domain,zdir);
422  h_avg_uv = sumToLine(mf_out, 4,1,domain,zdir);
423  h_avg_vv = sumToLine(mf_out, 5,1,domain,zdir);
424  h_avg_uth = sumToLine(mf_out, 6,1,domain,zdir);
425  h_avg_vth = sumToLine(mf_out, 7,1,domain,zdir);
426  h_avg_thth = sumToLine(mf_out, 8,1,domain,zdir);
427  h_avg_uiuiu= sumToLine(mf_out, 9,1,stag_domain,zdir);
428  h_avg_uiuiv= sumToLine(mf_out,10,1,stag_domain,zdir);
429  h_avg_p = sumToLine(mf_out,11,1,domain,zdir);
430  h_avg_pu = sumToLine(mf_out,12,1,domain,zdir);
431  h_avg_pv = sumToLine(mf_out,13,1,domain,zdir);
432 
433  h_avg_uw = sumToLine(mf_out_stag,0,1,stag_domain,zdir);
434  h_avg_vw = sumToLine(mf_out_stag,1,1,stag_domain,zdir);
435  h_avg_ww = sumToLine(mf_out_stag,2,1,stag_domain,zdir);
436  h_avg_wth = sumToLine(mf_out_stag,3,1,stag_domain,zdir);
437  h_avg_uiuiw= sumToLine(mf_out_stag,4,1,stag_domain,zdir);
438  h_avg_pw = sumToLine(mf_out_stag,5,1,stag_domain,zdir);
439 
440  // Divide by the total number of cells we are averaging over
441  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
442  int unstag_size = h_avg_w.size() - 1; // _un_staggered heights
443  for (int k = 0; k < unstag_size; ++k) {
444  h_avg_u[k] /= area_z;
445  h_avg_v[k] /= area_z;
446  h_avg_rho[k] /= area_z;
447  h_avg_ksgs[k] /= area_z;
448  h_avg_th[k] /= area_z;
449  h_avg_thth[k] /= area_z;
450  h_avg_uu[k] /= area_z;
451  h_avg_uv[k] /= area_z;
452  h_avg_vv[k] /= area_z;
453  h_avg_uth[k] /= area_z;
454  h_avg_vth[k] /= area_z;
455  h_avg_uiuiu[k] /= area_z;
456  h_avg_uiuiv[k] /= area_z;
457  h_avg_p[k] /= area_z;
458  h_avg_pu[k] /= area_z;
459  h_avg_pv[k] /= area_z;
460  }
461 
462  for (int k = 0; k < unstag_size+1; ++k) { // staggered heights
463  h_avg_w[k] /= area_z;
464  h_avg_uw[k] /= area_z;
465  h_avg_vw[k] /= area_z;
466  h_avg_ww[k] /= area_z;
467  h_avg_wth[k] /= area_z;
468  h_avg_uiuiw[k] /= area_z;
469  h_avg_pw[k] /= area_z;
470  }
471 }
Here is the call graph for this function:

◆ derive_stress_profiles()

void ERF::derive_stress_profiles ( amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau11,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau12,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau13,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau22,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau23,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau33,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_hfx3,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_diss 
)
367 {
368  int lev = 0;
369 
370  // This will hold the stress tensor components
371  MultiFab mf_out(grids[lev], dmap[lev], 8, 0);
372 
373  for ( MFIter mfi(mf_out,TilingIfNotGPU()); mfi.isValid(); ++mfi)
374  {
375  const Box& bx = mfi.tilebox();
376  const Array4<Real>& fab_arr = mf_out.array(mfi);
377 
378  // NOTE: These are from the last RK stage...
379  const Array4<const Real>& tau11_arr = Tau11_lev[lev]->const_array(mfi);
380  const Array4<const Real>& tau12_arr = Tau12_lev[lev]->const_array(mfi);
381  const Array4<const Real>& tau13_arr = Tau13_lev[lev]->const_array(mfi);
382  const Array4<const Real>& tau22_arr = Tau22_lev[lev]->const_array(mfi);
383  const Array4<const Real>& tau23_arr = Tau23_lev[lev]->const_array(mfi);
384  const Array4<const Real>& tau33_arr = Tau33_lev[lev]->const_array(mfi);
385 
386  // These should be re-calculated during ERF_slow_rhs_post
387  // -- just vertical SFS kinematic heat flux for now
388  //const Array4<const Real>& hfx1_arr = SFS_hfx1_lev[lev]->const_array(mfi);
389  //const Array4<const Real>& hfx2_arr = SFS_hfx2_lev[lev]->const_array(mfi);
390  const Array4<const Real>& hfx3_arr = SFS_hfx3_lev[lev]->const_array(mfi);
391  const Array4<const Real>& diss_arr = SFS_diss_lev[lev]->const_array(mfi);
392 
393  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
394  {
395  fab_arr(i, j, k, 0) = tau11_arr(i,j,k);
396  fab_arr(i, j, k, 1) = 0.25 * ( tau12_arr(i,j ,k) + tau12_arr(i+1,j ,k)
397  + tau12_arr(i,j+1,k) + tau12_arr(i+1,j+1,k) );
398  fab_arr(i, j, k, 2) = 0.25 * ( tau13_arr(i,j,k ) + tau13_arr(i+1,j,k)
399  + tau13_arr(i,j,k+1) + tau13_arr(i+1,j,k+1) );
400  fab_arr(i, j, k, 3) = tau22_arr(i,j,k);
401  fab_arr(i, j, k, 4) = 0.25 * ( tau23_arr(i,j,k ) + tau23_arr(i,j+1,k)
402  + tau23_arr(i,j,k+1) + tau23_arr(i,j+1,k+1) );
403  fab_arr(i, j, k, 5) = tau33_arr(i,j,k);
404  fab_arr(i, j, k, 6) = hfx3_arr(i,j,k);
405  fab_arr(i, j, k, 7) = diss_arr(i,j,k);
406  });
407  }
408 
409  int zdir = 2;
410  auto domain = geom[0].Domain();
411 
412  h_avg_tau11 = sumToLine(mf_out,0,1,domain,zdir);
413  h_avg_tau12 = sumToLine(mf_out,1,1,domain,zdir);
414  h_avg_tau13 = sumToLine(mf_out,2,1,domain,zdir);
415  h_avg_tau22 = sumToLine(mf_out,3,1,domain,zdir);
416  h_avg_tau23 = sumToLine(mf_out,4,1,domain,zdir);
417  h_avg_tau33 = sumToLine(mf_out,5,1,domain,zdir);
418  h_avg_hfx3 = sumToLine(mf_out,6,1,domain,zdir);
419  h_avg_diss = sumToLine(mf_out,7,1,domain,zdir);
420 
421  int ht_size = h_avg_tau11.size();
422 
423  // Divide by the total number of cells we are averaging over
424  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
425  for (int k = 0; k < ht_size; ++k) {
426  h_avg_tau11[k] /= area_z; h_avg_tau12[k] /= area_z; h_avg_tau13[k] /= area_z;
427  h_avg_tau22[k] /= area_z; h_avg_tau23[k] /= area_z; h_avg_tau33[k] /= area_z;
428  h_avg_hfx3[k] /= area_z;
429  h_avg_diss[k] /= area_z;
430  }
431 }

◆ derive_stress_profiles_stag()

void ERF::derive_stress_profiles_stag ( amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau11,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau12,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau13,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau22,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau23,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_tau33,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_hfx3,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_diss 
)
478 {
479  int lev = 0;
480 
481  // This will hold the stress tensor components
482  MultiFab mf_out(grids[lev], dmap[lev], 8, 0);
483 
484  // This will hold Tau13 and Tau23
485  MultiFab mf_out_stag(convert(grids[lev], IntVect(0,0,1)), dmap[lev], 2, 0);
486 
487  for ( MFIter mfi(mf_out,TilingIfNotGPU()); mfi.isValid(); ++mfi)
488  {
489  const Box& bx = mfi.tilebox();
490  const Array4<Real>& fab_arr = mf_out.array(mfi);
491  const Array4<Real>& fab_arr_stag = mf_out_stag.array(mfi);
492 
493  // NOTE: These are from the last RK stage...
494  const Array4<const Real>& tau11_arr = Tau11_lev[lev]->const_array(mfi);
495  const Array4<const Real>& tau12_arr = Tau12_lev[lev]->const_array(mfi);
496  const Array4<const Real>& tau13_arr = Tau13_lev[lev]->const_array(mfi);
497  const Array4<const Real>& tau22_arr = Tau22_lev[lev]->const_array(mfi);
498  const Array4<const Real>& tau23_arr = Tau23_lev[lev]->const_array(mfi);
499  const Array4<const Real>& tau33_arr = Tau33_lev[lev]->const_array(mfi);
500 
501  // These should be re-calculated during ERF_slow_rhs_post
502  // -- just vertical SFS kinematic heat flux for now
503  //const Array4<const Real>& hfx1_arr = SFS_hfx1_lev[lev]->const_array(mfi);
504  //const Array4<const Real>& hfx2_arr = SFS_hfx2_lev[lev]->const_array(mfi);
505  const Array4<const Real>& hfx3_arr = SFS_hfx3_lev[lev]->const_array(mfi);
506  const Array4<const Real>& diss_arr = SFS_diss_lev[lev]->const_array(mfi);
507 
508  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
509  {
510  fab_arr(i, j, k, 0) = tau11_arr(i,j,k);
511  fab_arr(i, j, k, 1) = 0.25 * ( tau12_arr(i,j ,k) + tau12_arr(i+1,j ,k)
512  + tau12_arr(i,j+1,k) + tau12_arr(i+1,j+1,k) );
513 // fab_arr(i, j, k, 2) = 0.25 * ( tau13_arr(i,j,k ) + tau13_arr(i+1,j,k)
514 // + tau13_arr(i,j,k+1) + tau13_arr(i+1,j,k+1) );
515  fab_arr(i, j, k, 3) = tau22_arr(i,j,k);
516 // fab_arr(i, j, k, 4) = 0.25 * ( tau23_arr(i,j,k ) + tau23_arr(i,j+1,k)
517 // + tau23_arr(i,j,k+1) + tau23_arr(i,j+1,k+1) );
518  fab_arr(i, j, k, 5) = tau33_arr(i,j,k);
519  fab_arr(i, j, k, 6) = hfx3_arr(i,j,k);
520  fab_arr(i, j, k, 7) = diss_arr(i,j,k);
521  });
522 
523  const Box& zbx = mfi.tilebox(IntVect(0,0,1));
524  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
525  {
526  fab_arr_stag(i,j,k,0) = 0.5*(tau13_arr(i,j,k) + tau13_arr(i+1,j ,k));
527  fab_arr_stag(i,j,k,1) = 0.5*(tau23_arr(i,j,k) + tau23_arr(i ,j+1,k));
528  });
529  }
530 
531  int zdir = 2;
532  auto domain = geom[0].Domain();
533  Box stag_domain = domain;
534  stag_domain.convert(IntVect(0,0,1));
535 
536  h_avg_tau11 = sumToLine(mf_out,0,1,domain,zdir);
537  h_avg_tau12 = sumToLine(mf_out,1,1,domain,zdir);
538 // h_avg_tau13 = sumToLine(mf_out,2,1,domain,zdir);
539  h_avg_tau22 = sumToLine(mf_out,3,1,domain,zdir);
540 // h_avg_tau23 = sumToLine(mf_out,4,1,domain,zdir);
541  h_avg_tau33 = sumToLine(mf_out,5,1,domain,zdir);
542  h_avg_hfx3 = sumToLine(mf_out,6,1,domain,zdir);
543  h_avg_diss = sumToLine(mf_out,7,1,domain,zdir);
544 
545  h_avg_tau13 = sumToLine(mf_out_stag,0,1,stag_domain,zdir);
546  h_avg_tau23 = sumToLine(mf_out_stag,1,1,stag_domain,zdir);
547 
548  int ht_size = h_avg_tau11.size(); // _un_staggered
549 
550  // Divide by the total number of cells we are averaging over
551  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
552  for (int k = 0; k < ht_size; ++k) {
553  h_avg_tau11[k] /= area_z; h_avg_tau12[k] /= area_z;
554  h_avg_tau22[k] /= area_z; h_avg_tau33[k] /= area_z;
555  h_avg_hfx3[k] /= area_z;
556  h_avg_diss[k] /= area_z;
557  }
558  for (int k = 0; k < ht_size+1; ++k) { // staggered heights
559  h_avg_tau13[k] /= area_z;
560  h_avg_tau23[k] /= area_z;
561  }
562 }

◆ derive_upwp()

void ERF::derive_upwp ( amrex::Vector< amrex::Real > &  h_havg)

◆ erf_enforce_hse()

void ERF::erf_enforce_hse ( int  lev,
amrex::MultiFab &  dens,
amrex::MultiFab &  pres,
amrex::MultiFab &  pi,
std::unique_ptr< amrex::MultiFab > &  z_cc 
)

Enforces hydrostatic equilibrium when using terrain.

Parameters
[in]levInteger specifying the current level
[out]densMultiFab storing base state density
[out]presMultiFab storing base state pressure
[out]piMultiFab storing base state Exner function
[in]z_ccPointer to MultiFab storing cell centered z-coordinates
262 {
263  Real l_gravity = solverChoice.gravity;
264  bool l_use_terrain = solverChoice.use_terrain;
265 
266  const auto geomdata = geom[lev].data();
267  const Real dz = geomdata.CellSize(2);
268 
269  const Box& domain = geom[lev].Domain();
270 
271  for ( MFIter mfi(dens, TileNoZ()); mfi.isValid(); ++mfi )
272  {
273  // Create a flat box with same horizontal extent but only one cell in vertical
274  const Box& tbz = mfi.nodaltilebox(2);
275  int klo = tbz.smallEnd(2);
276  int khi = tbz.bigEnd(2);
277 
278  Box b2d = tbz; // Copy constructor
279  b2d.grow(0,1); b2d.grow(1,1); // Grow by one in the lateral directions
280  b2d.setRange(2,0);
281 
282  // We integrate to the first cell (and below) by using rho in this cell
283  // If gravity == 0 this is constant pressure
284  // If gravity != 0, hence this is a wall, this gives gp0 = dens[0] * gravity
285  // (dens_hse*gravity would also be dens[0]*gravity because we use foextrap for rho at k = -1)
286  // Note ng_pres_hse = 1
287 
288  // We start by assuming pressure on the ground is p_0 (in ERF_Constants.H)
289  // Note that gravity is positive
290 
291  Array4<Real> rho_arr = dens.array(mfi);
292  Array4<Real> pres_arr = pres.array(mfi);
293  Array4<Real> pi_arr = pi.array(mfi);
294  Array4<Real> zcc_arr;
295  if (l_use_terrain) {
296  zcc_arr = z_cc->array(mfi);
297  }
298 
299  const Real rdOcp = solverChoice.rdOcp;
300 
301  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int)
302  {
303  // Set value at surface from Newton iteration for rho
304  if (klo == 0) {
305  // Physical height of the terrain at cell center
306  Real hz;
307  if (l_use_terrain) {
308  hz = zcc_arr(i,j,klo);
309  } else {
310  hz = 0.5*dz;
311  }
312 
313  pres_arr(i,j,klo ) = p_0 - hz * rho_arr(i,j,klo) * l_gravity;
314  pi_arr(i,j,klo ) = getExnergivenP(pres_arr(i,j,klo ), rdOcp);
315 
316  // Set ghost cell with dz and rho at boundary
317  pres_arr(i,j,klo-1) = p_0 + hz * rho_arr(i,j,klo) * l_gravity;
318  pi_arr(i,j,klo-1) = getExnergivenP(pres_arr(i,j,klo-1), rdOcp);
319 
320  } else {
321  // If klo > 0, we need to use the value of pres_arr(i,j,klo-1) which was
322  // filled from FillPatch-ing it.
323  Real dz_loc;
324  if (l_use_terrain) {
325  dz_loc = (zcc_arr(i,j,klo) - zcc_arr(i,j,klo-1));
326  } else {
327  dz_loc = dz;
328  }
329  Real dens_interp = 0.5*(rho_arr(i,j,klo) + rho_arr(i,j,klo-1));
330  pres_arr(i,j,klo) = pres_arr(i,j,klo-1) - dz_loc * dens_interp * l_gravity;
331 
332  pi_arr(i,j,klo ) = getExnergivenP(pres_arr(i,j,klo ), rdOcp);
333  pi_arr(i,j,klo-1) = getExnergivenP(pres_arr(i,j,klo-1), rdOcp);
334  }
335 
336  Real dens_interp;
337  if (l_use_terrain) {
338  for (int k = klo+1; k <= khi; k++) {
339  Real dz_loc = (zcc_arr(i,j,k) - zcc_arr(i,j,k-1));
340  dens_interp = 0.5*(rho_arr(i,j,k) + rho_arr(i,j,k-1));
341  pres_arr(i,j,k) = pres_arr(i,j,k-1) - dz_loc * dens_interp * l_gravity;
342  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
343  }
344  } else {
345  for (int k = klo+1; k <= khi; k++) {
346  dens_interp = 0.5*(rho_arr(i,j,k) + rho_arr(i,j,k-1));
347  pres_arr(i,j,k) = pres_arr(i,j,k-1) - dz * dens_interp * l_gravity;
348  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
349  }
350  }
351  });
352 
353  int domlo_x = domain.smallEnd(0); int domhi_x = domain.bigEnd(0);
354  int domlo_y = domain.smallEnd(1); int domhi_y = domain.bigEnd(1);
355 
356  if (pres[mfi].box().smallEnd(0) < domlo_x)
357  {
358  Box bx = mfi.nodaltilebox(2);
359  bx.setSmall(0,domlo_x-1);
360  bx.setBig(0,domlo_x-1);
361  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
362  pres_arr(i,j,k) = pres_arr(domlo_x,j,k);
363  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
364  });
365  }
366 
367  if (pres[mfi].box().bigEnd(0) > domhi_x)
368  {
369  Box bx = mfi.nodaltilebox(2);
370  bx.setSmall(0,domhi_x+1);
371  bx.setBig(0,domhi_x+1);
372  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
373  pres_arr(i,j,k) = pres_arr(domhi_x,j,k);
374  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
375  });
376  }
377 
378  if (pres[mfi].box().smallEnd(1) < domlo_y)
379  {
380  Box bx = mfi.nodaltilebox(2);
381  bx.setSmall(1,domlo_y-1);
382  bx.setBig(1,domlo_y-1);
383  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
384  pres_arr(i,j,k) = pres_arr(i,domlo_y,k);
385  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
386  });
387  }
388 
389  if (pres[mfi].box().bigEnd(1) > domhi_y)
390  {
391  Box bx = mfi.nodaltilebox(2);
392  bx.setSmall(1,domhi_y+1);
393  bx.setBig(1,domhi_y+1);
394  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
395  pres_arr(i,j,k) = pres_arr(i,domhi_y,k);
396  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
397  });
398  }
399  }
400 
401  dens.FillBoundary(geom[lev].periodicity());
402  pres.FillBoundary(geom[lev].periodicity());
403 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getExnergivenP(const amrex::Real P, const amrex::Real rdOcp)
Definition: EOS.H:103
constexpr amrex::Real p_0
Definition: ERF_Constants.H:18
@ pres
Definition: Kessler.H:33
amrex::Real rdOcp
Definition: DataStruct.H:413
Here is the call graph for this function:

◆ ErrorEst()

void ERF::ErrorEst ( int  lev,
amrex::TagBoxArray &  tags,
amrex::Real  time,
int  ngrow 
)
override

Function to tag cells for refinement – this overrides the pure virtual function in AmrCore

Parameters
[in]levclevel of refinement at which we tag cells (0 is coarsest level)
[out]tagsarray of tagged cells
[in]timecurrent time
16 {
17  const int clearval = TagBox::CLEAR;
18  const int tagval = TagBox::SET;
19 
20  for (int j=0; j < ref_tags.size(); ++j)
21  {
22  std::unique_ptr<MultiFab> mf = std::make_unique<MultiFab>(grids[levc], dmap[levc], 1, 0);
23 
24  // This allows dynamic refinement based on the value of the density
25  if (ref_tags[j].Field() == "density")
26  {
27  MultiFab::Copy(*mf,vars_new[levc][Vars::cons],Rho_comp,0,1,0);
28 
29  // This allows dynamic refinement based on the value of qv
30  } else if ( ref_tags[j].Field() == "qv" ) {
31  MultiFab qv(vars_new[levc][Vars::cons],make_alias,0,RhoQ1_comp+1);
32  MultiFab::Copy( *mf, qv, RhoQ1_comp, 0, 1, 0);
33  MultiFab::Divide(*mf, qv, Rho_comp , 0, 1, 0);
34 
35 
36  // This allows dynamic refinement based on the value of qc
37  } else if (ref_tags[j].Field() == "qc" ) {
38  MultiFab qc(vars_new[levc][Vars::cons],make_alias,0,RhoQ2_comp+1);
39  MultiFab::Copy( *mf, qc, RhoQ2_comp, 0, 1, 0);
40  MultiFab::Divide(*mf, qc, Rho_comp , 0, 1, 0);
41 
42 
43  // This allows dynamic refinement based on the value of the scalar/pressure/theta
44  } else if ( (ref_tags[j].Field() == "scalar" ) ||
45  (ref_tags[j].Field() == "pressure") ||
46  (ref_tags[j].Field() == "theta" ) )
47  {
48  for (MFIter mfi(*mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
49  {
50  const Box& bx = mfi.tilebox();
51  auto& dfab = (*mf)[mfi];
52  auto& sfab = vars_new[levc][Vars::cons][mfi];
53  if (ref_tags[j].Field() == "scalar") {
54  derived::erf_derscalar(bx, dfab, 0, 1, sfab, Geom(levc), time, nullptr, levc);
55  } else if (ref_tags[j].Field() == "theta") {
56  derived::erf_dertheta(bx, dfab, 0, 1, sfab, Geom(levc), time, nullptr, levc);
57  }
58  } // mfi
59 #ifdef ERF_USE_PARTICLES
60  } else {
61  //
62  // This allows dynamic refinement based on the number of particles per cell
63  //
64  // Note that we must count all the particles in levels both at and above the current,
65  // since otherwise, e.g., if the particles are all at level 1, counting particles at
66  // level 0 will not trigger refinement when regridding so level 1 will disappear,
67  // then come back at the next regridding
68  //
69  const auto& particles_namelist( particleData.getNames() );
70  mf->setVal(0.0);
71  for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++)
72  {
73  std::string tmp_string(particles_namelist[i]+"_count");
74  IntVect rr = IntVect::TheUnitVector();
75  if (ref_tags[j].Field() == tmp_string) {
76  for (int lev = levc; lev <= finest_level; lev++)
77  {
78  MultiFab temp_dat(grids[lev], dmap[lev], 1, 0); temp_dat.setVal(0);
79  particleData[particles_namelist[i]]->IncrementWithTotal(temp_dat, lev);
80 
81  MultiFab temp_dat_crse(grids[levc], dmap[levc], 1, 0); temp_dat_crse.setVal(0);
82 
83  if (lev == levc) {
84  MultiFab::Copy(*mf, temp_dat, 0, 0, 1, 0);
85  } else {
86  for (int d = 0; d < AMREX_SPACEDIM; d++) {
87  rr[d] *= ref_ratio[levc][d];
88  }
89  average_down(temp_dat, temp_dat_crse, 0, 1, rr);
90  MultiFab::Add(*mf, temp_dat_crse, 0, 0, 1, 0);
91  }
92  }
93  }
94  }
95 #endif
96  }
97 
98  ref_tags[j](tags,mf.get(),clearval,tagval,time,levc,geom[levc]);
99  } // loop over j
100 }
static amrex::Vector< amrex::AMRErrorTag > ref_tags
Definition: ERF.H:943
@ qv
Definition: Kessler.H:36
void erf_derscalar(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:142
void erf_dertheta(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:121
Here is the call graph for this function:

◆ estTimeStep()

Real ERF::estTimeStep ( int  level,
long &  dt_fast_ratio 
) const

Function that calls estTimeStep for each level

Parameters
[in]levellevel of refinement (coarsest level i 0)
[out]dt_fast_ratioratio of slow to fast time step
50 {
51  BL_PROFILE("ERF::estTimeStep()");
52 
53  Real estdt_comp = 1.e20;
54  Real estdt_lowM = 1.e20;
55 
56  auto const dxinv = geom[level].InvCellSizeArray();
57  auto const dzinv = 1.0 / dz_min;
58 
59  MultiFab const& S_new = vars_new[level][Vars::cons];
60 
61  MultiFab ccvel(grids[level],dmap[level],3,0);
62 
63  average_face_to_cellcenter(ccvel,0,
64  Array<const MultiFab*,3>{&vars_new[level][Vars::xvel],
65  &vars_new[level][Vars::yvel],
66  &vars_new[level][Vars::zvel]});
67 
68  int l_no_substepping = solverChoice.no_substepping;
69 
70 #ifdef ERF_USE_EB
71  EBFArrayBoxFactory ebfact = EBFactory(level);
72  const MultiFab& detJ = ebfact.getVolFrac();
73 #endif
74 
75 #ifdef ERF_USE_EB
76  Real estdt_comp_inv = ReduceMax(S_new, ccvel, detJ, 0,
77  [=] AMREX_GPU_HOST_DEVICE (Box const& b,
78  Array4<Real const> const& s,
79  Array4<Real const> const& vf,
80  Array4<Real const> const& u) -> Real
81 #else
82  Real estdt_comp_inv = ReduceMax(S_new, ccvel, 0,
83  [=] AMREX_GPU_HOST_DEVICE (Box const& b,
84  Array4<Real const> const& s,
85  Array4<Real const> const& u) -> Real
86 #endif
87  {
88  Real new_comp_dt = -1.e100;
89  amrex::Loop(b, [=,&new_comp_dt] (int i, int j, int k) noexcept
90  {
91 #ifdef ERF_USE_EB
92  if (vf(i,j,k) > 0.)
93 #endif
94  {
95  const Real rho = s(i, j, k, Rho_comp);
96  const Real rhotheta = s(i, j, k, RhoTheta_comp);
97 
98  // NOTE: even when moisture is present,
99  // we only use the partial pressure of the dry air
100  // to compute the soundspeed
101  Real pressure = getPgivenRTh(rhotheta);
102  Real c = std::sqrt(Gamma * pressure / rho);
103 
104  // If we are not doing the acoustic substepping, then the z-direction contributes
105  // to the computation of the time step
106  if (l_no_substepping) {
107  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0))+c)*dxinv[0]),
108  ((amrex::Math::abs(u(i,j,k,1))+c)*dxinv[1]),
109  ((amrex::Math::abs(u(i,j,k,2))+c)*dzinv ), new_comp_dt);
110 
111  // If we are doing the acoustic substepping, then the z-direction does not contribute
112  // to the computation of the time step
113  } else {
114  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0))+c)*dxinv[0]),
115  ((amrex::Math::abs(u(i,j,k,1))+c)*dxinv[1]), new_comp_dt);
116  }
117  }
118  });
119  return new_comp_dt;
120  });
121 
122  ParallelDescriptor::ReduceRealMax(estdt_comp_inv);
123  estdt_comp = cfl / estdt_comp_inv;
124 
125  Real estdt_lowM_inv = ReduceMax(ccvel, 0,
126  [=] AMREX_GPU_HOST_DEVICE (Box const& b,
127  Array4<Real const> const& u) -> Real
128  {
129  Real new_lm_dt = -1.e100;
130  Loop(b, [=,&new_lm_dt] (int i, int j, int k) noexcept
131  {
132  new_lm_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0)))*dxinv[0]),
133  ((amrex::Math::abs(u(i,j,k,1)))*dxinv[1]),
134  ((amrex::Math::abs(u(i,j,k,2)))*dxinv[2]), new_lm_dt);
135  });
136  return new_lm_dt;
137  });
138 
139  ParallelDescriptor::ReduceRealMax(estdt_lowM_inv);
140  if (estdt_lowM_inv > 0.0_rt)
141  estdt_lowM = cfl / estdt_lowM_inv;
142 
143  if (verbose) {
144  if (fixed_dt <= 0.0) {
145  Print() << "Using cfl = " << cfl << std::endl;
146  Print() << "Fast dt at level " << level << ": " << estdt_comp << std::endl;
147  if (estdt_lowM_inv > 0.0_rt) {
148  Print() << "Slow dt at level " << level << ": " << estdt_lowM << std::endl;
149  } else {
150  Print() << "Slow dt at level " << level << ": undefined " << std::endl;
151  }
152  }
153 
154  if (fixed_dt > 0.0) {
155  Print() << "Based on cfl of 1.0 " << std::endl;
156  Print() << "Fast dt at level " << level << " would be: " << estdt_comp/cfl << std::endl;
157  if (estdt_lowM_inv > 0.0_rt) {
158  Print() << "Slow dt at level " << level << " would be: " << estdt_lowM/cfl << std::endl;
159  } else {
160  Print() << "Slow dt at level " << level << " would be undefined " << std::endl;
161  }
162  Print() << "Fixed dt at level " << level << " is: " << fixed_dt << std::endl;
163  if (fixed_fast_dt > 0.0) {
164  Print() << "Fixed fast dt at level " << level << " is: " << fixed_fast_dt << std::endl;
165  }
166  }
167  }
168 
169  if (fixed_dt > 0. && fixed_fast_dt > 0.) {
170  dt_fast_ratio = static_cast<long>( fixed_dt / fixed_fast_dt );
171  } else if (fixed_dt > 0.) {
172  dt_fast_ratio = static_cast<long>( std::ceil((fixed_dt/estdt_comp)) );
173  } else {
174  dt_fast_ratio = (estdt_lowM_inv > 0.0) ? static_cast<long>( std::ceil((estdt_lowM/estdt_comp)) ) : 1;
175  }
176 
177  // Force time step ratio to be an even value
179  if ( dt_fast_ratio%2 != 0) dt_fast_ratio += 1;
180  } else {
181  if ( dt_fast_ratio%6 != 0) {
182  Print() << "mri_dt_ratio = " << dt_fast_ratio
183  << " not divisible by 6 for N/3 substeps in stage 1" << std::endl;
184  dt_fast_ratio = static_cast<int>(std::ceil(dt_fast_ratio/6.0) * 6);
185  }
186  }
187 
188  if (verbose)
189  Print() << "smallest even ratio is: " << dt_fast_ratio << std::endl;
190 
191  if (fixed_dt > 0.0) {
192  return fixed_dt;
193  } else {
194  if (l_no_substepping) {
195  return estdt_comp;
196  } else {
197  return estdt_lowM;
198  }
199  }
200 }
constexpr amrex::Real Gamma
Definition: ERF_Constants.H:19
amrex::Real dz_min
Definition: ERF.H:951
static amrex::Real fixed_fast_dt
Definition: ERF.H:756
static amrex::Real cfl
Definition: ERF.H:750
static amrex::Real fixed_dt
Definition: ERF.H:755
@ rho
Definition: Kessler.H:30
int no_substepping
Definition: DataStruct.H:383
int force_stage1_single_substep
Definition: DataStruct.H:384
Here is the call graph for this function:

◆ Evolve()

void ERF::Evolve ( )
310 {
311  BL_PROFILE_VAR("ERF::Evolve()", evolve);
312 
313  Real cur_time = t_new[0];
314 
315  // Take one coarse timestep by calling timeStep -- which recursively calls timeStep
316  // for finer levels (with or without subcycling)
317  for (int step = istep[0]; step < max_step && cur_time < stop_time; ++step)
318  {
319  Print() << "\nCoarse STEP " << step+1 << " starts ..." << std::endl;
320 
321  ComputeDt();
322 
323  // Make sure we have read enough of the boundary plane data to make it through this timestep
324  if (input_bndry_planes)
325  {
326  m_r2d->read_input_files(cur_time,dt[0],m_bc_extdir_vals);
327  }
328 
329  int lev = 0;
330  int iteration = 1;
331  timeStep(lev, cur_time, iteration);
332 
333  cur_time += dt[0];
334 
335  Print() << "Coarse STEP " << step+1 << " ends." << " TIME = " << cur_time
336  << " DT = " << dt[0] << std::endl;
337 
338  post_timestep(step, cur_time, dt[0]);
339 
340  if (writeNow(cur_time, dt[0], step+1, m_plot_int_1, m_plot_per_1)) {
341  last_plot_file_step_1 = step+1;
343  }
344  if (writeNow(cur_time, dt[0], step+1, m_plot_int_2, m_plot_per_2)) {
345  last_plot_file_step_2 = step+1;
347  }
348 
349  if (writeNow(cur_time, dt[0], step+1, m_check_int, m_check_per)) {
350  last_check_file_step = step+1;
351 #ifdef ERF_USE_NETCDF
352  if (check_type == "netcdf") {
353  WriteNCCheckpointFile();
354  }
355 #endif
356  if (check_type == "native") {
358  }
359  }
360 
361 #ifdef AMREX_MEM_PROFILING
362  {
363  std::ostringstream ss;
364  ss << "[STEP " << step+1 << "]";
365  MemProfiler::report(ss.str());
366  }
367 #endif
368 
369  if (cur_time >= stop_time - 1.e-6*dt[0]) break;
370  }
371 
372  // Write plotfiles at final time
373  if ( (m_plot_int_1 > 0 || m_plot_per_1 > 0.) && istep[0] > last_plot_file_step_1 ) {
375  }
376  if ( (m_plot_int_2 > 0 || m_plot_per_2 > 0.) && istep[0] > last_plot_file_step_2) {
378  }
379 
380  if ( (m_check_int > 0 || m_check_per > 0.) && istep[0] > last_check_file_step) {
381 #ifdef ERF_USE_NETCDF
382  if (check_type == "netcdf") {
383  WriteNCCheckpointFile();
384  }
385 #endif
386  if (check_type == "native") {
388  }
389  }
390 
391  BL_PROFILE_VAR_STOP(evolve);
392 }
int last_check_file_step
Definition: ERF.H:735
int max_step
Definition: ERF.H:742
int last_plot_file_step_2
Definition: ERF.H:733
void WritePlotFile(int which, amrex::Vector< std::string > plot_var_names)
Definition: Plotfile.cpp:154
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NVAR_max > m_bc_extdir_vals
Definition: ERF.H:713
amrex::Real m_plot_per_1
Definition: ERF.H:768
std::string check_type
Definition: ERF.H:779
int m_plot_int_1
Definition: ERF.H:766
void post_timestep(int nstep, amrex::Real time, amrex::Real dt_lev)
Definition: ERF.cpp:396
amrex::Real m_check_per
Definition: ERF.H:782
void ComputeDt()
Definition: ERF_ComputeTimestep.cpp:11
int m_check_int
Definition: ERF.H:781
int last_plot_file_step_1
Definition: ERF.H:732
static int input_bndry_planes
Definition: ERF.H:889
void WriteCheckpointFile() const
Definition: Checkpoint.cpp:23
int m_plot_int_2
Definition: ERF.H:767
std::unique_ptr< ReadBndryPlanes > m_r2d
Definition: ERF.H:937
bool writeNow(const amrex::Real cur_time, const amrex::Real dt, const int nstep, const int plot_int, const amrex::Real plot_per)
Definition: ERF.cpp:1987
void timeStep(int lev, amrex::Real time, int iteration)
Definition: ERF_TimeStep.cpp:16
amrex::Real m_plot_per_2
Definition: ERF.H:769

Referenced by main().

Here is the caller graph for this function:

◆ Factory()

amrex::FabFactory<amrex::FArrayBox> const& ERF::Factory ( int  lev) const
inlineprivatenoexcept
1154 { return *m_factory[lev]; }

◆ fill_from_bndryregs()

void ERF::fill_from_bndryregs ( const amrex::Vector< amrex::MultiFab * > &  mfs,
amrex::Real  time 
)
14 {
15  //
16  // We now assume that if we read in on one face, we read in on all faces
17  //
18  AMREX_ALWAYS_ASSERT(m_r2d);
19 
20  int lev = 0;
21  const Box& domain = geom[lev].Domain();
22 
23  const auto& dom_lo = lbound(domain);
24  const auto& dom_hi = ubound(domain);
25 
26  Vector<std::unique_ptr<PlaneVector>>& bndry_data = m_r2d->interp_in_time(time);
27 
28  const BCRec* bc_ptr = domain_bcs_type_d.data();
29 
30  // xlo: ori = 0
31  // ylo: ori = 1
32  // zlo: ori = 2
33  // xhi: ori = 3
34  // yhi: ori = 4
35  // zhi: ori = 5
36  const auto& bdatxlo = (*bndry_data[0])[lev].const_array();
37  const auto& bdatylo = (*bndry_data[1])[lev].const_array();
38  const auto& bdatxhi = (*bndry_data[3])[lev].const_array();
39  const auto& bdatyhi = (*bndry_data[4])[lev].const_array();
40 
41  int bccomp;
42 
43  for (int var_idx = 0; var_idx < Vars::NumTypes; ++var_idx)
44  {
45  MultiFab& mf = *mfs[var_idx];
46  const int icomp = 0;
47  const int ncomp = mf.nComp();
48 
49  if (var_idx == Vars::xvel) {
50  bccomp = BCVars::xvel_bc;
51  } else if (var_idx == Vars::yvel) {
52  bccomp = BCVars::yvel_bc;
53  } else if (var_idx == Vars::zvel) {
54  bccomp = BCVars::zvel_bc;
55  } else if (var_idx == Vars::cons) {
56  bccomp = BCVars::cons_bc;
57  }
58 
59 #ifdef AMREX_USE_OMP
60 #pragma omp parallel if (Gpu::notInLaunchRegion())
61 #endif
62  for (MFIter mfi(mf); mfi.isValid(); ++mfi)
63  {
64  const Array4<Real>& dest_arr = mf.array(mfi);
65  Box bx = mfi.growntilebox();
66 
67  // x-faces
68  {
69  Box bx_xlo(bx); bx_xlo.setBig(0,dom_lo.x-1);
70  if (var_idx == Vars::xvel) bx_xlo.setBig(0,dom_lo.x);
71 
72  Box bx_xhi(bx); bx_xhi.setSmall(0,dom_hi.x+1);
73  if (var_idx == Vars::xvel) bx_xhi.setSmall(0,dom_hi.x);
74 
75  ParallelFor(
76  bx_xlo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
77  if (bc_ptr[icomp+n].lo(0) == ERFBCType::ext_dir_ingested) {
78  int jb = std::min(std::max(j,dom_lo.y),dom_hi.y);
79  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
80  dest_arr(i,j,k,icomp+n) = bdatxlo(dom_lo.x-1,jb,kb,bccomp+n);
81  }
82  },
83  bx_xhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
84  if (bc_ptr[icomp+n].hi(0) == ERFBCType::ext_dir_ingested) {
85  int jb = std::min(std::max(j,dom_lo.y),dom_hi.y);
86  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
87  dest_arr(i,j,k,icomp+n) = bdatxhi(dom_hi.x+1,jb,kb,bccomp+n);
88  }
89  }
90  );
91  } // x-faces
92 
93  // y-faces
94  {
95  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
96  if (var_idx == Vars::yvel) bx_ylo.setBig(1,dom_lo.y);
97 
98  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
99  if (var_idx == Vars::yvel) bx_yhi.setSmall(1,dom_hi.y);
100 
101  ParallelFor(
102  bx_ylo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
103  if (bc_ptr[icomp+n].lo(1) == ERFBCType::ext_dir_ingested) {
104  int ib = std::min(std::max(i,dom_lo.x),dom_hi.x);
105  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
106  dest_arr(i,j,k,icomp+n) = bdatylo(ib,dom_lo.y-1,kb,bccomp+n);
107  }
108  },
109  bx_yhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
110  if (bc_ptr[icomp+n].hi(1) == ERFBCType::ext_dir_ingested) {
111  int ib = std::min(std::max(i,dom_lo.x),dom_hi.x);
112  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
113  dest_arr(i,j,k,icomp+n) = bdatyhi(ib,dom_hi.y+1,kb,bccomp+n);
114  }
115  }
116  );
117  } // y-faces
118  } // mf
119  } // var_idx
120 }
@ zvel_bc
Definition: IndexDefines.H:57
@ yvel_bc
Definition: IndexDefines.H:56
@ cons_bc
Definition: IndexDefines.H:47
@ xvel_bc
Definition: IndexDefines.H:55
@ ext_dir_ingested
Definition: IndexDefines.H:154

◆ fill_rhs()

void ERF::fill_rhs ( amrex::MultiFab &  rhs_mf,
const amrex::MultiFab &  state_mf,
amrex::Real  time,
const amrex::Geometry &  geom 
)
private

◆ FillBdyCCVels()

void ERF::FillBdyCCVels ( amrex::Vector< amrex::MultiFab > &  mf_cc_vel)
549 {
550  // Impose bc's at domain boundaries
551  for (int lev = 0; lev <= finest_level; ++lev)
552  {
553  Box domain(Geom(lev).Domain());
554 
555  int ihi = domain.bigEnd(0);
556  int jhi = domain.bigEnd(1);
557  int khi = domain.bigEnd(2);
558 
559  // Impose periodicity first
560  mf_cc_vel[lev].FillBoundary(geom[lev].periodicity());
561 
562  for (MFIter mfi(mf_cc_vel[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
563  {
564  // Note that we don't fill corners here -- only the cells that share a face
565  // with interior cells -- this is all that is needed to calculate vorticity
566  const Box& bx = mfi.tilebox();
567  const Array4<Real>& vel_arr = mf_cc_vel[lev].array(mfi);
568 
569  if (!Geom(lev).isPeriodic(0)) {
570  // Low-x side
571  if (bx.smallEnd(0) <= domain.smallEnd(0)) {
572  Real mult = (phys_bc_type[0] == ERF_BC::no_slip_wall) ? -1. : 1.;
573  ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
574  {
575  vel_arr(-1,j,k,1) = mult*vel_arr(0,j,k,1); // v
576  vel_arr(-1,j,k,2) = mult*vel_arr(0,j,k,2); // w
577  });
578  }
579 
580  // High-x side
581  if (bx.bigEnd(0) >= domain.bigEnd(0)) {
582  Real mult = (phys_bc_type[3] == ERF_BC::no_slip_wall) ? -1. : 1.;
583  ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
584  {
585  vel_arr(ihi+1,j,k,1) = mult*vel_arr(ihi,j,k,1); // v
586  vel_arr(ihi+1,j,k,2) = mult*vel_arr(ihi,j,k,2); // w
587  });
588  }
589  } // !periodic
590 
591  if (!Geom(lev).isPeriodic(1)) {
592  // Low-y side
593  if (bx.smallEnd(1) <= domain.smallEnd(1)) {
594  Real mult = (phys_bc_type[1] == ERF_BC::no_slip_wall) ? -1. : 1.;
595  ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
596  {
597  vel_arr(i,-1,k,0) = mult*vel_arr(i,0,k,0); // u
598  vel_arr(i,-1,k,2) = mult*vel_arr(i,0,k,2); // w
599  });
600  }
601 
602  // High-y side
603  if (bx.bigEnd(1) >= domain.bigEnd(1)) {
604  Real mult = (phys_bc_type[4] == ERF_BC::no_slip_wall) ? -1. : 1.;
605  ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
606  {
607  vel_arr(i,jhi+1,k,0) = mult*vel_arr(i,jhi,k,0); // u
608  vel_arr(i,jhi+1,k,2) = mult*-vel_arr(i,jhi,k,2); // w
609  });
610  }
611  } // !periodic
612 
613  if (!Geom(lev).isPeriodic(2)) {
614  // Low-z side
615  if (bx.smallEnd(2) <= domain.smallEnd(2)) {
616  Real mult = (phys_bc_type[2] == ERF_BC::no_slip_wall) ? -1. : 1.;
617  ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
618  {
619  vel_arr(i,j,-1,0) = mult*vel_arr(i,j,0,0); // u
620  vel_arr(i,j,-1,1) = mult*vel_arr(i,j,0,1); // v
621  });
622  }
623 
624  // High-z side
625  if (bx.bigEnd(2) >= domain.bigEnd(2)) {
626  Real mult = (phys_bc_type[5] == ERF_BC::no_slip_wall) ? -1. : 1.;
627  ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
628  {
629  vel_arr(i,j,khi+1,0) = mult*vel_arr(i,j,khi,0); // u
630  vel_arr(i,j,khi+1,1) = mult*vel_arr(i,j,khi,1); // v
631  });
632  }
633  } // !periodic
634  } // MFIter
635 
636  } // lev
637 }
@ no_slip_wall

◆ FillCoarsePatch()

void ERF::FillCoarsePatch ( int  lev,
amrex::Real  time 
)
private
431 {
432  BL_PROFILE_VAR("FillCoarsePatch()",FillCoarsePatch);
433  AMREX_ASSERT(lev > 0);
434 
435  //
436  // First fill density at the COARSE level so we can convert velocity to momenta at the COARSE level
437  //
438  bool cons_only = true;
439  FillPatch(lev-1, time, {&vars_new[lev-1][Vars::cons], &vars_new[lev-1][Vars::xvel],
440  &vars_new[lev-1][Vars::yvel], &vars_new[lev-1][Vars::zvel]},
441  {&vars_new[lev-1][Vars::cons],
442  &rU_new[lev-1], &rV_new[lev-1], &rW_new[lev-1]},
443  false, cons_only);
444 
445  //
446  // Convert velocity to momentum at the COARSE level
447  //
448  IntVect ngu = IntVect(0,0,0);
449  IntVect ngv = IntVect(0,0,0);
450  IntVect ngw = IntVect(0,0,0);
451 
453  vars_new[lev-1][Vars::yvel], ngv,
454  vars_new[lev-1][Vars::zvel], ngw,
455  vars_new[lev-1][Vars::cons],
456  rU_new[lev-1],
457  rV_new[lev-1],
458  rW_new[lev-1],
459  Geom(lev).Domain(),
461 
462 
463  //
464  // Interpolate all cell-centered variables from coarse to fine level
465  //
466  Interpolater* mapper_c = &cell_cons_interp;
467  Interpolater* mapper_f = &face_cons_linear_interp;
468 
469  int icomp = 0;
470  int bccomp = BCVars::cons_bc;
471  InterpFromCoarseLevel(vars_new[lev][Vars::cons], time, vars_new[lev-1][Vars::cons],
472  icomp, icomp, vars_new[lev][Vars::cons].nComp(),
473  geom[lev-1], geom[lev],
474  *physbcs_cons[lev-1], BCVars::cons_bc,
476  refRatio(lev-1), mapper_c, domain_bcs_type, bccomp);
477 
478  //
479  // Interpolate x-momentum from coarse to fine level
480  //
481  InterpFromCoarseLevel(rU_new[lev], time, rU_new[lev-1],
482  0, 0, 1, geom[lev-1], geom[lev],
483  *physbcs_u[lev-1], BCVars::xvel_bc,
484  *physbcs_u[lev ], BCVars::xvel_bc,
485  refRatio(lev-1), mapper_f,
487 
488  //
489  // Interpolate y-momentum from coarse to fine level
490  //
491  bccomp = BCVars::yvel_bc;
492  InterpFromCoarseLevel(rV_new[lev], time, rV_new[lev-1],
493  0, 0, 1, geom[lev-1], geom[lev],
494  *physbcs_v[lev-1], BCVars::yvel_bc,
495  *physbcs_v[lev ], BCVars::yvel_bc,
496  refRatio(lev-1), mapper_f,
498 
499  //
500  // Interpolate z-momentum from coarse to fine level
501  //
502 
503  InterpFromCoarseLevel(rW_new[lev], time, rW_new[lev-1],
504  0, 0, 1, geom[lev-1], geom[lev],
507  refRatio(lev-1), mapper_f,
509 
510  for (int which_lev = lev-1; which_lev <= lev; which_lev++)
511  {
513  vars_new[which_lev][Vars::yvel],
514  vars_new[which_lev][Vars::zvel],
515  vars_new[which_lev][Vars::cons],
516  rU_new[which_lev],
517  rV_new[which_lev],
518  rW_new[which_lev],
519  Geom(lev).Domain(),
521  }
522 
523  vars_new[lev][Vars::cons].FillBoundary(geom[lev].periodicity());
524  vars_new[lev][Vars::xvel].FillBoundary(geom[lev].periodicity());
525  vars_new[lev][Vars::yvel].FillBoundary(geom[lev].periodicity());
526  vars_new[lev][Vars::zvel].FillBoundary(geom[lev].periodicity());
527 
528  // ***************************************************************************
529  // Physical bc's at domain boundary
530  // ***************************************************************************
531  IntVect ngvect_cons = vars_new[lev][Vars::cons].nGrowVect();
532  IntVect ngvect_vels = vars_new[lev][Vars::xvel].nGrowVect();
533 
534  int ncomp_cons = vars_new[lev][Vars::cons].nComp();
535 
536  (*physbcs_cons[lev])(vars_new[lev][Vars::cons],0,ncomp_cons,ngvect_cons,time,BCVars::cons_bc);
537  ( *physbcs_u[lev])(vars_new[lev][Vars::xvel],0,1 ,ngvect_vels,time,BCVars::xvel_bc);
538  ( *physbcs_v[lev])(vars_new[lev][Vars::yvel],0,1 ,ngvect_vels,time,BCVars::yvel_bc);
541 
542  // ***************************************************************************
543  // Since lev > 0 here we don't worry about m_r2d or wrfbdy data
544  // ***************************************************************************
545 }
void FillCoarsePatch(int lev, amrex::Real time)
Definition: ERF_FillPatch.cpp:430
Here is the call graph for this function:

◆ FillIntermediatePatch()

void ERF::FillIntermediatePatch ( int  lev,
amrex::Real  time,
const amrex::Vector< amrex::MultiFab * > &  mfs_vel,
const amrex::Vector< amrex::MultiFab * > &  mfs_mom,
int  ng_cons,
int  ng_vel,
bool  cons_only,
int  icomp_cons,
int  ncomp_cons,
bool  allow_most_bcs = true 
)
private
237 {
238  BL_PROFILE_VAR("FillIntermediatePatch()",FillIntermediatePatch);
239  int bccomp;
240  Interpolater* mapper;
241 
242  //
243  // ***************************************************************************
244  // The first thing we do is interpolate the momenta on the "valid" faces of
245  // the fine grids (where the interface is coarse/fine not fine/fine) -- this
246  // will not be over-written by interpolation below because the FillPatch
247  // operators see these as valid faces. But we must have these interpolated
248  // values in the fine data before we call FillPatchTwoLevels.
249  //
250  // Also -- note that we might be filling values by interpolation at physical boundaries
251  // here but that's ok because we will overwrite those values when we impose
252  // the physical bc's below
253  // ***************************************************************************
254  if (lev>0) {
255  if (cf_set_width > 0) {
256  // We note that mfs_vel[Vars::cons] and mfs_mom[Vars::cons] are in fact the same pointer
257  FPr_c[lev-1].FillSet(*mfs_vel[Vars::cons], time, null_bc, domain_bcs_type);
258  }
259  if ( !cons_only && (cf_set_width >= 0) ) {
260  FPr_u[lev-1].FillSet(*mfs_mom[IntVars::xmom], time, null_bc, domain_bcs_type);
261  FPr_v[lev-1].FillSet(*mfs_mom[IntVars::ymom], time, null_bc, domain_bcs_type);
262  FPr_w[lev-1].FillSet(*mfs_mom[IntVars::zmom], time, null_bc, domain_bcs_type);
263  }
264  }
265 
266  AMREX_ALWAYS_ASSERT(mfs_mom.size() == IntVars::NumTypes);
267  AMREX_ALWAYS_ASSERT(mfs_vel.size() == Vars::NumTypes);
268 
269  // Enforce no penetration for thin immersed body
270  if (xflux_imask[lev]) {
271  ApplyMask(*mfs_mom[IntVars::xmom], *xflux_imask[lev]);
272  }
273  if (yflux_imask[lev]) {
274  ApplyMask(*mfs_mom[IntVars::ymom], *yflux_imask[lev]);
275  }
276  if (zflux_imask[lev]) {
277  ApplyMask(*mfs_mom[IntVars::zmom], *zflux_imask[lev]);
278  }
279 
280  // We always come in to this call with updated momenta but we need to create updated velocity
281  // in order to impose the rest of the bc's
282  if (!cons_only) {
283  // This only fills VALID region of velocity
284  MomentumToVelocity(*mfs_vel[Vars::xvel], *mfs_vel[Vars::yvel], *mfs_vel[Vars::zvel],
285  *mfs_vel[Vars::cons],
286  *mfs_mom[IntVars::xmom], *mfs_mom[IntVars::ymom], *mfs_mom[IntVars::zmom],
287  Geom(lev).Domain(), domain_bcs_type);
288  }
289 
290  // We now start working on VELOCITY
291  for (int var_idx = 0; var_idx < Vars::NumTypes; ++var_idx)
292  {
293  if (cons_only && var_idx != Vars::cons) continue;
294 
295  MultiFab& mf = *mfs_vel[var_idx];
296 
297  IntVect ngvect;
298  int icomp, ncomp;
299  if (var_idx == Vars::cons)
300  {
301  bccomp = icomp_cons;
302  mapper = &cell_cons_interp;
303  ngvect = IntVect(ng_cons,ng_cons,ng_cons);
304  icomp = icomp_cons;
305  ncomp = ncomp_cons;
306  }
307  else if (var_idx == IntVars::xmom)
308  {
309  bccomp = BCVars::xvel_bc;
310  mapper = &face_cons_linear_interp;
311  ngvect = IntVect(ng_vel,ng_vel,ng_vel);
312  icomp = 0;
313  ncomp = 1;
314  }
315  else if (var_idx == IntVars::ymom)
316  {
317  bccomp = BCVars::yvel_bc;
318  mapper = &face_cons_linear_interp;
319  ngvect = IntVect(ng_vel,ng_vel,ng_vel);
320  icomp = 0;
321  ncomp = 1;
322  }
323  else if (var_idx == IntVars::zmom)
324  {
325  bccomp = BCVars::zvel_bc;
326  mapper = &face_cons_linear_interp;
327  ngvect = IntVect(ng_vel,ng_vel,0);
328  icomp = 0;
329  ncomp = 1;
330  }
331 
332  if (lev == 0)
333  {
334  // This fills fine-fine ghost values of VELOCITY
335  mf.FillBoundary(icomp,ncomp,ngvect,geom[lev].periodicity());
336  }
337  else
338  {
339  //
340  // NOTE: All interpolation here happens on velocities not momenta;
341  // note we only do the interpolation and FillBoundary here,
342  // physical bc's are imposed later
343  //
344  // NOTE: This will only fill velocity from coarse grid *outside* the fine grids
345  // unlike the FillSet calls above which filled momenta on the coarse/fine bdy
346  //
347  Vector<MultiFab*> fmf = {&mf};
348  Vector<MultiFab*> cmf = {&vars_old[lev-1][var_idx], &vars_new[lev-1][var_idx]};
349  Vector<Real> ctime = {t_old[lev-1], t_new[lev-1]};
350 
351  FillPatchTwoLevels(mf, time, cmf, ctime, fmf, {time},
352  icomp, icomp, ncomp, geom[lev-1], geom[lev],
353  null_bc, 0, null_bc, 0, refRatio(lev-1),
354  mapper, domain_bcs_type, bccomp);
355  } // lev > 0
356  } // var_idx
357 
358  // ***************************************************************************
359  // Physical bc's at domain boundary
360  // ***************************************************************************
361  IntVect ngvect_cons = IntVect(ng_cons,ng_cons,ng_cons);
362  IntVect ngvect_vels = IntVect(ng_vel ,ng_vel ,ng_vel);
363 
364 #ifdef ERF_USE_NETCDF
365  // We call this here because it is an ERF routine
366  if (use_real_bcs && (lev==0)) {
367  fill_from_realbdy(mfs_vel,time,false,0,ncomp_cons);
368  }
369 #endif
370 
371  if (m_r2d) fill_from_bndryregs(mfs_vel,time);
372 
373  // We call this even if init_type == real because this routine will fill the vertical bcs
374  (*physbcs_cons[lev])(*mfs_vel[Vars::cons],icomp_cons,ncomp_cons,ngvect_cons,time,BCVars::cons_bc);
375  if (!cons_only) {
376  (*physbcs_u[lev])(*mfs_vel[Vars::xvel],0,1,ngvect_vels,time,BCVars::xvel_bc);
377  (*physbcs_v[lev])(*mfs_vel[Vars::yvel],0,1,ngvect_vels,time,BCVars::yvel_bc);
378  (*physbcs_w[lev])(*mfs_vel[Vars::zvel],*mfs_vel[Vars::xvel],*mfs_vel[Vars::yvel],
380  }
381  // ***************************************************************************
382 
383  // MOST boundary conditions
384  if (!(cons_only && ncomp_cons == 1) && m_most && allow_most_bcs) {
385  m_most->impose_most_bcs(lev,mfs_vel,
386 #ifdef ERF_EXPLICIT_MOST_STRESS
387  Tau13_lev[lev].get(), Tau31_lev[lev].get(),
388  Tau23_lev[lev].get(), Tau32_lev[lev].get(),
389  SFS_hfx3_lev[lev].get(),
390 #else
391  eddyDiffs_lev[lev].get(),
392 #endif
393  z_phys_nd[lev].get());
394  }
395 
396  // We always come in to this call with momenta so we need to leave with momenta!
397  // We need to make sure we convert back on all ghost cells/faces because this is
398  // how velocity from fine-fine copies (as well as physical and interpolated bcs) will be filled
399  if (!cons_only) {
400  IntVect ngu = mfs_vel[Vars::xvel]->nGrowVect();
401  IntVect ngv = mfs_vel[Vars::yvel]->nGrowVect();
402  IntVect ngw = mfs_vel[Vars::zvel]->nGrowVect();
403 
404  if (!solverChoice.use_NumDiff) {
405  ngu = IntVect(1,1,1);
406  ngv = IntVect(1,1,1);
407  ngw = IntVect(1,1,0);
408  }
409  VelocityToMomentum(*mfs_vel[Vars::xvel], ngu,
410  *mfs_vel[Vars::yvel], ngv,
411  *mfs_vel[Vars::zvel], ngw,
412  *mfs_vel[Vars::cons],
413  *mfs_mom[IntVars::xmom], *mfs_mom[IntVars::ymom], *mfs_mom[IntVars::zmom],
414  Geom(lev).Domain(),
416  }
417 }
PhysBCFunctNoOp null_bc
Definition: ERF_FillPatch.cpp:10
AMREX_GPU_HOST AMREX_FORCE_INLINE void ApplyMask(amrex::MultiFab &dst, const amrex::iMultiFab &imask, const int nghost=0)
Definition: Utils.H:351
void fill_from_bndryregs(const amrex::Vector< amrex::MultiFab * > &mfs, amrex::Real time)
Definition: BoundaryConditions_bndryreg.cpp:13
void FillIntermediatePatch(int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, const amrex::Vector< amrex::MultiFab * > &mfs_mom, int ng_cons, int ng_vel, bool cons_only, int icomp_cons, int ncomp_cons, bool allow_most_bcs=true)
Definition: ERF_FillPatch.cpp:231
static bool use_real_bcs
Definition: ERF.H:854
@ NumTypes
Definition: IndexDefines.H:113
Here is the call graph for this function:

◆ FillPatch()

void ERF::FillPatch ( int  lev,
amrex::Real  time,
const amrex::Vector< amrex::MultiFab * > &  mfs_vel,
const amrex::Vector< amrex::MultiFab * > &  mfs_mom,
bool  fillset = true,
bool  cons_only = false 
)
private
26 {
27  BL_PROFILE_VAR("ERF::FillPatch()",ERF_FillPatch);
28  Interpolater* mapper = nullptr;
29 
30  //
31  // ***************************************************************************
32  // The first thing we do is interpolate the momenta on the "valid" faces of
33  // the fine grids (where the interface is coarse/fine not fine/fine) -- this
34  // will not be over-written below because the FillPatch operators see these as
35  // valid faces.
36  //
37  // Note that we interpolate momentum not velocity, but all the other boundary
38  // conditions are imposed on velocity, so we convert to momentum here then
39  // convert back.
40  // ***************************************************************************
41  if (lev>0 && fillset) {
42  if (cf_set_width > 0) {
43  FPr_c[lev-1].FillSet(*mfs_vel[Vars::cons], time, null_bc, domain_bcs_type);
44  }
45  if (cf_set_width >= 0 && !cons_only) {
46  //
47  // This is an optimization since we won't need more than one ghost
48  // cell of momentum in the integrator if not using NumDiff
49  //
50  //IntVect ngu = (solverChoice.use_NumDiff) ? IntVect(1,1,1) : mfs_vel[Vars::xvel]->nGrowVect();
51  //IntVect ngv = (solverChoice.use_NumDiff) ? IntVect(1,1,1) : mfs_vel[Vars::yvel]->nGrowVect();
52  //IntVect ngw = (solverChoice.use_NumDiff) ? IntVect(1,1,0) : mfs_vel[Vars::zvel]->nGrowVect();
53  IntVect ngu = IntVect::TheZeroVector();
54  IntVect ngv = IntVect::TheZeroVector();
55  IntVect ngw = IntVect::TheZeroVector();
56 
57  VelocityToMomentum(*mfs_vel[Vars::xvel], ngu,
58  *mfs_vel[Vars::yvel], ngv,
59  *mfs_vel[Vars::zvel], ngw,
60  *mfs_vel[Vars::cons],
61  *mfs_mom[IntVars::xmom],
62  *mfs_mom[IntVars::ymom],
63  *mfs_mom[IntVars::zmom],
64  Geom(lev).Domain(),
66 
67  FPr_u[lev-1].FillSet(*mfs_mom[IntVars::xmom], time, null_bc, domain_bcs_type);
68  FPr_v[lev-1].FillSet(*mfs_mom[IntVars::ymom], time, null_bc, domain_bcs_type);
69  FPr_w[lev-1].FillSet(*mfs_mom[IntVars::zmom], time, null_bc, domain_bcs_type);
70 
71  MomentumToVelocity(*mfs_vel[Vars::xvel], *mfs_vel[Vars::yvel], *mfs_vel[Vars::zvel],
72  *mfs_vel[Vars::cons],
73  *mfs_mom[IntVars::xmom],
74  *mfs_mom[IntVars::ymom],
75  *mfs_mom[IntVars::zmom],
76  Geom(lev).Domain(),
78  }
79  }
80 
81  IntVect ngvect_cons = mfs_vel[Vars::cons]->nGrowVect();
82  IntVect ngvect_vels = mfs_vel[Vars::xvel]->nGrowVect();
83 
84  if (lev == 0)
85  {
86  const int icomp = 0;
87 
88  Vector<Real> ftime = {t_old[lev], t_new[lev]};
89 
90  Vector<MultiFab*> fmf = {&vars_old[lev][Vars::cons], &vars_new[lev][Vars::cons]};
91  const int ncomp = mfs_vel[Vars::cons]->nComp();
92  FillPatchSingleLevel(*mfs_vel[Vars::cons], time, fmf, ftime, icomp, icomp, ncomp,
93  geom[lev], *physbcs_cons[lev], BCVars::cons_bc+icomp);
94 
95  if (!cons_only) {
96  fmf = {&vars_old[lev][Vars::xvel], &vars_new[lev][Vars::xvel]};
97  const int ncomp_u = 1;
98  FillPatchSingleLevel(*mfs_vel[Vars::xvel], time, fmf, ftime, icomp, icomp, ncomp_u,
99  geom[lev], *physbcs_u[lev], BCVars::xvel_bc);
100 
101  fmf = {&vars_old[lev][Vars::yvel], &vars_new[lev][Vars::yvel]};
102  const int ncomp_v = 1;
103  FillPatchSingleLevel(*mfs_vel[Vars::yvel], time, fmf, ftime, icomp, icomp, ncomp_v,
104  geom[lev], *physbcs_v[lev], BCVars::yvel_bc);
105 
106  fmf = {&vars_old[lev][Vars::zvel], &vars_new[lev][Vars::zvel]};
107  const int ncomp_w = 1;
108  FillPatchSingleLevel(*mfs_vel[Vars::zvel], time, fmf, ftime, icomp, icomp, ncomp_w,
109  geom[lev], *physbcs_w_no_terrain[lev], BCVars::zvel_bc);
110  (*physbcs_w[lev])(*mfs_vel[Vars::zvel],*mfs_vel[Vars::xvel],*mfs_vel[Vars::yvel],
112  } // !cons_only
113 
114  } else {
115 
116  Vector<Real> ftime = {t_old[lev], t_new[lev]};
117  Vector<Real> ctime = {t_old[lev-1], t_new[lev-1]};
118 
119  Vector<MultiFab*> fmf = {&vars_old[lev ][Vars::cons], &vars_new[lev ][Vars::cons]};
120  Vector<MultiFab*> cmf = {&vars_old[lev-1][Vars::cons], &vars_new[lev-1][Vars::cons]};
121  MultiFab& mf_c = *mfs_vel[Vars::cons];
122  mapper = &cell_cons_interp;
123  FillPatchTwoLevels(mf_c, time, cmf, ctime, fmf, ftime,
124  0, 0, mf_c.nComp(), geom[lev-1], geom[lev],
125  null_bc, BCVars::cons_bc, null_bc, BCVars::cons_bc, refRatio(lev-1),
127 
128  if (!cons_only) {
129  mapper = &face_cons_linear_interp;
130 
131  MultiFab& mf_u = *mfs_vel[Vars::xvel];
132  fmf = {&vars_old[lev ][Vars::xvel], &vars_new[lev ][Vars::xvel]};
133  cmf = {&vars_old[lev-1][Vars::xvel], &vars_new[lev-1][Vars::xvel]};
134  FillPatchTwoLevels(mf_u, time, cmf, ctime, fmf, ftime,
135  0, 0, 1, geom[lev-1], geom[lev],
136  null_bc, BCVars::xvel_bc, null_bc, BCVars::xvel_bc, refRatio(lev-1),
138 
139  MultiFab& mf_v = *mfs_vel[Vars::yvel];
140  fmf = {&vars_old[lev ][Vars::yvel], &vars_new[lev ][Vars::yvel]};
141  cmf = {&vars_old[lev-1][Vars::yvel], &vars_new[lev-1][Vars::yvel]};
142  FillPatchTwoLevels(mf_v, time, cmf, ctime, fmf, ftime,
143  0, 0, 1, geom[lev-1], geom[lev],
144  null_bc, BCVars::yvel_bc, null_bc, BCVars::yvel_bc, refRatio(lev-1),
146 
147  MultiFab& mf_w = *mfs_vel[Vars::zvel];
148  fmf = {&vars_old[lev ][Vars::zvel], &vars_new[lev ][Vars::zvel]};
149  cmf = {&vars_old[lev-1][Vars::zvel], &vars_new[lev-1][Vars::zvel]};
150  FillPatchTwoLevels(mf_w, time, cmf, ctime, fmf, ftime,
151  0, 0, 1, geom[lev-1], geom[lev],
152  null_bc, BCVars::zvel_bc, null_bc, BCVars::zvel_bc, refRatio(lev-1),
154  } // !cons_only
155  } // lev > 0
156 
157  // ***************************************************************************
158  // Physical bc's at domain boundary
159  // ***************************************************************************
160  int icomp_cons = 0;
161  int ncomp_cons = mfs_vel[Vars::cons]->nComp();
162 
163 #ifdef ERF_USE_NETCDF
164  // We call this here because it is an ERF routine
165  if (use_real_bcs && (lev==0)) {
166  fill_from_realbdy(mfs_vel,time,false,0,ncomp_cons);
167  }
168 #endif
169 
170  if (m_r2d) fill_from_bndryregs(mfs_vel,time);
171 
172  // We call these even if init_type == real because these will fill the vertical bcs
173  (*physbcs_cons[lev])(*mfs_vel[Vars::cons],icomp_cons,ncomp_cons,ngvect_cons,time,BCVars::cons_bc);
174  if (!cons_only) {
175  (*physbcs_u[lev])(*mfs_vel[Vars::xvel],0,1,ngvect_vels,time,BCVars::xvel_bc);
176  (*physbcs_v[lev])(*mfs_vel[Vars::yvel],0,1,ngvect_vels,time,BCVars::yvel_bc);
177  (*physbcs_w[lev])(*mfs_vel[Vars::zvel],*mfs_vel[Vars::xvel],*mfs_vel[Vars::yvel],
179  }
180 }
Here is the call graph for this function:

◆ FillPatchMoistVars()

void ERF::FillPatchMoistVars ( int  lev,
amrex::MultiFab &  mf 
)
private
191 {
192  BL_PROFILE_VAR("ERF::FillPatchMoistVars()",ERF_FillPatchMoistVars);
193  // ***************************************************************************
194  // Physical bc's at domain boundary
195  // ***************************************************************************
196  int icomp_cons = 0;
197  int ncomp_cons = 1; // We only fill qv, the first component
198 
199  // Note that we are filling qv, stored in qmoist[lev], with the input data (if there is any), stored
200  // in RhoQ1_comp.
201 
202  if (!use_real_bcs) {
203  Real time = Real(0.0);
204  IntVect ngvect_cons = mf.nGrowVect();
205  int bccomp_cons = BCVars::RhoQ1_bc_comp;
206 
207  (*physbcs_cons[lev])(mf,icomp_cons,ncomp_cons,ngvect_cons,time,bccomp_cons);
208  }
209 
210  mf.FillBoundary(geom[lev].periodicity());
211 }
@ RhoQ1_bc_comp
Definition: IndexDefines.H:53

◆ getAdvFluxReg()

AMREX_FORCE_INLINE amrex::YAFluxRegister* ERF::getAdvFluxReg ( int  lev)
inlineprivate
994  {
995  return advflux_reg[lev];
996  }

◆ getCPUTime()

static amrex::Real ERF::getCPUTime ( )
inlinestaticprivate
1071  {
1072  int numCores = amrex::ParallelDescriptor::NProcs();
1073 #ifdef _OPENMP
1074  numCores = numCores * omp_get_max_threads();
1075 #endif
1076 
1077  amrex::Real T =
1078  numCores * (amrex::ParallelDescriptor::second() - startCPUTime) +
1080 
1081  return T;
1082  }
static amrex::Real previousCPUTimeUsed
Definition: ERF.H:1067
static amrex::Real startCPUTime
Definition: ERF.H:1066
@ T
Definition: IndexDefines.H:67

◆ GotoNextLine()

void ERF::GotoNextLine ( std::istream &  is)
staticprivate

Utility to skip to next line in Header file input stream.

14 {
15  constexpr std::streamsize bl_ignore_max { 100000 };
16  is.ignore(bl_ignore_max, '\n');
17 }

◆ init1DArrays()

void ERF::init1DArrays ( )
private

◆ init_bcs()

void ERF::init_bcs ( )
private

Initializes data structures in the ERF class that specify which boundary conditions we are implementing on each face of the domain.

This function also maps the selected boundary condition types (e.g. Outflow, Inflow, Periodic, Dirichlet, ...) to the specific implementation needed for each variable.

Stores this information in both host and device vectors so it is available for GPU kernels.

22 {
23  auto f = [this] (std::string const& bcid, Orientation ori)
24  {
25  // These are simply defaults for Dirichlet faces -- they should be over-written below
27  m_bc_extdir_vals[BCVars::RhoTheta_bc_comp][ori] = -1.0; // It is important to set this negative
28  // because the sign is tested on below
34 
35  m_bc_extdir_vals[BCVars::xvel_bc][ori] = 0.0; // default
38 
39  // These are simply defaults for Neumann gradients -- they should be over-written below
50 
51  std::string pp_text;
52  if (pp_prefix == "erf") {
53  pp_text = bcid;
54  } else {
55  pp_text = pp_prefix + "." + bcid;
56  }
57  ParmParse pp(pp_text);
58  std::string bc_type_in = "null";
59  pp.query("type", bc_type_in);
60  //if (pp.query("type", bc_type_in))
61  // Print() << "INPUT BC TYPE " << bcid << " " << bc_type_in << std::endl;
62  std::string bc_type = amrex::toLower(bc_type_in);
63 
64  if (bc_type == "symmetry")
65  {
66  // Print() << bcid << " set to symmetry.\n";
68  domain_bc_type[ori] = "Symmetry";
69  }
70  else if (bc_type == "outflow")
71  {
72  // Print() << bcid << " set to outflow.\n";
74  domain_bc_type[ori] = "Outflow";
75  }
76  else if (bc_type == "open")
77  {
78  // Print() << bcid << " set to open.\n";
79  AMREX_ASSERT_WITH_MESSAGE((ori.coordDir() != 2), "Open boundary not valid on zlo or zhi!");
81  domain_bc_type[ori] = "Open";
82  }
83  else if (bc_type == "inflow")
84  {
85  // Print() << bcid << " set to inflow.\n";
87  domain_bc_type[ori] = "Inflow";
88 
89  std::vector<Real> v;
90  if (input_bndry_planes && m_r2d->ingested_velocity()) {
94  } else {
95  pp.getarr("velocity", v, 0, AMREX_SPACEDIM);
96  m_bc_extdir_vals[BCVars::xvel_bc][ori] = v[0];
97  m_bc_extdir_vals[BCVars::yvel_bc][ori] = v[1];
98  m_bc_extdir_vals[BCVars::zvel_bc][ori] = v[2];
99  }
100 
101  Real rho_in;
102  if (input_bndry_planes && m_r2d->ingested_density()) {
104  } else {
105  pp.get("density", rho_in);
106  m_bc_extdir_vals[BCVars::Rho_bc_comp][ori] = rho_in;
107  }
108  Real theta_in;
109  if (input_bndry_planes && m_r2d->ingested_theta()) {
111  } else {
112  pp.get("theta", theta_in);
113  m_bc_extdir_vals[BCVars::RhoTheta_bc_comp][ori] = rho_in*theta_in;
114  }
115  Real scalar_in = 0.;
116  if (input_bndry_planes && m_r2d->ingested_scalar()) {
118  } else {
119  if (pp.query("scalar", scalar_in))
120  m_bc_extdir_vals[BCVars::RhoScalar_bc_comp][ori] = rho_in*scalar_in;
121  }
122 
124  Real qv_in = 0.;
125  if (input_bndry_planes && m_r2d->ingested_q1()) {
127  } else {
128  if (pp.query("qv", qv_in))
129  m_bc_extdir_vals[BCVars::RhoQ1_bc_comp][ori] = rho_in*qv_in;
130  }
131  Real qc_in = 0.;
132  if (input_bndry_planes && m_r2d->ingested_q2()) {
134  } else {
135  if (pp.query("qc", qc_in))
136  m_bc_extdir_vals[BCVars::RhoQ2_bc_comp][ori] = rho_in*qc_in;
137  }
138  }
139 
140  Real KE_in = 0.;
141  if (input_bndry_planes && m_r2d->ingested_KE()) {
143  } else {
144  if (pp.query("KE", KE_in))
145  m_bc_extdir_vals[BCVars::RhoKE_bc_comp][ori] = rho_in*KE_in;
146  }
147  Real QKE_in = 0.;
148  if (input_bndry_planes && m_r2d->ingested_QKE()) {
150  } else {
151  if (pp.query("QKE", QKE_in))
152  m_bc_extdir_vals[BCVars::RhoQKE_bc_comp][ori] = rho_in*QKE_in;
153  }
154 
155  }
156  else if (bc_type == "noslipwall")
157  {
158  // Print() << bcid <<" set to no-slip wall.\n";
160  domain_bc_type[ori] = "NoSlipWall";
161 
162  std::vector<Real> v;
163 
164  // The values of m_bc_extdir_vals default to 0.
165  // But if we find "velocity" in the inputs file, use those values instead.
166  if (pp.queryarr("velocity", v, 0, AMREX_SPACEDIM))
167  {
168  v[ori.coordDir()] = 0.0;
169  m_bc_extdir_vals[BCVars::xvel_bc][ori] = v[0];
170  m_bc_extdir_vals[BCVars::yvel_bc][ori] = v[1];
171  m_bc_extdir_vals[BCVars::zvel_bc][ori] = v[2];
172  }
173 
174  Real rho_in;
175  if (pp.query("density", rho_in))
176  {
177  m_bc_extdir_vals[BCVars::Rho_bc_comp][ori] = rho_in;
178  }
179 
180  Real theta_in;
181  if (pp.query("theta", theta_in))
182  {
184  }
185 
186  Real theta_grad_in;
187  if (pp.query("theta_grad", theta_grad_in))
188  {
189  m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori] = theta_grad_in;
190  }
191  }
192  else if (bc_type == "slipwall")
193  {
194  // Print() << bcid <<" set to slip wall.\n";
195 
197  domain_bc_type[ori] = "SlipWall";
198 
199  Real rho_in;
200  if (pp.query("density", rho_in))
201  {
202  m_bc_extdir_vals[BCVars::Rho_bc_comp][ori] = rho_in;
203  }
204 
205  Real theta_in;
206  if (pp.query("theta", theta_in))
207  {
209  }
210 
211  Real rho_grad_in;
212  if (pp.query("density_grad", rho_grad_in))
213  {
214  m_bc_neumann_vals[BCVars::Rho_bc_comp][ori] = rho_grad_in;
215  }
216 
217  Real theta_grad_in;
218  if (pp.query("theta_grad", theta_grad_in))
219  {
220  m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori] = theta_grad_in;
221  }
222  }
223  else if (bc_type == "most")
224  {
225  phys_bc_type[ori] = ERF_BC::MOST;
226  domain_bc_type[ori] = "MOST";
227  }
228  else
229  {
231  }
232 
233  if (geom[0].isPeriodic(ori.coordDir())) {
234  domain_bc_type[ori] = "Periodic";
235  if (phys_bc_type[ori] == ERF_BC::undefined)
236  {
238  } else {
239  Abort("Wrong BC type for periodic boundary");
240  }
241  }
242 
243  if (phys_bc_type[ori] == ERF_BC::undefined)
244  {
245  Print() << "BC Type specified for face " << bcid << " is " << bc_type_in << std::endl;
246  Abort("This BC type is unknown");
247  }
248  };
249 
250  f("xlo", Orientation(Direction::x,Orientation::low));
251  f("xhi", Orientation(Direction::x,Orientation::high));
252  f("ylo", Orientation(Direction::y,Orientation::low));
253  f("yhi", Orientation(Direction::y,Orientation::high));
254  f("zlo", Orientation(Direction::z,Orientation::low));
255  f("zhi", Orientation(Direction::z,Orientation::high));
256 
257  // *****************************************************************************
258  //
259  // Here we translate the physical boundary conditions -- one type per face --
260  // into logical boundary conditions for each velocity component
261  //
262  // *****************************************************************************
263  {
264  domain_bcs_type.resize(AMREX_SPACEDIM+NVAR_max);
265  domain_bcs_type_d.resize(AMREX_SPACEDIM+NVAR_max);
266 
267  for (OrientationIter oit; oit; ++oit) {
268  Orientation ori = oit();
269  int dir = ori.coordDir();
270  Orientation::Side side = ori.faceDir();
271  auto const bct = phys_bc_type[ori];
272  if ( bct == ERF_BC::symmetry )
273  {
274  if (side == Orientation::low) {
275  for (int i = 0; i < AMREX_SPACEDIM; i++) {
277  }
279  } else {
280  for (int i = 0; i < AMREX_SPACEDIM; i++) {
282  }
284  }
285  }
286  else if (bct == ERF_BC::outflow)
287  {
288  if (side == Orientation::low) {
289  for (int i = 0; i < AMREX_SPACEDIM; i++) {
291  }
293  } else {
294  for (int i = 0; i < AMREX_SPACEDIM; i++) {
296  }
298  }
299  }
300  else if (bct == ERF_BC::open)
301  {
302  if (side == Orientation::low) {
303  for (int i = 0; i < AMREX_SPACEDIM; i++)
305  } else {
306  for (int i = 0; i < AMREX_SPACEDIM; i++)
308  }
309  }
310  else if (bct == ERF_BC::inflow)
311  {
312  if (side == Orientation::low) {
313  for (int i = 0; i < AMREX_SPACEDIM; i++) {
315  if (input_bndry_planes && dir < 2 && m_r2d->ingested_velocity()) {
317  }
318  }
319  } else {
320  for (int i = 0; i < AMREX_SPACEDIM; i++) {
322  if (input_bndry_planes && dir < 2 && m_r2d->ingested_velocity()) {
324  }
325  }
326  }
327  }
328  else if (bct == ERF_BC::no_slip_wall)
329  {
330  if (side == Orientation::low) {
331  for (int i = 0; i < AMREX_SPACEDIM; i++) {
333  }
334  } else {
335  for (int i = 0; i < AMREX_SPACEDIM; i++) {
337  }
338  }
339  }
340  else if (bct == ERF_BC::slip_wall)
341  {
342  if (side == Orientation::low) {
343  for (int i = 0; i < AMREX_SPACEDIM; i++) {
345  }
346  // Only normal direction has ext_dir
348 
349  } else {
350  for (int i = 0; i < AMREX_SPACEDIM; i++) {
352  }
353  // Only normal direction has ext_dir
355  }
356  }
357  else if (bct == ERF_BC::periodic)
358  {
359  if (side == Orientation::low) {
360  for (int i = 0; i < AMREX_SPACEDIM; i++) {
362  }
363  } else {
364  for (int i = 0; i < AMREX_SPACEDIM; i++) {
366  }
367  }
368  }
369  else if ( bct == ERF_BC::MOST )
370  {
371  AMREX_ALWAYS_ASSERT(dir == 2 && side == Orientation::low);
375  }
376  }
377  }
378 
379  // *****************************************************************************
380  //
381  // Here we translate the physical boundary conditions -- one type per face --
382  // into logical boundary conditions for each cell-centered variable
383  //
384  // *****************************************************************************
385  {
386  for (OrientationIter oit; oit; ++oit) {
387  Orientation ori = oit();
388  int dir = ori.coordDir();
389  Orientation::Side side = ori.faceDir();
390  auto const bct = phys_bc_type[ori];
391  if ( bct == ERF_BC::symmetry )
392  {
393  if (side == Orientation::low) {
394  for (int i = 0; i < NVAR_max; i++) {
396  }
397  } else {
398  for (int i = 0; i < NVAR_max; i++) {
400  }
401  }
402  }
403  else if ( bct == ERF_BC::outflow )
404  {
405  if (side == Orientation::low) {
406  for (int i = 0; i < NVAR_max; i++) {
408  }
409  } else {
410  for (int i = 0; i < NVAR_max; i++) {
412  }
413  }
414  }
415  else if ( bct == ERF_BC::open )
416  {
417  if (side == Orientation::low) {
418  for (int i = 0; i < NVAR_max; i++)
420  } else {
421  for (int i = 0; i < NVAR_max; i++)
423  }
424  }
425  else if ( bct == ERF_BC::no_slip_wall)
426  {
427  if (side == Orientation::low) {
428  for (int i = 0; i < NVAR_max; i++) {
430  }
433  }
434  if (std::abs(m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori]) > 0.) {
436  }
437  } else {
438  for (int i = 0; i < NVAR_max; i++) {
440  }
443  }
444  if (std::abs(m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori]) > 0.) {
446  }
447  }
448  }
449  else if (bct == ERF_BC::slip_wall)
450  {
451  if (side == Orientation::low) {
452  for (int i = 0; i < NVAR_max; i++) {
454  }
457  }
458  if (std::abs(m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori]) > 0.) {
460  }
461  if (std::abs(m_bc_neumann_vals[BCVars::Rho_bc_comp][ori]) > 0.) {
463  }
464  } else {
465  for (int i = 0; i < NVAR_max; i++) {
467  }
470  }
471  if (std::abs(m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori]) > 0.) {
473  }
474  if (std::abs(m_bc_neumann_vals[BCVars::Rho_bc_comp][ori]) > 0.) {
476  }
477  }
478  }
479  else if (bct == ERF_BC::inflow)
480  {
481  if (side == Orientation::low) {
482  for (int i = 0; i < NVAR_max; i++) {
484  if (input_bndry_planes && dir < 2 && (
485  ( (BCVars::cons_bc+i == BCVars::Rho_bc_comp) && m_r2d->ingested_density()) ||
486  ( (BCVars::cons_bc+i == BCVars::RhoTheta_bc_comp) && m_r2d->ingested_theta() ) ||
487  ( (BCVars::cons_bc+i == BCVars::RhoKE_bc_comp) && m_r2d->ingested_KE() ) ||
488  ( (BCVars::cons_bc+i == BCVars::RhoQKE_bc_comp) && m_r2d->ingested_QKE() ) ||
489  ( (BCVars::cons_bc+i == BCVars::RhoScalar_bc_comp) && m_r2d->ingested_scalar() ) ||
490  ( (BCVars::cons_bc+i == BCVars::RhoQ1_bc_comp) && m_r2d->ingested_q1() ) ||
491  ( (BCVars::cons_bc+i == BCVars::RhoQ2_bc_comp) && m_r2d->ingested_q2() )) ) {
493  }
494  }
495  } else {
496  for (int i = 0; i < NVAR_max; i++) {
498  if (input_bndry_planes && dir < 2 && (
499  ( (BCVars::cons_bc+i == BCVars::Rho_bc_comp) && m_r2d->ingested_density()) ||
500  ( (BCVars::cons_bc+i == BCVars::RhoTheta_bc_comp) && m_r2d->ingested_theta() ) ||
501  ( (BCVars::cons_bc+i == BCVars::RhoKE_bc_comp) && m_r2d->ingested_KE() ) ||
502  ( (BCVars::cons_bc+i == BCVars::RhoQKE_bc_comp) && m_r2d->ingested_QKE() ) ||
503  ( (BCVars::cons_bc+i == BCVars::RhoScalar_bc_comp) && m_r2d->ingested_scalar() ) ||
504  ( (BCVars::cons_bc+i == BCVars::RhoQ1_bc_comp) && m_r2d->ingested_q1() ) ||
505  ( (BCVars::cons_bc+i == BCVars::RhoQ2_bc_comp) && m_r2d->ingested_q2() )
506  ) ) {
508  }
509  }
510  }
511  }
512  else if (bct == ERF_BC::periodic)
513  {
514  if (side == Orientation::low) {
515  for (int i = 0; i < NVAR_max; i++) {
517  }
518  } else {
519  for (int i = 0; i < NVAR_max; i++) {
521  }
522  }
523  }
524  else if ( bct == ERF_BC::MOST )
525  {
526  AMREX_ALWAYS_ASSERT(dir == 2 && side == Orientation::low);
527  for (int i = 0; i < NVAR_max; i++) {
529  }
530  }
531  }
532  }
533 
534  // NOTE: Gpu:copy is a wrapper to htod_memcpy (GPU) or memcpy (CPU) and is a blocking comm
535  Gpu::copy(Gpu::hostToDevice, domain_bcs_type.begin(), domain_bcs_type.end(), domain_bcs_type_d.begin());
536 }
#define NVAR_max
Definition: IndexDefines.H:27
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NVAR_max > m_bc_neumann_vals
Definition: ERF.H:716
amrex::Array< std::string, 2 *AMREX_SPACEDIM > domain_bc_type
Definition: ERF.H:710
@ RhoScalar_bc_comp
Definition: IndexDefines.H:52
@ RhoKE_bc_comp
Definition: IndexDefines.H:50
@ RhoQKE_bc_comp
Definition: IndexDefines.H:51
@ RhoTheta_bc_comp
Definition: IndexDefines.H:49
@ RhoQ2_bc_comp
Definition: IndexDefines.H:54
@ Rho_bc_comp
Definition: IndexDefines.H:48
@ neumann
Definition: IndexDefines.H:155
@ open
Definition: IndexDefines.H:157
@ reflect_odd
Definition: IndexDefines.H:148
@ foextrap
Definition: IndexDefines.H:151
@ ext_dir
Definition: IndexDefines.H:152
@ int_dir
Definition: IndexDefines.H:149
@ neumann_int
Definition: IndexDefines.H:156
@ reflect_even
Definition: IndexDefines.H:150
Here is the call graph for this function:

◆ init_custom()

void ERF::init_custom ( int  lev)
private

Wrapper for custom problem-specific initialization routines that can be defined by the user as they set up a new problem in ERF. This wrapper handles all the overhead of defining the perturbation as well as initializing the random seed if needed.

This wrapper calls a user function to customize initialization on a per-Fab level inside an MFIter loop, so all the MultiFab operations are hidden from the user.

Parameters
levInteger specifying the current level
27 {
28  auto& lev_new = vars_new[lev];
29 
30  MultiFab r_hse(base_state[lev], make_alias, 0, 1); // r_0 is first component
31  MultiFab p_hse(base_state[lev], make_alias, 1, 1); // p_0 is second component
32 
33  MultiFab cons_pert(lev_new[Vars::cons].boxArray(), lev_new[Vars::cons].DistributionMap(),
34  lev_new[Vars::cons].nComp() , lev_new[Vars::cons].nGrow());
35  MultiFab xvel_pert(lev_new[Vars::xvel].boxArray(), lev_new[Vars::xvel].DistributionMap(), 1, lev_new[Vars::xvel].nGrowVect());
36  MultiFab yvel_pert(lev_new[Vars::yvel].boxArray(), lev_new[Vars::yvel].DistributionMap(), 1, lev_new[Vars::yvel].nGrowVect());
37  MultiFab zvel_pert(lev_new[Vars::zvel].boxArray(), lev_new[Vars::zvel].DistributionMap(), 1, lev_new[Vars::zvel].nGrowVect());
38 
39  // Default all perturbations to zero
40  cons_pert.setVal(0.);
41  xvel_pert.setVal(0.);
42  yvel_pert.setVal(0.);
43  zvel_pert.setVal(0.);
44 
45  int fix_random_seed = 0;
46  ParmParse pp("erf"); pp.query("fix_random_seed", fix_random_seed);
47  // Note that the value of 1024UL is not significant -- the point here is just to set the
48  // same seed for all MPI processes for the purpose of regression testing
49  if (fix_random_seed) {
50  Print() << "Fixing the random seed" << std::endl;
51  InitRandom(1024UL);
52  }
53 
54 #ifdef _OPENMP
55 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
56 #endif
57  for (MFIter mfi(lev_new[Vars::cons], TileNoZ()); mfi.isValid(); ++mfi)
58  {
59  const Box &bx = mfi.tilebox();
60  const Box &xbx = mfi.tilebox(IntVect(1,0,0));
61  const Box &ybx = mfi.tilebox(IntVect(0,1,0));
62  const Box &zbx = mfi.tilebox(IntVect(0,0,1));
63 
64 
65  const auto &cons_pert_arr = cons_pert.array(mfi);
66  const auto &xvel_pert_arr = xvel_pert.array(mfi);
67  const auto &yvel_pert_arr = yvel_pert.array(mfi);
68  const auto &zvel_pert_arr = zvel_pert.array(mfi);
69 
70  Array4<Real const> cons_arr = lev_new[Vars::cons].const_array(mfi);
71  Array4<Real const> z_nd_arr = (solverChoice.use_terrain) ? z_phys_nd[lev]->const_array(mfi) : Array4<Real const>{};
72  Array4<Real const> z_cc_arr = (solverChoice.use_terrain) ? z_phys_cc[lev]->const_array(mfi) : Array4<Real const>{};
73 
74  Array4<Real const> mf_m = mapfac_m[lev]->array(mfi);
75  Array4<Real const> mf_u = mapfac_m[lev]->array(mfi);
76  Array4<Real const> mf_v = mapfac_m[lev]->array(mfi);
77 
78  Array4<Real> r_hse_arr = r_hse.array(mfi);
79  Array4<Real> p_hse_arr = p_hse.array(mfi);
80 
81  prob->init_custom_pert(bx, xbx, ybx, zbx, cons_arr, cons_pert_arr,
82  xvel_pert_arr, yvel_pert_arr, zvel_pert_arr,
83  r_hse_arr, p_hse_arr, z_nd_arr, z_cc_arr,
84  geom[lev].data(), mf_m, mf_u, mf_v,
85  solverChoice);
86  } //mfi
87 
88  // Add problem-specific perturbation to background flow
89  MultiFab::Add(lev_new[Vars::cons], cons_pert, Rho_comp, Rho_comp, 1, cons_pert.nGrow());
90  MultiFab::Add(lev_new[Vars::cons], cons_pert, RhoTheta_comp, RhoTheta_comp, 1, cons_pert.nGrow());
91  MultiFab::Add(lev_new[Vars::cons], cons_pert, RhoScalar_comp,RhoScalar_comp,1, cons_pert.nGrow());
92 
93  // RhoKE is only relevant if using Deardorff with LES
94  if (solverChoice.turbChoice[lev].les_type == LESType::Deardorff) {
95  MultiFab::Add(lev_new[Vars::cons], cons_pert, RhoKE_comp, RhoKE_comp, 1, cons_pert.nGrow());
96  }
97 
98  // RhoQKE is only relevant if using MYNN2.5 or YSU
99  if (solverChoice.turbChoice[lev].pbl_type == PBLType::None) {
100  lev_new[Vars::cons].setVal(0.0,RhoQKE_comp,1);
101  } else {
102  MultiFab::Add(lev_new[Vars::cons], cons_pert, RhoQKE_comp, RhoQKE_comp, 1, cons_pert.nGrow());
103  }
104 
106  int qstate_size = micro->Get_Qstate_Size();
107  MultiFab::Add(lev_new[Vars::cons], cons_pert, RhoQ1_comp, RhoQ1_comp, 1, cons_pert.nGrow());
108  MultiFab::Add(lev_new[Vars::cons], cons_pert, RhoQ2_comp, RhoQ2_comp, 1, cons_pert.nGrow());
109  for (int q_offset(2); q_offset<qstate_size; ++q_offset) {
110  int q_idx = RhoQ1_comp+q_offset;
111  MultiFab::Add(lev_new[Vars::cons], cons_pert, q_idx, q_idx, 1, cons_pert.nGrow());
112  }
113  }
114 
115  MultiFab::Add(lev_new[Vars::xvel], xvel_pert, 0, 0, 1, xvel_pert.nGrowVect());
116  MultiFab::Add(lev_new[Vars::yvel], yvel_pert, 0, 0, 1, yvel_pert.nGrowVect());
117  MultiFab::Add(lev_new[Vars::zvel], zvel_pert, 0, 0, 1, zvel_pert.nGrowVect());
118 }
#define RhoScalar_comp
Definition: IndexDefines.H:16
Here is the call graph for this function:

◆ init_from_hse()

void ERF::init_from_hse ( int  lev)

Initialize the background flow to have the calculated HSE density and rho*theta calculated from the HSE pressure. In general, the hydrostatically balanced density and pressure (r_hse and p_hse from base_state) used here may be calculated through a solver path such as:

ERF::initHSE(lev)

  • call prob->erf_init_dens_hse(...)
    • call Problem::init_isentropic_hse(...), to simultaneously calculate r_hse and p_hse with Newton iteration – assuming constant theta
    • save r_hse
  • call ERF::enforce_hse(...), calculates p_hse from saved r_hse (redundant, but needed because p_hse is not necessarily calculated by the Problem implementation) and pi_hse – note: this pressure does not exactly match the p_hse from before because what is calculated by init_isentropic_hse comes from the EOS whereas what is calculated here comes from the hydro- static equation
Parameters
levInteger specifying the current level
35 {
36  auto& lev_new = vars_new[lev];
37 
38  MultiFab r_hse(base_state[lev], make_alias, 0, 1); // r_0 is first component
39  MultiFab p_hse(base_state[lev], make_alias, 1, 1); // p_0 is second component
40 
41 #ifdef _OPENMP
42 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
43 #endif
44  for (MFIter mfi(lev_new[Vars::cons], TileNoZ()); mfi.isValid(); ++mfi)
45  {
46  const Box &gbx = mfi.growntilebox(1);
47  const Array4<Real >& cons_arr = lev_new[Vars::cons].array(mfi);
48  const Array4<Real const>& r_hse_arr = r_hse.const_array(mfi);
49  const Array4<Real const>& p_hse_arr = p_hse.const_array(mfi);
50 
51  ParallelFor(gbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
52  {
53  cons_arr(i,j,k,Rho_comp) = r_hse_arr(i,j,k);
54  cons_arr(i,j,k,RhoTheta_comp) = getRhoThetagivenP(p_hse_arr(i,j,k));
55  });
56  } //mfi
57 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getRhoThetagivenP(const amrex::Real p, const amrex::Real qv=0.0)
Definition: EOS.H:130
Here is the call graph for this function:

◆ init_from_input_sounding()

void ERF::init_from_input_sounding ( int  lev)

High level wrapper for initializing scalar and velocity level data from input sounding data.

Parameters
levInteger specifying the current level
50 {
51  // We only want to read the file once -- here we fill one FArrayBox (per variable) that spans the domain
52  if (lev == 0) {
53  if (input_sounding_file.empty())
54  Error("input_sounding file name must be provided via input");
55 
56  // this will interpolate the input profiles to the nominal height levels
57  // (ranging from 0 to the domain top)
59 
60  // this will calculate the hydrostatically balanced density and pressure
61  // profiles following WRF ideal.exe
63  }
64 
65  auto& lev_new = vars_new[lev];
66 
67  // update if init_sounding_ideal == true
68  MultiFab r_hse (base_state[lev], make_alias, 0, 1); // r_0 is first component
69  MultiFab p_hse (base_state[lev], make_alias, 1, 1); // p_0 is second component
70  MultiFab pi_hse(base_state[lev], make_alias, 2, 1); // pi_0 is third component
71 
72  const Real l_gravity = solverChoice.gravity;
73  const Real l_rdOcp = solverChoice.rdOcp;
74  const bool l_moist = (solverChoice.moisture_type != MoistureType::None);
75 
76 #ifdef _OPENMP
77 #pragma omp parallel if (Gpu::notInLaunchRegion())
78 #endif
79  for (MFIter mfi(lev_new[Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
80  const Box &bx = mfi.tilebox();
81  const auto &cons_arr = lev_new[Vars::cons].array(mfi);
82  const auto &xvel_arr = lev_new[Vars::xvel].array(mfi);
83  const auto &yvel_arr = lev_new[Vars::yvel].array(mfi);
84  const auto &zvel_arr = lev_new[Vars::zvel].array(mfi);
85  Array4<Real> r_hse_arr = r_hse.array(mfi);
86  Array4<Real> p_hse_arr = p_hse.array(mfi);
87  Array4<Real> pi_hse_arr = pi_hse.array(mfi);
88 
89  Array4<Real const> z_cc_arr = (solverChoice.use_terrain) ? z_phys_cc[lev]->const_array(mfi) : Array4<Real const>{};
90  Array4<Real const> z_nd_arr = (solverChoice.use_terrain) ? z_phys_nd[lev]->const_array(mfi) : Array4<Real const>{};
91 
93  {
94  // HSE will be initialized here, interpolated from values previously
95  // calculated by calc_rho_p()
97  bx, cons_arr,
98  r_hse_arr, p_hse_arr, pi_hse_arr,
99  geom[lev].data(), z_cc_arr,
100  l_gravity, l_rdOcp, l_moist, input_sounding_data);
101  }
102  else
103  {
104  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(!solverChoice.use_terrain,
105  "Terrain is not supported without init_sounding_ideal option.");
106 
107  // HSE will be calculated later with call to initHSE
109  bx, cons_arr,
110  geom[lev].data(), z_cc_arr,
111  l_moist, input_sounding_data);
112  }
113 
115  bx, xvel_arr, yvel_arr, zvel_arr,
116  geom[lev].data(), z_nd_arr,
118 
119  } //mfi
120 }
void init_bx_scalars_from_input_sounding(const Box &bx, Array4< Real > const &state, GeometryData const &geomdata, Array4< const Real > const &z_cc_arr, const bool &l_moist, InputSoundingData const &inputSoundingData)
Definition: ERF_init_from_input_sounding.cpp:132
void init_bx_velocities_from_input_sounding(const Box &bx, Array4< Real > const &x_vel, Array4< Real > const &y_vel, Array4< Real > const &z_vel, GeometryData const &geomdata, Array4< const Real > const &z_nd_arr, InputSoundingData const &inputSoundingData)
Definition: ERF_init_from_input_sounding.cpp:279
void init_bx_scalars_from_input_sounding_hse(const Box &bx, Array4< Real > const &state, Array4< Real > const &r_hse_arr, Array4< Real > const &p_hse_arr, Array4< Real > const &pi_hse_arr, GeometryData const &geomdata, Array4< const Real > const &z_cc_arr, const Real &l_gravity, const Real &l_rdOcp, const bool &l_moist, InputSoundingData const &inputSoundingData)
Definition: ERF_init_from_input_sounding.cpp:191
static bool init_sounding_ideal
Definition: ERF.H:872
static std::string input_sounding_file
Definition: ERF.H:865
InputSoundingData input_sounding_data
Definition: ERF.H:546
void read_from_file(const std::string input_sounding_file, const amrex::Geometry &geom, const amrex::Vector< amrex::Real > &zlevels_stag)
Definition: InputSoundingData.H:24
void calc_rho_p()
Definition: InputSoundingData.H:123
Here is the call graph for this function:

◆ init_only()

void ERF::init_only ( int  lev,
amrex::Real  time 
)
1110 {
1111  t_new[lev] = time;
1112  t_old[lev] = time - 1.e200;
1113 
1114  auto& lev_new = vars_new[lev];
1115  auto& lev_old = vars_old[lev];
1116 
1117  // Loop over grids at this level to initialize our grid data
1118  lev_new[Vars::cons].setVal(0.0); lev_old[Vars::cons].setVal(0.0);
1119  lev_new[Vars::xvel].setVal(0.0); lev_old[Vars::xvel].setVal(0.0);
1120  lev_new[Vars::yvel].setVal(0.0); lev_old[Vars::yvel].setVal(0.0);
1121  lev_new[Vars::zvel].setVal(0.0); lev_old[Vars::zvel].setVal(0.0);
1122 
1123  // Initialize background flow (optional)
1124  if (init_type == "input_sounding") {
1125  // The base state is initialized by integrating vertically through the
1126  // input sounding, if the init_sounding_ideal flag is set; otherwise
1127  // it is set by initHSE()
1129  if (init_sounding_ideal) {
1130  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(solverChoice.use_gravity,
1131  "Gravity should be on to be consistent with sounding initialization.");
1132  } else {
1133  initHSE();
1134  }
1135 
1136 #ifdef ERF_USE_NETCDF
1137  } else if (init_type == "ideal" || init_type == "real") {
1138  // The base state is initialized from WRF wrfinput data, output by
1139  // ideal.exe or real.exe
1140  init_from_wrfinput(lev);
1141  if (init_type == "ideal") initHSE();
1142 
1143  } else if (init_type == "metgrid") {
1144  // The base state is initialized from data output by WPS metgrid;
1145  // we will rebalance after interpolation
1146  init_from_metgrid(lev);
1147 #endif
1148  } else if (init_type == "uniform") {
1149  // Initialize a uniform background field and base state based on the
1150  // problem-specified reference density and temperature
1151  init_uniform(lev);
1152  initHSE(lev);
1153  } else {
1154  // No background flow initialization specified, initialize the
1155  // background field to be equal to the base state, calculated from the
1156  // problem-specific erf_init_dens_hse
1157  initHSE(lev); // need to call this first
1158  init_from_hse(lev);
1159  }
1160 
1161  // Add problem-specific flow features
1162  //
1163  // Notes:
1164  // - This calls init_custom_pert that is defined for each problem
1165  // - This may modify the base state
1166  // - The fields set by init_custom_pert are **perturbations** to the
1167  // background flow set based on init_type
1168  init_custom(lev);
1169 
1170  // Ensure that the face-based data are the same on both sides of a periodic domain.
1171  // The data associated with the lower grid ID is considered the correct value.
1172  lev_new[Vars::xvel].OverrideSync(geom[lev].periodicity());
1173  lev_new[Vars::yvel].OverrideSync(geom[lev].periodicity());
1174  lev_new[Vars::zvel].OverrideSync(geom[lev].periodicity());
1175 
1176  // Initialize wind farm
1177 
1178 #ifdef ERF_USE_WINDFARM
1179  init_windfarm(lev);
1180 #endif
1181 
1182  if(solverChoice.spongeChoice.sponge_type == "input_sponge"){
1183  input_sponge(lev);
1184  }
1185 
1186 }
void init_from_input_sounding(int lev)
Definition: ERF_init_from_input_sounding.cpp:49
void init_custom(int lev)
Definition: ERF_init_custom.cpp:26
void init_from_hse(int lev)
Definition: ERF_init_from_hse.cpp:34
void initHSE()
Initialize HSE.
Definition: ERF_init1d.cpp:240
void input_sponge(int lev)
Definition: ERF_input_sponge.cpp:20
void init_uniform(int lev)
Definition: ERF_init_uniform.cpp:17
static std::string init_type
Definition: ERF.H:847
bool use_gravity
Definition: DataStruct.H:399

◆ init_stuff()

void ERF::init_stuff ( int  lev,
const amrex::BoxArray &  ba,
const amrex::DistributionMapping &  dm,
amrex::Vector< amrex::MultiFab > &  lev_new,
amrex::Vector< amrex::MultiFab > &  lev_old 
)
private
28 {
29  if (lev == 0) {
30  min_k_at_level[lev] = 0;
31  max_k_at_level[lev] = geom[lev].Domain().bigEnd(2);
32  } else {
33  // Start with unreasonable values so we compute the right min/max
34  min_k_at_level[lev] = geom[lev].Domain().bigEnd(2);
35  max_k_at_level[lev] = geom[lev].Domain().smallEnd(2);
36  for (int n = 0; n < ba.size(); n++)
37  {
38  min_k_at_level[lev] = std::min(min_k_at_level[lev], ba[n].smallEnd(2));
39  max_k_at_level[lev] = std::max(max_k_at_level[lev], ba[n].bigEnd(2));
40  }
41  }
42 
43  // ********************************************************************************************
44  // Base state holds r_0, pres_0, pi_0 (in that order)
45  // ********************************************************************************************
46  base_state[lev].define(ba,dm,3,1);
47  base_state[lev].setVal(0.);
48 
50  base_state_new[lev].define(ba,dm,3,1);
51  base_state_new[lev].setVal(0.);
52  }
53 
54  // ********************************************************************************************
55  // Allocate terrain arrays
56  // ********************************************************************************************
58  z_phys_cc[lev] = std::make_unique<MultiFab>(ba,dm,1,1);
59 
61  {
62  detJ_cc_new[lev] = std::make_unique<MultiFab>(ba,dm,1,1);
63  detJ_cc_src[lev] = std::make_unique<MultiFab>(ba,dm,1,1);
64 
65  ax_src[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(1,0,0)),dm,1,1);
66  ay_src[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(0,1,0)),dm,1,1);
67  az_src[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(0,0,1)),dm,1,1);
68 
69  ax_new[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(1,0,0)),dm,1,1);
70  ay_new[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(0,1,0)),dm,1,1);
71  az_new[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(0,0,1)),dm,1,1);
72 
73  z_t_rk[lev] = std::make_unique<MultiFab>( convert(ba, IntVect(0,0,1)), dm, 1, 1 );
74  }
75 
76  BoxArray ba_nd(ba);
77  ba_nd.surroundingNodes();
78 
79  // We need this to be one greater than the ghost cells to handle levels > 0
81  z_phys_nd[lev] = std::make_unique<MultiFab>(ba_nd,dm,1,IntVect(ngrow,ngrow,1));
83  z_phys_nd_new[lev] = std::make_unique<MultiFab>(ba_nd,dm,1,IntVect(ngrow,ngrow,1));
84  z_phys_nd_src[lev] = std::make_unique<MultiFab>(ba_nd,dm,1,IntVect(ngrow,ngrow,1));
85  }
86 
87  } else {
88  z_phys_nd[lev] = nullptr;
89  z_phys_cc[lev] = nullptr;
90 
91  z_phys_nd_new[lev] = nullptr;
92  detJ_cc_new[lev] = nullptr;
93 
94  z_phys_nd_src[lev] = nullptr;
95  detJ_cc_src[lev] = nullptr;
96 
97  z_t_rk[lev] = nullptr;
98  }
99 
100  // We use these area arrays regardless of terrain, EB or none of the above
101  detJ_cc[lev] = std::make_unique<MultiFab>(ba,dm,1,1);
102  ax[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(1,0,0)),dm,1,1);
103  ay[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(0,1,0)),dm,1,1);
104  az[lev] = std::make_unique<MultiFab>(convert(ba,IntVect(0,0,1)),dm,1,1);
105 
106  detJ_cc[lev]->setVal(1.0);
107  ax[lev]->setVal(1.0);
108  ay[lev]->setVal(1.0);
109  az[lev]->setVal(1.0);
110 
111  // ********************************************************************************************
112  // These are the persistent containers for the old and new data
113  // ********************************************************************************************
114  int ncomp;
115  if (lev > 0) {
116  ncomp = vars_new[lev-1][Vars::cons].nComp();
117  } else {
118  int n_qstate = micro->Get_Qstate_Size();
119  ncomp = NVAR_max - (NMOIST_max - n_qstate);
120  }
121 
122  // ********************************************************************************************
123  // The number of ghost cells for density must be 1 greater than that for velocity
124  // so that we can go back in forth betwen velocity and momentum on all faces
125  // ********************************************************************************************
128 
129  // ********************************************************************************************
130  // New solution data containers
131  // ********************************************************************************************
132  lev_new[Vars::cons].define(ba, dm, ncomp, ngrow_state);
133  lev_old[Vars::cons].define(ba, dm, ncomp, ngrow_state);
134 
135  lev_new[Vars::xvel].define(convert(ba, IntVect(1,0,0)), dm, 1, ngrow_vels);
136  lev_old[Vars::xvel].define(convert(ba, IntVect(1,0,0)), dm, 1, ngrow_vels);
137 
138  lev_new[Vars::yvel].define(convert(ba, IntVect(0,1,0)), dm, 1, ngrow_vels);
139  lev_old[Vars::yvel].define(convert(ba, IntVect(0,1,0)), dm, 1, ngrow_vels);
140 
141  lev_new[Vars::zvel].define(convert(ba, IntVect(0,0,1)), dm, 1, IntVect(ngrow_vels,ngrow_vels,0));
142  lev_old[Vars::zvel].define(convert(ba, IntVect(0,0,1)), dm, 1, IntVect(ngrow_vels,ngrow_vels,0));
143 
144  // ********************************************************************************************
145  // These are just used for scratch in the time integrator but we might as well define them here
146  // ********************************************************************************************
147  rU_old[lev].define(convert(ba, IntVect(1,0,0)), dm, 1, ngrow_vels);
148  rU_new[lev].define(convert(ba, IntVect(1,0,0)), dm, 1, ngrow_vels);
149 
150  rV_old[lev].define(convert(ba, IntVect(0,1,0)), dm, 1, ngrow_vels);
151  rV_new[lev].define(convert(ba, IntVect(0,1,0)), dm, 1, ngrow_vels);
152 
153  rW_old[lev].define(convert(ba, IntVect(0,0,1)), dm, 1, ngrow_vels);
154  rW_new[lev].define(convert(ba, IntVect(0,0,1)), dm, 1, ngrow_vels);
155 
156  // We do this here just so they won't be undefined in the initial FillPatch
157  rU_new[lev].setVal(1.2e21);
158  rV_new[lev].setVal(3.4e22);
159  rW_new[lev].setVal(5.6e23);
160 
161  // ********************************************************************************************
162  // These are just time averaged fields for diagnostics
163  // ********************************************************************************************
164 
165  // NOTE: We are not completing a fillpach call on the time averaged data;
166  // which would copy on intersection and interpolate from coarse.
167  // Therefore, we are restarting the averaging when the ba changes,
168  // this may give poor statistics for dynamic mesh refinment.
169  vel_t_avg[lev] = nullptr;
171  vel_t_avg[lev] = std::make_unique<MultiFab>(ba, dm, 4, 0); // Each vel comp and the mag
172  vel_t_avg[lev]->setVal(0.0);
173  t_avg_cnt[lev] = 0.0;
174  }
175 
176  // ********************************************************************************************
177  // Initialize flux registers whenever we create/re-create a level
178  // ********************************************************************************************
180  if (lev == 0) {
181  advflux_reg[0] = nullptr;
182  } else {
183  int ncomp_reflux = vars_new[0][Vars::cons].nComp();
184  advflux_reg[lev] = new YAFluxRegister(ba , grids[lev-1],
185  dm , dmap[lev-1],
186  geom[lev], geom[lev-1],
187  ref_ratio[lev-1], lev, ncomp_reflux);
188  }
189  }
190 
191  // ********************************************************************************************
192  // Define Theta_prim storage if using MOST BC
193  // ********************************************************************************************
194  if (phys_bc_type[Orientation(Direction::z,Orientation::low)] == ERF_BC::MOST) {
195  Theta_prim[lev] = std::make_unique<MultiFab>(ba,dm,1,IntVect(ngrow_state,ngrow_state,0));
197  Qv_prim[lev] = std::make_unique<MultiFab>(ba,dm,1,IntVect(ngrow_state,ngrow_state,0));
198  } else {
199  Qv_prim[lev] = nullptr;
200  }
201  } else {
202  Theta_prim[lev] = nullptr;
203  Qv_prim[lev] = nullptr;
204  }
205 
206  // ********************************************************************************************
207  // Map factors
208  // ********************************************************************************************
209  BoxList bl2d = ba.boxList();
210  for (auto& b : bl2d) {
211  b.setRange(2,0);
212  }
213  BoxArray ba2d(std::move(bl2d));
214 
215  mapfac_m[lev] = std::make_unique<MultiFab>(ba2d,dm,1,3);
216  mapfac_u[lev] = std::make_unique<MultiFab>(convert(ba2d,IntVect(1,0,0)),dm,1,3);
217  mapfac_v[lev] = std::make_unique<MultiFab>(convert(ba2d,IntVect(0,1,0)),dm,1,3);
219  mapfac_m[lev]->setVal(0.5);
220  mapfac_u[lev]->setVal(0.5);
221  mapfac_v[lev]->setVal(0.5);
222  }
223  else {
224  mapfac_m[lev]->setVal(1.);
225  mapfac_u[lev]->setVal(1.);
226  mapfac_v[lev]->setVal(1.);
227  }
228 
229 #if defined(ERF_USE_WINDFARM)
230  //*********************************************************
231  // Variables for Ftich model for windfarm parametrization
232  //*********************************************************
235  vars_fitch[lev].define(ba, dm, 5, ngrow_state); // V, dVabsdt, dudt, dvdt, dTKEdt
236  Nturb[lev].define(ba, dm, 1, ngrow_state); // Number of turbines in a cell
237  }
240  vars_ewp[lev].define(ba, dm, 3, ngrow_state); // dudt, dvdt, dTKEdt
241  Nturb[lev].define(ba, dm, 1, ngrow_state); // Number of turbines in a cell
242  }
243 #endif
244 
245 #if defined(ERF_USE_RRTMGP)
246  //*********************************************************
247  // Radiation heating source terms
248  //*********************************************************
249  qheating_rates[lev] = std::make_unique<MultiFab>(ba, dm, 2, ngrow_state);
250  qheating_rates[lev]->setVal(0.);
251 #endif
252 }
#define NMOIST_max
Definition: IndexDefines.H:30
amrex::Vector< int > min_k_at_level
Definition: ERF.H:576
amrex::Vector< int > max_k_at_level
Definition: ERF.H:577
static AMREX_FORCE_INLINE int ComputeGhostCells(const AdvChoice &advChoice, bool use_num_diff)
Definition: ERF.H:955
bool test_mapfactor
Definition: DataStruct.H:393
AdvChoice advChoice
Definition: DataStruct.H:375
TerrainType terrain_type
Definition: DataStruct.H:444

◆ init_uniform()

void ERF::init_uniform ( int  lev)
private

Use problem-specific reference density and temperature to set the background state to a uniform value.

Parameters
levInteger specifying the current level
18 {
19  auto& lev_new = vars_new[lev];
20  for (MFIter mfi(lev_new[Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
21  const Box &gbx = mfi.growntilebox(1);
22  const auto &cons_arr = lev_new[Vars::cons].array(mfi);
23  prob->init_uniform(gbx, cons_arr);
24  }
25 }

◆ InitData()

void ERF::InitData ( )
521 {
522  BL_PROFILE_VAR("ERF::InitData()", InitData);
523 
524  // Initialize the start time for our CPU-time tracker
525  startCPUTime = ParallelDescriptor::second();
526 
527  // Create the ReadBndryPlanes object so we can read boundary plane data
528  // m_r2d is used by init_bcs so we must instantiate this class before
529  if (input_bndry_planes) {
530  Print() << "Defining r2d for the first time " << std::endl;
531  m_r2d = std::make_unique<ReadBndryPlanes>(geom[0], solverChoice.rdOcp);
532  }
533 
534  // Map the words in the inputs file to BC types, then translate
535  // those types into what they mean for each variable
536  init_bcs();
537 
538  // Verify BCs are compatible with solver choice
539  for (int lev(0); lev <= max_level; ++lev) {
540  if ( ( (solverChoice.turbChoice[lev].pbl_type == PBLType::MYNN25) ||
541  (solverChoice.turbChoice[lev].pbl_type == PBLType::YSU) ) &&
542  phys_bc_type[Orientation(Direction::z,Orientation::low)] != ERF_BC::MOST ) {
543  Abort("MYNN2.5/YSU PBL Model requires MOST at lower boundary");
544  }
545  }
546 
548  Abort("We do not allow non-static terrain_type with use_terrain = false");
549  }
550 
554 
555  if (restart_chkfile.empty()) {
556  // start simulation from the beginning
557 
558  const Real time = start_time;
559  InitFromScratch(time);
560 
561 #ifdef ERF_USE_MULTIBLOCK
562 #ifndef ERF_MB_EXTERN // enter only if multiblock does not involve an external class
563  // Multiblock: hook to set BL & comms once ba/dm are known
564  if(domain_p[0].bigEnd(0) < 500 ) {
565  m_mbc->SetBoxLists();
566  m_mbc->SetBlockCommMetaData();
567  }
568 #endif
569 #endif
570 
572  if (init_type == "ideal") {
573  Abort("We do not currently support init_type = ideal with terrain");
574  }
575  }
576 
577  //
578  // Make sure that detJ and z_phys_cc are the average of the data on a finer level if there is one
579  //
580  if (solverChoice.use_terrain != 0) {
581  for (int crse_lev = finest_level-1; crse_lev >= 0; crse_lev--) {
582  average_down( *detJ_cc[crse_lev+1], *detJ_cc[crse_lev], 0, 1, refRatio(crse_lev));
583  average_down(*z_phys_cc[crse_lev+1], *z_phys_cc[crse_lev], 0, 1, refRatio(crse_lev));
584  }
585  }
586 
587  // If using the Deardoff LES model,
588  // we initialize rho_KE to be nonzero (and positive) so that we end up
589  // with reasonable values for the eddy diffusivity and the MOST fluxes
590  // (~ 1/diffusivity) do not blow up
591  Real RhoKE_0;
592  ParmParse pp(pp_prefix);
593  if (pp.query("RhoKE_0", RhoKE_0)) {
594  // Uniform initial rho*e field
595  for (int lev = 0; lev <= finest_level; lev++) {
596  if (solverChoice.turbChoice[lev].les_type == LESType::Deardorff) {
597  Print() << "Initializing uniform rhoKE=" << RhoKE_0
598  << " on level " << lev
599  << std::endl;
600  vars_new[lev][Vars::cons].setVal(RhoKE_0,RhoKE_comp,1,0);
601  } else {
602  vars_new[lev][Vars::cons].setVal(0.0,RhoKE_comp,1,0);
603  }
604  }
605  }
606 
607  Real KE_0;
608  if (pp.query("KE_0", KE_0)) {
609  // Uniform initial e field
610  for (int lev = 0; lev <= finest_level; lev++) {
611  auto& lev_new = vars_new[lev];
612  if (solverChoice.turbChoice[lev].les_type == LESType::Deardorff) {
613  Print() << "Initializing uniform KE=" << KE_0
614  << " on level " << lev
615  << std::endl;
616  for (MFIter mfi(lev_new[Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
617  const Box &bx = mfi.tilebox();
618  const auto &cons_arr = lev_new[Vars::cons].array(mfi);
619  // We want to set the lateral BC values, too
620  Box gbx = bx; // Copy constructor
621  gbx.grow(0,1); gbx.grow(1,1); // Grow by one in the lateral directions
622  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
623  cons_arr(i,j,k,RhoKE_comp) = cons_arr(i,j,k,Rho_comp) * KE_0;
624  });
625  } // mfi
626  } else {
627  lev_new[Vars::cons].setVal(0.0,RhoKE_comp,1,0);
628  }
629  } // lev
630  }
631 
632  Real QKE_0;
633  if (pp.query("QKE_0", QKE_0)) {
634  Print() << "Initializing uniform QKE=" << QKE_0 << std::endl;
635  for (int lev = 0; lev <= finest_level; lev++) {
636  auto& lev_new = vars_new[lev];
637  for (MFIter mfi(lev_new[Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
638  const Box &bx = mfi.tilebox();
639  const auto &cons_arr = lev_new[Vars::cons].array(mfi);
640  // We want to set the lateral BC values, too
641  Box gbx = bx; // Copy constructor
642  gbx.grow(0,1); gbx.grow(1,1); // Grow by one in the lateral directions
643  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
644  cons_arr(i,j,k,RhoQKE_comp) = cons_arr(i,j,k,Rho_comp) * QKE_0;
645  });
646  } // mfi
647  }
648  }
649 
651  AverageDown();
652  }
653 
654  if ((solverChoice.advChoice.zero_xflux.size() > 0) ||
655  (solverChoice.advChoice.zero_yflux.size() > 0) ||
656  (solverChoice.advChoice.zero_zflux.size() > 0))
657  {
658  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(finest_level == 0,
659  "Thin immersed body with refinement not currently supported.");
660  if (solverChoice.use_terrain == 1) {
661  amrex::Print() << "NOTE: Thin immersed body with terrain has not been tested." << std::endl;
662  }
663  }
664 
665  } else { // Restart from a checkpoint
666 
667  restart();
668 
669 
670  // TODO: Check if this is needed. I don't think it is since we now
671  // advect all the scalars...
672 
673  // Need to fill ghost cells here since we will use this qmoist in advance
675  {
676  for (int lev = 0; lev <= finest_level; lev++) {
677  if (qmoist[lev].size() > 0) FillPatchMoistVars(lev, *(qmoist[lev][0])); // qv component
678  }
679  }
680  }
681 
682 #ifdef ERF_USE_PARTICLES
683  /* If using a Lagrangian microphysics model, its particle container has now been
684  constructed and initialized (calls to micro->Init). So, add its pointer to
685  ERF::particleData and remove its name from list of unallocated particle containers. */
687  const auto& pc_name( dynamic_cast<LagrangianMicrophysics&>(*micro).getName() );
688  const auto& pc_ptr( dynamic_cast<LagrangianMicrophysics&>(*micro).getParticleContainer() );
689  particleData.pushBack(pc_name, pc_ptr);
690  particleData.getNamesUnalloc().remove(pc_name);
691  }
692 #endif
693 
694  if (input_bndry_planes) {
695  // Read the "time.dat" file to know what data is available
696  m_r2d->read_time_file();
697 
698  // We haven't populated dt yet, set to 0 to ensure assert doesn't crash
699  Real dt_dummy = 0.0;
700  m_r2d->read_input_files(t_new[0],dt_dummy,m_bc_extdir_vals);
701  }
702 
704  {
705  h_rhotheta_src.resize(max_level+1, Vector<Real>(0));
706  d_rhotheta_src.resize(max_level+1, Gpu::DeviceVector<Real>(0));
707  for (int lev = 0; lev <= finest_level; lev++) {
708  const int domlen = geom[lev].Domain().length(2);
709  h_rhotheta_src[lev].resize(domlen, 0.0_rt);
710  d_rhotheta_src[lev].resize(domlen, 0.0_rt);
711  prob->update_rhotheta_sources(t_new[0],
712  h_rhotheta_src[lev], d_rhotheta_src[lev],
713  geom[lev], z_phys_cc[lev]);
714  }
715  }
716 
718  {
719  h_u_geos.resize(max_level+1, Vector<Real>(0));
720  d_u_geos.resize(max_level+1, Gpu::DeviceVector<Real>(0));
721  h_v_geos.resize(max_level+1, Vector<Real>(0));
722  d_v_geos.resize(max_level+1, Gpu::DeviceVector<Real>(0));
723  for (int lev = 0; lev <= finest_level; lev++) {
724  const int domlen = geom[lev].Domain().length(2);
725  h_u_geos[lev].resize(domlen, 0.0_rt);
726  d_u_geos[lev].resize(domlen, 0.0_rt);
727  h_v_geos[lev].resize(domlen, 0.0_rt);
728  d_v_geos[lev].resize(domlen, 0.0_rt);
729  prob->update_geostrophic_profile(t_new[0],
730  h_u_geos[lev], d_u_geos[lev],
731  h_v_geos[lev], d_v_geos[lev],
732  geom[lev], z_phys_cc[lev]);
733  }
734  }
735 
737  {
738  h_rhoqt_src.resize(max_level+1, Vector<Real>(0));
739  d_rhoqt_src.resize(max_level+1, Gpu::DeviceVector<Real>(0));
740  for (int lev = 0; lev <= finest_level; lev++) {
741  const int domlen = geom[lev].Domain().length(2);
742  h_rhoqt_src[lev].resize(domlen, 0.0_rt);
743  d_rhoqt_src[lev].resize(domlen, 0.0_rt);
744  prob->update_rhoqt_sources(t_new[0],
745  h_rhoqt_src[lev], d_rhoqt_src[lev],
746  geom[lev], z_phys_cc[lev]);
747  }
748  }
749 
751  {
752  h_w_subsid.resize(max_level+1, Vector<Real>(0));
753  d_w_subsid.resize(max_level+1, Gpu::DeviceVector<Real>(0));
754  for (int lev = 0; lev <= finest_level; lev++) {
755  const int domlen = geom[lev].Domain().length(2);
756  h_w_subsid[lev].resize(domlen, 0.0_rt);
757  d_w_subsid[lev].resize(domlen, 0.0_rt);
758  prob->update_w_subsidence(t_new[0],
759  h_w_subsid[lev], d_w_subsid[lev],
760  geom[lev], z_phys_cc[lev]);
761  }
762  }
763 
766  {
767  initRayleigh();
768  if (init_type == "input_sounding")
769  {
770  // Overwrite ubar, vbar, and thetabar with input profiles;
771  // wbar is assumed to be 0. Note: the tau coefficient set by
772  // prob->erf_init_rayleigh() is still used
773  bool restarting = (!restart_chkfile.empty());
774  setRayleighRefFromSounding(restarting);
775  }
776  }
777 
778  // Read in sponge data from input file
779  if(solverChoice.spongeChoice.sponge_type == "input_sponge")
780  {
781  initSponge();
782  bool restarting = (!restart_chkfile.empty());
783  setSpongeRefFromSounding(restarting);
784  }
785 
788  if (cc_profiles) {
789  // all variables cell-centered
791  } else {
792  // some variables staggered
794  }
795  }
796 
797  // We only write the file at level 0 for now
799  {
800  // Create the WriteBndryPlanes object so we can handle writing of boundary plane data
801  m_w2d = std::make_unique<WriteBndryPlanes>(grids,geom);
802 
803  Real time = 0.;
804  if (time >= bndry_output_planes_start_time) {
805  m_w2d->write_planes(0, time, vars_new);
806  }
807  }
808 
809 #ifdef ERF_USE_POISSON_SOLVE
810  if (restart_chkfile == "")
811  {
812  // Note -- this projection is only defined for no terrain
813  if (solverChoice.project_initial_velocity) {
814  AMREX_ALWAYS_ASSERT(solverChoice.use_terrain == 0);
815  project_velocities(vars_new);
816  }
817  }
818 #endif
819  // Copy from new into old just in case
820  for (int lev = 0; lev <= finest_level; ++lev)
821  {
822  auto& lev_new = vars_new[lev];
823  auto& lev_old = vars_old[lev];
824 
825  int ncomp = lev_new[Vars::cons].nComp();
826 
827  MultiFab::Copy(lev_old[Vars::cons],lev_new[Vars::cons],0,0,ncomp,lev_new[Vars::cons].nGrowVect());
828  MultiFab::Copy(lev_old[Vars::xvel],lev_new[Vars::xvel],0,0, 1,lev_new[Vars::xvel].nGrowVect());
829  MultiFab::Copy(lev_old[Vars::yvel],lev_new[Vars::yvel],0,0, 1,lev_new[Vars::yvel].nGrowVect());
830  MultiFab::Copy(lev_old[Vars::zvel],lev_new[Vars::zvel],0,0, 1,lev_new[Vars::zvel].nGrowVect());
831  }
832 
833  // Compute the minimum dz in the domain (to be used for setting the timestep)
834  dz_min = geom[0].CellSize(2);
835  if ( solverChoice.use_terrain ) {
836  dz_min *= (*detJ_cc[0]).min(0);
837  }
838 
839  ComputeDt();
840 
841  // Fill ghost cells/faces
842  for (int lev = 0; lev <= finest_level; ++lev)
843  {
844  if (lev > 0 && cf_width >= 0) {
846  }
847 
848  //
849  // Fill boundary conditions -- not sure why we need this here
850  //
851  bool fillset = false;
852  auto& lev_new = vars_new[lev];
853  FillPatch(lev, t_new[lev],
854  {&lev_new[Vars::cons],&lev_new[Vars::xvel],&lev_new[Vars::yvel],&lev_new[Vars::zvel]},
855  {&lev_new[Vars::cons],&rU_new[lev],&rV_new[lev],&rW_new[lev]},
856  fillset);
857 
858  //
859  // We do this here to make sure level (lev-1) boundary conditions are filled
860  // before we interpolate to level (lev) ghost cells
861  //
862  if (lev < finest_level) {
863  auto& lev_old = vars_old[lev];
864  MultiFab::Copy(lev_old[Vars::cons],lev_new[Vars::cons],0,0,lev_old[Vars::cons].nComp(),lev_old[Vars::cons].nGrowVect());
865  MultiFab::Copy(lev_old[Vars::xvel],lev_new[Vars::xvel],0,0,lev_old[Vars::xvel].nComp(),lev_old[Vars::xvel].nGrowVect());
866  MultiFab::Copy(lev_old[Vars::yvel],lev_new[Vars::yvel],0,0,lev_old[Vars::yvel].nComp(),lev_old[Vars::yvel].nGrowVect());
867  MultiFab::Copy(lev_old[Vars::zvel],lev_new[Vars::zvel],0,0,lev_old[Vars::zvel].nComp(),lev_old[Vars::zvel].nGrowVect());
868  }
869 
870  //
871  // We fill the ghost cell values of the base state in case it wasn't done in the initialization
872  //
873  base_state[lev].FillBoundary(geom[lev].periodicity());
874 
875  // For moving terrain only
877  MultiFab::Copy(base_state_new[lev],base_state[lev],0,0,3,1);
878  base_state_new[lev].FillBoundary(geom[lev].periodicity());
879  }
880  }
881 
882  // Configure ABLMost params if used MostWall boundary condition
883  // NOTE: we must set up the MOST routine after calling FillPatch
884  // in order to have lateral ghost cells filled (MOST + terrain interp).
885  // FillPatch does not call MOST, FillIntermediatePatch does.
886  if (phys_bc_type[Orientation(Direction::z,Orientation::low)] == ERF_BC::MOST)
887  {
888 #ifdef ERF_EXPLICIT_MOST_STRESS
889  Print() << "Using MOST with explicitly included surface stresses" << std::endl;
890 #endif
891 
892  m_most = std::make_unique<ABLMost>(geom, vars_old, Theta_prim, Qv_prim, z_phys_nd,
894 #ifdef ERF_USE_NETCDF
895  ,start_bdy_time, bdy_time_interval
896 #endif
897  );
898 
899  // We now configure ABLMost params here so that we can print the averages at t=0
900  // Note we don't fill ghost cells here because this is just for diagnostics
901  for (int lev = 0; lev <= finest_level; ++lev)
902  {
903  Real time = t_new[lev];
904  IntVect ng = Theta_prim[lev]->nGrowVect();
905  MultiFab S(vars_new[lev][Vars::cons],make_alias,0,RhoTheta_comp+1);
906  MultiFab::Copy( *Theta_prim[lev], S, RhoTheta_comp, 0, 1, ng);
907  MultiFab::Divide(*Theta_prim[lev], S, Rho_comp , 0, 1, ng);
909  ng = Qv_prim[lev]->nGrowVect();
910  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,RhoQ1_comp+1);
911  MultiFab::Copy( *Qv_prim[lev], Sm, RhoQ1_comp, 0, 1, ng);
912  MultiFab::Divide(*Qv_prim[lev], Sm, Rho_comp , 0, 1, ng);
913  }
914  m_most->update_mac_ptrs(lev, vars_new, Theta_prim, Qv_prim);
915  m_most->update_fluxes(lev, time);
916  }
917  }
918 
919  // Update micro vars before first plot file
921  for (int lev = 0; lev <= finest_level; ++lev) micro->Update_Micro_Vars_Lev(lev, vars_new[lev][Vars::cons]);
922  }
923 
924  // Fill time averaged velocities before first plot file
926  for (int lev = 0; lev <= finest_level; ++lev) {
927  Time_Avg_Vel_atCC(dt[lev], t_avg_cnt[lev], vel_t_avg[lev].get(),
928  vars_new[lev][Vars::xvel],
929  vars_new[lev][Vars::yvel],
930  vars_new[lev][Vars::zvel]);
931  }
932  }
933 
934  // check for additional plotting variables that are available after particle containers
935  // are setup.
936  const std::string& pv1 = "plot_vars_1"; appendPlotVariables(pv1,plot_var_names_1);
937  const std::string& pv2 = "plot_vars_2"; appendPlotVariables(pv2,plot_var_names_2);
938 
939  if ( restart_chkfile.empty() && (m_check_int > 0 || m_check_per > 0.) )
940  {
941 #ifdef ERF_USE_NETCDF
942  if (check_type == "netcdf") {
943  WriteNCCheckpointFile();
944  }
945 #endif
946  if (check_type == "native") {
948  }
950  }
951 
952  if ( (restart_chkfile.empty()) ||
953  (!restart_chkfile.empty() && plot_file_on_restart) )
954  {
955  if (m_plot_int_1 > 0 || m_plot_per_1 > 0.)
956  {
959  }
960  if (m_plot_int_2 > 0 || m_plot_per_2 > 0.)
961  {
964  }
965  }
966 
967  // Set these up here because we need to know which MPI rank "cell" is on...
968  ParmParse pp("erf");
969  if (pp.contains("data_log"))
970  {
971  int num_datalogs = pp.countval("data_log");
972  datalog.resize(num_datalogs);
973  datalogname.resize(num_datalogs);
974  pp.queryarr("data_log",datalogname,0,num_datalogs);
975  for (int i = 0; i < num_datalogs; i++)
977  }
978 
979  if (pp.contains("sample_point_log") && pp.contains("sample_point"))
980  {
981  int lev = 0;
982 
983  int num_samplepts = pp.countval("sample_point") / AMREX_SPACEDIM;
984  if (num_samplepts > 0) {
985  Vector<int> index; index.resize(num_samplepts*AMREX_SPACEDIM);
986  samplepoint.resize(num_samplepts);
987 
988  pp.queryarr("sample_point",index,0,num_samplepts*AMREX_SPACEDIM);
989  for (int i = 0; i < num_samplepts; i++) {
990  IntVect iv(index[AMREX_SPACEDIM*i+0],index[AMREX_SPACEDIM*i+1],index[AMREX_SPACEDIM*i+2]);
991  samplepoint[i] = iv;
992  }
993  }
994 
995  int num_sampleptlogs = pp.countval("sample_point_log");
996  AMREX_ALWAYS_ASSERT(num_sampleptlogs == num_samplepts);
997  if (num_sampleptlogs > 0) {
998  sampleptlog.resize(num_sampleptlogs);
999  sampleptlogname.resize(num_sampleptlogs);
1000  pp.queryarr("sample_point_log",sampleptlogname,0,num_sampleptlogs);
1001 
1002  for (int i = 0; i < num_sampleptlogs; i++) {
1004  }
1005  }
1006 
1007  }
1008 
1009  if (pp.contains("sample_line_log") && pp.contains("sample_line"))
1010  {
1011  int lev = 0;
1012 
1013  int num_samplelines = pp.countval("sample_line") / AMREX_SPACEDIM;
1014  if (num_samplelines > 0) {
1015  Vector<int> index; index.resize(num_samplelines*AMREX_SPACEDIM);
1016  sampleline.resize(num_samplelines);
1017 
1018  pp.queryarr("sample_line",index,0,num_samplelines*AMREX_SPACEDIM);
1019  for (int i = 0; i < num_samplelines; i++) {
1020  IntVect iv(index[AMREX_SPACEDIM*i+0],index[AMREX_SPACEDIM*i+1],index[AMREX_SPACEDIM*i+2]);
1021  sampleline[i] = iv;
1022  }
1023  }
1024 
1025  int num_samplelinelogs = pp.countval("sample_line_log");
1026  AMREX_ALWAYS_ASSERT(num_samplelinelogs == num_samplelines);
1027  if (num_samplelinelogs > 0) {
1028  samplelinelog.resize(num_samplelinelogs);
1029  samplelinelogname.resize(num_samplelinelogs);
1030  pp.queryarr("sample_line_log",samplelinelogname,0,num_samplelinelogs);
1031 
1032  for (int i = 0; i < num_samplelinelogs; i++) {
1034  }
1035  }
1036 
1037  }
1038 
1039  BL_PROFILE_VAR_STOP(InitData);
1040 
1041 #ifdef ERF_USE_EB
1042  bool write_eb_surface = false;
1043  pp.query("write_eb_surface", write_eb_surface);
1044  if (write_eb_surface) WriteMyEBSurface();
1045 #endif
1046 
1047 }
void initRayleigh()
Initialize Rayleigh damping profiles.
Definition: ERF_init1d.cpp:18
amrex::Vector< std::string > samplelinelogname
Definition: ERF.H:1139
void setRayleighRefFromSounding(bool restarting)
Set Rayleigh mean profiles from input sounding.
Definition: ERF_init1d.cpp:56
amrex::Vector< amrex::IntVect > sampleline
Definition: ERF.H:1140
amrex::Vector< amrex::Vector< amrex::Real > > h_w_subsid
Definition: ERF.H:901
static amrex::Real sum_per
Definition: ERF.H:841
void setRecordDataInfo(int i, const std::string &filename)
Definition: ERF.H:1084
bool cc_profiles
Definition: ERF.H:775
void write_1D_profiles_stag(amrex::Real time)
Definition: ERF_Write1DProfiles_stag.cpp:21
amrex::Vector< std::unique_ptr< std::fstream > > samplelinelog
Definition: ERF.H:1138
static int sum_interval
Definition: ERF.H:840
void restart()
Definition: ERF.cpp:1078
void write_1D_profiles(amrex::Real time)
Definition: ERF_Write1DProfiles.cpp:15
void init_bcs()
Definition: ERF_init_bcs.cpp:21
void appendPlotVariables(const std::string &pp_plot_var_names, amrex::Vector< std::string > &plot_var_names)
Definition: Plotfile.cpp:96
static int output_bndry_planes
Definition: ERF.H:883
void AverageDown()
Definition: ERF.cpp:1588
static amrex::Real bndry_output_planes_start_time
Definition: ERF.H:886
std::string restart_chkfile
Definition: ERF.H:747
amrex::Vector< std::string > sampleptlogname
Definition: ERF.H:1135
void sum_integrated_quantities(amrex::Real time)
Definition: ERF_WriteScalarProfiles.cpp:14
amrex::Vector< std::unique_ptr< std::fstream > > sampleptlog
Definition: ERF.H:1134
amrex::Real start_time
Definition: ERF.H:743
std::unique_ptr< WriteBndryPlanes > m_w2d
Definition: ERF.H:936
void initSponge()
Initialize sponge profiles.
Definition: ERF_init1d.cpp:122
static bool is_it_time_for_action(int nstep, amrex::Real time, amrex::Real dt, int action_interval, amrex::Real action_per)
Definition: ERF_WriteScalarProfiles.cpp:396
void InitData()
Definition: ERF.cpp:520
int plot_file_on_restart
Definition: ERF.H:736
void Construct_ERFFillPatchers(int lev)
Definition: ERF.cpp:1696
void setRecordSampleLineInfo(int i, int lev, amrex::IntVect &cell, const std::string &filename)
Definition: ERF.H:1114
void setSpongeRefFromSounding(bool restarting)
Set sponge mean profiles from input sounding.
Definition: ERF_init1d.cpp:152
amrex::Vector< amrex::IntVect > samplepoint
Definition: ERF.H:1136
void setRecordSamplePointInfo(int i, int lev, amrex::IntVect &cell, const std::string &filename)
Definition: ERF.H:1097
static MoistureModelType modelType(const MoistureType a_moisture_type)
query if a specified moisture model is Eulerian or Lagrangian
Definition: Microphysics.H:58
amrex::Vector< amrex::IntVect > zero_yflux
Definition: AdvStruct.H:302
amrex::Vector< amrex::IntVect > zero_xflux
Definition: AdvStruct.H:301
amrex::Vector< amrex::IntVect > zero_zflux
Definition: AdvStruct.H:303

Referenced by MultiBlockContainer::InitializeBlocks(), and main().

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

◆ initHSE() [1/2]

void ERF::initHSE ( )
private

Initialize HSE.

241 {
242  AMREX_ALWAYS_ASSERT(!init_sounding_ideal);
243  for (int lev = 0; lev <= finest_level; lev++)
244  {
245  initHSE(lev);
246  }
247 }

◆ initHSE() [2/2]

void ERF::initHSE ( int  lev)
private

Initialize density and pressure base state in hydrostatic equilibrium.

205 {
206  MultiFab r_hse (base_state[lev], make_alias, 0, 1); // r_0 is first component
207  MultiFab p_hse (base_state[lev], make_alias, 1, 1); // p_0 is second component
208  MultiFab pi_hse(base_state[lev], make_alias, 2, 1); // pi_0 is third component
209 
210  if (lev > 0) {
211 
212  // Interp all three components: rho, p, pi
213  int icomp = 0; int bccomp = 0; int ncomp = 3;
214 
215  PhysBCFunctNoOp null_bc;
216  Real time = 0.;
217  Interpolater* mapper = &cell_cons_interp;
218 
219  InterpFromCoarseLevel(base_state[lev], time, base_state[lev-1],
220  icomp, icomp, ncomp,
221  geom[lev-1], geom[lev],
222  null_bc, 0, null_bc, 0, refRatio(lev-1),
223  mapper, domain_bcs_type, bccomp);
224  }
225 
226  // Initial r_hse may or may not be in HSE -- defined in prob.cpp
228  prob->erf_init_dens_hse_moist(r_hse, z_phys_nd[lev], geom[lev]);
229  } else {
230  prob->erf_init_dens_hse(r_hse, z_phys_nd[lev], z_phys_cc[lev], geom[lev]);
231  }
232 
233  // This integrates up through column to update p_hse, pi_hse;
234  // r_hse is not const b/c FillBoundary is called at the end for r_hse and p_hse
235  erf_enforce_hse(lev, r_hse, p_hse, pi_hse, z_phys_cc[lev]);
236 
237 }
void erf_enforce_hse(int lev, amrex::MultiFab &dens, amrex::MultiFab &pres, amrex::MultiFab &pi, std::unique_ptr< amrex::MultiFab > &z_cc)
Definition: ERF_init1d.cpp:259
bool use_moist_background
Definition: DataStruct.H:457

◆ initialize_bcs()

void ERF::initialize_bcs ( int  lev)
private
391 {
392  physbcs_cons[lev] = std::make_unique<ERFPhysBCFunct_cons> (lev, geom[lev], domain_bcs_type, domain_bcs_type_d,
394  z_phys_nd[lev], use_real_bcs);
395  physbcs_u[lev] = std::make_unique<ERFPhysBCFunct_u> (lev, geom[lev], domain_bcs_type, domain_bcs_type_d,
397  z_phys_nd[lev], use_real_bcs);
398  physbcs_v[lev] = std::make_unique<ERFPhysBCFunct_v> (lev, geom[lev], domain_bcs_type, domain_bcs_type_d,
400  z_phys_nd[lev], use_real_bcs);
401  physbcs_w[lev] = std::make_unique<ERFPhysBCFunct_w> (lev, geom[lev], domain_bcs_type, domain_bcs_type_d,
404  physbcs_w_no_terrain[lev] = std::make_unique<ERFPhysBCFunct_w_no_terrain>
405  (lev, geom[lev], domain_bcs_type, domain_bcs_type_d,
407 }

◆ initialize_integrator()

void ERF::initialize_integrator ( int  lev,
amrex::MultiFab &  cons_mf,
amrex::MultiFab &  vel_mf 
)
private
369 {
370  const BoxArray& ba(cons_mf.boxArray());
371  const DistributionMapping& dm(cons_mf.DistributionMap());
372 
373  int ncomp_cons = cons_mf.nComp();
374 
375  // Initialize the integrator memory
376  Vector<MultiFab> int_state; // integration state data structure example
377  int_state.push_back(MultiFab(cons_mf, make_alias, 0, ncomp_cons)); // cons
378  int_state.push_back(MultiFab(convert(ba,IntVect(1,0,0)), dm, 1, vel_mf.nGrow())); // xmom
379  int_state.push_back(MultiFab(convert(ba,IntVect(0,1,0)), dm, 1, vel_mf.nGrow())); // ymom
380  int_state.push_back(MultiFab(convert(ba,IntVect(0,0,1)), dm, 1, vel_mf.nGrow())); // zmom
381 
382  mri_integrator_mem[lev] = std::make_unique<MRISplitIntegrator<Vector<MultiFab> > >(int_state);
383  mri_integrator_mem[lev]->setNoSubstepping(solverChoice.no_substepping);
384  mri_integrator_mem[lev]->setIncompressible(solverChoice.incompressible);
385  mri_integrator_mem[lev]->setNcompCons(ncomp_cons);
386  mri_integrator_mem[lev]->setForceFirstStageSingleSubstep(solverChoice.force_stage1_single_substep);
387 }

◆ InitializeFromFile()

void ERF::InitializeFromFile ( )
private

◆ InitializeLevelFromData()

void ERF::InitializeLevelFromData ( int  lev,
const amrex::MultiFab &  initial_data 
)
private

◆ initializeMicrophysics()

void ERF::initializeMicrophysics ( const int &  a_nlevsmax)
private
Parameters
a_nlevsmaxnumber of AMR levels
1052 {
1054 
1055  micro = std::make_unique<EulerianMicrophysics>(a_nlevsmax, solverChoice.moisture_type);
1056 
1058 #ifdef ERF_USE_PARTICLES
1059 
1060  micro = std::make_unique<LagrangianMicrophysics>(a_nlevsmax, solverChoice.moisture_type);
1061  /* Lagrangian microphysics models will have a particle container; it needs to be added
1062  to ERF::particleData */
1063  const auto& pc_name( dynamic_cast<LagrangianMicrophysics&>(*micro).getName() );
1064  /* The particle container has not yet been constructed and initialized, so just add
1065  its name here for now (so that functions to set plotting variables can see it). */
1066  particleData.addName( pc_name );
1067 
1068 #else
1069  Abort("Lagrangian microphysics can be used when compiled with ERF_USE_PARTICLES");
1070 #endif
1071  }
1072 
1073  qmoist.resize(a_nlevsmax);
1074  return;
1075 }
Here is the call graph for this function:

◆ initRayleigh()

void ERF::initRayleigh ( )
private

Initialize Rayleigh damping profiles.

Initialization function for host and device vectors used to store averaged quantities when calculating the effects of Rayleigh Damping.

19 {
20  h_rayleigh_ptrs.resize(max_level+1);
21  d_rayleigh_ptrs.resize(max_level+1);
22 
23  for (int lev = 0; lev <= finest_level; lev++)
24  {
25  // These have 5 components: tau, ubar, vbar, wbar, thetabar
26  h_rayleigh_ptrs[lev].resize(Rayleigh::nvars);
27  d_rayleigh_ptrs[lev].resize(Rayleigh::nvars);
28 
29  const int zlen_rayleigh = geom[lev].Domain().length(2);
30 
31  // Allocate space for these 1D vectors
32  for (int n = 0; n < Rayleigh::nvars; n++) {
33  h_rayleigh_ptrs[lev][n].resize(zlen_rayleigh, 0.0_rt);
34  d_rayleigh_ptrs[lev][n].resize(zlen_rayleigh, 0.0_rt);
35  }
36 
37  // Init the host vectors
38  prob->erf_init_rayleigh(h_rayleigh_ptrs[lev], geom[lev], z_phys_cc[lev]);
39 
40  // Copy from host vectors to device vectors
41  for (int n = 0; n < Rayleigh::nvars; n++) {
42  Gpu::copy(Gpu::hostToDevice, h_rayleigh_ptrs[lev][n].begin(), h_rayleigh_ptrs[lev][n].end(),
43  d_rayleigh_ptrs[lev][n].begin());
44  }
45  }
46 }
amrex::Vector< amrex::Vector< amrex::Vector< amrex::Real > > > h_rayleigh_ptrs
Definition: ERF.H:911

◆ initSponge()

void ERF::initSponge ( )
private

Initialize sponge profiles.

Initialization function for host and device vectors used to store the effects of sponge Damping.

123 {
124  h_sponge_ptrs.resize(max_level+1);
125  d_sponge_ptrs.resize(max_level+1);
126 
127  for (int lev = 0; lev <= finest_level; lev++)
128  {
129  // These have 2 components: ubar, vbar
130  h_sponge_ptrs[lev].resize(Sponge::nvars_sponge);
131  d_sponge_ptrs[lev].resize(Sponge::nvars_sponge);
132 
133  const int zlen_sponge = geom[lev].Domain().length(2);
134 
135  // Allocate space for these 1D vectors
136  for (int n = 0; n < Sponge::nvars_sponge; n++) {
137  h_sponge_ptrs[lev][n].resize(zlen_sponge, 0.0_rt);
138  d_sponge_ptrs[lev][n].resize(zlen_sponge, 0.0_rt);
139  }
140 
141  }
142 }
amrex::Vector< amrex::Vector< amrex::Vector< amrex::Real > > > h_sponge_ptrs
Definition: ERF.H:914

◆ input_sponge()

void ERF::input_sponge ( int  lev)

High level wrapper for sponge x and y velocities level data from input sponge data.

Parameters
levInteger specifying the current level
21 {
22  // We only want to read the file once
23  if (lev == 0) {
24  if (input_sponge_file.empty())
25  Error("input_sounding file name must be provided via input");
26 
27  // this will interpolate the input profiles to the nominal height levels
28  // (ranging from 0 to the domain top)
30 
31  }
32 }
static std::string input_sponge_file
Definition: ERF.H:868
InputSpongeData input_sponge_data
Definition: ERF.H:549
void read_from_file(const std::string input_sponge_file, const amrex::Geometry &geom, const amrex::Vector< amrex::Real > &zlevels_stag)
Definition: InputSpongeData.H:23

◆ is_it_time_for_action()

bool ERF::is_it_time_for_action ( int  nstep,
amrex::Real  time,
amrex::Real  dt,
int  action_interval,
amrex::Real  action_per 
)
static

Helper function which uses the current step number, time, and timestep to determine whether it is time to take an action specified at every interval of timesteps.

Parameters
nstepTimestep number
timeCurrent time
dtlevTimestep for the current level
action_intervalInterval in number of timesteps for taking action
action_perInterval in simulation time for taking action
397 {
398  bool int_test = (action_interval > 0 && nstep % action_interval == 0);
399 
400  bool per_test = false;
401  if (action_per > 0.0) {
402  const int num_per_old = static_cast<int>(amrex::Math::floor((time - dtlev) / action_per));
403  const int num_per_new = static_cast<int>(amrex::Math::floor((time) / action_per));
404 
405  if (num_per_old != num_per_new) {
406  per_test = true;
407  }
408  }
409 
410  return int_test || per_test;
411 }

◆ MakeDiagnosticAverage()

void ERF::MakeDiagnosticAverage ( amrex::Vector< amrex::Real > &  h_havg,
amrex::MultiFab &  S,
int  n 
)
1542 {
1543  // Get the number of cells in z at level 0
1544  int dir_z = AMREX_SPACEDIM-1;
1545  auto domain = geom[0].Domain();
1546  int size_z = domain.length(dir_z);
1547  int start_z = domain.smallEnd()[dir_z];
1548  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
1549 
1550  // resize the level 0 horizontal average vectors
1551  h_havg.resize(size_z, 0.0_rt);
1552 
1553  // Get the cell centered data and construct sums
1554 #ifdef _OPENMP
1555 #pragma omp parallel if (Gpu::notInLaunchRegion())
1556 #endif
1557  for (MFIter mfi(S); mfi.isValid(); ++mfi) {
1558  const Box& box = mfi.validbox();
1559  const IntVect& se = box.smallEnd();
1560  const IntVect& be = box.bigEnd();
1561 
1562  auto fab_arr = S[mfi].array();
1563 
1564  FArrayBox fab_reduce(box, 1, The_Async_Arena());
1565  auto arr_reduce = fab_reduce.array();
1566 
1567  ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
1568  arr_reduce(i, j, k, 0) = fab_arr(i,j,k,n);
1569  });
1570 
1571  for (int k=se[dir_z]; k <= be[dir_z]; ++k) {
1572  Box kbox(box); kbox.setSmall(dir_z,k); kbox.setBig(dir_z,k);
1573  h_havg[k-start_z] += fab_reduce.sum<RunOn::Device>(kbox,0);
1574  }
1575  }
1576 
1577  // combine sums from different MPI ranks
1578  ParallelDescriptor::ReduceRealSum(h_havg.dataPtr(), h_havg.size());
1579 
1580  // divide by the total number of cells we are averaging over
1581  for (int k = 0; k < size_z; ++k) {
1582  h_havg[k] /= area_z;
1583  }
1584 }

◆ MakeHorizontalAverages()

void ERF::MakeHorizontalAverages ( )
1447 {
1448  int lev = 0;
1449 
1450  // First, average down all levels (if doing two-way coupling)
1452  AverageDown();
1453  }
1454 
1455  MultiFab mf(grids[lev], dmap[lev], 5, 0);
1456 
1457  int zdir = 2;
1458  auto domain = geom[0].Domain();
1459 
1460  bool use_moisture = (solverChoice.moisture_type != MoistureType::None);
1461 
1462  for (MFIter mfi(mf); mfi.isValid(); ++mfi) {
1463  const Box& bx = mfi.validbox();
1464  auto fab_arr = mf.array(mfi);
1465  auto const cons_arr = vars_new[lev][Vars::cons].const_array(mfi);
1466  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
1467  Real dens = cons_arr(i, j, k, Rho_comp);
1468  fab_arr(i, j, k, 0) = dens;
1469  fab_arr(i, j, k, 1) = cons_arr(i, j, k, RhoTheta_comp) / dens;
1470  if (!use_moisture) {
1471  fab_arr(i, j, k, 2) = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp));
1472  }
1473  });
1474  }
1475 
1476  if (use_moisture)
1477  {
1478  for (MFIter mfi(mf); mfi.isValid(); ++mfi) {
1479  const Box& bx = mfi.validbox();
1480  auto fab_arr = mf.array(mfi);
1481  auto const cons_arr = vars_new[lev][Vars::cons].const_array(mfi);
1482  auto const qv_arr = qmoist[lev][0]->const_array(mfi);
1483  int ncomp = vars_new[lev][Vars::cons].nComp();
1484 
1485  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
1486  Real dens = cons_arr(i, j, k, Rho_comp);
1487  fab_arr(i, j, k, 2) = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_arr(i,j,k));
1488  fab_arr(i, j, k, 3) = (ncomp > RhoQ1_comp ? cons_arr(i, j, k, RhoQ1_comp) / dens : 0.0);
1489  fab_arr(i, j, k, 4) = (ncomp > RhoQ2_comp ? cons_arr(i, j, k, RhoQ2_comp) / dens : 0.0);
1490  });
1491  }
1492 
1493  Gpu::HostVector<Real> h_avg_qv = sumToLine(mf,3,1,domain,zdir);
1494  Gpu::HostVector<Real> h_avg_qc = sumToLine(mf,4,1,domain,zdir);
1495  }
1496 
1497  // Sum in the horizontal plane
1498  Gpu::HostVector<Real> h_avg_density = sumToLine(mf,0,1,domain,zdir);
1499  Gpu::HostVector<Real> h_avg_temperature = sumToLine(mf,1,1,domain,zdir);
1500  Gpu::HostVector<Real> h_avg_pressure = sumToLine(mf,2,1,domain,zdir);
1501 
1502  // Divide by the total number of cells we are averaging over
1503  int size_z = domain.length(zdir);
1504  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
1505  int klen = static_cast<int>(h_avg_density.size());
1506 
1507  for (int k = 0; k < klen; ++k) {
1508  h_havg_density[k] /= area_z;
1509  h_havg_temperature[k] /= area_z;
1510  h_havg_pressure[k] /= area_z;
1512  {
1513  h_havg_qc[k] /= area_z;
1514  h_havg_qv[k] /= area_z;
1515  }
1516  } // k
1517 
1518  // resize device vectors
1519  d_havg_density.resize(size_z, 0.0_rt);
1520  d_havg_temperature.resize(size_z, 0.0_rt);
1521  d_havg_pressure.resize(size_z, 0.0_rt);
1522 
1523  // copy host vectors to device vectors
1524  Gpu::copy(Gpu::hostToDevice, h_havg_density.begin(), h_havg_density.end(), d_havg_density.begin());
1525  Gpu::copy(Gpu::hostToDevice, h_havg_temperature.begin(), h_havg_temperature.end(), d_havg_temperature.begin());
1526  Gpu::copy(Gpu::hostToDevice, h_havg_pressure.begin(), h_havg_pressure.end(), d_havg_pressure.begin());
1527 
1529  {
1530  d_havg_qv.resize(size_z, 0.0_rt);
1531  d_havg_qc.resize(size_z, 0.0_rt);
1532  Gpu::copy(Gpu::hostToDevice, h_havg_qv.begin(), h_havg_qv.end(), d_havg_qv.begin());
1533  Gpu::copy(Gpu::hostToDevice, h_havg_qc.begin(), h_havg_qc.end(), d_havg_qc.begin());
1534  }
1535 }
amrex::Gpu::DeviceVector< amrex::Real > d_havg_temperature
Definition: ERF.H:929
amrex::Gpu::DeviceVector< amrex::Real > d_havg_qv
Definition: ERF.H:931
amrex::Vector< amrex::Real > h_havg_pressure
Definition: ERF.H:924
amrex::Vector< amrex::Real > h_havg_qc
Definition: ERF.H:926
amrex::Vector< amrex::Real > h_havg_density
Definition: ERF.H:922
amrex::Gpu::DeviceVector< amrex::Real > d_havg_qc
Definition: ERF.H:932
amrex::Gpu::DeviceVector< amrex::Real > d_havg_density
Definition: ERF.H:928
amrex::Vector< amrex::Real > h_havg_temperature
Definition: ERF.H:923
amrex::Gpu::DeviceVector< amrex::Real > d_havg_pressure
Definition: ERF.H:930
amrex::Vector< amrex::Real > h_havg_qv
Definition: ERF.H:925
Here is the call graph for this function:

◆ MakeNewLevelFromCoarse()

void ERF::MakeNewLevelFromCoarse ( int  lev,
amrex::Real  time,
const amrex::BoxArray &  ba,
const amrex::DistributionMapping &  dm 
)
override
272 {
273  AMREX_ALWAYS_ASSERT(lev > 0);
274 
275  // amrex::Print() <<" NEW BA FROM COARSE AT LEVEL " << lev << " " << ba << std::endl;
276 
277  //********************************************************************************************
278  // This allocates all kinds of things, including but not limited to: solution arrays,
279  // terrain arrays and metrics,a nd base state.
280  // *******************************************************************************************
281  init_stuff(lev, ba, dm, vars_new[lev], vars_old[lev]);
282 
283  t_new[lev] = time;
284  t_old[lev] = time - 1.e200;
285 
286  // ********************************************************************************************
287  // Build the data structures for terrain-related quantities
288  // ********************************************************************************************
289  update_terrain_arrays(lev, time);
290 
291  //
292  // Make sure that detJ and z_phys_cc are the average of the data on a finer level if there is one
293  //
294  if (solverChoice.use_terrain != 0) {
295  for (int crse_lev = lev-1; crse_lev >= 0; crse_lev--) {
296  average_down( *detJ_cc[crse_lev+1], *detJ_cc[crse_lev], 0, 1, refRatio(crse_lev));
297  average_down(*z_phys_cc[crse_lev+1], *z_phys_cc[crse_lev], 0, 1, refRatio(crse_lev));
298  }
299  }
300 
301  //********************************************************************************************
302  // Microphysics
303  // *******************************************************************************************
304  int q_size = micro->Get_Qmoist_Size(lev);
305  qmoist[lev].resize(q_size);
306  micro->Define(lev, solverChoice);
308  {
309  micro->Init(lev, vars_new[lev][Vars::cons],
310  grids[lev], Geom(lev), 0.0,
311  z_phys_nd[lev], detJ_cc[lev]); // dummy dt value
312  }
313  for (int mvar(0); mvar<qmoist[lev].size(); ++mvar) {
314  qmoist[lev][mvar] = micro->Get_Qmoist_Ptr(lev,mvar);
315  }
316 
317  // ********************************************************************************************
318  // Update the base state at this level
319  // ********************************************************************************************
320  // base_state[lev].define(ba,dm,3,1);
321  // base_state[lev].setVal(0.);
322  initHSE(lev);
323 
324  // ********************************************************************************************
325  // Build the data structures for calculating diffusive/turbulent terms
326  // ********************************************************************************************
327  update_diffusive_arrays(lev, ba, dm);
328 
329  // *****************************************************************************************************
330  // Initialize the boundary conditions (after initializing the terrain but before calling FillCoarsePatch
331  // *****************************************************************************************************
332  initialize_bcs(lev);
333 
334  // ********************************************************************************************
335  // Fill data at the new level by interpolation from the coarser level
336  // Note that internal to FillCoarsePatch we will convert velocity to momentum,
337  // then interpolate momentum, then convert momentum back to velocity
338  // Also note that FillCoarsePatch is hard-wired to act only on lev_new at coarse and fine
339  // ********************************************************************************************
340  FillCoarsePatch(lev, time);
341 
342  // ********************************************************************************************
343  // Initialize the integrator class
344  // ********************************************************************************************
345  dt_mri_ratio[lev] = dt_mri_ratio[lev-1];
347 
348  // ********************************************************************************************
349  // If we are making a new level then the FillPatcher for this level hasn't been allocated yet
350  // ********************************************************************************************
351  if (lev > 0 && cf_width >= 0) {
354  }
355 
356 #ifdef ERF_USE_PARTICLES
357  // particleData.Redistribute();
358 #endif
359 }
void initialize_bcs(int lev)
Definition: ERF_make_new_arrays.cpp:390
void update_diffusive_arrays(int lev, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm)
Definition: ERF_make_new_arrays.cpp:255
void initialize_integrator(int lev, amrex::MultiFab &cons_mf, amrex::MultiFab &vel_mf)
Definition: ERF_make_new_arrays.cpp:368
void update_terrain_arrays(int lev, amrex::Real time)
Definition: ERF_make_new_arrays.cpp:320
void init_stuff(int lev, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm, amrex::Vector< amrex::MultiFab > &lev_new, amrex::Vector< amrex::MultiFab > &lev_old)
Definition: ERF_make_new_arrays.cpp:26
void Define_ERFFillPatchers(int lev)
Definition: ERF.cpp:1722

◆ MakeNewLevelFromScratch()

void ERF::MakeNewLevelFromScratch ( int  lev,
amrex::Real  time,
const amrex::BoxArray &  ba,
const amrex::DistributionMapping &  dm 
)
override
29 {
30  // Set BoxArray grids and DistributionMapping dmap in AMReX_AmrMesh.H class
31  SetBoxArray(lev, ba);
32  SetDistributionMap(lev, dm);
33 
34  // amrex::Print() <<" BA FROM SCRATCH AT LEVEL " << lev << " " << ba << std::endl;
35 
36 #ifdef AMREX_USE_EB
37  m_factory[lev] = makeEBFabFactory(geom[lev], grids[lev], dmap[lev],
38  {nghost_eb_basic(),
39  nghost_eb_volume(),
40  nghost_eb_full()},
41  EBSupport::full);
42 #else
43  m_factory[lev] = std::make_unique<FArrayBoxFactory>();
44 #endif
45 
46  // The number of ghost cells for density must be 1 greater than that for velocity
47  // so that we can go back in forth betwen velocity and momentum on all faces
48  // int ngrow_state = ComputeGhostCells(solverChoice.advChoice, solverChoice.use_NumDiff) + 1;
49  // int ngrow_vels = ComputeGhostCells(solverChoice.advChoice, solverChoice.use_NumDiff);
50 
51  auto& lev_new = vars_new[lev];
52  auto& lev_old = vars_old[lev];
53 
54  //********************************************************************************************
55  // This allocates all kinds of things, including but not limited to: solution arrays,
56  // terrain arrays and metrics,a nd base state.
57  // *******************************************************************************************
58  init_stuff(lev, ba, dm, lev_new, lev_old);
59 
60  //********************************************************************************************
61  // Land Surface Model
62  // *******************************************************************************************
63  int lsm_size = lsm.Get_Data_Size();
64  lsm_data[lev].resize(lsm_size);
65  lsm_flux[lev].resize(lsm_size);
66  lsm.Define(lev, solverChoice);
68  {
69  lsm.Init(lev, vars_new[lev][Vars::cons], Geom(lev), 0.0); // dummy dt value
70  }
71  for (int mvar(0); mvar<lsm_data[lev].size(); ++mvar) {
72  lsm_data[lev][mvar] = lsm.Get_Data_Ptr(lev,mvar);
73  lsm_flux[lev][mvar] = lsm.Get_Flux_Ptr(lev,mvar);
74  }
75 
76  // ********************************************************************************************
77  // Build the data structures for calculating diffusive/turbulent terms
78  // ********************************************************************************************
79  update_diffusive_arrays(lev, ba, dm);
80 
81  sst_lev[lev].resize(1); sst_lev[lev][0] = nullptr;
82  lmask_lev[lev].resize(1); lmask_lev[lev][0] = nullptr;
83 
84  //********************************************************************************************
85  // Thin immersed body
86  // *******************************************************************************************
87 #if 0
88  if ((solverChoice.advChoice.zero_xflux.size() > 0) ||
89  (solverChoice.advChoice.zero_yflux.size() > 0) ||
90  (solverChoice.advChoice.zero_zflux.size() > 0))
91  {
92  overset_imask[lev] = std::make_unique<iMultiFab>(ba,dm,1,0);
93  overset_imask[lev]->setVal(1); // == value is unknown (to be solved)
94  }
95 #endif
96 
97  if (solverChoice.advChoice.zero_xflux.size() > 0) {
98  amrex::Print() << "Setting up thin immersed body for "
99  << solverChoice.advChoice.zero_xflux.size() << " xfaces" << std::endl;
100  BoxArray ba_xf(ba);
101  ba_xf.surroundingNodes(0);
102  thin_xforce[lev] = std::make_unique<MultiFab>(ba_xf,dm,1,0);
103  thin_xforce[lev]->setVal(0.0);
104  xflux_imask[lev] = std::make_unique<iMultiFab>(ba_xf,dm,1,0);
105  xflux_imask[lev]->setVal(1);
106  for ( MFIter mfi(*xflux_imask[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi )
107  {
108  Array4<int> const& imask_arr = xflux_imask[lev]->array(mfi);
109  //Array4<int> const& imask_cell_arr = overset_imask[lev]->array(mfi);
110  Box xbx = mfi.nodaltilebox(0);
111  for (int iv=0; iv < solverChoice.advChoice.zero_xflux.size(); ++iv) {
112  const auto& faceidx = solverChoice.advChoice.zero_xflux[iv];
113  if ((faceidx[0] >= xbx.smallEnd(0)) && (faceidx[0] <= xbx.bigEnd(0)) &&
114  (faceidx[1] >= xbx.smallEnd(1)) && (faceidx[1] <= xbx.bigEnd(1)) &&
115  (faceidx[2] >= xbx.smallEnd(2)) && (faceidx[2] <= xbx.bigEnd(2)))
116  {
117  imask_arr(faceidx[0],faceidx[1],faceidx[2]) = 0;
118  //imask_cell_arr(faceidx[0],faceidx[1],faceidx[2]) = 0;
119  //imask_cell_arr(faceidx[0]-1,faceidx[1],faceidx[2]) = 0;
120  amrex::AllPrint() << " mask xface at " << faceidx << std::endl;
121  }
122  }
123  }
124  } else {
125  thin_xforce[lev] = nullptr;
126  xflux_imask[lev] = nullptr;
127  }
128 
129  if (solverChoice.advChoice.zero_yflux.size() > 0) {
130  amrex::Print() << "Setting up thin interface boundary for "
131  << solverChoice.advChoice.zero_yflux.size() << " yfaces" << std::endl;
132  BoxArray ba_yf(ba);
133  ba_yf.surroundingNodes(1);
134  thin_yforce[lev] = std::make_unique<MultiFab>(ba_yf,dm,1,0);
135  thin_yforce[lev]->setVal(0.0);
136  yflux_imask[lev] = std::make_unique<iMultiFab>(ba_yf,dm,1,0);
137  yflux_imask[lev]->setVal(1);
138  for ( MFIter mfi(*yflux_imask[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi )
139  {
140  Array4<int> const& imask_arr = yflux_imask[lev]->array(mfi);
141  //Array4<int> const& imask_cell_arr = overset_imask[lev]->array(mfi);
142  Box ybx = mfi.nodaltilebox(1);
143  for (int iv=0; iv < solverChoice.advChoice.zero_yflux.size(); ++iv) {
144  const auto& faceidx = solverChoice.advChoice.zero_yflux[iv];
145  if ((faceidx[0] >= ybx.smallEnd(0)) && (faceidx[0] <= ybx.bigEnd(0)) &&
146  (faceidx[1] >= ybx.smallEnd(1)) && (faceidx[1] <= ybx.bigEnd(1)) &&
147  (faceidx[2] >= ybx.smallEnd(2)) && (faceidx[2] <= ybx.bigEnd(2)))
148  {
149  imask_arr(faceidx[0],faceidx[1],faceidx[2]) = 0;
150  //imask_cell_arr(faceidx[0],faceidx[1],faceidx[2]) = 0;
151  //imask_cell_arr(faceidx[0],faceidx[1]-1,faceidx[2]) = 0;
152  amrex::AllPrint() << " mask yface at " << faceidx << std::endl;
153  }
154  }
155  }
156  } else {
157  thin_yforce[lev] = nullptr;
158  yflux_imask[lev] = nullptr;
159  }
160 
161  if (solverChoice.advChoice.zero_zflux.size() > 0) {
162  amrex::Print() << "Setting up thin interface boundary for "
163  << solverChoice.advChoice.zero_zflux.size() << " zfaces" << std::endl;
164  BoxArray ba_zf(ba);
165  ba_zf.surroundingNodes(2);
166  thin_zforce[lev] = std::make_unique<MultiFab>(ba_zf,dm,1,0);
167  thin_zforce[lev]->setVal(0.0);
168  zflux_imask[lev] = std::make_unique<iMultiFab>(ba_zf,dm,1,0);
169  zflux_imask[lev]->setVal(1);
170  for ( MFIter mfi(*zflux_imask[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi )
171  {
172  Array4<int> const& imask_arr = zflux_imask[lev]->array(mfi);
173  //Array4<int> const& imask_cell_arr = overset_imask[lev]->array(mfi);
174  Box zbx = mfi.nodaltilebox(2);
175  for (int iv=0; iv < solverChoice.advChoice.zero_zflux.size(); ++iv) {
176  const auto& faceidx = solverChoice.advChoice.zero_zflux[iv];
177  if ((faceidx[0] >= zbx.smallEnd(0)) && (faceidx[0] <= zbx.bigEnd(0)) &&
178  (faceidx[1] >= zbx.smallEnd(1)) && (faceidx[1] <= zbx.bigEnd(1)) &&
179  (faceidx[2] >= zbx.smallEnd(2)) && (faceidx[2] <= zbx.bigEnd(2)))
180  {
181  imask_arr(faceidx[0],faceidx[1],faceidx[2]) = 0;
182  //imask_cell_arr(faceidx[0],faceidx[1],faceidx[2]) = 0;
183  //imask_cell_arr(faceidx[0],faceidx[1],faceidx[2]-1) = 0;
184  amrex::AllPrint() << " mask zface at " << faceidx << std::endl;
185  }
186  }
187  }
188  } else {
189  thin_zforce[lev] = nullptr;
190  zflux_imask[lev] = nullptr;
191  }
192 
193  //********************************************************************************************
194  // Microphysics
195  // *******************************************************************************************
196  int q_size = micro->Get_Qmoist_Size(lev);
197  qmoist[lev].resize(q_size);
198  micro->Define(lev, solverChoice);
200  {
201  micro->Init(lev, vars_new[lev][Vars::cons],
202  grids[lev], Geom(lev), 0.0,
203  z_phys_nd[lev], detJ_cc[lev]); // dummy dt value
204  }
205  for (int mvar(0); mvar<qmoist[lev].size(); ++mvar) {
206  qmoist[lev][mvar] = micro->Get_Qmoist_Ptr(lev,mvar);
207  }
208 
209  // ********************************************************************************************
210  // Initialize the integrator class
211  // ********************************************************************************************
212  initialize_integrator(lev, lev_new[Vars::cons],lev_new[Vars::xvel]);
213 
214  // ********************************************************************************************
215  // Initialize the data itself
216  // If (init_type == "real") then we are initializing terrain and the initial data in
217  // the same call so we must call init_only before update_terrain_arrays
218  // If (init_type != "real") then we want to initialize the terrain before the initial data
219  // since we may need to use the grid information before constructing
220  // initial idealized data
221  // ********************************************************************************************
222  if ((init_type == "real") || (init_type == "metgrid")) {
223 
224  // If called from restart, the data structures for terrain-related quantities
225  // are built in the ReadCheckpoint routine. Otherwise we build them here.
226  if (restart_chkfile.empty()) {
227  init_only(lev, start_time);
228  update_terrain_arrays(lev, time);
229  }
230 
231  } else {
232  // Build the data structures for terrain-related quantities
233  update_terrain_arrays(lev, time);
234 
235  // Initialize the solution data itself
236  if (restart_chkfile.empty()) {
237  init_only(lev, start_time);
238  }
239  }
240 
241  // ********************************************************************************************
242  // If we are making a new level then the FillPatcher for this level hasn't been allocated yet
243  // ********************************************************************************************
244  if (lev > 0 && cf_width >= 0) {
247  }
248 
249  // ********************************************************************************************
250  // Initialize the boundary conditions
251  // ********************************************************************************************
252  initialize_bcs(lev);
253 
254 #ifdef ERF_USE_PARTICLES
255  if (restart_chkfile.empty()) {
256  if (lev == 0) {
257  initializeTracers((ParGDBBase*)GetParGDB(),z_phys_nd);
258  } else {
259  particleData.Redistribute();
260  }
261  }
262 #endif
263 }
void init_only(int lev, amrex::Real time)
Definition: ERF.cpp:1109
int Get_Data_Size()
Definition: LandSurface.H:74
amrex::MultiFab * Get_Flux_Ptr(const int &lev, const int &varIdx)
Definition: LandSurface.H:68
void Init(const int &lev, const amrex::MultiFab &cons_in, const amrex::Geometry &geom, const amrex::Real &dt_advance)
Definition: LandSurface.H:38
void Define(const int &lev, SolverChoice &sc)
Definition: LandSurface.H:31
amrex::MultiFab * Get_Data_Ptr(const int &lev, const int &varIdx)
Definition: LandSurface.H:65

◆ NumDataLogs()

AMREX_FORCE_INLINE int ERF::NumDataLogs ( )
inlineprivatenoexcept
1008  {
1009  return datalog.size();
1010  }

◆ NumSampleLineLogs()

AMREX_FORCE_INLINE int ERF::NumSampleLineLogs ( )
inlineprivatenoexcept
1036  {
1037  return samplelinelog.size();
1038  }

◆ NumSampleLines()

AMREX_FORCE_INLINE int ERF::NumSampleLines ( )
inlineprivatenoexcept
1062  {
1063  return sampleline.size();
1064  }

◆ NumSamplePointLogs()

AMREX_FORCE_INLINE int ERF::NumSamplePointLogs ( )
inlineprivatenoexcept
1022  {
1023  return sampleptlog.size();
1024  }

◆ NumSamplePoints()

AMREX_FORCE_INLINE int ERF::NumSamplePoints ( )
inlineprivatenoexcept
1049  {
1050  return samplepoint.size();
1051  }

◆ operator=() [1/2]

ERF& ERF::operator= ( const ERF other)
delete

◆ operator=() [2/2]

ERF& ERF::operator= ( ERF &&  other)
deletenoexcept

◆ PlotFileName()

std::string ERF::PlotFileName ( int  lev) const
private

◆ PlotFileVarNames()

Vector< std::string > ERF::PlotFileVarNames ( amrex::Vector< std::string >  plot_var_names)
staticprivate
143 {
144  Vector<std::string> names;
145 
146  names.insert(names.end(), plot_var_names.begin(), plot_var_names.end());
147 
148  return names;
149 
150 }

◆ post_timestep()

void ERF::post_timestep ( int  nstep,
amrex::Real  time,
amrex::Real  dt_lev 
)
397 {
398  BL_PROFILE("ERF::post_timestep()");
399 
400 #ifdef ERF_USE_PARTICLES
401  particleData.Redistribute();
402 #endif
403 
405  {
406  bool use_terrain = solverChoice.use_terrain;
407  int ncomp = vars_new[0][Vars::cons].nComp();
408  for (int lev = finest_level-1; lev >= 0; lev--)
409  {
410  // The quantity that is conserved is not (rho S), but rather (rho S / m^2) where
411  // m is the map scale factor at cell centers
412  // Here we pre-divide (rho S) by m^2 before refluxing
413  for (MFIter mfi(vars_new[lev][Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
414  const Box& bx = mfi.tilebox();
415  const Array4< Real> cons_arr = vars_new[lev][Vars::cons].array(mfi);
416  const Array4<const Real> mapfac_arr = mapfac_m[lev]->const_array(mfi);
417  if (use_terrain) {
418  const Array4<const Real> detJ_arr = detJ_cc[lev]->const_array(mfi);
419  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
420  {
421  cons_arr(i,j,k,n) *= detJ_arr(i,j,k) / (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
422  });
423  } else {
424  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
425  {
426  cons_arr(i,j,k,n) /= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
427  });
428  }
429  } // mfi
430 
431  // This call refluxes from the lev/lev+1 interface onto lev
432  getAdvFluxReg(lev+1)->Reflux(vars_new[lev][Vars::cons], 0, 0, ncomp);
433 
434  // Here we multiply (rho S) by m^2 after refluxing
435  for (MFIter mfi(vars_new[lev][Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
436  const Box& bx = mfi.tilebox();
437  const Array4< Real> cons_arr = vars_new[lev][Vars::cons].array(mfi);
438  const Array4<const Real> mapfac_arr = mapfac_m[lev]->const_array(mfi);
439  if (use_terrain) {
440  const Array4<const Real> detJ_arr = detJ_cc[lev]->const_array(mfi);
441  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
442  {
443  cons_arr(i,j,k,n) *= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0)) / detJ_arr(i,j,k);
444  });
445  } else {
446  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
447  {
448  cons_arr(i,j,k,n) *= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
449  });
450  }
451  } // mfi
452 
453  // We need to do this before anything else because refluxing changes the
454  // values of coarse cells underneath fine grids with the assumption they'll
455  // be over-written by averaging down
456  AverageDownTo(lev,0,ncomp);
457  }
458  }
459 
460  if (is_it_time_for_action(nstep, time, dt_lev0, sum_interval, sum_per)) {
462  }
463 
464  if (profile_int > 0 && (nstep+1) % profile_int == 0) {
465  if (cc_profiles) {
466  // all variables cell-centered
467  write_1D_profiles(time);
468  } else {
469  // some variables staggered
471  }
472  }
473 
474  if (output_1d_column) {
475 #ifdef ERF_USE_NETCDF
476  if (is_it_time_for_action(nstep, time, dt_lev0, column_interval, column_per))
477  {
478  int lev_column = 0;
479  for (int lev = finest_level; lev >= 0; lev--)
480  {
481  Real dx_lev = geom[lev].CellSize(0);
482  Real dy_lev = geom[lev].CellSize(1);
483  int i_lev = static_cast<int>(std::floor(column_loc_x / dx_lev));
484  int j_lev = static_cast<int>(std::floor(column_loc_y / dy_lev));
485  if (grids[lev].contains(IntVect(i_lev,j_lev,0))) lev_column = lev;
486  }
487  writeToNCColumnFile(lev_column, column_file_name, column_loc_x, column_loc_y, time);
488  }
489 #else
490  Abort("To output 1D column files ERF must be compiled with NetCDF");
491 #endif
492  }
493 
495  {
498  {
499  m_w2d->write_planes(istep[0], time, vars_new);
500  }
501  }
502 
503  // Moving terrain
505  {
506  for (int lev = finest_level; lev >= 0; lev--)
507  {
508  // Copy z_phs_nd and detJ_cc at end of timestep
509  MultiFab::Copy(*z_phys_nd[lev], *z_phys_nd_new[lev], 0, 0, 1, z_phys_nd[lev]->nGrowVect());
510  MultiFab::Copy( *detJ_cc[lev], *detJ_cc_new[lev], 0, 0, 1, detJ_cc[lev]->nGrowVect());
511  MultiFab::Copy(base_state[lev],base_state_new[lev],0,0,3,1);
512 
513  make_zcc(geom[lev],*z_phys_nd[lev],*z_phys_cc[lev]);
514  }
515  }
516 } // post_timestep
void make_zcc(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &z_phys_cc)
Definition: TerrainMetrics.cpp:556
static amrex::Real column_loc_y
Definition: ERF.H:879
static std::string column_file_name
Definition: ERF.H:880
AMREX_FORCE_INLINE amrex::YAFluxRegister * getAdvFluxReg(int lev)
Definition: ERF.H:993
static amrex::Real bndry_output_planes_per
Definition: ERF.H:885
int profile_int
Definition: ERF.H:774
static amrex::Real column_per
Definition: ERF.H:877
static amrex::Real column_loc_x
Definition: ERF.H:878
static int bndry_output_planes_interval
Definition: ERF.H:884
static int output_1d_column
Definition: ERF.H:875
static int column_interval
Definition: ERF.H:876
Here is the call graph for this function:

◆ post_update()

void ERF::post_update ( amrex::MultiFab &  state_mf,
amrex::Real  time,
const amrex::Geometry &  geom 
)
private

◆ print_banner()

void ERF::print_banner ( MPI_Comm  comm,
std::ostream &  out 
)
static
65  : " << msg << std::endl;
66 }
67 
68 void ERF::print_banner (MPI_Comm comm, std::ostream& out)
69 {
70 #ifdef AMREX_USE_MPI
71  int irank = 0;
72  int num_ranks = 1;
73  MPI_Comm_size(comm, &num_ranks);
74  MPI_Comm_rank(comm, &irank);
75 
76  // Only root process does the printing
77  if (irank != 0) return;
78 #else
79  amrex::ignore_unused(comm);
80 #endif
81 
82  auto etime = std::chrono::system_clock::now();
83  auto etimet = std::chrono::system_clock::to_time_t(etime);
84 #ifndef _WIN32
85  char time_buf[64];
86  ctime_r(&etimet, time_buf);
87  const std::string tstamp(time_buf);
88 #else
89  char* time_buf = new char[64];
90  ctime_s(time_buf, 64, &etimet);
91  const std::string tstamp(time_buf);
92 #endif
93 
94  const char* githash1 = amrex::buildInfoGetGitHash(1);
95  const char* githash2 = amrex::buildInfoGetGitHash(2);
96 
97  // clang-format off
98  out << dbl_line
99  << " ERF (https://github.com/erf-model/ERF)"
100  << std::endl << std::endl
101  << " ERF Git SHA :: " << githash1 << std::endl
102  << " AMReX Git SHA :: " << githash2 << std::endl
103  << " AMReX version :: " << amrex::Version() << std::endl << std::endl
104  << " Exec. time :: " << tstamp
105  << " Build time :: " << amrex::buildInfoGetBuildDate() << std::endl
106  << " C++ compiler :: " << amrex::buildInfoGetComp()
107  << " " << amrex::buildInfoGetCompVersion() << std::endl << std::endl
108  << " MPI :: "
109 #ifdef AMREX_USE_MPI
110  << "ON (Num. ranks = " << num_ranks << ")" << std::endl
111 #else
112  << "OFF " << std::endl
113 #endif
114  << " GPU :: "
115 #ifdef AMREX_USE_GPU
116  << "ON "
117 #if defined(AMREX_USE_CUDA)
118  << "(Backend: CUDA)"
119 #elif defined(AMREX_USE_HIP)
120  << "(Backend: HIP)"
121 #elif defined(AMREX_USE_SYCL)
122  << "(Backend: SYCL)"
123 #endif
124  << std::endl
125 #else
126  << "OFF" << std::endl
127 #endif
128  << " OpenMP :: "
129 #ifdef AMREX_USE_OMP
130  << "ON (Num. threads = " << omp_get_max_threads() << ")" << std::endl
131 #else
132  << "OFF" << std::endl
133 #endif
134  << std::endl;
135 
ERF()
Definition: ERF.cpp:93
const char * buildInfoGetBuildDate()
const char * buildInfoGetComp()
const char * buildInfoGetCompVersion()

Referenced by main().

Here is the caller graph for this function:

◆ print_error()

void ERF::print_error ( MPI_Comm  comm,
const std::string &  msg 
)
static
43  :
44  input_file : Input file with simulation settings
45 
46 Optional:
47  param=value : Overrides for parameters during runtime
48 )doc" << std::endl;
49 }
50 
51 void ERF::print_error (MPI_Comm comm, const std::string& msg)
52 {
53 #ifdef AMREX_USE_MPI
54  int irank = 0;
55  int num_ranks = 1;
56  MPI_Comm_size(comm, &num_ranks);
57  MPI_Comm_rank(comm, &irank);
58 

Referenced by main().

Here is the caller graph for this function:

◆ print_summary()

static void ERF::print_summary ( std::ostream &  )
static

◆ print_tpls()

void ERF::print_tpls ( std::ostream &  out)
static
140  ://github.com/erf-model/ERF/blob/development/LICENSE for details. "
141  << dash_line << std::endl;
142  // clang-format on
143 }
144 
145 void ERF::print_tpls (std::ostream& out)
146 {
147  amrex::Vector<std::string> tpls;
148 
149 #ifdef ERF_USE_NETCDF
150  tpls.push_back(std::string("NetCDF ") + NC_VERSION);
151 #endif
152 #ifdef AMREX_USE_SUNDIALS
153  tpls.push_back(std::string("SUNDIALS ") + SUNDIALS_VERSION);
154 #endif
155 
156  if (!tpls.empty()) {
157  out << " Enabled third-party libraries: ";
158  for (const auto& val : tpls) {
static void print_tpls(std::ostream &)
Definition: console_io.cpp:137

◆ print_usage()

void ERF::print_usage ( MPI_Comm  comm,
std::ostream &  out 
)
static
27 {
28 #ifdef AMREX_USE_MPI
29  int irank = 0;
30  int num_ranks = 1;
31  MPI_Comm_size(comm, &num_ranks);
32  MPI_Comm_rank(comm, &irank);
33 
34  // Only root process does the printing
35  if (irank != 0) return;
36 #else
37  amrex::ignore_unused(comm);
38 #endif
39 
40  out << R"doc(Usage:
41  ERF3d.*.ex <input_file> [param=value] [param=value] ...

Referenced by main().

Here is the caller graph for this function:

◆ ReadCheckpointFile()

void ERF::ReadCheckpointFile ( )
private

ERF function for reading data from a checkpoint file during restart.

266 {
267  Print() << "Restart from native checkpoint " << restart_chkfile << "\n";
268 
269  // Header
270  std::string File(restart_chkfile + "/Header");
271 
272  VisMF::IO_Buffer io_buffer(VisMF::GetIOBufferSize());
273 
274  Vector<char> fileCharPtr;
275  ParallelDescriptor::ReadAndBcastFile(File, fileCharPtr);
276  std::string fileCharPtrString(fileCharPtr.dataPtr());
277  std::istringstream is(fileCharPtrString, std::istringstream::in);
278 
279  std::string line, word;
280 
281  int chk_ncomp_cons, chk_ncomp;
282 
283  // read in title line
284  std::getline(is, line);
285 
286  // read in finest_level
287  is >> finest_level;
288  GotoNextLine(is);
289 
290  // read the number of components
291  // for each variable we store
292 
293  // conservative, cell-centered vars
294  is >> chk_ncomp_cons;
295  GotoNextLine(is);
296 
297  // x-velocity on faces
298  is >> chk_ncomp;
299  GotoNextLine(is);
300  AMREX_ASSERT(chk_ncomp == 1);
301 
302  // y-velocity on faces
303  is >> chk_ncomp;
304  GotoNextLine(is);
305  AMREX_ASSERT(chk_ncomp == 1);
306 
307  // z-velocity on faces
308  is >> chk_ncomp;
309  GotoNextLine(is);
310  AMREX_ASSERT(chk_ncomp == 1);
311 
312  // read in array of istep
313  std::getline(is, line);
314  {
315  std::istringstream lis(line);
316  int i = 0;
317  while (lis >> word) {
318  istep[i++] = std::stoi(word);
319  }
320  }
321 
322  // read in array of dt
323  std::getline(is, line);
324  {
325  std::istringstream lis(line);
326  int i = 0;
327  while (lis >> word) {
328  dt[i++] = std::stod(word);
329  }
330  }
331 
332  // read in array of t_new
333  std::getline(is, line);
334  {
335  std::istringstream lis(line);
336  int i = 0;
337  while (lis >> word) {
338  t_new[i++] = std::stod(word);
339  }
340  }
341 
342  for (int lev = 0; lev <= finest_level; ++lev) {
343  // read in level 'lev' BoxArray from Header
344  BoxArray ba;
345  ba.readFrom(is);
346  GotoNextLine(is);
347 
348  // create a distribution mapping
349  DistributionMapping dm { ba, ParallelDescriptor::NProcs() };
350 
351  MakeNewLevelFromScratch (lev, t_new[lev], ba, dm);
352  }
353 
354  // ncomp is only valid after we MakeNewLevelFromScratch (asks micro how many vars)
355  // NOTE: Data is written over ncomp, so check that we match the header file
356  int ncomp_cons = vars_new[0][Vars::cons].nComp();
357  AMREX_ASSERT(chk_ncomp_cons == ncomp_cons);
358 
359  // read in the MultiFab data
360  for (int lev = 0; lev <= finest_level; ++lev)
361  {
362  MultiFab cons(grids[lev],dmap[lev],ncomp_cons,0);
363  VisMF::Read(cons, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "Cell"));
364  MultiFab::Copy(vars_new[lev][Vars::cons],cons,0,0,ncomp_cons,0);
365  vars_new[lev][Vars::cons].setBndry(1.0e34);
366 
367  MultiFab xvel(convert(grids[lev],IntVect(1,0,0)),dmap[lev],1,0);
368  VisMF::Read(xvel, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "XFace"));
369  MultiFab::Copy(vars_new[lev][Vars::xvel],xvel,0,0,1,0);
370  vars_new[lev][Vars::xvel].setBndry(1.0e34);
371 
372  MultiFab yvel(convert(grids[lev],IntVect(0,1,0)),dmap[lev],1,0);
373  VisMF::Read(yvel, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "YFace"));
374  MultiFab::Copy(vars_new[lev][Vars::yvel],yvel,0,0,1,0);
375  vars_new[lev][Vars::yvel].setBndry(1.0e34);
376 
377  MultiFab zvel(convert(grids[lev],IntVect(0,0,1)),dmap[lev],1,0);
378  VisMF::Read(zvel, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "ZFace"));
379  MultiFab::Copy(vars_new[lev][Vars::zvel],zvel,0,0,1,0);
380  vars_new[lev][Vars::zvel].setBndry(1.0e34);
381 
382  // Note that we read the ghost cells of the base state (unlike above)
383  IntVect ng = base_state[lev].nGrowVect();
384  MultiFab base(grids[lev],dmap[lev],base_state[lev].nComp(),ng);
385  VisMF::Read(base, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "BaseState"));
386  MultiFab::Copy(base_state[lev],base,0,0,base.nComp(),ng);
387  base_state[lev].FillBoundary(geom[lev].periodicity());
388 
390  // Note that we also read the ghost cells of z_phys_nd
391  ng = z_phys_nd[lev]->nGrowVect();
392  MultiFab z_height(convert(grids[lev],IntVect(1,1,1)),dmap[lev],1,ng);
393  VisMF::Read(z_height, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "Z_Phys_nd"));
394  MultiFab::Copy(*z_phys_nd[lev],z_height,0,0,1,ng);
395  update_terrain_arrays(lev, t_new[lev]);
396  }
397 
398  // Read in the precipitation accumulation component
400  ng = qmoist[lev][4]->nGrowVect();
401  int nvar = 1;
402  MultiFab moist_vars(grids[lev],dmap[lev],nvar,ng);
403  VisMF::Read(moist_vars, amrex::MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "RainAccum"));
404  MultiFab::Copy(*(qmoist[lev][4]),moist_vars,0,0,nvar,ng);
405  }
406 
408  ng = qmoist[lev][8]->nGrowVect();
409  int nvar = 1;
410  MultiFab rain_accum(grids[lev],dmap[lev],nvar,ng);
411  VisMF::Read(rain_accum, amrex::MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "RainAccum"));
412  MultiFab::Copy(*(qmoist[lev][8]),rain_accum,0,0,nvar,ng);
413 
414  ng = qmoist[lev][9]->nGrowVect();
415  MultiFab snow_accum(grids[lev],dmap[lev],nvar,ng);
416  VisMF::Read(snow_accum, amrex::MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "SnowAccum"));
417  MultiFab::Copy(*(qmoist[lev][9]),snow_accum,0,0,nvar,ng);
418 
419  ng = qmoist[lev][10]->nGrowVect();
420  MultiFab graup_accum(grids[lev],dmap[lev],nvar,ng);
421  VisMF::Read(graup_accum, amrex::MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "GraupAccum"));
422  MultiFab::Copy(*(qmoist[lev][10]),graup_accum,0,0,nvar,ng);
423 
424  }
425 
426 #if defined(ERF_USE_WINDFARM)
428  ng = Nturb[lev].nGrowVect();
429  MultiFab mf_Nturb(grids[lev],dmap[lev],1,ng);
430  VisMF::Read(mf_Nturb, amrex::MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "NumTurb"));
431  MultiFab::Copy(Nturb[lev],mf_Nturb,0,0,1,ng);
432  }
433 #endif
434 
436  for (int mvar(0); mvar<lsm_data[lev].size(); ++mvar) {
437  BoxArray ba = lsm_data[lev][mvar]->boxArray();
438  DistributionMapping dm = lsm_data[lev][mvar]->DistributionMap();
439  ng = lsm_data[lev][mvar]->nGrowVect();
440  int nvar = lsm_data[lev][mvar]->nComp();
441  MultiFab lsm_vars(ba,dm,nvar,ng);
442  VisMF::Read(lsm_vars, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "LsmVars"));
443  MultiFab::Copy(*(lsm_data[lev][mvar]),lsm_vars,0,0,nvar,ng);
444  }
445  }
446 
447  // Note that we read the ghost cells of the mapfactors
448  BoxList bl2d = grids[lev].boxList();
449  for (auto& b : bl2d) {
450  b.setRange(2,0);
451  }
452  BoxArray ba2d(std::move(bl2d));
453 
454  ng = mapfac_m[lev]->nGrowVect();
455  MultiFab mf_m(ba2d,dmap[lev],1,ng);
456  VisMF::Read(mf_m, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "MapFactor_m"));
457  MultiFab::Copy(*mapfac_m[lev],mf_m,0,0,1,ng);
458 
459  ng = mapfac_u[lev]->nGrowVect();
460  MultiFab mf_u(convert(ba2d,IntVect(1,0,0)),dmap[lev],1,ng);
461  VisMF::Read(mf_u, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "MapFactor_u"));
462  MultiFab::Copy(*mapfac_u[lev],mf_u,0,0,1,ng);
463 
464  ng = mapfac_v[lev]->nGrowVect();
465  MultiFab mf_v(convert(ba2d,IntVect(0,1,0)),dmap[lev],1,ng);
466  VisMF::Read(mf_v, MultiFabFileFullPrefix(lev, restart_chkfile, "Level_", "MapFactor_v"));
467  MultiFab::Copy(*mapfac_v[lev],mf_v,0,0,1,ng);
468  }
469 
470 #ifdef ERF_USE_PARTICLES
471  particleData.Restart((ParGDBBase*)GetParGDB(),restart_chkfile);
472 #endif
473 
474 #ifdef ERF_USE_NETCDF
475  // Read bdy_data files
476  if ((init_type=="real") || (init_type=="metgrid")) {
477  int ioproc = ParallelDescriptor::IOProcessorNumber(); // I/O rank
478  int num_time;
479  int num_var;
480  Vector<Box> bx_v;
481  if (ParallelDescriptor::IOProcessor()) {
482  // Open header file and read from it
483  std::ifstream bdy_h_file(MultiFabFileFullPrefix(0, restart_chkfile, "Level_", "bdy_H"));
484  bdy_h_file >> num_time;
485  bdy_h_file >> num_var;
486  bdy_h_file >> start_bdy_time;
487  bdy_h_file >> bdy_time_interval;
488  bdy_h_file >> real_width;
489  bx_v.resize(4*num_var);
490  for (int ivar(0); ivar<num_var; ++ivar) {
491  bdy_h_file >> bx_v[4*ivar ];
492  bdy_h_file >> bx_v[4*ivar+1];
493  bdy_h_file >> bx_v[4*ivar+2];
494  bdy_h_file >> bx_v[4*ivar+3];
495  }
496 
497  // IO size the FABs
498  bdy_data_xlo.resize(num_time);
499  bdy_data_xhi.resize(num_time);
500  bdy_data_ylo.resize(num_time);
501  bdy_data_yhi.resize(num_time);
502  for (int itime(0); itime<num_time; ++itime) {
503  bdy_data_xlo[itime].resize(num_var);
504  bdy_data_xhi[itime].resize(num_var);
505  bdy_data_ylo[itime].resize(num_var);
506  bdy_data_yhi[itime].resize(num_var);
507  for (int ivar(0); ivar<num_var; ++ivar) {
508  bdy_data_xlo[itime][ivar].resize(bx_v[4*ivar ]);
509  bdy_data_xhi[itime][ivar].resize(bx_v[4*ivar+1]);
510  bdy_data_ylo[itime][ivar].resize(bx_v[4*ivar+2]);
511  bdy_data_yhi[itime][ivar].resize(bx_v[4*ivar+3]);
512  }
513  }
514 
515  // Open data file and read from it
516  std::ifstream bdy_d_file(MultiFabFileFullPrefix(0, restart_chkfile, "Level_", "bdy_D"));
517  for (int itime(0); itime<num_time; ++itime) {
518  for (int ivar(0); ivar<num_var; ++ivar) {
519  bdy_data_xlo[itime][ivar].readFrom(bdy_d_file);
520  bdy_data_xhi[itime][ivar].readFrom(bdy_d_file);
521  bdy_data_ylo[itime][ivar].readFrom(bdy_d_file);
522  bdy_data_yhi[itime][ivar].readFrom(bdy_d_file);
523  }
524  }
525  } // IO
526 
527  // Broadcast the data
528  ParallelDescriptor::Barrier();
529  ParallelDescriptor::Bcast(&start_bdy_time,1,ioproc);
530  ParallelDescriptor::Bcast(&bdy_time_interval,1,ioproc);
531  ParallelDescriptor::Bcast(&real_width,1,ioproc);
532  ParallelDescriptor::Bcast(&num_time,1,ioproc);
533  ParallelDescriptor::Bcast(&num_var,1,ioproc);
534 
535  // Everyone size their boxes
536  bx_v.resize(4*num_var);
537 
538  ParallelDescriptor::Bcast(bx_v.dataPtr(),bx_v.size(),ioproc);
539 
540  // Everyone but IO size their FABs
541  if (!ParallelDescriptor::IOProcessor()) {
542  bdy_data_xlo.resize(num_time);
543  bdy_data_xhi.resize(num_time);
544  bdy_data_ylo.resize(num_time);
545  bdy_data_yhi.resize(num_time);
546  for (int itime(0); itime<num_time; ++itime) {
547  bdy_data_xlo[itime].resize(num_var);
548  bdy_data_xhi[itime].resize(num_var);
549  bdy_data_ylo[itime].resize(num_var);
550  bdy_data_yhi[itime].resize(num_var);
551  for (int ivar(0); ivar<num_var; ++ivar) {
552  bdy_data_xlo[itime][ivar].resize(bx_v[4*ivar ]);
553  bdy_data_xhi[itime][ivar].resize(bx_v[4*ivar+1]);
554  bdy_data_ylo[itime][ivar].resize(bx_v[4*ivar+2]);
555  bdy_data_yhi[itime][ivar].resize(bx_v[4*ivar+3]);
556  }
557  }
558  }
559 
560  for (int itime(0); itime<num_time; ++itime) {
561  for (int ivar(0); ivar<num_var; ++ivar) {
562  ParallelDescriptor::Bcast(bdy_data_xlo[itime][ivar].dataPtr(),bdy_data_xlo[itime][ivar].box().numPts(),ioproc);
563  ParallelDescriptor::Bcast(bdy_data_xhi[itime][ivar].dataPtr(),bdy_data_xhi[itime][ivar].box().numPts(),ioproc);
564  ParallelDescriptor::Bcast(bdy_data_ylo[itime][ivar].dataPtr(),bdy_data_ylo[itime][ivar].box().numPts(),ioproc);
565  ParallelDescriptor::Bcast(bdy_data_yhi[itime][ivar].dataPtr(),bdy_data_yhi[itime][ivar].box().numPts(),ioproc);
566  }
567  }
568  } // init real
569 #endif
570 }
static void GotoNextLine(std::istream &is)
Definition: Checkpoint.cpp:13
void MakeNewLevelFromScratch(int lev, amrex::Real time, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm) override
Definition: ERF_make_new_level.cpp:27
int real_width
Definition: ERF.H:861
@ rain_accum
Definition: Kessler.H:41
@ snow_accum
Definition: SAM.H:47
@ graup_accum
Definition: SAM.H:48

◆ ReadParameters()

void ERF::ReadParameters ( )
private
1191 {
1192  {
1193  ParmParse pp; // Traditionally, max_step and stop_time do not have prefix.
1194  pp.query("max_step", max_step);
1195  pp.query("stop_time", stop_time);
1196 
1197  pp.query("start_time", start_time); // This is optional, it defaults to 0
1198  }
1199 
1200  ParmParse pp(pp_prefix);
1201  ParmParse pp_amr("amr");
1202  {
1203  // The type of the file we restart from
1204  pp.query("restart_type", restart_type);
1205 
1206  pp.query("regrid_int", regrid_int);
1207  pp.query("check_file", check_file);
1208  pp.query("check_type", check_type);
1209 
1210  // The regression tests use "amr.restart" and "amr.m_check_int" so we allow
1211  // for those or "erf.restart" / "erf.m_check_int" with the former taking
1212  // precedence if both are specified
1213  pp.query("check_int", m_check_int);
1214  pp.query("check_per", m_check_per);
1215  pp_amr.query("check_int", m_check_int);
1216  pp_amr.query("check_per", m_check_per);
1217 
1218  pp.query("restart", restart_chkfile);
1219  pp_amr.query("restart", restart_chkfile);
1220 
1221  // Verbosity
1222  pp.query("v", verbose);
1223 
1224  // Frequency of diagnostic output
1225  pp.query("sum_interval", sum_interval);
1226  pp.query("sum_period" , sum_per);
1227 
1228  // Time step controls
1229  pp.query("cfl", cfl);
1230  pp.query("init_shrink", init_shrink);
1231  pp.query("change_max", change_max);
1232 
1233  pp.query("fixed_dt", fixed_dt);
1234  pp.query("fixed_fast_dt", fixed_fast_dt);
1235  pp.query("fixed_mri_dt_ratio", fixed_mri_dt_ratio);
1236 
1237  // If this is set, it must be even
1238  if (fixed_mri_dt_ratio > 0 && (fixed_mri_dt_ratio%2 != 0) )
1239  {
1240  Abort("If you specify fixed_mri_dt_ratio, it must be even");
1241  }
1242 
1243  // If both fixed_dt and fast_dt are specified, their ratio must be an even integer
1244  if (fixed_dt > 0. && fixed_fast_dt > 0. && fixed_mri_dt_ratio <= 0)
1245  {
1246  Real eps = 1.e-12;
1247  int ratio = static_cast<int>( ( (1.0+eps) * fixed_dt ) / fixed_fast_dt );
1248  if (fixed_dt / fixed_fast_dt != ratio)
1249  {
1250  Abort("Ratio of fixed_dt to fixed_fast_dt must be an even integer");
1251  }
1252  }
1253 
1254  // If all three are specified, they must be consistent
1255  if (fixed_dt > 0. && fixed_fast_dt > 0. && fixed_mri_dt_ratio > 0)
1256  {
1258  {
1259  Abort("Dt is over-specfied");
1260  }
1261  }
1262 
1263  AMREX_ALWAYS_ASSERT(cfl > 0. || fixed_dt > 0.);
1264 
1265  // How to initialize
1266  pp.query("init_type",init_type);
1267  if (!init_type.empty() &&
1268  init_type != "uniform" &&
1269  init_type != "ideal" &&
1270  init_type != "real" &&
1271  init_type != "metgrid" &&
1272  init_type != "input_sounding")
1273  {
1274  Error("if specified, init_type must be uniform, ideal, real, metgrid or input_sounding");
1275  }
1276 
1277  // Should we use the bcs we've read in from wrfbdy or metgrid files?
1278  // We default to yes if we have them, but the user can override that option
1279  use_real_bcs = ( (init_type == "real") || (init_type == "metgrid") );
1280  pp.query("use_real_bcs",use_real_bcs);
1281 
1282  // We don't allow use_real_bcs to be true if init_type is not either real or metgrid
1283  AMREX_ALWAYS_ASSERT(!use_real_bcs || ((init_type == "real") || (init_type == "metgrid")) );
1284 
1285  // No moving terrain with init real
1287  Abort("Moving terrain is not supported with init real");
1288  }
1289 
1290  // We use this to keep track of how many boxes we read in from WRF initialization
1291  num_files_at_level.resize(max_level+1,0);
1292 
1293  // We use this to keep track of how many boxes are specified thru the refinement indicators
1294  num_boxes_at_level.resize(max_level+1,0);
1295  boxes_at_level.resize(max_level+1);
1296 
1297  // These hold the minimum and maximum value of k in the boxes *at each level*
1298  min_k_at_level.resize(max_level+1,0);
1299  max_k_at_level.resize(max_level+1,0);
1300 
1301  // We always have exactly one file at level 0
1302  num_boxes_at_level[0] = 1;
1303  boxes_at_level[0].resize(1);
1304  boxes_at_level[0][0] = geom[0].Domain();
1305 
1306 #ifdef ERF_USE_NETCDF
1307  nc_init_file.resize(max_level+1);
1308 
1309  // NetCDF wrfinput initialization files -- possibly multiple files at each of multiple levels
1310  // but we always have exactly one file at level 0
1311  for (int lev = 0; lev <= max_level; lev++)
1312  {
1313  const std::string nc_file_names = Concatenate("nc_init_file_",lev,1);
1314  if (pp.contains(nc_file_names.c_str()))
1315  {
1316  int num_files = pp.countval(nc_file_names.c_str());
1317  num_files_at_level[lev] = num_files;
1318  nc_init_file[lev].resize(num_files);
1319  pp.queryarr(nc_file_names.c_str(), nc_init_file[lev],0,num_files);
1320  for (int j = 0; j < num_files; j++)
1321  Print() << "Reading NC init file names at level " << lev << " and index " << j << " : " << nc_init_file[lev][j] << std::endl;
1322  }
1323  }
1324 
1325  // NetCDF wrfbdy lateral boundary file
1326  pp.query("nc_bdy_file", nc_bdy_file);
1327 #endif
1328 
1329  // Text input_sounding file
1330  pp.query("input_sounding_file", input_sounding_file);
1331 
1332  // Text input_sounding file
1333  pp.query("input_sponge_file", input_sponge_file);
1334 
1335  // Flag to trigger initialization from input_sounding like WRF's ideal.exe
1336  pp.query("init_sounding_ideal", init_sounding_ideal);
1337 
1338  // Output format
1339  pp.query("plotfile_type", plotfile_type);
1340  if (plotfile_type != "amrex" &&
1341  plotfile_type != "netcdf" && plotfile_type != "NetCDF" &&
1342  plotfile_type != "hdf5" && plotfile_type != "HDF5" )
1343  {
1344  Print() << "User selected plotfile_type = " << plotfile_type << std::endl;
1345  Abort("Dont know this plotfile_type");
1346  }
1347  pp.query("plot_file_1", plot_file_1);
1348  pp.query("plot_file_2", plot_file_2);
1349  pp.query("plot_int_1" , m_plot_int_1);
1350  pp.query("plot_int_2" , m_plot_int_2);
1351  pp.query("plot_per_1", m_plot_per_1);
1352  pp.query("plot_per_2", m_plot_per_2);
1353 
1354  if ( (m_plot_int_1 > 0 && m_plot_per_1 > 0) ||
1355  (m_plot_int_2 > 0 && m_plot_per_2 > 0.) ) {
1356  Abort("Must choose only one of plot_int or plot_per");
1357  }
1358 
1359  pp.query("profile_int", profile_int);
1360  pp.query("interp_profiles_to_cc", cc_profiles);
1361 
1362  pp.query("plot_lsm", plot_lsm);
1363 
1364  pp.query("output_1d_column", output_1d_column);
1365  pp.query("column_per", column_per);
1366  pp.query("column_interval", column_interval);
1367  pp.query("column_loc_x", column_loc_x);
1368  pp.query("column_loc_y", column_loc_y);
1369  pp.query("column_file_name", column_file_name);
1370 
1371  // Specify information about outputting planes of data
1372  pp.query("output_bndry_planes", output_bndry_planes);
1373  pp.query("bndry_output_planes_interval", bndry_output_planes_interval);
1374  pp.query("bndry_output_planes_per", bndry_output_planes_per);
1375  pp.query("bndry_output_start_time", bndry_output_planes_start_time);
1376 
1377  // Specify whether ingest boundary planes of data
1378  pp.query("input_bndry_planes", input_bndry_planes);
1379 
1380  // Query the set and total widths for wrfbdy interior ghost cells
1381  pp.query("real_width", real_width);
1382  pp.query("real_set_width", real_set_width);
1383  AMREX_ALWAYS_ASSERT(real_width >= 0);
1384  AMREX_ALWAYS_ASSERT(real_set_width >= 0);
1385  AMREX_ALWAYS_ASSERT(real_width >= real_set_width);
1386 
1387  // Query the set and total widths for crse-fine interior ghost cells
1388  pp.query("cf_width", cf_width);
1389  pp.query("cf_set_width", cf_set_width);
1390  if (cf_width < 0 || cf_set_width < 0 || cf_width < cf_set_width) {
1391  Abort("You must set cf_width >= cf_set_width >= 0");
1392  }
1393  if (max_level > 0 && cf_set_width > 0) {
1394  for (int lev = 1; lev <= max_level; lev++) {
1395  if (cf_set_width%ref_ratio[lev-1][0] != 0 ||
1396  cf_set_width%ref_ratio[lev-1][1] != 0 ||
1397  cf_set_width%ref_ratio[lev-1][2] != 0 ) {
1398  Abort("You must set cf_width to be a multiple of ref_ratio");
1399  }
1400  }
1401  }
1402 
1403  // AmrMesh iterate on grids?
1404  bool iterate(true);
1405  pp_amr.query("iterate_grids",iterate);
1406  if (!iterate) SetIterateToFalse();
1407  }
1408 
1409 #ifdef ERF_USE_PARTICLES
1410  readTracersParams();
1411 #endif
1412 
1413 #ifdef ERF_USE_MULTIBLOCK
1415 #endif
1416 
1417  solverChoice.init_params(max_level);
1418 
1419  // What type of land surface model to use
1420  // NOTE: Must be checked after init_params
1422  lsm.SetModel<SLM>();
1423  Print() << "SLM land surface model!\n";
1424  } else if (solverChoice.lsm_type == LandSurfaceType::MM5) {
1425  lsm.SetModel<MM5>();
1426  Print() << "MM5 land surface model!\n";
1428  lsm.SetModel<NullSurf>();
1429  Print() << "Null land surface model!\n";
1430  } else {
1431  Abort("Dont know this moisture_type!") ;
1432  }
1433 
1434  if (verbose > 0) {
1436  }
1437 
1439  Abort("For two-way coupling you must set cf_width = 0");
1440  }
1441 }
amrex::Vector< amrex::Vector< amrex::Box > > boxes_at_level
Definition: ERF.H:583
std::string plot_file_2
Definition: ERF.H:765
std::string restart_type
Definition: ERF.H:780
int regrid_int
Definition: ERF.H:761
amrex::Vector< int > num_files_at_level
Definition: ERF.H:582
static std::string nc_bdy_file
Definition: ERF.H:860
static amrex::Vector< amrex::Vector< std::string > > nc_init_file
Definition: ERF.H:857
std::string plot_file_1
Definition: ERF.H:764
int real_set_width
Definition: ERF.H:862
static amrex::Real init_shrink
Definition: ERF.H:751
amrex::Vector< int > num_boxes_at_level
Definition: ERF.H:581
std::string check_file
Definition: ERF.H:778
static std::string plotfile_type
Definition: ERF.H:844
bool plot_lsm
Definition: ERF.H:771
void SetModel()
Definition: LandSurface.H:23
Definition: MM5.H:26
Definition: NullSurf.H:8
Definition: SLM.H:26
std::string pp_prefix
Definition: DataStruct.H:381
void init_params(int max_level)
Definition: DataStruct.H:65
void display()
Definition: DataStruct.H:293
Here is the call graph for this function:

◆ refinement_criteria_setup()

void ERF::refinement_criteria_setup ( )
private

Function to define the refinement criteria based on user input

108 {
109  if (max_level > 0)
110  {
111  ParmParse pp(pp_prefix);
112  Vector<std::string> refinement_indicators;
113  pp.queryarr("refinement_indicators",refinement_indicators,0,pp.countval("refinement_indicators"));
114 
115  for (int i=0; i<refinement_indicators.size(); ++i)
116  {
117  std::string ref_prefix = pp_prefix + "." + refinement_indicators[i];
118 
119  ParmParse ppr(ref_prefix);
120  RealBox realbox;
121  int lev_for_box;
122  if (ppr.countval("in_box_lo")) {
123  std::vector<Real> box_lo(3), box_hi(3);
124  ppr.get("max_level",lev_for_box);
125  if (lev_for_box <= max_level)
126  {
127  ppr.getarr("in_box_lo",box_lo,0,AMREX_SPACEDIM);
128  ppr.getarr("in_box_hi",box_hi,0,AMREX_SPACEDIM);
129  realbox = RealBox(&(box_lo[0]),&(box_hi[0]));
130 
131  Print() << "Reading " << realbox << " at level " << lev_for_box << std::endl;
132  num_boxes_at_level[lev_for_box] += 1;
133 
134  const auto* dx = geom[lev_for_box].CellSize();
135  const Real* plo = geom[lev_for_box].ProbLo();
136  int ilo = static_cast<int>((box_lo[0] - plo[0])/dx[0]);
137  int jlo = static_cast<int>((box_lo[1] - plo[1])/dx[1]);
138  int klo = static_cast<int>((box_lo[2] - plo[2])/dx[2]);
139  int ihi = static_cast<int>((box_hi[0] - plo[0])/dx[0]-1);
140  int jhi = static_cast<int>((box_hi[1] - plo[1])/dx[1]-1);
141  int khi = static_cast<int>((box_hi[2] - plo[2])/dx[2]-1);
142  Box bx(IntVect(ilo,jlo,klo),IntVect(ihi,jhi,khi));
143  if ( (ilo%ref_ratio[lev_for_box-1][0] != 0) || ((ihi+1)%ref_ratio[lev_for_box-1][0] != 0) ||
144  (jlo%ref_ratio[lev_for_box-1][1] != 0) || ((jhi+1)%ref_ratio[lev_for_box-1][1] != 0) )
145  amrex::Error("Fine box is not legit with this ref_ratio");
146  boxes_at_level[lev_for_box].push_back(bx);
147  Print() << "Saving in 'boxes at level' as " << bx << std::endl;
148  } // lev
149  if (init_type == "real" || init_type == "metgrid") {
150  if (num_boxes_at_level[lev_for_box] != num_files_at_level[lev_for_box]) {
151  amrex::Error("Number of boxes doesnt match number of input files");
152 
153  }
154  }
155  }
156 
157  AMRErrorTagInfo info;
158 
159  if (realbox.ok()) {
160  info.SetRealBox(realbox);
161  }
162  if (ppr.countval("start_time") > 0) {
163  Real ref_min_time; ppr.get("start_time",ref_min_time);
164  info.SetMinTime(ref_min_time);
165  }
166  if (ppr.countval("end_time") > 0) {
167  Real ref_max_time; ppr.get("end_time",ref_max_time);
168  info.SetMaxTime(ref_max_time);
169  }
170  if (ppr.countval("max_level") > 0) {
171  int ref_max_level; ppr.get("max_level",ref_max_level);
172  info.SetMaxLevel(ref_max_level);
173  }
174 
175  if (ppr.countval("value_greater")) {
176  int num_val = ppr.countval("value_greater");
177  Vector<Real> value(num_val);
178  ppr.getarr("value_greater",value,0,num_val);
179  std::string field; ppr.get("field_name",field);
180  ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::GREATER,field,info));
181  }
182  else if (ppr.countval("value_less")) {
183  int num_val = ppr.countval("value_less");
184  Vector<Real> value(num_val);
185  ppr.getarr("value_less",value,0,num_val);
186  std::string field; ppr.get("field_name",field);
187  ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::LESS,field,info));
188  }
189  else if (ppr.countval("adjacent_difference_greater")) {
190  int num_val = ppr.countval("adjacent_difference_greater");
191  Vector<Real> value(num_val);
192  ppr.getarr("adjacent_difference_greater",value,0,num_val);
193  std::string field; ppr.get("field_name",field);
194  ref_tags.push_back(AMRErrorTag(value,AMRErrorTag::GRAD,field,info));
195  }
196  else if (realbox.ok())
197  {
198  ref_tags.push_back(AMRErrorTag(info));
199  } else {
200  Abort(std::string("Unrecognized refinement indicator for " + refinement_indicators[i]).c_str());
201  }
202  } // loop over criteria
203  } // if max_level > 0
204 }
Here is the call graph for this function:

◆ RemakeLevel()

void ERF::RemakeLevel ( int  lev,
amrex::Real  time,
const amrex::BoxArray &  ba,
const amrex::DistributionMapping &  dm 
)
override
367 {
368  // amrex::Print() <<" REMAKING WITH NEW BA AT LEVEL " << lev << " " << ba << std::endl;
369 
370  BoxArray ba_old(vars_new[lev][Vars::cons].boxArray());
371  DistributionMapping dm_old(vars_new[lev][Vars::cons].DistributionMap());
372 
373  int ncomp_cons = vars_new[lev][Vars::cons].nComp();
374  IntVect ngrow_state = vars_new[lev][Vars::cons].nGrowVect();
375 
376  // int ngrow_state = ComputeGhostCells(solverChoice.advChoice, solverChoice.use_NumDiff) + 1;
378 
379  Vector<MultiFab> temp_lev_new(Vars::NumTypes);
380  Vector<MultiFab> temp_lev_old(Vars::NumTypes);
381 
382  //********************************************************************************************
383  // This allocates all kinds of things, including but not limited to: solution arrays,
384  // terrain arrays and metrics, and base state.
385  // *******************************************************************************************
386  init_stuff(lev, ba, dm, temp_lev_new, temp_lev_old);
387 
388  // *****************************************************************************************************
389  // Initialize the boundary conditions (after initializing the terrain but before calling FillCoarsePatch
390  // *****************************************************************************************************
391  initialize_bcs(lev);
392 
393  // ********************************************************************************************
394  // This will fill the temporary MultiFabs with data from vars_new
395  // ********************************************************************************************
396  FillPatch(lev, time, {&temp_lev_new[Vars::cons],&temp_lev_new[Vars::xvel],
397  &temp_lev_new[Vars::yvel],&temp_lev_new[Vars::zvel]},
398  {&temp_lev_new[Vars::cons],&rU_new[lev],&rV_new[lev],&rW_new[lev]},
399  false);
400 
401  // ********************************************************************************************
402  // Copy from new into old just in case
403  // ********************************************************************************************
404  MultiFab::Copy(temp_lev_old[Vars::cons],temp_lev_new[Vars::cons],0,0,ncomp_cons,ngrow_state);
405  MultiFab::Copy(temp_lev_old[Vars::xvel],temp_lev_new[Vars::xvel],0,0, 1,ngrow_vels);
406  MultiFab::Copy(temp_lev_old[Vars::yvel],temp_lev_new[Vars::yvel],0,0, 1,ngrow_vels);
407  MultiFab::Copy(temp_lev_old[Vars::zvel],temp_lev_new[Vars::zvel],0,0, 1,IntVect(ngrow_vels,ngrow_vels,0));
408 
409  // ********************************************************************************************
410  // Now swap the pointers
411  // ********************************************************************************************
412  for (int var_idx = 0; var_idx < Vars::NumTypes; ++var_idx) {
413  std::swap(temp_lev_new[var_idx], vars_new[lev][var_idx]);
414  std::swap(temp_lev_old[var_idx], vars_old[lev][var_idx]);
415  }
416 
417  t_new[lev] = time;
418  t_old[lev] = time - 1.e200;
419 
420  // ********************************************************************************************
421  // Build the data structures for calculating diffusive/turbulent terms
422  // ********************************************************************************************
423  update_diffusive_arrays(lev, ba, dm);
424 
425  // ********************************************************************************************
426  // Build the data structures for terrain-related quantities
427  // ********************************************************************************************
428  update_terrain_arrays(lev, time);
429 
430  //
431  // Make sure that detJ and z_phys_cc are the average of the data on a finer level if there is one
432  //
433  if (solverChoice.use_terrain != 0) {
434  for (int crse_lev = lev-1; crse_lev >= 0; crse_lev--) {
435  average_down( *detJ_cc[crse_lev+1], *detJ_cc[crse_lev], 0, 1, refRatio(crse_lev));
436  average_down(*z_phys_cc[crse_lev+1], *z_phys_cc[crse_lev], 0, 1, refRatio(crse_lev));
437  }
438  }
439 
440  //********************************************************************************************
441  // Microphysics
442  // *******************************************************************************************
443  int q_size = micro->Get_Qmoist_Size(lev);
444  qmoist[lev].resize(q_size);
445  micro->Define(lev, solverChoice);
447  {
448  micro->Init(lev, vars_new[lev][Vars::cons],
449  grids[lev], Geom(lev), 0.0,
450  z_phys_nd[lev], detJ_cc[lev]); // dummy dt value
451  }
452  for (int mvar(0); mvar<qmoist[lev].size(); ++mvar) {
453  qmoist[lev][mvar] = micro->Get_Qmoist_Ptr(lev,mvar);
454  }
455 
456  // ********************************************************************************************
457  // Update the base state at this level
458  // ********************************************************************************************
459  // base_state[lev].define(ba,dm,3,1);
460  // base_state[lev].setVal(0.);
461  initHSE(lev);
462 
463  // ********************************************************************************************
464  // Initialize the integrator class
465  // ********************************************************************************************
467 
468  // We need to re-define the FillPatcher if the grids have changed
469  if (lev > 0 && cf_width >= 0) {
470  bool ba_changed = (ba != ba_old);
471  bool dm_changed = (dm != dm_old);
472  if (ba_changed || dm_changed) {
474  }
475  }
476 
477 #ifdef ERF_USE_PARTICLES
478  particleData.Redistribute();
479 #endif
480 }

◆ restart()

void ERF::restart ( )
1079 {
1080  // TODO: This could be deleted since ba/dm are not created yet?
1081  for (int lev = 0; lev <= finest_level; ++lev)
1082  {
1083  auto& lev_new = vars_new[lev];
1084  auto& lev_old = vars_old[lev];
1085  lev_new[Vars::cons].setVal(0.); lev_old[Vars::cons].setVal(0.);
1086  lev_new[Vars::xvel].setVal(0.); lev_old[Vars::xvel].setVal(0.);
1087  lev_new[Vars::yvel].setVal(0.); lev_old[Vars::yvel].setVal(0.);
1088  lev_new[Vars::zvel].setVal(0.); lev_old[Vars::zvel].setVal(0.);
1089  }
1090 
1091 #ifdef ERF_USE_NETCDF
1092  if (restart_type == "netcdf") {
1093  ReadNCCheckpointFile();
1094  }
1095 #endif
1096  if (restart_type == "native") {
1098  }
1099 
1100  // We set this here so that we don't over-write the checkpoint file we just started from
1102 }
void ReadCheckpointFile()
Definition: Checkpoint.cpp:265

◆ sample_lines()

void ERF::sample_lines ( int  lev,
amrex::Real  time,
amrex::IntVect  cell,
amrex::MultiFab &  mf 
)

Utility function for sampling data along a line along the z-dimension at the (x,y) indices specified and writes it to an output file.

Parameters
levCurrent level
timeCurrent time
cellIntVect containing the x,y-dimension indices to sample along z
mfMultiFab from which we sample the data
220 {
221  int datwidth = 14;
222  int datprecision = 6;
223 
224  int ifile = 0;
225 
226  const int ncomp = mf.nComp(); // cell-centered state vars
227 
228  MultiFab mf_vels(grids[lev], dmap[lev], AMREX_SPACEDIM, 0);
229  average_face_to_cellcenter(mf_vels, 0,
230  Array<const MultiFab*,3>{&vars_new[lev][Vars::xvel],&vars_new[lev][Vars::yvel],&vars_new[lev][Vars::zvel]});
231 
232  //
233  // Sample the data at a line (in direction "dir") in space
234  // In this case we sample in the vertical direction so dir = 2
235  // The "k" value of "cell" is ignored
236  //
237  int dir = 2;
238  MultiFab my_line = get_line_data(mf, dir, cell);
239  MultiFab my_line_vels = get_line_data(mf_vels, dir, cell);
240  MultiFab my_line_tau11 = get_line_data(*Tau11_lev[lev], dir, cell);
241  MultiFab my_line_tau12 = get_line_data(*Tau12_lev[lev], dir, cell);
242  MultiFab my_line_tau13 = get_line_data(*Tau13_lev[lev], dir, cell);
243  MultiFab my_line_tau22 = get_line_data(*Tau22_lev[lev], dir, cell);
244  MultiFab my_line_tau23 = get_line_data(*Tau23_lev[lev], dir, cell);
245  MultiFab my_line_tau33 = get_line_data(*Tau33_lev[lev], dir, cell);
246 
247  for (MFIter mfi(my_line, false); mfi.isValid(); ++mfi)
248  {
249  // HERE DO WHATEVER YOU WANT TO THE DATA BEFORE WRITING
250 
251  std::ostream& sample_log = SampleLineLog(ifile);
252  if (sample_log.good()) {
253  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << time;
254  const auto& my_line_arr = my_line[0].const_array();
255  const auto& my_line_vels_arr = my_line_vels[0].const_array();
256  const auto& my_line_tau11_arr = my_line_tau11[0].const_array();
257  const auto& my_line_tau12_arr = my_line_tau12[0].const_array();
258  const auto& my_line_tau13_arr = my_line_tau13[0].const_array();
259  const auto& my_line_tau22_arr = my_line_tau22[0].const_array();
260  const auto& my_line_tau23_arr = my_line_tau23[0].const_array();
261  const auto& my_line_tau33_arr = my_line_tau33[0].const_array();
262  const Box& my_box = my_line[0].box();
263  const int klo = my_box.smallEnd(2);
264  const int khi = my_box.bigEnd(2);
265  int i = cell[0];
266  int j = cell[1];
267  for (int n = 0; n < ncomp; n++) {
268  for (int k = klo; k <= khi; k++) {
269  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_arr(i,j,k,n);
270  }
271  }
272  for (int n = 0; n < AMREX_SPACEDIM; n++) {
273  for (int k = klo; k <= khi; k++) {
274  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_vels_arr(i,j,k,n);
275  }
276  }
277  for (int k = klo; k <= khi; k++) {
278  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_tau11_arr(i,j,k);
279  }
280  for (int k = klo; k <= khi; k++) {
281  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_tau12_arr(i,j,k);
282  }
283  for (int k = klo; k <= khi; k++) {
284  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_tau13_arr(i,j,k);
285  }
286  for (int k = klo; k <= khi; k++) {
287  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_tau22_arr(i,j,k);
288  }
289  for (int k = klo; k <= khi; k++) {
290  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_tau23_arr(i,j,k);
291  }
292  for (int k = klo; k <= khi; k++) {
293  sample_log << std::setw(datwidth) << std::setprecision(datprecision) << my_line_tau33_arr(i,j,k);
294  }
295  sample_log << std::endl;
296  } // if good
297  } // mfi
298 }
AMREX_FORCE_INLINE std::ostream & SampleLineLog(int i)
Definition: ERF.H:1028

◆ sample_points()

void ERF::sample_points ( int  lev,
amrex::Real  time,
amrex::IntVect  cell,
amrex::MultiFab &  mf 
)

Utility function for sampling MultiFab data at a specified cell index.

Parameters
levLevel for the associated MultiFab data
timeCurrent time
cellIntVect containing the indexes for the cell where we want to sample
mfMultiFab from which we wish to sample data
182 {
183  int datwidth = 14;
184 
185  int ifile = 0;
186 
187  //
188  // Sample the data at a single point in space
189  //
190  int ncomp = mf.nComp();
191  Vector<Real> my_point = get_cell_data(mf, cell);
192 
193  if (!my_point.empty()) {
194 
195  // HERE DO WHATEVER YOU WANT TO THE DATA BEFORE WRITING
196 
197  std::ostream& sample_log = SamplePointLog(ifile);
198  if (sample_log.good()) {
199  sample_log << std::setw(datwidth) << time;
200  for (int i = 0; i < ncomp; ++i)
201  {
202  sample_log << std::setw(datwidth) << my_point[i];
203  }
204  sample_log << std::endl;
205  } // if good
206  } // only write from processor that holds the cell
207 }
AMREX_FORCE_INLINE std::ostream & SamplePointLog(int i)
Definition: ERF.H:1014

◆ SampleLine()

amrex::IntVect& ERF::SampleLine ( int  i)
inlineprivate
1055  {
1056  return sampleline[i];
1057  }

◆ SampleLineLog()

AMREX_FORCE_INLINE std::ostream& ERF::SampleLineLog ( int  i)
inlineprivate
1029  {
1030  return *samplelinelog[i];
1031  }

◆ SampleLineLogName()

std::string ERF::SampleLineLogName ( int  i) const
inlineprivatenoexcept

The filename of the ith samplelinelog file.

1149 { return samplelinelogname[i]; }

◆ SamplePoint()

amrex::IntVect& ERF::SamplePoint ( int  i)
inlineprivate
1042  {
1043  return samplepoint[i];
1044  }

◆ SamplePointLog()

AMREX_FORCE_INLINE std::ostream& ERF::SamplePointLog ( int  i)
inlineprivate
1015  {
1016  return *sampleptlog[i];
1017  }

◆ SamplePointLogName()

std::string ERF::SamplePointLogName ( int  i) const
inlineprivatenoexcept

The filename of the ith sampleptlog file.

1146 { return sampleptlogname[i]; }

◆ setPlotVariables()

void ERF::setPlotVariables ( const std::string &  pp_plot_var_names,
amrex::Vector< std::string > &  plot_var_names 
)
private
19 {
20  ParmParse pp(pp_prefix);
21 
22  if (pp.contains(pp_plot_var_names.c_str()))
23  {
24  std::string nm;
25 
26  int nPltVars = pp.countval(pp_plot_var_names.c_str());
27 
28  for (int i = 0; i < nPltVars; i++)
29  {
30  pp.get(pp_plot_var_names.c_str(), nm, i);
31 
32  // Add the named variable to our list of plot variables
33  // if it is not already in the list
34  if (!containerHasElement(plot_var_names, nm)) {
35  plot_var_names.push_back(nm);
36  }
37  }
38  } else {
39  //
40  // The default is to add none of the variables to the list
41  //
42  plot_var_names.clear();
43  }
44 
45  // Get state variables in the same order as we define them,
46  // since they may be in any order in the input list
47  Vector<std::string> tmp_plot_names;
48 
49  int n_qstate = micro->Get_Qstate_Size();
50  int ncomp_cons = NVAR_max - (NMOIST_max - n_qstate);
51 
52  for (int i = 0; i < ncomp_cons; ++i) {
53  if ( containerHasElement(plot_var_names, cons_names[i]) ) {
54  tmp_plot_names.push_back(cons_names[i]);
55  }
56  }
57  // check for velocity since it's not in cons_names
58  // if we are asked for any velocity component, we will need them all
59  if (containerHasElement(plot_var_names, "x_velocity") ||
60  containerHasElement(plot_var_names, "y_velocity") ||
61  containerHasElement(plot_var_names, "z_velocity")) {
62  tmp_plot_names.push_back("x_velocity");
63  tmp_plot_names.push_back("y_velocity");
64  tmp_plot_names.push_back("z_velocity");
65  }
66  for (int i = 0; i < derived_names.size(); ++i) {
67  if ( containerHasElement(plot_var_names, derived_names[i]) ) {
68  if (solverChoice.use_terrain || (derived_names[i] != "z_phys" && derived_names[i] != "detJ") ) {
69  tmp_plot_names.push_back(derived_names[i]);
70  }
71  }
72  }
73 #ifdef ERF_USE_PARTICLES
74  const auto& particles_namelist( particleData.getNamesUnalloc() );
75  for (auto it = particles_namelist.cbegin(); it != particles_namelist.cend(); ++it) {
76  std::string tmp( (*it)+"_count" );
77  if (containerHasElement(plot_var_names, tmp) ) {
78  tmp_plot_names.push_back(tmp);
79  }
80  }
81 #endif
82 
83 #ifdef ERF_USE_EB
84  if (containerHasElement(plot_var_names, "volfrac")) {
85  tmp_plot_names.push_back("volfrac");
86  }
87 #endif
88 
89  plot_var_names = tmp_plot_names;
90 
91  for (int i=0; i<plot_var_names.size(); i++) {
92  }
93 }
const amrex::Vector< std::string > derived_names
Definition: ERF.H:791
const amrex::Vector< std::string > cons_names
Definition: ERF.H:786
Here is the call graph for this function:

◆ setRayleighRefFromSounding()

void ERF::setRayleighRefFromSounding ( bool  restarting)
private

Set Rayleigh mean profiles from input sounding.

Sets the Rayleigh Damping averaged quantities from an externally supplied input sounding data file.

Parameters
[in]restartingBoolean parameter that indicates whether we are currently restarting from a checkpoint file.
57 {
58  // If we are restarting then we haven't read the input_sounding file yet
59  // so we need to read it here
60  // TODO: should we store this information in the checkpoint file instead?
61  if (restarting) {
63  }
64 
65  const Real* z_inp_sound = input_sounding_data.z_inp_sound.dataPtr();
66  const Real* U_inp_sound = input_sounding_data.U_inp_sound.dataPtr();
67  const Real* V_inp_sound = input_sounding_data.V_inp_sound.dataPtr();
68  const Real* theta_inp_sound = input_sounding_data.theta_inp_sound.dataPtr();
69  const int inp_sound_size = input_sounding_data.size();
70 
71  for (int lev = 0; lev <= finest_level; lev++)
72  {
73  const int khi = geom[lev].Domain().bigEnd()[2];
74  Vector<Real> zcc(khi+1);
75 
76  if (z_phys_cc[lev]) {
77  // use_terrain=1
78  // calculate the damping strength based on the max height at each k
80  } else {
81  const auto *const prob_lo = geom[lev].ProbLo();
82  const auto *const dx = geom[lev].CellSize();
83  for (int k = 0; k <= khi; k++)
84  {
85  zcc[k] = prob_lo[2] + (k+0.5) * dx[2];
86  }
87  }
88 
89  for (int k = 0; k <= khi; k++)
90  {
91  h_rayleigh_ptrs[lev][Rayleigh::ubar][k] = interpolate_1d(z_inp_sound, U_inp_sound, zcc[k], inp_sound_size);
92  h_rayleigh_ptrs[lev][Rayleigh::vbar][k] = interpolate_1d(z_inp_sound, V_inp_sound, zcc[k], inp_sound_size);
93  h_rayleigh_ptrs[lev][Rayleigh::wbar][k] = Real(0.0);
94  h_rayleigh_ptrs[lev][Rayleigh::thetabar][k] = interpolate_1d(z_inp_sound, theta_inp_sound, zcc[k], inp_sound_size);
95  if (h_rayleigh_ptrs[lev][Rayleigh::tau][k] > 0) {
96  Print() << zcc[k] << ":" << " tau=" << h_rayleigh_ptrs[lev][Rayleigh::tau][k];
97  if (solverChoice.rayleigh_damp_U) Print() << " ubar = " << h_rayleigh_ptrs[lev][Rayleigh::ubar][k];
98  if (solverChoice.rayleigh_damp_V) Print() << " vbar = " << h_rayleigh_ptrs[lev][Rayleigh::vbar][k];
99  if (solverChoice.rayleigh_damp_W) Print() << " wbar = " << h_rayleigh_ptrs[lev][Rayleigh::wbar][k];
100  if (solverChoice.rayleigh_damp_T) Print() << " thetabar= " << h_rayleigh_ptrs[lev][Rayleigh::thetabar][k];
101  Print() << std::endl;
102  }
103  }
104 
105  // Copy from host version to device version
106  Gpu::copy(Gpu::hostToDevice, h_rayleigh_ptrs[lev][Rayleigh::ubar].begin(), h_rayleigh_ptrs[lev][Rayleigh::ubar].end(),
107  d_rayleigh_ptrs[lev][Rayleigh::ubar].begin());
108  Gpu::copy(Gpu::hostToDevice, h_rayleigh_ptrs[lev][Rayleigh::vbar].begin(), h_rayleigh_ptrs[lev][Rayleigh::vbar].end(),
109  d_rayleigh_ptrs[lev][Rayleigh::vbar].begin());
110  Gpu::copy(Gpu::hostToDevice, h_rayleigh_ptrs[lev][Rayleigh::wbar].begin(), h_rayleigh_ptrs[lev][Rayleigh::wbar].end(),
111  d_rayleigh_ptrs[lev][Rayleigh::wbar].begin());
112  Gpu::copy(Gpu::hostToDevice, h_rayleigh_ptrs[lev][Rayleigh::thetabar].begin(), h_rayleigh_ptrs[lev][Rayleigh::thetabar].end(),
113  d_rayleigh_ptrs[lev][Rayleigh::thetabar].begin());
114  }
115 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real interpolate_1d(const amrex::Real *alpha, const amrex::Real *beta, const amrex::Real alpha_interp, const int alpha_size)
Definition: Interpolation_1D.H:12
AMREX_FORCE_INLINE void reduce_to_max_per_level(amrex::Vector< amrex::Real > &v, std::unique_ptr< amrex::MultiFab > &mf)
Definition: ParFunctions.H:8
amrex::Vector< amrex::Real > z_inp_sound
Definition: InputSoundingData.H:248
amrex::Vector< amrex::Real > U_inp_sound
Definition: InputSoundingData.H:248
amrex::Vector< amrex::Real > V_inp_sound
Definition: InputSoundingData.H:248
amrex::Vector< amrex::Real > theta_inp_sound
Definition: InputSoundingData.H:248
int size() const
Definition: InputSoundingData.H:236
Here is the call graph for this function:

◆ setRecordDataInfo()

void ERF::setRecordDataInfo ( int  i,
const std::string &  filename 
)
inlineprivate
1085  {
1086  if (amrex::ParallelDescriptor::IOProcessor())
1087  {
1088  datalog[i] = std::make_unique<std::fstream>();
1089  datalog[i]->open(filename.c_str(),std::ios::out|std::ios::app);
1090  if (!datalog[i]->good()) {
1091  amrex::FileOpenFailed(filename);
1092  }
1093  }
1094  amrex::ParallelDescriptor::Barrier("ERF::setRecordDataInfo");
1095  }

◆ setRecordSampleLineInfo()

void ERF::setRecordSampleLineInfo ( int  i,
int  lev,
amrex::IntVect &  cell,
const std::string &  filename 
)
inlineprivate
1115  {
1116  amrex::MultiFab dummy(grids[lev],dmap[lev],1,0);
1117  for (amrex::MFIter mfi(dummy); mfi.isValid(); ++mfi)
1118  {
1119  const amrex::Box& bx = mfi.validbox();
1120  if (bx.contains(cell)) {
1121  samplelinelog[i] = std::make_unique<std::fstream>();
1122  samplelinelog[i]->open(filename.c_str(),std::ios::out|std::ios::app);
1123  if (!samplelinelog[i]->good()) {
1124  amrex::FileOpenFailed(filename);
1125  }
1126  }
1127  }
1128  amrex::ParallelDescriptor::Barrier("ERF::setRecordSampleLineInfo");
1129  }

◆ setRecordSamplePointInfo()

void ERF::setRecordSamplePointInfo ( int  i,
int  lev,
amrex::IntVect &  cell,
const std::string &  filename 
)
inlineprivate
1098  {
1099  amrex::MultiFab dummy(grids[lev],dmap[lev],1,0);
1100  for (amrex::MFIter mfi(dummy); mfi.isValid(); ++mfi)
1101  {
1102  const amrex::Box& bx = mfi.validbox();
1103  if (bx.contains(cell)) {
1104  sampleptlog[i] = std::make_unique<std::fstream>();
1105  sampleptlog[i]->open(filename.c_str(),std::ios::out|std::ios::app);
1106  if (!sampleptlog[i]->good()) {
1107  amrex::FileOpenFailed(filename);
1108  }
1109  }
1110  }
1111  amrex::ParallelDescriptor::Barrier("ERF::setRecordSamplePointInfo");
1112  }

◆ setSpongeRefFromSounding()

void ERF::setSpongeRefFromSounding ( bool  restarting)
private

Set sponge mean profiles from input sounding.

Sets the sponge damping averaged quantities from an externally supplied input sponge data file.

Parameters
[in]restartingBoolean parameter that indicates whether we are currently restarting from a checkpoint file.
153 {
154 
155  // If we are restarting then we haven't read the input_sponge file yet
156  // so we need to read it here
157  // TODO: should we store this information in the checkpoint file instead?
158  if (restarting) {
160  }
161 
162  const Real* z_inp_sponge = input_sponge_data.z_inp_sponge.dataPtr();
163  const Real* U_inp_sponge = input_sponge_data.U_inp_sponge.dataPtr();
164  const Real* V_inp_sponge = input_sponge_data.V_inp_sponge.dataPtr();
165  const int inp_sponge_size = input_sponge_data.size();
166 
167  for (int lev = 0; lev <= finest_level; lev++)
168  {
169  const int khi = geom[lev].Domain().bigEnd()[2];
170  Vector<Real> zcc(khi+1);
171 
172  if (z_phys_cc[lev]) {
173  // use_terrain=1
174  // calculate the damping strength based on the max height at each k
176  } else {
177  const auto *const prob_lo = geom[lev].ProbLo();
178  const auto *const dx = geom[lev].CellSize();
179  for (int k = 0; k <= khi; k++)
180  {
181  zcc[k] = prob_lo[2] + (k+0.5) * dx[2];
182  }
183  }
184 
185  for (int k = 0; k <= khi; k++)
186  {
187  h_sponge_ptrs[lev][Sponge::ubar_sponge][k] = interpolate_1d(z_inp_sponge, U_inp_sponge, zcc[k], inp_sponge_size);
188  h_sponge_ptrs[lev][Sponge::vbar_sponge][k] = interpolate_1d(z_inp_sponge, V_inp_sponge, zcc[k], inp_sponge_size);
189  }
190 
191  // Copy from host version to device version
192  Gpu::copy(Gpu::hostToDevice, h_sponge_ptrs[lev][Sponge::ubar_sponge].begin(), h_sponge_ptrs[lev][Sponge::ubar_sponge].end(),
193  d_sponge_ptrs[lev][Sponge::ubar_sponge].begin());
194  Gpu::copy(Gpu::hostToDevice, h_sponge_ptrs[lev][Sponge::vbar_sponge].begin(), h_sponge_ptrs[lev][Sponge::vbar_sponge].end(),
195  d_sponge_ptrs[lev][Sponge::vbar_sponge].begin());
196  }
197 }
amrex::Vector< amrex::Real > V_inp_sponge
Definition: InputSpongeData.H:107
amrex::Vector< amrex::Real > z_inp_sponge
Definition: InputSpongeData.H:107
amrex::Vector< amrex::Real > U_inp_sponge
Definition: InputSpongeData.H:107
int size() const
Definition: InputSpongeData.H:98
Here is the call graph for this function:

◆ sum_integrated_quantities()

void ERF::sum_integrated_quantities ( amrex::Real  time)

Computes the integrated quantities on the grid such as the total scalar and total mass quantities. Prints and writes to output file.

Parameters
timeCurrent time
15 {
16  BL_PROFILE("ERF::sum_integrated_quantities()");
17 
18  if (verbose <= 0)
19  return;
20 
21  int datwidth = 14;
22  int datprecision = 6;
23 
24  // Single level sum
25  Real mass_sl;
26 
27  // Multilevel sums
28  Real mass_ml = 0.0;
29  Real rhth_ml = 0.0;
30  Real scal_ml = 0.0;
31 
32 #if 1
33  mass_sl = volWgtSumMF(0,vars_new[0][Vars::cons],Rho_comp,*mapfac_m[0],true,false);
34  for (int lev = 0; lev <= finest_level; lev++) {
35  mass_ml += volWgtSumMF(lev,vars_new[lev][Vars::cons],Rho_comp,*mapfac_m[lev],true,true);
36  }
37 #else
38  for (int lev = 0; lev <= finest_level; lev++) {
39  MultiFab pert_dens(vars_new[lev][Vars::cons].boxArray(),
40  vars_new[lev][Vars::cons].DistributionMap(),
41  1,0);
42  MultiFab r_hse (base_state[lev], make_alias, 0, 1); // r_0 is first component
43  for ( MFIter mfi(pert_dens,TilingIfNotGPU()); mfi.isValid(); ++mfi)
44  {
45  const Box& bx = mfi.tilebox();
46  const Array4<Real >& pert_dens_arr = pert_dens.array(mfi);
47  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
48  const Array4<Real const>& r0_arr = r_hse.const_array(mfi);
49  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
50  pert_dens_arr(i, j, k, 0) = S_arr(i,j,k,Rho_comp) - r0_arr(i,j,k);
51  });
52  }
53  if (lev == 0) {
54  mass_sl = volWgtSumMF(0,pert_dens,0,*mapfac_m[0],true,false);
55  }
56  mass_ml += volWgtSumMF(lev,pert_dens,0,*mapfac_m[lev],true,true);
57  } // lev
58 #endif
59 
60  Real rhth_sl = volWgtSumMF(0,vars_new[0][Vars::cons], RhoTheta_comp,*mapfac_m[0],true,false);
61  Real scal_sl = volWgtSumMF(0,vars_new[0][Vars::cons],RhoScalar_comp,*mapfac_m[0],true,false);
62 
63  for (int lev = 0; lev <= finest_level; lev++) {
64  rhth_ml += volWgtSumMF(lev,vars_new[lev][Vars::cons], RhoTheta_comp,*mapfac_m[lev],true,true);
65  scal_ml += volWgtSumMF(lev,vars_new[lev][Vars::cons],RhoScalar_comp,*mapfac_m[lev],true,true);
66  }
67 
68  Gpu::HostVector<Real> h_avg_ustar; h_avg_ustar.resize(1);
69  Gpu::HostVector<Real> h_avg_tstar; h_avg_tstar.resize(1);
70  Gpu::HostVector<Real> h_avg_olen; h_avg_olen.resize(1);
71  if ((m_most != nullptr) && (NumDataLogs() > 0)) {
72  Box domain = geom[0].Domain();
73  int zdir = 2;
74  h_avg_ustar = sumToLine(*m_most->get_u_star(0),0,1,domain,zdir);
75  h_avg_tstar = sumToLine(*m_most->get_t_star(0),0,1,domain,zdir);
76  h_avg_olen = sumToLine(*m_most->get_olen(0),0,1,domain,zdir);
77 
78  // Divide by the total number of cells we are averaging over
79  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
80  h_avg_ustar[0] /= area_z;
81  h_avg_tstar[0] /= area_z;
82  h_avg_olen[0] /= area_z;
83 
84  } else {
85  h_avg_ustar[0] = 0.;
86  h_avg_tstar[0] = 0.;
87  h_avg_olen[0] = 0.;
88  }
89 
90  const int nfoo = 6;
91  Real foo[nfoo] = {mass_sl,rhth_sl,scal_sl,mass_ml,rhth_ml,scal_ml};
92 #ifdef AMREX_LAZY
93  Lazy::QueueReduction([=]() mutable {
94 #endif
95  ParallelDescriptor::ReduceRealSum(
96  foo, nfoo, ParallelDescriptor::IOProcessorNumber());
97 
98  if (ParallelDescriptor::IOProcessor()) {
99  int i = 0;
100  mass_sl = foo[i++];
101  rhth_sl = foo[i++];
102  scal_sl = foo[i++];
103  mass_ml = foo[i++];
104  rhth_ml = foo[i++];
105  scal_ml = foo[i++];
106 
107  Print() << '\n';
108  if (finest_level == 0) {
109 #if 1
110  Print() << "TIME= " << time << " MASS = " << mass_sl << '\n';
111 #else
112  Print() << "TIME= " << time << " PERT MASS = " << mass_sl << '\n';
113 #endif
114  Print() << "TIME= " << time << " RHO THETA = " << rhth_sl << '\n';
115  Print() << "TIME= " << time << " RHO SCALAR = " << scal_sl << '\n';
116  } else {
117 #if 1
118  Print() << "TIME= " << time << " MASS SL/ML = " << mass_sl << " " << mass_ml << '\n';
119 #else
120  Print() << "TIME= " << time << " PERT MASS SL/ML = " << mass_sl << " " << mass_ml << '\n';
121 #endif
122  Print() << "TIME= " << time << " RHO THETA SL/ML = " << rhth_sl << " " << rhth_ml << '\n';
123  Print() << "TIME= " << time << " RHO SCALAR SL/ML = " << scal_sl << " " << scal_ml << '\n';
124  }
125 
126  // The first data log only holds scalars
127  if (NumDataLogs() > 0)
128  {
129  int nd = 0;
130  std::ostream& data_log1 = DataLog(nd);
131  if (data_log1.good()) {
132  if (time == 0.0) {
133  data_log1 << std::setw(datwidth) << " time";
134  data_log1 << std::setw(datwidth) << " u_star";
135  data_log1 << std::setw(datwidth) << " t_star";
136  data_log1 << std::setw(datwidth) << " olen";
137  data_log1 << std::endl;
138  } // time = 0
139 
140  // Write the quantities at this time
141  data_log1 << std::setw(datwidth) << time;
142  data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
143  << h_avg_ustar[0];
144  data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
145  << h_avg_tstar[0];
146  data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
147  << h_avg_olen[0];
148  data_log1 << std::endl;
149  } // if good
150  } // loop over i
151  } // if IOProcessor
152 #ifdef AMREX_LAZY
153  });
154 #endif
155 
156  // This is just an alias for convenience
157  int lev = 0;
158  if (NumSamplePointLogs() > 0 && NumSamplePoints() > 0) {
159  for (int i = 0; i < NumSamplePoints(); ++i)
160  {
161  sample_points(lev, time, SamplePoint(i), vars_new[lev][Vars::cons]);
162  }
163  }
164  if (NumSampleLineLogs() > 0 && NumSampleLines() > 0) {
165  for (int i = 0; i < NumSampleLines(); ++i)
166  {
167  sample_lines(lev, time, SampleLine(i), vars_new[lev][Vars::cons]);
168  }
169  }
170 }
AMREX_FORCE_INLINE int NumSampleLineLogs() noexcept
Definition: ERF.H:1035
AMREX_FORCE_INLINE int NumSamplePointLogs() noexcept
Definition: ERF.H:1021
amrex::IntVect & SampleLine(int i)
Definition: ERF.H:1054
AMREX_FORCE_INLINE int NumSamplePoints() noexcept
Definition: ERF.H:1048
AMREX_FORCE_INLINE int NumSampleLines() noexcept
Definition: ERF.H:1061
amrex::IntVect & SamplePoint(int i)
Definition: ERF.H:1041
void sample_points(int lev, amrex::Real time, amrex::IntVect cell, amrex::MultiFab &mf)
Definition: ERF_WriteScalarProfiles.cpp:181
AMREX_FORCE_INLINE std::ostream & DataLog(int i)
Definition: ERF.H:1000
AMREX_FORCE_INLINE int NumDataLogs() noexcept
Definition: ERF.H:1007
amrex::Real volWgtSumMF(int lev, const amrex::MultiFab &mf, int comp, const amrex::MultiFab &mapfac, bool local, bool finemask)
Definition: ERF_WriteScalarProfiles.cpp:310
void sample_lines(int lev, amrex::Real time, amrex::IntVect cell, amrex::MultiFab &mf)
Definition: ERF_WriteScalarProfiles.cpp:219

◆ timeStep()

void ERF::timeStep ( int  lev,
amrex::Real  time,
int  iteration 
)
private

Function that coordinates the evolution across levels – this calls Advance to do the actual advance at this level, then recursively calls itself at finer levels

Parameters
[in]levlevel of refinement (coarsest level is 0)
[in]timestart time for time advance
[in]iterationtime step counter
17 {
18  if (regrid_int > 0) // We may need to regrid
19  {
20  // help keep track of whether a level was already regridded
21  // from a coarser level call to regrid
22  static Vector<int> last_regrid_step(max_level+1, 0);
23 
24  // regrid changes level "lev+1" so we don't regrid on max_level
25  // also make sure we don't regrid fine levels again if
26  // it was taken care of during a coarser regrid
27  if (lev < max_level)
28  {
29  if ( (istep[lev] % regrid_int == 0) && (istep[lev] > last_regrid_step[lev]) )
30  {
31  // regrid could add newly refine levels (if finest_level < max_level)
32  // so we save the previous finest level index
33  int old_finest = finest_level;
34 
35  regrid(lev, time);
36 
37 #ifdef ERF_USE_PARTICLES
38  if (finest_level != old_finest) {
39  particleData.Redistribute();
40  }
41 #endif
42 
43  // mark that we have regridded this level already
44  for (int k = lev; k <= finest_level; ++k) {
45  last_regrid_step[k] = istep[k];
46  }
47 
48  // if there are newly created levels, set the time step
49  for (int k = old_finest+1; k <= finest_level; ++k) {
50  dt[k] = dt[k-1] / MaxRefRatio(k-1);
51  }
52  } // if
53  } // lev
54  }
55 
56  // Update what we call "old" and "new" time
57  t_old[lev] = t_new[lev];
58  t_new[lev] += dt[lev];
59 
60  if (Verbose()) {
61  amrex::Print() << "[Level " << lev << " step " << istep[lev]+1 << "] ";
62  amrex::Print() << "ADVANCE from time = " << t_old[lev] << " to " << t_new[lev]
63  << " with dt = " << dt[lev] << std::endl;
64  }
65 
66  // Advance a single level for a single time step
67  Advance(lev, time, dt[lev], istep[lev], nsubsteps[lev]);
68 
69  ++istep[lev];
70 
71  if (Verbose()) {
72  amrex::Print() << "[Level " << lev << " step " << istep[lev] << "] ";
73  amrex::Print() << "Advanced " << CountCells(lev) << " cells" << std::endl;
74  }
75 
76  if (lev < finest_level)
77  {
78  // recursive call for next-finer level
79  for (int i = 1; i <= nsubsteps[lev+1]; ++i)
80  {
81  Real strt_time_for_fine = time + (i-1)*dt[lev+1];
82  timeStep(lev+1, strt_time_for_fine, i);
83  }
84  }
85 }
void Advance(int lev, amrex::Real time, amrex::Real dt_lev, int iteration, int ncycle)
Definition: ERF_Advance.cpp:21

◆ update_diffusive_arrays()

void ERF::update_diffusive_arrays ( int  lev,
const amrex::BoxArray &  ba,
const amrex::DistributionMapping &  dm 
)
private
256 {
257  // ********************************************************************************************
258  // Diffusive terms
259  // ********************************************************************************************
260  bool l_use_terrain = solverChoice.use_terrain;
261  bool l_use_diff = ( (solverChoice.diffChoice.molec_diff_type != MolecDiffType::None) ||
262  (solverChoice.turbChoice[lev].les_type != LESType::None) ||
263  (solverChoice.turbChoice[lev].pbl_type != PBLType::None) );
264  bool l_use_kturb = ( (solverChoice.turbChoice[lev].les_type != LESType::None) ||
265  (solverChoice.turbChoice[lev].pbl_type != PBLType::None) );
266  bool l_use_ddorf = ( solverChoice.turbChoice[lev].les_type == LESType::Deardorff);
267 
268  BoxArray ba12 = convert(ba, IntVect(1,1,0));
269  BoxArray ba13 = convert(ba, IntVect(1,0,1));
270  BoxArray ba23 = convert(ba, IntVect(0,1,1));
271 
272  if (l_use_diff) {
273  Tau11_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,0) );
274  Tau22_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,0) );
275  Tau33_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,0) );
276  Tau12_lev[lev] = std::make_unique<MultiFab>( ba12, dm, 1, IntVect(1,1,0) );
277  Tau13_lev[lev] = std::make_unique<MultiFab>( ba13, dm, 1, IntVect(1,1,0) );
278  Tau23_lev[lev] = std::make_unique<MultiFab>( ba23, dm, 1, IntVect(1,1,0) );
279  if (l_use_terrain) {
280  Tau21_lev[lev] = std::make_unique<MultiFab>( ba12, dm, 1, IntVect(1,1,0) );
281  Tau31_lev[lev] = std::make_unique<MultiFab>( ba13, dm, 1, IntVect(1,1,0) );
282  Tau32_lev[lev] = std::make_unique<MultiFab>( ba23, dm, 1, IntVect(1,1,0) );
283  } else {
284  Tau21_lev[lev] = nullptr;
285  Tau31_lev[lev] = nullptr;
286  Tau32_lev[lev] = nullptr;
287  }
288  SFS_hfx1_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,0) );
289  SFS_hfx2_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,0) );
290  SFS_hfx3_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,1) );
291  SFS_diss_lev[lev] = std::make_unique<MultiFab>( ba , dm, 1, IntVect(1,1,0) );
292  SFS_hfx1_lev[lev]->setVal(0.);
293  SFS_hfx2_lev[lev]->setVal(0.);
294  SFS_hfx3_lev[lev]->setVal(0.);
295  SFS_diss_lev[lev]->setVal(0.);
296  } else {
297  Tau11_lev[lev] = nullptr; Tau22_lev[lev] = nullptr; Tau33_lev[lev] = nullptr;
298  Tau12_lev[lev] = nullptr; Tau21_lev[lev] = nullptr;
299  Tau13_lev[lev] = nullptr; Tau31_lev[lev] = nullptr;
300  Tau23_lev[lev] = nullptr; Tau32_lev[lev] = nullptr;
301  SFS_hfx1_lev[lev] = nullptr; SFS_hfx2_lev[lev] = nullptr; SFS_hfx3_lev[lev] = nullptr;
302  SFS_diss_lev[lev] = nullptr;
303  }
304 
305  if (l_use_kturb) {
306  eddyDiffs_lev[lev] = std::make_unique<MultiFab>( ba, dm, EddyDiff::NumDiffs, 1 );
307  eddyDiffs_lev[lev]->setVal(0.0);
308  if(l_use_ddorf) {
309  SmnSmn_lev[lev] = std::make_unique<MultiFab>( ba, dm, 1, 0 );
310  } else {
311  SmnSmn_lev[lev] = nullptr;
312  }
313  } else {
314  eddyDiffs_lev[lev] = nullptr;
315  SmnSmn_lev[lev] = nullptr;
316  }
317 }
@ NumDiffs
Definition: IndexDefines.H:134

◆ update_terrain_arrays()

void ERF::update_terrain_arrays ( int  lev,
amrex::Real  time 
)
private
321 {
323 
324  if (lev == 0 && (init_type != "real" && init_type != "metgrid") ) {
325  prob->init_custom_terrain(geom[lev],*z_phys_nd[lev],time);
326  init_terrain_grid(lev,geom[lev],*z_phys_nd[lev],zlevels_stag);
327  }
328 
329  if (lev > 0) {
330  Vector<MultiFab*> fmf = {z_phys_nd[lev].get(), z_phys_nd[lev].get()};
331  Vector<Real> ftime = {t_old[lev], t_new[lev]};
332  Vector<MultiFab*> cmf = {z_phys_nd[lev-1].get(), z_phys_nd[lev-1].get()};
333  Vector<Real> ctime = {t_old[lev-1], t_new[lev-1]};
334 
335  //
336  // First we fill z_phys_nd at lev>0 through interpolation
337  //
338  Interpolater* mapper = &node_bilinear_interp;
339  PhysBCFunctNoOp null_bc;
340  InterpFromCoarseLevel(*z_phys_nd[lev], time, *z_phys_nd[lev-1],
341  0, 0, 1,
342  geom[lev-1], geom[lev],
343  null_bc, 0, null_bc, 0, refRatio(lev-1),
344  mapper, domain_bcs_type, 0);
345 
346  //
347  // Then if not using real/metgrid data, we
348  // 1) redefine the terrain at k=0 for every fine box which includes k=0
349  // 2) recreate z_phys_nd at every fine node using
350  // the data at the bottom of each fine grid
351  // which has been either been interpolated from the coarse grid (k>0)
352  // or set in init_custom_terrain (k=0)
353  //
354  prob->init_custom_terrain(geom[lev],*z_phys_nd[lev],time);
355  if (init_type != "real" && init_type != "metgrid") {
356  init_terrain_grid(lev,geom[lev],*z_phys_nd[lev],zlevels_stag);
357  }
358  }
359 
360  make_J(geom[lev],*z_phys_nd[lev],*detJ_cc[lev]);
361  make_areas(geom[lev],*z_phys_nd[lev],*ax[lev],*ay[lev],*az[lev]);
362 
363  make_zcc(geom[lev],*z_phys_nd[lev],*z_phys_cc[lev]);
364  }
365 }
void make_areas(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &ax, MultiFab &ay, MultiFab &az)
Definition: TerrainMetrics.cpp:491
void make_J(const Geometry &geom, MultiFab &z_phys_nd, MultiFab &detJ_cc)
Definition: TerrainMetrics.cpp:453
void init_terrain_grid(int lev, const Geometry &geom, MultiFab &z_phys_nd, Vector< Real > const &z_levels_h)
Definition: TerrainMetrics.cpp:75
Here is the call graph for this function:

◆ volWgtSumMF()

Real ERF::volWgtSumMF ( int  lev,
const amrex::MultiFab &  mf,
int  comp,
const amrex::MultiFab &  mapfac,
bool  local,
bool  finemask 
)

Utility function for computing a volume weighted sum of MultiFab data for a single component

Parameters
levCurrent level
mfMultiFab on which we do the volume weighted sum
compIndex of the component we want to sum
localBoolean sets whether or not to reduce the sum over the domain (false) or compute sums local to each MPI rank (true)
finemaskIf a finer level is available, determines whether we mask fine data
313 {
314  BL_PROFILE("ERF::volWgtSumMF()");
315 
316  Real sum = 0.0;
317  MultiFab tmp(grids[lev], dmap[lev], 1, 0);
318  MultiFab::Copy(tmp, mf, comp, 0, 1, 0);
319 
320  // The quantity that is conserved is not (rho S), but rather (rho S / m^2) where
321  // m is the map scale factor at cell centers
322  for (MFIter mfi(tmp, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
323  const Box& bx = mfi.tilebox();
324  const Array4< Real> tmp_arr = tmp.array(mfi);
325  const Array4<const Real> mapfac_arr = mapfac.const_array(mfi);
326  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
327  {
328  tmp_arr(i,j,k) /= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
329  });
330  } // mfi
331 
332  if (lev < finest_level && finemask) {
333  const MultiFab& mask = build_fine_mask(lev+1);
334  MultiFab::Multiply(tmp, mask, 0, 0, 1, 0);
335  }
336 
337  MultiFab volume(grids[lev], dmap[lev], 1, 0);
338  auto const& dx = geom[lev].CellSizeArray();
339  Real cell_vol = dx[0]*dx[1]*dx[2];
340  volume.setVal(cell_vol);
342  MultiFab::Multiply(volume, *detJ_cc[lev], 0, 0, 1, 0);
343  sum = MultiFab::Dot(tmp, 0, volume, 0, 1, 0, local);
344 
345  if (!local)
346  ParallelDescriptor::ReduceRealSum(sum);
347 
348  return sum;
349 }
amrex::MultiFab & build_fine_mask(int lev)
Definition: ERF_WriteScalarProfiles.cpp:359

◆ write_1D_profiles()

void ERF::write_1D_profiles ( amrex::Real  time)

Writes 1-dimensional averaged quantities as profiles to output log files at the given time.

Parameters
timeCurrent time
16 {
17  BL_PROFILE("ERF::write_1D_profiles()");
18 
19  if (verbose <= 0)
20  return;
21 
22  int datwidth = 14;
23  int datprecision = 6;
24  int timeprecision = 13; // e.g., 1-yr LES: 31,536,000 s with dt ~ 0.01 ==> min prec = 10
25 
26  if (verbose > 0 && NumDataLogs() > 1)
27  {
28  // Define the 1d arrays we will need
29  Gpu::HostVector<Real> h_avg_u, h_avg_v, h_avg_w;
30  Gpu::HostVector<Real> h_avg_rho, h_avg_th, h_avg_ksgs;
31  Gpu::HostVector<Real> h_avg_qv, h_avg_qc, h_avg_qr, h_avg_wqv, h_avg_wqc, h_avg_wqr;
32  Gpu::HostVector<Real> h_avg_uth, h_avg_vth, h_avg_wth, h_avg_thth;
33  Gpu::HostVector<Real> h_avg_uu, h_avg_uv, h_avg_uw, h_avg_vv, h_avg_vw, h_avg_ww;
34  Gpu::HostVector<Real> h_avg_uiuiu, h_avg_uiuiv, h_avg_uiuiw;
35  Gpu::HostVector<Real> h_avg_p, h_avg_pu, h_avg_pv, h_avg_pw;
36  Gpu::HostVector<Real> h_avg_tau11, h_avg_tau12, h_avg_tau13, h_avg_tau22, h_avg_tau23, h_avg_tau33;
37  Gpu::HostVector<Real> h_avg_sgshfx, h_avg_sgsdiss; // only output tau_{theta,w} and epsilon for now
38 
39  if (NumDataLogs() > 1) {
40  derive_diag_profiles(h_avg_u, h_avg_v, h_avg_w,
41  h_avg_rho, h_avg_th, h_avg_ksgs,
42  h_avg_qv, h_avg_qc, h_avg_qr, h_avg_wqv, h_avg_wqc, h_avg_wqr,
43  h_avg_uu, h_avg_uv, h_avg_uw, h_avg_vv, h_avg_vw, h_avg_ww,
44  h_avg_uth, h_avg_vth, h_avg_wth, h_avg_thth,
45  h_avg_uiuiu, h_avg_uiuiv, h_avg_uiuiw,
46  h_avg_p, h_avg_pu, h_avg_pv, h_avg_pw);
47  }
48 
49  if (NumDataLogs() > 3) {
50  derive_stress_profiles(h_avg_tau11, h_avg_tau12, h_avg_tau13,
51  h_avg_tau22, h_avg_tau23, h_avg_tau33,
52  h_avg_sgshfx,
53  h_avg_sgsdiss);
54  }
55 
56  int hu_size = h_avg_u.size();
57 
58  auto const& dx = geom[0].CellSizeArray();
59  if (ParallelDescriptor::IOProcessor()) {
60  if (NumDataLogs() > 1) {
61  std::ostream& data_log1 = DataLog(1);
62  if (data_log1.good()) {
63  // Write the quantities at this time
64  for (int k = 0; k < hu_size; k++) {
65  Real z = (k + 0.5)* dx[2];
66  data_log1 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
67  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
68  << h_avg_u[k] << " " << h_avg_v[k] << " " << h_avg_w[k] << " "
69  << h_avg_rho[k] << " " << h_avg_th[k] << " " << h_avg_ksgs[k] << " "
70  << h_avg_qv[k] << " " << h_avg_qc[k] << " " << h_avg_qr[k]
71  << std::endl;
72  } // loop over z
73  } // if good
74  } // NumDataLogs
75 
76  if (NumDataLogs() > 2) {
77  std::ostream& data_log2 = DataLog(2);
78  if (data_log2.good()) {
79  // Write the perturbational quantities at this time
80  for (int k = 0; k < hu_size; k++) {
81  Real z = (k + 0.5)* dx[2];
82  data_log2 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
83  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
84  << h_avg_uu[k] - h_avg_u[k]*h_avg_u[k] << " "
85  << h_avg_uv[k] - h_avg_u[k]*h_avg_v[k] << " "
86  << h_avg_uw[k] - h_avg_u[k]*h_avg_w[k] << " "
87  << h_avg_vv[k] - h_avg_v[k]*h_avg_v[k] << " "
88  << h_avg_vw[k] - h_avg_v[k]*h_avg_w[k] << " "
89  << h_avg_ww[k] - h_avg_w[k]*h_avg_w[k] << " "
90  << h_avg_uth[k] - h_avg_u[k]*h_avg_th[k] << " "
91  << h_avg_vth[k] - h_avg_v[k]*h_avg_th[k] << " "
92  << h_avg_wth[k] - h_avg_w[k]*h_avg_th[k] << " "
93  << h_avg_thth[k] - h_avg_th[k]*h_avg_th[k] << " "
94  // Note: <u'_i u'_i u'_j> = <u_i u_i u_j>
95  // - <u_i u_i> * <u_j>
96  // - 2*<u_i> * <u_i u_j>
97  // + 2*<u_i>*<u_i> * <u_j>
98  << h_avg_uiuiu[k]
99  - (h_avg_uu[k] + h_avg_vv[k] + h_avg_ww[k])*h_avg_u[k]
100  - 2*(h_avg_u[k]*h_avg_uu[k] + h_avg_v[k]*h_avg_uv[k] + h_avg_w[k]*h_avg_uw[k])
101  + 2*(h_avg_u[k]*h_avg_u[k] + h_avg_v[k]*h_avg_v[k] + h_avg_w[k]*h_avg_w[k])*h_avg_u[k]
102  << " " // (u'_i u'_i)u'
103  << h_avg_uiuiv[k]
104  - (h_avg_uu[k] + h_avg_vv[k] + h_avg_ww[k])*h_avg_v[k]
105  - 2*(h_avg_u[k]*h_avg_uv[k] + h_avg_v[k]*h_avg_vv[k] + h_avg_w[k]*h_avg_vw[k])
106  + 2*(h_avg_u[k]*h_avg_u[k] + h_avg_v[k]*h_avg_v[k] + h_avg_w[k]*h_avg_w[k])*h_avg_v[k]
107  << " " // (u'_i u'_i)v'
108  << h_avg_uiuiw[k]
109  - (h_avg_uu[k] + h_avg_vv[k] + h_avg_ww[k])*h_avg_w[k]
110  - 2*(h_avg_u[k]*h_avg_uw[k] + h_avg_v[k]*h_avg_vw[k] + h_avg_w[k]*h_avg_ww[k])
111  + 2*(h_avg_u[k]*h_avg_u[k] + h_avg_v[k]*h_avg_v[k] + h_avg_w[k]*h_avg_w[k])*h_avg_w[k]
112  << " " // (u'_i u'_i)w'
113  << h_avg_pu[k] - h_avg_p[k]*h_avg_u[k] << " "
114  << h_avg_pv[k] - h_avg_p[k]*h_avg_v[k] << " "
115  << h_avg_pw[k] - h_avg_p[k]*h_avg_w[k] << " "
116  << h_avg_wqv[k] - h_avg_qv[k]*h_avg_w[k] << " "
117  << h_avg_wqc[k] - h_avg_qc[k]*h_avg_w[k] << " "
118  << h_avg_wqr[k] - h_avg_qr[k]*h_avg_w[k]
119  << std::endl;
120  } // loop over z
121  } // if good
122  } // NumDataLogs
123 
124  if (NumDataLogs() > 3) {
125  std::ostream& data_log3 = DataLog(3);
126  if (data_log3.good()) {
127  // Write the average stresses
128  for (int k = 0; k < hu_size; k++) {
129  Real z = (k + 0.5)* dx[2];
130  data_log3 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
131  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
132  << h_avg_tau11[k] << " " << h_avg_tau12[k] << " " << h_avg_tau13[k] << " "
133  << h_avg_tau22[k] << " " << h_avg_tau23[k] << " " << h_avg_tau33[k] << " "
134  << h_avg_sgshfx[k] << " " << h_avg_sgsdiss[k]
135  << std::endl;
136  } // loop over z
137  } // if good
138  } // NumDataLogs
139  } // if IOProcessor
140  } // if verbose
141 }
void derive_stress_profiles(amrex::Gpu::HostVector< amrex::Real > &h_avg_tau11, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau12, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau13, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau22, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau23, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau33, amrex::Gpu::HostVector< amrex::Real > &h_avg_hfx3, amrex::Gpu::HostVector< amrex::Real > &h_avg_diss)
Definition: ERF_Write1DProfiles.cpp:363
void derive_diag_profiles(amrex::Gpu::HostVector< amrex::Real > &h_avg_u, amrex::Gpu::HostVector< amrex::Real > &h_avg_v, amrex::Gpu::HostVector< amrex::Real > &h_avg_w, amrex::Gpu::HostVector< amrex::Real > &h_avg_rho, amrex::Gpu::HostVector< amrex::Real > &h_avg_th, amrex::Gpu::HostVector< amrex::Real > &h_avg_ksgs, amrex::Gpu::HostVector< amrex::Real > &h_avg_qv, amrex::Gpu::HostVector< amrex::Real > &h_avg_qc, amrex::Gpu::HostVector< amrex::Real > &h_avg_qr, amrex::Gpu::HostVector< amrex::Real > &h_avg_wqv, amrex::Gpu::HostVector< amrex::Real > &h_avg_wqc, amrex::Gpu::HostVector< amrex::Real > &h_avg_wqr, amrex::Gpu::HostVector< amrex::Real > &h_avg_uu, amrex::Gpu::HostVector< amrex::Real > &h_avg_uv, amrex::Gpu::HostVector< amrex::Real > &h_avg_uw, amrex::Gpu::HostVector< amrex::Real > &h_avg_vv, amrex::Gpu::HostVector< amrex::Real > &h_avg_vw, amrex::Gpu::HostVector< amrex::Real > &h_avg_ww, amrex::Gpu::HostVector< amrex::Real > &h_avg_uth, amrex::Gpu::HostVector< amrex::Real > &h_avg_vth, amrex::Gpu::HostVector< amrex::Real > &h_avg_wth, amrex::Gpu::HostVector< amrex::Real > &h_avg_thth, amrex::Gpu::HostVector< amrex::Real > &h_avg_ku, amrex::Gpu::HostVector< amrex::Real > &h_avg_kv, amrex::Gpu::HostVector< amrex::Real > &h_avg_kw, amrex::Gpu::HostVector< amrex::Real > &h_avg_p, amrex::Gpu::HostVector< amrex::Real > &h_avg_pu, amrex::Gpu::HostVector< amrex::Real > &h_avg_pv, amrex::Gpu::HostVector< amrex::Real > &h_avg_pw)
Definition: ERF_Write1DProfiles.cpp:169

◆ write_1D_profiles_stag()

void ERF::write_1D_profiles_stag ( amrex::Real  time)

Writes 1-dimensional averaged quantities as profiles to output log files at the given time. Quantities are output at their native grid locations, therefore W and associated quantities <(*)'w'>, tau13, and tau23 (where * includes u, v, p, theta, and k) will be output at staggered heights (i.e., z faces) rather than cell-center heights to avoid performing additional averaging. The unstaggered quantities are associated with the left cell face, i.e., they share the same k index. These quantities will have a zero value at the max height of Nz+1.

Parameters
timeCurrent time
22 {
23  BL_PROFILE("ERF::write_1D_profiles()");
24 
25  if (verbose <= 0)
26  return;
27 
28  int datwidth = 14;
29  int datprecision = 6;
30  int timeprecision = 13; // e.g., 1-yr LES: 31,536,000 s with dt ~ 0.01 ==> min prec = 10
31 
32  if (verbose > 0 && NumDataLogs() > 1)
33  {
34  // Define the 1d arrays we will need
35  Gpu::HostVector<Real> h_avg_u, h_avg_v, h_avg_w;
36  Gpu::HostVector<Real> h_avg_rho, h_avg_th, h_avg_ksgs;
37  Gpu::HostVector<Real> h_avg_uth, h_avg_vth, h_avg_wth, h_avg_thth;
38  Gpu::HostVector<Real> h_avg_uu, h_avg_uv, h_avg_uw, h_avg_vv, h_avg_vw, h_avg_ww;
39  Gpu::HostVector<Real> h_avg_uiuiu, h_avg_uiuiv, h_avg_uiuiw;
40  Gpu::HostVector<Real> h_avg_p, h_avg_pu, h_avg_pv, h_avg_pw;
41  Gpu::HostVector<Real> h_avg_tau11, h_avg_tau12, h_avg_tau13, h_avg_tau22, h_avg_tau23, h_avg_tau33;
42  Gpu::HostVector<Real> h_avg_sgshfx, h_avg_sgsdiss; // only output tau_{theta,w} and epsilon for now
43 
44  if (NumDataLogs() > 1) {
45  derive_diag_profiles_stag(h_avg_u, h_avg_v, h_avg_w,
46  h_avg_rho, h_avg_th, h_avg_ksgs,
47  h_avg_uu, h_avg_uv, h_avg_uw, h_avg_vv, h_avg_vw, h_avg_ww,
48  h_avg_uth, h_avg_vth, h_avg_wth, h_avg_thth,
49  h_avg_uiuiu, h_avg_uiuiv, h_avg_uiuiw,
50  h_avg_p, h_avg_pu, h_avg_pv, h_avg_pw);
51  }
52 
53  if (NumDataLogs() > 3) {
54  derive_stress_profiles_stag(h_avg_tau11, h_avg_tau12, h_avg_tau13,
55  h_avg_tau22, h_avg_tau23, h_avg_tau33,
56  h_avg_sgshfx,
57  h_avg_sgsdiss);
58  }
59 
60  int unstag_size = h_avg_w.size() - 1; // _un_staggered heights
61 
62  auto const& dx = geom[0].CellSizeArray();
63  if (ParallelDescriptor::IOProcessor()) {
64  if (NumDataLogs() > 1) {
65  std::ostream& data_log1 = DataLog(1);
66  if (data_log1.good()) {
67  // Write the quantities at this time
68  for (int k = 0; k < unstag_size; k++) {
69  Real z = k * dx[2];
70  data_log1 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
71  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
72  << h_avg_u[k] << " " << h_avg_v[k] << " " << h_avg_w[k] << " "
73  << h_avg_rho[k] << " " << h_avg_th[k] << " " << h_avg_ksgs[k]
74  << std::endl;
75  } // loop over z
76  // Write top face values
77  data_log1 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
78  << std::setw(datwidth) << std::setprecision(datprecision) << unstag_size * dx[2] << " "
79  << 0 << " " << 0 << " " << h_avg_w[unstag_size+1] << " "
80  << 0 << " " << 0 << " " << 0
81  << std::endl;
82  } // if good
83  } // NumDataLogs
84 
85  if (NumDataLogs() > 2) {
86  std::ostream& data_log2 = DataLog(2);
87  if (data_log2.good()) {
88  // Write the perturbational quantities at this time
89  // For surface values (k=0), assume w = uw = vw = ww = 0
90  Real w_cc = h_avg_w[1] / 2; // w at first cell center
91  Real uw_cc = h_avg_uw[1] / 2; // u*w at first cell center
92  Real vw_cc = h_avg_vw[1] / 2; // v*w at first cell center
93  Real ww_cc = h_avg_ww[1] / 2; // w*w at first cell center
94  data_log2 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
95  << std::setw(datwidth) << std::setprecision(datprecision) << 0 << " "
96  << h_avg_uu[0] - h_avg_u[0]*h_avg_u[0] << " " // u'u'
97  << h_avg_uv[0] - h_avg_u[0]*h_avg_v[0] << " " // u'v'
98  << 0 << " " // u'w'
99  << h_avg_vv[0] - h_avg_v[0]*h_avg_v[0] << " " // v'v'
100  << 0 << " " // v'w'
101  << 0 << " " // w'w'
102  << h_avg_uth[0] - h_avg_u[0]*h_avg_th[0] << " " // u'th'
103  << h_avg_vth[0] - h_avg_v[0]*h_avg_th[0] << " " // v'th'
104  << 0 << " " // w'th'
105  << h_avg_thth[0] - h_avg_th[0]*h_avg_th[0] << " " // th'th'
106  << h_avg_uiuiu[0]
107  - (h_avg_uu[0] + h_avg_vv[0] + ww_cc)*h_avg_u[0]
108  - 2*(h_avg_u[0]*h_avg_uu[0] + h_avg_v[0]*h_avg_uv[0] + w_cc*uw_cc)
109  + 2*(h_avg_u[0]*h_avg_u[0] + h_avg_v[0]*h_avg_v[0] + w_cc*w_cc)*h_avg_u[0]
110  << " " // (u'_i u'_i)u'
111  << h_avg_uiuiv[0]
112  - (h_avg_uu[0] + h_avg_vv[0] + ww_cc)*h_avg_v[0]
113  - 2*(h_avg_u[0]*h_avg_uv[0] + h_avg_v[0]*h_avg_vv[0] + w_cc*vw_cc)
114  + 2*(h_avg_u[0]*h_avg_u[0] + h_avg_v[0]*h_avg_v[0] + w_cc*w_cc)*h_avg_v[0]
115  << " " // (u'_i u'_i)v'
116  << 0 << " " // (u'_i u'_i)w'
117  << h_avg_pu[0] - h_avg_p[0]*h_avg_u[0] << " " // pu'
118  << h_avg_pv[0] - h_avg_p[0]*h_avg_v[0] << " " // pv'
119  << 0 // pw'
120  << std::endl;
121 
122  // For internal values, interpolate scalar quantities to faces
123  for (int k = 1; k < unstag_size; k++) {
124  Real z = k * dx[2];
125  Real uface = 0.5*(h_avg_u[k] + h_avg_u[k-1]);
126  Real vface = 0.5*(h_avg_v[k] + h_avg_v[k-1]);
127  Real thface = 0.5*(h_avg_th[k] + h_avg_th[k-1]);
128  Real pface = 0.5*(h_avg_p[k] + h_avg_p[k-1]);
129  Real uuface = 0.5*(h_avg_uu[k] + h_avg_uu[k-1]);
130  Real uvface = 0.5*(h_avg_uv[k] + h_avg_uv[k-1]);
131  Real vvface = 0.5*(h_avg_vv[k] + h_avg_vv[k-1]);
132  w_cc = 0.5*(h_avg_w[k-1] + h_avg_w[k]);
133  uw_cc = 0.5*(h_avg_uw[k-1] + h_avg_uw[k]);
134  vw_cc = 0.5*(h_avg_vw[k-1] + h_avg_vw[k]);
135  ww_cc = 0.5*(h_avg_ww[k-1] + h_avg_ww[k]);
136  amrex::ignore_unused(uvface);
137  data_log2 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
138  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
139  << h_avg_uu[k] - h_avg_u[k]*h_avg_u[k] << " " // u'u'
140  << h_avg_uv[k] - h_avg_u[k]*h_avg_v[k] << " " // u'v'
141  << h_avg_uw[k] - uface*h_avg_w[k] << " " // u'w'
142  << h_avg_vv[k] - h_avg_v[k]*h_avg_v[k] << " " // v'v'
143  << h_avg_vw[k] - vface*h_avg_w[k] << " " // v'w'
144  << h_avg_ww[k] - h_avg_w[k]*h_avg_w[k] << " " // w'w'
145  << h_avg_uth[k] - h_avg_u[k]*h_avg_th[k] << " " // u'th'
146  << h_avg_vth[k] - h_avg_v[k]*h_avg_th[k] << " " // v'th'
147  << h_avg_wth[k] - h_avg_w[k]*thface << " " // w'th'
148  << h_avg_thth[k] - h_avg_th[k]*h_avg_th[k] << " " // th'th'
149  // Note: <u'_i u'_i u'_j> = <u_i u_i u_j>
150  // - <u_i u_i> * <u_j>
151  // - 2*<u_i> * <u_i u_j>
152  // + 2*<u_i>*<u_i> * <u_j>
153  << h_avg_uiuiu[k]
154  - (h_avg_uu[k] + h_avg_vv[k] + ww_cc)*h_avg_u[k]
155  - 2*(h_avg_u[k]*h_avg_uu[k] + h_avg_v[k]*h_avg_uv[k] + w_cc*uw_cc)
156  + 2*(h_avg_u[k]*h_avg_u[k] + h_avg_v[k]*h_avg_v[k] + w_cc*w_cc)*h_avg_u[k]
157  << " " // cell-centered (u'_i u'_i)u'
158  << h_avg_uiuiv[k]
159  - (h_avg_uu[k] + h_avg_vv[k] + ww_cc)*h_avg_v[k]
160  - 2*(h_avg_u[k]*h_avg_uv[k] + h_avg_v[k]*h_avg_vv[k] + w_cc*vw_cc)
161  + 2*(h_avg_u[k]*h_avg_u[k] + h_avg_v[k]*h_avg_v[k] + w_cc*w_cc)*h_avg_v[k]
162  << " " // cell-centered (u'_i u'_i)v'
163  << h_avg_uiuiw[k]
164  - (uuface + vvface + h_avg_ww[k])*h_avg_w[k]
165  - 2*(uface*h_avg_uw[k] + vface*h_avg_vw[k] + h_avg_w[k]*h_avg_ww[k])
166  + 2*(uface*uface + vface*vface + h_avg_w[k]*h_avg_w[k])*h_avg_w[k]
167  << " " // face-centered (u'_i u'_i)w'
168  << h_avg_pu[k] - h_avg_p[k]*h_avg_u[k] << " " // pu'
169  << h_avg_pv[k] - h_avg_p[k]*h_avg_v[k] << " " // pv'
170  << h_avg_pw[k] - pface*h_avg_w[k] // pw'
171  << std::endl;
172  } // loop over z
173 
174  // Write top face values, extrapolating scalar quantities
175  const int k = unstag_size;
176  Real uface = 1.5*h_avg_u[k-1] - 0.5*h_avg_u[k-2];
177  Real vface = 1.5*h_avg_v[k-1] - 0.5*h_avg_v[k-2];
178  Real thface = 1.5*h_avg_th[k-1] - 0.5*h_avg_th[k-2];
179  Real pface = 1.5*h_avg_p[k-1] - 0.5*h_avg_p[k-2];
180  Real uuface = 1.5*h_avg_uu[k-1] - 0.5*h_avg_uu[k-2];
181  Real uvface = 1.5*h_avg_uv[k-1] - 0.5*h_avg_uv[k-2];
182  Real vvface = 1.5*h_avg_vv[k-1] - 0.5*h_avg_vv[k-2];
183  amrex::ignore_unused(uvface);
184  data_log2 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
185  << std::setw(datwidth) << std::setprecision(datprecision) << k * dx[2] << " "
186  << 0 << " " // u'u'
187  << 0 << " " // u'v'
188  << h_avg_uw[k] - uface*h_avg_w[k] << " " // u'w'
189  << 0 << " " // v'v'
190  << h_avg_vw[k] - vface*h_avg_w[k] << " " // v'w'
191  << h_avg_ww[k] - h_avg_w[k]*h_avg_w[k] << " " // w'w'
192  << 0 << " " // u'th'
193  << 0 << " " // v'th'
194  << h_avg_wth[k] - thface*h_avg_w[k] << " " // w'th'
195  << 0 << " " // th'th'
196  << 0 << " " // (u'_i u'_i)u'
197  << 0 << " " // (u'_i u'_i)v'
198  << h_avg_uiuiw[k]
199  - (uuface + vvface + h_avg_ww[k])*h_avg_w[k]
200  - 2*(uface*h_avg_uw[k] + vface*h_avg_vw[k] + h_avg_w[k]*h_avg_ww[k])
201  + 2*(uface*uface + vface*vface + h_avg_w[k]*h_avg_w[k])*h_avg_w[k]
202  << " " // (u'_i u'_i)w'
203  << 0 << " " // pu'
204  << 0 << " " // pv'
205  << h_avg_pw[k] - pface*h_avg_w[k] // pw'
206  << std::endl;
207  } // if good
208  } // NumDataLogs
209 
210  if (NumDataLogs() > 3) {
211  std::ostream& data_log3 = DataLog(3);
212  if (data_log3.good()) {
213  // Write the average stresses
214  for (int k = 0; k < unstag_size; k++) {
215  Real z = k * dx[2];
216  data_log3 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
217  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
218  << h_avg_tau11[k] << " " << h_avg_tau12[k] << " " << h_avg_tau13[k] << " "
219  << h_avg_tau22[k] << " " << h_avg_tau23[k] << " " << h_avg_tau33[k] << " "
220  << h_avg_sgshfx[k] << " " << h_avg_sgsdiss[k]
221  << std::endl;
222  } // loop over z
223  // Write top face values
224  data_log3 << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
225  << std::setw(datwidth) << std::setprecision(datprecision) << unstag_size * dx[2] << " "
226  << 0 << " " << 0 << " " << h_avg_tau13[unstag_size] << " "
227  << 0 << " " << h_avg_tau23[unstag_size] << " " << 0 << " "
228  << 0 << " " << 0
229  << std::endl;
230  } // if good
231  } // NumDataLogs
232  } // if IOProcessor
233  } // if verbose
234 }
void derive_diag_profiles_stag(amrex::Gpu::HostVector< amrex::Real > &h_avg_u, amrex::Gpu::HostVector< amrex::Real > &h_avg_v, amrex::Gpu::HostVector< amrex::Real > &h_avg_w, amrex::Gpu::HostVector< amrex::Real > &h_avg_rho, amrex::Gpu::HostVector< amrex::Real > &h_avg_th, amrex::Gpu::HostVector< amrex::Real > &h_avg_ksgs, amrex::Gpu::HostVector< amrex::Real > &h_avg_uu, amrex::Gpu::HostVector< amrex::Real > &h_avg_uv, amrex::Gpu::HostVector< amrex::Real > &h_avg_uw, amrex::Gpu::HostVector< amrex::Real > &h_avg_vv, amrex::Gpu::HostVector< amrex::Real > &h_avg_vw, amrex::Gpu::HostVector< amrex::Real > &h_avg_ww, amrex::Gpu::HostVector< amrex::Real > &h_avg_uth, amrex::Gpu::HostVector< amrex::Real > &h_avg_vth, amrex::Gpu::HostVector< amrex::Real > &h_avg_wth, amrex::Gpu::HostVector< amrex::Real > &h_avg_thth, amrex::Gpu::HostVector< amrex::Real > &h_avg_ku, amrex::Gpu::HostVector< amrex::Real > &h_avg_kv, amrex::Gpu::HostVector< amrex::Real > &h_avg_kw, amrex::Gpu::HostVector< amrex::Real > &h_avg_p, amrex::Gpu::HostVector< amrex::Real > &h_avg_pu, amrex::Gpu::HostVector< amrex::Real > &h_avg_pv, amrex::Gpu::HostVector< amrex::Real > &h_avg_pw)
Definition: ERF_Write1DProfiles_stag.cpp:261
void derive_stress_profiles_stag(amrex::Gpu::HostVector< amrex::Real > &h_avg_tau11, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau12, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau13, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau22, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau23, amrex::Gpu::HostVector< amrex::Real > &h_avg_tau33, amrex::Gpu::HostVector< amrex::Real > &h_avg_hfx3, amrex::Gpu::HostVector< amrex::Real > &h_avg_diss)
Definition: ERF_Write1DProfiles_stag.cpp:474

◆ writeBuildInfo()

void ERF::writeBuildInfo ( std::ostream &  os)
static
138 {
139  std::string PrettyLine = std::string(78, '=') + "\n";
140  std::string OtherLine = std::string(78, '-') + "\n";
141  std::string SkipSpace = std::string(8, ' ');
142 
143  // build information
144  os << PrettyLine;
145  os << " ERF Build Information\n";
146  os << PrettyLine;
147 
148  os << "build date: " << buildInfoGetBuildDate() << "\n";
149  os << "build machine: " << buildInfoGetBuildMachine() << "\n";
150  os << "build dir: " << buildInfoGetBuildDir() << "\n";
151  os << "AMReX dir: " << buildInfoGetAMReXDir() << "\n";
152 
153  os << "\n";
154 
155  os << "COMP: " << buildInfoGetComp() << "\n";
156  os << "COMP version: " << buildInfoGetCompVersion() << "\n";
157 
158  os << "C++ compiler: " << buildInfoGetCXXName() << "\n";
159  os << "C++ flags: " << buildInfoGetCXXFlags() << "\n";
160 
161  os << "\n";
162 
163  os << "Link flags: " << buildInfoGetLinkFlags() << "\n";
164  os << "Libraries: " << buildInfoGetLibraries() << "\n";
165 
166  os << "\n";
167 
168  for (int n = 1; n <= buildInfoGetNumModules(); n++) {
169  os << buildInfoGetModuleName(n) << ": "
170  << buildInfoGetModuleVal(n) << "\n";
171  }
172 
173  os << "\n";
174  const char* githash1 = buildInfoGetGitHash(1);
175  const char* githash2 = buildInfoGetGitHash(2);
176  if (strlen(githash1) > 0) {
177  os << "ERF git hash: " << githash1 << "\n";
178  }
179  if (strlen(githash2) > 0) {
180  os << "AMReX git hash: " << githash2 << "\n";
181  }
182 
183  const char* buildgithash = buildInfoGetBuildGitHash();
184  const char* buildgitname = buildInfoGetBuildGitName();
185  if (strlen(buildgithash) > 0) {
186  os << buildgitname << " git hash: " << buildgithash << "\n";
187  }
188 
189  os << "\n";
190  os << " ERF Compile time variables: \n";
191 
192  os << "\n";
193  os << " ERF Defines: \n";
194 #ifdef _OPENMP
195  os << std::setw(35) << std::left << "_OPENMP " << std::setw(6) << "ON"
196  << std::endl;
197 #else
198  os << std::setw(35) << std::left << "_OPENMP " << std::setw(6) << "OFF"
199  << std::endl;
200 #endif
201 
202 #ifdef MPI_VERSION
203  os << std::setw(35) << std::left << "MPI_VERSION " << std::setw(6)
204  << MPI_VERSION << std::endl;
205 #else
206  os << std::setw(35) << std::left << "MPI_VERSION " << std::setw(6)
207  << "UNDEFINED" << std::endl;
208 #endif
209 
210 #ifdef MPI_SUBVERSION
211  os << std::setw(35) << std::left << "MPI_SUBVERSION " << std::setw(6)
212  << MPI_SUBVERSION << std::endl;
213 #else
214  os << std::setw(35) << std::left << "MPI_SUBVERSION " << std::setw(6)
215  << "UNDEFINED" << std::endl;
216 #endif
217 
218  os << "\n\n";
219 }

Referenced by main().

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

◆ WriteCheckpointFile()

void ERF::WriteCheckpointFile ( ) const
private

ERF function for writing a checkpoint file.

24 {
25  // chk00010 write a checkpoint file with this root directory
26  // chk00010/Header this contains information you need to save (e.g., finest_level, t_new, etc.) and also
27  // the BoxArrays at each level
28  // chk00010/Level_0/
29  // chk00010/Level_1/
30  // etc. these subdirectories will hold the MultiFab data at each level of refinement
31 
32  // checkpoint file name, e.g., chk00010
33  const std::string& checkpointname = Concatenate(check_file,istep[0],5);
34 
35  Print() << "Writing native checkpoint " << checkpointname << "\n";
36 
37  const int nlevels = finest_level+1;
38 
39  // ---- prebuild a hierarchy of directories
40  // ---- dirName is built first. if dirName exists, it is renamed. then build
41  // ---- dirName/subDirPrefix_0 .. dirName/subDirPrefix_nlevels-1
42  // ---- if callBarrier is true, call ParallelDescriptor::Barrier()
43  // ---- after all directories are built
44  // ---- ParallelDescriptor::IOProcessor() creates the directories
45  PreBuildDirectorHierarchy(checkpointname, "Level_", nlevels, true);
46 
47  int ncomp_cons = vars_new[0][Vars::cons].nComp();
48 
49  // write Header file
50  if (ParallelDescriptor::IOProcessor()) {
51 
52  std::string HeaderFileName(checkpointname + "/Header");
53  VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size);
54  std::ofstream HeaderFile;
55  HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size());
56  HeaderFile.open(HeaderFileName.c_str(), std::ofstream::out |
57  std::ofstream::trunc |
58  std::ofstream::binary);
59  if( ! HeaderFile.good()) {
60  FileOpenFailed(HeaderFileName);
61  }
62 
63  HeaderFile.precision(17);
64 
65  // write out title line
66  HeaderFile << "Checkpoint file for ERF\n";
67 
68  // write out finest_level
69  HeaderFile << finest_level << "\n";
70 
71  // write the number of components
72  // for each variable we store
73 
74  // conservative, cell-centered vars
75  HeaderFile << ncomp_cons << "\n";
76 
77  // x-velocity on faces
78  HeaderFile << 1 << "\n";
79 
80  // y-velocity on faces
81  HeaderFile << 1 << "\n";
82 
83  // z-velocity on faces
84  HeaderFile << 1 << "\n";
85 
86  // write out array of istep
87  for (int i = 0; i < istep.size(); ++i) {
88  HeaderFile << istep[i] << " ";
89  }
90  HeaderFile << "\n";
91 
92  // write out array of dt
93  for (int i = 0; i < dt.size(); ++i) {
94  HeaderFile << dt[i] << " ";
95  }
96  HeaderFile << "\n";
97 
98  // write out array of t_new
99  for (int i = 0; i < t_new.size(); ++i) {
100  HeaderFile << t_new[i] << " ";
101  }
102  HeaderFile << "\n";
103 
104  // write the BoxArray at each level
105  for (int lev = 0; lev <= finest_level; ++lev) {
106  boxArray(lev).writeOn(HeaderFile);
107  HeaderFile << '\n';
108  }
109  }
110 
111  // write the MultiFab data to, e.g., chk00010/Level_0/
112  // Here we make copies of the MultiFab with no ghost cells
113  for (int lev = 0; lev <= finest_level; ++lev)
114  {
115  MultiFab cons(grids[lev],dmap[lev],ncomp_cons,0);
116  MultiFab::Copy(cons,vars_new[lev][Vars::cons],0,0,ncomp_cons,0);
117  VisMF::Write(cons, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "Cell"));
118 
119  MultiFab xvel(convert(grids[lev],IntVect(1,0,0)),dmap[lev],1,0);
120  MultiFab::Copy(xvel,vars_new[lev][Vars::xvel],0,0,1,0);
121  VisMF::Write(xvel, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "XFace"));
122 
123  MultiFab yvel(convert(grids[lev],IntVect(0,1,0)),dmap[lev],1,0);
124  MultiFab::Copy(yvel,vars_new[lev][Vars::yvel],0,0,1,0);
125  VisMF::Write(yvel, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "YFace"));
126 
127  MultiFab zvel(convert(grids[lev],IntVect(0,0,1)),dmap[lev],1,0);
128  MultiFab::Copy(zvel,vars_new[lev][Vars::zvel],0,0,1,0);
129  VisMF::Write(zvel, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "ZFace"));
130 
131  // Note that we write the ghost cells of the base state (unlike above)
132  IntVect ng = base_state[lev].nGrowVect();
133  MultiFab base(grids[lev],dmap[lev],base_state[lev].nComp(),ng);
134  MultiFab::Copy(base,base_state[lev],0,0,base.nComp(),ng);
135  VisMF::Write(base, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "BaseState"));
136 
138  // Note that we also write the ghost cells of z_phys_nd
139  ng = z_phys_nd[lev]->nGrowVect();
140  MultiFab z_height(convert(grids[lev],IntVect(1,1,1)),dmap[lev],1,ng);
141  MultiFab::Copy(z_height,*z_phys_nd[lev],0,0,1,ng);
142  VisMF::Write(z_height, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "Z_Phys_nd"));
143  }
144 
145  // We must read and write qmoist with ghost cells because we don't directly impose BCs on these vars
146  // Write the precipitation accumulation component only
148  ng = qmoist[lev][4]->nGrowVect();
149  int nvar = 1;
150  MultiFab moist_vars(grids[lev],dmap[lev],nvar,ng);
151  MultiFab::Copy(moist_vars,*(qmoist[lev][4]),0,0,nvar,ng);
152  VisMF::Write(moist_vars, amrex::MultiFabFileFullPrefix(lev, checkpointname, "Level_", "RainAccum"));
153  }
154 
156  ng = qmoist[lev][8]->nGrowVect();
157  int nvar = 1;
158  MultiFab rain_accum(grids[lev],dmap[lev],nvar,ng);
159  MultiFab::Copy(rain_accum,*(qmoist[lev][8]),0,0,nvar,ng);
160  VisMF::Write(rain_accum, amrex::MultiFabFileFullPrefix(lev, checkpointname, "Level_", "RainAccum"));
161 
162  ng = qmoist[lev][9]->nGrowVect();
163  MultiFab snow_accum(grids[lev],dmap[lev],nvar,ng);
164  MultiFab::Copy(snow_accum,*(qmoist[lev][9]),0,0,nvar,ng);
165  VisMF::Write(snow_accum, amrex::MultiFabFileFullPrefix(lev, checkpointname, "Level_", "SnowAccum"));
166 
167  ng = qmoist[lev][10]->nGrowVect();
168  MultiFab graup_accum(grids[lev],dmap[lev],nvar,ng);
169  MultiFab::Copy(graup_accum,*(qmoist[lev][10]),0,0,nvar,ng);
170  VisMF::Write(graup_accum, amrex::MultiFabFileFullPrefix(lev, checkpointname, "Level_", "GraupAccum"));
171  }
172 
173 
174 #if defined(ERF_USE_WINDFARM)
176  ng = Nturb[lev].nGrowVect();
177  MultiFab mf_Nturb(grids[lev],dmap[lev],1,ng);
178  MultiFab::Copy(mf_Nturb,Nturb[lev],0,0,1,ng);
179  VisMF::Write(mf_Nturb, amrex::MultiFabFileFullPrefix(lev, checkpointname, "Level_", "NumTurb"));
180  }
181 #endif
182 
183 
185  for (int mvar(0); mvar<lsm_data[lev].size(); ++mvar) {
186  BoxArray ba = lsm_data[lev][mvar]->boxArray();
187  DistributionMapping dm = lsm_data[lev][mvar]->DistributionMap();
188  ng = lsm_data[lev][mvar]->nGrowVect();
189  int nvar = lsm_data[lev][mvar]->nComp();
190  MultiFab lsm_vars(ba,dm,nvar,ng);
191  MultiFab::Copy(lsm_vars,*(lsm_data[lev][mvar]),0,0,nvar,ng);
192  VisMF::Write(lsm_vars, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "LsmVars"));
193  }
194  }
195 
196  // Note that we also write the ghost cells of the mapfactors (2D)
197  BoxList bl2d = grids[lev].boxList();
198  for (auto& b : bl2d) {
199  b.setRange(2,0);
200  }
201  BoxArray ba2d(std::move(bl2d));
202 
203  ng = mapfac_m[lev]->nGrowVect();
204  MultiFab mf_m(ba2d,dmap[lev],1,ng);
205  MultiFab::Copy(mf_m,*mapfac_m[lev],0,0,1,ng);
206  VisMF::Write(mf_m, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "MapFactor_m"));
207 
208  ng = mapfac_u[lev]->nGrowVect();
209  MultiFab mf_u(convert(ba2d,IntVect(1,0,0)),dmap[lev],1,ng);
210  MultiFab::Copy(mf_u,*mapfac_u[lev],0,0,1,ng);
211  VisMF::Write(mf_u, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "MapFactor_u"));
212 
213  ng = mapfac_v[lev]->nGrowVect();
214  MultiFab mf_v(convert(ba2d,IntVect(0,1,0)),dmap[lev],1,ng);
215  MultiFab::Copy(mf_v,*mapfac_v[lev],0,0,1,ng);
216  VisMF::Write(mf_v, MultiFabFileFullPrefix(lev, checkpointname, "Level_", "MapFactor_v"));
217  }
218 
219 #ifdef ERF_USE_PARTICLES
220  particleData.Checkpoint(checkpointname);
221 #endif
222 
223 #ifdef ERF_USE_NETCDF
224  // Write bdy_data files
225  if (ParallelDescriptor::IOProcessor() && ((init_type=="real") || (init_type=="metgrid"))) {
226 
227  // Vector dimensions
228  int num_time = bdy_data_xlo.size();
229  int num_var = bdy_data_xlo[0].size();
230 
231  // Open header file and write to it
232  std::ofstream bdy_h_file(MultiFabFileFullPrefix(0, checkpointname, "Level_", "bdy_H"));
233  bdy_h_file << std::setprecision(1) << std::fixed;
234  bdy_h_file << num_time << "\n";
235  bdy_h_file << num_var << "\n";
236  bdy_h_file << start_bdy_time << "\n";
237  bdy_h_file << bdy_time_interval << "\n";
238  bdy_h_file << real_width << "\n";
239  for (int ivar(0); ivar<num_var; ++ivar) {
240  bdy_h_file << bdy_data_xlo[0][ivar].box() << "\n";
241  bdy_h_file << bdy_data_xhi[0][ivar].box() << "\n";
242  bdy_h_file << bdy_data_ylo[0][ivar].box() << "\n";
243  bdy_h_file << bdy_data_yhi[0][ivar].box() << "\n";
244  }
245 
246  // Open data file and write to it
247  std::ofstream bdy_d_file(MultiFabFileFullPrefix(0, checkpointname, "Level_", "bdy_D"));
248  for (int itime(0); itime<num_time; ++itime) {
249  for (int ivar(0); ivar<num_var; ++ivar) {
250  bdy_data_xlo[itime][ivar].writeOn(bdy_d_file,0,1);
251  bdy_data_xhi[itime][ivar].writeOn(bdy_d_file,0,1);
252  bdy_data_ylo[itime][ivar].writeOn(bdy_d_file,0,1);
253  bdy_data_yhi[itime][ivar].writeOn(bdy_d_file,0,1);
254  }
255  }
256  }
257 #endif
258 
259 }

◆ WriteGenericPlotfileHeaderWithTerrain()

void ERF::WriteGenericPlotfileHeaderWithTerrain ( std::ostream &  HeaderFile,
int  nlevels,
const amrex::Vector< amrex::BoxArray > &  bArray,
const amrex::Vector< std::string > &  varnames,
amrex::Real  time,
const amrex::Vector< int > &  level_steps,
const std::string &  versionName,
const std::string &  levelPrefix,
const std::string &  mfPrefix 
) const
1454 {
1455  AMREX_ALWAYS_ASSERT(nlevels <= bArray.size());
1456  AMREX_ALWAYS_ASSERT(nlevels <= ref_ratio.size()+1);
1457  AMREX_ALWAYS_ASSERT(nlevels <= level_steps.size());
1458 
1459  HeaderFile.precision(17);
1460 
1461  // ---- this is the generic plot file type name
1462  HeaderFile << versionName << '\n';
1463 
1464  HeaderFile << varnames.size() << '\n';
1465 
1466  for (int ivar = 0; ivar < varnames.size(); ++ivar) {
1467  HeaderFile << varnames[ivar] << "\n";
1468  }
1469  HeaderFile << AMREX_SPACEDIM << '\n';
1470  HeaderFile << time << '\n';
1471  HeaderFile << finest_level << '\n';
1472  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
1473  HeaderFile << geom[0].ProbLo(i) << ' ';
1474  }
1475  HeaderFile << '\n';
1476  for (int i = 0; i < AMREX_SPACEDIM; ++i) {
1477  HeaderFile << geom[0].ProbHi(i) << ' ';
1478  }
1479  HeaderFile << '\n';
1480  for (int i = 0; i < finest_level; ++i) {
1481  HeaderFile << ref_ratio[i][0] << ' ';
1482  }
1483  HeaderFile << '\n';
1484  for (int i = 0; i <= finest_level; ++i) {
1485  HeaderFile << geom[i].Domain() << ' ';
1486  }
1487  HeaderFile << '\n';
1488  for (int i = 0; i <= finest_level; ++i) {
1489  HeaderFile << level_steps[i] << ' ';
1490  }
1491  HeaderFile << '\n';
1492  for (int i = 0; i <= finest_level; ++i) {
1493  for (int k = 0; k < AMREX_SPACEDIM; ++k) {
1494  HeaderFile << geom[i].CellSize()[k] << ' ';
1495  }
1496  HeaderFile << '\n';
1497  }
1498  HeaderFile << (int) geom[0].Coord() << '\n';
1499  HeaderFile << "0\n";
1500 
1501  for (int level = 0; level <= finest_level; ++level) {
1502  HeaderFile << level << ' ' << bArray[level].size() << ' ' << time << '\n';
1503  HeaderFile << level_steps[level] << '\n';
1504 
1505  const IntVect& domain_lo = geom[level].Domain().smallEnd();
1506  for (int i = 0; i < bArray[level].size(); ++i)
1507  {
1508  // Need to shift because the RealBox ctor we call takes the
1509  // physical location of index (0,0,0). This does not affect
1510  // the usual cases where the domain index starts with 0.
1511  const Box& b = shift(bArray[level][i], -domain_lo);
1512  RealBox loc = RealBox(b, geom[level].CellSize(), geom[level].ProbLo());
1513  for (int n = 0; n < AMREX_SPACEDIM; ++n) {
1514  HeaderFile << loc.lo(n) << ' ' << loc.hi(n) << '\n';
1515  }
1516  }
1517 
1518  HeaderFile << MultiFabHeaderPath(level, levelPrefix, mfPrefix) << '\n';
1519  }
1520  HeaderFile << "1" << "\n";
1521  HeaderFile << "3" << "\n";
1522  HeaderFile << "amrexvec_nu_x" << "\n";
1523  HeaderFile << "amrexvec_nu_y" << "\n";
1524  HeaderFile << "amrexvec_nu_z" << "\n";
1525  std::string mf_nodal_prefix = "Nu_nd";
1526  for (int level = 0; level <= finest_level; ++level) {
1527  HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_nodal_prefix) << '\n';
1528  }
1529 }
Coord
Definition: DataStruct.H:47

◆ writeJobInfo()

void ERF::writeJobInfo ( const std::string &  dir) const
10 {
11  // job_info file with details about the run
12  std::ofstream jobInfoFile;
13  std::string FullPathJobInfoFile = dir;
14  FullPathJobInfoFile += "/job_info";
15  jobInfoFile.open(FullPathJobInfoFile.c_str(), std::ios::out);
16 
17  std::string PrettyLine = "==================================================="
18  "============================\n";
19  std::string OtherLine = "----------------------------------------------------"
20  "----------------------------\n";
21  std::string SkipSpace = " ";
22 
23  // job information
24  jobInfoFile << PrettyLine;
25  jobInfoFile << " ERF Job Information\n";
26  jobInfoFile << PrettyLine;
27 
28  jobInfoFile << "inputs file: " << inputs_name << "\n\n";
29 
30  jobInfoFile << "number of MPI processes: "
31  << ParallelDescriptor::NProcs() << "\n";
32 #ifdef _OPENMP
33  jobInfoFile << "number of threads: " << omp_get_max_threads() << "\n";
34 #endif
35 
36  jobInfoFile << "\n";
37  jobInfoFile << "CPU time used since start of simulation (CPU-hours): "
38  << getCPUTime() / 3600.0;
39 
40  jobInfoFile << "\n\n";
41 
42  // plotfile information
43  jobInfoFile << PrettyLine;
44  jobInfoFile << " Plotfile Information\n";
45  jobInfoFile << PrettyLine;
46 
47  time_t now = time(nullptr);
48 
49  // Convert now to tm struct for local timezone
50  tm* localtm = localtime(&now);
51  jobInfoFile << "output data / time: " << asctime(localtm);
52 
53  std::string currentDir = FileSystem::CurrentPath();
54  jobInfoFile << "output dir: " << currentDir << "\n";
55 
56  jobInfoFile << "\n\n";
57 
58  // build information
59  jobInfoFile << PrettyLine;
60  jobInfoFile << " Build Information\n";
61  jobInfoFile << PrettyLine;
62 
63  jobInfoFile << "build date: " << buildInfoGetBuildDate() << "\n";
64  jobInfoFile << "build machine: " << buildInfoGetBuildMachine() << "\n";
65  jobInfoFile << "build dir: " << buildInfoGetBuildDir() << "\n";
66  jobInfoFile << "AMReX dir: " << buildInfoGetAMReXDir() << "\n";
67 
68  jobInfoFile << "\n";
69 
70  jobInfoFile << "COMP: " << buildInfoGetComp() << "\n";
71  jobInfoFile << "COMP version: " << buildInfoGetCompVersion() << "\n";
72 
73  jobInfoFile << "\n";
74 
75  for (int n = 1; n <= buildInfoGetNumModules(); n++) {
76  jobInfoFile << buildInfoGetModuleName(n) << ": "
77  << buildInfoGetModuleVal(n) << "\n";
78  }
79 
80  jobInfoFile << "\n";
81 
82  const char* githash1 = buildInfoGetGitHash(1);
83  const char* githash2 = buildInfoGetGitHash(2);
84  if (strlen(githash1) > 0) {
85  jobInfoFile << "ERF git hash: " << githash1 << "\n";
86  }
87  if (strlen(githash2) > 0) {
88  jobInfoFile << "AMReX git hash: " << githash2 << "\n";
89  }
90 
91  const char* buildgithash = buildInfoGetBuildGitHash();
92  const char* buildgitname = buildInfoGetBuildGitName();
93  if (strlen(buildgithash) > 0) {
94  jobInfoFile << buildgitname << " git hash: " << buildgithash << "\n";
95  }
96 
97  jobInfoFile << "\n\n";
98 
99  // grid information
100  jobInfoFile << PrettyLine;
101  jobInfoFile << " Grid Information\n";
102  jobInfoFile << PrettyLine;
103 
104  int f_lev = finest_level;
105 
106  for (int i = 0; i <= f_lev; i++) {
107  jobInfoFile << " level: " << i << "\n";
108  jobInfoFile << " number of boxes = " << grids[i].size() << "\n";
109  jobInfoFile << " maximum zones = ";
110  for (int n = 0; n < AMREX_SPACEDIM; n++) {
111  jobInfoFile << geom[i].Domain().length(n) << " ";
112  }
113  jobInfoFile << "\n\n";
114  }
115 
116  jobInfoFile << " Boundary conditions\n";
117 
118  jobInfoFile << " -x: " << domain_bc_type[0] << "\n";
119  jobInfoFile << " +x: " << domain_bc_type[3] << "\n";
120  jobInfoFile << " -y: " << domain_bc_type[1] << "\n";
121  jobInfoFile << " +y: " << domain_bc_type[4] << "\n";
122  jobInfoFile << " -z: " << domain_bc_type[2] << "\n";
123  jobInfoFile << " +z: " << domain_bc_type[5] << "\n";
124 
125  jobInfoFile << "\n\n";
126 
127  // runtime parameters
128  jobInfoFile << PrettyLine;
129  jobInfoFile << " Inputs File Parameters\n";
130  jobInfoFile << PrettyLine;
131 
132  ParmParse::dumpTable(jobInfoFile, true);
133  jobInfoFile.close();
134 }
static amrex::Real getCPUTime()
Definition: ERF.H:1070
std::string inputs_name
Definition: main.cpp:14
Here is the call graph for this function:

◆ WriteMultiLevelPlotfileWithTerrain()

void ERF::WriteMultiLevelPlotfileWithTerrain ( const std::string &  plotfilename,
int  nlevels,
const amrex::Vector< const amrex::MultiFab * > &  mf,
const amrex::Vector< const amrex::MultiFab * > &  mf_nd,
const amrex::Vector< std::string > &  varnames,
amrex::Real  time,
const amrex::Vector< int > &  level_steps,
const std::string &  versionName = "HyperCLaw-V1.1",
const std::string &  levelPrefix = "Level_",
const std::string &  mfPrefix = "Cell",
const amrex::Vector< std::string > &  extra_dirs = amrex::Vector<std::string>() 
) const
1370 {
1371  BL_PROFILE("WriteMultiLevelPlotfileWithTerrain()");
1372 
1373  AMREX_ALWAYS_ASSERT(nlevels <= mf.size());
1374  AMREX_ALWAYS_ASSERT(nlevels <= ref_ratio.size()+1);
1375  AMREX_ALWAYS_ASSERT(nlevels <= level_steps.size());
1376  AMREX_ALWAYS_ASSERT(mf[0]->nComp() == varnames.size());
1377 
1378  bool callBarrier(false);
1379  PreBuildDirectorHierarchy(plotfilename, levelPrefix, nlevels, callBarrier);
1380  if (!extra_dirs.empty()) {
1381  for (const auto& d : extra_dirs) {
1382  const std::string ed = plotfilename+"/"+d;
1383  PreBuildDirectorHierarchy(ed, levelPrefix, nlevels, callBarrier);
1384  }
1385  }
1386  ParallelDescriptor::Barrier();
1387 
1388  if (ParallelDescriptor::MyProc() == ParallelDescriptor::NProcs()-1) {
1389  Vector<BoxArray> boxArrays(nlevels);
1390  for(int level(0); level < boxArrays.size(); ++level) {
1391  boxArrays[level] = mf[level]->boxArray();
1392  }
1393 
1394  auto f = [=]() {
1395  VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size);
1396  std::string HeaderFileName(plotfilename + "/Header");
1397  std::ofstream HeaderFile;
1398  HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size());
1399  HeaderFile.open(HeaderFileName.c_str(), std::ofstream::out |
1400  std::ofstream::trunc |
1401  std::ofstream::binary);
1402  if( ! HeaderFile.good()) FileOpenFailed(HeaderFileName);
1403  WriteGenericPlotfileHeaderWithTerrain(HeaderFile, nlevels, boxArrays, varnames,
1404  time, level_steps, versionName,
1405  levelPrefix, mfPrefix);
1406  };
1407 
1408  if (AsyncOut::UseAsyncOut()) {
1409  AsyncOut::Submit(std::move(f));
1410  } else {
1411  f();
1412  }
1413  }
1414 
1415  std::string mf_nodal_prefix = "Nu_nd";
1416  for (int level = 0; level <= finest_level; ++level)
1417  {
1418  if (AsyncOut::UseAsyncOut()) {
1419  VisMF::AsyncWrite(*mf[level],
1420  MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mfPrefix),
1421  true);
1422  VisMF::AsyncWrite(*mf_nd[level],
1423  MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_nodal_prefix),
1424  true);
1425  } else {
1426  const MultiFab* data;
1427  std::unique_ptr<MultiFab> mf_tmp;
1428  if (mf[level]->nGrowVect() != 0) {
1429  mf_tmp = std::make_unique<MultiFab>(mf[level]->boxArray(),
1430  mf[level]->DistributionMap(),
1431  mf[level]->nComp(), 0, MFInfo(),
1432  mf[level]->Factory());
1433  MultiFab::Copy(*mf_tmp, *mf[level], 0, 0, mf[level]->nComp(), 0);
1434  data = mf_tmp.get();
1435  } else {
1436  data = mf[level];
1437  }
1438  VisMF::Write(*data , MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mfPrefix));
1439  VisMF::Write(*mf_nd[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_nodal_prefix));
1440  }
1441  }
1442 }
void WriteGenericPlotfileHeaderWithTerrain(std::ostream &HeaderFile, int nlevels, const amrex::Vector< amrex::BoxArray > &bArray, const amrex::Vector< std::string > &varnames, amrex::Real time, const amrex::Vector< int > &level_steps, const std::string &versionName, const std::string &levelPrefix, const std::string &mfPrefix) const
Definition: Plotfile.cpp:1445
amrex::FabFactory< amrex::FArrayBox > const & Factory(int lev) const noexcept
Definition: ERF.H:1154

◆ writeNow()

bool ERF::writeNow ( const amrex::Real  cur_time,
const amrex::Real  dt,
const int  nstep,
const int  plot_int,
const amrex::Real  plot_per 
)
1988 {
1989  bool write_now = false;
1990 
1991  if ( plot_int > 0 && (nstep % plot_int == 0) ) {
1992  write_now = true;
1993 
1994  } else if (plot_per > 0.0) {
1995 
1996  // Check to see if we've crossed a plot_per interval by comparing
1997  // the number of intervals that have elapsed for both the current
1998  // time and the time at the beginning of this timestep.
1999 
2000  const Real eps = std::numeric_limits<Real>::epsilon() * Real(10.0) * std::abs(cur_time);
2001 
2002  int num_per_old = static_cast<int>(std::round((cur_time-eps-dt_lev) / plot_per));
2003  int num_per_new = static_cast<int>(std::round((cur_time-eps ) / plot_per));
2004 
2005  // Before using these, however, we must test for the case where we're
2006  // within machine epsilon of the next interval. In that case, increment
2007  // the counter, because we have indeed reached the next plot_per interval
2008  // at this point.
2009 
2010  const Real next_plot_time = (num_per_old + 1) * plot_per;
2011 
2012  if ((num_per_new == num_per_old) && std::abs(cur_time - next_plot_time) <= eps)
2013  {
2014  num_per_new += 1;
2015  }
2016 
2017  // Similarly, we have to account for the case where the old time is within
2018  // machine epsilon of the beginning of this interval, so that we don't double
2019  // count that time threshold -- we already plotted at that time on the last timestep.
2020 
2021  if ((num_per_new != num_per_old) && std::abs((cur_time - dt_lev) - next_plot_time) <= eps)
2022  num_per_old += 1;
2023 
2024  if (num_per_old != num_per_new)
2025  write_now = true;
2026  }
2027  return write_now;
2028 }

◆ WritePlotFile()

void ERF::WritePlotFile ( int  which,
amrex::Vector< std::string >  plot_var_names 
)
155 {
156  const Vector<std::string> varnames = PlotFileVarNames(plot_var_names);
157  const int ncomp_mf = varnames.size();
158 
159  int ncomp_cons = vars_new[0][Vars::cons].nComp();
160 
161  if (ncomp_mf == 0) return;
162 
163  // We Fillpatch here because some of the derived quantities require derivatives
164  // which require ghost cells to be filled. We do not need to call FillPatcher
165  // because we don't need to set interior fine points.
166  for (int lev = 0; lev <= finest_level; ++lev) {
167  bool fillset = false;
168  FillPatch(lev, t_new[lev], {&vars_new[lev][Vars::cons], &vars_new[lev][Vars::xvel],
169  &vars_new[lev][Vars::yvel], &vars_new[lev][Vars::zvel]},
170  {&vars_new[lev][Vars::cons], &rU_new[lev],
171  &rV_new[lev], &rW_new[lev]}, fillset);
172  }
173 
174  // Get qmoist pointers if using moisture
175  bool use_moisture = (solverChoice.moisture_type != MoistureType::None);
176  for (int lev = 0; lev <= finest_level; ++lev) {
177  for (int mvar(0); mvar<qmoist[lev].size(); ++mvar) {
178  qmoist[lev][mvar] = micro->Get_Qmoist_Ptr(lev,mvar);
179  }
180  }
181 
182  // Vector of MultiFabs for cell-centered data
183  Vector<MultiFab> mf(finest_level+1);
184  for (int lev = 0; lev <= finest_level; ++lev) {
185  mf[lev].define(grids[lev], dmap[lev], ncomp_mf, 0);
186  }
187 
188  // Vector of MultiFabs for nodal data
189  Vector<MultiFab> mf_nd(finest_level+1);
191  for (int lev = 0; lev <= finest_level; ++lev) {
192  BoxArray nodal_grids(grids[lev]); nodal_grids.surroundingNodes();
193  mf_nd[lev].define(nodal_grids, dmap[lev], 3, 0);
194  mf_nd[lev].setVal(0.);
195  }
196  }
197 
198  // Array of MultiFabs for cell-centered velocity
199  Vector<MultiFab> mf_cc_vel(finest_level+1);
200 
201  if (containerHasElement(plot_var_names, "x_velocity" ) ||
202  containerHasElement(plot_var_names, "y_velocity" ) ||
203  containerHasElement(plot_var_names, "z_velocity" ) ||
204  containerHasElement(plot_var_names, "magvel" ) ||
205  containerHasElement(plot_var_names, "vorticity_x") ||
206  containerHasElement(plot_var_names, "vorticity_y") ||
207  containerHasElement(plot_var_names, "vorticity_z") ) {
208 
209  for (int lev = 0; lev <= finest_level; ++lev) {
210  mf_cc_vel[lev].define(grids[lev], dmap[lev], AMREX_SPACEDIM, IntVect(1,1,1));
211  average_face_to_cellcenter(mf_cc_vel[lev],0,
212  Array<const MultiFab*,3>{&vars_new[lev][Vars::xvel],
213  &vars_new[lev][Vars::yvel],
214  &vars_new[lev][Vars::zvel]});
215  } // lev
216  } // if (vel or vort)
217 
218  // We need ghost cells if computing vorticity
219  if ( containerHasElement(plot_var_names, "vorticity_x")||
220  containerHasElement(plot_var_names, "vorticity_y") ||
221  containerHasElement(plot_var_names, "vorticity_z") )
222  {
223  amrex::Interpolater* mapper = &cell_cons_interp;
224  for (int lev = 1; lev <= finest_level; ++lev)
225  {
226  Vector<MultiFab*> fmf = {&(mf_cc_vel[lev]), &(mf_cc_vel[lev])};
227  Vector<Real> ftime = {t_new[lev], t_new[lev]};
228  Vector<MultiFab*> cmf = {&mf_cc_vel[lev-1], &mf_cc_vel[lev-1]};
229  Vector<Real> ctime = {t_new[lev], t_new[lev]};
230 
231  amrex::FillPatchTwoLevels(mf_cc_vel[lev], t_new[lev], cmf, ctime, fmf, ftime,
232  0, 0, AMREX_SPACEDIM, geom[lev-1], geom[lev],
233  null_bc_for_fill, 0, null_bc_for_fill, 0, refRatio(lev-1),
234  mapper, domain_bcs_type, 0);
235  } // lev
236 
237  // Impose bc's at domain boundaries at all levels
238  FillBdyCCVels(mf_cc_vel);
239  } // if (vort)
240 
241  for (int lev = 0; lev <= finest_level; ++lev)
242  {
243  int mf_comp = 0;
244 
245  // First, copy any of the conserved state variables into the output plotfile
246  AMREX_ALWAYS_ASSERT(cons_names.size() >= ncomp_cons);
247  for (int i = 0; i < ncomp_cons; ++i) {
248  if (containerHasElement(plot_var_names, cons_names[i])) {
249  MultiFab::Copy(mf[lev],vars_new[lev][Vars::cons],i,mf_comp,1,0);
250  mf_comp++;
251  }
252  }
253 
254  // Next, check for velocities
255  if (containerHasElement(plot_var_names, "x_velocity")) {
256  MultiFab::Copy(mf[lev], mf_cc_vel[lev], 0, mf_comp, 1, 0);
257  mf_comp += 1;
258  }
259  if (containerHasElement(plot_var_names, "y_velocity")) {
260  MultiFab::Copy(mf[lev], mf_cc_vel[lev], 1, mf_comp, 1, 0);
261  mf_comp += 1;
262  }
263  if (containerHasElement(plot_var_names, "z_velocity")) {
264  MultiFab::Copy(mf[lev], mf_cc_vel[lev], 2, mf_comp, 1, 0);
265  mf_comp += 1;
266  }
267 
268  // Finally, check for any derived quantities and compute them, inserting
269  // them into our output multifab
270  auto calculate_derived = [&](const std::string& der_name,
271  MultiFab& src_mf,
272  decltype(derived::erf_dernull)& der_function)
273  {
274  if (containerHasElement(plot_var_names, der_name)) {
275  MultiFab dmf(mf[lev], make_alias, mf_comp, 1);
276 #ifdef _OPENMP
277 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
278 #endif
279  for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
280  {
281  const Box& bx = mfi.tilebox();
282  auto& dfab = dmf[mfi];
283  auto& sfab = src_mf[mfi];
284  der_function(bx, dfab, 0, 1, sfab, Geom(lev), t_new[0], nullptr, lev);
285  }
286 
287  mf_comp++;
288  }
289  };
290 
291  // Note: All derived variables must be computed in order of "derived_names" defined in ERF.H
292  calculate_derived("soundspeed", vars_new[lev][Vars::cons], derived::erf_dersoundspeed);
293  calculate_derived("temp", vars_new[lev][Vars::cons], derived::erf_dertemp);
294  calculate_derived("theta", vars_new[lev][Vars::cons], derived::erf_dertheta);
295  calculate_derived("KE", vars_new[lev][Vars::cons], derived::erf_derKE);
296  calculate_derived("QKE", vars_new[lev][Vars::cons], derived::erf_derQKE);
297  calculate_derived("scalar", vars_new[lev][Vars::cons], derived::erf_derscalar);
298  calculate_derived("vorticity_x", mf_cc_vel[lev] , derived::erf_dervortx);
299  calculate_derived("vorticity_y", mf_cc_vel[lev] , derived::erf_dervorty);
300  calculate_derived("vorticity_z", mf_cc_vel[lev] , derived::erf_dervortz);
301  calculate_derived("magvel" , mf_cc_vel[lev] , derived::erf_dermagvel);
302 
303  if (containerHasElement(plot_var_names, "divU"))
304  {
305  MultiFab dmf(mf[lev], make_alias, mf_comp, 1);
306  Array<MultiFab const*, AMREX_SPACEDIM> u;
307  u[0] = &(vars_new[lev][Vars::xvel]);
308  u[1] = &(vars_new[lev][Vars::yvel]);
309  u[2] = &(vars_new[lev][Vars::zvel]);
310  computeDivergence(dmf, u, geom[lev]);
311  mf_comp += 1;
312  }
313 
314  MultiFab r_hse(base_state[lev], make_alias, 0, 1); // r_0 is first component
315  MultiFab p_hse(base_state[lev], make_alias, 1, 1); // p_0 is second component
316  if (containerHasElement(plot_var_names, "pres_hse"))
317  {
318  // p_0 is second component of base_state
319  MultiFab::Copy(mf[lev],p_hse,0,mf_comp,1,0);
320  mf_comp += 1;
321  }
322  if (containerHasElement(plot_var_names, "dens_hse"))
323  {
324  // r_0 is first component of base_state
325  MultiFab::Copy(mf[lev],r_hse,0,mf_comp,1,0);
326  mf_comp += 1;
327  }
328 
329  if (containerHasElement(plot_var_names, "pressure"))
330  {
331 #ifdef _OPENMP
332 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
333 #endif
334  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
335  {
336  const Box& bx = mfi.tilebox();
337  const Array4<Real >& derdat = mf[lev].array(mfi);
338  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
339  const int ncomp = vars_new[lev][Vars::cons].nComp();
340 
341  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
342  {
343  Real qv_for_p = (use_moisture && (ncomp > RhoQ1_comp)) ? S_arr(i,j,k,RhoQ1_comp)/S_arr(i,j,k,Rho_comp) : 0;
344  const Real rhotheta = S_arr(i,j,k,RhoTheta_comp);
345  derdat(i, j, k, mf_comp) = getPgivenRTh(rhotheta,qv_for_p);
346  });
347  }
348  mf_comp += 1;
349  }
350  if (containerHasElement(plot_var_names, "pert_pres"))
351  {
352 #ifdef _OPENMP
353 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
354 #endif
355  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
356  {
357  const Box& bx = mfi.tilebox();
358  const Array4<Real>& derdat = mf[lev].array(mfi);
359  const Array4<Real const>& p0_arr = p_hse.const_array(mfi);
360  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
361  const int ncomp = vars_new[lev][Vars::cons].nComp();
362 
363  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
364  {
365  Real qv_for_p = (use_moisture && (ncomp > RhoQ1_comp)) ? S_arr(i,j,k,RhoQ1_comp)/S_arr(i,j,k,Rho_comp) : 0;
366  const Real rhotheta = S_arr(i,j,k,RhoTheta_comp);
367  derdat(i, j, k, mf_comp) = getPgivenRTh(rhotheta,qv_for_p) - p0_arr(i,j,k);
368  });
369  }
370  mf_comp += 1;
371  }
372  if (containerHasElement(plot_var_names, "pert_dens"))
373  {
374 #ifdef _OPENMP
375 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
376 #endif
377  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
378  {
379  const Box& bx = mfi.tilebox();
380  const Array4<Real>& derdat = mf[lev].array(mfi);
381  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
382  const Array4<Real const>& r0_arr = r_hse.const_array(mfi);
383  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
384  derdat(i, j, k, mf_comp) = S_arr(i,j,k,Rho_comp) - r0_arr(i,j,k);
385  });
386  }
387  mf_comp ++;
388  }
389 
390  if (containerHasElement(plot_var_names, "eq_pot_temp"))
391  {
392 #ifdef _OPENMP
393 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
394 #endif
395  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
396  {
397  const Box& bx = mfi.tilebox();
398  const Array4<Real>& derdat = mf[lev].array(mfi);
399  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
400  const int ncomp = vars_new[lev][Vars::cons].nComp();
401  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
402  Real qv = (use_moisture && (ncomp > RhoQ1_comp)) ? S_arr(i,j,k,RhoQ1_comp)/S_arr(i,j,k,Rho_comp) : 0.0;
403  Real qc = (use_moisture && (ncomp > RhoQ2_comp)) ? S_arr(i,j,k,RhoQ2_comp)/S_arr(i,j,k,Rho_comp) : 0.0;
404  Real T = getTgivenRandRTh(S_arr(i,j,k,Rho_comp), S_arr(i,j,k,RhoTheta_comp), qv);
405  Real pressure = getPgivenRTh(S_arr(i,j,k,RhoTheta_comp), qv);
406  Real fac = Cp_d + Cp_l*(qv + qc);
407  Real pv = erf_esatw(T)*100.0;
408 
409  derdat(i, j, k, mf_comp) = T*std::pow((pressure - pv)/p_0, -R_d/fac)*std::exp(L_v*qv/(fac*T)) ;
410  });
411  }
412  mf_comp ++;
413  }
414 
415 #ifdef ERF_USE_WINDFARM
416  if (containerHasElement(plot_var_names, "num_turb"))
417  {
418  std::cout << "Plotting num_turb" << "\n";
419 #ifdef _OPENMP
420 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
421 #endif
422  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
423  {
424  const Box& bx = mfi.tilebox();
425  const Array4<Real>& derdat = mf[lev].array(mfi);
426  const Array4<Real const>& Nturb_array = Nturb[lev].const_array(mfi);
427  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
428  derdat(i, j, k, mf_comp) = Nturb_array(i,j,k,0);
429  });
430  }
431  mf_comp ++;
432  }
433 #endif
434 
435  int klo = geom[lev].Domain().smallEnd(2);
436  int khi = geom[lev].Domain().bigEnd(2);
437 
438  if (containerHasElement(plot_var_names, "dpdx"))
439  {
440  auto dxInv = geom[lev].InvCellSizeArray();
441  MultiFab pres(vars_new[lev][Vars::cons].boxArray(), vars_new[lev][Vars::cons].DistributionMap(), 1, 1);
442 #ifdef _OPENMP
443 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
444 #endif
445  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
446  {
447  // First define pressure on grown box
448  const Box& gbx = mfi.growntilebox(1);
449  const Array4<Real> & p_arr = pres.array(mfi);
450  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
451  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
452  p_arr(i,j,k) = getPgivenRTh(S_arr(i,j,k,RhoTheta_comp));
453  });
454  }
455  pres.FillBoundary(geom[lev].periodicity());
456 
457 #ifdef _OPENMP
458 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
459 #endif
460  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
461  {
462  // Now compute pressure gradient on valid box
463  const Box& bx = mfi.tilebox();
464  const Array4<Real>& derdat = mf[lev].array(mfi);
465  const Array4<Real> & p_arr = pres.array(mfi);
466 
468  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
469 
470  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
471 
472  // Pgrad at lower I face
473  Real met_h_xi_lo = Compute_h_xi_AtIface (i, j, k, dxInv, z_nd);
474  Real met_h_zeta_lo = Compute_h_zeta_AtIface(i, j, k, dxInv, z_nd);
475  Real gp_xi_lo = dxInv[0] * (p_arr(i,j,k) - p_arr(i-1,j,k));
476  Real gp_zeta_on_iface_lo;
477  if(k == klo) {
478  gp_zeta_on_iface_lo = 0.5 * dxInv[2] * (
479  p_arr(i-1,j,k+1) + p_arr(i,j,k+1)
480  - p_arr(i-1,j,k ) - p_arr(i,j,k ) );
481  } else if (k == khi) {
482  gp_zeta_on_iface_lo = 0.5 * dxInv[2] * (
483  p_arr(i-1,j,k ) + p_arr(i,j,k )
484  - p_arr(i-1,j,k-1) - p_arr(i,j,k-1) );
485  } else {
486  gp_zeta_on_iface_lo = 0.25 * dxInv[2] * (
487  p_arr(i-1,j,k+1) + p_arr(i,j,k+1)
488  - p_arr(i-1,j,k-1) - p_arr(i,j,k-1) );
489  }
490  Real gpx_lo = gp_xi_lo - (met_h_xi_lo/ met_h_zeta_lo) * gp_zeta_on_iface_lo;
491 
492  // Pgrad at higher I face
493  Real met_h_xi_hi = Compute_h_xi_AtIface (i+1, j, k, dxInv, z_nd);
494  Real met_h_zeta_hi = Compute_h_zeta_AtIface(i+1, j, k, dxInv, z_nd);
495  Real gp_xi_hi = dxInv[0] * (p_arr(i+1,j,k) - p_arr(i,j,k));
496  Real gp_zeta_on_iface_hi;
497  if(k == klo) {
498  gp_zeta_on_iface_hi = 0.5 * dxInv[2] * (
499  p_arr(i+1,j,k+1) + p_arr(i,j,k+1)
500  - p_arr(i+1,j,k ) - p_arr(i,j,k ) );
501  } else if (k == khi) {
502  gp_zeta_on_iface_hi = 0.5 * dxInv[2] * (
503  p_arr(i+1,j,k ) + p_arr(i,j,k )
504  - p_arr(i+1,j,k-1) - p_arr(i,j,k-1) );
505  } else {
506  gp_zeta_on_iface_hi = 0.25 * dxInv[2] * (
507  p_arr(i+1,j,k+1) + p_arr(i,j,k+1)
508  - p_arr(i+1,j,k-1) - p_arr(i,j,k-1) );
509  }
510  Real gpx_hi = gp_xi_hi - (met_h_xi_hi/ met_h_zeta_hi) * gp_zeta_on_iface_hi;
511 
512  // Average P grad to CC
513  derdat(i ,j ,k, mf_comp) = 0.5 * (gpx_lo + gpx_hi);
514  });
515  } else {
516  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
517  derdat(i ,j ,k, mf_comp) = 0.5 * (p_arr(i+1,j,k) - p_arr(i-1,j,k)) * dxInv[0];
518  });
519  }
520  } // mfi
521  mf_comp ++;
522  } // dpdx
523 
524  if (containerHasElement(plot_var_names, "dpdy"))
525  {
526  auto dxInv = geom[lev].InvCellSizeArray();
527 
528  MultiFab pres(vars_new[lev][Vars::cons].boxArray(), vars_new[lev][Vars::cons].DistributionMap(), 1, 1);
529 #ifdef _OPENMP
530 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
531 #endif
532  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
533  {
534  // First define pressure on grown box
535  const Box& gbx = mfi.growntilebox(1);
536  const Array4<Real> & p_arr = pres.array(mfi);
537  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
538  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
539  p_arr(i,j,k) = getPgivenRTh(S_arr(i,j,k,RhoTheta_comp));
540  });
541  }
542  pres.FillBoundary(geom[lev].periodicity());
543 
544 #ifdef _OPENMP
545 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
546 #endif
547  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
548  {
549  // Now compute pressure gradient on valid box
550  const Box& bx = mfi.tilebox();
551  const Array4<Real>& derdat = mf[lev].array(mfi);
552  const Array4<Real> & p_arr = pres.array(mfi);
553 
555  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
556 
557  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
558 
559  Real met_h_eta_lo = Compute_h_eta_AtJface (i, j, k, dxInv, z_nd);
560  Real met_h_zeta_lo = Compute_h_zeta_AtJface(i, j, k, dxInv, z_nd);
561  Real gp_eta_lo = dxInv[1] * (p_arr(i,j,k) - p_arr(i,j-1,k));
562  Real gp_zeta_on_jface_lo;
563  if (k == klo) {
564  gp_zeta_on_jface_lo = 0.5 * dxInv[2] * (
565  p_arr(i,j,k+1) + p_arr(i,j-1,k+1)
566  - p_arr(i,j,k ) - p_arr(i,j-1,k ) );
567  } else if (k == khi) {
568  gp_zeta_on_jface_lo = 0.5 * dxInv[2] * (
569  p_arr(i,j,k ) + p_arr(i,j-1,k )
570  - p_arr(i,j,k-1) - p_arr(i,j-1,k-1) );
571  } else {
572  gp_zeta_on_jface_lo = 0.25 * dxInv[2] * (
573  p_arr(i,j,k+1) + p_arr(i,j-1,k+1)
574  - p_arr(i,j,k-1) - p_arr(i,j-1,k-1) );
575  }
576  Real gpy_lo = gp_eta_lo - (met_h_eta_lo / met_h_zeta_lo) * gp_zeta_on_jface_lo;
577 
578  Real met_h_eta_hi = Compute_h_eta_AtJface (i, j+1, k, dxInv, z_nd);
579  Real met_h_zeta_hi = Compute_h_zeta_AtJface(i, j+1, k, dxInv, z_nd);
580  Real gp_eta_hi = dxInv[1] * (p_arr(i,j+1,k) - p_arr(i,j,k));
581  Real gp_zeta_on_jface_hi;
582  if (k == klo) {
583  gp_zeta_on_jface_hi = 0.5 * dxInv[2] * (
584  p_arr(i,j+1,k+1) + p_arr(i,j,k+1)
585  - p_arr(i,j+1,k ) - p_arr(i,j,k ) );
586  } else if (k == khi) {
587  gp_zeta_on_jface_hi = 0.5 * dxInv[2] * (
588  p_arr(i,j+1,k ) + p_arr(i,j,k )
589  - p_arr(i,j+1,k-1) - p_arr(i,j,k-1) );
590  } else {
591  gp_zeta_on_jface_hi = 0.25 * dxInv[2] * (
592  p_arr(i,j+1,k+1) + p_arr(i,j,k+1)
593  - p_arr(i,j+1,k-1) - p_arr(i,j,k-1) );
594  }
595  Real gpy_hi = gp_eta_hi - (met_h_eta_hi / met_h_zeta_hi) * gp_zeta_on_jface_hi;
596 
597  derdat(i ,j ,k, mf_comp) = 0.5 * (gpy_lo + gpy_hi);
598  });
599  } else {
600  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
601  derdat(i ,j ,k, mf_comp) = 0.5 * (p_arr(i,j+1,k) - p_arr(i,j-1,k)) * dxInv[1];
602  });
603  }
604  } // mf
605  mf_comp ++;
606  } // dpdy
607 
608  if (containerHasElement(plot_var_names, "pres_hse_x"))
609  {
610  auto dxInv = geom[lev].InvCellSizeArray();
611 #ifdef _OPENMP
612 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
613 #endif
614  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
615  {
616  const Box& bx = mfi.tilebox();
617  const Array4<Real >& derdat = mf[lev].array(mfi);
618  const Array4<Real const>& p_arr = p_hse.const_array(mfi);
619 
620  //USE_TERRAIN POSSIBLE ISSUE HERE
621  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
622 
623  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
624  Real met_h_xi_lo = Compute_h_xi_AtIface (i, j, k, dxInv, z_nd);
625  Real met_h_zeta_lo = Compute_h_zeta_AtIface(i, j, k, dxInv, z_nd);
626  Real gp_xi_lo = dxInv[0] * (p_arr(i,j,k) - p_arr(i-1,j,k));
627  Real gp_zeta_on_iface_lo;
628  if (k == klo) {
629  gp_zeta_on_iface_lo = 0.5 * dxInv[2] * (
630  p_arr(i-1,j,k+1) + p_arr(i,j,k+1)
631  - p_arr(i-1,j,k ) - p_arr(i,j,k ) );
632  } else if (k == khi) {
633  gp_zeta_on_iface_lo = 0.5 * dxInv[2] * (
634  p_arr(i-1,j,k ) + p_arr(i,j,k )
635  - p_arr(i-1,j,k-1) - p_arr(i,j,k-1) );
636  } else {
637  gp_zeta_on_iface_lo = 0.25 * dxInv[2] * (
638  p_arr(i-1,j,k+1) + p_arr(i,j,k+1)
639  - p_arr(i-1,j,k-1) - p_arr(i,j,k-1) );
640  }
641  Real gpx_lo = gp_xi_lo - (met_h_xi_lo/ met_h_zeta_lo) * gp_zeta_on_iface_lo;
642 
643  Real met_h_xi_hi = Compute_h_xi_AtIface (i+1, j, k, dxInv, z_nd);
644  Real met_h_zeta_hi = Compute_h_zeta_AtIface(i+1, j, k, dxInv, z_nd);
645  Real gp_xi_hi = dxInv[0] * (p_arr(i+1,j,k) - p_arr(i,j,k));
646  Real gp_zeta_on_iface_hi;
647  if (k == klo) {
648  gp_zeta_on_iface_hi = 0.5 * dxInv[2] * (
649  p_arr(i+1,j,k+1) + p_arr(i,j,k+1)
650  - p_arr(i+1,j,k ) - p_arr(i,j,k ) );
651  } else if (k == khi) {
652  gp_zeta_on_iface_hi = 0.5 * dxInv[2] * (
653  p_arr(i+1,j,k ) + p_arr(i,j,k )
654  - p_arr(i+1,j,k-1) - p_arr(i,j,k-1) );
655  } else {
656  gp_zeta_on_iface_hi = 0.25 * dxInv[2] * (
657  p_arr(i+1,j,k+1) + p_arr(i,j,k+1)
658  - p_arr(i+1,j,k-1) - p_arr(i,j,k-1) );
659  }
660  Real gpx_hi = gp_xi_hi - (met_h_xi_hi/ met_h_zeta_hi) * gp_zeta_on_iface_hi;
661 
662  derdat(i ,j ,k, mf_comp) = 0.5 * (gpx_lo + gpx_hi);
663  });
664  }
665  mf_comp += 1;
666  } // pres_hse_x
667 
668  if (containerHasElement(plot_var_names, "pres_hse_y"))
669  {
670  auto dxInv = geom[lev].InvCellSizeArray();
671 #ifdef _OPENMP
672 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
673 #endif
674  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
675  {
676  const Box& bx = mfi.tilebox();
677  const Array4<Real >& derdat = mf[lev].array(mfi);
678  const Array4<Real const>& p_arr = p_hse.const_array(mfi);
679  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
680  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
681  Real met_h_eta_lo = Compute_h_eta_AtJface (i, j, k, dxInv, z_nd);
682  Real met_h_zeta_lo = Compute_h_zeta_AtJface(i, j, k, dxInv, z_nd);
683  Real gp_eta_lo = dxInv[1] * (p_arr(i,j,k) - p_arr(i,j-1,k));
684  Real gp_zeta_on_jface_lo;
685  if (k == klo) {
686  gp_zeta_on_jface_lo = 0.5 * dxInv[2] * (
687  p_arr(i,j,k+1) + p_arr(i,j-1,k+1)
688  - p_arr(i,j,k ) - p_arr(i,j-1,k ) );
689  } else if (k == khi) {
690  gp_zeta_on_jface_lo = 0.5 * dxInv[2] * (
691  p_arr(i,j,k ) + p_arr(i,j-1,k )
692  - p_arr(i,j,k-1) - p_arr(i,j-1,k-1) );
693  } else {
694  gp_zeta_on_jface_lo = 0.25 * dxInv[2] * (
695  p_arr(i,j,k+1) + p_arr(i,j-1,k+1)
696  - p_arr(i,j,k-1) - p_arr(i,j-1,k-1) );
697  }
698  Real gpy_lo = gp_eta_lo - (met_h_eta_lo / met_h_zeta_lo) * gp_zeta_on_jface_lo;
699 
700  Real met_h_eta_hi = Compute_h_eta_AtJface (i, j+1, k, dxInv, z_nd);
701  Real met_h_zeta_hi = Compute_h_zeta_AtJface(i, j+1, k, dxInv, z_nd);
702  Real gp_eta_hi = dxInv[1] * (p_arr(i,j+1,k) - p_arr(i,j,k));
703  Real gp_zeta_on_jface_hi;
704  if (k == klo) {
705  gp_zeta_on_jface_hi = 0.5 * dxInv[2] * (
706  p_arr(i,j+1,k+1) + p_arr(i,j,k+1)
707  - p_arr(i,j+1,k ) - p_arr(i,j,k ) );
708  } else if (k == khi) {
709  gp_zeta_on_jface_hi = 0.5 * dxInv[2] * (
710  p_arr(i,j+1,k ) + p_arr(i,j,k )
711  - p_arr(i,j+1,k-1) - p_arr(i,j,k-1) );
712  } else {
713  gp_zeta_on_jface_hi = 0.25 * dxInv[2] * (
714  p_arr(i,j+1,k+1) + p_arr(i,j,k+1)
715  - p_arr(i,j+1,k-1) - p_arr(i,j,k-1) );
716  }
717  Real gpy_hi = gp_eta_hi - (met_h_eta_hi / met_h_zeta_hi) * gp_zeta_on_jface_hi;
718 
719  derdat(i ,j ,k, mf_comp) = 0.5 * (gpy_lo + gpy_hi);
720  });
721  }
722  mf_comp += 1;
723  } // pres_hse_y
724 
726  if (containerHasElement(plot_var_names, "z_phys"))
727  {
728  MultiFab::Copy(mf[lev],*z_phys_cc[lev],0,mf_comp,1,0);
729  mf_comp ++;
730  }
731 
732  if (containerHasElement(plot_var_names, "detJ"))
733  {
734  MultiFab::Copy(mf[lev],*detJ_cc[lev],0,mf_comp,1,0);
735  mf_comp ++;
736  }
737  } // use_terrain
738 
739  if (containerHasElement(plot_var_names, "mapfac")) {
740 #ifdef _OPENMP
741 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
742 #endif
743  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
744  {
745  const Box& bx = mfi.tilebox();
746  const Array4<Real>& derdat = mf[lev].array(mfi);
747  const Array4<Real>& mf_m = mapfac_m[lev]->array(mfi);
748  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
749  derdat(i ,j ,k, mf_comp) = mf_m(i,j,0);
750  });
751  }
752  mf_comp ++;
753  }
754 
755 #ifdef ERF_USE_NETCDF
756  if (use_real_bcs) {
757  if (containerHasElement(plot_var_names, "lat_m")) {
758 #ifdef _OPENMP
759 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
760 #endif
761  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
762  {
763  const Box& bx = mfi.tilebox();
764  const Array4<Real>& derdat = mf[lev].array(mfi);
765  const Array4<Real>& data = lat_m[lev]->array(mfi);
766  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
767  derdat(i, j, k, mf_comp) = data(i,j,0);
768  });
769  }
770  mf_comp ++;
771  } // lat_m
772  if (containerHasElement(plot_var_names, "lon_m")) {
773 #ifdef _OPENMP
774 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
775 #endif
776  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
777  {
778  const Box& bx = mfi.tilebox();
779  const Array4<Real>& derdat = mf[lev].array(mfi);
780  const Array4<Real>& data = lon_m[lev]->array(mfi);
781  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
782  derdat(i, j, k, mf_comp) = data(i,j,0);
783  });
784  }
785  mf_comp ++;
786  } // lon_m
787  } // use_real_bcs
788 #endif
789 
790 
792  if (containerHasElement(plot_var_names, "u_t_avg")) {
793 #ifdef _OPENMP
794 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
795 #endif
796  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
797  {
798  const Box& bx = mfi.tilebox();
799  const Array4<Real>& derdat = mf[lev].array(mfi);
800  const Array4<Real>& data = vel_t_avg[lev]->array(mfi);
801  const Real norm = t_avg_cnt[lev];
802  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
803  {
804  derdat(i ,j ,k, mf_comp) = data(i,j,k,0) / norm;
805  });
806  }
807  mf_comp ++;
808  }
809 
810  if (containerHasElement(plot_var_names, "v_t_avg")) {
811 #ifdef _OPENMP
812 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
813 #endif
814  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
815  {
816  const Box& bx = mfi.tilebox();
817  const Array4<Real>& derdat = mf[lev].array(mfi);
818  const Array4<Real>& data = vel_t_avg[lev]->array(mfi);
819  const Real norm = t_avg_cnt[lev];
820  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
821  {
822  derdat(i ,j ,k, mf_comp) = data(i,j,k,1) / norm;
823  });
824  }
825  mf_comp ++;
826  }
827 
828  if (containerHasElement(plot_var_names, "w_t_avg")) {
829 #ifdef _OPENMP
830 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
831 #endif
832  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
833  {
834  const Box& bx = mfi.tilebox();
835  const Array4<Real>& derdat = mf[lev].array(mfi);
836  const Array4<Real>& data = vel_t_avg[lev]->array(mfi);
837  const Real norm = t_avg_cnt[lev];
838  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
839  {
840  derdat(i ,j ,k, mf_comp) = data(i,j,k,2) / norm;
841  });
842  }
843  mf_comp ++;
844  }
845 
846  if (containerHasElement(plot_var_names, "umag_t_avg")) {
847 #ifdef _OPENMP
848 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
849 #endif
850  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
851  {
852  const Box& bx = mfi.tilebox();
853  const Array4<Real>& derdat = mf[lev].array(mfi);
854  const Array4<Real>& data = vel_t_avg[lev]->array(mfi);
855  const Real norm = t_avg_cnt[lev];
856  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
857  {
858  derdat(i ,j ,k, mf_comp) = data(i,j,k,3) / norm;
859  });
860  }
861  mf_comp ++;
862  }
863  }
864 
865  if (containerHasElement(plot_var_names, "Kmv")) {
866  MultiFab::Copy(mf[lev],*eddyDiffs_lev[lev],EddyDiff::Mom_v,mf_comp,1,0);
867  mf_comp ++;
868  }
869  if (containerHasElement(plot_var_names, "Kmh")) {
870  MultiFab::Copy(mf[lev],*eddyDiffs_lev[lev],EddyDiff::Mom_h,mf_comp,1,0);
871  mf_comp ++;
872  }
873  if (containerHasElement(plot_var_names, "Khv")) {
874  MultiFab::Copy(mf[lev],*eddyDiffs_lev[lev],EddyDiff::Theta_v,mf_comp,1,0);
875  mf_comp ++;
876  }
877  if (containerHasElement(plot_var_names, "Khh")) {
878  MultiFab::Copy(mf[lev],*eddyDiffs_lev[lev],EddyDiff::Theta_h,mf_comp,1,0);
879  mf_comp ++;
880  }
881  if (containerHasElement(plot_var_names, "Lpbl")) {
882  MultiFab::Copy(mf[lev],*eddyDiffs_lev[lev],EddyDiff::PBL_lengthscale,mf_comp,1,0);
883  mf_comp ++;
884  }
885 
886  // TODO: The size of the q variables can vary with different
887  // moisture models. Therefore, certain components may
888  // reside at different indices. For example, Kessler is
889  // warm but precipitating. This puts qp at index 3.
890  // However, SAM is cold and precipitating so qp is index 4.
891  // Need to built an external enum struct or a better pathway.
892 
893  // NOTE: Protect against accessing non-existent data
894  if (use_moisture) {
895  int n_qstate = micro->Get_Qstate_Size();
896 
897  // Non-precipitating components
898  //--------------------------------------------------------------------------
899  if(containerHasElement(plot_var_names, "qt"))
900  {
901  int n_start = RhoQ1_comp;
902  int n_end = RhoQ2_comp;
903  if (n_qstate > 3) n_end = RhoQ3_comp;
904  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,ncomp_cons);
905  MultiFab::Copy( mf[lev], Sm, n_start, mf_comp, 1, 0);
906  for (int n_comp(n_start+1); n_comp <= n_end; ++n_comp) {
907  MultiFab::Add( mf[lev], Sm, n_comp, mf_comp, 1, 0);
908  }
909  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
910  mf_comp += 1;
911  }
912 
913  if(containerHasElement(plot_var_names, "qv") && (n_qstate >= 1))
914  {
915  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,RhoQ1_comp+1);
916  MultiFab::Copy( mf[lev], Sm, RhoQ1_comp, mf_comp, 1, 0);
917  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
918  mf_comp += 1;
919  }
920 
921  if(containerHasElement(plot_var_names, "qc") && (n_qstate >= 2))
922  {
923  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,RhoQ2_comp+1);
924  MultiFab::Copy( mf[lev], Sm, RhoQ2_comp, mf_comp, 1, 0);
925  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
926  mf_comp += 1;
927  }
928 
929  if(containerHasElement(plot_var_names, "qi") && (n_qstate >= 4))
930  {
931  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,RhoQ3_comp+1);
932  MultiFab::Copy( mf[lev], Sm, RhoQ3_comp, mf_comp, 1, 0);
933  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
934  mf_comp += 1;
935  }
936 
937  // Precipitating components
938  //--------------------------------------------------------------------------
939  if(containerHasElement(plot_var_names, "qp"))
940  {
941  int n_start = RhoQ3_comp;
942  int n_end = ncomp_cons - 1;
943  if (n_qstate > 3) n_start = RhoQ4_comp;
944  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,ncomp_cons);
945  MultiFab::Copy( mf[lev], Sm, n_start, mf_comp, 1, 0);
946  for (int n_comp(n_start+1); n_comp <= n_end; ++n_comp) {
947  MultiFab::Add( mf[lev], Sm, n_comp, mf_comp, 1, 0);
948  }
949  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
950  mf_comp += 1;
951  }
952 
953  if(containerHasElement(plot_var_names, "qrain") && (n_qstate >= 3))
954  {
955  int n_start = RhoQ3_comp;
956  if (n_qstate > 3) n_start = RhoQ4_comp;
957  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,ncomp_cons);
958  MultiFab::Copy( mf[lev], Sm, n_start , mf_comp, 1, 0);
959  MultiFab::Divide(mf[lev], Sm, Rho_comp, mf_comp, 1, 0);
960  mf_comp += 1;
961  }
962 
963  if(containerHasElement(plot_var_names, "qsnow") && (n_qstate >= 5))
964  {
965  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,RhoQ5_comp+1);
966  MultiFab::Copy( mf[lev], Sm, RhoQ5_comp, mf_comp, 1, 0);
967  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
968  mf_comp += 1;
969  }
970 
971  if(containerHasElement(plot_var_names, "qgraup") && (n_qstate >= 6))
972  {
973  MultiFab Sm(vars_new[lev][Vars::cons],make_alias,0,RhoQ6_comp+1);
974  MultiFab::Copy( mf[lev], Sm, RhoQ6_comp, mf_comp, 1, 0);
975  MultiFab::Divide(mf[lev], Sm, Rho_comp , mf_comp, 1, 0);
976  mf_comp += 1;
977  }
978 
980  if (containerHasElement(plot_var_names, "rain_accum"))
981  {
982  MultiFab rain_accum_mf(*(qmoist[lev][4]), make_alias, 0, 1);
983  MultiFab::Copy(mf[lev],rain_accum_mf,0,mf_comp,1,0);
984  mf_comp += 1;
985  }
986  }
988  {
989  if (containerHasElement(plot_var_names, "rain_accum"))
990  {
991  MultiFab rain_accum_mf(*(qmoist[lev][8]), make_alias, 0, 1);
992  MultiFab::Copy(mf[lev],rain_accum_mf,0,mf_comp,1,0);
993  mf_comp += 1;
994  }
995  if (containerHasElement(plot_var_names, "snow_accum"))
996  {
997  MultiFab snow_accum_mf(*(qmoist[lev][9]), make_alias, 0, 1);
998  MultiFab::Copy(mf[lev],snow_accum_mf,0,mf_comp,1,0);
999  mf_comp += 1;
1000  }
1001  if (containerHasElement(plot_var_names, "graup_accum"))
1002  {
1003  MultiFab graup_accum_mf(*(qmoist[lev][10]), make_alias, 0, 1);
1004  MultiFab::Copy(mf[lev],graup_accum_mf,0,mf_comp,1,0);
1005  mf_comp += 1;
1006  }
1007  }
1008  }
1009 
1010 #ifdef ERF_USE_PARTICLES
1011  const auto& particles_namelist( particleData.getNames() );
1012  for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++) {
1013  if (containerHasElement(plot_var_names, std::string(particles_namelist[i]+"_count"))) {
1014  MultiFab temp_dat(mf[lev].boxArray(), mf[lev].DistributionMap(), 1, 0);
1015  temp_dat.setVal(0);
1016  particleData[particles_namelist[i]]->Increment(temp_dat, lev);
1017  MultiFab::Copy(mf[lev], temp_dat, 0, mf_comp, 1, 0);
1018  mf_comp += 1;
1019  }
1020  }
1021 
1022  Vector<std::string> particle_mesh_plot_names(0);
1023  particleData.GetMeshPlotVarNames( particle_mesh_plot_names );
1024  for (int i = 0; i < particle_mesh_plot_names.size(); i++) {
1025  std::string plot_var_name(particle_mesh_plot_names[i]);
1026  if (containerHasElement(plot_var_names, plot_var_name) ) {
1027  MultiFab temp_dat(mf[lev].boxArray(), mf[lev].DistributionMap(), 1, 1);
1028  temp_dat.setVal(0);
1029  particleData.GetMeshPlotVar(plot_var_name, temp_dat, lev);
1030  MultiFab::Copy(mf[lev], temp_dat, 0, mf_comp, 1, 0);
1031  mf_comp += 1;
1032  }
1033  }
1034 #endif
1035 
1036 #ifdef ERF_USE_EB
1037  if (containerHasElement(plot_var_names, "volfrac")) {
1038  MultiFab::Copy(mf[lev], EBFactory(lev).getVolFrac(), 0, mf_comp, 1, 0);
1039  mf_comp += 1;
1040  }
1041 #endif
1042 
1043 #ifdef ERF_COMPUTE_ERROR
1044  // Next, check for error in velocities and if desired, output them -- note we output none or all, not just some
1045  if (containerHasElement(plot_var_names, "xvel_err") ||
1046  containerHasElement(plot_var_names, "yvel_err") ||
1047  containerHasElement(plot_var_names, "zvel_err"))
1048  {
1049  //
1050  // Moving terrain ANALYTICAL
1051  //
1052  Real H = geom[lev].ProbHi()[2];
1053  Real Ampl = 0.16;
1054  Real wavelength = 100.;
1055  Real kp = 2. * PI / wavelength;
1056  Real g = CONST_GRAV;
1057  Real omega = std::sqrt(g * kp);
1058  Real omega_t = omega * t_new[lev];
1059 
1060  const auto dx = geom[lev].CellSizeArray();
1061 
1062 #ifdef _OPENMP
1063 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
1064 #endif
1065  for (MFIter mfi(mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
1066  {
1067  const Box& bx = mfi.validbox();
1068  Box xbx(bx); xbx.surroundingNodes(0);
1069  const Array4<Real> xvel_arr = vars_new[lev][Vars::xvel].array(mfi);
1070  const Array4<Real> zvel_arr = vars_new[lev][Vars::zvel].array(mfi);
1071 
1072  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
1073 
1074  ParallelFor(xbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1075  {
1076  Real x = i * dx[0];
1077  Real z = 0.25 * (z_nd(i,j,k) + z_nd(i,j+1,k) + z_nd(i,j,k+1) + z_nd(i,j+1,k+1));
1078 
1079  Real z_base = Ampl * std::sin(kp * x - omega_t);
1080  z -= z_base;
1081 
1082  Real fac = std::cosh( kp * (z - H) ) / std::sinh(kp * H);
1083 
1084  xvel_arr(i,j,k) -= -Ampl * omega * fac * std::sin(kp * x - omega_t);
1085  });
1086 
1087  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1088  {
1089  Real x = (i + 0.5) * dx[0];
1090  Real z = 0.25 * ( z_nd(i,j,k) + z_nd(i+1,j,k) + z_nd(i,j+1,k) + z_nd(i+1,j+1,k));
1091 
1092  Real z_base = Ampl * std::sin(kp * x - omega_t);
1093  z -= z_base;
1094 
1095  Real fac = std::sinh( kp * (z - H) ) / std::sinh(kp * H);
1096 
1097  zvel_arr(i,j,k) -= Ampl * omega * fac * std::cos(kp * x - omega_t);
1098  });
1099  }
1100 
1101  MultiFab temp_mf(mf[lev].boxArray(), mf[lev].DistributionMap(), AMREX_SPACEDIM, 0);
1102  average_face_to_cellcenter(temp_mf,0,
1103  Array<const MultiFab*,3>{&vars_new[lev][Vars::xvel],&vars_new[lev][Vars::yvel],&vars_new[lev][Vars::zvel]});
1104 
1105  if (containerHasElement(plot_var_names, "xvel_err")) {
1106  MultiFab::Copy(mf[lev],temp_mf,0,mf_comp,1,0);
1107  mf_comp += 1;
1108  }
1109  if (containerHasElement(plot_var_names, "yvel_err")) {
1110  MultiFab::Copy(mf[lev],temp_mf,1,mf_comp,1,0);
1111  mf_comp += 1;
1112  }
1113  if (containerHasElement(plot_var_names, "zvel_err")) {
1114  MultiFab::Copy(mf[lev],temp_mf,2,mf_comp,1,0);
1115  mf_comp += 1;
1116  }
1117 
1118  // Now restore the velocities to what they were
1119 #ifdef _OPENMP
1120 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
1121 #endif
1122  for (MFIter mfi(mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
1123  {
1124  const Box& bx = mfi.validbox();
1125  Box xbx(bx); xbx.surroundingNodes(0);
1126 
1127  const Array4<Real> xvel_arr = vars_new[lev][Vars::xvel].array(mfi);
1128  const Array4<Real> zvel_arr = vars_new[lev][Vars::zvel].array(mfi);
1129 
1130  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
1131 
1132  ParallelFor(xbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1133  {
1134  Real x = i * dx[0];
1135  Real z = 0.25 * (z_nd(i,j,k) + z_nd(i,j+1,k) + z_nd(i,j,k+1) + z_nd(i,j+1,k+1));
1136  Real z_base = Ampl * std::sin(kp * x - omega_t);
1137 
1138  z -= z_base;
1139 
1140  Real fac = std::cosh( kp * (z - H) ) / std::sinh(kp * H);
1141  xvel_arr(i,j,k) += -Ampl * omega * fac * std::sin(kp * x - omega_t);
1142  });
1143  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1144  {
1145  Real x = (i + 0.5) * dx[0];
1146  Real z = 0.25 * ( z_nd(i,j,k) + z_nd(i+1,j,k) + z_nd(i,j+1,k) + z_nd(i+1,j+1,k));
1147  Real z_base = Ampl * std::sin(kp * x - omega_t);
1148 
1149  z -= z_base;
1150  Real fac = std::sinh( kp * (z - H) ) / std::sinh(kp * H);
1151 
1152  zvel_arr(i,j,k) += Ampl * omega * fac * std::cos(kp * x - omega_t);
1153  });
1154  }
1155  } // end xvel_err, yvel_err, zvel_err
1156 
1157  if (containerHasElement(plot_var_names, "pp_err"))
1158  {
1159  // Moving terrain ANALYTICAL
1160 #ifdef _OPENMP
1161 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
1162 #endif
1163  for ( MFIter mfi(mf[lev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
1164  {
1165  const Box& bx = mfi.tilebox();
1166  const Array4<Real>& derdat = mf[lev].array(mfi);
1167  const Array4<Real const>& p0_arr = p_hse.const_array(mfi);
1168  const Array4<Real const>& S_arr = vars_new[lev][Vars::cons].const_array(mfi);
1169 
1170  const auto dx = geom[lev].CellSizeArray();
1171  const Array4<Real const>& z_nd = z_phys_nd[lev]->const_array(mfi);
1172  const Array4<Real const>& r0_arr = r_hse.const_array(mfi);
1173 
1174  Real H = geom[lev].ProbHi()[2];
1175  Real Ampl = 0.16;
1176  Real wavelength = 100.;
1177  Real kp = 2. * PI / wavelength;
1178  Real g = CONST_GRAV;
1179  Real omega = std::sqrt(g * kp);
1180  Real omega_t = omega * t_new[lev];
1181 
1182  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
1183  {
1184  const Real rhotheta = S_arr(i,j,k,RhoTheta_comp);
1185  derdat(i, j, k, mf_comp) = getPgivenRTh(rhotheta) - p0_arr(i,j,k);
1186 
1187  Real rho_hse = r0_arr(i,j,k);
1188 
1189  Real x = (i + 0.5) * dx[0];
1190  Real z = 0.125 * ( z_nd(i,j,k ) + z_nd(i+1,j,k ) + z_nd(i,j+1,k ) + z_nd(i+1,j+1,k )
1191  +z_nd(i,j,k+1) + z_nd(i+1,j,k+1) + z_nd(i,j+1,k+1) + z_nd(i+1,j+1,k+1) );
1192  Real z_base = Ampl * std::sin(kp * x - omega_t);
1193 
1194  z -= z_base;
1195  Real fac = std::cosh( kp * (z - H) ) / std::sinh(kp * H);
1196  Real pprime_exact = -(Ampl * omega * omega / kp) * fac *
1197  std::sin(kp * x - omega_t) * r0_arr(i,j,k);
1198 
1199  derdat(i,j,k,mf_comp) -= pprime_exact;
1200  });
1201  }
1202  mf_comp += 1;
1203  }
1204 #endif
1205  }
1206 
1207 #ifdef EB_USE_EB
1208  for (int lev = 0; lev <= finest_level; ++lev) {
1209  EB_set_covered(mf[lev], 0.0);
1210  }
1211 #endif
1212 
1213  // Fill terrain distortion MF
1214  if (solverChoice.use_terrain) {
1215  for (int lev(0); lev <= finest_level; ++lev) {
1216  MultiFab::Copy(mf_nd[lev],*z_phys_nd[lev],0,2,1,0);
1217  Real dz = Geom()[lev].CellSizeArray()[2];
1218  for (MFIter mfi(mf_nd[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
1219  const Box& bx = mfi.tilebox();
1220  Array4< Real> mf_arr = mf_nd[lev].array(mfi);
1221  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
1222  mf_arr(i,j,k,2) -= k * dz;
1223  });
1224  }
1225  }
1226  }
1227 
1228  std::string plotfilename;
1229  if (which == 1)
1230  plotfilename = Concatenate(plot_file_1, istep[0], 5);
1231  else if (which == 2)
1232  plotfilename = Concatenate(plot_file_2, istep[0], 5);
1233 
1234  // LSM writes it's own data
1235  if (which==1 && plot_lsm) {
1236  lsm.Plot_Lsm_Data(t_new[0], istep, refRatio());
1237  }
1238 
1239  if (finest_level == 0)
1240  {
1241  if (plotfile_type == "amrex") {
1242  Print() << "Writing native plotfile " << plotfilename << "\n";
1243  if (solverChoice.use_terrain) {
1244  WriteMultiLevelPlotfileWithTerrain(plotfilename, finest_level+1,
1245  GetVecOfConstPtrs(mf),
1246  GetVecOfConstPtrs(mf_nd),
1247  varnames,
1248  t_new[0], istep);
1249  } else {
1250  WriteMultiLevelPlotfile(plotfilename, finest_level+1,
1251  GetVecOfConstPtrs(mf),
1252  varnames,
1253  Geom(), t_new[0], istep, refRatio());
1254  }
1255  writeJobInfo(plotfilename);
1256 
1257 #ifdef ERF_USE_PARTICLES
1258  particleData.Checkpoint(plotfilename);
1259 #endif
1260 #ifdef ERF_USE_HDF5
1261  } else if (plotfile_type == "hdf5" || plotfile_type == "HDF5") {
1262  Print() << "Writing plotfile " << plotfilename+"d01.h5" << "\n";
1263  WriteMultiLevelPlotfileHDF5(plotfilename, finest_level+1,
1264  GetVecOfConstPtrs(mf),
1265  varnames,
1266  Geom(), t_new[0], istep, refRatio());
1267 #endif
1268 #ifdef ERF_USE_NETCDF
1269  } else if (plotfile_type == "netcdf" || plotfile_type == "NetCDF") {
1270  int lev = 0;
1271  int l_which = 0;
1272  writeNCPlotFile(lev, l_which, plotfilename, GetVecOfConstPtrs(mf), varnames, istep, t_new[0]);
1273 #endif
1274  } else {
1275  Print() << "User specified plot_filetype = " << plotfile_type << std::endl;
1276  Abort("Dont know this plot_filetype");
1277  }
1278 
1279  } else { // multilevel
1280 
1281  Vector<IntVect> r2(finest_level);
1282  Vector<Geometry> g2(finest_level+1);
1283  Vector<MultiFab> mf2(finest_level+1);
1284 
1285  mf2[0].define(grids[0], dmap[0], ncomp_mf, 0);
1286 
1287  // Copy level 0 as is
1288  MultiFab::Copy(mf2[0],mf[0],0,0,mf[0].nComp(),0);
1289 
1290  // Define a new multi-level array of Geometry's so that we pass the new "domain" at lev > 0
1291  Array<int,AMREX_SPACEDIM> periodicity =
1292  {Geom()[0].isPeriodic(0),Geom()[0].isPeriodic(1),Geom()[0].isPeriodic(2)};
1293  g2[0].define(Geom()[0].Domain(),&(Geom()[0].ProbDomain()),0,periodicity.data());
1294 
1295  if (plotfile_type == "amrex") {
1296  r2[0] = IntVect(1,1,ref_ratio[0][0]);
1297  for (int lev = 1; lev <= finest_level; ++lev) {
1298  if (lev > 1) {
1299  r2[lev-1][0] = 1;
1300  r2[lev-1][1] = 1;
1301  r2[lev-1][2] = r2[lev-2][2] * ref_ratio[lev-1][0];
1302  }
1303 
1304  mf2[lev].define(refine(grids[lev],r2[lev-1]), dmap[lev], ncomp_mf, 0);
1305 
1306  // Set the new problem domain
1307  Box d2(Geom()[lev].Domain());
1308  d2.refine(r2[lev-1]);
1309 
1310  g2[lev].define(d2,&(Geom()[lev].ProbDomain()),0,periodicity.data());
1311  }
1312 
1313  // Do piecewise interpolation of mf into mf2
1314  for (int lev = 1; lev <= finest_level; ++lev) {
1315  Interpolater* mapper_c = &pc_interp;
1316  InterpFromCoarseLevel(mf2[lev], t_new[lev], mf[lev],
1317  0, 0, ncomp_mf,
1318  geom[lev], g2[lev],
1320  r2[lev-1], mapper_c, domain_bcs_type, 0);
1321  }
1322 
1323  // Define an effective ref_ratio which is isotropic to be passed into WriteMultiLevelPlotfile
1324  Vector<IntVect> rr(finest_level);
1325  for (int lev = 0; lev < finest_level; ++lev) {
1326  rr[lev] = IntVect(ref_ratio[lev][0],ref_ratio[lev][1],ref_ratio[lev][0]);
1327  }
1328 
1329  Print() << "Writing plotfile " << plotfilename << "\n";
1330  if (solverChoice.use_terrain) {
1331  WriteMultiLevelPlotfileWithTerrain(plotfilename, finest_level+1,
1332  GetVecOfConstPtrs(mf),
1333  GetVecOfConstPtrs(mf_nd),
1334  varnames,
1335  t_new[0], istep);
1336  } else {
1337  WriteMultiLevelPlotfile(plotfilename, finest_level+1,
1338  GetVecOfConstPtrs(mf2), varnames,
1339  g2, t_new[0], istep, rr);
1340  }
1341 
1342  writeJobInfo(plotfilename);
1343 
1344 #ifdef ERF_USE_PARTICLES
1345  particleData.Checkpoint(plotfilename);
1346 #endif
1347 #ifdef ERF_USE_NETCDF
1348  } else if (plotfile_type == "netcdf" || plotfile_type == "NetCDF") {
1349  for (int lev = 0; lev <= finest_level; ++lev) {
1350  for (int which_box = 0; which_box < num_boxes_at_level[lev]; which_box++) {
1351  writeNCPlotFile(lev, which_box, plotfilename, GetVecOfConstPtrs(mf), varnames, istep, t_new[0]);
1352  }
1353  }
1354 #endif
1355  }
1356  } // end multi-level
1357 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=0.0)
Definition: EOS.H:29
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:12
constexpr amrex::Real PI
Definition: ERF_Constants.H:6
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:21
constexpr amrex::Real Cp_l
Definition: ERF_Constants.H:14
constexpr amrex::Real R_d
Definition: ERF_Constants.H:10
constexpr amrex::Real L_v
Definition: ERF_Constants.H:16
#define RhoQ6_comp
Definition: IndexDefines.H:22
#define RhoQ5_comp
Definition: IndexDefines.H:21
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_esatw(amrex::Real t)
Definition: Microphysics_Utils.H:44
PhysBCFunctNoOp null_bc_for_fill
Definition: Plotfile.cpp:10
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: TerrainMetrics.H:93
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: TerrainMetrics.H:79
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtJface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: TerrainMetrics.H:122
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtJface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: TerrainMetrics.H:150
void FillBdyCCVels(amrex::Vector< amrex::MultiFab > &mf_cc_vel)
Definition: ERF_FillPatch.cpp:548
static amrex::Vector< std::string > PlotFileVarNames(amrex::Vector< std::string > plot_var_names)
Definition: Plotfile.cpp:142
void WriteMultiLevelPlotfileWithTerrain(const std::string &plotfilename, int nlevels, const amrex::Vector< const amrex::MultiFab * > &mf, const amrex::Vector< const amrex::MultiFab * > &mf_nd, const amrex::Vector< std::string > &varnames, amrex::Real time, const amrex::Vector< int > &level_steps, const std::string &versionName="HyperCLaw-V1.1", const std::string &levelPrefix="Level_", const std::string &mfPrefix="Cell", const amrex::Vector< std::string > &extra_dirs=amrex::Vector< std::string >()) const
Definition: Plotfile.cpp:1360
void writeJobInfo(const std::string &dir) const
Definition: writeJobInfo.cpp:9
void Plot_Lsm_Data(amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &ref_ratio)
Definition: LandSurface.H:80
@ Theta_v
Definition: IndexDefines.H:128
@ Mom_h
Definition: IndexDefines.H:121
@ Mom_v
Definition: IndexDefines.H:127
@ PBL_lengthscale
Definition: IndexDefines.H:133
@ Theta_h
Definition: IndexDefines.H:122
@ omega
Definition: SAM.H:49
void erf_dervortx(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Geometry &geomdata, amrex::Real, const int *, const int)
Definition: Derive.cpp:198
void erf_dervorty(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Geometry &geomdata, amrex::Real, const int *, const int)
Definition: Derive.cpp:226
void erf_dermagvel(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Geometry &, amrex::Real, const int *, const int)
Definition: Derive.cpp:282
void erf_dernull(const Box &, FArrayBox &, int, int, const FArrayBox &, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:39
void erf_dervortz(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Geometry &geomdata, amrex::Real, const int *, const int)
Definition: Derive.cpp:254
void erf_dertemp(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:91
void erf_derKE(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:163
void erf_derQKE(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:184
void erf_dersoundspeed(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: Derive.cpp:58
Here is the call graph for this function:

Member Data Documentation

◆ advflux_reg

amrex::Vector<amrex::YAFluxRegister*> ERF::advflux_reg
private

Referenced by getAdvFluxReg().

◆ ax

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::ax
private

◆ ax_new

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::ax_new
private

◆ ax_src

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::ax_src
private

◆ ay

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::ay
private

◆ ay_new

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::ay_new
private

◆ ay_src

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::ay_src
private

◆ az

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::az
private

◆ az_new

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::az_new
private

◆ az_src

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::az_src
private

◆ base_state

amrex::Vector<amrex::MultiFab> ERF::base_state
private

◆ base_state_new

amrex::Vector<amrex::MultiFab> ERF::base_state_new
private

◆ bndry_output_planes_interval

int ERF::bndry_output_planes_interval = -1
staticprivate

◆ bndry_output_planes_per

Real ERF::bndry_output_planes_per = -1.0
staticprivate

◆ bndry_output_planes_start_time

Real ERF::bndry_output_planes_start_time = 0.0
staticprivate

◆ boxes_at_level

amrex::Vector<amrex::Vector<amrex::Box> > ERF::boxes_at_level
private

◆ cc_profiles

bool ERF::cc_profiles = true
private

◆ cf_set_width

int ERF::cf_set_width {0}
private

◆ cf_width

int ERF::cf_width {0}
private

◆ cfl

Real ERF::cfl = 0.8
staticprivate

◆ change_max

Real ERF::change_max = 1.1
staticprivate

◆ check_file

std::string ERF::check_file {"chk"}
private

◆ check_type

std::string ERF::check_type {"native"}
private

◆ column_file_name

std::string ERF::column_file_name = "column_data.nc"
staticprivate

◆ column_interval

int ERF::column_interval = -1
staticprivate

◆ column_loc_x

Real ERF::column_loc_x = 0.0
staticprivate

◆ column_loc_y

Real ERF::column_loc_y = 0.0
staticprivate

◆ column_per

Real ERF::column_per = -1.0
staticprivate

◆ cons_names

const amrex::Vector<std::string> ERF::cons_names
private
Initial value:
{"density", "rhotheta", "rhoKE", "rhoQKE", "rhoadv_0",
"rhoQ1", "rhoQ2", "rhoQ3",
"rhoQ4", "rhoQ5", "rhoQ6"}

◆ d_havg_density

amrex::Gpu::DeviceVector<amrex::Real> ERF::d_havg_density
private

◆ d_havg_pressure

amrex::Gpu::DeviceVector<amrex::Real> ERF::d_havg_pressure
private

◆ d_havg_qc

amrex::Gpu::DeviceVector<amrex::Real> ERF::d_havg_qc
private

◆ d_havg_qv

amrex::Gpu::DeviceVector<amrex::Real> ERF::d_havg_qv
private

◆ d_havg_temperature

amrex::Gpu::DeviceVector<amrex::Real> ERF::d_havg_temperature
private

◆ d_rayleigh_ptrs

amrex::Vector<amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > > ERF::d_rayleigh_ptrs
private

◆ d_rhoqt_src

amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > ERF::d_rhoqt_src
private

◆ d_rhotheta_src

amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > ERF::d_rhotheta_src
private

◆ d_sponge_ptrs

amrex::Vector<amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > > ERF::d_sponge_ptrs
private

◆ d_u_geos

amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > ERF::d_u_geos
private

◆ d_v_geos

amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > ERF::d_v_geos
private

◆ d_w_subsid

amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real> > ERF::d_w_subsid
private

◆ datalog

amrex::Vector<std::unique_ptr<std::fstream> > ERF::datalog
private

◆ datalogname

amrex::Vector<std::string> ERF::datalogname
private

Referenced by DataLogName().

◆ derived_names

const amrex::Vector<std::string> ERF::derived_names
private
Initial value:
{"soundspeed", "temp", "theta", "KE", "QKE", "scalar",
"vorticity_x","vorticity_y","vorticity_z",
"magvel", "divU",
"pres_hse", "dens_hse", "pressure", "pert_pres", "pert_dens", "eq_pot_temp", "num_turb",
"dpdx", "dpdy", "pres_hse_x", "pres_hse_y",
"z_phys", "detJ" , "mapfac", "lat_m", "lon_m",
"u_t_avg", "v_t_avg", "w_t_avg", "umag_t_avg",
"Kmv","Kmh",
"Khv","Khh",
"Lpbl",
"qt", "qv", "qc", "qi", "qp", "qrain", "qsnow", "qgraup", "rain_accum", "snow_accum", "graup_accum"
}

◆ detJ_cc

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::detJ_cc
private

◆ detJ_cc_new

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::detJ_cc_new
private

◆ detJ_cc_src

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::detJ_cc_src
private

◆ domain_bc_type

amrex::Array<std::string,2*AMREX_SPACEDIM> ERF::domain_bc_type
private

◆ domain_bcs_type

amrex::Vector<amrex::BCRec> ERF::domain_bcs_type
private

◆ domain_bcs_type_d

amrex::Gpu::DeviceVector<amrex::BCRec> ERF::domain_bcs_type_d
private

◆ dt

amrex::Vector<amrex::Real> ERF::dt
private

◆ dt_mri_ratio

amrex::Vector<long> ERF::dt_mri_ratio
private

◆ dz_min

amrex::Real ERF::dz_min
private

◆ eddyDiffs_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::eddyDiffs_lev
private

◆ fine_mask

amrex::MultiFab ERF::fine_mask
private

◆ fixed_dt

Real ERF::fixed_dt = -1.0
staticprivate

◆ fixed_fast_dt

Real ERF::fixed_fast_dt = -1.0
staticprivate

◆ fixed_mri_dt_ratio

int ERF::fixed_mri_dt_ratio = 0
staticprivate

◆ FPr_c

amrex::Vector<ERFFillPatcher> ERF::FPr_c
private

◆ FPr_u

amrex::Vector<ERFFillPatcher> ERF::FPr_u
private

◆ FPr_v

amrex::Vector<ERFFillPatcher> ERF::FPr_v
private

◆ FPr_w

amrex::Vector<ERFFillPatcher> ERF::FPr_w
private

◆ h_havg_density

amrex::Vector<amrex::Real> ERF::h_havg_density
private

◆ h_havg_pressure

amrex::Vector<amrex::Real> ERF::h_havg_pressure
private

◆ h_havg_qc

amrex::Vector<amrex::Real> ERF::h_havg_qc
private

◆ h_havg_qv

amrex::Vector<amrex::Real> ERF::h_havg_qv
private

◆ h_havg_temperature

amrex::Vector<amrex::Real> ERF::h_havg_temperature
private

◆ h_rayleigh_ptrs

amrex::Vector<amrex::Vector< amrex::Vector<amrex::Real> > > ERF::h_rayleigh_ptrs
private

◆ h_rhoqt_src

amrex::Vector< amrex::Vector<amrex::Real> > ERF::h_rhoqt_src
private

◆ h_rhotheta_src

amrex::Vector< amrex::Vector<amrex::Real> > ERF::h_rhotheta_src
private

◆ h_sponge_ptrs

amrex::Vector<amrex::Vector< amrex::Vector<amrex::Real> > > ERF::h_sponge_ptrs
private

◆ h_u_geos

amrex::Vector< amrex::Vector<amrex::Real> > ERF::h_u_geos
private

◆ h_v_geos

amrex::Vector< amrex::Vector<amrex::Real> > ERF::h_v_geos
private

◆ h_w_subsid

amrex::Vector< amrex::Vector<amrex::Real> > ERF::h_w_subsid
private

◆ hub_height

amrex::Real ERF::hub_height
private

◆ init_shrink

Real ERF::init_shrink = 1.0
staticprivate

◆ init_sounding_ideal

bool ERF::init_sounding_ideal = false
staticprivate

◆ init_type

std::string ERF::init_type
staticprivate

◆ input_bndry_planes

int ERF::input_bndry_planes = 0
staticprivate

◆ input_sounding_data

InputSoundingData ERF::input_sounding_data
private

◆ input_sounding_file

std::string ERF::input_sounding_file = "input_sounding"
staticprivate

◆ input_sponge_data

InputSpongeData ERF::input_sponge_data
private

◆ input_sponge_file

std::string ERF::input_sponge_file = "input_sponge_file.txt"
staticprivate

◆ istep

amrex::Vector<int> ERF::istep
private

◆ last_check_file_step

int ERF::last_check_file_step
private

◆ last_plot_file_step_1

int ERF::last_plot_file_step_1
private

◆ last_plot_file_step_2

int ERF::last_plot_file_step_2
private

◆ lmask_lev

amrex::Vector<amrex::Vector<std::unique_ptr<amrex::iMultiFab> > > ERF::lmask_lev
private

◆ lsm

LandSurface ERF::lsm
private

◆ lsm_data

amrex::Vector<amrex::Vector<amrex::MultiFab*> > ERF::lsm_data
private

◆ lsm_flux

amrex::Vector<amrex::Vector<amrex::MultiFab*> > ERF::lsm_flux
private

◆ m_bc_extdir_vals

amrex::Array<amrex::Array<amrex::Real, AMREX_SPACEDIM*2>, AMREX_SPACEDIM+NVAR_max> ERF::m_bc_extdir_vals
private

◆ m_bc_neumann_vals

amrex::Array<amrex::Array<amrex::Real, AMREX_SPACEDIM*2>, AMREX_SPACEDIM+NVAR_max> ERF::m_bc_neumann_vals
private

◆ m_check_int

int ERF::m_check_int = -1
private

◆ m_check_per

amrex::Real ERF::m_check_per = -1.0
private

◆ m_factory

amrex::Vector<std::unique_ptr<amrex::FabFactory<amrex::FArrayBox> > > ERF::m_factory
private

Referenced by Factory().

◆ m_most

std::unique_ptr<ABLMost> ERF::m_most = nullptr
private

◆ m_plot_int_1

int ERF::m_plot_int_1 = -1
private

◆ m_plot_int_2

int ERF::m_plot_int_2 = -1
private

◆ m_plot_per_1

amrex::Real ERF::m_plot_per_1 = -1.0
private

◆ m_plot_per_2

amrex::Real ERF::m_plot_per_2 = -1.0
private

◆ m_r2d

std::unique_ptr<ReadBndryPlanes> ERF::m_r2d = nullptr
private

◆ m_w2d

std::unique_ptr<WriteBndryPlanes> ERF::m_w2d = nullptr
private

◆ mapfac_m

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::mapfac_m
private

◆ mapfac_u

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::mapfac_u
private

◆ mapfac_v

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::mapfac_v
private

◆ max_k_at_level

amrex::Vector<int> ERF::max_k_at_level
private

◆ max_step

int ERF::max_step = std::numeric_limits<int>::max()
private

◆ micro

std::unique_ptr<Microphysics> ERF::micro
private

◆ min_k_at_level

amrex::Vector<int> ERF::min_k_at_level
private

◆ mri_integrator_mem

amrex::Vector<std::unique_ptr<MRISplitIntegrator<amrex::Vector<amrex::MultiFab> > > > ERF::mri_integrator_mem
private

◆ nc_bdy_file

std::string ERF::nc_bdy_file
staticprivate

◆ nc_init_file

Vector< Vector< std::string > > ERF::nc_init_file = {{""}}
staticprivate

◆ ng_dens_hse

int ERF::ng_dens_hse
staticprivate

◆ ng_pres_hse

int ERF::ng_pres_hse
staticprivate

◆ nominal_power

amrex::Real ERF::nominal_power
private

◆ nsubsteps

amrex::Vector<int> ERF::nsubsteps
private

◆ Nturb

amrex::Vector<amrex::MultiFab> ERF::Nturb
private

◆ num_boxes_at_level

amrex::Vector<int> ERF::num_boxes_at_level
private

◆ num_files_at_level

amrex::Vector<int> ERF::num_files_at_level
private

◆ output_1d_column

int ERF::output_1d_column = 0
staticprivate

◆ output_bndry_planes

int ERF::output_bndry_planes = 0
staticprivate

◆ phys_bc_type

amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2> ERF::phys_bc_type
private

◆ physbcs_cons

amrex::Vector<std::unique_ptr<ERFPhysBCFunct_cons> > ERF::physbcs_cons
private

◆ physbcs_u

amrex::Vector<std::unique_ptr<ERFPhysBCFunct_u> > ERF::physbcs_u
private

◆ physbcs_v

amrex::Vector<std::unique_ptr<ERFPhysBCFunct_v> > ERF::physbcs_v
private

◆ physbcs_w

amrex::Vector<std::unique_ptr<ERFPhysBCFunct_w> > ERF::physbcs_w
private

◆ physbcs_w_no_terrain

amrex::Vector<std::unique_ptr<ERFPhysBCFunct_w_no_terrain> > ERF::physbcs_w_no_terrain
private

◆ plot_file_1

std::string ERF::plot_file_1 {"plt_1_"}
private

◆ plot_file_2

std::string ERF::plot_file_2 {"plt_2_"}
private

◆ plot_file_on_restart

int ERF::plot_file_on_restart = 1
private

◆ plot_lsm

bool ERF::plot_lsm = false
private

◆ plot_var_names_1

amrex::Vector<std::string> ERF::plot_var_names_1
private

◆ plot_var_names_2

amrex::Vector<std::string> ERF::plot_var_names_2
private

◆ plotfile_type

std::string ERF::plotfile_type = "amrex"
staticprivate

◆ power

amrex::Vector<amrex::Real> ERF::power
private

◆ pp_prefix

std::string ERF::pp_prefix {"erf"}

◆ previousCPUTimeUsed

Real ERF::previousCPUTimeUsed = 0.0
staticprivate

Referenced by getCPUTime().

◆ prob

std::unique_ptr<ProblemBase> ERF::prob = nullptr
private

◆ profile_int

int ERF::profile_int = -1
private

◆ qmoist

amrex::Vector<amrex::Vector<amrex::MultiFab*> > ERF::qmoist
private

◆ Qv_prim

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Qv_prim
private

◆ real_set_width

int ERF::real_set_width {0}
private

◆ real_width

int ERF::real_width {0}
private

◆ ref_tags

Vector< AMRErrorTag > ERF::ref_tags
staticprivate

◆ regrid_int

int ERF::regrid_int = -1
private

◆ restart_chkfile

std::string ERF::restart_chkfile = ""
private

◆ restart_type

std::string ERF::restart_type {"native"}
private

◆ rotor_dia

amrex::Real ERF::rotor_dia
private

◆ rU_new

amrex::Vector<amrex::MultiFab> ERF::rU_new
private

◆ rU_old

amrex::Vector<amrex::MultiFab> ERF::rU_old
private

◆ rV_new

amrex::Vector<amrex::MultiFab> ERF::rV_new
private

◆ rV_old

amrex::Vector<amrex::MultiFab> ERF::rV_old
private

◆ rW_new

amrex::Vector<amrex::MultiFab> ERF::rW_new
private

◆ rW_old

amrex::Vector<amrex::MultiFab> ERF::rW_old
private

◆ sampleline

amrex::Vector<amrex::IntVect> ERF::sampleline
private

Referenced by NumSampleLines(), and SampleLine().

◆ samplelinelog

amrex::Vector<std::unique_ptr<std::fstream> > ERF::samplelinelog
private

◆ samplelinelogname

amrex::Vector<std::string> ERF::samplelinelogname
private

Referenced by SampleLineLogName().

◆ samplepoint

amrex::Vector<amrex::IntVect> ERF::samplepoint
private

Referenced by NumSamplePoints(), and SamplePoint().

◆ sampleptlog

amrex::Vector<std::unique_ptr<std::fstream> > ERF::sampleptlog
private

◆ sampleptlogname

amrex::Vector<std::string> ERF::sampleptlogname
private

Referenced by SamplePointLogName().

◆ SFS_diss_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::SFS_diss_lev
private

◆ SFS_hfx1_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::SFS_hfx1_lev
private

◆ SFS_hfx2_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::SFS_hfx2_lev
private

◆ SFS_hfx3_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::SFS_hfx3_lev
private

◆ SmnSmn_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::SmnSmn_lev
private

◆ solverChoice

SolverChoice ERF::solverChoice
staticprivate

◆ sponge_type

std::string ERF::sponge_type
staticprivate

◆ sst_lev

amrex::Vector<amrex::Vector<std::unique_ptr<amrex::MultiFab> > > ERF::sst_lev
private

◆ start_time

amrex::Real ERF::start_time = 0.0
private

◆ startCPUTime

Real ERF::startCPUTime = 0.0
staticprivate

Referenced by getCPUTime().

◆ stop_time

amrex::Real ERF::stop_time = std::numeric_limits<amrex::Real>::max()
private

◆ sum_interval

int ERF::sum_interval = -1
staticprivate

◆ sum_per

Real ERF::sum_per = -1.0
staticprivate

◆ t_avg_cnt

amrex::Vector<amrex::Real> ERF::t_avg_cnt
private

◆ t_new

amrex::Vector<amrex::Real> ERF::t_new
private

◆ t_old

amrex::Vector<amrex::Real> ERF::t_old
private

◆ Tau11_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau11_lev
private

◆ Tau12_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau12_lev
private

◆ Tau13_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau13_lev
private

◆ Tau21_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau21_lev
private

◆ Tau22_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau22_lev
private

◆ Tau23_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau23_lev
private

◆ Tau31_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau31_lev
private

◆ Tau32_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau32_lev
private

◆ Tau33_lev

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Tau33_lev
private

◆ Theta_prim

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::Theta_prim
private

◆ thin_xforce

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::thin_xforce
private

◆ thin_yforce

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::thin_yforce
private

◆ thin_zforce

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::thin_zforce
private

◆ thrust_coeff

amrex::Vector<amrex::Real> ERF::thrust_coeff
private

◆ thrust_coeff_standing

amrex::Real ERF::thrust_coeff_standing
private

◆ use_real_bcs

bool ERF::use_real_bcs
staticprivate

◆ vars_ewp

amrex::Vector<amrex::MultiFab> ERF::vars_ewp
private

◆ vars_fitch

amrex::Vector<amrex::MultiFab> ERF::vars_fitch
private

◆ vars_new

amrex::Vector<amrex::Vector<amrex::MultiFab> > ERF::vars_new
private

◆ vars_old

amrex::Vector<amrex::Vector<amrex::MultiFab> > ERF::vars_old
private

◆ vel_t_avg

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::vel_t_avg
private

◆ verbose

int ERF::verbose = 0
staticprivate

◆ wind_speed

amrex::Vector<amrex::Real> ERF::wind_speed
private

◆ xflux_imask

amrex::Vector<std::unique_ptr<amrex::iMultiFab> > ERF::xflux_imask
private

◆ yflux_imask

amrex::Vector<std::unique_ptr<amrex::iMultiFab> > ERF::yflux_imask
private

◆ z_phys_cc

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::z_phys_cc
private

◆ z_phys_nd

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::z_phys_nd
private

◆ z_phys_nd_new

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::z_phys_nd_new
private

◆ z_phys_nd_src

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::z_phys_nd_src
private

◆ z_t_rk

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ERF::z_t_rk
private

◆ zflux_imask

amrex::Vector<std::unique_ptr<amrex::iMultiFab> > ERF::zflux_imask
private

◆ zlevels_stag

amrex::Vector<amrex::Real> ERF::zlevels_stag
private

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