ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
NOAH Class Reference

#include <ERF_NOAH.H>

Inheritance diagram for NOAH:
Collaboration diagram for NOAH:

Public Member Functions

 NOAH ()
 
virtual ~NOAH ()=default
 
void Define (SolverChoice &) override
 
void Init (const amrex::MultiFab &cons_in, const amrex::Geometry &geom, const amrex::Real &dt) override
 
void Advance (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
 
- 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 = 1
 
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_NOAH::NumVarslsm_fab_vars
 
amrex::Array< FabPtr, LsmVar_NOAH::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
 

Member Typedef Documentation

◆ FabPtr

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

Constructor & Destructor Documentation

◆ NOAH()

NOAH::NOAH ( )
inline
36 {}

◆ ~NOAH()

virtual NOAH::~NOAH ( )
virtualdefault

Member Function Documentation

◆ Advance()

void NOAH::Advance ( 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.

178  {
179 
180  Box domain = m_geom.Domain();
181 
182  amrex::Print () << "Noah-MP driver started at time step: " << nstep+1 << std::endl;
183 
184  // Loop over blocks to copy forcing data to Noahmp, drive the land model,
185  // and copy data back to ERF Multifabs.
186  int idb = 0;
187  for (amrex::MFIter mfi(xvel_in, false); mfi.isValid(); ++mfi, ++idb) {
188 
189  const amrex::Box& bx = mfi.tilebox();
190 
191  // Check if tile is at the lower boundary in lower z direction
192  if (bx.smallEnd(2) == domain.smallEnd(2)) {
193 
194  NoahmpIO_type* noahmpio = &noahmpio_vect[idb];
195 
196  const amrex::Array4<const amrex::Real>& U_PHY = xvel_in.const_array(mfi);
197  const amrex::Array4<const amrex::Real>& V_PHY = yvel_in.const_array(mfi);
198  const amrex::Array4<const amrex::Real>& QV_TH = cons_in.const_array(mfi);
199 
200  amrex::Array4<amrex::Real> SHBXY = hfx3_out->array(mfi);
201  amrex::Array4<amrex::Real> EVBXY = qfx3_out->array(mfi);
202 
203  // Copy forcing data from ERF to Noahmp.
204  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int ) noexcept
205  {
206  noahmpio->U_PHY(i,1,j) = U_PHY(i,j,0);
207  noahmpio->V_PHY(i,1,j) = V_PHY(i,j,0);
208  noahmpio->T_PHY(i,1,j) = QV_TH(i,j,0,RhoTheta_comp)/QV_TH(i,j,0,Rho_comp);
209  noahmpio->QV_CURR(i,1,j) = QV_TH(i,j,0,RhoQ1_comp)/QV_TH(i,j,0,Rho_comp);
210 
211  });
212 
213  // Call the noahmpio driver code. This runs the land model forcing for
214  // each object in noahmpio_vect that represent a block in the domain.
215  noahmpio->itimestep = nstep+1;
216  noahmpio->DriverMain();
217 
218  // Copy forcing data from Noahmp to ERF
219  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int ) noexcept
220  {
221  SHBXY(i,j,0) = noahmpio->SHBXY(i,j);
222  EVBXY(i,j,0) = noahmpio->EVBXY(i,j);
223  });
224  }
225  }
226  amrex::Print () << "Noah-MP driver completed" << std::endl;
227 };
#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::Geometry m_geom
Definition: ERF_NOAH.H:113
NoahmpIO_vector noahmpio_vect
Definition: ERF_NOAH.H:157

◆ Define()

void NOAH::Define ( SolverChoice )
inlineoverridevirtual

Reimplemented from NullSurf.

44  {
45  // NOTE: We should parse things from sc here,
46  // but they are hard coded because this
47  // is a demonstration for now.
48  }

◆ Init()

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

Reimplemented from NullSurf.

