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
 
void ERF_shared ()
 
 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 InitData_pre ()
 
void InitData_post ()
 
void compute_divergence (int lev, amrex::MultiFab &rhs, amrex::Vector< amrex::MultiFab > &mom_mf, amrex::Geometry const &geom_at_lev)
 
void project_velocities (int lev, amrex::Real dt, amrex::Vector< amrex::MultiFab > &vars, amrex::MultiFab &p)
 
void project_velocities_tb (int lev, amrex::Real dt, amrex::Vector< amrex::MultiFab > &vars, amrex::MultiFab &p)
 
void solve_with_gmres (int lev, amrex::Vector< amrex::MultiFab > &rhs, amrex::Vector< amrex::MultiFab > &p, amrex::Vector< amrex::Array< amrex::MultiFab, AMREX_SPACEDIM >> &fluxes)
 
void solve_with_mlmg (int lev, amrex::Vector< amrex::MultiFab > &rhs, amrex::Vector< amrex::MultiFab > &p, amrex::Vector< amrex::Array< amrex::MultiFab, AMREX_SPACEDIM >> &fluxes)
 
amrex::Array< amrex::LinOpBCType, AMREX_SPACEDIM > get_projection_bc (amrex::Orientation::Side side) const noexcept
 
bool projection_has_dirichlet (amrex::Array< amrex::LinOpBCType, AMREX_SPACEDIM > bcs) const
 
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)
 
amrex::Real cloud_fraction (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::Real time, 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_Kmv, amrex::Gpu::HostVector< amrex::Real > &h_avg_Khv, 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_qi, amrex::Gpu::HostVector< amrex::Real > &h_avg_qs, amrex::Gpu::HostVector< amrex::Real > &h_avg_qg, 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, amrex::Gpu::HostVector< amrex::Real > &h_avg_wthv)
 
void derive_diag_profiles_stag (amrex::Real time, 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_Kmv, amrex::Gpu::HostVector< amrex::Real > &h_avg_Khv, 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_qi, amrex::Gpu::HostVector< amrex::Real > &h_avg_qs, amrex::Gpu::HostVector< amrex::Real > &h_avg_qg, 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, amrex::Gpu::HostVector< amrex::Real > &h_avg_wthv)
 
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_q1fx3, amrex::Gpu::HostVector< amrex::Real > &h_avg_q2fx3, 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_q1fx3, amrex::Gpu::HostVector< amrex::Real > &h_avg_q2fx3, 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, PlotFileType plotfile_type, 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, const amrex::Vector< amrex::Geometry > &my_geom, amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &my_ref_ratio, 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, const amrex::Vector< amrex::Geometry > &my_geom, amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &my_ref_ratio, 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, amrex::MultiFab &th, 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 init_immersed_body (int lev, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm)
 
void fill_from_bndryregs (const amrex::Vector< amrex::MultiFab * > &mfs, amrex::Real time)
 
void AverageDownTo (int crse_lev, int scomp, int ncomp)
 
void WriteCheckpointFile () const
 
void ReadCheckpointFile ()
 
void ReadCheckpointFileMOST ()
 
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 ParameterSanityChecks ()
 
void AverageDown ()
 
void update_diffusive_arrays (int lev, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm)
 
void init_zphys (int lev, amrex::Real time)
 
void remake_zphys (int lev, std::unique_ptr< amrex::MultiFab > &temp_zphys_nd)
 
void update_terrain_arrays (int lev)
 
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, amrex::MultiFab &tmp_base_state, std::unique_ptr< amrex::MultiFab > &tmp_zphys_nd)
 
void turbPert_update (const int lev, const amrex::Real dt)
 
void turbPert_amplitude (const int lev)
 
void initialize_integrator (int lev, amrex::MultiFab &cons_mf, amrex::MultiFab &vel_mf)
 
void make_physbcs (int lev)
 
void initializeMicrophysics (const int &)
 
void FillPatch (int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, bool cons_only=false)
 
void FillPatch (int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, const amrex::Vector< amrex::MultiFab * > &mfs_mom, const amrex::MultiFab &old_base_state, const amrex::MultiFab &new_base_state, bool fillset=true, bool cons_only=false)
 
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 (int step=-1)
 
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 init_Dirichlet_bc_data (const std::string input_file)
 
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 init_geo_wind_profile (const std::string input_file, amrex::Vector< amrex::Real > &u_geos, amrex::Gpu::DeviceVector< amrex::Real > &u_geos_d, amrex::Vector< amrex::Real > &v_geos, amrex::Gpu::DeviceVector< amrex::Real > &v_geos_d, const amrex::Geometry &lgeom, const amrex::Vector< amrex::Real > &zlev_stag)
 
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...
 

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< amrex::Gpu::DeviceVector< amrex::Real > > xvel_bc_data
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > yvel_bc_data
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > zvel_bc_data
 
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< amrex::MultiFab > pp_inc
 
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_base > > physbcs_base
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Theta_prim
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Qv_prim
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Qr_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
 
amrex::Vector< amrex::MultiFab > zmom_crse_rhs
 
std::unique_ptr< Microphysicsmicro
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > qmoist
 
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< std::unique_ptr< amrex::MultiFab > > SFS_q1fx1_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q1fx2_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q1fx3_lev
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q2fx3_lev
 
amrex::Vector< 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::Vector< amrex::Real > > stretched_dz_h
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > stretched_dz_d
 
amrex::Vector< amrex::MultiFab > base_state
 
amrex::Vector< amrex::MultiFab > base_state_new
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Hwave
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Lwave
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Hwave_onegrid
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Lwave_onegrid
 
bool finished_wave = false
 
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+NBCVAR_maxm_bc_extdir_vals
 
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_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 = ""
 
amrex::Vector< amrex::Real > fixed_dt
 
amrex::Vector< amrex::Real > fixed_fast_dt
 
int regrid_int = -1
 
std::string plot_file_1 {"plt_1_"}
 
std::string plot_file_2 {"plt_2_"}
 
bool m_expand_plotvars_to_unif_rr = false
 
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 m_plot_face_vels = false
 
bool plot_lsm = false
 
int profile_int = -1
 
bool destag_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
 
TurbulentPerturbation turbPert
 
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::Vector< std::unique_ptr< ForestDrag > > m_forest
 
amrex::MultiFab fine_mask
 
amrex::Vector< amrex::Real > dz_min
 
int sampler_interval = -1
 
amrex::Real sampler_per = -1.0
 
std::unique_ptr< SampleDatadata_sampler = nullptr
 
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 int fixed_mri_dt_ratio = 0
 
static SolverChoice solverChoice
 
static int verbose = 0
 
static int mg_verbose = 0
 
static bool use_fft = false
 
static int sum_interval = -1
 
static int pert_interval = -1
 
static amrex::Real sum_per = -1.0
 
static PlotFileType plotfile_type_1 = PlotFileType::None
 
static PlotFileType plotfile_type_2 = PlotFileType::None
 
static InitType init_type
 
static StateInterpType interpolation_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 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 ( )
86 {
87  ERF_shared();
88 }
void ERF_shared()
Definition: ERF.cpp:91

