ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InitForEnsemble.cpp File Reference
#include <ERF.H>
#include <ERF_TileNoZ.H>
#include <AMReX_PlotFileUtil.H>
#include <filesystem>
Include dependency graph for ERF_InitForEnsemble.cpp:

Functions

void NormalizeMultiFabRMS_PerComponent (MultiFab &mf_cc_pert)
 
void ApplyNeumannBCs (const Geometry &geom, MultiFab &mf_cc)
 
void ReadCustomDataFile (const std::string &filename_custom, int &nx, int &ny, int &nz, int &ng, int &ncomp, std::array< Real, 3 > &problo_ext, std::array< Real, 3 > &probhi_ext, Vector< Real > &data_rho, Vector< Real > &data_theta, Vector< Real > &data_xvel, Vector< Real > &data_yvel, Vector< Real > &data_zvel, Vector< Real > &data_qv, Vector< Real > &data_qc, Vector< Real > &data_qrain)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx (int i, int j, int k, int nx, int ny)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real interp_trilinear (const Real *f, int i, int j, int k, Real tx, Real ty, Real tz, int nx, int ny, int nz)
 
void InterpolateToFineMF (const Vector< Real > &data_rho, const Vector< Real > &data_theta, const Vector< Real > &data_xvel, const Vector< Real > &data_yvel, const Vector< Real > &data_zvel, const Vector< Real > &data_qv, const Vector< Real > &data_qc, const Vector< Real > &data_qrain, int nx, int ny, int nz, const std::array< Real, 3 > &problo, const std::array< Real, 3 > &probhi, MultiFab &mf_fine, const Geometry &geom_fine)
 
void MakeFinalMultiFabs (const MultiFab &mf_cc_fine, MultiFab &cons_pert, MultiFab &xvel_pert, MultiFab &yvel_pert, MultiFab &zvel_pert, const int n_qstate_moist)
 
void AddPertToBckgnd (MultiFab &mf_cc_fine, const MultiFab &mf_cc_pert, const Real &ens_pert_amplitude)
 

Function Documentation

◆ AddPertToBckgnd()

void AddPertToBckgnd ( MultiFab &  mf_cc_fine,
const MultiFab &  mf_cc_pert,
const Real ens_pert_amplitude 
)

Add normalized perturbations to the interpolated background state.

Parameters
mf_cc_fineBackground state modified in place
mf_cc_pertPerturbation field to apply
ens_pert_amplitudeRelative perturbation amplitude
662 {
663  const int ncomp = mf_cc_fine.nComp();
664 
665  // Optional safety check (recommended)
666  AMREX_ALWAYS_ASSERT(mf_cc_pert.nComp() == ncomp);
667 
668  for (MFIter mfi(mf_cc_fine, TilingIfNotGPU()); mfi.isValid(); ++mfi)
669  {
670  const Box& bx = mfi.tilebox();
671 
672  auto const& bg = mf_cc_fine.array(mfi);
673  auto const& pert = mf_cc_pert.const_array(mfi);
674 
675  amrex::ParallelFor(bx, ncomp,
676  [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
677  {
678  Real ens_amp = ens_pert_amplitude*std::abs(bg(i,j,k,n));
679  bg(i,j,k,n) += ens_amp*pert(i,j,k,n);
680  });
681  }
682 }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
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);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
real(c_double), private bg
Definition: ERF_module_mp_morr_two_moment.F90:182

Referenced by ERF::create_background_state_for_ensemble().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ApplyNeumannBCs()

void ApplyNeumannBCs ( const Geometry &  geom,
MultiFab &  mf_cc 
)

Fill periodic ghost cells and apply first-order extrapolation at boundaries.