18 {
19 
20  m_dt = dt;
21  m_geom = geom;
22 
23  Box domain = geom.Domain();
24  khi_lsm = domain.smallEnd(2) - 1;
25 
26  LsmVarMap.resize(m_lsm_size);
28 
29  LsmVarName.resize(m_lsm_size);
30  LsmVarName = {"theta"};
31 
32  // NOTE: lsm data is not used for Noahmp, however, the initialization is done
33  // to maintin consistency with IO and Driver interfaces that depend on
34  // this data. We eventually want to tweak those interfaces so we don't
35  // have to allocate lsm_data while using Noahmp lsm.
36 
37  // NOTE: All boxes in ba extend from zlo to zhi, so this transform is valid.
38  // If that were to change, the dm and new ba are no longer valid and
39  // direct copying between lsm data/flux vars cannot be done in a parfor.
40 
41  // Set box array for lsm data
42  IntVect ng(0,0,1);
43  BoxArray ba = cons_in.boxArray();
44  DistributionMapping dm = cons_in.DistributionMap();
45  BoxList bl_lsm = ba.boxList();
46  for (auto& b : bl_lsm) {
47  b.setBig(2,khi_lsm); // First point below the surface
48  b.setSmall(2,khi_lsm - m_nz_lsm + 1); // Last point below the surface
49  }
50  BoxArray ba_lsm(std::move(bl_lsm));
51 
52  // Set up lsm geometry
53  const RealBox& dom_rb = m_geom.ProbDomain();
54  const Real* dom_dx = m_geom.CellSize();
55  RealBox lsm_rb = dom_rb;
56  Real lsm_dx[AMREX_SPACEDIM] = {AMREX_D_DECL(dom_dx[0],dom_dx[1],m_dz_lsm)};
57  Real lsm_z_hi = dom_rb.lo(2);
58  Real lsm_z_lo = lsm_z_hi - Real(m_nz_lsm)*lsm_dx[2];
59  lsm_rb.setHi(2,lsm_z_hi); lsm_rb.setLo(2,lsm_z_lo);
60  m_lsm_geom.define( ba_lsm.minimalBox(), lsm_rb, m_geom.Coord(), m_geom.isPeriodic() );
61 
62  // Create the data and fluxes
63  for (auto ivar = 0; ivar < LsmVar_NOAH::NumVars; ++ivar) {
64  // State vars are CC
65  Real theta_0 = m_theta_dir;
66  lsm_fab_vars[ivar] = std::make_shared<MultiFab>(ba_lsm, dm, 1, ng);
67  lsm_fab_vars[ivar]->setVal(theta_0);
68 
69  // Fluxes are nodal in z
70  lsm_fab_flux[ivar] = std::make_shared<MultiFab>(convert(ba_lsm, IntVect(0,0,1)), dm, 1, IntVect(0,0,0));
71  lsm_fab_flux[ivar]->setVal(0.);
72  }
73 
74  // NOTE: Actual NoahmpIO interface that is relevant for the
75  // implementation of this lsm
76 
77  amrex::Print() << "Noah-MP initialization started" << std::endl;
78 
79  // Set noahmpio_vect to the size of local blocks (boxes)
80  noahmpio_vect.resize(cons_in.local_size());
81 
82  // Iterate over multifab and noahmpio object together. Multifabs is
83  // used to extract size of blocks and set bounds for noahmpio objects.
84  int idb = 0;
85  for (amrex::MFIter mfi(cons_in, false); mfi.isValid(); ++mfi, ++idb) {
86 
87  // Get bounds for the tile
88  const amrex::Box& bx = mfi.tilebox();
89 
90  // Check if tile is at the lower boundary in lower z direction
91  if (bx.smallEnd(2) == domain.smallEnd(2)) {
92 
93  // Get reference to the noahmpio object
94  NoahmpIO_type* noahmpio = &noahmpio_vect[idb];
95 
96  // Pass idb context to noahmpio
97  noahmpio->blkid = idb;
98 
99  // Initialize scalar values
100  noahmpio->ScalarInitDefault();
101 
102  // Store the rank of process for noahmp
103  noahmpio->rank = amrex::ParallelDescriptor::MyProc();
104 
105  // Read namelist.erf file. This file contains
106  // noahmpio specific parameters and is read by
107  // the Fortran side of the implementation.
108  noahmpio->ReadNamelist();
109 
110  // Read the headers from the NetCDF land file. This is also
111  // implemented on the Fortran side of things currently.
112  noahmpio->ReadLandHeader();
113 
114  // Extract tile bounds and set them to their corresponding
115  // noahmpio variables. At present we will set all the variables
116  // corresponding to domain, memory, and tile to the same bounds.
117  // This will be changed later if we want to do special memory
118  // management for expensive use cases.
119  noahmpio->xstart = bx.smallEnd(0);
120  noahmpio->xend = bx.bigEnd(0);
121  noahmpio->ystart = bx.smallEnd(1);
122  noahmpio->yend = bx.bigEnd(1);
123 
124  // Domain bounds
125  noahmpio->ids = noahmpio->xstart;
126  noahmpio->ide = noahmpio->xend;
127  noahmpio->jds = noahmpio->ystart;
128  noahmpio->jde = noahmpio->yend;
129  noahmpio->kds = 1;
130  noahmpio->kde = 2;
131 
132  // Tile bounds
133  noahmpio->its = noahmpio->xstart;
134  noahmpio->ite = noahmpio->xend;
135  noahmpio->jts = noahmpio->ystart;
136  noahmpio->jte = noahmpio->yend;
137  noahmpio->kts = 1;
138  noahmpio->kte = 2;
139 
140  // Memory bounds
141  noahmpio->ims = noahmpio->xstart;
142  noahmpio->ime = noahmpio->xend;
143  noahmpio->jms = noahmpio->ystart;
144  noahmpio->jme = noahmpio->yend;
145  noahmpio->kms = 1;
146  noahmpio->kme = 2;
147 
148  // This procedure allocates memory in Fortran for IO variables
149  // using bounds that are set above and read from namelist.erf
150  // and headers from the NetCDF land file
151  noahmpio->VarInitDefault();
152 
153  // This reads NoahmpTable.TBL file which is another input file
154  // we need to set some IO variables.
155  noahmpio->ReadTable();
156 
157  // Read and initialize data from the NetCDF land file.
158  noahmpio->ReadLandMain();
159 
160  // Compute additional initial values that were not supplied
161  // by the NetCDF land file.
162  noahmpio->InitMain();
163  }
164  }
165 
166  amrex::Print() << "Noah-MP initialization completed" << std::endl;
167 
168 };
int m_lsm_size
Definition: ERF_NOAH.H:104
amrex::Vector< std::string > LsmVarName
Definition: ERF_NOAH.H:110
amrex::Array< FabPtr, LsmVar_NOAH::NumVars > lsm_fab_flux
Definition: ERF_NOAH.H:134
amrex::Vector< int > LsmVarMap
Definition: ERF_NOAH.H:107
amrex::Real m_dz_lsm
Definition: ERF_NOAH.H:142
int m_nz_lsm
Definition: ERF_NOAH.H:139
amrex::Real m_theta_dir
Definition: ERF_NOAH.H:151
amrex::Array< FabPtr, LsmVar_NOAH::NumVars > lsm_fab_vars
Definition: ERF_NOAH.H:131
int khi_lsm
Definition: ERF_NOAH.H:122
amrex::Geometry m_lsm_geom
Definition: ERF_NOAH.H:116
amrex::Real m_dt
Definition: ERF_NOAH.H:119
@ NumVars
Definition: ERF_NOAH.H:26
@ theta
Definition: ERF_NOAH.H:25

