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

#include <ERF_NOAHMP.H>

Inheritance diagram for NOAHMP:
Collaboration diagram for NOAHMP:

Public Member Functions

 NOAHMP ()
 
virtual ~NOAHMP ()=default
 
void Define (SolverChoice &) override
 
void Init (const int &lev, const amrex::MultiFab &cons_in, const amrex::Geometry &geom, const amrex::Real &dt) override
 
void Advance_With_State (const int &lev, amrex::MultiFab &cons_in, amrex::MultiFab &xvel_in, amrex::MultiFab &yvel_in, amrex::MultiFab *hfx3_out, amrex::MultiFab *qfx3_out, const amrex::Real &dt, const int &nstep) override
 
amrex::MultiFab * Lsm_Data_Ptr (const int &varIdx) override
 
amrex::MultiFab * Lsm_Flux_Ptr (const int &varIdx) override
 
amrex::Geometry Lsm_Geom () override
 
int Lsm_Data_Size () override
 
std::string Lsm_VarName (const int &varIdx) override
 
int Lsm_VarIndex (std::string varname) override
 
- Public Member Functions inherited from NullSurf
 NullSurf ()
 
virtual ~NullSurf ()=default
 
virtual void Advance (const amrex::Real &)
 
virtual void Update_Micro_Vars (amrex::MultiFab &)
 
virtual void Update_State_Vars (amrex::MultiFab &)
 
virtual void Copy_State_to_Micro (const amrex::MultiFab &)
 
virtual void Copy_Micro_to_State (amrex::MultiFab &)
 

Private Types

using FabPtr = std::shared_ptr< amrex::MultiFab >
 

Private Attributes

int m_lsm_size = LsmVar_NOAHMP::NumVars
 
amrex::Vector< int > LsmVarMap
 
amrex::Vector< std::string > LsmVarName
 
amrex::Geometry m_geom
 
amrex::Geometry m_lsm_geom
 
amrex::Real m_dt
 
int khi_lsm
 
amrex::Array< FabPtr, LsmVar_NOAHMP::NumVarslsm_fab_vars
 
amrex::Array< FabPtr, LsmVar_NOAHMP::NumVarslsm_fab_flux
 
int m_nz_lsm = 30
 
amrex::Real m_dz_lsm = 0.1
 
amrex::Real m_cp_soil = 1.26e6
 
amrex::Real m_k_soil = 0.2
 
amrex::Real m_theta_dir = 400.0
 
amrex::Real m_d_soil = m_k_soil / m_cp_soil
 
NoahmpIO_vector noahmpio_vect
 
int m_plot_int_1 = -1
 

Member Typedef Documentation

◆ FabPtr

using NOAHMP::FabPtr = std::shared_ptr<amrex::MultiFab>
private

Constructor & Destructor Documentation

◆ NOAHMP()

NOAHMP::NOAHMP ( )
inline
43 {}

◆ ~NOAHMP()

virtual NOAHMP::~NOAHMP ( )
virtualdefault

Member Function Documentation

◆ Advance_With_State()

void NOAHMP::Advance_With_State ( const int &  lev,
amrex::MultiFab &  cons_in,
amrex::MultiFab &  xvel_in,
amrex::MultiFab &  yvel_in,
amrex::MultiFab *  hfx3_out,
amrex::MultiFab *  qfx3_out,
const amrex::Real dt,
const int &  nstep 
)
overridevirtual

Reimplemented from NullSurf.

201  {
202 
203  Box domain = m_geom.Domain();
204 
205  amrex::Print () << "Noah-MP driver started at time step: " << nstep+1 << std::endl;
206 
207  // Loop over blocks to copy forcing data to Noahmp, drive the land model,
208  // and copy data back to ERF Multifabs.
209  int idb = 0;
210  for (amrex::MFIter mfi(cons_in, false); mfi.isValid(); ++mfi, ++idb) {
211 
212  const amrex::Box& bx = mfi.tilebox();
213 
214  // Check if tile is at the lower boundary in lower z direction
215  if (bx.smallEnd(2) == domain.smallEnd(2)) {
216 
217  NoahmpIO_type* noahmpio = &noahmpio_vect[idb];
218 
219  const amrex::Array4<const amrex::Real>& U_PHY = xvel_in.const_array(mfi);
220  const amrex::Array4<const amrex::Real>& V_PHY = yvel_in.const_array(mfi);
221  const amrex::Array4<const amrex::Real>& QV_TH = cons_in.const_array(mfi);
222  const amrex::Array4<const amrex::Real>& SWDOWN = lsm_fab_vars[LsmVar_NOAHMP::sw_flux_dn]->const_array(mfi);
223  const amrex::Array4<const amrex::Real>& GLW = lsm_fab_vars[LsmVar_NOAHMP::lw_flux_dn]->const_array(mfi);
224 
225  amrex::Array4<amrex::Real> TSK = lsm_fab_vars[LsmVar_NOAHMP::t_sfc]->array(mfi);
226  amrex::Array4<amrex::Real> EMISS = lsm_fab_vars[LsmVar_NOAHMP::sfc_emis]->array(mfi);
227  amrex::Array4<amrex::Real> ALBSFCDIR_VIS = lsm_fab_vars[LsmVar_NOAHMP::sfc_alb_dir_vis]->array(mfi);
228  amrex::Array4<amrex::Real> ALBSFCDIR_NIR = lsm_fab_vars[LsmVar_NOAHMP::sfc_alb_dir_nir]->array(mfi);
229  amrex::Array4<amrex::Real> ALBSFCDIF_VIS = lsm_fab_vars[LsmVar_NOAHMP::sfc_alb_dif_vis]->array(mfi);
230  amrex::Array4<amrex::Real> ALBSFCDIF_NIR = lsm_fab_vars[LsmVar_NOAHMP::sfc_alb_dif_nir]->array(mfi);
231  amrex::Array4<amrex::Real> SHBXY = hfx3_out->array(mfi);
232  amrex::Array4<amrex::Real> EVBXY = qfx3_out->array(mfi);
233 
234  // Copy forcing data from ERF to Noahmp.
235  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int ) noexcept
236  {
237  noahmpio->U_PHY(i,1,j) = 0.5*(U_PHY(i,j,0)+U_PHY(i+1,j,0));
238  noahmpio->V_PHY(i,1,j) = 0.5*(V_PHY(i,j,0)+V_PHY(i,j+1,0));
239  noahmpio->T_PHY(i,1,j) = QV_TH(i,j,0,RhoTheta_comp)/QV_TH(i,j,0,Rho_comp);
240  noahmpio->QV_CURR(i,1,j) = QV_TH(i,j,0,RhoQ1_comp)/QV_TH(i,j,0,Rho_comp);
241  noahmpio->SWDOWN(i,j) = SWDOWN(i,j,0);
242  noahmpio->GLW(i,j) = GLW(i,j,0);
243  });
244 
245  // Call the noahmpio driver code. This runs the land model forcing for
246  // each object in noahmpio_vect that represent a block in the domain.
247  noahmpio->itimestep = nstep+1;
248  noahmpio->DriverMain();
249 
250  // Copy forcing data from Noahmp to ERF
251  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int ) noexcept
252  {
253  SHBXY(i,j,0) = noahmpio->SHBXY(i,j);
254  EVBXY(i,j,0) = noahmpio->EVBXY(i,j);
255  TSK(i,j,0) = noahmpio->TSK(i,j);
256  EMISS(i,j,0) = noahmpio->EMISS(i,j);
257  ALBSFCDIR_VIS(i,j,0) = noahmpio->ALBSFCDIRXY(i,1,j);
258  ALBSFCDIR_NIR(i,j,0) = noahmpio->ALBSFCDIRXY(i,2,j);
259  ALBSFCDIF_VIS(i,j,0) = noahmpio->ALBSFCDIFXY(i,1,j);
260  ALBSFCDIF_NIR(i,j,0) = noahmpio->ALBSFCDIFXY(i,2,j);
261  });
262 
263  if((nstep+1)%m_plot_int_1 == 0) {
264  noahmpio->WriteLand(nstep+1);
265  }
266  }
267  }
268  amrex::Print () << "Noah-MP driver completed" << std::endl;
269 };
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
int m_plot_int_1
Definition: ERF_NOAHMP.H:180
amrex::Array< FabPtr, LsmVar_NOAHMP::NumVars > lsm_fab_vars
Definition: ERF_NOAHMP.H:152
NoahmpIO_vector noahmpio_vect
Definition: ERF_NOAHMP.H:178
amrex::Geometry m_geom
Definition: ERF_NOAHMP.H:134
@ sw_flux_dn
Definition: ERF_NOAHMP.H:31
@ lw_flux_dn
Definition: ERF_NOAHMP.H:32
@ t_sfc
Definition: ERF_NOAHMP.H:25
@ sfc_alb_dif_vis
Definition: ERF_NOAHMP.H:29
@ sfc_alb_dir_vis
Definition: ERF_NOAHMP.H:27
@ sfc_alb_dir_nir
Definition: ERF_NOAHMP.H:28
@ sfc_alb_dif_nir
Definition: ERF_NOAHMP.H:30
@ sfc_emis
Definition: ERF_NOAHMP.H:26