◆ ~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
21 {
22  BL_PROFILE("ERF::Advance()");
23 
24  // We must swap the pointers so the previous step's "new" is now this step's "old"
25  std::swap(vars_old[lev], vars_new[lev]);
26 
27  MultiFab& S_old = vars_old[lev][Vars::cons];
28  MultiFab& S_new = vars_new[lev][Vars::cons];
29 
30  MultiFab& U_old = vars_old[lev][Vars::xvel];
31  MultiFab& V_old = vars_old[lev][Vars::yvel];
32  MultiFab& W_old = vars_old[lev][Vars::zvel];
33 
34  MultiFab& U_new = vars_new[lev][Vars::xvel];
35  MultiFab& V_new = vars_new[lev][Vars::yvel];
36  MultiFab& W_new = vars_new[lev][Vars::zvel];
37 
38  // We need to set these because otherwise in the first call to erf_advance we may
39  // read uninitialized data on ghost values in setting the bc's on the velocities
40  U_new.setVal(1.e34,U_new.nGrowVect());
41  V_new.setVal(1.e34,V_new.nGrowVect());
42  W_new.setVal(1.e34,W_new.nGrowVect());
43 
44  //
45  // NOTE: the momenta here are not fillpatched (they are only used as scratch space)
46  // If lev == 0 we have already FillPatched this in ERF::TimeStep
47  //
48 // if (lev == 0) {
49 // FillPatch(lev, time, {&S_old, &U_old, &V_old, &W_old});
50 // } else {
51  if (lev > 0) {
52  FillPatch(lev, time, {&S_old, &U_old, &V_old, &W_old},
53  {&S_old, &rU_old[lev], &rV_old[lev], &rW_old[lev]},
54  base_state[lev], base_state[lev]);
55  }
56 
57  //
58  // So we must convert the fillpatched to momenta, including the ghost values
59  //
60  VelocityToMomentum(U_old, rU_old[lev].nGrowVect(),
61  V_old, rV_old[lev].nGrowVect(),
62  W_old, rW_old[lev].nGrowVect(),
63  S_old, rU_old[lev], rV_old[lev], rW_old[lev],
64  Geom(lev).Domain(),
66 
67  // TODO: Can test on multiple levels later
68  // Update the inflow perturbation update time and amplitude
69  if (lev == 0) {
70  if (solverChoice.pert_type == PerturbationType::Source ||
71  solverChoice.pert_type == PerturbationType::Direct)
72  {
73  turbPert.calc_tpi_update(lev, dt_lev, U_old, V_old, S_old);
74  }
75 
76  // If PerturbationType::Direct is selected, directly add the computed perturbation
77  // on the conserved field
78  if (solverChoice.pert_type == PerturbationType::Direct)
79  {
80  auto m_ixtype = S_old.boxArray().ixType(); // Conserved term
81  for (MFIter mfi(S_old,TileNoZ()); mfi.isValid(); ++mfi) {
82  Box bx = mfi.tilebox();
83  const Array4<Real> &cell_data = S_old.array(mfi);
84  const Array4<const Real> &pert_cell = turbPert.pb_cell.array(mfi);
85  turbPert.apply_tpi(lev, bx, RhoTheta_comp, m_ixtype, cell_data, pert_cell);
86  }
87  }
88  }
89 
90  // configure ABLMost params if used MostWall boundary condition
91  if (phys_bc_type[Orientation(Direction::z,Orientation::low)] == ERF_BC::MOST) {
92  if (m_most) {
93  IntVect ng = Theta_prim[lev]->nGrowVect();
94  MultiFab::Copy( *Theta_prim[lev], S_old, RhoTheta_comp, 0, 1, ng);
95  MultiFab::Divide(*Theta_prim[lev], S_old, Rho_comp , 0, 1, ng);
96  if (solverChoice.moisture_type != MoistureType::None) {
97  ng = Qv_prim[lev]->nGrowVect();
98 
99  MultiFab::Copy( *Qv_prim[lev], S_old, RhoQ1_comp, 0, 1, ng);
100  MultiFab::Divide(*Qv_prim[lev], S_old, Rho_comp , 0, 1, ng);
101 
102  if (solverChoice.RhoQr_comp > -1) {
103  MultiFab::Copy( *Qr_prim[lev], S_old, solverChoice.RhoQr_comp, 0, 1, ng);
104  MultiFab::Divide(*Qr_prim[lev], S_old, Rho_comp , 0, 1, ng);
105  } else {
106  Qr_prim[lev]->setVal(0.0);
107  }
108  }
109  // NOTE: std::swap above causes the field ptrs to be out of date.
110  // Reassign the field ptrs for MAC avg computation.
111  m_most->update_mac_ptrs(lev, vars_old, Theta_prim, Qv_prim, Qr_prim);
112  m_most->update_pblh(lev, vars_old, z_phys_cc[lev].get(),
114  m_most->update_fluxes(lev, time);
115  }
116  }
117 
118 #if defined(ERF_USE_WINDFARM)
119  if (solverChoice.windfarm_type != WindFarmType::None) {
120  advance_windfarm(Geom(lev), dt_lev, S_old,
121  U_old, V_old, W_old, vars_windfarm[lev], Nturb[lev], SMark[lev], time);
122  }
123 
124 #endif
125 
126  const BoxArray& ba = S_old.boxArray();
127  const DistributionMapping& dm = S_old.DistributionMap();
128 
129  int nvars = S_old.nComp();
130 
131  // Source array for conserved cell-centered quantities -- this will be filled
132  // in the call to make_sources in ERF_TI_slow_rhs_fun.H
133  MultiFab cc_source(ba,dm,nvars,1); cc_source.setVal(0.0);
134 
135  // Source arrays for momenta -- these will be filled
136  // in the call to make_mom_sources in ERF_TI_slow_rhs_fun.H
137  BoxArray ba_x(ba); ba_x.surroundingNodes(0);
138  MultiFab xmom_source(ba_x,dm,nvars,1); xmom_source.setVal(0.0);
139 
140  BoxArray ba_y(ba); ba_y.surroundingNodes(1);
141  MultiFab ymom_source(ba_y,dm,nvars,1); ymom_source.setVal(0.0);
142 
143  BoxArray ba_z(ba); ba_z.surroundingNodes(2);
144  MultiFab zmom_source(ba_z,dm,nvars,1); zmom_source.setVal(0.0);
145 
146  // We don't need to call FillPatch on cons_mf because we have fillpatch'ed S_old above
147  MultiFab cons_mf(ba,dm,nvars,S_old.nGrowVect());
148  MultiFab::Copy(cons_mf,S_old,0,0,S_old.nComp(),S_old.nGrowVect());
149 
150  amrex::Vector<MultiFab> state_old;
151  amrex::Vector<MultiFab> state_new;
152 
153  // **************************************************************************************
154  // Here we define state_old and state_new which are to be advanced
155  // **************************************************************************************
156  // Initial solution
157  // Note that "old" and "new" here are relative to each RK stage.
158  state_old.push_back(MultiFab(cons_mf , amrex::make_alias, 0, nvars)); // cons
159  state_old.push_back(MultiFab(rU_old[lev], amrex::make_alias, 0, 1)); // xmom
160  state_old.push_back(MultiFab(rV_old[lev], amrex::make_alias, 0, 1)); // ymom
161  state_old.push_back(MultiFab(rW_old[lev], amrex::make_alias, 0, 1)); // zmom
162 
163  // Final solution
164  // state_new at the end of the last RK stage holds the t^{n+1} data
165  state_new.push_back(MultiFab(S_new , amrex::make_alias, 0, nvars)); // cons
166  state_new.push_back(MultiFab(rU_new[lev], amrex::make_alias, 0, 1)); // xmom
167  state_new.push_back(MultiFab(rV_new[lev], amrex::make_alias, 0, 1)); // ymom
168  state_new.push_back(MultiFab(rW_new[lev], amrex::make_alias, 0, 1)); // zmom
169 
170  // **************************************************************************************
171  // Update the dycore
172  // **************************************************************************************
173  advance_dycore(lev, state_old, state_new,
174  U_old, V_old, W_old,
175  U_new, V_new, W_new,
176  cc_source, xmom_source, ymom_source, zmom_source,
177  Geom(lev), dt_lev, time);
178 
179  // **************************************************************************************
180  // Update the microphysics (moisture)
181  // **************************************************************************************
182  advance_microphysics(lev, S_new, dt_lev, iteration, time);
183 
184  // **************************************************************************************
185  // Update the land surface model
186  // **************************************************************************************
187  advance_lsm(lev, S_new, dt_lev);
188 
189 #if defined(ERF_USE_RRTMGP)
190  // **************************************************************************************
191  // Update the radiation
192  // **************************************************************************************
193  advance_radiation(lev, S_new, dt_lev);
194 #endif
195 
196 #ifdef ERF_USE_PARTICLES
197  // **************************************************************************************
198  // Update the particle positions
199  // **************************************************************************************
200  evolveTracers( lev, dt_lev, vars_new, z_phys_nd );
201 #endif
202 
203  // ***********************************************************************************************
204  // Impose domain boundary conditions here so that in FillPatching the fine data we won't
205  // need to re-fill these
206  // ***********************************************************************************************
207  if (lev < finest_level) {
208  IntVect ngvect_vels = vars_new[lev][Vars::xvel].nGrowVect();
209  (*physbcs_cons[lev])(vars_new[lev][Vars::cons],0,vars_new[lev][Vars::cons].nComp(),
210  vars_new[lev][Vars::cons].nGrowVect(),time,BCVars::cons_bc,true);
211  (*physbcs_u[lev])(vars_new[lev][Vars::xvel],0,1,ngvect_vels,time,BCVars::xvel_bc,true);
212  (*physbcs_v[lev])(vars_new[lev][Vars::yvel],0,1,ngvect_vels,time,BCVars::yvel_bc,true);
213  (*physbcs_w[lev])(vars_new[lev][Vars::zvel], vars_new[lev][Vars::xvel], vars_new[lev][Vars::yvel],
214  ngvect_vels,time,BCVars::zvel_bc,true);
215  }
216 
217  // **************************************************************************************
218  // Register old and new coarse data if we are at a level less than the finest level
219  // **************************************************************************************
220  if (lev < finest_level)
221  {
222  if (cf_width > 0) {
223  // We must fill the ghost cells of these so that the parallel copy works correctly
224  state_old[IntVars::cons].FillBoundary(geom[lev].periodicity());
225  state_new[IntVars::cons].FillBoundary(geom[lev].periodicity());
226  FPr_c[lev].RegisterCoarseData({&state_old[IntVars::cons], &state_new[IntVars::cons]},
227  {time, time + dt_lev});
228  }
229 
230  if (cf_width >= 0) {
231  // We must fill the ghost cells of these so that the parallel copy works correctly
232  state_old[IntVars::xmom].FillBoundary(geom[lev].periodicity());
233  state_new[IntVars::xmom].FillBoundary(geom[lev].periodicity());
234  FPr_u[lev].RegisterCoarseData({&state_old[IntVars::xmom], &state_new[IntVars::xmom]},
235  {time, time + dt_lev});
236 
237  state_old[IntVars::ymom].FillBoundary(geom[lev].periodicity());
238  state_new[IntVars::ymom].FillBoundary(geom[lev].periodicity());
239  FPr_v[lev].RegisterCoarseData({&state_old[IntVars::ymom], &state_new[IntVars::ymom]},
240  {time, time + dt_lev});
241 
242  state_old[IntVars::zmom].FillBoundary(geom[lev].periodicity());
243  state_new[IntVars::zmom].FillBoundary(geom[lev].periodicity());
244  FPr_w[lev].RegisterCoarseData({&state_old[IntVars::zmom], &state_new[IntVars::zmom]},
245  {time, time + dt_lev});
246  }
247 
248  //
249  // Now create a MultiFab that holds (S_new - S_old) / dt from the coarse level interpolated
250  // on to the coarse/fine boundary at the fine resolution
251  //
252  Interpolater* mapper_f = &face_cons_linear_interp;
253 
254  // PhysBCFunctNoOp null_bc;
255  // MultiFab tempx(vars_new[lev+1][Vars::xvel].boxArray(),vars_new[lev+1][Vars::xvel].DistributionMap(),1,0);
256  // tempx.setVal(0.0);
257  // xmom_crse_rhs[lev+1].setVal(0.0);
258  // FPr_u[lev].FillSet(tempx , time , null_bc, domain_bcs_type);
259  // FPr_u[lev].FillSet(xmom_crse_rhs[lev+1], time+dt_lev, null_bc, domain_bcs_type);
260  // MultiFab::Subtract(xmom_crse_rhs[lev+1],tempx,0,0,1,IntVect{0});
261  // xmom_crse_rhs[lev+1].mult(1.0/dt_lev,0,1,0);
262 
263  // MultiFab tempy(vars_new[lev+1][Vars::yvel].boxArray(),vars_new[lev+1][Vars::yvel].DistributionMap(),1,0);
264  // tempy.setVal(0.0);
265  // ymom_crse_rhs[lev+1].setVal(0.0);
266  // FPr_v[lev].FillSet(tempy , time , null_bc, domain_bcs_type);
267  // FPr_v[lev].FillSet(ymom_crse_rhs[lev+1], time+dt_lev, null_bc, domain_bcs_type);
268  // MultiFab::Subtract(ymom_crse_rhs[lev+1],tempy,0,0,1,IntVect{0});
269  // ymom_crse_rhs[lev+1].mult(1.0/dt_lev,0,1,0);
270 
271  MultiFab temp_state(zmom_crse_rhs[lev+1].boxArray(),zmom_crse_rhs[lev+1].DistributionMap(),1,0);
272  InterpFromCoarseLevel(temp_state, IntVect{0}, IntVect{0}, state_old[IntVars::zmom], 0, 0, 1,
273  geom[lev], geom[lev+1], refRatio(lev), mapper_f, domain_bcs_type, BCVars::zvel_bc);
274  InterpFromCoarseLevel(zmom_crse_rhs[lev+1], IntVect{0}, IntVect{0}, state_new[IntVars::zmom], 0, 0, 1,
275  geom[lev], geom[lev+1], refRatio(lev), mapper_f, domain_bcs_type, BCVars::zvel_bc);
276  MultiFab::Subtract(zmom_crse_rhs[lev+1],temp_state,0,0,1,IntVect{0});
277  zmom_crse_rhs[lev+1].mult(1.0/dt_lev,0,1,0);
278  }
279 
280  // ***********************************************************************************************
281  // Update the time averaged velocities if they are requested
282  // ***********************************************************************************************
284  Time_Avg_Vel_atCC(dt[lev], t_avg_cnt[lev], vel_t_avg[lev].get(), U_new, V_new, W_new);
285  }
286 }
@ nvars
Definition: ERF_DataStruct.H:66
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
void Time_Avg_Vel_atCC(const Real &dt, Real &t_avg_cnt, MultiFab *vel_t_avg, MultiFab &xvel, MultiFab &yvel, MultiFab &zvel)
Definition: ERF_TimeAvgVel.cpp:9
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::MultiFab > rU_new
Definition: ERF.H:750
std::unique_ptr< ABLMost > m_most
Definition: ERF.H:1126
amrex::Vector< ERFFillPatcher > FPr_u
Definition: ERF.H:795
amrex::Vector< amrex::Vector< amrex::MultiFab > > vars_new
Definition: ERF.H:725
amrex::Vector< ERFFillPatcher > FPr_v
Definition: ERF.H:796
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_cons > > physbcs_cons
Definition: ERF.H:737
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_cc
Definition: ERF.H:820
static SolverChoice solverChoice
Definition: ERF.H:983
amrex::Vector< ERFFillPatcher > FPr_c
Definition: ERF.H:794
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vel_t_avg
Definition: ERF.H:729
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_w > > physbcs_w
Definition: ERF.H:740
amrex::Vector< amrex::MultiFab > base_state
Definition: ERF.H:848
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Qv_prim
Definition: ERF.H:745
amrex::Vector< amrex::MultiFab > rV_new
Definition: ERF.H:752
amrex::Vector< amrex::BCRec > domain_bcs_type
Definition: ERF.H:864
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Qr_prim
Definition: ERF.H:746
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_u > > physbcs_u
Definition: ERF.H:738
amrex::Vector< amrex::Real > t_avg_cnt
Definition: ERF.H:730
amrex::Vector< amrex::MultiFab > rU_old
Definition: ERF.H:749
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Theta_prim
Definition: ERF.H:744
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_v > > physbcs_v
Definition: ERF.H:739
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd
Definition: ERF.H:819
amrex::Vector< amrex::MultiFab > rW_new
Definition: ERF.H:754
amrex::Vector< amrex::MultiFab > zmom_crse_rhs
Definition: ERF.H:758
TurbulentPerturbation turbPert
Definition: ERF.H:986
amrex::Vector< amrex::MultiFab > rW_old
Definition: ERF.H:753
void advance_lsm(int lev, amrex::MultiFab &, const amrex::Real &dt_advance)
Definition: ERF_AdvanceLSM.cpp:5
amrex::Vector< ERFFillPatcher > FPr_w
Definition: ERF.H:797
amrex::Vector< amrex::Real > dt
Definition: ERF.H:719
void advance_microphysics(int lev, amrex::MultiFab &cons_in, const amrex::Real &dt_advance, const int &iteration, const amrex::Real &time)
Definition: ERF_AdvanceMicrophysics.cpp:5
int cf_width
Definition: ERF.H:792
amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > phys_bc_type
Definition: ERF.H:877
amrex::Vector< amrex::MultiFab > rV_old
Definition: ERF.H:751
amrex::Vector< amrex::Vector< amrex::MultiFab > > vars_old
Definition: ERF.H:726
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_AdvanceDycore.cpp:37
void FillPatch(int lev, amrex::Real time, const amrex::Vector< amrex::MultiFab * > &mfs_vel, bool cons_only=false)
@ zvel_bc
Definition: ERF_IndexDefines.H:90
@ yvel_bc
Definition: ERF_IndexDefines.H:89
@ cons_bc
Definition: ERF_IndexDefines.H:76
@ xvel_bc
Definition: ERF_IndexDefines.H:88
@ ymom
Definition: ERF_IndexDefines.H:141
@ cons
Definition: ERF_IndexDefines.H:139
@ zmom
Definition: ERF_IndexDefines.H:142
@ xmom
Definition: ERF_IndexDefines.H:140
@ xvel
Definition: ERF_IndexDefines.H:130
@ cons
Definition: ERF_IndexDefines.H:129
@ zvel
Definition: ERF_IndexDefines.H:132
@ yvel
Definition: ERF_IndexDefines.H:131
int RhoQr_comp
Definition: ERF_DataStruct.H:645
int RhoQv_comp
Definition: ERF_DataStruct.H:639
MoistureType moisture_type
Definition: ERF_DataStruct.H:623
PerturbationType pert_type
Definition: ERF_DataStruct.H:613
WindFarmType windfarm_type
Definition: ERF_DataStruct.H:624
bool time_avg_vel
Definition: ERF_DataStruct.H:610
void calc_tpi_update(const int lev, const amrex::Real dt, amrex::MultiFab &mf_xvel, amrex::MultiFab &mf_yvel, amrex::MultiFab &mf_cons)
Definition: ERF_TurbPertStruct.H:184
amrex::MultiFab pb_cell
Definition: ERF_TurbPertStruct.H:536
void apply_tpi(const int &lev, const amrex::Box &vbx, const int &comp, const amrex::IndexType &m_ixtype, const amrex::Array4< amrex::Real > &src_arr, const amrex::Array4< amrex::Real const > &pert_cell)
Definition: ERF_TurbPertStruct.H:245
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
46 {
47  BL_PROFILE_VAR("erf_advance_dycore()",erf_advance_dycore);
48 
49  const Box& domain = fine_geom.Domain();
50 
54 
55  MultiFab r_hse (base_state[level], make_alias, BaseState::r0_comp , 1);
56  MultiFab p_hse (base_state[level], make_alias, BaseState::p0_comp , 1);
57  MultiFab pi_hse(base_state[level], make_alias, BaseState::pi0_comp, 1);
58 
59  // These pointers are used in the MRI utility functions
60  MultiFab* r0 = &r_hse;
61  MultiFab* p0 = &p_hse;
62  MultiFab* pi0 = &pi_hse;
63 
64  Real* dptr_rhotheta_src = solverChoice.custom_rhotheta_forcing ? d_rhotheta_src[level].data() : nullptr;
65  Real* dptr_rhoqt_src = solverChoice.custom_moisture_forcing ? d_rhoqt_src[level].data() : nullptr;
66  Real* dptr_wbar_sub = solverChoice.custom_w_subsidence ? d_w_subsid[level].data() : nullptr;
67 
68  // Turbulent Perturbation Pointer
69  //Real* dptr_rhotheta_src = solverChoice.pert_type ? d_rhotheta_src[level].data() : nullptr;
70 
71  Vector<Real*> d_rayleigh_ptrs_at_lev;
72  d_rayleigh_ptrs_at_lev.resize(Rayleigh::nvars);
73  d_rayleigh_ptrs_at_lev[Rayleigh::ubar] = solverChoice.rayleigh_damp_U ? d_rayleigh_ptrs[level][Rayleigh::ubar].data() : nullptr;
74  d_rayleigh_ptrs_at_lev[Rayleigh::vbar] = solverChoice.rayleigh_damp_V ? d_rayleigh_ptrs[level][Rayleigh::vbar].data() : nullptr;
75  d_rayleigh_ptrs_at_lev[Rayleigh::wbar] = solverChoice.rayleigh_damp_W ? d_rayleigh_ptrs[level][Rayleigh::wbar].data() : nullptr;
76  d_rayleigh_ptrs_at_lev[Rayleigh::thetabar] = solverChoice.rayleigh_damp_T ? d_rayleigh_ptrs[level][Rayleigh::thetabar].data() : nullptr;
77 
78  Vector<Real*> d_sponge_ptrs_at_lev;
79  if(sc.sponge_type=="input_sponge")
80  {
81  d_sponge_ptrs_at_lev.resize(Sponge::nvars_sponge);
82  d_sponge_ptrs_at_lev[Sponge::ubar_sponge] = d_sponge_ptrs[level][Sponge::ubar_sponge].data();
83  d_sponge_ptrs_at_lev[Sponge::vbar_sponge] = d_sponge_ptrs[level][Sponge::vbar_sponge].data();
84  }
85 
86  bool l_use_terrain = (SolverChoice::terrain_type != TerrainType::None);
87  bool l_use_diff = ( (dc.molec_diff_type != MolecDiffType::None) ||
88  (tc.les_type != LESType::None) ||
89  (tc.pbl_type != PBLType::None) );
90  bool l_use_kturb = ( (tc.les_type != LESType::None) ||
91  (tc.pbl_type != PBLType::None) );
92  bool l_use_moisture = ( solverChoice.moisture_type != MoistureType::None );
93  bool l_implicit_substepping = ( solverChoice.substepping_type[level] == SubsteppingType::Implicit );
94 
95  const bool use_most = (m_most != nullptr);
96  const bool exp_most = (solverChoice.use_explicit_most);
97  amrex::ignore_unused(use_most);
98 
99  const BoxArray& ba = state_old[IntVars::cons].boxArray();
100  const BoxArray& ba_z = zvel_old.boxArray();
101  const DistributionMapping& dm = state_old[IntVars::cons].DistributionMap();
102 
103  int num_prim = state_old[IntVars::cons].nComp() - 1;
104 
105  MultiFab S_prim (ba , dm, num_prim, state_old[IntVars::cons].nGrowVect());
106  MultiFab pi_stage (ba , dm, 1, state_old[IntVars::cons].nGrowVect());
107  MultiFab fast_coeffs(ba_z, dm, 5, 0);
108  MultiFab* eddyDiffs = eddyDiffs_lev[level].get();
109  MultiFab* SmnSmn = SmnSmn_lev[level].get();
110 
111  // **************************************************************************************
112  // Compute strain for use in slow RHS, Smagorinsky model, and MOST
113  // **************************************************************************************
114  {
115  BL_PROFILE("erf_advance_strain");
116  if (l_use_diff) {
117 
118  const BCRec* bc_ptr_h = domain_bcs_type.data();
119  const GpuArray<Real, AMREX_SPACEDIM> dxInv = fine_geom.InvCellSizeArray();
120 
121 #ifdef _OPENMP
122 #pragma omp parallel if (Gpu::notInLaunchRegion())
123 #endif
124  for ( MFIter mfi(state_new[IntVars::cons],TileNoZ()); mfi.isValid(); ++mfi)
125  {
126  Box bxcc = mfi.growntilebox(IntVect(1,1,0));
127  Box tbxxy = mfi.tilebox(IntVect(1,1,0),IntVect(1,1,0));
128  Box tbxxz = mfi.tilebox(IntVect(1,0,1),IntVect(1,1,0));
129  Box tbxyz = mfi.tilebox(IntVect(0,1,1),IntVect(1,1,0));
130 
131  if (bxcc.smallEnd(2) != domain.smallEnd(2)) {
132  bxcc.growLo(2,1);
133  tbxxy.growLo(2,1);
134  tbxxz.growLo(2,1);
135  tbxyz.growLo(2,1);
136  }
137 
138  if (bxcc.bigEnd(2) != domain.bigEnd(2)) {
139  bxcc.growHi(2,1);
140  tbxxy.growHi(2,1);
141  tbxxz.growHi(2,1);
142  tbxyz.growHi(2,1);
143  }
144 
145  const Array4<const Real> & u = xvel_old.array(mfi);
146  const Array4<const Real> & v = yvel_old.array(mfi);
147  const Array4<const Real> & w = zvel_old.array(mfi);
148 
149  Array4<Real> tau11 = Tau11_lev[level].get()->array(mfi);
150  Array4<Real> tau22 = Tau22_lev[level].get()->array(mfi);
151  Array4<Real> tau33 = Tau33_lev[level].get()->array(mfi);
152  Array4<Real> tau12 = Tau12_lev[level].get()->array(mfi);
153  Array4<Real> tau13 = Tau13_lev[level].get()->array(mfi);
154  Array4<Real> tau23 = Tau23_lev[level].get()->array(mfi);
155 
156  Array4<Real> tau21 = l_use_terrain ? Tau21_lev[level].get()->array(mfi) : Array4<Real>{};
157  Array4<Real> tau31 = l_use_terrain ? Tau31_lev[level].get()->array(mfi) : Array4<Real>{};
158  Array4<Real> tau32 = l_use_terrain ? Tau32_lev[level].get()->array(mfi) : Array4<Real>{};
159  const Array4<const Real>& z_nd = l_use_terrain ? z_phys_nd[level]->const_array(mfi) : Array4<const Real>{};
160 
161  const Array4<const Real> mf_m = mapfac_m[level]->array(mfi);
162  const Array4<const Real> mf_u = mapfac_u[level]->array(mfi);
163  const Array4<const Real> mf_v = mapfac_v[level]->array(mfi);
164 
165  if (l_use_terrain) {
166  ComputeStrain_T(bxcc, tbxxy, tbxxz, tbxyz, domain,
167  u, v, w,
168  tau11, tau22, tau33,
169  tau12, tau13,
170  tau21, tau23,
171  tau31, tau32,
172  z_nd, detJ_cc[level]->const_array(mfi), bc_ptr_h, dxInv,
173  mf_m, mf_u, mf_v);
174  } else {
175  ComputeStrain_N(bxcc, tbxxy, tbxxz, tbxyz, domain,
176  u, v, w,
177  tau11, tau22, tau33,
178  tau12, tau13, tau23,
179  bc_ptr_h, dxInv,
180  mf_m, mf_u, mf_v);
181  }
182  } // mfi
183  } // l_use_diff
184  } // profile
185 
186 #include "ERF_TI_utils.H"
187 
188  // Additional SFS quantities, calculated once per timestep
189  MultiFab* Hfx1 = SFS_hfx1_lev[level].get();
190  MultiFab* Hfx2 = SFS_hfx2_lev[level].get();
191  MultiFab* Hfx3 = SFS_hfx3_lev[level].get();
192  MultiFab* Q1fx1 = SFS_q1fx1_lev[level].get();
193  MultiFab* Q1fx2 = SFS_q1fx2_lev[level].get();
194  MultiFab* Q1fx3 = SFS_q1fx3_lev[level].get();
195  MultiFab* Q2fx3 = SFS_q2fx3_lev[level].get();
196  MultiFab* Diss = SFS_diss_lev[level].get();
197 
198  // *************************************************************************
199  // Calculate cell-centered eddy viscosity & diffusivities
200  //
201  // Notes -- we fill all the data in ghost cells before calling this so
202  // that we can fill the eddy viscosity in the ghost regions and
203  // not have to call a boundary filler on this data itself
204  //
205  // LES - updates both horizontal and vertical eddy viscosity components
206  // PBL - only updates vertical eddy viscosity components so horizontal
207  // components come from the LES model or are left as zero.
208  // *************************************************************************
209  if (l_use_kturb)
210  {
211  // NOTE: state_new transfers to state_old for PBL (due to ptr swap in advance)
212  const BCRec* bc_ptr_h = domain_bcs_type.data();
213  ComputeTurbulentViscosity(xvel_old, yvel_old,
214  *Tau11_lev[level].get(), *Tau22_lev[level].get(), *Tau33_lev[level].get(),
215  *Tau12_lev[level].get(), *Tau13_lev[level].get(), *Tau23_lev[level].get(),
216  state_old[IntVars::cons],
217  *eddyDiffs, *Hfx1, *Hfx2, *Hfx3, *Diss, // to be updated
218  fine_geom, *mapfac_u[level], *mapfac_v[level],
219  z_phys_nd[level], solverChoice,
220  m_most, exp_most, l_use_moisture, level, bc_ptr_h);
221  }
222 
223  // ***********************************************************************************************
224  // Update user-defined source terms -- these are defined once per time step (not per RK stage)
225  // ***********************************************************************************************
227  prob->update_rhotheta_sources(old_time,
228  h_rhotheta_src[level], d_rhotheta_src[level],
229  fine_geom, z_phys_cc[level]);
230  }
231 
233  prob->update_rhoqt_sources(old_time,
234  h_rhoqt_src[level], d_rhoqt_src[level],
235  fine_geom, z_phys_cc[level]);
236  }
237 
239  prob->update_geostrophic_profile(old_time,
240  h_u_geos[level], d_u_geos[level],
241  h_v_geos[level], d_v_geos[level],
242  fine_geom, z_phys_cc[level]);
243  }
244 
245  // ***********************************************************************************************
246  // Convert old velocity available on faces to old momentum on faces to be used in time integration
247  // ***********************************************************************************************
248  MultiFab density(state_old[IntVars::cons], make_alias, Rho_comp, 1);
249 
250  //
251  // This is an optimization since we won't need more than one ghost
252  // cell of momentum in the integrator if not using NumDiff
253  //
254  IntVect ngu = (!solverChoice.use_NumDiff) ? IntVect(1,1,1) : xvel_old.nGrowVect();
255  IntVect ngv = (!solverChoice.use_NumDiff) ? IntVect(1,1,1) : yvel_old.nGrowVect();
256  IntVect ngw = (!solverChoice.use_NumDiff) ? IntVect(1,1,0) : zvel_old.nGrowVect();
257 
258  VelocityToMomentum(xvel_old, ngu, yvel_old, ngv, zvel_old, ngw, density,
259  state_old[IntVars::xmom],
260  state_old[IntVars::ymom],
261  state_old[IntVars::zmom],
262  domain, domain_bcs_type);
263 
264  MultiFab::Copy(xvel_new,xvel_old,0,0,1,xvel_old.nGrowVect());
265  MultiFab::Copy(yvel_new,yvel_old,0,0,1,yvel_old.nGrowVect());
266  MultiFab::Copy(zvel_new,zvel_old,0,0,1,zvel_old.nGrowVect());
267 
268  bool fast_only = false;
269  bool vel_and_mom_synced = true;
270 
271  apply_bcs(state_old, old_time,
272  state_old[IntVars::cons].nGrow(), state_old[IntVars::xmom].nGrow(),
273  fast_only, vel_and_mom_synced);
274  cons_to_prim(state_old[IntVars::cons], state_old[IntVars::cons].nGrow());
275 
276 #include "ERF_TI_no_substep_fun.H"
277 #include "ERF_TI_substep_fun.H"
278 #include "ERF_TI_slow_rhs_fun.H"
279 
280  // ***************************************************************************************
281  // Setup the integrator and integrate for a single timestep
282  // **************************************************************************************
283  MRISplitIntegrator<Vector<MultiFab> >& mri_integrator = *mri_integrator_mem[level];
284 
285  // Define rhs and 'post update' utility function that is called after calculating
286  // any state data (e.g. at RK stages or at the end of a timestep)
287  mri_integrator.set_slow_rhs_pre(slow_rhs_fun_pre);
288  mri_integrator.set_slow_rhs_post(slow_rhs_fun_post);
289 
290  if (solverChoice.anelastic[level]) {
291  mri_integrator.set_slow_rhs_inc(slow_rhs_fun_inc);
292  }
293 
294  mri_integrator.set_fast_rhs(fast_rhs_fun);
296  mri_integrator.set_no_substep(no_substep_fun);
297 
298  mri_integrator.advance(state_old, state_new, old_time, dt_advance);
299 
300  if (verbose) Print() << "Done with advance_dycore at level " << level << std::endl;
301 }
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: ERF_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 > &mf_m, const Array4< const Real > &mf_u, const Array4< const Real > &mf_v)
Definition: ERF_ComputeStrain_T.cpp:33
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 SolverChoice &solverChoice, std::unique_ptr< ABLMost > &most, const bool &exp_most, const bool &use_moisture, int level, const BCRec *bc_ptr, bool vert_only)
Definition: ERF_ComputeTurbulentViscosity.cpp:436
@ ubar
Definition: ERF_DataStruct.H:66
@ wbar
Definition: ERF_DataStruct.H:66
@ vbar
Definition: ERF_DataStruct.H:66
@ thetabar
Definition: ERF_DataStruct.H:66
@ nvars_sponge
Definition: ERF_DataStruct.H:71
@ vbar_sponge
Definition: ERF_DataStruct.H:71
@ ubar_sponge
Definition: ERF_DataStruct.H:71
auto no_substep_fun
Definition: ERF_TI_no_substep_fun.H:4
auto slow_rhs_fun_inc
Definition: ERF_TI_slow_rhs_fun.H:392
auto slow_rhs_fun_pre
Definition: ERF_TI_slow_rhs_fun.H:6
auto slow_rhs_fun_post
Definition: ERF_TI_slow_rhs_fun.H:298
auto fast_rhs_fun
Definition: ERF_TI_substep_fun.H:4
auto apply_bcs
Definition: ERF_TI_utils.H:50
auto cons_to_prim
Definition: ERF_TI_utils.H:4
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau23_lev
Definition: ERF.H:803
amrex::Vector< std::unique_ptr< MRISplitIntegrator< amrex::Vector< amrex::MultiFab > > > > mri_integrator_mem
Definition: ERF.H:732
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_rhotheta_src
Definition: ERF.H:1075
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q1fx3_lev
Definition: ERF.H:814
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx3_lev
Definition: ERF.H:812
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_u
Definition: ERF.H:842
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau31_lev
Definition: ERF.H:802
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_m
Definition: ERF.H:841
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx1_lev
Definition: ERF.H:812
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc
Definition: ERF.H:822
amrex::Vector< std::unique_ptr< amrex::MultiFab > > eddyDiffs_lev
Definition: ERF.H:804
amrex::Vector< amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > > d_sponge_ptrs
Definition: ERF.H:1108
amrex::Vector< amrex::Vector< amrex::Real > > h_rhoqt_src
Definition: ERF.H:1077
amrex::Vector< long > dt_mri_ratio
Definition: ERF.H:720
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q2fx3_lev
Definition: ERF.H:815
static int verbose
Definition: ERF.H:1018
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau13_lev
Definition: ERF.H:802
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q1fx2_lev
Definition: ERF.H:814
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau21_lev
Definition: ERF.H:801
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau33_lev
Definition: ERF.H:800
std::unique_ptr< ProblemBase > prob
Definition: ERF.H:707
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_diss_lev
Definition: ERF.H:813
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_v_geos
Definition: ERF.H:1087
amrex::Vector< amrex::Vector< amrex::Real > > h_v_geos
Definition: ERF.H:1086
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_rhoqt_src
Definition: ERF.H:1078
amrex::Vector< amrex::Vector< amrex::Real > > h_rhotheta_src
Definition: ERF.H:1074
amrex::Vector< amrex::Vector< amrex::Real > > h_u_geos
Definition: ERF.H:1083
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SmnSmn_lev
Definition: ERF.H:805
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau32_lev
Definition: ERF.H:803
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_u_geos
Definition: ERF.H:1084
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > d_w_subsid
Definition: ERF.H:1081
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_hfx2_lev
Definition: ERF.H:812
static int fixed_mri_dt_ratio
Definition: ERF.H:915
amrex::Vector< amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > > d_rayleigh_ptrs
Definition: ERF.H:1105
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau12_lev
Definition: ERF.H:801
amrex::Vector< std::unique_ptr< amrex::MultiFab > > SFS_q1fx1_lev
Definition: ERF.H:814
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mapfac_v
Definition: ERF.H:843
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau11_lev
Definition: ERF.H:800
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Tau22_lev
Definition: ERF.H:800
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:134
void set_no_substep(std::function< void(T &, T &, T &, amrex::Real, amrex::Real, int)> F)
Definition: ERF_MRI.H:164
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:138
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:147
void set_slow_fast_timestep_ratio(const int timestep_ratio=1)
Definition: ERF_MRI.H:154
amrex::Real advance(T &S_old, T &S_new, amrex::Real time, const amrex::Real time_step)
Definition: ERF_MRI.H:174
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:142
@ pi0_comp
Definition: ERF_IndexDefines.H:65
@ p0_comp
Definition: ERF_IndexDefines.H:64
@ r0_comp
Definition: ERF_IndexDefines.H:63
Definition: ERF_DiffStruct.H:19
MolecDiffType molec_diff_type
Definition: ERF_DiffStruct.H:76
bool rayleigh_damp_T
Definition: ERF_DataStruct.H:567
bool use_explicit_most
Definition: ERF_DataStruct.H:604
bool rayleigh_damp_V
Definition: ERF_DataStruct.H:565
DiffChoice diffChoice
Definition: ERF_DataStruct.H:538
bool custom_rhotheta_forcing
Definition: ERF_DataStruct.H:593
bool custom_w_subsidence
Definition: ERF_DataStruct.H:595
bool rayleigh_damp_U
Definition: ERF_DataStruct.H:564
bool custom_geostrophic_profile
Definition: ERF_DataStruct.H:596
amrex::Vector< SubsteppingType > substepping_type
Definition: ERF_DataStruct.H:547
bool use_NumDiff
Definition: ERF_DataStruct.H:616
bool custom_moisture_forcing
Definition: ERF_DataStruct.H:594
amrex::Vector< TurbChoice > turbChoice
Definition: ERF_DataStruct.H:540
amrex::Vector< int > anelastic
Definition: ERF_DataStruct.H:548
static TerrainType terrain_type
Definition: ERF_DataStruct.H:529
bool rayleigh_damp_W
Definition: ERF_DataStruct.H:566
SpongeChoice spongeChoice
Definition: ERF_DataStruct.H:539
Definition: ERF_SpongeStruct.H:15
std::string sponge_type
Definition: ERF_SpongeStruct.H:61
Definition: ERF_TurbStruct.H:29
PBLType pbl_type
Definition: ERF_TurbStruct.H:192
LESType les_type
Definition: ERF_TurbStruct.H:169
Here is the call graph for this function:

◆ advance_lsm()

void ERF::advance_lsm ( int  lev,
amrex::MultiFab &  ,
const amrex::Real &  dt_advance 
)
8 {
9  if (solverChoice.lsm_type != LandSurfaceType::None) {
10  lsm.Advance(lev, dt_advance);
11  }
12 }
LandSurface lsm
Definition: ERF.H:776
void Advance(const int &lev, const amrex::Real &dt_advance)
Definition: ERF_LandSurface.H:51
LandSurfaceType lsm_type
Definition: ERF_DataStruct.H:626