◆ Lsm_Data_Ptr()

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

Reimplemented from NullSurf.

70  {
71  int lsmIdx = LsmVarMap[varIdx];
72  AMREX_ALWAYS_ASSERT(lsmIdx < NOAH::m_lsm_size && lsmIdx>=0);
73  return lsm_fab_vars[lsmIdx].get();
74  }

◆ Lsm_Data_Size()

int NOAH::Lsm_Data_Size ( )
inlineoverridevirtual

Reimplemented from NullSurf.

91 { return NOAH::m_lsm_size; }

◆ Lsm_Flux_Ptr()

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

Reimplemented from NullSurf.

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

◆ Lsm_Geom()

amrex::Geometry NOAH::Lsm_Geom ( )
inlineoverridevirtual

Reimplemented from NullSurf.

87 { return m_lsm_geom; }

◆ Lsm_VarName()

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

Reimplemented from NullSurf.

96  {
97  int lsmIdx = LsmVarMap[varIdx];
98  AMREX_ALWAYS_ASSERT(lsmIdx < NOAH::m_lsm_size && lsmIdx>=0);
99  return LsmVarName[lsmIdx];
100  }

Member Data Documentation

◆ khi_lsm

int NOAH::khi_lsm
private

◆ lsm_fab_flux

amrex::Array<FabPtr, LsmVar_NOAH::NumVars> NOAH::lsm_fab_flux
private

Referenced by Lsm_Flux_Ptr().

◆ lsm_fab_vars

amrex::Array<FabPtr, LsmVar_NOAH::NumVars> NOAH::lsm_fab_vars
private

Referenced by Lsm_Data_Ptr().

◆ LsmVarMap

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

◆ LsmVarName

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

Referenced by Lsm_VarName().

◆ m_cp_soil

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

◆ m_d_soil

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

◆ m_dt

amrex::Real NOAH::m_dt
private

◆ m_dz_lsm

amrex::Real NOAH::m_dz_lsm = 0.1
private

◆ m_geom

amrex::Geometry NOAH::m_geom
private

◆ m_k_soil

amrex::Real NOAH::m_k_soil = 0.2
private

◆ m_lsm_geom

amrex::Geometry NOAH::m_lsm_geom
private

Referenced by Lsm_Geom().

◆ m_lsm_size

int NOAH::m_lsm_size = 1
private

Referenced by Lsm_Data_Size().

◆ m_nz_lsm

int NOAH::m_nz_lsm = 30
private

◆ m_theta_dir

amrex::Real NOAH::m_theta_dir = 400.0
private

◆ noahmpio_vect

NoahmpIO_vector NOAH::noahmpio_vect
private

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