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.

117 {
118  std::ifstream file(forestfile, std::ios::in);
119  if (!file.good()) {
120  Abort("Cannot find forest file: " + forestfile);
121  }
122  // TreeType xc yc height diameter cd lai laimax
123  Real value1, value2, value3, value4, value5, value6, value7, value8;
124  int row_number = 0;
125  while (file >> value1 >> value2 >> value3 >> value4 >> value5 >> value6 >>
126  value7 >> value8) {
127  ++row_number;
128  if (value1 == Real(2.0)) {
129  const std::string error = erf_forest_utils::validate_laimax(
130  value8, "Forest file '" + forestfile + "' row " +
131  std::to_string(row_number) + " column 8 (laimax)");
132  if (!error.empty()) {
133  Abort(error);
134  }
135  }
136  m_type_forest.push_back(value1);
137  m_x_forest.push_back(value2);
138  m_y_forest.push_back(value3);
139  m_height_forest.push_back(value4);
140  m_diameter_forest.push_back(value5);
141  m_cd_forest.push_back(value6);
142  m_lai_forest.push_back(value7);
143  m_laimax_forest.push_back(value8);
144  }
145  file.close();
146 }
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.
215 {
216  m_use_gridded_data = true;
217  m_tree_type = tree_type;
218  m_laimax = laimax;
219 
221  tree_type == 1 || tree_type == 2,
222  "forest_tree_type must be 1 or 2");
223  if (tree_type == 2) {
224  const std::string error = erf_forest_utils::validate_laimax(
225  laimax, "erf.forest_laimax");
226  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(error.empty(), error.c_str());
227  m_lad_normalization = compute_lad_normalization(laimax);
228  }
229 
230 #ifdef ERF_USE_NETCDF
231  read_netcdf_file(lai_file, "LAI", m_gridded_lai,
235 
236  int nx_check, ny_check;
237  Real dx_check, dy_check, xmin_check, ymin_check;
238  read_netcdf_file(height_file, "height", m_gridded_height,
239  nx_check, ny_check, dx_check, dy_check,
240  xmin_check, ymin_check);
241 
244  const erf_grid_utils::UniformGridMetadata height_grid{
245  nx_check, ny_check, dx_check, dy_check, xmin_check, ymin_check};
246  std::string grid_error = erf_grid_utils::validate_matching_grid(
247  lai_grid, height_grid, "forest field 'LAI' in '" + lai_file + "'",
248  "forest field 'height' in '" + height_file + "'");
249  if (!grid_error.empty()) {
250  Abort(grid_error);
251  }
252 
253  read_netcdf_file(cd_file, "cd", m_gridded_cd,
254  nx_check, ny_check, dx_check, dy_check,
255  xmin_check, ymin_check);
256 
258  nx_check, ny_check, dx_check, dy_check, xmin_check, ymin_check};
260  lai_grid, cd_grid, "forest field 'LAI' in '" + lai_file + "'",
261  "forest field 'cd' in '" + cd_file + "'");
262  if (!grid_error.empty()) {
263  Abort(grid_error);
264  }
265 
266  Print() << "ForestDrag: Successfully read gridded forest data\n"
267  << " Grid size: " << m_grid_nx << " x " << m_grid_ny << "\n"
268  << " Grid spacing: dx=" << m_grid_dx << ", dy=" << m_grid_dy << "\n"
269  << " Domain: x=[" << m_grid_xmin << ", "
270  << (m_grid_xmin + (m_grid_nx-1)*m_grid_dx) << "], y=["
271  << m_grid_ymin << ", "
272  << (m_grid_ymin + (m_grid_ny-1)*m_grid_dy) << "]\n"
273  << " Tree type: " << m_tree_type << "\n"
274  << " LAImax: " << m_laimax << "\n";
275 
276 #else
277  amrex::ignore_unused(lai_file, height_file, cd_file);
278  Abort("ERF must be compiled with NetCDF support to use gridded forest data");
279 #endif
280 }
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.
156 {
157  m_use_gridded_data = true;
158  m_use_const_cd = true;
159  m_cd_const = cd_const;
160  m_tree_type = tree_type;
161  m_laimax = laimax;
162 
164  tree_type == 1 || tree_type == 2,
165  "forest_tree_type must be 1 or 2");
166  if (tree_type == 2) {
167  const std::string error = erf_forest_utils::validate_laimax(
168  laimax, "erf.forest_laimax");
169  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(error.empty(), error.c_str());
170  m_lad_normalization = compute_lad_normalization(laimax);
171  }
172 
173 #ifdef ERF_USE_NETCDF
174  read_netcdf_file(lai_file, "LAI", m_gridded_lai,
178 
179  int nx_check, ny_check;
180  Real dx_check, dy_check, xmin_check, ymin_check;
181  read_netcdf_file(height_file, "height", m_gridded_height,
182  nx_check, ny_check, dx_check, dy_check,
183  xmin_check, ymin_check);
184 
187  const erf_grid_utils::UniformGridMetadata height_grid{
188  nx_check, ny_check, dx_check, dy_check, xmin_check, ymin_check};
189  const std::string height_grid_error = erf_grid_utils::validate_matching_grid(
190  lai_grid, height_grid, "forest field 'LAI' in '" + lai_file + "'",
191  "forest field 'height' in '" + height_file + "'");
192  if (!height_grid_error.empty()) {
193  Abort(height_grid_error);
194  }
195 
196  Print() << "ForestDrag: Gridded LAI/height + constant Cd=" << m_cd_const << "\n"
197  << " Grid size: " << m_grid_nx << " x " << m_grid_ny << "\n"
198  << " Grid spacing: dx=" << m_grid_dx << ", dy=" << m_grid_dy << "\n"
199  << " Tree type: " << m_tree_type << " LAImax: " << m_laimax << "\n";
200 
201 #else
202  amrex::ignore_unused(lai_file, height_file);
203  Abort("ERF must be compiled with NetCDF support to use gridded forest data");
204 #endif
205 }
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.

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