◆ 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 {
11  if (solverChoice.moisture_type != MoistureType::None) {
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:760

◆ appendPlotVariables()

void ERF::appendPlotVariables ( const std::string &  pp_plot_var_names,
amrex::Vector< std::string > &  plot_var_names 
)
private
129 {
130  ParmParse pp(pp_prefix);
131 
132  Vector<std::string> plot_var_names(0);
133  if (pp.contains(pp_plot_var_names.c_str())) {
134  std::string nm;
135  int nPltVars = pp.countval(pp_plot_var_names.c_str());
136  for (int i = 0; i < nPltVars; i++) {
137  pp.get(pp_plot_var_names.c_str(), nm, i);
138  // Add the named variable to our list of plot variables
139  // if it is not already in the list
140  if (!containerHasElement(plot_var_names, nm)) {
141  plot_var_names.push_back(nm);
142  }
143  }
144  }
145 
146  Vector<std::string> tmp_plot_names(0);
147 #ifdef ERF_USE_PARTICLES
148  Vector<std::string> particle_mesh_plot_names;
149  particleData.GetMeshPlotVarNames( particle_mesh_plot_names );
150  for (int i = 0; i < particle_mesh_plot_names.size(); i++) {
151  std::string tmp(particle_mesh_plot_names[i]);
152  if (containerHasElement(plot_var_names, tmp) ) {
153  tmp_plot_names.push_back(tmp);
154  }
155  }
156 #endif
157 
158  for (int i = 0; i < tmp_plot_names.size(); i++) {
159  a_plot_var_names.push_back( tmp_plot_names[i] );
160  }
161 
162  // Finally, check to see if we found all the requested variables
163  for (const auto& plot_name : plot_var_names) {
164  if (!containerHasElement(a_plot_var_names, plot_name)) {
165  if (amrex::ParallelDescriptor::IOProcessor()) {
166  Warning("\nWARNING: Requested to plot variable '" + plot_name + "' but it is not available");
167  }
168  }
169  }
170 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:219
bool containerHasElement(const V &iterable, const T &query)
Definition: ERF_Plotfile.cpp:13
std::string pp_prefix
Definition: ERF.H:441
Here is the call graph for this function:

◆ AverageDown()

void ERF::AverageDown ( )
private
17 {
18  AMREX_ALWAYS_ASSERT(solverChoice.coupling_type == CouplingType::TwoWay);
19 
20  int src_comp, num_comp;
21  for (int lev = finest_level-1; lev >= 0; --lev)
22  {
23  // If anelastic we don't average down rho because rho == rho0.
24  if (solverChoice.anelastic[lev]) {
25  src_comp = 1;
26  } else {
27  src_comp = 0;
28  }
29  num_comp = vars_new[0][Vars::cons].nComp() - src_comp;
30  AverageDownTo(lev,src_comp,num_comp);
31  }
32 }
void AverageDownTo(int crse_lev, int scomp, int ncomp)
Definition: ERF_AverageDown.cpp:36
CouplingType coupling_type
Definition: ERF_DataStruct.H:622

◆ AverageDownTo()

void ERF::AverageDownTo ( int  crse_lev,
int  scomp,
int  ncomp 
)
37 {
38  if (solverChoice.anelastic[crse_lev]) {
39  AMREX_ALWAYS_ASSERT(scomp == 1);
40  } else {
41  AMREX_ALWAYS_ASSERT(scomp == 0);
42  }
43 
44  AMREX_ALWAYS_ASSERT(ncomp == vars_new[crse_lev][Vars::cons].nComp() - scomp);
45  AMREX_ALWAYS_ASSERT(solverChoice.coupling_type == CouplingType::TwoWay);
46 
47  // ******************************************************************************************
48  // First do cell-centered quantities
49  // The quantity that is conserved is not (rho S), but rather (rho S / m^2) where
50  // m is the map scale factor at cell centers
51  // Here we pre-divide (rho S) by m^2 before average down
52  // ******************************************************************************************
53  for (int lev = crse_lev; lev <= crse_lev+1; lev++) {
54  for (MFIter mfi(vars_new[lev][Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
55  const Box& bx = mfi.tilebox();
56  const Array4< Real> cons_arr = vars_new[lev][Vars::cons].array(mfi);
57  const Array4<const Real> mapfac_arr = mapfac_m[lev]->const_array(mfi);
58  if (SolverChoice::terrain_type != TerrainType::None) {
59  const Array4<const Real> detJ_arr = detJ_cc[lev]->const_array(mfi);
60  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
61  {
62  cons_arr(i,j,k,scomp+n) *= detJ_arr(i,j,k) / (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
63  });
64  } else {
65  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
66  {
67  cons_arr(i,j,k,scomp+n) /= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
68  });
69  }
70  } // mfi
71  } // lev
72 
73  int fine_lev = crse_lev+1;
74 
75  if (interpolation_type == StateInterpType::Perturbational) {
76  // Make the fine rho and (rho theta) be perturbational
77  MultiFab::Divide(vars_new[fine_lev][Vars::cons],vars_new[fine_lev][Vars::cons],
78  Rho_comp,RhoTheta_comp,1,IntVect{0});
79  MultiFab::Subtract(vars_new[fine_lev][Vars::cons],base_state[fine_lev],
80  BaseState::r0_comp,Rho_comp,1,IntVect{0});
81  MultiFab::Subtract(vars_new[fine_lev][Vars::cons],base_state[fine_lev],
82  BaseState::th0_comp,RhoTheta_comp,1,IntVect{0});
83 
84  // Make the crse rho and (rho theta) be perturbational
85  MultiFab::Divide(vars_new[crse_lev][Vars::cons],vars_new[crse_lev][Vars::cons],
86  Rho_comp,RhoTheta_comp,1,IntVect{0});
87  MultiFab::Subtract(vars_new[crse_lev][Vars::cons],base_state[crse_lev],
88  BaseState::r0_comp,Rho_comp,1,IntVect{0});
89  MultiFab::Subtract(vars_new[crse_lev][Vars::cons],base_state[crse_lev],
90  BaseState::th0_comp,RhoTheta_comp,1,IntVect{0});
91  }
92 
93  average_down(vars_new[crse_lev+1][Vars::cons],vars_new[crse_lev ][Vars::cons],
94  scomp, ncomp, refRatio(crse_lev));
95 
96  if (interpolation_type == StateInterpType::Perturbational) {
97  // Restore the fine data to what it was
98  MultiFab::Add(vars_new[fine_lev][Vars::cons],base_state[fine_lev],
99  BaseState::r0_comp,Rho_comp,1,IntVect{0});
100  MultiFab::Add(vars_new[fine_lev][Vars::cons],base_state[fine_lev],
101  BaseState::th0_comp,RhoTheta_comp,1,IntVect{0});
102  MultiFab::Multiply(vars_new[fine_lev][Vars::cons],vars_new[fine_lev][Vars::cons],
103  Rho_comp,RhoTheta_comp,1,IntVect{0});
104 
105  // Make the crse data be full values not perturbational
106  MultiFab::Add(vars_new[crse_lev][Vars::cons],base_state[crse_lev],
107  BaseState::r0_comp,Rho_comp,1,IntVect{0});
108  MultiFab::Add(vars_new[crse_lev][Vars::cons],base_state[crse_lev],
109  BaseState::th0_comp,RhoTheta_comp,1,IntVect{0});
110  MultiFab::Multiply(vars_new[crse_lev][Vars::cons],vars_new[crse_lev][Vars::cons],
111  Rho_comp,RhoTheta_comp,1,IntVect{0});
112  }
113 
114  vars_new[crse_lev][Vars::cons].FillBoundary(geom[crse_lev].periodicity());
115 
116  // Here we multiply (rho S) by m^2 after average down
117  for (int lev = crse_lev; lev <= crse_lev+1; lev++) {
118  for (MFIter mfi(vars_new[lev][Vars::cons], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
119  const Box& bx = mfi.tilebox();
120  const Array4< Real> cons_arr = vars_new[lev][Vars::cons].array(mfi);
121  const Array4<const Real> mapfac_arr = mapfac_m[lev]->const_array(mfi);
122  if (SolverChoice::terrain_type != TerrainType::None) {
123  const Array4<const Real> detJ_arr = detJ_cc[lev]->const_array(mfi);
124  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
125  {
126  cons_arr(i,j,k,scomp+n) *= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0)) / detJ_arr(i,j,k);
127  });
128  } else {
129  ParallelFor(bx, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
130  {
131  cons_arr(i,j,k,scomp+n) *= (mapfac_arr(i,j,0)*mapfac_arr(i,j,0));
132  });
133  }
134  } // mfi
135  } // lev
136 
137  // ******************************************************************************************
138  // Now average down momenta.
139  // Note that vars_new holds velocities not momenta, but we want to do conservative
140  // averaging so we first convert to momentum, then average down, then convert
141  // back to velocities -- only on the valid region
142  // ******************************************************************************************
143  for (int lev = crse_lev; lev <= crse_lev+1; lev++)
144  {
145  // FillBoundary for density so we can go back and forth between velocity and momentum
146  vars_new[lev][Vars::cons].FillBoundary(geom[lev].periodicity());
147 
148  VelocityToMomentum(vars_new[lev][Vars::xvel], IntVect(0,0,0),
149  vars_new[lev][Vars::yvel], IntVect(0,0,0),
150  vars_new[lev][Vars::zvel], IntVect(0,0,0),
151  vars_new[lev][Vars::cons],
152  rU_new[lev],
153  rV_new[lev],
154  rW_new[lev],
155  Geom(lev).Domain(),
157  }
158 
159  average_down_faces(rU_new[crse_lev+1], rU_new[crse_lev], refRatio(crse_lev), geom[crse_lev]);
160  average_down_faces(rV_new[crse_lev+1], rV_new[crse_lev], refRatio(crse_lev), geom[crse_lev]);
161  average_down_faces(rW_new[crse_lev+1], rW_new[crse_lev], refRatio(crse_lev), geom[crse_lev]);
162 
163  for (int lev = crse_lev; lev <= crse_lev+1; lev++) {
165  vars_new[lev][Vars::yvel],
166  vars_new[lev][Vars::zvel],
167  vars_new[lev][Vars::cons],
168  rU_new[lev],
169  rV_new[lev],
170  rW_new[lev],
171  Geom(lev).Domain(),
173  }
174 }
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: ERF_MomentumToVelocity.cpp:25
static StateInterpType interpolation_type
Definition: ERF.H:1032
@ th0_comp
Definition: ERF_IndexDefines.H:66
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
430 {
431  // Mask for zeroing covered cells
432  AMREX_ASSERT(level > 0);
433 
434  const BoxArray& cba = grids[level-1];
435  const DistributionMapping& cdm = dmap[level-1];
436 
437  // TODO -- we should make a vector of these a member of ERF class
438  fine_mask.define(cba, cdm, 1, 0, MFInfo());
439  fine_mask.setVal(1.0);
440 
441  BoxArray fba = grids[level];
442  iMultiFab ifine_mask = makeFineMask(cba, cdm, fba, ref_ratio[level-1], 1, 0);
443 
444  const auto fma = fine_mask.arrays();
445  const auto ifma = ifine_mask.arrays();
446  ParallelFor(fine_mask, [=] AMREX_GPU_DEVICE(int bno, int i, int j, int k) noexcept
447  {
448  fma[bno](i,j,k) = ifma[bno](i,j,k);
449  });
450 
451  return fine_mask;
452 }
amrex::MultiFab fine_mask
Definition: ERF.H:1138

◆ ClearLevel()

void ERF::ClearLevel ( int  lev)
override
458 {
459  for (int var_idx = 0; var_idx < Vars::NumTypes; ++var_idx) {
460  vars_new[lev][var_idx].clear();
461  vars_old[lev][var_idx].clear();
462  }
463 
464  base_state[lev].clear();
465 
466  rU_new[lev].clear();
467  rU_old[lev].clear();
468  rV_new[lev].clear();
469  rV_old[lev].clear();
470  rW_new[lev].clear();
471  rW_old[lev].clear();
472 
473  if (lev > 0) {
474  zmom_crse_rhs[lev].clear();
475  }
476 
477  if (solverChoice.anelastic[lev] == 1) {
478  pp_inc[lev].clear();
479  }
480 
481  // Clears the integrator memory
482  mri_integrator_mem[lev].reset();
483 
484  // Clears the physical boundary condition routines
485  physbcs_cons[lev].reset();
486  physbcs_u[lev].reset();
487  physbcs_v[lev].reset();
488  physbcs_w[lev].reset();
489  physbcs_base[lev].reset();
490 
491  // Clears the flux register array
492  advflux_reg[lev]->reset();
493 }
amrex::Vector< amrex::MultiFab > pp_inc
Definition: ERF.H:734
amrex::Vector< amrex::YAFluxRegister * > advflux_reg
Definition: ERF.H:859
amrex::Vector< std::unique_ptr< ERFPhysBCFunct_base > > physbcs_base
Definition: ERF.H:741
@ NumTypes
Definition: ERF_IndexDefines.H:133

◆ cloud_fraction()

Real ERF::cloud_fraction ( amrex::Real  time)
174 {
175  BL_PROFILE("ERF::cloud_fraction()");
176 
177  int lev = 0;
178  // This holds all of qc
179  MultiFab qc(vars_new[lev][Vars::cons],make_alias,RhoQ2_comp,1);
180 
181  int direction = 2; // z-direction
182  Box const& domain = geom[lev].Domain();
183 
184  auto const& qc_arr = qc.const_arrays();
185 
186  // qc_2d is an BaseFab<int> holding the max value over the column
187  auto qc_2d = ReduceToPlane<ReduceOpMax,int>(direction, domain, qc,
188  [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) -> int
189  {
190  if (qc_arr[box_no](i,j,k) > 0) {
191  return 1;
192  } else {
193  return 0;
194  }
195  });
196 
197  auto* p = qc_2d.dataPtr();
198 
199  Long numpts = qc_2d.numPts();
200 
201  AMREX_ASSERT(numpts < Long(std::numeric_limits<int>::max));
202 
203 #if 1
204  if (ParallelDescriptor::UseGpuAwareMpi()) {
205  ParallelDescriptor::ReduceIntMax(p,static_cast<int>(numpts));
206  } else {
207  Gpu::PinnedVector<int> hv(numpts);
208  Gpu::copyAsync(Gpu::deviceToHost, p, p+numpts, hv.data());
209  Gpu::streamSynchronize();
210  ParallelDescriptor::ReduceIntMax(hv.data(),static_cast<int>(numpts));
211  Gpu::copyAsync(Gpu::hostToDevice, hv.data(), hv.data()+numpts, p);
212  }
213 
214  // Sum over component 0
215  Long num_cloudy = qc_2d.template sum<RunOn::Device>(0);
216 
217 #else
218  //
219  // We need this if we allow domain decomposition in the vertical
220  // but for now we leave it commented out
221  //
222  Long num_cloudy = Reduce::Sum<Long>(numpts,
223  [=] AMREX_GPU_DEVICE (Long i) -> Long {
224  if (p[i] == 1) {
225  return 1;
226  } else {
227  return 0;
228  }
229  });
230  ParallelDescriptor::ReduceLongSum(num_cloudy);
231 #endif
232 
233  Real num_total = qc_2d.box().d_numPts();
234 
235  Real cloud_frac = num_cloudy / num_total;
236 
237  return cloud_frac;
238 }
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:43

◆ compute_divergence()

void ERF::compute_divergence ( int  lev,
amrex::MultiFab &  rhs,
amrex::Vector< amrex::MultiFab > &  mom_mf,
amrex::Geometry const &  geom_at_lev 
)

Project the single-level velocity field to enforce incompressibility Note that the level may or may not be level 0.

11 {
12  BL_PROFILE("ERF::compute_divergence()");
13 
14  bool l_use_terrain = (solverChoice.terrain_type != TerrainType::None);
15 
16  auto dxInv = geom[lev].InvCellSizeArray();
17 
18  Array<MultiFab const*, AMREX_SPACEDIM> rho0_u_const;
19  rho0_u_const[0] = &mom_mf[IntVars::xmom];
20  rho0_u_const[1] = &mom_mf[IntVars::ymom];
21  rho0_u_const[2] = &mom_mf[IntVars::zmom];
22 
23  // ****************************************************************************
24  // Compute divergence which will form RHS
25  // Note that we replace "rho0w" with the contravariant momentum, Omega
26  // ****************************************************************************
27 #ifdef ERF_USE_EB
28  bool already_on_centroids = true;
29  EB_computeDivergence(rhs, rho0_u_const, geom_at_lev, already_on_centroids);
30 #else
31  if (l_use_terrain && SolverChoice::terrain_is_flat)
32  {
33  for ( MFIter mfi(rhs,TilingIfNotGPU()); mfi.isValid(); ++mfi)
34  {
35  Box bx = mfi.tilebox();
36  const Array4<Real const>& rho0u_arr = mom_mf[IntVars::xmom].const_array(mfi);
37  const Array4<Real const>& rho0v_arr = mom_mf[IntVars::ymom].const_array(mfi);
38  const Array4<Real const>& rho0w_arr = mom_mf[IntVars::zmom].const_array(mfi);
39  const Array4<Real >& rhs_arr = rhs.array(mfi);
40 
41  Real* stretched_dz_d_ptr = stretched_dz_d[lev].data();
42  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept {
43  Real dz = stretched_dz_d_ptr[k];
44  rhs_arr(i,j,k) = (rho0u_arr(i+1,j,k) - rho0u_arr(i,j,k)) * dxInv[0]
45  +(rho0v_arr(i,j+1,k) - rho0v_arr(i,j,k)) * dxInv[1]
46  +(rho0w_arr(i,j,k+1) - rho0w_arr(i,j,k)) / dz;
47  });
48  } // mfi
49  }
50  else if (l_use_terrain) // terrain is not flat
51  {
52  //
53  // Note we compute the divergence using "rho0w" == Omega
54  //
55  for ( MFIter mfi(rhs,TilingIfNotGPU()); mfi.isValid(); ++mfi)
56  {
57  Box bx = mfi.tilebox();
58  const Array4<Real >& rho0u_arr = mom_mf[IntVars::xmom].array(mfi);
59  const Array4<Real >& rho0v_arr = mom_mf[IntVars::ymom].array(mfi);
60  const Array4<Real >& rho0w_arr = mom_mf[IntVars::zmom].array(mfi);
61  const Array4<Real >& rhs_arr = rhs.array(mfi);
62 
63  const Array4<Real const>& ax_arr = ax[lev]->const_array(mfi);
64  const Array4<Real const>& ay_arr = ay[lev]->const_array(mfi);
65  const Array4<Real const>& az_arr = az[lev]->const_array(mfi);
66  const Array4<Real const>& dJ_arr = detJ_cc[lev]->const_array(mfi);
67 
68  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
69  {
70  rhs_arr(i,j,k) = ((ax_arr(i+1,j,k)*rho0u_arr(i+1,j,k) - ax_arr(i,j,k)*rho0u_arr(i,j,k)) * dxInv[0]
71  +(ay_arr(i,j+1,k)*rho0v_arr(i,j+1,k) - ay_arr(i,j,k)*rho0v_arr(i,j,k)) * dxInv[1]
72  +(az_arr(i,j,k+1)*rho0w_arr(i,j,k+1) - az_arr(i,j,k)*rho0w_arr(i,j,k)) * dxInv[2]) / dJ_arr(i,j,k);
73  });
74  } // mfi
75 
76  }
77  else // no terrain
78  {
79  computeDivergence(rhs, rho0_u_const, geom_at_lev);
80  }
81 #endif
82 }
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az
Definition: ERF.H:825
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > stretched_dz_d
Definition: ERF.H:846
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax
Definition: ERF.H:823
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay
Definition: ERF.H:824
static bool terrain_is_flat
Definition: ERF_DataStruct.H:526

◆ ComputeDt()

void ERF::ComputeDt ( int  step = -1)
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  if (step == 0){
29  dt_0 *= init_shrink;
30  if (verbose && init_shrink != 1.0) {
31  Print() << "Timestep 0: shrink initial dt at level " << lev << " by " << init_shrink << std::endl;
32  }
33  }
34  }
35 
36  // Limit dt's by the value of stop_time.
37  const Real eps = 1.e-3*dt_0;
38  if (t_new[0] + dt_0 > stop_time - eps) {
39  dt_0 = stop_time - t_new[0];
40  }
41 
42  dt[0] = dt_0;
43  for (int lev = 1; lev <= finest_level; ++lev) {
44  dt[lev] = dt[lev-1] / nsubsteps[lev];
45  }
46 }
amrex::Real stop_time
Definition: ERF.H:902
amrex::Vector< amrex::Real > t_new
Definition: ERF.H:717
amrex::Real estTimeStep(int lev, long &dt_fast_ratio) const
Definition: ERF_ComputeTimestep.cpp:55
amrex::Vector< int > nsubsteps
Definition: ERF.H:714
static amrex::Real init_shrink
Definition: ERF.H:909
static amrex::Real change_max
Definition: ERF.H:910

◆ ComputeGhostCells()

static AMREX_FORCE_INLINE int ERF::ComputeGhostCells ( const AdvChoice advChoice,
bool  use_num_diff 
)
inlinestaticprivate
1145  {
1146  if (use_num_diff)
1147  {
1148  return 3;
1149  } else {
1150  if (
1156  || (advChoice.dryscal_vert_adv_type == AdvType::Centered_6th) )
1157  { return 3; }
1158  else if (
1160  || (advChoice.dycore_vert_adv_type == AdvType::Upwind_5th)
1164  || (advChoice.dryscal_vert_adv_type == AdvType::Upwind_5th) )
1165  { return 3; }
1166  else if (
1168  || (advChoice.dryscal_vert_adv_type == AdvType::Weno_5)
1169  || (advChoice.moistscal_horiz_adv_type == AdvType::Weno_5)
1170  || (advChoice.moistscal_vert_adv_type == AdvType::Weno_5)
1171  || (advChoice.moistscal_horiz_adv_type == AdvType::Weno_5Z)
1172  || (advChoice.moistscal_vert_adv_type == AdvType::Weno_5Z)
1173  || (advChoice.dryscal_horiz_adv_type == AdvType::Weno_5Z)
1174  || (advChoice.dryscal_vert_adv_type == AdvType::Weno_5Z) )
1175  { return 3; }
1176  else if (
1178  || (advChoice.dryscal_vert_adv_type == AdvType::Weno_7)
1179  || (advChoice.moistscal_horiz_adv_type == AdvType::Weno_7)
1180  || (advChoice.moistscal_vert_adv_type == AdvType::Weno_7)
1181  || (advChoice.moistscal_horiz_adv_type == AdvType::Weno_7Z)
1182  || (advChoice.moistscal_vert_adv_type == AdvType::Weno_7Z)
1183  || (advChoice.dryscal_horiz_adv_type == AdvType::Weno_7Z)
1184  || (advChoice.dryscal_vert_adv_type == AdvType::Weno_7Z) )
1185  { return 4; }
1186  else
1187  { return 2; }
1188  }
1189  }
@ Centered_6th
AdvType moistscal_horiz_adv_type
Definition: ERF_AdvStruct.H:285
AdvType dycore_vert_adv_type
Definition: ERF_AdvStruct.H:282
AdvType moistscal_vert_adv_type
Definition: ERF_AdvStruct.H:286
AdvType dryscal_horiz_adv_type
Definition: ERF_AdvStruct.H:283
AdvType dycore_horiz_adv_type
Definition: ERF_AdvStruct.H:281
AdvType dryscal_vert_adv_type
Definition: ERF_AdvStruct.H:284

◆ Construct_ERFFillPatchers()