Parameters
geomGeometry defining domain bounds and periodicity
mf_ccCell-centered MultiFab whose ghost cells are filled in place
187 {
188 
189  // -------------------------------------------------
190  // 2. Fill interior + periodic ghost cells
191  // -------------------------------------------------
192  mf_cc.FillBoundary(geom.periodicity());
193  // -------------------------------------------------
194  // 3. Apply FOExtrap (Neumann) at domain boundaries
195  // -------------------------------------------------
196  const Box& domain = geom.Domain();
197 
198  const bool periodic_x = geom.isPeriodic(0);
199  const bool periodic_y = geom.isPeriodic(1);
200  const bool periodic_z = geom.isPeriodic(2);
201 
202  for (MFIter mfi(mf_cc, TilingIfNotGPU()); mfi.isValid(); ++mfi)
203  {
204  const Box& gbx = mfi.growntilebox(); // includes ghost cells
205  const Box& vbx = mfi.validbox();
206 
207  auto const& arr = mf_cc.array(mfi);
208  int ncomp = mf_cc.nComp();
209 
210  ParallelFor(gbx, ncomp,
211  [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
212  {
213  if (vbx.contains(i,j,k)) return;
214 
215  int ii = i;
216  int jj = j;
217  int kk = k;
218 
219  if (!periodic_x) {
220  ii = amrex::max(domain.smallEnd(0),
221  amrex::min(i, domain.bigEnd(0)));
222  }
223 
224  if (!periodic_y) {
225  jj = amrex::max(domain.smallEnd(1),
226  amrex::min(j, domain.bigEnd(1)));
227  }
228 
229  if (!periodic_z) {
230  kk = amrex::max(domain.smallEnd(2),
231  amrex::min(k, domain.bigEnd(2)));
232  }
233 
234  arr(i,j,k,n) = arr(ii,jj,kk,n);
235  });
236  }
237 }
if(l_use_mynn &&start_comp<=RhoKE_comp &&end_comp >=RhoKE_comp)
Definition: ERF_AddQKESources.H:2

Referenced by ERF::create_background_state_for_ensemble().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ idx()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx ( int  i,
int  j,
int  k,
int  nx,
int  ny 
)

Convert a three-dimensional cell index into a flattened array index.

Parameters
ix-index
jy-index
kz-index
nxNumber of cells in the x-direction
nyNumber of cells in the y-direction
Returns
Flattened index into a row-major 3D array
366 {
367  return i + nx * (j + ny * k);
368 }

Referenced by br_shift(), ChopGrids2D(), clamp_interp_index(), closest_index(), ERF::FillSurfaceStateMultiFabs(), NOAHMP::Init(), ERF::init_stuff(), ERF::InitData_post(), MRISplitIntegrator< T >::initialize_data(), interp_trilinear(), NOAHMP::Lsm_DataIndex(), NOAHMP::Lsm_FluxIndex(), parse_fixed_width_int(), ERF::read_box_for_refinement(), ReadBndryPlanes::read_file(), ReadBndryPlanes::read_input_files(), ReadCustomBinaryIC(), ReadCustomDataFile(), SatMethods::wv_sat_qsat_ice(), SatMethods::wv_sat_qsat_trans(), SatMethods::wv_sat_qsat_water(), SatMethods::wv_sat_svp_ice(), SatMethods::wv_sat_svp_trans(), and SatMethods::wv_sat_svp_water().

Here is the caller graph for this function:

◆ interp_trilinear()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real interp_trilinear ( const Real f,
int  i,
int  j,
int  k,
Real  tx,
Real  ty,
Real  tz,
int  nx,
int  ny,
int  nz 
)

Trilinearly interpolate one scalar component from a flattened array.

Parameters
fFlattened source data
iLower x-index of the interpolation cell
jLower y-index of the interpolation cell
kLower z-index of the interpolation cell
txFractional x-coordinate within the cell
tyFractional y-coordinate within the cell
tzFractional z-coordinate within the cell
nxNumber of cells in the x-direction
nyNumber of cells in the y-direction
nzNumber of cells in the z-direction
Returns
Interpolated scalar value
392 {
393  int i1 = amrex::min(i+1, nx-1);
394  int j1 = amrex::min(j+1, ny-1);
395  int k1 = amrex::min(k+1, nz-1);
396 
397  Real c000 = f[idx(i ,j ,k ,nx,ny)];
398  Real c100 = f[idx(i1,j ,k ,nx,ny)];
399  Real c010 = f[idx(i ,j1,k ,nx,ny)];
400  Real c110 = f[idx(i1,j1,k ,nx,ny)];
401  Real c001 = f[idx(i ,j ,k1,nx,ny)];
402  Real c101 = f[idx(i1,j ,k1,nx,ny)];
403  Real c011 = f[idx(i ,j1,k1,nx,ny)];
404  Real c111 = f[idx(i1,j1,k1,nx,ny)];
405 
406  Real c00 = c000*(1-tx) + c100*tx;
407  Real c10 = c010*(1-tx) + c110*tx;
408  Real c01 = c001*(1-tx) + c101*tx;
409  Real c11 = c011*(1-tx) + c111*tx;
410 
411  Real c0 = c00*(1-ty) + c10*ty;
412  Real c1 = c01*(1-ty) + c11*ty;
413 
414  return c0*(1-tz) + c1*tz;
415 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx(int i, int j, int k, int nx, int ny)
Definition: ERF_InitForEnsemble.cpp:365
real(c_double), private k1
Definition: ERF_module_mp_morr_two_moment.F90:213
real(c_double), private c1
Definition: ERF_module_mp_morr_two_moment.F90:212

Referenced by InterpolateToFineMF().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ InterpolateToFineMF()

void InterpolateToFineMF ( const Vector< Real > &  data_rho,
const Vector< Real > &  data_theta,
const Vector< Real > &  data_xvel,
const Vector< Real > &  data_yvel,
const Vector< Real > &  data_zvel,
const Vector< Real > &  data_qv,
const Vector< Real > &  data_qc,
const Vector< Real > &  data_qrain,
int  nx,
int  ny,
int  nz,
const std::array< Real, 3 > &  problo,
const std::array< Real, 3 > &  probhi,
MultiFab &  mf_fine,
const Geometry &  geom_fine 
)

Interpolate coarse custom background data onto the fine cell-centered grid.

Parameters
data_rhoCoarse density values
data_thetaCoarse potential temperature values
data_xvelCoarse x-velocity values
data_yvelCoarse y-velocity values
data_zvelCoarse z-velocity values
data_qvCoarse water vapor values
data_qcCoarse cloud water values
data_qrainCoarse rain water values
nxNumber of coarse cells in the x-direction
nyNumber of coarse cells in the y-direction
nzNumber of coarse cells in the z-direction
probloPhysical lower bounds of the coarse data
probhiPhysical upper bounds of the coarse data
mf_fineFine-grid cell-centered MultiFab to fill
geom_fineGeometry of the fine grid
451 {
452  // coarse spacing
453  Real dx_c[3];
454  dx_c[0] = (probhi[0] - problo[0]) / nx;
455  dx_c[1] = (probhi[1] - problo[1]) / ny;
456  dx_c[2] = (probhi[2] - problo[2]) / nz;
457 
458  const auto problo_f = geom_fine.ProbLoArray();
459  const auto dx_f = geom_fine.CellSizeArray();
460 
461  // Step 1: declare device vectors with correct size
462  amrex::Gpu::DeviceVector<Real> d_rho(data_rho.size());
463  amrex::Gpu::DeviceVector<Real> d_theta(data_theta.size());
464  amrex::Gpu::DeviceVector<Real> d_xvel(data_xvel.size());
465  amrex::Gpu::DeviceVector<Real> d_yvel(data_yvel.size());
466  amrex::Gpu::DeviceVector<Real> d_zvel(data_zvel.size());
467  amrex::Gpu::DeviceVector<Real> d_qv(data_qv.size());
468  amrex::Gpu::DeviceVector<Real> d_qc(data_qc.size());
469  amrex::Gpu::DeviceVector<Real> d_qrain(data_qrain.size());
470 
471  // Step 2: copy data from host to device
472  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
473  data_rho.begin(), data_rho.end(),
474  d_rho.begin());
475 
476  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
477  data_theta.begin(), data_theta.end(),
478  d_theta.begin());
479 
480  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
481  data_xvel.begin(), data_xvel.end(),
482  d_xvel.begin());
483 
484  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
485  data_yvel.begin(), data_yvel.end(),
486  d_yvel.begin());
487 
488  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
489  data_zvel.begin(), data_zvel.end(),
490  d_zvel.begin());
491 
492  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
493  data_qv.begin(), data_qv.end(),
494  d_qv.begin());
495 
496  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
497  data_qc.begin(), data_qc.end(),
498  d_qc.begin());
499 
500  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
501  data_qrain.begin(), data_qrain.end(),
502  d_qrain.begin());
503 
504  const Real* rho_ptr = d_rho.data();
505  const Real* theta_ptr = d_theta.data();
506  const Real* xvel_ptr = d_xvel.data();
507  const Real* yvel_ptr = d_yvel.data();
508  const Real* zvel_ptr = d_zvel.data();
509  const Real* qv_ptr = d_qv.data();
510  const Real* qc_ptr = d_qc.data();
511  const Real* qrain_ptr = d_qrain.data();
512 
513  // -------------------------------
514  // GPU kernel over MultiFab
515  // -------------------------------
516  for (MFIter mfi(mf_fine); mfi.isValid(); ++mfi)
517  {
518  const Box& bx = mfi.validbox();
519  auto arr = mf_fine.array(mfi);
520 
522  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
523  {
524  // physical location (fine cell center)
525  Real x = problo_f[0] + (i + myhalf) * dx_f[0];
526  Real y = problo_f[1] + (j + myhalf) * dx_f[1];
527  Real z = problo_f[2] + (k + myhalf) * dx_f[2];
528 
529  // map to coarse index space (cell centers)
530  Real rx = (x - problo[0]) / dx_c[0] - myhalf;
531  Real ry = (y - problo[1]) / dx_c[1] - myhalf;
532  Real rz = (z - problo[2]) / dx_c[2] - myhalf;
533 
534  // clamp coordinates into valid coarse cell-center range
535  rx = amrex::max(Real(0), amrex::min(rx, Real(nx-1)));
536  ry = amrex::max(Real(0), amrex::min(ry, Real(ny-1)));
537  rz = amrex::max(Real(0), amrex::min(rz, Real(nz-1)));
538 
539  int ic = static_cast<int>(amrex::Math::floor(rx));
540  int jc = static_cast<int>(amrex::Math::floor(ry));
541  int kc = static_cast<int>(amrex::Math::floor(rz));
542 
543  Real tx = rx - ic;
544  Real ty = ry - jc;
545  Real tz = rz - kc;
546 
547  // optional: avoid degenerate interpolation at upper edge
548  if (ic == nx-1) tx = Real(0);
549  if (jc == ny-1) ty = Real(0);
550  if (kc == nz-1) tz = Real(0);
551 
552  //printf("The values are x, y, z, rx, ry, rz = %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g\n", x, y, z, rx, ry, rz);
553 
554  // interpolate each component using device trilinear
555  arr(i,j,k,0) = interp_trilinear(rho_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
556  arr(i,j,k,1) = interp_trilinear(theta_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
557  arr(i,j,k,2) = interp_trilinear(xvel_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
558  arr(i,j,k,3) = interp_trilinear(yvel_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
559  arr(i,j,k,4) = interp_trilinear(zvel_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
560  arr(i,j,k,5) = interp_trilinear(qv_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
561  arr(i,j,k,6) = interp_trilinear(qc_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
562  arr(i,j,k,7) = interp_trilinear(qrain_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
563 
564  /*printf("Values are %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g\n",
565  arr(i,j,k,0), arr(i,j,k,1), arr(i,j,k,2), arr(i,j,k,3),
566  arr(i,j,k,4), arr(i,j,k,5), arr(i,j,k,6), arr(i,j,k,7));*/
567  });
568  }
569 }
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
auto probhi
Definition: ERF_InitCustomPertVels_ABL.H:21
auto problo
Definition: ERF_InitCustomPertVels_ABL.H:20
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real interp_trilinear(const Real *f, int i, int j, int k, Real tx, Real ty, Real tz, int nx, int ny, int nz)
Definition: ERF_InitForEnsemble.cpp:387

Referenced by ERF::create_background_state_for_ensemble().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeFinalMultiFabs()

void MakeFinalMultiFabs ( const MultiFab &  mf_cc_fine,
MultiFab &  cons_pert,
MultiFab &  xvel_pert,
MultiFab &  yvel_pert,
MultiFab &  zvel_pert,
const int  n_qstate_moist 
)

Split cell-centered interpolated background data into ERF state and face velocities.

Parameters
mf_cc_fineFine-grid cell-centered source data
cons_pertConserved-state perturbation MultiFab to fill
xvel_pertx-face velocity perturbation MultiFab to fill
yvel_perty-face velocity perturbation MultiFab to fill
zvel_pertz-face velocity perturbation MultiFab to fill
587 {
588 
589  for (MFIter mfi(cons_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
590  {
591  const Box& bx = mfi.tilebox();
592 
593  auto const& mf_cc_fine_arr = mf_cc_fine.const_array(mfi);
594  auto const& cons_pert_arr = cons_pert.array(mfi);
595 
596  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
597  {
598  Real tmp_rho = mf_cc_fine_arr(i,j,k,0);
599  Real tmp_theta = mf_cc_fine_arr(i,j,k,1);
600  Real tmp_qv = mf_cc_fine_arr(i,j,k,5);
601  Real tmp_qc = mf_cc_fine_arr(i,j,k,6);
602  Real tmp_qrain = mf_cc_fine_arr(i,j,k,7);
603  cons_pert_arr(i,j,k,Rho_comp) = tmp_rho;
604  cons_pert_arr(i,j,k,RhoTheta_comp) = tmp_rho*tmp_theta;
605  if (n_qstate_moist > 0) cons_pert_arr(i,j,k,RhoQ1_comp) = tmp_rho*tmp_qv;
606  if (n_qstate_moist > 1) cons_pert_arr(i,j,k,RhoQ2_comp) = tmp_rho*tmp_qc;
607  if (n_qstate_moist > 2) cons_pert_arr(i,j,k,RhoQ3_comp) = tmp_rho*tmp_qrain;
608  });
609  }
610 
611  // --- X-faces (component 2) ---
612  for (MFIter mfi(xvel_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
613  {
614  const Box& bx = mfi.tilebox();
615  auto const& uface = xvel_pert.array(mfi);
616  auto const& cc = mf_cc_fine.const_array(mfi);
617 
618  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
619  {
620  uface(i,j,k) = myhalf * (cc(i-1,j,k,2) + cc(i,j,k,2));
621  });
622  }
623 
624  // --- Y-faces (component 3) ---
625  for (MFIter mfi(yvel_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
626  {
627  const Box& bx = mfi.tilebox();
628  auto const& vface = yvel_pert.array(mfi);
629  auto const& cc = mf_cc_fine.const_array(mfi);
630 
631  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
632  {
633  vface(i,j,k) = myhalf * (cc(i,j-1,k,3) + cc(i,j,k,3));
634  });
635  }
636 
637  // --- Z-faces (component 4) ---
638  for (MFIter mfi(zvel_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
639  {
640  const Box& bx = mfi.tilebox();
641  auto const& wface = zvel_pert.array(mfi);
642  //auto const& cc = mf_cc_fine.const_array(mfi);
643 
644  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
645  {
646  wface(i,j,k) = zero; //myhalf * (cc(i,j,k-1,4) + cc(i,j,k,4));
647  });
648  }
649 }
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:43
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:44
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42

Referenced by ERF::create_background_state_for_ensemble().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ NormalizeMultiFabRMS_PerComponent()

void NormalizeMultiFabRMS_PerComponent ( MultiFab &  mf_cc_pert)

Normalize each component of a perturbation MultiFab by its global RMS value.

Parameters
mf_cc_pertMultiFab whose components are normalized in place
52 {
53  const int ncomp = mf_cc_pert.nComp();
54 
55  for (int n = 0; n < ncomp; ++n)
56  {
57  // 1. Set up AMReX reduction (sum of squares + count)
58  ReduceOps<ReduceOpSum, ReduceOpSum> reduce_op;
59  ReduceData<Real, Long> reduce_data(reduce_op);
60  using ReduceTuple = typename decltype(reduce_data)::Type;
61 
62  // 2. Loop over tiles and accumulate
63  for (MFIter mfi(mf_cc_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
64  {
65  const Box& bx = mfi.tilebox();
66  auto const& arr = mf_cc_pert.const_array(mfi);
67 
68  reduce_op.eval(bx, reduce_data,
69  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept -> ReduceTuple
70  {
71  Real v = arr(i, j, k, n);
72  return { v * v, 1L };
73  });
74  }
75 
76  // 3. Retrieve results (includes implicit GPU sync + host copy)
77  auto rv = reduce_data.value(reduce_op);
78  Real h_sumsq = amrex::get<0>(rv);
79  Long h_count = amrex::get<1>(rv);
80 
81  // 4. Sum across MPI ranks
82  ParallelDescriptor::ReduceRealSum(h_sumsq);
83  ParallelDescriptor::ReduceLongSum(h_count);
84 
85  // 5. Compute RMS and normalize
86  if (h_count > 0)
87  {
88  Real rms = std::sqrt(h_sumsq / static_cast<Real>(h_count));
89  if (rms > zero) {
90  mf_cc_pert.mult(one / rms, n, 1);
91  }
92  }
93  }
94 }
constexpr amrex::Real one
Definition: ERF_Constants.H:9

Referenced by ERF::apply_gaussian_smoothing_to_perturbations().

Here is the caller graph for this function:

◆ ReadCustomDataFile()

void ReadCustomDataFile ( const std::string &  filename_custom,
int &  nx,
int &  ny,
int &  nz,
int &  ng,
int &  ncomp,
std::array< Real, 3 > &  problo_ext,
std::array< Real, 3 > &  probhi_ext,
Vector< Real > &  data_rho,
Vector< Real > &  data_theta,
Vector< Real > &  data_xvel,
Vector< Real > &  data_yvel,
Vector< Real > &  data_zvel,
Vector< Real > &  data_qv,
Vector< Real > &  data_qc,
Vector< Real > &  data_qrain 
)

Read binary custom ensemble background data into host vectors.

Parameters
filename_customPath to the custom binary data file
nxNumber of cells in the x-direction read from the file
nyNumber of cells in the y-direction read from the file
nzNumber of cells in the z-direction read from the file
ngNumber of ghost cells read from the file
ncompNumber of stored components read from the file
problo_extPhysical lower bounds read from the file
probhi_extPhysical upper bounds read from the file
data_rhoDensity values read from the file
data_thetaPotential temperature values read from the file
data_xvelx-velocity values read from the file
data_yvely-velocity values read from the file
data_zvelz-velocity values read from the file
data_qvWater vapor values read from the file
data_qcCloud water values read from the file
data_qrainRain water values read from the file
274 {
275  std::ifstream ifs(filename_custom, std::ios::binary);
276  if (!ifs.is_open()) {
277  Abort("Failed to open file " + filename_custom + " for reading");
278  }
279 
280  // ----------------------------
281  // Read header
282  // ----------------------------
283  ifs.read(reinterpret_cast<char*>(&nx), sizeof(int));
284  ifs.read(reinterpret_cast<char*>(&ny), sizeof(int));
285  ifs.read(reinterpret_cast<char*>(&nz), sizeof(int));
286 
287  ifs.read(reinterpret_cast<char*>(&ng), sizeof(int));
288  ifs.read(reinterpret_cast<char*>(&ncomp), sizeof(int));
289 
290  ifs.read(reinterpret_cast<char*>(&problo_ext[0]), sizeof(Real));
291  ifs.read(reinterpret_cast<char*>(&problo_ext[1]), sizeof(Real));
292  ifs.read(reinterpret_cast<char*>(&problo_ext[2]), sizeof(Real));
293 
294  ifs.read(reinterpret_cast<char*>(&probhi_ext[0]), sizeof(Real));
295  ifs.read(reinterpret_cast<char*>(&probhi_ext[1]), sizeof(Real));
296  ifs.read(reinterpret_cast<char*>(&probhi_ext[2]), sizeof(Real));
297 
298  const std::size_t ncell = static_cast<std::size_t>(nx) * ny * nz;
299 
300  // ----------------------------
301  // Allocate storage
302  // ----------------------------
303  data_rho.resize(ncell);
304  data_theta.resize(ncell);
305  data_xvel.resize(ncell);
306  data_yvel.resize(ncell);
307  data_zvel.resize(ncell);
308  data_qv.resize(ncell);
309  data_qc.resize(ncell);
310  data_qrain.resize(ncell);
311 
312  // ----------------------------
313  // Read data
314  // ----------------------------
315  std::size_t idx = 0;
316 
317  for (int k = 0; k < nz; ++k)
318  {
319  for (int j = 0; j < ny; ++j)
320  {
321  for (int i = 0; i < nx; ++i)
322  {
323  // Skip coordinates
324  Real x, y, z;
325  ifs.read(reinterpret_cast<char*>(&x), sizeof(Real));
326  ifs.read(reinterpret_cast<char*>(&y), sizeof(Real));
327  ifs.read(reinterpret_cast<char*>(&z), sizeof(Real));
328 
329  // Read components (fixed order)
330  ifs.read(reinterpret_cast<char*>(&data_rho[idx]), sizeof(Real));
331  ifs.read(reinterpret_cast<char*>(&data_theta[idx]), sizeof(Real));
332  ifs.read(reinterpret_cast<char*>(&data_xvel[idx]), sizeof(Real));
333  ifs.read(reinterpret_cast<char*>(&data_yvel[idx]), sizeof(Real));
334  ifs.read(reinterpret_cast<char*>(&data_zvel[idx]), sizeof(Real));
335  ifs.read(reinterpret_cast<char*>(&data_qv[idx]), sizeof(Real));
336  ifs.read(reinterpret_cast<char*>(&data_qc[idx]), sizeof(Real));
337  ifs.read(reinterpret_cast<char*>(&data_qrain[idx]), sizeof(Real));
338 
339  /*if(ParallelDescriptor::IOProcessor()) {
340  std::cout << "Values are " << data_rho[idx] << " " << data_theta[idx] << " "
341  << data_xvel[idx] << " " << data_yvel[idx] << " "
342  << data_zvel[idx] << " " << data_qv[idx] << " "
343  << data_qc[idx] << " " << data_qrain[idx] << std::endl;
344  }*/
345  ++idx;
346  }
347  }
348  }
349 
350  ifs.close();
351 }
@ ng
Definition: ERF_Morrison.H:49

Referenced by ERF::create_background_state_for_ensemble().

Here is the call graph for this function:
Here is the caller graph for this function: