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

#include <ERF_ForestDrag.H>

Collaboration diagram for ForestDrag:

Public Member Functions

 ForestDrag (std::string forestfile)
 
 ForestDrag (std::string lai_file, std::string height_file, std::string cd_file, int tree_type=1, amrex::Real laimax=0.8)
 
 ForestDrag (std::string lai_file, std::string height_file, amrex::Real cd_const, int tree_type=1, amrex::Real laimax=0.8)
 
 ~ForestDrag ()=default
 
void define_drag_field (const amrex::BoxArray &ba, const amrex::DistributionMapping &dm, amrex::Geometry &geom, amrex::MultiFab *z_phys_cc, amrex::MultiFab *z_phys_nd, bool need_frontal_area, int level)
 
amrex::MultiFab * get_drag_field ()
 
amrex::MultiFab * get_frontal_area ()
 

Private Member Functions

void read_netcdf_file (const std::string &filename, const std::string &varname, amrex::Vector< amrex::Real > &data, int &nx, int &ny, amrex::Real &dx, amrex::Real &dy, amrex::Real &xmin, amrex::Real &ymin)
 

Private Attributes

bool m_use_gridded_data {false}
 
bool m_need_frontal_area {true}
 
bool m_use_const_cd {false}
 
amrex::Real m_cd_const {0.0}
 
amrex::Vector< amrex::Realm_type_forest
 
amrex::Vector< amrex::Realm_x_forest
 
amrex::Vector< amrex::Realm_y_forest
 
amrex::Vector< amrex::Realm_height_forest
 
amrex::Vector< amrex::Realm_diameter_forest
 
amrex::Vector< amrex::Realm_cd_forest
 
amrex::Vector< amrex::Realm_lai_forest
 
amrex::Vector< amrex::Realm_laimax_forest
 
amrex::Vector< amrex::Realm_gridded_lai
 
amrex::Vector< amrex::Realm_gridded_height
 
amrex::Vector< amrex::Realm_gridded_cd
 
int m_grid_nx {0}
 
int m_grid_ny {0}
 
amrex::Real m_grid_dx {0.0}
 
amrex::Real m_grid_dy {0.0}
 
amrex::Real m_grid_xmin {0.0}
 
amrex::Real m_grid_ymin {0.0}
 
int m_tree_type {1}
 
amrex::Real m_laimax {0.8}
 
amrex::Real m_lad_normalization {1.0}
 
std::unique_ptr< amrex::MultiFab > m_forest_drag
 
std::unique_ptr< amrex::MultiFab > m_frontal_area
 

Detailed Description

Build canopy leaf-area-density and momentum-drag fields.

The vertical leaf-area-density profiles follow Lalic and Mihailovic (2004), https://doi.org/10.1175/1520-0450(2004)043%3C0641:AERDLD%3E2.0.CO;2. Canopies may be supplied as discrete patches in a text file or as gridded LAI, height, and drag-coefficient NetCDF fields.

Constructor & Destructor Documentation

◆ ForestDrag() [1/3]

ForestDrag::ForestDrag ( std::string  forestfile)
explicit

Construct a discrete-patch canopy from a text file.

118 {
119  std::ifstream file(forestfile, std::ios::in);
120  if (!file.good()) {
121  Abort("Cannot find forest file: " + forestfile);
122  }
123  // TreeType xc yc height diameter cd lai laimax
124  Real value1, value2, value3, value4, value5, value6, value7, value8;
125  int row_number = 0;
126  while (file >> value1 >> value2 >> value3 >> value4 >> value5 >> value6 >>
127  value7 >> value8) {
128  ++row_number;
129  if (value1 == Real(2.0)) {
130  const std::string error = erf_forest_utils::validate_laimax(
131  value8, "Forest file '" + forestfile + "' row " +
132  std::to_string(row_number) + " column 8 (laimax)");
133  if (!error.empty()) {
134  Abort(error);
135  }
136  }
137  m_type_forest.push_back(value1);
138  m_x_forest.push_back(value2);
139  m_y_forest.push_back(value3);
140  m_height_forest.push_back(value4);
141  m_diameter_forest.push_back(value5);
142  m_cd_forest.push_back(value6);
143  m_lai_forest.push_back(value7);
144  m_laimax_forest.push_back(value8);
145  }
146  file.close();
147 }
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Vector< amrex::Real > m_diameter_forest
Definition: ERF_ForestDrag.H:96
amrex::Vector< amrex::Real > m_laimax_forest
Definition: ERF_ForestDrag.H:99
amrex::Vector< amrex::Real > m_lai_forest
Definition: ERF_ForestDrag.H:98
amrex::Vector< amrex::Real > m_x_forest
Definition: ERF_ForestDrag.H:93
amrex::Vector< amrex::Real > m_height_forest
Definition: ERF_ForestDrag.H:95
amrex::Vector< amrex::Real > m_cd_forest
Definition: ERF_ForestDrag.H:97
amrex::Vector< amrex::Real > m_type_forest
Definition: ERF_ForestDrag.H:92
amrex::Vector< amrex::Real > m_y_forest
Definition: ERF_ForestDrag.H:94
std::string validate_laimax(const amrex::Real laimax, const std::string &source)
Definition: ERF_ForestUtils.H:36
Here is the call graph for this function:

◆ ForestDrag() [2/3]

ForestDrag::ForestDrag ( std::string  lai_file,
std::string  height_file,
std::string  cd_file,
int  tree_type = 1,
amrex::Real  laimax = 0.8 
)

Construct a gridded canopy with drag coefficient read from NetCDF.

Parameters
lai_fileNetCDF file containing the horizontal LAI field.
height_fileNetCDF file containing canopy height.
cd_fileNetCDF file containing the cd field.
tree_typeLAD profile selector (1 uniform, 2 Lalic–Mihailovic).
laimaxFractional height of maximum LAD for profile type 2.
216 {
217  m_use_gridded_data = true;
218  m_tree_type = tree_type;
219  m_laimax = laimax;
220 
222  tree_type == 1 || tree_type == 2,
223  "forest_tree_type must be 1 or 2");
224  if (tree_type == 2) {
225  const std::string error = erf_forest_utils::validate_laimax(
226  laimax, "erf.forest_laimax");
227  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(error.empty(), error.c_str());
228  m_lad_normalization = compute_lad_normalization(laimax);
229  }
230 
231 #ifdef ERF_USE_NETCDF
232  read_netcdf_file(lai_file, "LAI", m_gridded_lai,
236 
237  int nx_check, ny_check;
238  Real dx_check, dy_check, xmin_check, ymin_check;
239  read_netcdf_file(height_file, "height", m_gridded_height,
240  nx_check, ny_check, dx_check, dy_check,
241  xmin_check, ymin_check);
242 
245  const erf_grid_utils::UniformGridMetadata height_grid{
246  nx_check, ny_check, dx_check, dy_check, xmin_check, ymin_check};
247  std::string grid_error = erf_grid_utils::validate_matching_grid(
248  lai_grid, height_grid, "forest field 'LAI' in '" + lai_file + "'",
249  "forest field 'height' in '" + height_file + "'");
250  if (!grid_error.empty()) {
251  Abort(grid_error);
252  }
253 
254  read_netcdf_file(cd_file, "cd", m_gridded_cd,
255  nx_check, ny_check, dx_check, dy_check,
256  xmin_check, ymin_check);
257 
259  nx_check, ny_check, dx_check, dy_check, xmin_check, ymin_check};
261  lai_grid, cd_grid, "forest field 'LAI' in '" + lai_file + "'",
262  "forest field 'cd' in '" + cd_file + "'");
263  if (!grid_error.empty()) {
264  Abort(grid_error);
265  }
266 
267  Print() << "ForestDrag: Successfully read gridded forest data\n"
268  << " Grid size: " << m_grid_nx << " x " << m_grid_ny << "\n"
269  << " Grid spacing: dx=" << m_grid_dx << ", dy=" << m_grid_dy << "\n"
270  << " Domain: x=[" << m_grid_xmin << ", "
271  << (m_grid_xmin + (m_grid_nx-1)*m_grid_dx) << "], y=["
272  << m_grid_ymin << ", "
273  << (m_grid_ymin + (m_grid_ny-1)*m_grid_dy) << "]\n"
274  << " Tree type: " << m_tree_type << "\n"
275  << " LAImax: " << m_laimax << "\n";
276 
277 #else
278  amrex::ignore_unused(lai_file, height_file, cd_file);
279  Abort("ERF must be compiled with NetCDF support to use gridded forest data");
280 #endif
281 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
amrex::Real m_lad_normalization
Definition: ERF_ForestDrag.H:119
amrex::Real m_grid_xmin
Definition: ERF_ForestDrag.H:110
amrex::Real m_grid_dy
Definition: ERF_ForestDrag.H:109
int m_grid_nx
Definition: ERF_ForestDrag.H:106
void read_netcdf_file(const std::string &filename, const std::string &varname, amrex::Vector< amrex::Real > &data, int &nx, int &ny, amrex::Real &dx, amrex::Real &dy, amrex::Real &xmin, amrex::Real &ymin)
amrex::Vector< amrex::Real > m_gridded_lai
Definition: ERF_ForestDrag.H:102
int m_tree_type
Definition: ERF_ForestDrag.H:114
amrex::Vector< amrex::Real > m_gridded_height
Definition: ERF_ForestDrag.H:103
amrex::Real m_grid_dx
Definition: ERF_ForestDrag.H:108
amrex::Real m_laimax
Definition: ERF_ForestDrag.H:115
amrex::Vector< amrex::Real > m_gridded_cd
Definition: ERF_ForestDrag.H:104
bool m_use_gridded_data
Definition: ERF_ForestDrag.H:82
int m_grid_ny
Definition: ERF_ForestDrag.H:107
amrex::Real m_grid_ymin
Definition: ERF_ForestDrag.H:111
std::string validate_matching_grid(const UniformGridMetadata &reference, const UniformGridMetadata &candidate, const std::string &reference_description, const std::string &candidate_description)
Definition: ERF_GridUtils.H:128
Definition: ERF_GridUtils.H:18
Here is the call graph for this function:

◆ ForestDrag() [3/3]

ForestDrag::ForestDrag ( std::string  lai_file,
std::string  height_file,
amrex::Real  cd_const,
int  tree_type = 1,
amrex::Real  laimax = 0.8 
)

Construct a gridded canopy with a spatially constant drag coefficient.

Parameters
lai_fileNetCDF file containing the horizontal LAI field.
height_fileNetCDF file containing canopy height.
cd_constSpatially constant drag coefficient.
tree_typeLAD profile selector (1 uniform, 2 Lalic–Mihailovic).
laimaxFractional height of maximum LAD for profile type 2.
157 {
158  m_use_gridded_data = true;
159  m_use_const_cd = true;
160  m_cd_const = cd_const;
161  m_tree_type = tree_type;
162  m_laimax = laimax;
163 
165  tree_type == 1 || tree_type == 2,
166  "forest_tree_type must be 1 or 2");
167  if (tree_type == 2) {
168  const std::string error = erf_forest_utils::validate_laimax(
169  laimax, "erf.forest_laimax");
170  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(error.empty(), error.c_str());
171  m_lad_normalization = compute_lad_normalization(laimax);
172  }
173 
174 #ifdef ERF_USE_NETCDF
175  read_netcdf_file(lai_file, "LAI", m_gridded_lai,
179 
180  int nx_check, ny_check;
181  Real dx_check, dy_check, xmin_check, ymin_check;
182  read_netcdf_file(height_file, "height", m_gridded_height,
183  nx_check, ny_check, dx_check, dy_check,
184  xmin_check, ymin_check);
185 
188  const erf_grid_utils::UniformGridMetadata height_grid{
189  nx_check, ny_check, dx_check, dy_check, xmin_check, ymin_check};
190  const std::string height_grid_error = erf_grid_utils::validate_matching_grid(
191  lai_grid, height_grid, "forest field 'LAI' in '" + lai_file + "'",
192  "forest field 'height' in '" + height_file + "'");
193  if (!height_grid_error.empty()) {
194  Abort(height_grid_error);
195  }
196 
197  Print() << "ForestDrag: Gridded LAI/height + constant Cd=" << m_cd_const << "\n"
198  << " Grid size: " << m_grid_nx << " x " << m_grid_ny << "\n"
199  << " Grid spacing: dx=" << m_grid_dx << ", dy=" << m_grid_dy << "\n"
200  << " Tree type: " << m_tree_type << " LAImax: " << m_laimax << "\n";
201 
202 #else
203  amrex::ignore_unused(lai_file, height_file);
204  Abort("ERF must be compiled with NetCDF support to use gridded forest data");
205 #endif
206 }
amrex::Real m_cd_const
Definition: ERF_ForestDrag.H:89
bool m_use_const_cd
Definition: ERF_ForestDrag.H:88
Here is the call graph for this function:

◆ ~ForestDrag()

ForestDrag::~ForestDrag ( )
default

Member Function Documentation

◆ define_drag_field()

void ForestDrag::define_drag_field ( const amrex::BoxArray &  ba,
const amrex::DistributionMapping &  dm,
amrex::Geometry &  geom,
amrex::MultiFab *  z_phys_cc,
amrex::MultiFab *  z_phys_nd,
bool  need_frontal_area,
int  level 
)

Allocate and fill drag and, optionally, frontal-area-density fields.

Parameters
need_frontal_areaAllocate the frontal-area-density field, which is only consumed by the fixed-leaf-temperature path.
levelLevel index, used only in diagnostic messages.

Neither argument is defaulted on purpose: every caller must state whether the frontal-area field is needed, so that a new call site cannot silently allocate and fill it when forest biophysics is off, nor report a placeholder level in the coverage warning.

291 {
292  m_need_frontal_area = need_frontal_area;
293  // Geometry params
294  const auto& dx = geom.CellSizeArray();
295  const auto& prob_lo = geom.ProbLoArray();
296 
297  bool all_boxes_touch_bottom = true;
298  for (int i = 0; i < ba.size(); i++) {
299  if (ba[i].smallEnd(2) != geom.Domain().smallEnd(2)) {
300  all_boxes_touch_bottom = false;
301  }
302  }
303  AMREX_ALWAYS_ASSERT(all_boxes_touch_bottom);
304 
305  // Allocate the forest drag MF and frontal area MF
306  // NOTE: 1 ghost cell for averaging to faces
307  m_forest_drag.reset();
308  m_forest_drag = std::make_unique<MultiFab>(ba,dm,1,1);
309  m_forest_drag->setVal(zero);
310 
311  m_frontal_area.reset();
312  if (m_need_frontal_area) {
313  m_frontal_area = std::make_unique<MultiFab>(ba,dm,1,1);
314  m_frontal_area->setVal(zero);
315  }
316 
317  // Copy namespace-scope constants into automatic-storage values before
318  // entering GPU lambdas. NVCC does not make these host-side constexpr
319  // variables available as device symbols automatically.
320  const Real zero_d = zero;
321  const Real one_d = one;
322  const Real myhalf_d = myhalf;
323  const Real fourth_d = fourth;
324  const bool store_frontal_area = m_need_frontal_area;
325 
326  if (m_use_gridded_data) {
327  // =====================================================================
328  // Gridded NetCDF mode: interpolate from gridded LAI/height/cd data
329  // =====================================================================
330 
331  const Real* lai_data_h = m_gridded_lai.data();
332  const Real* height_data_h = m_gridded_height.data();
333  const Real* cd_data_h = m_use_const_cd ? nullptr : m_gridded_cd.data();
334 
335  const int grid_nx = m_grid_nx;
336  const int grid_ny = m_grid_ny;
337  const Real grid_dx = m_grid_dx;
338  const Real grid_dy = m_grid_dy;
339  const Real grid_xmin = m_grid_xmin;
340  const Real grid_ymin = m_grid_ymin;
341 
342  warn_if_forest_grid_does_not_cover_targets(
343  *m_forest_drag, geom, grid_xmin, grid_ymin, grid_dx, grid_dy,
344  grid_nx, grid_ny, level);
345 
346  const int grid_size = m_grid_nx * m_grid_ny;
347  Gpu::DeviceVector<Real> lai_data_d(grid_size);
348  Gpu::DeviceVector<Real> height_data_d(grid_size);
349  Gpu::DeviceVector<Real> cd_data_d;
350  if (!m_use_const_cd) {
351  cd_data_d.resize(grid_size);
352  }
353 
354  Gpu::copy(Gpu::hostToDevice, lai_data_h, lai_data_h + grid_size,
355  lai_data_d.begin());
356  Gpu::copy(Gpu::hostToDevice, height_data_h, height_data_h + grid_size,
357  height_data_d.begin());
358  if (!m_use_const_cd) {
359  Gpu::copy(Gpu::hostToDevice, cd_data_h, cd_data_h + grid_size,
360  cd_data_d.begin());
361  }
362 
363  const Real* lai_data = lai_data_d.data();
364  const Real* height_data = height_data_d.data();
365  const Real* cd_data = m_use_const_cd ? nullptr : cd_data_d.data();
366  const Real cd_const = m_cd_const;
367  const bool use_const_cd = m_use_const_cd;
368 
369  const int tree_type = m_tree_type;
370  const Real laimax = m_laimax;
371  const Real lad_normalization = m_lad_normalization;
372 
373  for (MFIter mfi(*m_forest_drag); mfi.isValid(); ++mfi) {
374  Box gtbx = mfi.growntilebox();
375  const Array4<Real>& levelDrag = m_forest_drag->array(mfi);
376  const Array4<Real> frontalArea = store_frontal_area
377  ? m_frontal_area->array(mfi) : Array4<Real>{};
378  const Array4<const Real>& z_cc = z_phys_cc->const_array(mfi);
379  const Array4<const Real>& z_nd = z_phys_nd->const_array(mfi);
380 
381  ParallelFor(gtbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
382  {
383  const Real x = prob_lo[0] + (i + myhalf_d) * dx[0];
384  const Real y = prob_lo[1] + (j + myhalf_d) * dx[1];
385 
386  const Real z_sfc = fourth_d * (z_nd(i, j, 0) + z_nd(i + 1, j, 0) +
387  z_nd(i, j + 1, 0) + z_nd(i + 1, j + 1, 0));
388  const Real z = amrex::max((z_cc(i, j, k) - z_sfc), zero_d);
389 
390  const auto x_stencil = erf_grid_utils::uniform_interpolation_stencil(
391  x, grid_xmin, grid_dx, grid_nx);
392  const auto y_stencil = erf_grid_utils::uniform_interpolation_stencil(
393  y, grid_ymin, grid_dy, grid_ny);
394 
395  if (x_stencil.inside && y_stencil.inside) {
396  const int ii_c = x_stencil.lower;
397  const int jj_c = y_stencil.lower;
398  const Real wx = x_stencil.weight;
399  const Real wy = y_stencil.weight;
400 
401  // Bilinear interpolation of LAI
402  Real lai00 = lai_data[jj_c * grid_nx + ii_c];
403  Real lai10 = lai_data[jj_c * grid_nx + (ii_c + 1)];
404  Real lai01 = lai_data[(jj_c + 1) * grid_nx + ii_c];
405  Real lai11 = lai_data[(jj_c + 1) * grid_nx + (ii_c + 1)];
406  Real lai_interp = (lai00 * (one_d - wx) + lai10 * wx) * (one_d - wy) +
407  (lai01 * (one_d - wx) + lai11 * wx) * wy;
408 
409  // Bilinear interpolation of height
410  Real h00 = height_data[jj_c * grid_nx + ii_c];
411  Real h10 = height_data[jj_c * grid_nx + (ii_c + 1)];
412  Real h01 = height_data[(jj_c + 1) * grid_nx + ii_c];
413  Real h11 = height_data[(jj_c + 1) * grid_nx + (ii_c + 1)];
414  Real height_interp = (h00 * (one_d - wx) + h10 * wx) * (one_d - wy) +
415  (h01 * (one_d - wx) + h11 * wx) * wy;
416 
417  Real cd_interp = cd_const;
418  if (!use_const_cd) {
419  // Bilinear interpolation of Cd from file.
420  Real cd00 = cd_data[jj_c * grid_nx + ii_c];
421  Real cd10 = cd_data[jj_c * grid_nx + (ii_c + 1)];
422  Real cd01 = cd_data[(jj_c + 1) * grid_nx + ii_c];
423  Real cd11 = cd_data[(jj_c + 1) * grid_nx + (ii_c + 1)];
424  cd_interp = (cd00 * (one_d - wx) + cd10 * wx) * (one_d - wy) +
425  (cd01 * (one_d - wx) + cd11 * wx) * wy;
426  }
427 
428  // Compute drag if within canopy
429  if (z < height_interp && height_interp > zero_d && lai_interp > zero_d) {
430  Real af;
431  Real factor = one_d;
432 
433  if (tree_type == 1) {
434  af = lai_interp / height_interp;
435  } else {
436  const Real treeZm = laimax * height_interp;
437  af = lai_interp / (height_interp * lad_normalization);
438 
439  Real ratio = (height_interp - treeZm) / (height_interp - z);
440  if (z < treeZm) {
441  factor = amrex::Math::powi<6>(ratio) *
442  std::exp(Real(6.0) * (one_d - ratio));
443  } else {
444  factor = std::sqrt(ratio) *
445  std::exp(myhalf_d * (one_d - ratio));
446  }
447  }
448 
449  levelDrag(i, j, k) = cd_interp * af * factor;
450  if (store_frontal_area) {
451  frontalArea(i, j, k) = af * factor;
452  }
453  }
454  }
455  });
456  } // mfi
457 
458  // Synchronize before DeviceVectors go out of scope
459  Gpu::synchronize();
460 
461  } else {
462  // =====================================================================
463  // Discrete patch mode: original implementation
464  // =====================================================================
465 
466  for (unsigned ii = 0; ii < m_x_forest.size(); ++ii) {
467  Real af;
468  Real treeZm = zero_d;
469  int tf = int(m_type_forest[ii]);
470  Real hf = m_height_forest[ii];
471  Real xf = m_x_forest[ii];
472  Real yf = m_y_forest[ii];
473  Real df = m_diameter_forest[ii];
474  Real cdf = m_cd_forest[ii];
475  Real laif = m_lai_forest[ii];
476  Real laimaxf = m_laimax_forest[ii];
477 
478  if (tf == 1) {
479  af = laif / hf;
480  } else {
481  treeZm = laimaxf * hf;
482  af = laif / (hf * compute_lad_normalization(laimaxf));
483  }
484 
485  for (MFIter mfi(*m_forest_drag); mfi.isValid(); ++mfi) {
486  Box gtbx = mfi.growntilebox();
487  const Array4<Real>& levelDrag = m_forest_drag->array(mfi);
488  const Array4<Real> frontalArea = store_frontal_area
489  ? m_frontal_area->array(mfi) : Array4<Real>{};
490  const Array4<const Real>& z_cc = z_phys_cc->const_array(mfi);
491  const Array4<const Real>& z_nd = z_phys_nd->const_array(mfi);
492 
493  ParallelFor(gtbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
494  {
495  const Real x = prob_lo[0] + (i + myhalf_d) * dx[0];
496  const Real y = prob_lo[1] + (j + myhalf_d) * dx[1];
497 
498  const Real z_sfc = fourth_d * (z_nd(i,j ,0) + z_nd(i+1,j ,0)
499  + z_nd(i,j+1,0) + z_nd(i+1,j+1,0));
500  const Real z = std::max((z_cc(i,j,k)-z_sfc), amrex::Real(0));
501 
502  const Real radius = std::sqrt((x - xf) * (x - xf) +
503  (y - yf) * (y - yf));
504 
505  Real factor = one_d;
506  if ((z <= hf) && (radius <= (myhalf_d * df))) {
507  if (tf == 2) {
508  Real ratio = (hf - treeZm) / (hf - z);
509  if (z < treeZm) {
510  factor = amrex::Math::powi<6>(ratio) *
511  std::exp(Real(6.0) * (one_d - ratio));
512  } else if (z <= hf) {
513  factor = std::sqrt(ratio) *
514  std::exp(myhalf_d * (one_d - ratio));
515  }
516  }
517  levelDrag(i, j, k) = cdf * af * factor;
518  if (store_frontal_area) {
519  frontalArea(i, j, k) = af * factor;
520  }
521  }
522  });
523  } // mfi
524  } // ii (forest patch)
525 
526  } // end else (discrete patch mode)
527 
528  // Fillboundary for periodic ghost cell copy
529  m_forest_drag->FillBoundary(geom.periodicity());
530  if (m_frontal_area != nullptr) {
531  m_frontal_area->FillBoundary(geom.periodicity());
532  }
533 
534 } // define_drag_field
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
const GpuArray< Real, AMREX_SPACEDIM > prob_lo
Definition: ERF_InitCustomPert_CloudChamber.H:33
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:30
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:35
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:34
bool m_need_frontal_area
Definition: ERF_ForestDrag.H:85
std::unique_ptr< amrex::MultiFab > m_frontal_area
Definition: ERF_ForestDrag.H:125
std::unique_ptr< amrex::MultiFab > m_forest_drag
Definition: ERF_ForestDrag.H:122
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE InterpolationStencil uniform_interpolation_stencil(amrex::Real coordinate, amrex::Real origin, amrex::Real spacing, int point_count) noexcept
Definition: ERF_GridUtils.H:173
Here is the call graph for this function:

◆ get_drag_field()

amrex::MultiFab* ForestDrag::get_drag_field ( )
inline

Return the cell-centered product of drag coefficient and LAD.

74 { return m_forest_drag.get(); }

◆ get_frontal_area()

amrex::MultiFab* ForestDrag::get_frontal_area ( )
inline

Return cell-centered leaf/frontal area density without drag coefficient.

78 { return m_frontal_area.get(); }

◆ read_netcdf_file()

void ForestDrag::read_netcdf_file ( const std::string &  filename,
const std::string &  varname,
amrex::Vector< amrex::Real > &  data,
int &  nx,
int &  ny,
amrex::Real dx,
amrex::Real dy,
amrex::Real xmin,
amrex::Real ymin 
)
private

Member Data Documentation

◆ m_cd_const

amrex::Real ForestDrag::m_cd_const {0.0}
private

◆ m_cd_forest

amrex::Vector<amrex::Real> ForestDrag::m_cd_forest
private

◆ m_diameter_forest

amrex::Vector<amrex::Real> ForestDrag::m_diameter_forest
private

◆ m_forest_drag

std::unique_ptr<amrex::MultiFab> ForestDrag::m_forest_drag
private

Referenced by get_drag_field().

◆ m_frontal_area

std::unique_ptr<amrex::MultiFab> ForestDrag::m_frontal_area
private

Referenced by get_frontal_area().

◆ m_grid_dx

amrex::Real ForestDrag::m_grid_dx {0.0}
private

◆ m_grid_dy

amrex::Real ForestDrag::m_grid_dy {0.0}
private

◆ m_grid_nx

int ForestDrag::m_grid_nx {0}
private

◆ m_grid_ny

int ForestDrag::m_grid_ny {0}
private

◆ m_grid_xmin

amrex::Real ForestDrag::m_grid_xmin {0.0}
private

◆ m_grid_ymin

amrex::Real ForestDrag::m_grid_ymin {0.0}
private

◆ m_gridded_cd

amrex::Vector<amrex::Real> ForestDrag::m_gridded_cd
private

◆ m_gridded_height

amrex::Vector<amrex::Real> ForestDrag::m_gridded_height
private

◆ m_gridded_lai

amrex::Vector<amrex::Real> ForestDrag::m_gridded_lai
private

◆ m_height_forest

amrex::Vector<amrex::Real> ForestDrag::m_height_forest
private

◆ m_lad_normalization

amrex::Real ForestDrag::m_lad_normalization {1.0}
private

◆ m_lai_forest

amrex::Vector<amrex::Real> ForestDrag::m_lai_forest
private

◆ m_laimax

amrex::Real ForestDrag::m_laimax {0.8}
private

◆ m_laimax_forest

amrex::Vector<amrex::Real> ForestDrag::m_laimax_forest
private

◆ m_need_frontal_area

bool ForestDrag::m_need_frontal_area {true}
private

◆ m_tree_type

int ForestDrag::m_tree_type {1}
private

◆ m_type_forest

amrex::Vector<amrex::Real> ForestDrag::m_type_forest
private

◆ m_use_const_cd

bool ForestDrag::m_use_const_cd {false}
private

◆ m_use_gridded_data

bool ForestDrag::m_use_gridded_data {false}
private

◆ m_x_forest

amrex::Vector<amrex::Real> ForestDrag::m_x_forest
private

◆ m_y_forest

amrex::Vector<amrex::Real> ForestDrag::m_y_forest
private

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