void ERF::Construct_ERFFillPatchers ( int  lev)
private
1877 {
1878  auto& fine_new = vars_new[lev];
1879  auto& crse_new = vars_new[lev-1];
1880  auto& ba_fine = fine_new[Vars::cons].boxArray();
1881  auto& ba_crse = crse_new[Vars::cons].boxArray();
1882  auto& dm_fine = fine_new[Vars::cons].DistributionMap();
1883  auto& dm_crse = crse_new[Vars::cons].DistributionMap();
1884 
1885  int ncomp = vars_new[lev][Vars::cons].nComp();
1886 
1887  FPr_c.emplace_back(ba_fine, dm_fine, geom[lev] ,
1888  ba_crse, dm_crse, geom[lev-1],
1889  -cf_width, -cf_set_width, ncomp, &cell_cons_interp);
1890  FPr_u.emplace_back(convert(ba_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
1891  convert(ba_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
1892  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1893  FPr_v.emplace_back(convert(ba_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
1894  convert(ba_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
1895  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1896  FPr_w.emplace_back(convert(ba_fine, IntVect(0,0,1)), dm_fine, geom[lev] ,
1897  convert(ba_crse, IntVect(0,0,1)), dm_crse, geom[lev-1],
1898  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1899 }
int cf_set_width
Definition: ERF.H:793

◆ DataLog()

AMREX_FORCE_INLINE std::ostream& ERF::DataLog ( int  i)
inlineprivate
1200  {
1201  return *datalog[i];
1202  }
amrex::Vector< std::unique_ptr< std::fstream > > datalog
Definition: ERF.H:1335

◆ DataLogName()

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

The filename of the ith datalog file.

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

◆ Define_ERFFillPatchers()

void ERF::Define_ERFFillPatchers ( int  lev)
private
1903 {
1904  auto& fine_new = vars_new[lev];
1905  auto& crse_new = vars_new[lev-1];
1906  auto& ba_fine = fine_new[Vars::cons].boxArray();
1907  auto& ba_crse = crse_new[Vars::cons].boxArray();
1908  auto& dm_fine = fine_new[Vars::cons].DistributionMap();
1909  auto& dm_crse = crse_new[Vars::cons].DistributionMap();
1910 
1911  int ncomp = fine_new[Vars::cons].nComp();
1912 
1913  FPr_c[lev-1].Define(ba_fine, dm_fine, geom[lev] ,
1914  ba_crse, dm_crse, geom[lev-1],
1915  -cf_width, -cf_set_width, ncomp, &cell_cons_interp);
1916  FPr_u[lev-1].Define(convert(ba_fine, IntVect(1,0,0)), dm_fine, geom[lev] ,
1917  convert(ba_crse, IntVect(1,0,0)), dm_crse, geom[lev-1],
1918  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1919  FPr_v[lev-1].Define(convert(ba_fine, IntVect(0,1,0)), dm_fine, geom[lev] ,
1920  convert(ba_crse, IntVect(0,1,0)), dm_crse, geom[lev-1],
1921  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1922  FPr_w[lev-1].Define(convert(ba_fine, IntVect(0,0,1)), dm_fine, geom[lev] ,
1923  convert(ba_crse, IntVect(0,0,1)), dm_crse, geom[lev-1],
1924  -cf_width, -cf_set_width, 1, &face_cons_linear_interp);
1925 }

◆ derive_diag_profiles()

void ERF::derive_diag_profiles ( amrex::Real  time,
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_Kmv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_Khv,
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_qi,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qs,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qg,
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,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wthv 
)

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
207 {
208  // We assume that this is always called at level 0
209  int lev = 0;
210 
211  bool l_use_kturb = ((solverChoice.turbChoice[lev].les_type != LESType::None) ||
212  (solverChoice.turbChoice[lev].pbl_type != PBLType::None));
213  bool l_use_KE = ( (solverChoice.turbChoice[lev].les_type == LESType::Deardorff) ||
214  (solverChoice.turbChoice[lev].pbl_type == PBLType::MYNN25) );
215 
216  // This will hold rho, theta, ksgs, Kmh, Kmv, uu, uv, uw, vv, vw, ww, uth, vth, wth,
217  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
218  // thth, uiuiu, uiuiv, uiuiw, p, pu, pv, pw, qv, qc, qr, wqv, wqc, wqr,
219  // 14 15 16 17 18 19 20 21 22 23 24 25 26 27
220  // qi, qs, qg, wthv
221  // 28 29 30 31
222  MultiFab mf_out(grids[lev], dmap[lev], 32, 0);
223 
224  MultiFab mf_vels(grids[lev], dmap[lev], AMREX_SPACEDIM, 0);
225 
226  MultiFab u_cc(mf_vels, make_alias, 0, 1); // u at cell centers
227  MultiFab v_cc(mf_vels, make_alias, 1, 1); // v at cell centers
228  MultiFab w_cc(mf_vels, make_alias, 2, 1); // w at cell centers
229 
230  average_face_to_cellcenter(mf_vels,0,
231  Array<const MultiFab*,3>{&vars_new[lev][Vars::xvel],&vars_new[lev][Vars::yvel],&vars_new[lev][Vars::zvel]});
232 
233  int zdir = 2;
234  auto domain = geom[0].Domain();
235 
236  // Sum in the horizontal plane
237  h_avg_u = sumToLine(mf_vels ,0,1,domain,zdir);
238  h_avg_v = sumToLine(mf_vels ,1,1,domain,zdir);
239  h_avg_w = sumToLine(mf_vels ,2,1,domain,zdir);
240 
241  int hu_size = h_avg_u.size();
242 
243  // Divide by the total number of cells we are averaging over
244  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
245  for (int k = 0; k < hu_size; ++k) {
246  h_avg_u[k] /= area_z; h_avg_v[k] /= area_z; h_avg_w[k] /= area_z;
247  }
248 
249  Gpu::DeviceVector<Real> d_avg_u(hu_size, Real(0.0));
250  Gpu::DeviceVector<Real> d_avg_v(hu_size, Real(0.0));
251  Gpu::DeviceVector<Real> d_avg_w(hu_size, Real(0.0));
252 
253 #if 0
254  auto* avg_u_ptr = d_avg_u.data();
255  auto* avg_v_ptr = d_avg_v.data();
256  auto* avg_w_ptr = d_avg_w.data();
257 #endif
258 
259  Gpu::copy(Gpu::hostToDevice, h_avg_u.begin(), h_avg_u.end(), d_avg_u.begin());
260  Gpu::copy(Gpu::hostToDevice, h_avg_v.begin(), h_avg_v.end(), d_avg_v.begin());
261  Gpu::copy(Gpu::hostToDevice, h_avg_w.begin(), h_avg_w.end(), d_avg_w.begin());
262 
263  int nvars = vars_new[lev][Vars::cons].nComp();
264  MultiFab mf_cons(vars_new[lev][Vars::cons], make_alias, 0, nvars);
265 
266  MultiFab p_hse (base_state[lev], make_alias, BaseState::p0_comp, 1);
267 
268  bool use_moisture = (solverChoice.moisture_type != MoistureType::None);
269 
270  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
271  {
272  const Box& bx = mfi.tilebox();
273  const Array4<Real>& fab_arr = mf_out.array(mfi);
274  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
275  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
276  const Array4<Real>& w_cc_arr = w_cc.array(mfi);
277  const Array4<Real>& cons_arr = mf_cons.array(mfi);
278  const Array4<Real>& p0_arr = p_hse.array(mfi);
279  const Array4<const Real>& eta_arr = (l_use_kturb) ? eddyDiffs_lev[lev]->const_array(mfi) :
280  Array4<const Real>{};
281 
282  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
283  {
284  Real theta = cons_arr(i,j,k,RhoTheta_comp) / cons_arr(i,j,k,Rho_comp);
285  fab_arr(i, j, k, 0) = cons_arr(i,j,k,Rho_comp);
286  fab_arr(i, j, k, 1) = theta;
287  Real ksgs = 0.0;
288  if (l_use_KE) {
289  ksgs = cons_arr(i,j,k,RhoKE_comp) / cons_arr(i,j,k,Rho_comp);
290  }
291  fab_arr(i, j, k, 2) = ksgs;
292 #if 1
293  if (l_use_kturb) {
294  fab_arr(i, j, k, 3) = eta_arr(i,j,k,EddyDiff::Mom_v); // Kmv
295  fab_arr(i, j, k, 4) = eta_arr(i,j,k,EddyDiff::Theta_v); // Khv
296  } else {
297  fab_arr(i, j, k, 3) = 0.0;
298  fab_arr(i, j, k, 4) = 0.0;
299  }
300 #else
301  // Here we hijack the "Kturb" variable name to print out the resolved kinetic energy
302  Real upert = u_cc_arr(i,j,k) - avg_u_ptr[k];
303  Real vpert = v_cc_arr(i,j,k) - avg_v_ptr[k];
304  Real wpert = w_cc_arr(i,j,k) - avg_w_ptr[k];
305  fab_arr(i, j, k, 3) = 0.5 * (upert*upert + vpert*vpert + wpert*wpert);
306 #endif
307  fab_arr(i, j, k, 5) = u_cc_arr(i,j,k) * u_cc_arr(i,j,k); // u*u
308  fab_arr(i, j, k, 6) = u_cc_arr(i,j,k) * v_cc_arr(i,j,k); // u*v
309  fab_arr(i, j, k, 7) = u_cc_arr(i,j,k) * w_cc_arr(i,j,k); // u*w
310  fab_arr(i, j, k, 8) = v_cc_arr(i,j,k) * v_cc_arr(i,j,k); // v*v
311  fab_arr(i, j, k, 9) = v_cc_arr(i,j,k) * w_cc_arr(i,j,k); // v*w
312  fab_arr(i, j, k,10) = w_cc_arr(i,j,k) * w_cc_arr(i,j,k); // w*w
313  fab_arr(i, j, k,11) = u_cc_arr(i,j,k) * theta; // u*th
314  fab_arr(i, j, k,12) = v_cc_arr(i,j,k) * theta; // v*th
315  fab_arr(i, j, k,13) = w_cc_arr(i,j,k) * theta; // w*th
316  fab_arr(i, j, k,14) = theta * theta; // th*th
317 
318  // if the number of fields is changed above, then be sure to update
319  // the following def!
320  Real uiui = fab_arr(i,j,k,5) + fab_arr(i,j,k,8) + fab_arr(i,j,k,10);
321  fab_arr(i, j, k,15) = uiui * u_cc_arr(i,j,k); // (ui*ui)*u
322  fab_arr(i, j, k,16) = uiui * v_cc_arr(i,j,k); // (ui*ui)*v
323  fab_arr(i, j, k,17) = uiui * w_cc_arr(i,j,k); // (ui*ui)*w
324 
325  if (!use_moisture) {
326  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp));
327  p -= p0_arr(i,j,k);
328  fab_arr(i, j, k,18) = p; // p
329  fab_arr(i, j, k,19) = p * u_cc_arr(i,j,k); // p*u
330  fab_arr(i, j, k,20) = p * v_cc_arr(i,j,k); // p*v
331  fab_arr(i, j, k,21) = p * w_cc_arr(i,j,k); // p*w
332  fab_arr(i, j, k,22) = 0.; // qv
333  fab_arr(i, j, k,23) = 0.; // qc
334  fab_arr(i, j, k,24) = 0.; // qr
335  fab_arr(i, j, k,25) = 0.; // w*qv
336  fab_arr(i, j, k,26) = 0.; // w*qc
337  fab_arr(i, j, k,27) = 0.; // w*qr
338  fab_arr(i, j, k,28) = 0.; // qi
339  fab_arr(i, j, k,29) = 0.; // qs
340  fab_arr(i, j, k,30) = 0.; // qg
341  fab_arr(i, j, k,31) = 0.; // w*thv
342  }
343  });
344  } // mfi
345 
346  if (use_moisture)
347  {
348  int n_qstate = micro->Get_Qstate_Size();
349 
350  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
351  {
352  const Box& bx = mfi.tilebox();
353  const Array4<Real>& fab_arr = mf_out.array(mfi);
354  const Array4<Real>& cons_arr = mf_cons.array(mfi);
355  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
356  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
357  const Array4<Real>& w_cc_arr = w_cc.array(mfi);
358  const Array4<Real>& p0_arr = p_hse.array(mfi);
359  const Array4<Real>& qv_arr = qmoist[0][0]->array(mfi); // TODO: Is this written only on lev 0?
360 
361  int rhoqr_comp = solverChoice.RhoQr_comp;
362 
363  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
364  {
365  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_arr(i,j,k));
366 
367  p -= p0_arr(i,j,k);
368  fab_arr(i, j, k,18) = p; // p
369  fab_arr(i, j, k,19) = p * u_cc_arr(i,j,k); // p*u
370  fab_arr(i, j, k,20) = p * v_cc_arr(i,j,k); // p*v
371  fab_arr(i, j, k,21) = p * w_cc_arr(i,j,k); // p*w
372  fab_arr(i, j, k,22) = cons_arr(i,j,k,RhoQ1_comp) / cons_arr(i,j,k,Rho_comp); // qv
373  fab_arr(i, j, k,23) = cons_arr(i,j,k,RhoQ2_comp) / cons_arr(i,j,k,Rho_comp); // qc
374  if (rhoqr_comp > -1) {
375  fab_arr(i, j, k,24) = cons_arr(i,j,k,rhoqr_comp) / cons_arr(i,j,k,Rho_comp); // qr
376  } else {
377  fab_arr(i, j, k,24) = Real(0.0);
378  }
379  fab_arr(i, j, k,25) = w_cc_arr(i,j,k) * cons_arr(i,j,k,RhoQ1_comp) / cons_arr(i,j,k,Rho_comp); // w*qv
380  fab_arr(i, j, k,26) = w_cc_arr(i,j,k) * cons_arr(i,j,k,RhoQ2_comp) / cons_arr(i,j,k,Rho_comp); // w*qc
381  if (rhoqr_comp > -1) {
382  fab_arr(i, j, k,27) = w_cc_arr(i,j,k) * cons_arr(i,j,k,rhoqr_comp) / cons_arr(i,j,k,Rho_comp); // w*qr
383  } else {
384  fab_arr(i, j, k,27) = Real(0.0);
385  }
386  if (n_qstate > 3) {
387  fab_arr(i, j, k,28) = cons_arr(i,j,k,RhoQ3_comp) / cons_arr(i,j,k,Rho_comp); // qi
388  fab_arr(i, j, k,29) = cons_arr(i,j,k,RhoQ5_comp) / cons_arr(i,j,k,Rho_comp); // qs
389  fab_arr(i, j, k,30) = cons_arr(i,j,k,RhoQ6_comp) / cons_arr(i,j,k,Rho_comp); // qg
390  } else {
391  fab_arr(i, j, k,28) = 0.0; // qi
392  fab_arr(i, j, k,29) = 0.0; // qs
393  fab_arr(i, j, k,30) = 0.0; // qg
394  }
395  Real ql = fab_arr(i, j, k,22) + fab_arr(i, j, k,23);
396  Real theta = cons_arr(i,j,k,RhoTheta_comp) / cons_arr(i,j,k,Rho_comp);
397  Real thv = theta * (1 + 0.61*qv_arr(i,j,k) - ql);
398  fab_arr(i, j, k,31) = w_cc_arr(i,j,k) * thv; // w*thv
399  });
400  } // mfi
401  } // use_moisture
402 
403  h_avg_rho = sumToLine(mf_out, 0,1,domain,zdir);
404  h_avg_th = sumToLine(mf_out, 1,1,domain,zdir);
405  h_avg_ksgs = sumToLine(mf_out, 2,1,domain,zdir);
406  h_avg_Kmv = sumToLine(mf_out, 3,1,domain,zdir);
407  h_avg_Khv = sumToLine(mf_out, 4,1,domain,zdir);
408  h_avg_uu = sumToLine(mf_out, 5,1,domain,zdir);
409  h_avg_uv = sumToLine(mf_out, 6,1,domain,zdir);
410  h_avg_uw = sumToLine(mf_out, 7,1,domain,zdir);
411  h_avg_vv = sumToLine(mf_out, 8,1,domain,zdir);
412  h_avg_vw = sumToLine(mf_out, 9,1,domain,zdir);
413  h_avg_ww = sumToLine(mf_out,10,1,domain,zdir);
414  h_avg_uth = sumToLine(mf_out,11,1,domain,zdir);
415  h_avg_vth = sumToLine(mf_out,12,1,domain,zdir);
416  h_avg_wth = sumToLine(mf_out,13,1,domain,zdir);
417  h_avg_thth = sumToLine(mf_out,14,1,domain,zdir);
418  h_avg_uiuiu = sumToLine(mf_out,15,1,domain,zdir);
419  h_avg_uiuiv = sumToLine(mf_out,16,1,domain,zdir);
420  h_avg_uiuiw = sumToLine(mf_out,17,1,domain,zdir);
421  h_avg_p = sumToLine(mf_out,18,1,domain,zdir);
422  h_avg_pu = sumToLine(mf_out,19,1,domain,zdir);
423  h_avg_pv = sumToLine(mf_out,20,1,domain,zdir);
424  h_avg_pw = sumToLine(mf_out,21,1,domain,zdir);
425  h_avg_qv = sumToLine(mf_out,22,1,domain,zdir);
426  h_avg_qc = sumToLine(mf_out,23,1,domain,zdir);
427  h_avg_qr = sumToLine(mf_out,24,1,domain,zdir);
428  h_avg_wqv = sumToLine(mf_out,25,1,domain,zdir);
429  h_avg_wqc = sumToLine(mf_out,26,1,domain,zdir);
430  h_avg_wqr = sumToLine(mf_out,27,1,domain,zdir);
431  h_avg_qi = sumToLine(mf_out,28,1,domain,zdir);
432  h_avg_qs = sumToLine(mf_out,29,1,domain,zdir);
433  h_avg_qg = sumToLine(mf_out,30,1,domain,zdir);
434  h_avg_wthv = sumToLine(mf_out,31,1,domain,zdir);
435 
436  // Divide by the total number of cells we are averaging over
437  int h_avg_u_size = static_cast<int>(h_avg_u.size());
438  for (int k = 0; k < h_avg_u_size; ++k) {
439  h_avg_rho[k] /= area_z;
440  h_avg_ksgs[k] /= area_z;
441  h_avg_Kmv[k] /= area_z;
442  h_avg_Khv[k] /= area_z;
443  h_avg_th[k] /= area_z;
444  h_avg_thth[k] /= area_z;
445  h_avg_uu[k] /= area_z;
446  h_avg_uv[k] /= area_z;
447  h_avg_uw[k] /= area_z;
448  h_avg_vv[k] /= area_z;
449  h_avg_vw[k] /= area_z;
450  h_avg_ww[k] /= area_z;
451  h_avg_uth[k] /= area_z;
452  h_avg_vth[k] /= area_z;
453  h_avg_wth[k] /= area_z;
454  h_avg_uiuiu[k] /= area_z;
455  h_avg_uiuiv[k] /= area_z;
456  h_avg_uiuiw[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  h_avg_pw[k] /= area_z;
461  h_avg_qv[k] /= area_z;
462  h_avg_qc[k] /= area_z;
463  h_avg_qr[k] /= area_z;
464  h_avg_wqv[k] /= area_z;
465  h_avg_wqc[k] /= area_z;
466  h_avg_wqr[k] /= area_z;
467  h_avg_qi[k] /= area_z;
468  h_avg_qs[k] /= area_z;
469  h_avg_qg[k] /= area_z;
470  h_avg_wthv[k] /= area_z;
471  }
472 
473 #if 0
474  // Here we print the integrated total kinetic energy as computed in the 1D profile above
475  Real sum = 0.;
476  Real dz = geom[0].ProbHi(2) / static_cast<Real>(h_avg_u_size);
477  for (int k = 0; k < h_avg_u_size; ++k) {
478  sum += h_avg_kturb[k] * h_avg_rho[k] * dz;
479  }
480  amrex::Print() << "ITKE " << time << " " << sum << " using " << h_avg_u_size << " " << dz << std::endl;
481 #endif
482 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=0.)
Definition: ERF_EOS.H:84
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:44
#define RhoQ6_comp
Definition: ERF_IndexDefines.H:47
#define RhoQ5_comp
Definition: ERF_IndexDefines.H:46
#define RhoKE_comp
Definition: ERF_IndexDefines.H:38
amrex::Vector< amrex::Vector< amrex::MultiFab * > > qmoist
Definition: ERF.H:761
@ Theta_v
Definition: ERF_IndexDefines.H:157
@ Mom_v
Definition: ERF_IndexDefines.H:156
@ theta
Definition: ERF_MM5.H:20
Here is the call graph for this function:

◆ derive_diag_profiles_stag()

void ERF::derive_diag_profiles_stag ( amrex::Real  time,
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_Kmv,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_Khv,
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_qi,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qs,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_qg,
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,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_wthv 
)

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
313 {
314  // We assume that this is always called at level 0
315  int lev = 0;
316 
317  bool l_use_kturb = ((solverChoice.turbChoice[lev].les_type != LESType::None) ||
318  (solverChoice.turbChoice[lev].pbl_type != PBLType::None));
319  bool l_use_KE = ( (solverChoice.turbChoice[lev].les_type == LESType::Deardorff) ||
320  (solverChoice.turbChoice[lev].pbl_type == PBLType::MYNN25) );
321 
322  // Note: "uiui" == u_i*u_i = u*u + v*v + w*w
323  // This will hold rho, theta, ksgs, Kmh, Kmv, uu, uv, vv, uth, vth,
324  // indices: 0 1 2 3 4 5 6 7 8 9
325  // thth, uiuiu, uiuiv, p, pu, pv, qv, qc, qr, qi, qs, qg
326  // 10 11 12 13 14 15 16 17 18 19 20 21
327  MultiFab mf_out(grids[lev], dmap[lev], 22, 0);
328 
329  // This will hold uw, vw, ww, wth, uiuiw, pw, wqv, wqc, wqr, wthv
330  // indices: 0 1 2 3 4 5 6 7 8 9
331  MultiFab mf_out_stag(convert(grids[lev], IntVect(0,0,1)), dmap[lev], 10, 0);
332 
333  // This is only used to average u and v; w is not averaged to cell centers
334  MultiFab mf_vels(grids[lev], dmap[lev], 2, 0);
335 
336  MultiFab u_cc(mf_vels, make_alias, 0, 1); // u at cell centers
337  MultiFab v_cc(mf_vels, make_alias, 1, 1); // v at cell centers
338  MultiFab w_fc(vars_new[lev][Vars::zvel], make_alias, 0, 1); // w at face centers (staggered)
339 
340  int zdir = 2;
341  auto domain = geom[0].Domain();
342  Box stag_domain = domain;
343  stag_domain.convert(IntVect(0,0,1));
344 
345  int nvars = vars_new[lev][Vars::cons].nComp();
346  MultiFab mf_cons(vars_new[lev][Vars::cons], make_alias, 0, nvars);
347 
348  MultiFab p_hse (base_state[lev], make_alias, BaseState::p0_comp, 1);
349 
350  bool use_moisture = (solverChoice.moisture_type != MoistureType::None);
351 
352  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
353  {
354  const Box& bx = mfi.tilebox();
355  const Array4<Real>& fab_arr = mf_out.array(mfi);
356  const Array4<Real>& fab_arr_stag = mf_out_stag.array(mfi);
357  const Array4<Real>& u_arr = vars_new[lev][Vars::xvel].array(mfi);
358  const Array4<Real>& v_arr = vars_new[lev][Vars::yvel].array(mfi);
359  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
360  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
361  const Array4<Real>& w_fc_arr = w_fc.array(mfi);
362  const Array4<Real>& cons_arr = mf_cons.array(mfi);
363  const Array4<Real>& p0_arr = p_hse.array(mfi);
364  const Array4<const Real>& eta_arr = (l_use_kturb) ? eddyDiffs_lev[lev]->const_array(mfi) :
365  Array4<const Real>{};
366 
367  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
368  {
369  u_cc_arr(i,j,k) = 0.5 * (u_arr(i,j,k) + u_arr(i+1,j ,k));
370  v_cc_arr(i,j,k) = 0.5 * (v_arr(i,j,k) + v_arr(i ,j+1,k));
371 
372  Real theta = cons_arr(i,j,k,RhoTheta_comp) / cons_arr(i,j,k,Rho_comp);
373  fab_arr(i, j, k, 0) = cons_arr(i,j,k,Rho_comp);
374  fab_arr(i, j, k, 1) = theta;
375  Real ksgs = 0.0;
376  if (l_use_KE) {
377  ksgs = cons_arr(i,j,k,RhoKE_comp) / cons_arr(i,j,k,Rho_comp);
378  }
379  fab_arr(i, j, k, 2) = ksgs;
380  if (l_use_kturb) {
381  fab_arr(i, j, k, 3) = eta_arr(i,j,k,EddyDiff::Mom_v); // Kmv
382  fab_arr(i, j, k, 4) = eta_arr(i,j,k,EddyDiff::Theta_v); // Khv
383  } else {
384  fab_arr(i, j, k, 3) = 0.0;
385  fab_arr(i, j, k, 4) = 0.0;
386  }
387  fab_arr(i, j, k, 5) = u_cc_arr(i,j,k) * u_cc_arr(i,j,k); // u*u
388  fab_arr(i, j, k, 6) = u_cc_arr(i,j,k) * v_cc_arr(i,j,k); // u*v
389  fab_arr(i, j, k, 7) = v_cc_arr(i,j,k) * v_cc_arr(i,j,k); // v*v
390  fab_arr(i, j, k, 8) = u_cc_arr(i,j,k) * theta; // u*th
391  fab_arr(i, j, k, 9) = v_cc_arr(i,j,k) * theta; // v*th
392  fab_arr(i, j, k,10) = theta * theta; // th*th
393 
394  Real wcc = 0.5 * (w_fc_arr(i,j,k) + w_fc_arr(i,j,k+1));
395 
396  // if the number of fields is changed above, then be sure to update
397  // the following def!
398  Real uiui = fab_arr(i,j,k,5) + fab_arr(i,j,k,7) + wcc*wcc;
399  fab_arr(i, j, k,11) = uiui * u_cc_arr(i,j,k); // (ui*ui)*u
400  fab_arr(i, j, k,12) = uiui * v_cc_arr(i,j,k); // (ui*ui)*v
401 
402  if (!use_moisture) {
403  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp));
404  p -= p0_arr(i,j,k);
405  fab_arr(i, j, k,13) = p; // p
406  fab_arr(i, j, k,14) = p * u_cc_arr(i,j,k); // p*u
407  fab_arr(i, j, k,15) = p * v_cc_arr(i,j,k); // p*v
408  fab_arr(i, j, k,16) = 0.; // qv
409  fab_arr(i, j, k,17) = 0.; // qc
410  fab_arr(i, j, k,18) = 0.; // qr
411  fab_arr(i, j, k,19) = 0.; // qi
412  fab_arr(i, j, k,20) = 0.; // qs
413  fab_arr(i, j, k,21) = 0.; // qg
414  }
415  });
416 
417  const Box& zbx = mfi.tilebox(IntVect(0,0,1));
418  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
419  {
420  // average to z faces (first to cell centers, then in z)
421  Real uface = 0.25 * ( u_arr(i ,j,k) + u_arr(i ,j,k-1)
422  + u_arr(i+1,j,k) + u_arr(i+1,j,k-1));
423  Real vface = 0.25 * ( v_arr(i,j ,k) + v_arr(i,j ,k-1)
424  + v_arr(i,j+1,k) + v_arr(i,j+1,k-1));
425  Real theta0 = cons_arr(i,j,k ,RhoTheta_comp) / cons_arr(i,j,k ,Rho_comp);
426  Real theta1 = cons_arr(i,j,k-1,RhoTheta_comp) / cons_arr(i,j,k-1,Rho_comp);
427  Real thface = 0.5*(theta0 + theta1);
428  fab_arr_stag(i,j,k,0) = uface * w_fc_arr(i,j,k); // u*w
429  fab_arr_stag(i,j,k,1) = vface * w_fc_arr(i,j,k); // v*w
430  fab_arr_stag(i,j,k,2) = w_fc_arr(i,j,k) * w_fc_arr(i,j,k); // w*w
431  fab_arr_stag(i,j,k,3) = thface * w_fc_arr(i,j,k); // th*w
432  Real uiui = uface*uface + vface*vface + fab_arr_stag(i,j,k,2);
433  fab_arr_stag(i,j,k,4) = uiui * w_fc_arr(i,j,k); // (ui*ui)*w
434  if (!use_moisture) {
435  Real p0 = getPgivenRTh(cons_arr(i, j, k , RhoTheta_comp)) - p0_arr(i,j,k );
436  Real p1 = getPgivenRTh(cons_arr(i, j, k-1, RhoTheta_comp)) - p0_arr(i,j,k-1);
437  Real pface = 0.5 * (p0 + p1);
438  fab_arr_stag(i,j,k,5) = pface * w_fc_arr(i,j,k); // p*w
439  fab_arr_stag(i,j,k,6) = 0.; // w*qv
440  fab_arr_stag(i,j,k,7) = 0.; // w*qc
441  fab_arr_stag(i,j,k,8) = 0.; // w*qr
442  fab_arr_stag(i,j,k,9) = 0.; // w*thv
443  }
444  });
445 
446  } // mfi
447 
448  if (use_moisture)
449  {
450  int n_qstate = micro->Get_Qstate_Size();
451 
452  for ( MFIter mfi(mf_cons,TilingIfNotGPU()); mfi.isValid(); ++mfi)
453  {
454  const Box& bx = mfi.tilebox();
455  const Array4<Real>& fab_arr = mf_out.array(mfi);
456  const Array4<Real>& fab_arr_stag = mf_out_stag.array(mfi);
457  const Array4<Real>& cons_arr = mf_cons.array(mfi);
458  const Array4<Real>& u_cc_arr = u_cc.array(mfi);
459  const Array4<Real>& v_cc_arr = v_cc.array(mfi);
460  const Array4<Real>& w_fc_arr = w_fc.array(mfi);
461  const Array4<Real>& p0_arr = p_hse.array(mfi);
462  const Array4<Real>& qv_arr = qmoist[0][0]->array(mfi); // TODO: Is this written only on lev 0?
463 
464  int rhoqr_comp = solverChoice.RhoQr_comp;
465 
466  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
467  {
468  Real p = getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_arr(i,j,k));
469 
470  p -= p0_arr(i,j,k);
471  fab_arr(i, j, k,13) = p; // p
472  fab_arr(i, j, k,14) = p * u_cc_arr(i,j,k); // p*u
473  fab_arr(i, j, k,15) = p * v_cc_arr(i,j,k); // p*v
474  fab_arr(i, j, k,16) = cons_arr(i,j,k,RhoQ1_comp) / cons_arr(i,j,k,Rho_comp); // qv
475  fab_arr(i, j, k,17) = cons_arr(i,j,k,RhoQ2_comp) / cons_arr(i,j,k,Rho_comp); // qc
476  fab_arr(i, j, k,18) = cons_arr(i,j,k,rhoqr_comp) / cons_arr(i,j,k,Rho_comp); // qr
477  if (n_qstate > 3) { // SAM model
478  fab_arr(i, j, k,19) = cons_arr(i,j,k,RhoQ3_comp) / cons_arr(i,j,k,Rho_comp); // qi
479  fab_arr(i, j, k,20) = cons_arr(i,j,k,RhoQ5_comp) / cons_arr(i,j,k,Rho_comp); // qs
480  fab_arr(i, j, k,21) = cons_arr(i,j,k,RhoQ6_comp) / cons_arr(i,j,k,Rho_comp); // qg
481  } else {
482  fab_arr(i, j, k,19) = 0.0; // qi
483  fab_arr(i, j, k,20) = 0.0; // qs
484  fab_arr(i, j, k,21) = 0.0; // qg
485  }
486  });
487 
488  const Box& zbx = mfi.tilebox(IntVect(0,0,1));
489  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
490  {
491  Real p0 = getPgivenRTh(cons_arr(i, j, k , RhoTheta_comp), qv_arr(i,j,k )) - p0_arr(i,j,k );
492  Real p1 = getPgivenRTh(cons_arr(i, j, k-1, RhoTheta_comp), qv_arr(i,j,k-1)) - p0_arr(i,j,k-1);
493  Real pface = 0.5 * (p0 + p1);
494 
495  Real qv0 = cons_arr(i,j,k ,RhoQ1_comp) / cons_arr(i,j,k ,Rho_comp);
496  Real qv1 = cons_arr(i,j,k-1,RhoQ1_comp) / cons_arr(i,j,k-1,Rho_comp);
497  Real qc0 = cons_arr(i,j,k ,RhoQ2_comp) / cons_arr(i,j,k ,Rho_comp);
498  Real qc1 = cons_arr(i,j,k-1,RhoQ2_comp) / cons_arr(i,j,k-1,Rho_comp);
499  Real qr0 = cons_arr(i,j,k ,RhoQ3_comp) / cons_arr(i,j,k ,Rho_comp);
500  Real qr1 = cons_arr(i,j,k-1,RhoQ3_comp) / cons_arr(i,j,k-1,Rho_comp);
501  Real qvface = 0.5 * (qv0 + qv1);
502  Real qcface = 0.5 * (qc0 + qc1);
503  Real qrface = 0.5 * (qr0 + qr1);
504 
505  Real theta0 = cons_arr(i,j,k ,RhoTheta_comp) / cons_arr(i,j,k ,Rho_comp);
506  Real theta1 = cons_arr(i,j,k-1,RhoTheta_comp) / cons_arr(i,j,k-1,Rho_comp);
507  Real thface = 0.5*(theta0 + theta1);
508  Real ql = qcface + qrface;
509  Real thv = thface * (1 + 0.61*qvface - ql);
510 
511  fab_arr_stag(i,j,k,5) = pface * w_fc_arr(i,j,k); // p*w
512  fab_arr_stag(i,j,k,6) = qvface * w_fc_arr(i,j,k); // w*qv
513  fab_arr_stag(i,j,k,7) = qcface * w_fc_arr(i,j,k); // w*qc
514  fab_arr_stag(i,j,k,8) = qrface * w_fc_arr(i,j,k); // w*qr
515  fab_arr_stag(i,j,k,9) = thv * w_fc_arr(i,j,k); // w*thv
516  });
517  } // mfi
518  } // use_moisture
519 
520  // Sum in the horizontal plane
521  h_avg_u = sumToLine(u_cc,0,1, domain,zdir);
522  h_avg_v = sumToLine(v_cc,0,1, domain,zdir);
523  h_avg_w = sumToLine(w_fc,0,1,stag_domain,zdir);
524 
525  h_avg_rho = sumToLine(mf_out, 0,1,domain,zdir);
526  h_avg_th = sumToLine(mf_out, 1,1,domain,zdir);
527  h_avg_ksgs = sumToLine(mf_out, 2,1,domain,zdir);
528  h_avg_Kmv = sumToLine(mf_out, 3,1,domain,zdir);
529  h_avg_Khv = sumToLine(mf_out, 4,1,domain,zdir);
530  h_avg_uu = sumToLine(mf_out, 5,1,domain,zdir);
531  h_avg_uv = sumToLine(mf_out, 6,1,domain,zdir);
532  h_avg_vv = sumToLine(mf_out, 7,1,domain,zdir);
533  h_avg_uth = sumToLine(mf_out, 8,1,domain,zdir);
534  h_avg_vth = sumToLine(mf_out, 9,1,domain,zdir);
535  h_avg_thth = sumToLine(mf_out,10,1,domain,zdir);
536  h_avg_uiuiu = sumToLine(mf_out,11,1,domain,zdir);
537  h_avg_uiuiv = sumToLine(mf_out,12,1,domain,zdir);
538  h_avg_p = sumToLine(mf_out,13,1,domain,zdir);
539  h_avg_pu = sumToLine(mf_out,14,1,domain,zdir);
540  h_avg_pv = sumToLine(mf_out,15,1,domain,zdir);
541  h_avg_qv = sumToLine(mf_out,16,1,domain,zdir);
542  h_avg_qc = sumToLine(mf_out,17,1,domain,zdir);
543  h_avg_qr = sumToLine(mf_out,18,1,domain,zdir);
544  h_avg_qi = sumToLine(mf_out,19,1,domain,zdir);
545  h_avg_qs = sumToLine(mf_out,20,1,domain,zdir);
546  h_avg_qg = sumToLine(mf_out,21,1,domain,zdir);
547 
548  h_avg_uw = sumToLine(mf_out_stag,0,1,stag_domain,zdir);
549  h_avg_vw = sumToLine(mf_out_stag,1,1,stag_domain,zdir);
550  h_avg_ww = sumToLine(mf_out_stag,2,1,stag_domain,zdir);
551  h_avg_wth = sumToLine(mf_out_stag,3,1,stag_domain,zdir);
552  h_avg_uiuiw = sumToLine(mf_out_stag,4,1,stag_domain,zdir);
553  h_avg_pw = sumToLine(mf_out_stag,5,1,stag_domain,zdir);
554  h_avg_wqv = sumToLine(mf_out_stag,6,1,stag_domain,zdir);
555  h_avg_wqc = sumToLine(mf_out_stag,7,1,stag_domain,zdir);
556  h_avg_wqr = sumToLine(mf_out_stag,8,1,stag_domain,zdir);
557  h_avg_wthv = sumToLine(mf_out_stag,9,1,stag_domain,zdir);
558 
559  // Divide by the total number of cells we are averaging over
560  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
561  int unstag_size = h_avg_w.size() - 1; // _un_staggered heights
562  for (int k = 0; k < unstag_size; ++k) {
563  h_avg_u[k] /= area_z;
564  h_avg_v[k] /= area_z;
565  h_avg_rho[k] /= area_z;
566  h_avg_ksgs[k] /= area_z;
567  h_avg_Kmv[k] /= area_z;
568  h_avg_Khv[k] /= area_z;
569  h_avg_th[k] /= area_z;
570  h_avg_thth[k] /= area_z;
571  h_avg_uu[k] /= area_z;
572  h_avg_uv[k] /= area_z;
573  h_avg_vv[k] /= area_z;
574  h_avg_uth[k] /= area_z;
575  h_avg_vth[k] /= area_z;
576  h_avg_uiuiu[k] /= area_z;
577  h_avg_uiuiv[k] /= area_z;
578  h_avg_p[k] /= area_z;
579  h_avg_pu[k] /= area_z;
580  h_avg_pv[k] /= area_z;
581  h_avg_qv[k] /= area_z;
582  h_avg_qc[k] /= area_z;
583  h_avg_qr[k] /= area_z;
584  h_avg_qi[k] /= area_z;
585  h_avg_qs[k] /= area_z;
586  h_avg_qg[k] /= area_z;
587  }
588 
589  for (int k = 0; k < unstag_size+1; ++k) { // staggered heights
590  h_avg_w[k] /= area_z;
591  h_avg_uw[k] /= area_z;
592  h_avg_vw[k] /= area_z;
593  h_avg_ww[k] /= area_z;
594  h_avg_wth[k] /= area_z;
595  h_avg_uiuiw[k] /= area_z;
596  h_avg_pw[k] /= area_z;
597  h_avg_wqv[k] /= area_z;
598  h_avg_wqc[k] /= area_z;
599  h_avg_wqr[k] /= area_z;
600  h_avg_wthv[k] /= area_z;
601  }
602 }
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_q1fx3,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_q2fx3,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_diss 
)
490 {
491  int lev = 0;
492 
493  // This will hold the stress tensor components
494  MultiFab mf_out(grids[lev], dmap[lev], 10, 0);
495 
496  bool l_use_moist = ( solverChoice.moisture_type != MoistureType::None );
497 
498  for ( MFIter mfi(mf_out,TilingIfNotGPU()); mfi.isValid(); ++mfi)
499  {
500  const Box& bx = mfi.tilebox();
501  const Array4<Real>& fab_arr = mf_out.array(mfi);
502 
503  // NOTE: These are from the last RK stage...
504  const Array4<const Real>& tau11_arr = Tau11_lev[lev]->const_array(mfi);
505  const Array4<const Real>& tau12_arr = Tau12_lev[lev]->const_array(mfi);
506  const Array4<const Real>& tau13_arr = Tau13_lev[lev]->const_array(mfi);
507  const Array4<const Real>& tau22_arr = Tau22_lev[lev]->const_array(mfi);
508  const Array4<const Real>& tau23_arr = Tau23_lev[lev]->const_array(mfi);
509  const Array4<const Real>& tau33_arr = Tau33_lev[lev]->const_array(mfi);
510 
511  // These should be re-calculated during ERF_slow_rhs_post
512  // -- just vertical SFS kinematic heat flux for now
513  //const Array4<const Real>& hfx1_arr = SFS_hfx1_lev[lev]->const_array(mfi);
514  //const Array4<const Real>& hfx2_arr = SFS_hfx2_lev[lev]->const_array(mfi);
515  const Array4<const Real>& hfx3_arr = SFS_hfx3_lev[lev]->const_array(mfi);
516  const Array4<const Real>& q1fx3_arr = (l_use_moist) ? SFS_q1fx3_lev[lev]->const_array(mfi) :
517  Array4<const Real>{};
518  const Array4<const Real>& q2fx3_arr = (l_use_moist) ? SFS_q2fx3_lev[lev]->const_array(mfi) :
519  Array4<const Real>{};
520  const Array4<const Real>& diss_arr = SFS_diss_lev[lev]->const_array(mfi);
521 
522  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
523  {
524  fab_arr(i, j, k, 0) = tau11_arr(i,j,k);
525  fab_arr(i, j, k, 1) = 0.25 * ( tau12_arr(i,j ,k) + tau12_arr(i+1,j ,k)
526  + tau12_arr(i,j+1,k) + tau12_arr(i+1,j+1,k) );
527  fab_arr(i, j, k, 2) = 0.25 * ( tau13_arr(i,j,k ) + tau13_arr(i+1,j,k)
528  + tau13_arr(i,j,k+1) + tau13_arr(i+1,j,k+1) );
529  fab_arr(i, j, k, 3) = tau22_arr(i,j,k);
530  fab_arr(i, j, k, 4) = 0.25 * ( tau23_arr(i,j,k ) + tau23_arr(i,j+1,k)
531  + tau23_arr(i,j,k+1) + tau23_arr(i,j+1,k+1) );
532  fab_arr(i, j, k, 5) = tau33_arr(i,j,k);
533  fab_arr(i, j, k, 6) = 0.5 * ( hfx3_arr(i,j,k) + hfx3_arr(i,j,k+1) );
534  fab_arr(i, j, k, 7) = (l_use_moist) ? 0.5 * ( q1fx3_arr(i,j,k) + q1fx3_arr(i,j,k+1) ) : 0.0;
535  fab_arr(i, j, k, 8) = (l_use_moist) ? 0.5 * ( q2fx3_arr(i,j,k) + q2fx3_arr(i,j,k+1) ) : 0.0;
536  fab_arr(i, j, k, 9) = diss_arr(i,j,k);
537  });
538  }
539 
540  int zdir = 2;
541  auto domain = geom[0].Domain();
542 
543  h_avg_tau11 = sumToLine(mf_out,0,1,domain,zdir);
544  h_avg_tau12 = sumToLine(mf_out,1,1,domain,zdir);
545  h_avg_tau13 = sumToLine(mf_out,2,1,domain,zdir);
546  h_avg_tau22 = sumToLine(mf_out,3,1,domain,zdir);
547  h_avg_tau23 = sumToLine(mf_out,4,1,domain,zdir);
548  h_avg_tau33 = sumToLine(mf_out,5,1,domain,zdir);
549  h_avg_hfx3 = sumToLine(mf_out,6,1,domain,zdir);
550  h_avg_q1fx3 = sumToLine(mf_out,7,1,domain,zdir);
551  h_avg_q2fx3 = sumToLine(mf_out,8,1,domain,zdir);
552  h_avg_diss = sumToLine(mf_out,9,1,domain,zdir);
553 
554  int ht_size = h_avg_tau11.size();
555 
556  // Divide by the total number of cells we are averaging over
557  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
558  for (int k = 0; k < ht_size; ++k) {
559  h_avg_tau11[k] /= area_z; h_avg_tau12[k] /= area_z; h_avg_tau13[k] /= area_z;
560  h_avg_tau22[k] /= area_z; h_avg_tau23[k] /= area_z;
561  h_avg_tau33[k] /= area_z;
562  h_avg_hfx3[k] /= area_z;
563  h_avg_q1fx3[k] /= area_z; h_avg_q2fx3[k] /= area_z;
564  h_avg_diss[k] /= area_z;
565  }
566 }

◆ 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_q1fx3,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_q2fx3,
amrex::Gpu::HostVector< amrex::Real > &  h_avg_diss 
)
610 {
611  int lev = 0;
612 
613  // This will hold the stress tensor components
614  MultiFab mf_out(grids[lev], dmap[lev], 10, 0);
615 
616  // This will hold Tau13 and Tau23
617  MultiFab mf_out_stag(convert(grids[lev], IntVect(0,0,1)), dmap[lev], 5, 0);
618 
619  bool l_use_moist = ( solverChoice.moisture_type != MoistureType::None );
620 
621  for ( MFIter mfi(mf_out,TilingIfNotGPU()); mfi.isValid(); ++mfi)
622  {
623  const Box& bx = mfi.tilebox();
624  const Array4<Real>& fab_arr = mf_out.array(mfi);
625  const Array4<Real>& fab_arr_stag = mf_out_stag.array(mfi);
626 
627  // NOTE: These are from the last RK stage...
628  const Array4<const Real>& tau11_arr = Tau11_lev[lev]->const_array(mfi);
629  const Array4<const Real>& tau12_arr = Tau12_lev[lev]->const_array(mfi);
630  const Array4<const Real>& tau13_arr = Tau13_lev[lev]->const_array(mfi);
631  const Array4<const Real>& tau22_arr = Tau22_lev[lev]->const_array(mfi);
632  const Array4<const Real>& tau23_arr = Tau23_lev[lev]->const_array(mfi);
633  const Array4<const Real>& tau33_arr = Tau33_lev[lev]->const_array(mfi);
634 
635  // These should be re-calculated during ERF_slow_rhs_post
636  // -- just vertical SFS kinematic heat flux for now
637  //const Array4<const Real>& hfx1_arr = SFS_hfx1_lev[lev]->const_array(mfi);
638  //const Array4<const Real>& hfx2_arr = SFS_hfx2_lev[lev]->const_array(mfi);
639  const Array4<const Real>& hfx3_arr = SFS_hfx3_lev[lev]->const_array(mfi);
640  const Array4<const Real>& q1fx3_arr = (l_use_moist) ? SFS_q1fx3_lev[lev]->const_array(mfi) :
641  Array4<const Real>{};
642  const Array4<const Real>& q2fx3_arr = (l_use_moist) ? SFS_q2fx3_lev[lev]->const_array(mfi) :
643  Array4<const Real>{};
644  const Array4<const Real>& diss_arr = SFS_diss_lev[lev]->const_array(mfi);
645 
646  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
647  {
648  fab_arr(i, j, k, 0) = tau11_arr(i,j,k);
649  fab_arr(i, j, k, 1) = 0.25 * ( tau12_arr(i,j ,k) + tau12_arr(i+1,j ,k)
650  + tau12_arr(i,j+1,k) + tau12_arr(i+1,j+1,k) );
651 // fab_arr(i, j, k, 2) = 0.25 * ( tau13_arr(i,j,k ) + tau13_arr(i+1,j,k)
652 // + tau13_arr(i,j,k+1) + tau13_arr(i+1,j,k+1) );
653  fab_arr(i, j, k, 3) = tau22_arr(i,j,k);
654 // fab_arr(i, j, k, 4) = 0.25 * ( tau23_arr(i,j,k ) + tau23_arr(i,j+1,k)
655 // + tau23_arr(i,j,k+1) + tau23_arr(i,j+1,k+1) );
656  fab_arr(i, j, k, 5) = tau33_arr(i,j,k);
657 // fab_arr(i, j, k, 6) = hfx3_arr(i,j,k);
658 // fab_arr(i, j, k, 7) = (l_use_moist) ? q1fx3_arr(i,j,k) : 0.0;
659 // fab_arr(i, j, k, 8) = (l_use_moist) ? q2fx3_arr(i,j,k) : 0.0;
660  fab_arr(i, j, k, 9) = diss_arr(i,j,k);
661  });
662 
663  const Box& zbx = mfi.tilebox(IntVect(0,0,1));
664  ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
665  {
666  // average from edge to face center
667  fab_arr_stag(i,j,k,0) = 0.5*(tau13_arr(i,j,k) + tau13_arr(i+1,j ,k));
668  fab_arr_stag(i,j,k,1) = 0.5*(tau23_arr(i,j,k) + tau23_arr(i ,j+1,k));
669 
670  fab_arr_stag(i,j,k,2) = hfx3_arr(i,j,k);
671  fab_arr_stag(i,j,k,3) = (l_use_moist) ? q1fx3_arr(i,j,k) : 0.0;
672  fab_arr_stag(i,j,k,4) = (l_use_moist) ? q2fx3_arr(i,j,k) : 0.0;
673  });
674  }
675 
676  int zdir = 2;
677  auto domain = geom[0].Domain();
678  Box stag_domain = domain;
679  stag_domain.convert(IntVect(0,0,1));
680 
681  h_avg_tau11 = sumToLine(mf_out,0,1,domain,zdir);
682  h_avg_tau12 = sumToLine(mf_out,1,1,domain,zdir);
683 // h_avg_tau13 = sumToLine(mf_out,2,1,domain,zdir);
684  h_avg_tau22 = sumToLine(mf_out,3,1,domain,zdir);
685 // h_avg_tau23 = sumToLine(mf_out,4,1,domain,zdir);
686  h_avg_tau33 = sumToLine(mf_out,5,1,domain,zdir);
687 // h_avg_hfx3 = sumToLine(mf_out,6,1,domain,zdir);
688 // h_avg_q1fx3 = sumToLine(mf_out,7,1,domain,zdir);
689 // h_avg_q2fx3 = sumToLine(mf_out,8,1,domain,zdir);
690  h_avg_diss = sumToLine(mf_out,9,1,domain,zdir);
691 
692  h_avg_tau13 = sumToLine(mf_out_stag,0,1,stag_domain,zdir);
693  h_avg_tau23 = sumToLine(mf_out_stag,1,1,stag_domain,zdir);
694  h_avg_hfx3 = sumToLine(mf_out_stag,2,1,stag_domain,zdir);
695  h_avg_q1fx3 = sumToLine(mf_out_stag,3,1,stag_domain,zdir);
696  h_avg_q2fx3 = sumToLine(mf_out_stag,4,1,stag_domain,zdir);
697 
698  int ht_size = h_avg_tau11.size(); // _un_staggered
699 
700  // Divide by the total number of cells we are averaging over
701  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
702  for (int k = 0; k < ht_size; ++k) {
703  h_avg_tau11[k] /= area_z; h_avg_tau12[k] /= area_z;
704  h_avg_tau22[k] /= area_z;
705  h_avg_tau33[k] /= area_z;
706  h_avg_diss[k] /= area_z;
707  }
708  for (int k = 0; k < ht_size+1; ++k) { // staggered heights
709  h_avg_tau13[k] /= area_z;
710  h_avg_tau23[k] /= area_z;
711  h_avg_hfx3[k] /= area_z;
712  h_avg_q1fx3[k] /= area_z; h_avg_q2fx3[k] /= area_z;
713  }
714 }

◆ 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,
amrex::MultiFab &  th,
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
152 {
153  Real l_gravity = solverChoice.gravity;
154  bool l_use_terrain = (solverChoice.terrain_type != TerrainType::None);
155 
156  const auto geomdata = geom[lev].data();
157  const Real dz = geomdata.CellSize(2);
158 
159  for ( MFIter mfi(dens, TileNoZ()); mfi.isValid(); ++mfi )
160  {
161  // Create a flat box with same horizontal extent but only one cell in vertical
162  const Box& tbz = mfi.nodaltilebox(2);
163  int klo = tbz.smallEnd(2);
164  int khi = tbz.bigEnd(2);
165 
166  // Note we only grow by 1 because that is how big z_cc is.
167  Box b2d = tbz; // Copy constructor
168  b2d.grow(0,1);
169  b2d.grow(1,1);
170  b2d.setRange(2,0);
171 
172  // We integrate to the first cell (and below) by using rho in this cell
173  // If gravity == 0 this is constant pressure
174  // If gravity != 0, hence this is a wall, this gives gp0 = dens[0] * gravity
175  // (dens_hse*gravity would also be dens[0]*gravity because we use foextrap for rho at k = -1)
176  // Note ng_pres_hse = 1
177 
178  // We start by assuming pressure on the ground is p_0 (in ERF_Constants.H)
179  // Note that gravity is positive
180 
181  Array4<Real> rho_arr = dens.array(mfi);
182  Array4<Real> pres_arr = pres.array(mfi);
183  Array4<Real> pi_arr = pi.array(mfi);
184  Array4<Real> th_arr = theta.array(mfi);
185  Array4<Real> zcc_arr;
186  if (l_use_terrain) {
187  zcc_arr = z_cc->array(mfi);
188  }
189 
190  const Real rdOcp = solverChoice.rdOcp;
191 
192  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int)
193  {
194  // Set value at surface from Newton iteration for rho
195  if (klo == 0)
196  {
197  // Physical height of the terrain at cell center
198  Real hz;
199  if (l_use_terrain) {
200  hz = zcc_arr(i,j,klo);
201  } else {
202  hz = 0.5*dz;
203  }
204 
205  pres_arr(i,j,klo) = p_0 - hz * rho_arr(i,j,klo) * l_gravity;
206  pi_arr(i,j,klo) = getExnergivenP(pres_arr(i,j,klo), rdOcp);
207  th_arr(i,j,klo) =getRhoThetagivenP(pres_arr(i,j,klo)) / rho_arr(i,j,klo);
208 
209  //
210  // Set ghost cell with dz and rho at boundary
211  // (We will set the rest of the ghost cells in the boundary condition routine)
212  //
213  pres_arr(i,j,klo-1) = p_0 + hz * rho_arr(i,j,klo) * l_gravity;
214  pi_arr(i,j,klo-1) = getExnergivenP(pres_arr(i,j,klo-1), rdOcp);
215  th_arr(i,j,klo-1) = getRhoThetagivenP(pres_arr(i,j,klo-1)) / rho_arr(i,j,klo-1);
216 
217  } else {
218 
219  // If level > 0 and klo > 0, we need to use the value of pres_arr(i,j,klo-1) which was
220  // filled from FillPatch-ing it.
221  Real dz_loc;
222  if (l_use_terrain) {
223  dz_loc = (zcc_arr(i,j,klo) - zcc_arr(i,j,klo-1));
224  } else {
225  dz_loc = dz;
226  }
227 
228  Real dens_interp = 0.5*(rho_arr(i,j,klo) + rho_arr(i,j,klo-1));
229  pres_arr(i,j,klo) = pres_arr(i,j,klo-1) - dz_loc * dens_interp * l_gravity;
230 
231  pi_arr(i,j,klo ) = getExnergivenP(pres_arr(i,j,klo ), rdOcp);
232  th_arr(i,j,klo ) = getRhoThetagivenP(pres_arr(i,j,klo )) / rho_arr(i,j,klo );
233 
234  pi_arr(i,j,klo-1) = getExnergivenP(pres_arr(i,j,klo-1), rdOcp);
235  th_arr(i,j,klo-1) = getRhoThetagivenP(pres_arr(i,j,klo-1)) / rho_arr(i,j,klo-1);
236  }
237 
238  Real dens_interp;
239  if (l_use_terrain) {
240  for (int k = klo+1; k <= khi; k++) {
241  Real dz_loc = (zcc_arr(i,j,k) - zcc_arr(i,j,k-1));
242  dens_interp = 0.5*(rho_arr(i,j,k) + rho_arr(i,j,k-1));
243  pres_arr(i,j,k) = pres_arr(i,j,k-1) - dz_loc * dens_interp * l_gravity;
244  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
245  th_arr(i,j,k) = getRhoThetagivenP(pres_arr(i,j,k)) / rho_arr(i,j,k);
246  }
247  } else {
248  for (int k = klo+1; k <= khi; k++) {
249  dens_interp = 0.5*(rho_arr(i,j,k) + rho_arr(i,j,k-1));
250  pres_arr(i,j,k) = pres_arr(i,j,k-1) - dz * dens_interp * l_gravity;
251  pi_arr(i,j,k) = getExnergivenP(pres_arr(i,j,k), rdOcp);
252  th_arr(i,j,k) = getRhoThetagivenP(pres_arr(i,j,k)) / rho_arr(i,j,k);
253  }
254  }
255  });
256 
257  } // mfi
258 
259  dens.FillBoundary(geom[lev].periodicity());
260  pres.FillBoundary(geom[lev].periodicity());
261  pi.FillBoundary(geom[lev].periodicity());
262  theta.FillBoundary(geom[lev].periodicity());
263 }
constexpr amrex::Real p_0
Definition: ERF_Constants.H:18
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getRhoThetagivenP(const amrex::Real p, const amrex::Real qv=0.0)
Definition: ERF_EOS.H:175
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getExnergivenP(const amrex::Real P, const amrex::Real rdOcp)
Definition: ERF_EOS.H:144
@ pres
Definition: ERF_Kessler.H:33
amrex::Real rdOcp
Definition: ERF_DataStruct.H:578
amrex::Real gravity
Definition: ERF_DataStruct.H:576
Here is the call graph for this function:

◆ ERF_shared()

void ERF::ERF_shared ( )
92 {
93  if (ParallelDescriptor::IOProcessor()) {
94  const char* erf_hash = buildInfoGetGitHash(1);
95  const char* amrex_hash = buildInfoGetGitHash(2);
96  const char* buildgithash = buildInfoGetBuildGitHash();
97  const char* buildgitname = buildInfoGetBuildGitName();
98 
99  if (strlen(erf_hash) > 0) {
100  Print() << "\n"
101  << "ERF git hash: " << erf_hash << "\n";
102  }
103  if (strlen(amrex_hash) > 0) {
104  Print() << "AMReX git hash: " << amrex_hash << "\n";
105  }
106  if (strlen(buildgithash) > 0) {
107  Print() << buildgitname << " git hash: " << buildgithash << "\n";
108  }
109 
110  Print() << "\n";
111  }
112 
113  int nlevs_max = max_level + 1;
114 
115 #ifdef ERF_USE_WINDFARM
116  Nturb.resize(nlevs_max);
117  vars_windfarm.resize(nlevs_max);
118  SMark.resize(nlevs_max);
119 #endif
120 
121 #if defined(ERF_USE_RRTMGP)
122  qheating_rates.resize(nlevs_max);
123  sw_lw_fluxes.resize(nlevs_max);
124  solar_zenith.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  // NOTE: size canopy model before readparams (if file exists, we construct)
133  m_forest.resize(nlevs_max);
134  for (int lev = 0; lev < max_level; ++lev) { m_forest[lev] = nullptr; }
135 
136  ReadParameters();
137  initializeMicrophysics(nlevs_max);
138 
139 #ifdef ERF_USE_WINDFARM
140  initializeWindFarm(nlevs_max);
141 #endif
142 
143  const std::string& pv1 = "plot_vars_1"; setPlotVariables(pv1,plot_var_names_1);
144  const std::string& pv2 = "plot_vars_2"; setPlotVariables(pv2,plot_var_names_2);
145 
146  // This is only used when we have flat terrain and stretched z levels.
147  stretched_dz_h.resize(nlevs_max);
148  stretched_dz_d.resize(nlevs_max);
149 
150  // Initialize staggered vertical levels for grid stretching or terrain, and
151  // to simplify Rayleigh damping layer calculations.
152  zlevels_stag.resize(max_level+1);
156  geom,
157  refRatio(),
160  solverChoice.dz0);
161 
162  if (SolverChoice::terrain_type != TerrainType::None) {
163  int nz = geom[0].Domain().length(2) + 1; // staggered
164  if (std::fabs(zlevels_stag[0][nz-1]-geom[0].ProbHi(2)) > 1.0e-4) {
165  Print() << "Note: prob_hi[2]=" << geom[0].ProbHi(2)
166  << " does not match highest requested z level " << zlevels_stag[0][nz-1]
167  << std::endl;
168  }
169  if (std::fabs(zlevels_stag[0][0]-geom[0].ProbLo(2)) > 1.0e-4) {
170  Print() << "Note: prob_lo[2]=" << geom[0].ProbLo(2)
171  << " does not match lowest requested level " << zlevels_stag[0][0]
172  << std::endl;
173  }
174 
175  // Redefine the problem domain here?
176  }
177 
178  prob = amrex_probinit(geom[0].ProbLo(),geom[0].ProbHi());
179 
180  // Geometry on all levels has been defined already.
181 
182  // No valid BoxArray and DistributionMapping have been defined.
183  // But the arrays for them have been resized.
184 
185  istep.resize(nlevs_max, 0);
186  nsubsteps.resize(nlevs_max, 1);
187  for (int lev = 1; lev <= max_level; ++lev) {
188  nsubsteps[lev] = MaxRefRatio(lev-1);
189  }
190 
191  t_new.resize(nlevs_max, 0.0);
192  t_old.resize(nlevs_max, -1.e100);
193  dt.resize(nlevs_max, 1.e100);
194  dt_mri_ratio.resize(nlevs_max, 1);
195 
196  vars_new.resize(nlevs_max);
197  vars_old.resize(nlevs_max);
198 
199  // We resize this regardless in order to pass it without error
200  pp_inc.resize(nlevs_max);
201 
202  rU_new.resize(nlevs_max);
203  rV_new.resize(nlevs_max);
204  rW_new.resize(nlevs_max);
205 
206  rU_old.resize(nlevs_max);
207  rV_old.resize(nlevs_max);
208  rW_old.resize(nlevs_max);
209 
210  // xmom_crse_rhs.resize(nlevs_max);
211  // ymom_crse_rhs.resize(nlevs_max);
212  zmom_crse_rhs.resize(nlevs_max);
213 
214  for (int lev = 0; lev < nlevs_max; ++lev) {
215  vars_new[lev].resize(Vars::NumTypes);
216  vars_old[lev].resize(Vars::NumTypes);
217  }
218 
219  // Time integrator
220  mri_integrator_mem.resize(nlevs_max);
221 
222  // Physical boundary conditions
223  physbcs_cons.resize(nlevs_max);
224  physbcs_u.resize(nlevs_max);
225  physbcs_v.resize(nlevs_max);
226  physbcs_w.resize(nlevs_max);
227  physbcs_base.resize(nlevs_max);
228 
229  // Planes to hold Dirichlet values at boundaries
230  xvel_bc_data.resize(nlevs_max);
231  yvel_bc_data.resize(nlevs_max);
232  zvel_bc_data.resize(nlevs_max);
233 
234  advflux_reg.resize(nlevs_max);
235 
236  // Stresses
237  Tau11_lev.resize(nlevs_max); Tau22_lev.resize(nlevs_max); Tau33_lev.resize(nlevs_max);
238  Tau12_lev.resize(nlevs_max); Tau21_lev.resize(nlevs_max);
239  Tau13_lev.resize(nlevs_max); Tau31_lev.resize(nlevs_max);
240  Tau23_lev.resize(nlevs_max); Tau32_lev.resize(nlevs_max);
241  SFS_hfx1_lev.resize(nlevs_max); SFS_hfx2_lev.resize(nlevs_max); SFS_hfx3_lev.resize(nlevs_max);
242  SFS_diss_lev.resize(nlevs_max);
243  SFS_q1fx1_lev.resize(nlevs_max); SFS_q1fx2_lev.resize(nlevs_max); SFS_q1fx3_lev.resize(nlevs_max);
244  SFS_q2fx3_lev.resize(nlevs_max);
245  eddyDiffs_lev.resize(nlevs_max);
246  SmnSmn_lev.resize(nlevs_max);
247 
248  // Sea surface temps
249  sst_lev.resize(nlevs_max);
250  lmask_lev.resize(nlevs_max);
251 
252  // Metric terms
253  z_phys_nd.resize(nlevs_max);
254  z_phys_cc.resize(nlevs_max);
255  detJ_cc.resize(nlevs_max);
256  ax.resize(nlevs_max);
257  ay.resize(nlevs_max);
258  az.resize(nlevs_max);
259 
260  z_phys_nd_new.resize(nlevs_max);
261  detJ_cc_new.resize(nlevs_max);
262  ax_new.resize(nlevs_max);
263  ay_new.resize(nlevs_max);
264  az_new.resize(nlevs_max);
265 
266  z_phys_nd_src.resize(nlevs_max);
267  detJ_cc_src.resize(nlevs_max);
268  ax_src.resize(nlevs_max);
269  ay_src.resize(nlevs_max);
270  az_src.resize(nlevs_max);
271 
272  z_t_rk.resize(nlevs_max);
273 
274  // Mapfactors
275  mapfac_m.resize(nlevs_max);
276  mapfac_u.resize(nlevs_max);
277  mapfac_v.resize(nlevs_max);
278 
279  // Thin immersed body
280  xflux_imask.resize(nlevs_max);
281  yflux_imask.resize(nlevs_max);
282  zflux_imask.resize(nlevs_max);
283  //overset_imask.resize(nlevs_max);
284  thin_xforce.resize(nlevs_max);
285  thin_yforce.resize(nlevs_max);
286  thin_zforce.resize(nlevs_max);
287 
288  // Base state
289  base_state.resize(nlevs_max);
290  base_state_new.resize(nlevs_max);
291 
292  // Wave coupling data
293  Hwave.resize(nlevs_max);
294  Lwave.resize(nlevs_max);
295  for (int lev = 0; lev < max_level; ++lev)
296  {
297  Hwave[lev] = nullptr;
298  Lwave[lev] = nullptr;
299  }
300  Hwave_onegrid.resize(nlevs_max);
301  Lwave_onegrid.resize(nlevs_max);
302  for (int lev = 0; lev < max_level; ++lev)
303  {
304  Hwave_onegrid[lev] = nullptr;
305  Lwave_onegrid[lev] = nullptr;
306  }
307 
308  // Theta prim for MOST
309  Theta_prim.resize(nlevs_max);
310 
311  // Qv prim for MOST
312  Qv_prim.resize(nlevs_max);
313 
314  // Qr prim for MOST
315  Qr_prim.resize(nlevs_max);
316 
317  // Time averaged velocity field
318  vel_t_avg.resize(nlevs_max);
319  t_avg_cnt.resize(nlevs_max);
320 
321 #ifdef ERF_USE_NETCDF
322  // Size lat long arrays if using netcdf
323  lat_m.resize(nlevs_max);
324  lon_m.resize(nlevs_max);
325  for (int lev = 0; lev < max_level; ++lev)
326  {
327  lat_m[lev] = nullptr;
328  lon_m[lev] = nullptr;
329  }
330 #endif
331 
332  // Initialize tagging criteria for mesh refinement
334 
335  for (int lev = 0; lev < max_level; ++lev)
336  {
337  Print() << "Refinement ratio at level " << lev+1 << " set to be " <<
338  ref_ratio[lev][0] << " " << ref_ratio[lev][1] << " " << ref_ratio[lev][2] << std::endl;
339  }
340 
341  // We will create each of these in MakeNewLevel.../RemakeLevel
342  m_factory.resize(max_level+1);
343 
344 #ifdef ERF_USE_EB
345  // This is needed before initializing level MultiFabs
346  MakeEBGeometry();
347 #endif
348 }
std::unique_ptr< ProblemBase > amrex_probinit(const amrex_real *problo, const amrex_real *probhi) AMREX_ATTRIBUTE_WEAK
void init_zlevels(Vector< Vector< Real >> &zlevels_stag, Vector< Vector< Real >> &stretched_dz_h, Vector< Gpu::DeviceVector< Real >> &stretched_dz_d, Vector< Geometry > const &geom, Vector< IntVect > const &ref_ratio, const Real grid_stretching_ratio, const Real zsurf, const Real dz0)
Definition: ERF_TerrainMetrics.cpp:11
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Hwave_onegrid
Definition: ERF.H:854
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_yforce
Definition: ERF.H:887
void setPlotVariables(const std::string &pp_plot_var_names, amrex::Vector< std::string > &plot_var_names)
Definition: ERF_Plotfile.cpp:18
amrex::Vector< std::unique_ptr< ForestDrag > > m_forest
Definition: ERF.H:1127
void ReadParameters()
Definition: ERF.cpp:1393
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay_new
Definition: ERF.H:836
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd_src
Definition: ERF.H:827
amrex::Vector< amrex::MultiFab > base_state_new
Definition: ERF.H:849
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::iMultiFab > > > lmask_lev
Definition: ERF.H:809
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_phys_nd_new
Definition: ERF.H:833
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_zforce
Definition: ERF.H:888
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > sst_lev
Definition: ERF.H:808
amrex::Vector< std::unique_ptr< amrex::MultiFab > > thin_xforce
Definition: ERF.H:886
amrex::Vector< std::string > plot_var_names_1
Definition: ERF.H:944
amrex::Vector< amrex::Real > t_old
Definition: ERF.H:718
amrex::Vector< std::unique_ptr< amrex::MultiFab > > z_t_rk
Definition: ERF.H:839
amrex::Vector< std::string > plot_var_names_2
Definition: ERF.H:945
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Lwave_onegrid
Definition: ERF.H:855
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > xvel_bc_data
Definition: ERF.H:682
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc_src
Definition: ERF.H:828
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ay_src
Definition: ERF.H:830
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > yflux_imask
Definition: ERF.H:881
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az_new
Definition: ERF.H:837
amrex::Vector< amrex::Vector< amrex::MultiFab * > > lsm_flux
Definition: ERF.H:778
void refinement_criteria_setup()
Definition: ERF_Tagging.cpp:105
amrex::Vector< std::unique_ptr< amrex::FabFactory< amrex::FArrayBox > > > m_factory
Definition: ERF.H:1376
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax_src
Definition: ERF.H:829
amrex::Vector< amrex::Vector< amrex::Real > > zlevels_stag
Definition: ERF.H:818
amrex::Vector< amrex::Vector< amrex::MultiFab * > > lsm_data
Definition: ERF.H:777
amrex::Vector< amrex::Vector< amrex::Real > > stretched_dz_h
Definition: ERF.H:845
amrex::Vector< std::unique_ptr< amrex::MultiFab > > az_src
Definition: ERF.H:831
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Lwave
Definition: ERF.H:853
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > zflux_imask
Definition: ERF.H:882
amrex::Vector< std::unique_ptr< amrex::MultiFab > > ax_new
Definition: ERF.H:835
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > zvel_bc_data
Definition: ERF.H:684
amrex::Vector< std::unique_ptr< amrex::MultiFab > > detJ_cc_new
Definition: ERF.H:834
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > yvel_bc_data
Definition: ERF.H:683
amrex::Vector< std::unique_ptr< amrex::MultiFab > > Hwave
Definition: ERF.H:852
amrex::Vector< int > istep
Definition: ERF.H:713
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > xflux_imask
Definition: ERF.H:880
void initializeMicrophysics(const int &)
Definition: ERF.cpp:1214
void ReSize(const int &nlev)
Definition: ERF_LandSurface.H:23
const char * buildInfoGetGitHash(int i)
amrex::Real dz0
Definition: ERF_DataStruct.H:583
amrex::Real grid_stretching_ratio
Definition: ERF_DataStruct.H:581
amrex::Real zsurf
Definition: ERF_DataStruct.H:582
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::Copy( *mf, vars_new[levc][Vars::cons], RhoQ1_comp, 0, 1, 0);
32  MultiFab::Divide(*mf, vars_new[levc][Vars::cons], Rho_comp, 0, 1, 0);
33 
34 
35  // This allows dynamic refinement based on the value of qc
36  } else if (ref_tags[j].Field() == "qc" ) {
37  MultiFab::Copy( *mf, vars_new[levc][Vars::cons], RhoQ2_comp, 0, 1, 0);
38  MultiFab::Divide(*mf, vars_new[levc][Vars::cons], Rho_comp, 0, 1, 0);
39 
40 
41  // This allows dynamic refinement based on the value of the scalar/pressure/theta
42  } else if ( (ref_tags[j].Field() == "scalar" ) ||
43  (ref_tags[j].Field() == "pressure") ||
44  (ref_tags[j].Field() == "theta" ) )
45  {
46  for (MFIter mfi(*mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
47  {
48  const Box& bx = mfi.tilebox();
49  auto& dfab = (*mf)[mfi];
50  auto& sfab = vars_new[levc][Vars::cons][mfi];
51  if (ref_tags[j].Field() == "scalar") {
52  derived::erf_derscalar(bx, dfab, 0, 1, sfab, Geom(levc), time, nullptr, levc);
53  } else if (ref_tags[j].Field() == "theta") {
54  derived::erf_dertheta(bx, dfab, 0, 1, sfab, Geom(levc), time, nullptr, levc);
55  }
56  } // mfi
57 #ifdef ERF_USE_PARTICLES
58  } else {
59  //
60  // This allows dynamic refinement based on the number of particles per cell
61  //
62  // Note that we must count all the particles in levels both at and above the current,
63  // since otherwise, e.g., if the particles are all at level 1, counting particles at
64  // level 0 will not trigger refinement when regridding so level 1 will disappear,
65  // then come back at the next regridding
66  //
67  const auto& particles_namelist( particleData.getNames() );
68  mf->setVal(0.0);
69  for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++)
70  {
71  std::string tmp_string(particles_namelist[i]+"_count");
72  IntVect rr = IntVect::TheUnitVector();
73  if (ref_tags[j].Field() == tmp_string) {
74  for (int lev = levc; lev <= finest_level; lev++)
75  {
76  MultiFab temp_dat(grids[lev], dmap[lev], 1, 0); temp_dat.setVal(0);
77  particleData[particles_namelist[i]]->IncrementWithTotal(temp_dat, lev);
78 
79  MultiFab temp_dat_crse(grids[levc], dmap[levc], 1, 0); temp_dat_crse.setVal(0);
80 
81  if (lev == levc) {
82  MultiFab::Copy(*mf, temp_dat, 0, 0, 1, 0);
83  } else {
84  for (int d = 0; d < AMREX_SPACEDIM; d++) {
85  rr[d] *= ref_ratio[levc][d];
86  }
87  average_down(temp_dat, temp_dat_crse, 0, 1, rr);
88  MultiFab::Add(*mf, temp_dat_crse, 0, 0, 1, 0);
89  }
90  }
91  }
92  }
93 #endif
94  }
95 
96  ref_tags[j](tags,mf.get(),clearval,tagval,time,levc,geom[levc]);
97  } // loop over j
98 }
static amrex::Vector< amrex::AMRErrorTag > ref_tags
Definition: ERF.H:1132
void erf_derscalar(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: ERF_Derive.cpp:165
void erf_dertheta(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const Geometry &, Real, const int *, const int)
Definition: ERF_Derive.cpp:144
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
56 {
57  BL_PROFILE("ERF::estTimeStep()");
58 
59  Real estdt_comp = 1.e20;
60  Real estdt_lowM = 1.e20;
61 
62  // We intentionally use the level 0 domain to compute whether to use this direction in the dt calculation
63  const int nxc = geom[0].Domain().length(0);
64  const int nyc = geom[0].Domain().length(1);
65 
66  auto const dxinv = geom[level].InvCellSizeArray();
67  auto const dzinv = 1.0 / dz_min[level];
68 
69  MultiFab const& S_new = vars_new[level][Vars::cons];
70 
71  MultiFab ccvel(grids[level],dmap[level],3,0);
72 
73  average_face_to_cellcenter(ccvel,0,
74  Array<const MultiFab*,3>{&vars_new[level][Vars::xvel],
75  &vars_new[level][Vars::yvel],
76  &vars_new[level][Vars::zvel]});
77 
78  int l_implicit_substepping = (solverChoice.substepping_type[level] == SubsteppingType::Implicit);
79  int l_anelastic = solverChoice.anelastic[level];
80 
81 #ifdef ERF_USE_EB
82  EBFArrayBoxFactory ebfact = EBFactory(level);
83  const MultiFab& detJ = ebfact.getVolFrac();
84 #endif
85 
86 #ifdef ERF_USE_EB
87  Real estdt_comp_inv = ReduceMax(S_new, ccvel, detJ, 0,
88  [=] AMREX_GPU_HOST_DEVICE (Box const& b,
89  Array4<Real const> const& s,
90  Array4<Real const> const& u,
91  Array4<Real const> const& vf) -> Real
92 #else
93  Real estdt_comp_inv = ReduceMax(S_new, ccvel, 0,
94  [=] AMREX_GPU_HOST_DEVICE (Box const& b,
95  Array4<Real const> const& s,
96  Array4<Real const> const& u) -> Real
97 #endif
98  {
99  Real new_comp_dt = -1.e100;
100  amrex::Loop(b, [=,&new_comp_dt] (int i, int j, int k) noexcept
101  {
102 #ifdef ERF_USE_EB
103  if (vf(i,j,k) > 0.)
104 #endif
105  {
106  const Real rho = s(i, j, k, Rho_comp);
107  const Real rhotheta = s(i, j, k, RhoTheta_comp);
108 
109  // NOTE: even when moisture is present,
110  // we only use the partial pressure of the dry air
111  // to compute the soundspeed
112  Real pressure = getPgivenRTh(rhotheta);
113  Real c = std::sqrt(Gamma * pressure / rho);
114 
115  // If we are doing implicit acoustic substepping, then the z-direction does not contribute
116  // to the computation of the time step
117  if (l_implicit_substepping) {
118  if (nxc > 1 && nyc > 1) {
119  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0))+c)*dxinv[0]),
120  ((amrex::Math::abs(u(i,j,k,1))+c)*dxinv[1]), new_comp_dt);
121  } else if (nxc > 1) {
122  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0))+c)*dxinv[0]), new_comp_dt);
123  } else if (nyc > 1) {
124  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,1))+c)*dxinv[1]), new_comp_dt);
125  } else {
126  amrex::Abort("Not sure how to compute dt for this case");
127  }
128 
129  // If we are not doing implicit acoustic substepping, then the z-direction contributes
130  // to the computation of the time step
131  } else {
132  if (nxc > 1 && nyc > 1) {
133  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0))+c)*dxinv[0]),
134  ((amrex::Math::abs(u(i,j,k,1))+c)*dxinv[1]),
135  ((amrex::Math::abs(u(i,j,k,2))+c)*dzinv ), new_comp_dt);
136  } else if (nxc > 1) {
137  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0))+c)*dxinv[0]),
138  ((amrex::Math::abs(u(i,j,k,2))+c)*dzinv ), new_comp_dt);
139  } else if (nyc > 1) {
140  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,1))+c)*dxinv[1]),
141  ((amrex::Math::abs(u(i,j,k,2))+c)*dzinv ), new_comp_dt);
142  } else {
143  new_comp_dt = amrex::max(((amrex::Math::abs(u(i,j,k,2))+c)*dzinv ), new_comp_dt);
144  }
145 
146  }
147  }
148  });
149  return new_comp_dt;
150  });
151 
152  ParallelDescriptor::ReduceRealMax(estdt_comp_inv);
153  estdt_comp = cfl / estdt_comp_inv;
154 
155  Real estdt_lowM_inv = ReduceMax(ccvel, 0,
156  [=] AMREX_GPU_HOST_DEVICE (Box const& b,
157  Array4<Real const> const& u) -> Real
158  {
159  Real new_lm_dt = -1.e100;
160  Loop(b, [=,&new_lm_dt] (int i, int j, int k) noexcept
161  {
162  new_lm_dt = amrex::max(((amrex::Math::abs(u(i,j,k,0)))*dxinv[0]),
163  ((amrex::Math::abs(u(i,j,k,1)))*dxinv[1]),
164  ((amrex::Math::abs(u(i,j,k,2)))*dxinv[2]), new_lm_dt);
165  });
166  return new_lm_dt;
167  });
168 
169  ParallelDescriptor::ReduceRealMax(estdt_lowM_inv);
170  if (estdt_lowM_inv > 0.0_rt)
171  estdt_lowM = cfl / estdt_lowM_inv;
172 
173  if (verbose) {
174  if (fixed_dt[level] <= 0.0) {
175  Print() << "Using cfl = " << cfl << " and dx/dy/dz_min = " <<
176  1.0/dxinv[0] << " " << 1.0/dxinv[1] << " " << dz_min[level] << std::endl;
177  Print() << "Compressible dt at level " << level << ": " << estdt_comp << std::endl;
178  if (estdt_lowM_inv > 0.0_rt) {
179  Print() << "Anelastic dt at level " << level << ": " << estdt_lowM << std::endl;
180  } else {
181  Print() << "Anelastic dt at level " << level << ": undefined " << std::endl;
182  }
183  }
184 
185  if (fixed_dt[level] > 0.0) {
186  Print() << "Based on cfl of 1.0 " << std::endl;
187  Print() << "Compressible dt at level " << level << " would be: " << estdt_comp/cfl << std::endl;
188  if (estdt_lowM_inv > 0.0_rt) {
189  Print() << "Anelastic dt at level " << level << " would be: " << estdt_lowM/cfl << std::endl;
190  } else {
191  Print() << "Anelastic dt at level " << level << " would be undefined " << std::endl;
192  }
193  Print() << "Fixed dt at level " << level << " is: " << fixed_dt[level] << std::endl;
194  if (fixed_fast_dt[level] > 0.0) {
195  Print() << "Fixed fast dt at level " << level << " is: " << fixed_fast_dt[level] << std::endl;
196  }
197  }
198  }
199 
200  if (solverChoice.substepping_type[level] != SubsteppingType::None) {
201  if (fixed_dt[level] > 0. && fixed_fast_dt[level] > 0.) {
202  dt_fast_ratio = static_cast<long>( fixed_dt[level] / fixed_fast_dt[level] );
203  } else if (fixed_dt[level] > 0.) {
204  dt_fast_ratio = static_cast<long>( 6 );
205  }
206 
207  // Force time step ratio to be an even value
209  if ( dt_fast_ratio%2 != 0) dt_fast_ratio += 1;
210  } else {
211  if ( dt_fast_ratio%6 != 0) {
212  Print() << "mri_dt_ratio = " << dt_fast_ratio
213  << " not divisible by 6 for N/3 substeps in stage 1" << std::endl;
214  dt_fast_ratio = static_cast<int>(std::ceil(dt_fast_ratio/6.0) * 6);
215  }
216  }
217 
218  if (verbose) {
219  Print() << "smallest even ratio is: " << dt_fast_ratio << std::endl;
220  }
221  } // if substepping, either explicit or implicit
222 
223  if (fixed_dt[level] > 0.0) {
224  return fixed_dt[level];
225  } else {
226  // Anelastic (substepping is not allowed)
227  if (l_anelastic) {
228  return estdt_lowM;
229 
230  // Compressible with or without substepping
231  } else {
232  return estdt_comp;
233  }
234  }
235 }
constexpr amrex::Real Gamma
Definition: ERF_Constants.H:19
amrex::Vector< amrex::Real > dz_min
Definition: ERF.H:1140
amrex::Vector< amrex::Real > fixed_dt
Definition: ERF.H:913
amrex::Vector< amrex::Real > fixed_fast_dt
Definition: ERF.H:914
static amrex::Real cfl
Definition: ERF.H:908
@ rho
Definition: ERF_Kessler.H:30
int force_stage1_single_substep
Definition: ERF_DataStruct.H:545
Here is the call graph for this function:

◆ Evolve()

void ERF::Evolve ( )
355 {
356  BL_PROFILE_VAR("ERF::Evolve()", evolve);
357 
358  Real cur_time = t_new[0];
359 
360  // Take one coarse timestep by calling timeStep -- which recursively calls timeStep
361  // for finer levels (with or without subcycling)
362  for (int step = istep[0]; step < max_step && cur_time < stop_time; ++step)
363  {
364  Print() << "\nCoarse STEP " << step+1 << " starts ..." << std::endl;
365 
366  ComputeDt(step);
367 
368  // Make sure we have read enough of the boundary plane data to make it through this timestep
369  if (input_bndry_planes)
370  {
371  m_r2d->read_input_files(cur_time,dt[0],m_bc_extdir_vals);
372  }
373 
374  int lev = 0;
375  int iteration = 1;
376  timeStep(lev, cur_time, iteration);
377 
378  cur_time += dt[0];
379 
380  Print() << "Coarse STEP " << step+1 << " ends." << " TIME = " << cur_time
381  << " DT = " << dt[0] << std::endl;
382 
383  post_timestep(step, cur_time, dt[0]);
384 
385  if (writeNow(cur_time, dt[0], step+1, m_plot_int_1, m_plot_per_1)) {
386  last_plot_file_step_1 = step+1;
388  }
389  if (writeNow(cur_time, dt[0], step+1, m_plot_int_2, m_plot_per_2)) {
390  last_plot_file_step_2 = step+1;
392  }
393 
394  if (writeNow(cur_time, dt[0], step+1, m_check_int, m_check_per)) {
395  last_check_file_step = step+1;
396 #ifdef ERF_USE_NETCDF
397  if (check_type == "netcdf") {
398  WriteNCCheckpointFile();
399  }
400 #endif
401  if (check_type == "native") {
403  }
404  }
405 
406 #ifdef AMREX_MEM_PROFILING
407  {
408  std::ostringstream ss;
409  ss << "[STEP " << step+1 << "]";
410  MemProfiler::report(ss.str());
411  }
412 #endif
413 
414  if (cur_time >= stop_time - 1.e-6*dt[0]) break;
415  }
416 
417  // Write plotfiles at final time
418  if ( (m_plot_int_1 > 0 || m_plot_per_1 > 0.) && istep[0] > last_plot_file_step_1 ) {
420  }
421  if ( (m_plot_int_2 > 0 || m_plot_per_2 > 0.) && istep[0] > last_plot_file_step_2) {
423  }
424 
425  if ( (m_check_int > 0 || m_check_per > 0.) && istep[0] > last_check_file_step) {
426 #ifdef ERF_USE_NETCDF
427  if (check_type == "netcdf") {
428  WriteNCCheckpointFile();
429  }
430 #endif
431  if (check_type == "native") {
433  }
434  }
435 
436  BL_PROFILE_VAR_STOP(evolve);
437 }
int last_check_file_step
Definition: ERF.H:893
int max_step
Definition: ERF.H:900
int last_plot_file_step_2
Definition: ERF.H:891
static PlotFileType plotfile_type_1
Definition: ERF.H:1028
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NBCVAR_max > m_bc_extdir_vals
Definition: ERF.H:871
amrex::Real m_plot_per_1
Definition: ERF.H:927
std::string check_type
Definition: ERF.H:939
int m_plot_int_1
Definition: ERF.H:925
void post_timestep(int nstep, amrex::Real time, amrex::Real dt_lev)
Definition: ERF.cpp:441
amrex::Real m_check_per
Definition: ERF.H:942
int m_check_int
Definition: ERF.H:941
int last_plot_file_step_1
Definition: ERF.H:890
static int input_bndry_planes
Definition: ERF.H:1068
static PlotFileType plotfile_type_2
Definition: ERF.H:1029
void WritePlotFile(int which, PlotFileType plotfile_type, amrex::Vector< std::string > plot_var_names)
Definition: ERF_Plotfile.cpp:186
void ComputeDt(int step=-1)
Definition: ERF_ComputeTimestep.cpp:11
void WriteCheckpointFile() const
Definition: ERF_Checkpoint.cpp:25
int m_plot_int_2
Definition: ERF.H:926
std::unique_ptr< ReadBndryPlanes > m_r2d
Definition: ERF.H:1125
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:1953
void timeStep(int lev, amrex::Real time, int iteration)
Definition: ERF_TimeStep.cpp:16
amrex::Real m_plot_per_2
Definition: ERF.H:928

Referenced by main().

Here is the caller graph for this function:

◆ 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  int bc_comp = (icomp+n >= RhoScalar_comp && icomp+n < RhoScalar_comp+NSCALARS) ?
78  BCVars::RhoScalar_bc_comp : icomp+n;
79  if (bc_ptr[bc_comp].lo(0) == ERFBCType::ext_dir_ingested) {
80  int jb = std::min(std::max(j,dom_lo.y),dom_hi.y);
81  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
82  dest_arr(i,j,k,icomp+n) = bdatxlo(dom_lo.x-1,jb,kb,bccomp+n);
83  }
84  },
85  bx_xhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
86  int bc_comp = (icomp+n >= RhoScalar_comp && icomp+n < RhoScalar_comp+NSCALARS) ?
87  BCVars::RhoScalar_bc_comp : icomp+n;
88  if (bc_ptr[bc_comp].hi(0) == ERFBCType::ext_dir_ingested) {
89  int jb = std::min(std::max(j,dom_lo.y),dom_hi.y);
90  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
91  dest_arr(i,j,k,icomp+n) = bdatxhi(dom_hi.x+1,jb,kb,bccomp+n);
92  }
93  }
94  );
95  } // x-faces
96 
97  // y-faces
98  {
99  Box bx_ylo(bx); bx_ylo.setBig (1,dom_lo.y-1);
100  if (var_idx == Vars::yvel) bx_ylo.setBig(1,dom_lo.y);
101 
102  Box bx_yhi(bx); bx_yhi.setSmall(1,dom_hi.y+1);
103  if (var_idx == Vars::yvel) bx_yhi.setSmall(1,dom_hi.y);
104 
105  ParallelFor(
106  bx_ylo, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
107  int bc_comp = (icomp+n >= RhoScalar_comp && icomp+n < RhoScalar_comp+NSCALARS) ?
108  BCVars::RhoScalar_bc_comp : icomp+n;
109  if (bc_ptr[bc_comp].lo(1) == ERFBCType::ext_dir_ingested) {
110  int ib = std::min(std::max(i,dom_lo.x),dom_hi.x);
111  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
112  dest_arr(i,j,k,icomp+n) = bdatylo(ib,dom_lo.y-1,kb,bccomp+n);
113  }
114  },
115  bx_yhi, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) {
116  int bc_comp = (icomp+n >= RhoScalar_comp && icomp+n < RhoScalar_comp+NSCALARS) ?
117  BCVars::RhoScalar_bc_comp : icomp+n;
118  if (bc_ptr[bc_comp].hi(1) == ERFBCType::ext_dir_ingested) {
119  int ib = std::min(std::max(i,dom_lo.x),dom_hi.x);
120  int kb = std::min(std::max(k,dom_lo.z),dom_hi.z);
121  dest_arr(i,j,k,icomp+n) = bdatyhi(ib,dom_hi.y+1,kb,bccomp+n);
122  }
123  }
124  );
125  } // y-faces
126  } // mf
127  } // var_idx
128 }
#define RhoScalar_comp
Definition: ERF_IndexDefines.H:40
#define NSCALARS
Definition: ERF_IndexDefines.H:16
amrex::Gpu::DeviceVector< amrex::BCRec > domain_bcs_type_d
Definition: ERF.H:865
@ RhoScalar_bc_comp
Definition: ERF_IndexDefines.H:80
@ ext_dir_ingested
Definition: ERF_IndexDefines.H:183

◆ 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)
12 {
13  // Impose bc's at domain boundaries
14  for (int lev = 0; lev <= finest_level; ++lev)
15  {
16  Box domain(Geom(lev).Domain());
17 
18  int ihi = domain.bigEnd(0);
19  int jhi = domain.bigEnd(1);
20  int khi = domain.bigEnd(2);
21 
22  // Impose periodicity first
23  mf_cc_vel[lev].FillBoundary(geom[lev].periodicity());
24 
25  for (MFIter mfi(mf_cc_vel[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
26  {
27  // Note that we don't fill corners here -- only the cells that share a face
28  // with interior cells -- this is all that is needed to calculate vorticity
29  const Box& bx = mfi.tilebox();
30  const Array4<Real>& vel_arr = mf_cc_vel[lev].array(mfi);
31 
32  if (!Geom(lev).isPeriodic(0)) {
33  // Low-x side
34  if (bx.smallEnd(0) <= domain.smallEnd(0)) {
35  Real mult = (phys_bc_type[0] == ERF_BC::no_slip_wall) ? -1. : 1.;
36  ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
37  {
38  vel_arr(-1,j,k,1) = mult*vel_arr(0,j,k,1); // v
39  vel_arr(-1,j,k,2) = mult*vel_arr(0,j,k,2); // w
40  });
41  }
42 
43  // High-x side
44  if (bx.bigEnd(0) >= domain.bigEnd(0)) {
45  Real mult = (phys_bc_type[3] == ERF_BC::no_slip_wall) ? -1. : 1.;
46  ParallelFor(makeSlab(bx,0,0), [=] AMREX_GPU_DEVICE(int , int j, int k) noexcept
47  {
48  vel_arr(ihi+1,j,k,1) = mult*vel_arr(ihi,j,k,1); // v
49  vel_arr(ihi+1,j,k,2) = mult*vel_arr(ihi,j,k,2); // w
50  });
51  }
52  } // !periodic
53 
54  if (!Geom(lev).isPeriodic(1)) {
55  // Low-y side
56  if (bx.smallEnd(1) <= domain.smallEnd(1)) {
57  Real mult = (phys_bc_type[1] == ERF_BC::no_slip_wall) ? -1. : 1.;
58  ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
59  {
60  vel_arr(i,-1,k,0) = mult*vel_arr(i,0,k,0); // u
61  vel_arr(i,-1,k,2) = mult*vel_arr(i,0,k,2); // w
62  });
63  }
64 
65  // High-y side
66  if (bx.bigEnd(1) >= domain.bigEnd(1)) {
67  Real mult = (phys_bc_type[4] == ERF_BC::no_slip_wall) ? -1. : 1.;
68  ParallelFor(makeSlab(bx,1,0), [=] AMREX_GPU_DEVICE(int i, int , int k) noexcept
69  {
70  vel_arr(i,jhi+1,k,0) = mult*vel_arr(i,jhi,k,0); // u
71  vel_arr(i,jhi+1,k,2) = mult*-vel_arr(i,jhi,k,2); // w
72  });
73  }
74  } // !periodic
75 
76  if (!Geom(lev).isPeriodic(2)) {
77  // Low-z side
78  if (bx.smallEnd(2) <= domain.smallEnd(2)) {
79  Real mult = (phys_bc_type[2] == ERF_BC::no_slip_wall) ? -1. : 1.;
80  ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
81  {
82  vel_arr(i,j,-1,0) = mult*vel_arr(i,j,0,0); // u
83  vel_arr(i,j,-1,1) = mult*vel_arr(i,j,0,1); // v
84  });
85  }
86 
87  // High-z side
88  if (bx.bigEnd(2) >= domain.bigEnd(2)) {
89  Real mult = (phys_bc_type[5] == ERF_BC::no_slip_wall) ? -1. : 1.;
90  ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
91  {
92  vel_arr(i,j,khi+1,0) = mult*vel_arr(i,j,khi,0); // u
93  vel_arr(i,j,khi+1,1) = mult*vel_arr(i,j,khi,1); // v
94  });
95  }
96  } // !periodic
97  } // MFIter
98 
99  } // lev
100 }
@ no_slip_wall

◆ FillCoarsePatch()

