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 ApplyNeumannBCs (const Geometry &geom, MultiFab &mf_cc)
 
void NormalizeMultiFabRMS_PerComponent (MultiFab &mf_cc_pert)
 
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)
 

Variables

Vector< Real > perturb_scale
 

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
701 {
702  const int ncomp = mf_cc_fine.nComp();
703 
704  // Optional safety check (recommended)
705  AMREX_ALWAYS_ASSERT(mf_cc_pert.nComp() == ncomp);
706 
707  // Create a GPU-accessible array and copy the host vector into it
708  GpuArray<Real, 8> scale_gpu; // Use the maximum possible ncomp, e.g., 8
709  for (int n = 0; n < ncomp; ++n) {
710  scale_gpu[n] = perturb_scale[n];
711  }
712 
713  for (MFIter mfi(mf_cc_fine, TilingIfNotGPU()); mfi.isValid(); ++mfi)
714  {
715  const Box& bx = mfi.tilebox();
716 
717  auto const& bg = mf_cc_fine.array(mfi);
718  auto const& pert = mf_cc_pert.const_array(mfi);
719 
720  amrex::ParallelFor(bx, ncomp,
721  [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
722  {
723  Real ens_amp = ens_pert_amplitude*scale_gpu[n]*std::abs(bg(i,j,k,n));
724  bg(i,j,k,n) += ens_amp*pert(i,j,k,n);
725  });
726  }
727 }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
Vector< Real > perturb_scale
Definition: ERF_InitForEnsemble.cpp:16
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
226 {
227 
228  // -------------------------------------------------
229  // 2. Fill interior + periodic ghost cells
230  // -------------------------------------------------
231  mf_cc.FillBoundary(geom.periodicity());
232  // -------------------------------------------------
233  // 3. Apply FOExtrap (Neumann) at domain boundaries
234  // -------------------------------------------------
235  const Box& domain = geom.Domain();
236 
237  const bool periodic_x = geom.isPeriodic(0);
238  const bool periodic_y = geom.isPeriodic(1);
239  const bool periodic_z = geom.isPeriodic(2);
240 
241  for (MFIter mfi(mf_cc, TilingIfNotGPU()); mfi.isValid(); ++mfi)
242  {
243  const Box& gbx = mfi.growntilebox(); // includes ghost cells
244  const Box& vbx = mfi.validbox();
245 
246  auto const& arr = mf_cc.array(mfi);
247  int ncomp = mf_cc.nComp();
248 
249  ParallelFor(gbx, ncomp,
250  [=] AMREX_GPU_DEVICE (int i, int j, int k, int n)
251  {
252  if (vbx.contains(i,j,k)) return;
253 
254  int ii = i;
255  int jj = j;
256  int kk = k;
257 
258  if (!periodic_x) {
259  ii = amrex::max(domain.smallEnd(0),
260  amrex::min(i, domain.bigEnd(0)));
261  }
262 
263  if (!periodic_y) {
264  jj = amrex::max(domain.smallEnd(1),
265  amrex::min(j, domain.bigEnd(1)));
266  }
267 
268  if (!periodic_z) {
269  kk = amrex::max(domain.smallEnd(2),
270  amrex::min(k, domain.bigEnd(2)));
271  }
272 
273  arr(i,j,k,n) = arr(ii,jj,kk,n);
274  });
275  }
276 }
if(KE_decay_height > 0 &&state_pert.nComp() > RhoKE_comp)
Definition: ERF_InitCustomPert_ABL.H:74

Referenced by ERF::apply_gaussian_smoothing_to_perturbations(), and 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 
)

◆ 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
431 {
432  int i1 = amrex::min(i+1, nx-1);
433  int j1 = amrex::min(j+1, ny-1);
434  int k1 = amrex::min(k+1, nz-1);
435 
436  Real c000 = f[idx(i ,j ,k ,nx,ny)];
437  Real c100 = f[idx(i1,j ,k ,nx,ny)];
438  Real c010 = f[idx(i ,j1,k ,nx,ny)];
439  Real c110 = f[idx(i1,j1,k ,nx,ny)];
440  Real c001 = f[idx(i ,j ,k1,nx,ny)];
441  Real c101 = f[idx(i1,j ,k1,nx,ny)];
442  Real c011 = f[idx(i ,j1,k1,nx,ny)];
443  Real c111 = f[idx(i1,j1,k1,nx,ny)];
444 
445  Real c00 = c000*(1-tx) + c100*tx;
446  Real c10 = c010*(1-tx) + c110*tx;
447  Real c01 = c001*(1-tx) + c101*tx;
448  Real c11 = c011*(1-tx) + c111*tx;
449 
450  Real c0 = c00*(1-ty) + c10*ty;
451  Real c1 = c01*(1-ty) + c11*ty;
452 
453  return c0*(1-tz) + c1*tz;
454 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx(int i, int j, int k, int nx, int ny)
Definition: ERF_InitForEnsemble.cpp:404
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
490 {
491  // coarse spacing
492  Real dx_c[3];
493  dx_c[0] = (probhi[0] - problo[0]) / nx;
494  dx_c[1] = (probhi[1] - problo[1]) / ny;
495  dx_c[2] = (probhi[2] - problo[2]) / nz;
496 
497  const auto problo_f = geom_fine.ProbLoArray();
498  const auto dx_f = geom_fine.CellSizeArray();
499 
500  // Step 1: declare device vectors with correct size
501  amrex::Gpu::DeviceVector<Real> d_rho(data_rho.size());
502  amrex::Gpu::DeviceVector<Real> d_theta(data_theta.size());
503  amrex::Gpu::DeviceVector<Real> d_xvel(data_xvel.size());
504  amrex::Gpu::DeviceVector<Real> d_yvel(data_yvel.size());
505  amrex::Gpu::DeviceVector<Real> d_zvel(data_zvel.size());
506  amrex::Gpu::DeviceVector<Real> d_qv(data_qv.size());
507  amrex::Gpu::DeviceVector<Real> d_qc(data_qc.size());
508  amrex::Gpu::DeviceVector<Real> d_qrain(data_qrain.size());
509 
510  // Step 2: copy data from host to device
511  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
512  data_rho.begin(), data_rho.end(),
513  d_rho.begin());
514 
515  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
516  data_theta.begin(), data_theta.end(),
517  d_theta.begin());
518 
519  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
520  data_xvel.begin(), data_xvel.end(),
521  d_xvel.begin());
522 
523  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
524  data_yvel.begin(), data_yvel.end(),
525  d_yvel.begin());
526 
527  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
528  data_zvel.begin(), data_zvel.end(),
529  d_zvel.begin());
530 
531  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
532  data_qv.begin(), data_qv.end(),
533  d_qv.begin());
534 
535  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
536  data_qc.begin(), data_qc.end(),
537  d_qc.begin());
538 
539  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice,
540  data_qrain.begin(), data_qrain.end(),
541  d_qrain.begin());
542 
543  const Real* rho_ptr = d_rho.data();
544  const Real* theta_ptr = d_theta.data();
545  const Real* xvel_ptr = d_xvel.data();
546  const Real* yvel_ptr = d_yvel.data();
547  const Real* zvel_ptr = d_zvel.data();
548  const Real* qv_ptr = d_qv.data();
549  const Real* qc_ptr = d_qc.data();
550  const Real* qrain_ptr = d_qrain.data();
551 
552  // -------------------------------
553  // GPU kernel over MultiFab
554  // -------------------------------
555  for (MFIter mfi(mf_fine); mfi.isValid(); ++mfi)
556  {
557  const Box& bx = mfi.validbox();
558  auto arr = mf_fine.array(mfi);
559 
561  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
562  {
563  // physical location (fine cell center)
564  Real x = problo_f[0] + (i + myhalf) * dx_f[0];
565  Real y = problo_f[1] + (j + myhalf) * dx_f[1];
566  Real z = problo_f[2] + (k + myhalf) * dx_f[2];
567 
568  // map to coarse index space (cell centers)
569  Real rx = (x - problo[0]) / dx_c[0] - myhalf;
570  Real ry = (y - problo[1]) / dx_c[1] - myhalf;
571  Real rz = (z - problo[2]) / dx_c[2] - myhalf;
572 
573  // clamp coordinates into valid coarse cell-center range
574  rx = amrex::max(Real(0), amrex::min(rx, Real(nx-1)));
575  ry = amrex::max(Real(0), amrex::min(ry, Real(ny-1)));
576  rz = amrex::max(Real(0), amrex::min(rz, Real(nz-1)));
577 
578  int ic = static_cast<int>(amrex::Math::floor(rx));
579  int jc = static_cast<int>(amrex::Math::floor(ry));
580  int kc = static_cast<int>(amrex::Math::floor(rz));
581 
582  Real tx = rx - ic;
583  Real ty = ry - jc;
584  Real tz = rz - kc;
585 
586  // optional: avoid degenerate interpolation at upper edge
587  if (ic == nx-1) tx = Real(0);
588  if (jc == ny-1) ty = Real(0);
589  if (kc == nz-1) tz = Real(0);
590 
591  //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);
592 
593  // interpolate each component using device trilinear
594  arr(i,j,k,0) = interp_trilinear(rho_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
595  arr(i,j,k,1) = interp_trilinear(theta_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
596  arr(i,j,k,2) = interp_trilinear(xvel_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
597  arr(i,j,k,3) = interp_trilinear(yvel_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
598  arr(i,j,k,4) = interp_trilinear(zvel_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
599  arr(i,j,k,5) = interp_trilinear(qv_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
600  arr(i,j,k,6) = interp_trilinear(qc_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
601  arr(i,j,k,7) = interp_trilinear(qrain_ptr, ic,jc,kc, tx,ty,tz, nx,ny,nz);
602 
603  /*printf("Values are %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g %0.15g\n",
604  arr(i,j,k,0), arr(i,j,k,1), arr(i,j,k,2), arr(i,j,k,3),
605  arr(i,j,k,4), arr(i,j,k,5), arr(i,j,k,6), arr(i,j,k,7));*/
606  });
607  }
608 }
auto probhi
Definition: ERF_InitCustomPertVels_ABL.H:37
auto problo
Definition: ERF_InitCustomPertVels_ABL.H:36
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:426
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41

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
626 {
627 
628  for (MFIter mfi(cons_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
629  {
630  const Box& bx = mfi.tilebox();
631 
632  auto const& mf_cc_fine_arr = mf_cc_fine.const_array(mfi);
633  auto const& cons_pert_arr = cons_pert.array(mfi);
634 
635  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
636  {
637  Real tmp_rho = mf_cc_fine_arr(i,j,k,0);
638  Real tmp_theta = mf_cc_fine_arr(i,j,k,1);
639  Real tmp_qv = mf_cc_fine_arr(i,j,k,5);
640  Real tmp_qc = mf_cc_fine_arr(i,j,k,6);
641  Real tmp_qrain = mf_cc_fine_arr(i,j,k,7);
642  cons_pert_arr(i,j,k,Rho_comp) = tmp_rho;
643  cons_pert_arr(i,j,k,RhoTheta_comp) = tmp_rho*tmp_theta;
644  if (n_qstate_moist > 0) cons_pert_arr(i,j,k,RhoQ1_comp) = std::max(tmp_rho*tmp_qv,0.0_rt);
645  if (n_qstate_moist > 1) cons_pert_arr(i,j,k,RhoQ2_comp) = std::max(tmp_rho*tmp_qc,0.0_rt);
646  if (n_qstate_moist > 2) cons_pert_arr(i,j,k,RhoQ3_comp) = std::max(tmp_rho*tmp_qrain,0.0_rt);
647  });
648  }
649 
650  // --- X-faces (component 2) ---
651  for (MFIter mfi(xvel_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
652  {
653  const Box& bx = mfi.tilebox();
654  auto const& uface = xvel_pert.array(mfi);
655  auto const& cc = mf_cc_fine.const_array(mfi);
656 
657  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
658  {
659  uface(i,j,k) = myhalf * (cc(i-1,j,k,2) + cc(i,j,k,2));
660  });
661  }
662 
663  // --- Y-faces (component 3) ---
664  for (MFIter mfi(yvel_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
665  {
666  const Box& bx = mfi.tilebox();
667  auto const& vface = yvel_pert.array(mfi);
668  auto const& cc = mf_cc_fine.const_array(mfi);
669 
670  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
671  {
672  vface(i,j,k) = myhalf * (cc(i,j-1,k,3) + cc(i,j,k,3));
673  });
674  }
675 
676  // --- Z-faces (component 4) ---
677  for (MFIter mfi(zvel_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
678  {
679  const Box& bx = mfi.tilebox();
680  auto const& wface = zvel_pert.array(mfi);
681  auto const& cc = mf_cc_fine.const_array(mfi);
682 
683  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
684  {
685  wface(i,j,k) = myhalf * (cc(i,j,k-1,4) + cc(i,j,k,4));
686  });
687  }
688 }
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:67
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:68
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66

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
67 {
68  const int ncomp = mf_cc_pert.nComp();
69 
70  for (int n = 0; n < ncomp; ++n)
71  {
72  // 1. Set up AMReX reduction (sum of squares + count)
73  ReduceOps<ReduceOpSum, ReduceOpSum> reduce_op;
74  ReduceData<Real, Long> reduce_data(reduce_op);
75  using ReduceTuple = typename decltype(reduce_data)::Type;
76 
77  // 2. Loop over tiles and accumulate
78  for (MFIter mfi(mf_cc_pert, TilingIfNotGPU()); mfi.isValid(); ++mfi)
79  {
80  const Box& bx = mfi.tilebox();
81  auto const& arr = mf_cc_pert.const_array(mfi);
82 
83  reduce_op.eval(bx, reduce_data,
84  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept -> ReduceTuple
85  {
86  Real v = arr(i, j, k, n);
87  return { v * v, 1L };
88  });
89  }
90 
91  // 3. Retrieve results (includes implicit GPU sync + host copy)
92  auto rv = reduce_data.value(reduce_op);
93  Real h_sumsq = amrex::get<0>(rv);
94  Long h_count = amrex::get<1>(rv);
95 
96  // 4. Sum across MPI ranks
97  ParallelDescriptor::ReduceRealSum(h_sumsq);
98  ParallelDescriptor::ReduceLongSum(h_count);
99 
100  // 5. Compute RMS and normalize
101  if (h_count > 0)
102  {
103  Real rms = std::sqrt(h_sumsq / static_cast<Real>(h_count));
104  if (rms > zero) {
105  mf_cc_pert.mult(one / rms, n, 1);
106  }
107  }
108  }
109 }
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36

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
313 {
314  std::ifstream ifs(filename_custom, std::ios::binary);
315  if (!ifs.is_open()) {
316  Abort("Failed to open file " + filename_custom + " for reading");
317  }
318 
319  // ----------------------------
320  // Read header
321  // ----------------------------
322  ifs.read(reinterpret_cast<char*>(&nx), sizeof(int));
323  ifs.read(reinterpret_cast<char*>(&ny), sizeof(int));
324  ifs.read(reinterpret_cast<char*>(&nz), sizeof(int));
325 
326  ifs.read(reinterpret_cast<char*>(&ng), sizeof(int));
327  ifs.read(reinterpret_cast<char*>(&ncomp), sizeof(int));
328 
329  ifs.read(reinterpret_cast<char*>(&problo_ext[0]), sizeof(Real));
330  ifs.read(reinterpret_cast<char*>(&problo_ext[1]), sizeof(Real));
331  ifs.read(reinterpret_cast<char*>(&problo_ext[2]), sizeof(Real));
332 
333  ifs.read(reinterpret_cast<char*>(&probhi_ext[0]), sizeof(Real));
334  ifs.read(reinterpret_cast<char*>(&probhi_ext[1]), sizeof(Real));
335  ifs.read(reinterpret_cast<char*>(&probhi_ext[2]), sizeof(Real));
336 
337  const std::size_t ncell = static_cast<std::size_t>(nx) * ny * nz;
338 
339  // ----------------------------
340  // Allocate storage
341  // ----------------------------
342  data_rho.resize(ncell);
343  data_theta.resize(ncell);
344  data_xvel.resize(ncell);
345  data_yvel.resize(ncell);
346  data_zvel.resize(ncell);
347  data_qv.resize(ncell);
348  data_qc.resize(ncell);
349  data_qrain.resize(ncell);
350 
351  // ----------------------------
352  // Read data
353  // ----------------------------
354  std::size_t idx = 0;
355 
356  for (int k = 0; k < nz; ++k)
357  {
358  for (int j = 0; j < ny; ++j)
359  {
360  for (int i = 0; i < nx; ++i)
361  {
362  // Skip coordinates
363  Real x, y, z;
364  ifs.read(reinterpret_cast<char*>(&x), sizeof(Real));
365  ifs.read(reinterpret_cast<char*>(&y), sizeof(Real));
366  ifs.read(reinterpret_cast<char*>(&z), sizeof(Real));
367 
368  // Read components (fixed order)
369  ifs.read(reinterpret_cast<char*>(&data_rho[idx]), sizeof(Real));
370  ifs.read(reinterpret_cast<char*>(&data_theta[idx]), sizeof(Real));
371  ifs.read(reinterpret_cast<char*>(&data_xvel[idx]), sizeof(Real));
372  ifs.read(reinterpret_cast<char*>(&data_yvel[idx]), sizeof(Real));
373  ifs.read(reinterpret_cast<char*>(&data_zvel[idx]), sizeof(Real));
374  ifs.read(reinterpret_cast<char*>(&data_qv[idx]), sizeof(Real));
375  ifs.read(reinterpret_cast<char*>(&data_qc[idx]), sizeof(Real));
376  ifs.read(reinterpret_cast<char*>(&data_qrain[idx]), sizeof(Real));
377 
378  /*if(ParallelDescriptor::IOProcessor()) {
379  std::cout << "Values are " << data_rho[idx] << " " << data_theta[idx] << " "
380  << data_xvel[idx] << " " << data_yvel[idx] << " "
381  << data_zvel[idx] << " " << data_qv[idx] << " "
382  << data_qc[idx] << " " << data_qrain[idx] << std::endl;
383  }*/
384  ++idx;
385  }
386  }
387  }
388 
389  ifs.close();
390 }
@ ng
Definition: ERF_Morrison.H:51

Referenced by ERF::create_background_state_for_ensemble().

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

Variable Documentation

◆ perturb_scale

Vector<Real> perturb_scale
Initial value:
=
{
0.01,
1.0,
1.0,
1.0,
0.5,
1.0e-6,
1.0e-6,
1.0e-6
}

Referenced by AddPertToBckgnd().