◆ Define()

void NOAHMP::Define ( SolverChoice )
inlineoverridevirtual

Reimplemented from NullSurf.

51  {
52  // NOTE: We should parse things from sc here,
53  // but they are hard coded because this
54  // is a demonstration for now.
55  }

◆ Init()

void NOAHMP::Init ( const int &  lev,
const amrex::MultiFab &  cons_in,
const amrex::Geometry &  geom,
const amrex::Real dt 
)
overridevirtual

Reimplemented from NullSurf.

19 {
20 
21  m_dt = dt;
22  m_geom = geom;
23 
24  Box domain = geom.Domain();
25  khi_lsm = domain.smallEnd(2) - 1;
26 
27  LsmVarMap.resize(m_lsm_size);
32 
33  LsmVarName.resize(m_lsm_size);
34  LsmVarName = {"t_sfc" , "sfc_emis" ,
35  "sfc_alb_dir_vis", "sfc_alb_dir_nir",
36  "sfc_alb_dif_vis", "sfc_alb_dif_nir",
37  "sw_flux_dn" , "lw_flux_dn" };
38 
39  amrex::ParmParse pp("erf");
40  pp.query("plot_int_1" , m_plot_int_1);
41 
42  // NOTE: All boxes in ba extend from zlo to zhi, so this transform is valid.
43  // If that were to change, the dm and new ba are no longer valid and
44  // direct copying between lsm data/flux vars cannot be done in a parfor.
45 
46  // Set 2D box array for lsm data
47  IntVect ng(0,0,0);
48  BoxArray ba = cons_in.boxArray();
49  DistributionMapping dm = cons_in.DistributionMap();
50  BoxList bl_lsm = ba.boxList();
51  for (auto& b : bl_lsm) {
52  b.setRange(2,0);
53  }
54  BoxArray ba_lsm(std::move(bl_lsm));
55 
56  // Set up lsm geometry
57  const RealBox& dom_rb = m_geom.ProbDomain();
58  const Real* dom_dx = m_geom.CellSize();
59  RealBox lsm_rb = dom_rb;
60  Real lsm_dx[AMREX_SPACEDIM] = {AMREX_D_DECL(dom_dx[0],dom_dx[1],m_dz_lsm)};
61  Real lsm_z_hi = dom_rb.lo(2);
62  Real lsm_z_lo = lsm_z_hi - Real(m_nz_lsm)*lsm_dx[2];
63  lsm_rb.setHi(2,lsm_z_hi); lsm_rb.setLo(2,lsm_z_lo);
64  m_lsm_geom.define( ba_lsm.minimalBox(), lsm_rb, m_geom.Coord(), m_geom.isPeriodic() );
65 
66  // Create the data and fluxes
67  for (auto ivar = 0; ivar < LsmVar_NOAHMP::NumVars; ++ivar) {
68  // State vars are CC
69  lsm_fab_vars[ivar] = std::make_shared<MultiFab>(ba_lsm, dm, 1, ng);
70 
71  // NOTE: Radiation steps first so we set values
72  // to reasonable initialization for coupling
73  Real val_to_set = 0.0;
74  if (ivar == LsmVar_NOAHMP::t_sfc) {
75  val_to_set = 300.0;
76  } else if (iver == LsmVar_NOAHMP::sfc_emis) {
77  val_to_set = 0.9;
78  } else if ((ivar>=LsmVar_NOAHMP::sfc_alb_dir_vis) && (ivar<=LsmVar_NOAHMP::sfc_alb_dif_nir)) {
79  val_to_set = 0.06;
80  } else {
81  val_to_set = 0.0;
82  }
83  lsm_fab_vars[ivar]->setVal(val_to_set);
84 
85  // Fluxes are nodal in z
86  lsm_fab_flux[ivar] = std::make_shared<MultiFab>(convert(ba_lsm, IntVect(0,0,1)), dm, 1, IntVect(0,0,0));
87  lsm_fab_flux[ivar]->setVal(0.);
88  }
89 
90  amrex::Print() << "Noah-MP initialization started" << std::endl;
91 
92  // Set noahmpio_vect to the size of local blocks (boxes)
93  noahmpio_vect.resize(cons_in.local_size(), lev);
94 
95  // Iterate over multifab and noahmpio object together. Multifabs is
96  // used to extract size of blocks and set bounds for noahmpio objects.
97  int idb = 0;
98  for (amrex::MFIter mfi(cons_in, false); mfi.isValid(); ++mfi, ++idb) {
99 
100  // Get bounds for the tile
101  const amrex::Box& bx = mfi.tilebox();
102 
103  // Check if tile is at the lower boundary in lower z direction
104  if (bx.smallEnd(2) == domain.smallEnd(2)) {
105 
106  // Get reference to the noahmpio object
107  NoahmpIO_type* noahmpio = &noahmpio_vect[idb];
108 
109  // Pass idb context to noahmpio
110  noahmpio->blkid = idb;
111 
112  // Pass level context to noahmpio
113  noahmpio->level = lev;
114 
115  // Initialize scalar values
116  noahmpio->ScalarInitDefault();
117 
118  // Store the rank of process for noahmp
119  noahmpio->rank = amrex::ParallelDescriptor::MyProc();
120 
121  // Store parallel communicator for noahmp
122  noahmpio->comm = MPI_Comm_c2f(amrex::ParallelDescriptor::Communicator());
123 
124  // Read namelist.erf file. This file contains
125  // noahmpio specific parameters and is read by
126  // the Fortran side of the implementation.
127  noahmpio->ReadNamelist();
128 
129  // Read the headers from the NetCDF land file. This is also
130  // implemented on the Fortran side of things currently.
131  noahmpio->ReadLandHeader();
132 
133  // Extract tile bounds and set them to their corresponding
134  // noahmpio variables. At present we will set all the variables
135  // corresponding to domain, memory, and tile to the same bounds.
136  // This will be changed later if we want to do special memory
137  // management for expensive use cases.
138  noahmpio->xstart = bx.smallEnd(0);
139  noahmpio->xend = bx.bigEnd(0);
140  noahmpio->ystart = bx.smallEnd(1);
141  noahmpio->yend = bx.bigEnd(1);
142 
143  // Domain bounds
144  noahmpio->ids = noahmpio->xstart;
145  noahmpio->ide = noahmpio->xend;
146  noahmpio->jds = noahmpio->ystart;
147  noahmpio->jde = noahmpio->yend;
148  noahmpio->kds = 1;
149  noahmpio->kde = 2;
150 
151  // Tile bounds
152  noahmpio->its = noahmpio->xstart;
153  noahmpio->ite = noahmpio->xend;
154  noahmpio->jts = noahmpio->ystart;
155  noahmpio->jte = noahmpio->yend;
156  noahmpio->kts = 1;
157  noahmpio->kte = 2;
158 
159  // Memory bounds
160  noahmpio->ims = noahmpio->xstart;
161  noahmpio->ime = noahmpio->xend;
162  noahmpio->jms = noahmpio->ystart;
163  noahmpio->jme = noahmpio->yend;
164  noahmpio->kms = 1;
165  noahmpio->kme = 2;
166 
167  // This procedure allocates memory in Fortran for IO variables
168  // using bounds that are set above and read from namelist.erf
169  // and headers from the NetCDF land file
170  noahmpio->VarInitDefault();
171 
172  // This reads NoahmpTable.TBL file which is another input file
173  // we need to set some IO variables.
174  noahmpio->ReadTable();
175 
176  // Read and initialize data from the NetCDF land file.
177  noahmpio->ReadLandMain();
178 
179  // Compute additional initial values that were not supplied
180  // by the NetCDF land file.
181  noahmpio->InitMain();
182 
183  // Write initial plotfile for land with the tag 0
184  amrex::Print() << "Noah-MP writing lnd.nc file at lev: " << lev << std::endl;
185  noahmpio->WriteLand(0);
186  }
187  }
188 
189  amrex::Print() << "Noah-MP initialization completed" << std::endl;
190 
191 };
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:230
amrex::Real Real
Definition: ERF_ShocInterface.H:16
int khi_lsm
Definition: ERF_NOAHMP.H:143
amrex::Vector< std::string > LsmVarName
Definition: ERF_NOAHMP.H:131
amrex::Vector< int > LsmVarMap
Definition: ERF_NOAHMP.H:128
int m_lsm_size
Definition: ERF_NOAHMP.H:125
amrex::Geometry m_lsm_geom
Definition: ERF_NOAHMP.H:137
amrex::Array< FabPtr, LsmVar_NOAHMP::NumVars > lsm_fab_flux
Definition: ERF_NOAHMP.H:155
int m_nz_lsm
Definition: ERF_NOAHMP.H:160
amrex::Real m_dz_lsm
Definition: ERF_NOAHMP.H:163
amrex::Real m_dt
Definition: ERF_NOAHMP.H:140
@ NumVars
Definition: ERF_NOAHMP.H:33
@ ng
Definition: ERF_Morrison.H:48
Here is the call graph for this function:

◆ Lsm_Data_Ptr()

amrex::MultiFab* NOAHMP::Lsm_Data_Ptr ( const int &  varIdx)
inlineoverridevirtual

Reimplemented from NullSurf.

78  {
79  int lsmIdx = LsmVarMap[varIdx];
80  AMREX_ALWAYS_ASSERT(lsmIdx < NOAHMP::m_lsm_size && lsmIdx>=0);
81  return lsm_fab_vars[lsmIdx].get();
82  }

◆ Lsm_Data_Size()

int NOAHMP::Lsm_Data_Size ( )
inlineoverridevirtual

Reimplemented from NullSurf.

99 { return NOAHMP::m_lsm_size; }

◆ Lsm_Flux_Ptr()

amrex::MultiFab* NOAHMP::Lsm_Flux_Ptr ( const int &  varIdx)
inlineoverridevirtual

Reimplemented from NullSurf.

87  {
88  int lsmIdx = LsmVarMap[varIdx];
89  AMREX_ALWAYS_ASSERT(lsmIdx < NOAHMP::m_lsm_size && lsmIdx>=0);
90  return lsm_fab_flux[lsmIdx].get();
91  }

◆ Lsm_Geom()

amrex::Geometry NOAHMP::Lsm_Geom ( )
inlineoverridevirtual

Reimplemented from NullSurf.

95 { return m_lsm_geom; }

◆ Lsm_VarIndex()

int NOAHMP::Lsm_VarIndex ( std::string  varname)
inlineoverridevirtual

Reimplemented from NullSurf.

112  {
113  int varIdx = -1;
114  std::string lc_varname = amrex::toLower(varname);
115  for (int idx(0); idx<LsmVar_NOAHMP::NumVars; ++idx) {
116  if (lc_varname == amrex::toLower(LsmVarName[idx])) {
117  varIdx = idx;
118  }
119  }
120  return varIdx;
121  }
std::string varname
Definition: ERF_NullSurf.H:89

◆ Lsm_VarName()

std::string NOAHMP::Lsm_VarName ( const int &  varIdx)
inlineoverridevirtual

Reimplemented from NullSurf.

104  {
105  int lsmIdx = LsmVarMap[varIdx];
106  AMREX_ALWAYS_ASSERT(lsmIdx < NOAHMP::m_lsm_size && lsmIdx>=0);
107  return LsmVarName[lsmIdx];
108  }

Member Data Documentation

◆ khi_lsm

int NOAHMP::khi_lsm
private

◆ lsm_fab_flux

amrex::Array<FabPtr, LsmVar_NOAHMP::NumVars> NOAHMP::lsm_fab_flux
private

Referenced by Lsm_Flux_Ptr().

◆ lsm_fab_vars

amrex::Array<FabPtr, LsmVar_NOAHMP::NumVars> NOAHMP::lsm_fab_vars
private

Referenced by Lsm_Data_Ptr().

◆ LsmVarMap

amrex::Vector<int> NOAHMP::LsmVarMap
private

◆ LsmVarName

amrex::Vector<std::string> NOAHMP::LsmVarName
private

Referenced by Lsm_VarIndex(), and Lsm_VarName().

◆ m_cp_soil

amrex::Real NOAHMP::m_cp_soil = 1.26e6
private

◆ m_d_soil

amrex::Real NOAHMP::m_d_soil = m_k_soil / m_cp_soil
private

◆ m_dt

amrex::Real NOAHMP::m_dt
private

◆ m_dz_lsm

amrex::Real NOAHMP::m_dz_lsm = 0.1
private

◆ m_geom

amrex::Geometry NOAHMP::m_geom
private

◆ m_k_soil

amrex::Real NOAHMP::m_k_soil = 0.2
private

◆ m_lsm_geom

amrex::Geometry NOAHMP::m_lsm_geom
private

Referenced by Lsm_Geom().

◆ m_lsm_size

int NOAHMP::m_lsm_size = LsmVar_NOAHMP::NumVars
private

Referenced by Lsm_Data_Size().

◆ m_nz_lsm

int NOAHMP::m_nz_lsm = 30
private

◆ m_plot_int_1

int NOAHMP::m_plot_int_1 = -1
private

◆ m_theta_dir

amrex::Real NOAHMP::m_theta_dir = 400.0
private

◆ noahmpio_vect

NoahmpIO_vector NOAHMP::noahmpio_vect
private

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