void ERF::FillCoarsePatch ( int  lev,
amrex::Real  time 
)
private
22 {
23  BL_PROFILE_VAR("FillCoarsePatch()",FillCoarsePatch);
24  AMREX_ASSERT(lev > 0);
25 
26  //
27  //****************************************************************************************************************
28  // First fill velocities and density at the COARSE level so we can convert velocity to momenta at the COARSE level
29  //****************************************************************************************************************
30  //
31  bool cons_only = false;
32  if (lev == 1) {
33  FillPatch(lev-1, time, {&vars_new[lev-1][Vars::cons], &vars_new[lev-1][Vars::xvel],
34  &vars_new[lev-1][Vars::yvel], &vars_new[lev-1][Vars::zvel]},
35  cons_only);
36  } else {
37  FillPatch(lev-1, time, {&vars_new[lev-1][Vars::cons], &vars_new[lev-1][Vars::xvel],
38  &vars_new[lev-1][Vars::yvel], &vars_new[lev-1][Vars::zvel]},
39  {&vars_new[lev-1][Vars::cons],
40  &rU_new[lev-1], &rV_new[lev-1], &rW_new[lev-1]},
41  base_state[lev-1], base_state[lev-1],
42  false, cons_only);
43  }
44 
45  //
46  // ************************************************
47  // Convert velocity to momentum at the COARSE level
48  // ************************************************
49  //
50  VelocityToMomentum(vars_new[lev-1][Vars::xvel], IntVect{0},
51  vars_new[lev-1][Vars::yvel], IntVect{0},
52  vars_new[lev-1][Vars::zvel], IntVect{0},
53  vars_new[lev-1][Vars::cons],
54  rU_new[lev-1],
55  rV_new[lev-1],
56  rW_new[lev-1],
57  Geom(lev).Domain(),
59  //
60  // *****************************************************************
61  // Interpolate all cell-centered variables from coarse to fine level
62  // *****************************************************************
63  //
64  Interpolater* mapper_c = &cell_cons_interp;
65  Interpolater* mapper_f = &face_cons_linear_interp;
66 
67  //
68  //************************************************************************************************
69  // Interpolate cell-centered data from coarse to fine level
70  // with InterpFromCoarseLevel which ASSUMES that all ghost cells have already been filled
71  // ************************************************************************************************
72  IntVect ngvect_cons = vars_new[lev][Vars::cons].nGrowVect();
73  int ncomp_cons = vars_new[lev][Vars::cons].nComp();
74 
75  InterpFromCoarseLevel(vars_new[lev ][Vars::cons], ngvect_cons, IntVect(0,0,0),
76  vars_new[lev-1][Vars::cons], 0, 0, ncomp_cons,
77  geom[lev-1], geom[lev],
78  refRatio(lev-1), mapper_c, domain_bcs_type, BCVars::cons_bc);
79 
80  //
81  //************************************************************************************************
82  // Interpolate x-momentum from coarse to fine level
83  // with InterpFromCoarseLevel which ASSUMES that all ghost cells have already been filled
84  // ************************************************************************************************
85  //
86  InterpFromCoarseLevel(rU_new[lev], IntVect{0}, IntVect{0}, rU_new[lev-1], 0, 0, 1,
87  geom[lev-1], geom[lev],
88  refRatio(lev-1), mapper_f, domain_bcs_type, BCVars::xvel_bc);
89 
90  //
91  //************************************************************************************************
92  // Interpolate y-momentum from coarse to fine level
93  // with InterpFromCoarseLevel which ASSUMES that all ghost cells have already been filled
94  // ************************************************************************************************
95  //
96  InterpFromCoarseLevel(rV_new[lev], IntVect{0}, IntVect{0}, rV_new[lev-1], 0, 0, 1,
97  geom[lev-1], geom[lev],
98  refRatio(lev-1), mapper_f, domain_bcs_type, BCVars::yvel_bc);
99 
100  //************************************************************************************************
101  // Interpolate z-momentum from coarse to fine level
102  // with InterpFromCoarseLevel which ASSUMES that all ghost cells have already been filled
103  // ************************************************************************************************
104  InterpFromCoarseLevel(rW_new[lev], IntVect{0}, IntVect{0}, rW_new[lev-1], 0, 0, 1,
105  geom[lev-1], geom[lev],
106  refRatio(lev-1), mapper_f, domain_bcs_type, BCVars::zvel_bc);
107  //
108  // *********************************************************
109  // After interpolation of momentum, convert back to velocity
110  // *********************************************************
111  //
112  for (int which_lev = lev-1; which_lev <= lev; which_lev++)
113  {
115  vars_new[which_lev][Vars::yvel],
116  vars_new[which_lev][Vars::zvel],
117  vars_new[which_lev][Vars::cons],
118  rU_new[which_lev],
119  rV_new[which_lev],
120  rW_new[which_lev],
121  Geom(lev).Domain(),
123  }
124 
125  // ***************************************************************************
126  // Physical bc's at domain boundary
127  // ***************************************************************************
128  IntVect ngvect_vels = vars_new[lev][Vars::xvel].nGrowVect();
129 
130  (*physbcs_cons[lev])(vars_new[lev][Vars::cons],0,ncomp_cons,ngvect_cons,time,BCVars::cons_bc,true);
131  ( *physbcs_u[lev])(vars_new[lev][Vars::xvel],0,1 ,ngvect_vels,time,BCVars::xvel_bc,true);
132  ( *physbcs_v[lev])(vars_new[lev][Vars::yvel],0,1 ,ngvect_vels,time,BCVars::yvel_bc,true);
134  ngvect_vels,time,BCVars::zvel_bc,true);
135 
136  // ***************************************************************************
137  // Since lev > 0 here we don't worry about m_r2d or wrfbdy data
138  // ***************************************************************************
139 }
void FillCoarsePatch(int lev, amrex::Real time)
Definition: ERF_FillCoarsePatch.cpp:21
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
34 {
35  BL_PROFILE_VAR("FillIntermediatePatch()",FillIntermediatePatch);
36  Interpolater* mapper;
37 
38  PhysBCFunctNoOp null_bc;
39 
40  //
41  // ***************************************************************************
42  // The first thing we do is interpolate the momenta on the "valid" faces of
43  // the fine grids (where the interface is coarse/fine not fine/fine) -- this
44  // will not be over-written by interpolation below because the FillPatch
45  // operators see these as valid faces. But we must have these interpolated
46  // values in the fine data before we call FillPatchTwoLevels.
47  //
48  // Also -- note that we might be filling values by interpolation at physical boundaries
49  // here but that's ok because we will overwrite those values when we impose
50  // the physical bc's below
51  // ***************************************************************************
52  if (lev>0) {
53  if (cf_set_width > 0) {
54  // We note that mfs_vel[Vars::cons] and mfs_mom[Vars::cons] are in fact the same pointer
55  FPr_c[lev-1].FillSet(*mfs_vel[Vars::cons], time, null_bc, domain_bcs_type);
56  }
57  if ( !cons_only && (cf_set_width >= 0) ) {
58  FPr_u[lev-1].FillSet(*mfs_mom[IntVars::xmom], time, null_bc, domain_bcs_type);
59  FPr_v[lev-1].FillSet(*mfs_mom[IntVars::ymom], time, null_bc, domain_bcs_type);
60  FPr_w[lev-1].FillSet(*mfs_mom[IntVars::zmom], time, null_bc, domain_bcs_type);
61  }
62  }
63 
64  // amrex::Print() << "LEVEL " << lev << " CONS ONLY " << cons_only <<
65  // " ICOMP NCOMP " << icomp_cons << " " << ncomp_cons << " NGHOST " << ng_cons << std::endl;
66 
67  if (!cons_only) {
68  AMREX_ALWAYS_ASSERT(mfs_mom.size() == IntVars::NumTypes);
69  AMREX_ALWAYS_ASSERT(mfs_vel.size() == Vars::NumTypes);
70  }
71 
72  // Enforce no penetration for thin immersed body
73  if (!cons_only) {
74  // Enforce no penetration for thin immersed body
75  if (xflux_imask[lev]) {
76  ApplyMask(*mfs_mom[IntVars::xmom], *xflux_imask[lev]);
77  }
78  if (yflux_imask[lev]) {
79  ApplyMask(*mfs_mom[IntVars::ymom], *yflux_imask[lev]);
80  }
81  if (zflux_imask[lev]) {
82  ApplyMask(*mfs_mom[IntVars::zmom], *zflux_imask[lev]);
83  }
84  }
85 
86  //
87  // We now start working on conserved quantities + VELOCITY
88  //
89  if (lev == 0)
90  {
91  // We don't do anything here because we will call the physbcs routines below,
92  // which calls FillBoundary and fills other domain boundary conditions
93  // Physical boundaries will be filled below
94 
95  if (!cons_only)
96  {
97  // ***************************************************************************
98  // We always come in to this call with updated momenta but we need to create updated velocity
99  // in order to impose the rest of the bc's
100  // ***************************************************************************
101  // This only fills VALID region of velocity
102  MomentumToVelocity(*mfs_vel[Vars::xvel], *mfs_vel[Vars::yvel], *mfs_vel[Vars::zvel],
103  *mfs_vel[Vars::cons],
104  *mfs_mom[IntVars::xmom], *mfs_mom[IntVars::ymom], *mfs_mom[IntVars::zmom],
105  Geom(lev).Domain(), domain_bcs_type);
106  }
107  }
108  else
109  {
110  //
111  // We must fill a temporary then copy it back so we don't double add/subtract
112  //
113  MultiFab mf(mfs_vel[Vars::cons]->boxArray(),mfs_vel[Vars::cons]->DistributionMap(),
114  mfs_vel[Vars::cons]->nComp() ,mfs_vel[Vars::cons]->nGrowVect());
115  //
116  // Set all components to 1.789e19, then copy just the density from *mfs_vel[Vars::cons]
117  //
118  mf.setVal(1.789e19);
119  MultiFab::Copy(mf,*mfs_vel[Vars::cons],Rho_comp,Rho_comp,1,mf.nGrowVect());
120 
121  Vector<MultiFab*> fmf = {mfs_vel[Vars::cons],mfs_vel[Vars::cons]};
122  Vector<MultiFab*> cmf = {&vars_old[lev-1][Vars::cons], &vars_new[lev-1][Vars::cons]};
123  Vector<Real> ctime = {t_old[lev-1], t_new[lev-1]};
124  Vector<Real> ftime = {time,time};
125 
126  // Impose physical bc's on fine data (note time and 0 are not used)
127  bool do_fb = true; bool do_terrain_adjustment = false;
128  (*physbcs_cons[lev])(*mfs_vel[Vars::cons],icomp_cons,ncomp_cons,IntVect{ng_cons},time,BCVars::cons_bc,
129  do_fb, do_terrain_adjustment);
130 
131  if ( (icomp_cons+ncomp_cons > 1) && (interpolation_type == StateInterpType::Perturbational) )
132  {
133  // Divide (rho theta) by rho to get theta
134  MultiFab::Divide(*mfs_vel[Vars::cons],*mfs_vel[Vars::cons],Rho_comp,RhoTheta_comp,1,IntVect{0});
135 
136  // Subtract theta_0 from theta
137  MultiFab::Subtract(*mfs_vel[Vars::cons],base_state[lev],BaseState::th0_comp,RhoTheta_comp,1,IntVect{0});
138 
139  if (!amrex::almostEqual(time,ctime[1])) {
140  MultiFab::Divide(vars_old[lev-1][Vars::cons], vars_old[lev-1][Vars::cons],
141  Rho_comp,RhoTheta_comp,1,vars_old[lev-1][Vars::cons].nGrowVect());
142  MultiFab::Subtract(vars_old[lev-1][Vars::cons], base_state[lev-1],
143  BaseState::th0_comp,RhoTheta_comp,1,vars_old[lev-1][Vars::cons].nGrowVect());
144  }
145  if (!amrex::almostEqual(time,ctime[0])) {
146  MultiFab::Divide(vars_new[lev-1][Vars::cons], vars_new[lev-1][Vars::cons],
147  Rho_comp,RhoTheta_comp,1,vars_new[lev-1][Vars::cons].nGrowVect());
148  MultiFab::Subtract(vars_new[lev-1][Vars::cons], base_state[lev-1],
149  BaseState::th0_comp,RhoTheta_comp,1,vars_new[lev-1][Vars::cons].nGrowVect());
150  }
151  }
152 
153  // Subtract rho_0 from rho before we interpolate -- note we only subtract
154  // on valid region of mf since the ghost cells will be filled below
155  if (icomp_cons == 0 && (interpolation_type == StateInterpType::Perturbational))
156  {
157  MultiFab::Subtract(*mfs_vel[Vars::cons],base_state[lev],BaseState::r0_comp,Rho_comp,1,IntVect{0});
158 
159  if (!amrex::almostEqual(time,ctime[1])) {
160  MultiFab::Subtract(vars_old[lev-1][Vars::cons], base_state[lev-1],
161  BaseState::r0_comp,Rho_comp,1,vars_old[lev-1][Vars::cons].nGrowVect());
162  }
163  if (!amrex::almostEqual(time,ctime[0])) {
164  MultiFab::Subtract(vars_new[lev-1][Vars::cons], base_state[lev-1],
165  BaseState::r0_comp,Rho_comp,1,vars_new[lev-1][Vars::cons].nGrowVect());
166  }
167  }
168 
169  // Call FillPatchTwoLevels which ASSUMES that all ghost cells have already been filled
170  mapper = &cell_cons_interp;
171  FillPatchTwoLevels(mf, IntVect{ng_cons}, IntVect(0,0,0),
172  time, cmf, ctime, fmf, ftime,
173  icomp_cons, icomp_cons, ncomp_cons, geom[lev-1], geom[lev],
174  refRatio(lev-1), mapper, domain_bcs_type,
175  icomp_cons);
176 
177  if (icomp_cons == 0 && (interpolation_type == StateInterpType::Perturbational))
178  {
179  // Restore the coarse values to what they were
180  if (!amrex::almostEqual(time,ctime[1])) {
181  MultiFab::Add(vars_old[lev-1][Vars::cons], base_state[lev-1],
182  BaseState::r0_comp,Rho_comp,1,vars_old[lev-1][Vars::cons].nGrowVect());
183  }
184  if (!amrex::almostEqual(time,ctime[0])) {
185  MultiFab::Add(vars_new[lev-1][Vars::cons], base_state[lev-1],
186  BaseState::r0_comp,Rho_comp,1,vars_new[lev-1][Vars::cons].nGrowVect());
187  }
188 
189  // Set values in the cells outside the domain boundary so that we can do the Add
190  // without worrying about uninitialized values outside the domain -- these
191  // will be filled in the physbcs call
192  mf.setDomainBndry(1.234e20,Rho_comp,1,geom[lev]);
193 
194  // Add rho_0 back to rho after we interpolate -- on all the valid + ghost region
195  MultiFab::Add(mf, base_state[lev],BaseState::r0_comp,Rho_comp,1,IntVect{ng_cons});
196  }
197 
198  if ( (icomp_cons+ncomp_cons > 1) && (interpolation_type == StateInterpType::Perturbational) )
199  {
200  // Add theta_0 to theta
201  if (!amrex::almostEqual(time,ctime[1])) {
202  MultiFab::Add(vars_old[lev-1][Vars::cons], base_state[lev-1],
203  BaseState::th0_comp,RhoTheta_comp,1,vars_old[lev-1][Vars::cons].nGrowVect());
204  MultiFab::Multiply(vars_old[lev-1][Vars::cons], vars_old[lev-1][Vars::cons],
205  Rho_comp,RhoTheta_comp,1,vars_old[lev-1][Vars::cons].nGrowVect());
206  }
207  if (!amrex::almostEqual(time,ctime[0])) {
208  MultiFab::Add(vars_new[lev-1][Vars::cons], base_state[lev-1],
209  BaseState::th0_comp,RhoTheta_comp,1,vars_new[lev-1][Vars::cons].nGrowVect());
210  MultiFab::Multiply(vars_new[lev-1][Vars::cons], vars_new[lev-1][Vars::cons],
211  Rho_comp,RhoTheta_comp,1,vars_new[lev-1][Vars::cons].nGrowVect());
212  }
213 
214  // Multiply theta by rho to get (rho theta)
215  MultiFab::Multiply(*mfs_vel[Vars::cons],*mfs_vel[Vars::cons],Rho_comp,RhoTheta_comp,1,IntVect{0});
216 
217  // Add theta_0 to theta
218  MultiFab::Add(*mfs_vel[Vars::cons],base_state[lev],BaseState::th0_comp,RhoTheta_comp,1,IntVect{0});
219 
220  // Add theta_0 back to theta
221  MultiFab::Add(mf,base_state[lev],BaseState::th0_comp,RhoTheta_comp,1,IntVect{ng_cons});
222 
223  // Multiply (theta) by rho to get (rho theta)
224  MultiFab::Multiply(mf,mf,Rho_comp,RhoTheta_comp,1,IntVect{ng_cons});
225  }
226 
227  // Make sure to only copy back the components we worked on
228  MultiFab::Copy(*mfs_vel[Vars::cons],mf,icomp_cons,icomp_cons,ncomp_cons,IntVect{ng_cons});
229 
230  // *****************************************************************************************
231 
232  if (!cons_only)
233  {
234  // ***************************************************************************
235  // We always come in to this call with updated momenta but we need to create updated velocity
236  // in order to impose the rest of the bc's
237  // ***************************************************************************
238  // This only fills VALID region of velocity
239  MomentumToVelocity(*mfs_vel[Vars::xvel], *mfs_vel[Vars::yvel], *mfs_vel[Vars::zvel],
240  *mfs_vel[Vars::cons],
241  *mfs_mom[IntVars::xmom], *mfs_mom[IntVars::ymom], *mfs_mom[IntVars::zmom],
242  Geom(lev).Domain(), domain_bcs_type);
243 
244  mapper = &face_cons_linear_interp;
245 
246  //
247  // NOTE: All interpolation here happens on velocities not momenta;
248  // note we only do the interpolation and FillBoundary here,
249  // physical bc's are imposed later
250  //
251  // NOTE: This will only fill velocity from coarse grid *outside* the fine grids
252  // unlike the FillSet calls above which filled momenta on the coarse/fine bdy
253  //
254 
255  MultiFab& mfu = *mfs_vel[Vars::xvel];
256 
257  fmf = {&mfu,&mfu};
258  cmf = {&vars_old[lev-1][Vars::xvel], &vars_new[lev-1][Vars::xvel]};
259 
260  // Call FillPatchTwoLevels which ASSUMES that all ghost cells have already been filled
261  FillPatchTwoLevels(mfu, IntVect{ng_vel}, IntVect(0,0,0),
262  time, cmf, ctime, fmf, ftime,
263  0, 0, 1, geom[lev-1], geom[lev],
264  refRatio(lev-1), mapper, domain_bcs_type,
266 
267  // *****************************************************************************************
268 
269  MultiFab& mfv = *mfs_vel[Vars::yvel];
270 
271  fmf = {&mfv,&mfv};
272  cmf = {&vars_old[lev-1][Vars::yvel], &vars_new[lev-1][Vars::yvel]};
273 
274  // Call FillPatchTwoLevels which ASSUMES that all ghost cells have already been filled
275  FillPatchTwoLevels(mfv, IntVect{ng_vel}, IntVect(0,0,0),
276  time, cmf, ctime, fmf, ftime,
277  0, 0, 1, geom[lev-1], geom[lev],
278  refRatio(lev-1), mapper, domain_bcs_type,
280 
281  // *****************************************************************************************
282 
283  MultiFab& mfw = *mfs_vel[Vars::zvel];
284 
285  fmf = {&mfw,&mfw};
286  cmf = {&vars_old[lev-1][Vars::zvel], &vars_new[lev-1][Vars::zvel]};
287 
288  // Call FillPatchTwoLevels which ASSUMES that all ghost cells have already been filled
289  FillPatchTwoLevels(mfw, IntVect{ng_vel}, IntVect(0,0,0),
290  time, cmf, ctime, fmf, ftime,
291  0, 0, 1, geom[lev-1], geom[lev],
292  refRatio(lev-1), mapper, domain_bcs_type,
294  } // !cons_only
295  } // lev > 0
296 
297  // ***************************************************************************
298  // Physical bc's at domain boundary
299  // ***************************************************************************
300  IntVect ngvect_cons = IntVect(ng_cons,ng_cons,ng_cons);
301  IntVect ngvect_vels = IntVect(ng_vel ,ng_vel ,ng_vel);
302 
303  bool do_fb = true;
304 
305 #ifdef ERF_USE_NETCDF
306  // We call this here because it is an ERF routine
307  if (use_real_bcs && (lev==0)) {
308  fill_from_realbdy(mfs_vel,time,cons_only,icomp_cons,ncomp_cons,ngvect_cons,ngvect_vels);
309  do_fb = false;
310  }
311 #endif
312 
313  if (m_r2d) fill_from_bndryregs(mfs_vel,time);
314 
315  // We call this even if init_type == InitType::Real because this routine will fill the vertical bcs
316  (*physbcs_cons[lev])(*mfs_vel[Vars::cons],icomp_cons,ncomp_cons,ngvect_cons,time,BCVars::cons_bc, do_fb);
317  if (!cons_only) {
318  (*physbcs_u[lev])(*mfs_vel[Vars::xvel],0,1,ngvect_vels,time,BCVars::xvel_bc, do_fb);
319  (*physbcs_v[lev])(*mfs_vel[Vars::yvel],0,1,ngvect_vels,time,BCVars::yvel_bc, do_fb);
320  (*physbcs_w[lev])(*mfs_vel[Vars::zvel],*mfs_vel[Vars::xvel],*mfs_vel[Vars::yvel],
321  ngvect_vels,time,BCVars::zvel_bc, do_fb);
322  }
323  // ***************************************************************************
324 
325  // MOST boundary conditions
326  if (!(cons_only && ncomp_cons == 1) && m_most && allow_most_bcs) {
327  m_most->impose_most_bcs(lev,mfs_vel,
328  Tau11_lev[lev].get(),
329  Tau22_lev[lev].get(),
330  Tau33_lev[lev].get(),
331  Tau12_lev[lev].get(), Tau21_lev[lev].get(),
332  Tau13_lev[lev].get(), Tau31_lev[lev].get(),
333  Tau23_lev[lev].get(), Tau32_lev[lev].get(),
334  SFS_hfx1_lev[lev].get(),
335  SFS_hfx2_lev[lev].get(),
336  SFS_hfx3_lev[lev].get(),
337  SFS_q1fx1_lev[lev].get(),
338  SFS_q1fx2_lev[lev].get(),
339  SFS_q1fx3_lev[lev].get(),
340  z_phys_nd[lev].get());
341  }
342 
343  // We always come in to this call with momenta so we need to leave with momenta!
344  // We need to make sure we convert back on all ghost cells/faces because this is
345  // how velocity from fine-fine copies (as well as physical and interpolated bcs) will be filled
346  if (!cons_only)
347  {
348  IntVect ngu = (!solverChoice.use_NumDiff) ? IntVect(1,1,1) : mfs_vel[Vars::xvel]->nGrowVect();
349  IntVect ngv = (!solverChoice.use_NumDiff) ? IntVect(1,1,1) : mfs_vel[Vars::yvel]->nGrowVect();
350  IntVect ngw = (!solverChoice.use_NumDiff) ? IntVect(1,1,0) : mfs_vel[Vars::zvel]->nGrowVect();
351 
352  VelocityToMomentum(*mfs_vel[Vars::xvel], ngu,
353  *mfs_vel[Vars::yvel], ngv,
354  *mfs_vel[Vars::zvel], ngw,
355  *mfs_vel[Vars::cons],
356  *mfs_mom[IntVars::xmom], *mfs_mom[IntVars::ymom], *mfs_mom[IntVars::zmom],
357  Geom(lev).Domain(),
359  }
360 
361  mfs_mom[IntVars::cons]->FillBoundary(geom[lev].periodicity());
362  mfs_mom[IntVars::xmom]->FillBoundary(geom[lev].periodicity());
363  mfs_mom[IntVars::ymom]->FillBoundary(geom[lev].periodicity());
364  mfs_mom[IntVars::zmom]->FillBoundary(geom[lev].periodicity());
365 }
AMREX_GPU_HOST AMREX_FORCE_INLINE void ApplyMask(amrex::MultiFab &dst, const amrex::iMultiFab &imask, const int nghost=0)
Definition: ERF_Utils.H:362
void fill_from_bndryregs(const amrex::Vector< amrex::MultiFab * > &mfs, amrex::Real time)
Definition: ERF_BoundaryConditionsBndryReg.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_FillIntermediatePatch.cpp:28
static bool use_real_bcs
Definition: ERF.H:1039
@ NumTypes
Definition: ERF_IndexDefines.H:143
Here is the call graph for this function:

◆ FillPatch() [1/2]

void ERF::FillPatch ( int  lev,
amrex::Real  time,
const amrex::Vector< amrex::MultiFab * > &  mfs_vel,
bool  cons_only = false 
)
private

◆ FillPatch() [2/2]

void ERF::FillPatch ( int  lev,
amrex::Real  time,
const amrex::Vector< amrex::MultiFab * > &  mfs_vel,
const amrex::Vector< amrex::MultiFab * > &  mfs_mom,
const amrex::MultiFab &  old_base_state,
const amrex::MultiFab &  new_base_state,
bool  fillset = true,
bool  cons_only = false 
)
private

◆ get_projection_bc()

Array< LinOpBCType, AMREX_SPACEDIM > ERF::get_projection_bc ( amrex::Orientation::Side  side) const
noexcept
18 {
19  amrex::Array<amrex::LinOpBCType,AMREX_SPACEDIM> r;
20  for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
21  if (geom[0].isPeriodic(dir)) {
22  r[dir] = LinOpBCType::Periodic;
23  } else {
24  auto bc_type = domain_bc_type[Orientation(dir,side)];
25  if (bc_type == "Outflow") {
26  r[dir] = LinOpBCType::Dirichlet;
27  } else
28  {
29  r[dir] = LinOpBCType::Neumann;
30  }
31  }
32  }
33  return r;
34 }
amrex::Array< std::string, 2 *AMREX_SPACEDIM > domain_bc_type
Definition: ERF.H:868

◆ getAdvFluxReg()

AMREX_FORCE_INLINE amrex::YAFluxRegister* ERF::getAdvFluxReg ( int  lev)
inlineprivate
1193  {
1194  return advflux_reg[lev];
1195  }

◆ getCPUTime()

static amrex::Real ERF::getCPUTime ( )
inlinestaticprivate
1270  {
1271  int numCores = amrex::ParallelDescriptor::NProcs();
1272 #ifdef _OPENMP
1273  numCores = numCores * omp_get_max_threads();
1274 #endif
1275 
1276  amrex::Real T =
1277  numCores * (amrex::ParallelDescriptor::second() - startCPUTime) +
1279 
1280  return T;
1281  }
static amrex::Real previousCPUTimeUsed
Definition: ERF.H:1266
static amrex::Real startCPUTime
Definition: ERF.H:1265
@ T
Definition: ERF_IndexDefines.H:99

◆ GotoNextLine()

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

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

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

◆ 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.

21 {
22  bool rho_read = false;
23  Vector<Real> cons_dir_init(NBCVAR_max,0.0);
24  cons_dir_init[BCVars::Rho_bc_comp] = 1.0;
25  cons_dir_init[BCVars::RhoTheta_bc_comp] = -1.0;
26  auto f = [this,&rho_read] (std::string const& bcid, Orientation ori)
27  {
28  // These are simply defaults for Dirichlet faces -- they should be over-written below
30  m_bc_extdir_vals[BCVars::RhoTheta_bc_comp][ori] = -1.0; // It is important to set this negative
31  // because the sign is tested on below
40 
41  m_bc_extdir_vals[BCVars::xvel_bc][ori] = 0.0; // default
44 
45  // These are simply defaults for Neumann gradients -- they should be over-written below
48 
57 
61 
62  std::string pp_text;
63  if (pp_prefix == "erf") {
64  pp_text = bcid;
65  } else {
66  pp_text = pp_prefix + "." + bcid;
67  }
68  ParmParse pp(pp_text);
69  std::string bc_type_in = "null";
70  pp.query("type", bc_type_in);
71  std::string bc_type = amrex::toLower(bc_type_in);
72 
73  if (bc_type == "symmetry")
74  {
75  // Print() << bcid << " set to symmetry.\n";
77  domain_bc_type[ori] = "Symmetry";
78  }
79  else if (bc_type == "outflow")
80  {
81  // Print() << bcid << " set to outflow.\n";
83  domain_bc_type[ori] = "Outflow";
84  }
85  else if (bc_type == "open")
86  {
87  // Print() << bcid << " set to open.\n";
88  AMREX_ASSERT_WITH_MESSAGE((ori.coordDir() != 2), "Open boundary not valid on zlo or zhi!");
90  domain_bc_type[ori] = "Open";
91  }
92  else if (bc_type == "ho_outflow")
93  {
95  domain_bc_type[ori] = "HO_Outflow";
96  }
97 
98  else if (bc_type == "inflow")
99  {
100  // Print() << bcid << " set to inflow.\n";
102  domain_bc_type[ori] = "Inflow";
103 
104  std::vector<Real> v;
105  if (input_bndry_planes && m_r2d->ingested_velocity()) {
109  } else {
110  // Test for input data file if at xlo face
111  std::string dirichlet_file;
112  auto file_exists = pp.query("dirichlet_file", dirichlet_file);
113  if (file_exists) {
114  init_Dirichlet_bc_data(dirichlet_file);
115  } else {
116  pp.getarr("velocity", v, 0, AMREX_SPACEDIM);
117  m_bc_extdir_vals[BCVars::xvel_bc][ori] = v[0];
118  m_bc_extdir_vals[BCVars::yvel_bc][ori] = v[1];
119  m_bc_extdir_vals[BCVars::zvel_bc][ori] = v[2];
120  }
121  }
122 
123  Real rho_in = 0.;
124  if (input_bndry_planes && m_r2d->ingested_density()) {
126  } else {
127  if (!pp.query("density", rho_in)) {
128  amrex::Print() << "Using interior values to set conserved vars" << std::endl;
129  }
130  m_bc_extdir_vals[BCVars::Rho_bc_comp][ori] = rho_in;
131  }
132  Real theta_in = 0.;
133  if (input_bndry_planes && m_r2d->ingested_theta()) {
135  } else {
136  if (rho_in > 0) {
137  pp.get("theta", theta_in);
138  }
139  m_bc_extdir_vals[BCVars::RhoTheta_bc_comp][ori] = rho_in*theta_in;
140  }
141  Real scalar_in = 0.;
142  if (input_bndry_planes && m_r2d->ingested_scalar()) {
144  } else {
145  if (pp.query("scalar", scalar_in))
146  m_bc_extdir_vals[BCVars::RhoScalar_bc_comp][ori] = rho_in*scalar_in;
147  }
148 
149  if (solverChoice.moisture_type != MoistureType::None) {
150  Real qv_in = 0.;
151  if (input_bndry_planes && m_r2d->ingested_q1()) {
153  } else {
154  if (pp.query("qv", qv_in))
155  m_bc_extdir_vals[BCVars::RhoQ1_bc_comp][ori] = rho_in*qv_in;
156  }
157  Real qc_in = 0.;
158  if (input_bndry_planes && m_r2d->ingested_q2()) {
160  } else {
161  if (pp.query("qc", qc_in))
162  m_bc_extdir_vals[BCVars::RhoQ2_bc_comp][ori] = rho_in*qc_in;
163  }
164  }
165 
166  Real KE_in = 0.;
167  if (input_bndry_planes && m_r2d->ingested_KE()) {
169  } else {
170  if (pp.query("KE", KE_in))
171  m_bc_extdir_vals[BCVars::RhoKE_bc_comp][ori] = rho_in*KE_in;
172  }
173  }
174  else if (bc_type == "noslipwall")
175  {
176  // Print() << bcid <<" set to no-slip wall.\n";
178  domain_bc_type[ori] = "NoSlipWall";
179 
180  std::vector<Real> v;
181 
182  // The values of m_bc_extdir_vals default to 0.
183  // But if we find "velocity" in the inputs file, use those values instead.
184  if (pp.queryarr("velocity", v, 0, AMREX_SPACEDIM))
185  {
186  v[ori.coordDir()] = 0.0;
187  m_bc_extdir_vals[BCVars::xvel_bc][ori] = v[0];
188  m_bc_extdir_vals[BCVars::yvel_bc][ori] = v[1];
189  m_bc_extdir_vals[BCVars::zvel_bc][ori] = v[2];
190  }
191 
192  Real rho_in;
193  rho_read = pp.query("density", rho_in);
194  if (rho_read)
195  {
196  m_bc_extdir_vals[BCVars::Rho_bc_comp][ori] = rho_in;
197  }
198 
199  Real theta_in;
200  if (pp.query("theta", theta_in))
201  {
203  }
204 
205  Real theta_grad_in;
206  if (pp.query("theta_grad", theta_grad_in))
207  {
208  m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori] = theta_grad_in;
209  }
210 
211  Real qv_in;
212  if (pp.query("qv", qv_in))
213  {
215  }
216  }
217  else if (bc_type == "slipwall")
218  {
219  // Print() << bcid <<" set to slip wall.\n";
220 
222  domain_bc_type[ori] = "SlipWall";
223 
224  Real rho_in;
225  if (pp.query("density", rho_in))
226  {
227  m_bc_extdir_vals[BCVars::Rho_bc_comp][ori] = rho_in;
228  }
229 
230  Real theta_in;
231  if (pp.query("theta", theta_in))
232  {
234  }
235 
236  Real rho_grad_in;
237  if (pp.query("density_grad", rho_grad_in))
238  {
239  m_bc_neumann_vals[BCVars::Rho_bc_comp][ori] = rho_grad_in;
240  }
241 
242  Real theta_grad_in;
243  if (pp.query("theta_grad", theta_grad_in))
244  {
245  m_bc_neumann_vals[BCVars::RhoTheta_bc_comp][ori] = theta_grad_in;
246  }
247  }
248  else if (bc_type == "most")
249  {
250  phys_bc_type[ori] = ERF_BC::MOST;
251  domain_bc_type[ori] = "MOST";
252  }
253  else
254  {
256  }
257 
258  if (geom[0].isPeriodic(ori.coordDir())) {
259  domain_bc_type[ori] = "Periodic";
260  if (phys_bc_type[ori] == ERF_BC::undefined)
261  {
263  } else {
264  Abort("Wrong BC type for periodic boundary");
265  }
266  }
267 
268  if (phys_bc_type[ori] == ERF_BC::undefined)
269  {
270  Print() << "BC Type specified for face " << bcid << " is " << bc_type_in << std::endl;
271  Abort("This BC type is unknown");
272  }
273  };
274 
275  f("xlo", Orientation(Direction::x,Orientation::low));
276  f("xhi", Orientation(Direction::x,Orientation::high));
277  f("ylo", Orientation(Direction::y,Orientation::low));
278  f("yhi", Orientation(Direction::y,Orientation::high));
279  f("zlo", Orientation(Direction::z,Orientation::low));
280  f("zhi", Orientation(Direction::z,Orientation::high));
281 
282  // *****************************************************************************
283  //
284  // Here we translate the physical boundary conditions -- one type per face --
285  // into logical boundary conditions for each velocity component
286  //
287  // *****************************************************************************
288  {
289  domain_bcs_type.resize(AMREX_SPACEDIM+NBCVAR_max);
290  domain_bcs_type_d.resize(AMREX_SPACEDIM+NBCVAR_max);
291 
292  for (OrientationIter oit; oit; ++oit) {
293  Orientation ori = oit();
294  int dir = ori.coordDir();
295  Orientation::Side side = ori.faceDir();
296  auto const bct = phys_bc_type[ori];
297  if ( bct == ERF_BC::symmetry )
298  {
299  if (side == Orientation::low) {
300  for (int i = 0; i < AMREX_SPACEDIM; i++) {
302  }
304  } else {
305  for (int i = 0; i < AMREX_SPACEDIM; i++) {
307  }
309  }
310  }
311  else if (bct == ERF_BC::outflow or bct == ERF_BC::ho_outflow )
312  {
313  if (side == Orientation::low) {
314  for (int i = 0; i < AMREX_SPACEDIM; i++) {
316  }
318  } else {
319  for (int i = 0; i < AMREX_SPACEDIM; i++) {
321  }
323  }
324  }
325  else if (bct == ERF_BC::open)
326  {
327  if (side == Orientation::low) {
328  for (int i = 0; i < AMREX_SPACEDIM; i++)
330  } else {
331  for (int i = 0; i < AMREX_SPACEDIM; i++)
333  }
334  }
335  else if (bct == ERF_BC::inflow)
336  {
337  if (side == Orientation::low) {
338  for (int i = 0; i < AMREX_SPACEDIM; i++) {
340  if (input_bndry_planes && dir < 2 && m_r2d->ingested_velocity()) {
342  }
343  }
344  } else {
345  for (int i = 0; i < AMREX_SPACEDIM; i++) {
347  if (input_bndry_planes && dir < 2 && m_r2d->ingested_velocity()) {
349  }
350  }
351  }
352  }
353  else if (bct == ERF_BC::no_slip_wall)
354  {
355  if (side == Orientation::low) {
356  for (int i = 0; i < AMREX_SPACEDIM; i++) {
358  }
359  } else {
360  for (int i = 0; i < AMREX_SPACEDIM; i++) {
362  }
363  }
364  }
365  else if (bct == ERF_BC::slip_wall)
366  {
367  if (side == Orientation::low) {
368  for (int i = 0; i < AMREX_SPACEDIM; i++) {
370  }
371  // Only normal direction has ext_dir
373 
374  } else {
375  for (int i = 0; i < AMREX_SPACEDIM; i++) {
377  }
378  // Only normal direction has ext_dir
380  }
381  }
382  else if (bct == ERF_BC::periodic)
383  {
384  if (side == Orientation::low) {
385  for (int i = 0; i < AMREX_SPACEDIM; i++) {
387  }
388  } else {
389  for (int i = 0; i < AMREX_SPACEDIM; i++) {
391  }
392  }
393  }
394  else if ( bct ==