ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
PlaneSampler Struct Reference

#include <ERF_SampleData.H>

Collaboration diagram for PlaneSampler:

Public Member Functions

 PlaneSampler ()
 
amrex::Box getIndexBox (const amrex::RealBox &real_box, const amrex::Geometry &geom)
 
void get_sample_data (amrex::Vector< amrex::Geometry > &geom, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_new)
 
void write_sample_data (amrex::Vector< amrex::Real > &time, amrex::Vector< int > &level_steps, amrex::Vector< amrex::IntVect > &ref_ratio, amrex::Vector< amrex::Geometry > &geom)
 

Public Attributes

amrex::Vector< int > m_dir
 
amrex::Vector< int > m_lev
 
amrex::Vector< amrex::RealBox > m_bnd_rbx
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_ps_mf
 
amrex::Vector< std::string > m_name
 
amrex::Vector< std::string > m_varnames {"magvel","theta"}
 

Constructor & Destructor Documentation

◆ PlaneSampler()

PlaneSampler::PlaneSampler ( )
inline
572  {
573  amrex::ParmParse pp("erf");
574 
575  // Count number of lo and hi points define the plane
576  int n_plane_lo = pp.countval("sample_plane_lo") / AMREX_SPACEDIM;
577  int n_plane_hi = pp.countval("sample_plane_hi") / AMREX_SPACEDIM;
578  int n_plane_dir = pp.countval("sample_plane_dir");
579  AMREX_ALWAYS_ASSERT( (n_plane_lo==n_plane_hi ) &&
580  (n_plane_lo==n_plane_dir) );
581 
582  // Parse the data
583  if (n_plane_lo > 0) {
584  // Parse lo
585  amrex::Vector<amrex::Real> r_lo; r_lo.resize(n_plane_lo*AMREX_SPACEDIM);
586  amrex::Vector<amrex::Vector<amrex::Real>> rv_lo;
587  pp.queryarr("sample_plane_lo",r_lo,0,n_plane_lo*AMREX_SPACEDIM);
588  for (int i(0); i < n_plane_lo; i++) {
589  amrex::Vector<amrex::Real> rv = {r_lo[AMREX_SPACEDIM*i+0],
590  r_lo[AMREX_SPACEDIM*i+1],
591  r_lo[AMREX_SPACEDIM*i+2]};
592  rv_lo.push_back(rv);
593  }
594 
595  // Parse hi
596  amrex::Vector<amrex::Real> r_hi; r_hi.resize(n_plane_hi*AMREX_SPACEDIM);
597  amrex::Vector<amrex::Vector<amrex::Real>> rv_hi;
598  pp.queryarr("sample_plane_hi",r_hi,0,n_plane_hi*AMREX_SPACEDIM);
599  for (int i(0); i < n_plane_hi; i++) {
600  amrex::Vector<amrex::Real> rv = {r_hi[AMREX_SPACEDIM*i+0],
601  r_hi[AMREX_SPACEDIM*i+1],
602  r_hi[AMREX_SPACEDIM*i+2]};
603  rv_hi.push_back(rv);
604  }
605 
606  // Construct vector of bounding real boxes
607  m_bnd_rbx.resize(n_plane_lo);
608  for (int i(0); i < n_plane_hi; i++){
609  amrex::RealBox rbx(rv_lo[i].data(),rv_hi[i].data());
610  m_bnd_rbx[i] = rbx;
611  }
612 
613  // Parse directionality
614  m_dir.resize(n_plane_dir);
615  pp.queryarr("sample_plane_dir",m_dir,0,n_plane_dir);
616 
617  // Parse names
618  std::string name_base = "plt_plane_";
619  m_name.resize(n_plane_lo);
620  int n_names = pp.countval("sample_plane_name");
621  if (n_names > 0) {
622  AMREX_ALWAYS_ASSERT( n_names==n_plane_lo );
623  pp.queryarr("sample_plane_name",m_name,0,n_names);
624  } else {
625  for (int iplane(0); iplane<n_plane_lo; ++iplane) {
626  m_name[iplane] = amrex::Concatenate(name_base, iplane , 5);
627  }
628  }
629 
630  // Allocate space for level indicator
631  m_lev.resize(n_plane_dir,0);
632 
633  // Allocate space for MF pointers
634  m_ps_mf.resize(n_plane_lo);
635 
636  // Get requested vars
637  if (pp.countval("plane_sampling_vars") > 0) {
638  m_varnames.clear();
639  amrex::Vector<std::string> requested_vars;
640  pp.queryarr("plane_sampling_vars",requested_vars);
641  amrex::Print() << "Selected plane sampling vars :";
642  if (containerHasElement(requested_vars, "density")) {
643  m_varnames.push_back("density");
644  amrex::Print() << " " << "density";
645  }
646  if (containerHasElement(requested_vars, "x_velocity")) {
647  m_varnames.push_back("x_velocity");
648  amrex::Print() << " " << "x_velocity";
649  }
650  if (containerHasElement(requested_vars, "y_velocity")) {
651  m_varnames.push_back("y_velocity");
652  amrex::Print() << " " << "y_velocity";
653  }
654  if (containerHasElement(requested_vars, "z_velocity")) {
655  m_varnames.push_back("z_velocity");
656  amrex::Print() << " " << "z_velocity";
657  }
658  if (containerHasElement(requested_vars, "magvel")) {
659  m_varnames.push_back("magvel");
660  amrex::Print() << " " << "magvel";
661  }
662  if (containerHasElement(requested_vars, "theta")) {
663  m_varnames.push_back("theta");
664  amrex::Print() << " " << "theta";
665  }
666  if (containerHasElement(requested_vars, "qv")) {
667  m_varnames.push_back("qv");
668  amrex::Print() << " " << "qv";
669  }
670  if (containerHasElement(requested_vars, "qc")) {
671  m_varnames.push_back("qc");
672  amrex::Print() << " " << "qc";
673  }
674  if (containerHasElement(requested_vars, "pressure")) {
675  m_varnames.push_back("pressure");
676  amrex::Print() << " " << "pressure";
677  }
678  amrex::Print() << std::endl;
679  }
680  }
681  }
bool containerHasElement(const V &iterable, const T &query)
Definition: ERF_Container.H:5
ParmParse pp("prob")
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
amrex::Vector< int > m_dir
Definition: ERF_SampleData.H:924
amrex::Vector< int > m_lev
Definition: ERF_SampleData.H:925
amrex::Vector< std::string > m_name
Definition: ERF_SampleData.H:928
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_ps_mf
Definition: ERF_SampleData.H:927
amrex::Vector< amrex::RealBox > m_bnd_rbx
Definition: ERF_SampleData.H:926
amrex::Vector< std::string > m_varnames
Definition: ERF_SampleData.H:930
Here is the call graph for this function:

Member Function Documentation

◆ get_sample_data()

void PlaneSampler::get_sample_data ( amrex::Vector< amrex::Geometry > &  geom,
amrex::Vector< amrex::Vector< amrex::MultiFab >> &  vars_new 
)
inline
703  {
704  int nlev = static_cast<int>(vars_new.size());
705  int nplane = static_cast<int>(m_bnd_rbx.size());
706  int ncomp = static_cast<int>(m_varnames.size());
707  bool interpolate = true;
708 
709  int qv_comp = -1;
710 
711  // Loop over each plane
712  for (int iplane(0); iplane<nplane; ++iplane) {
713  int dir = m_dir[iplane];
714  amrex::RealBox bnd_rbx = m_bnd_rbx[iplane];
715  amrex::Real point = bnd_rbx.lo(dir);
716 
717  // Search each level to get the finest data possible
718  for (int ilev(nlev-1); ilev>=0; --ilev) {
719 
720  // Construct CC velocities
721  amrex::MultiFab mf_cc_vel;
722  auto ba = vars_new[ilev][Vars::cons].boxArray();
723  auto dm = vars_new[ilev][Vars::cons].DistributionMap();
724  mf_cc_vel.define(ba, dm, AMREX_SPACEDIM, amrex::IntVect(1,1,1));
725  average_face_to_cellcenter(mf_cc_vel,0,
726  amrex::Array<const amrex::MultiFab*,3>{&vars_new[ilev][Vars::xvel],
727  &vars_new[ilev][Vars::yvel],
728  &vars_new[ilev][Vars::zvel]});
729 
730  // Construct MultiFab holding requested variables
731  amrex::MultiFab mf_cc_data;
732  mf_cc_data.define(ba, dm, ncomp, 1);
733 
734  int mf_comp = 0;
735 
736  if (containerHasElement(m_varnames, "density")) {
737  amrex::MultiFab::Copy(mf_cc_data, vars_new[ilev][Vars::cons], Rho_comp, mf_comp, 1, 0);
738  mf_comp += 1;
739  }
740 
741  if (containerHasElement(m_varnames, "x_velocity")) {
742  amrex::MultiFab::Copy(mf_cc_data, mf_cc_vel, 0, mf_comp, 1, 0);
743  mf_comp += 1;
744  }
745  if (containerHasElement(m_varnames, "y_velocity")) {
746  amrex::MultiFab::Copy(mf_cc_data, mf_cc_vel, 1, mf_comp, 1, 0);
747  mf_comp += 1;
748  }
749  if (containerHasElement(m_varnames, "z_velocity")) {
750  amrex::MultiFab::Copy(mf_cc_data, mf_cc_vel, 2, mf_comp, 1, 0);
751  mf_comp += 1;
752  }
753 
754  if (containerHasElement(m_varnames, "magvel")) {
755 #ifdef _OPENMP
756 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
757 #endif
758  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
759  const amrex::Box& tbx = mfi.tilebox();
760  auto const& dfab = mf_cc_data.array(mfi);
761  auto const& vfab = mf_cc_vel.array(mfi);
762 
763  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
764  {
765  dfab(i,j,k,mf_comp) = std::sqrt(vfab(i,j,k,0)*vfab(i,j,k,0)
766  + vfab(i,j,k,1)*vfab(i,j,k,1)
767  + vfab(i,j,k,2)*vfab(i,j,k,2));
768  });
769  }
770  mf_comp += 1;
771  }
772 
773  if (containerHasElement(m_varnames, "theta")) {
774 #ifdef _OPENMP
775 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
776 #endif
777  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
778  const amrex::Box& tbx = mfi.tilebox();
779  auto const& dfab = mf_cc_data.array(mfi);
780  auto const& cfab = vars_new[ilev][Vars::cons].array(mfi);
781 
782  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
783  {
784  dfab(i,j,k,mf_comp) = cfab(i,j,k,RhoTheta_comp) / cfab(i,j,k,Rho_comp);
785  });
786  }
787  mf_comp += 1;
788  }
789 
790  if (containerHasElement(m_varnames, "qv")) {
791  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(vars_new[ilev][Vars::cons].nComp() > RhoQ1_comp,
792  "qv sampling requested but moisture components not present in state");
793  if (qv_comp >= 0) AMREX_ALWAYS_ASSERT(qv_comp == mf_comp);
794  qv_comp = mf_comp;
795 #ifdef _OPENMP
796 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
797 #endif
798  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
799  const amrex::Box& tbx = mfi.tilebox();
800  auto const& dfab = mf_cc_data.array(mfi);
801  auto const& cfab = vars_new[ilev][Vars::cons].array(mfi);
802 
803  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
804  {
805  dfab(i,j,k,mf_comp) = cfab(i,j,k,RhoQ1_comp) / cfab(i,j,k,Rho_comp);
806  });
807  }
808  mf_comp += 1;
809  }
810  if (containerHasElement(m_varnames, "qc")) {
811  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(vars_new[ilev][Vars::cons].nComp() > RhoQ2_comp,
812  "qc sampling requested but moisture components not present in state");
813 #ifdef _OPENMP
814 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
815 #endif
816  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
817  const amrex::Box& tbx = mfi.tilebox();
818  auto const& dfab = mf_cc_data.array(mfi);
819  auto const& cfab = vars_new[ilev][Vars::cons].array(mfi);
820 
821  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
822  {
823  dfab(i,j,k,mf_comp) = cfab(i,j,k,RhoQ2_comp) / cfab(i,j,k,Rho_comp);
824  });
825  }
826  mf_comp += 1;
827  }
828 
829  if (containerHasElement(m_varnames, "pressure")) {
830  if (vars_new[ilev][Vars::cons].nComp() > RhoQ1_comp) {
831  // moist pressure: use qv from dfab if already sampled, else compute inline
832 #ifdef _OPENMP
833 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
834 #endif
835  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
836  const amrex::Box& tbx = mfi.tilebox();
837  auto const& dfab = mf_cc_data.array(mfi);
838  auto const& cfab = vars_new[ilev][Vars::cons].array(mfi);
839 
840  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
841  {
842  amrex::Real qv_val = (qv_comp >= 0) ? dfab(i,j,k,qv_comp)
843  : cfab(i,j,k,RhoQ1_comp) / cfab(i,j,k,Rho_comp);
844  dfab(i,j,k,mf_comp) = getPgivenRTh(cfab(i,j,k,RhoTheta_comp), qv_val);
845  });
846  }
847  } else {
848  // dry pressure
849 #ifdef _OPENMP
850 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
851 #endif
852  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
853  const amrex::Box& tbx = mfi.tilebox();
854  auto const& dfab = mf_cc_data.array(mfi);
855  auto const& cfab = vars_new[ilev][Vars::cons].array(mfi);
856 
857  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
858  {
859  dfab(i,j,k,mf_comp) = getPgivenRTh(cfab(i,j,k,RhoTheta_comp));
860  });
861  }
862  }
863  mf_comp += 1;
864  }
865 
866  m_lev[iplane] = ilev;
867  m_ps_mf[iplane] = get_slice_data(dir, point, mf_cc_data, geom[ilev],
868  0, ncomp, interpolate, bnd_rbx);
869 
870  // We can stop if we got the entire plane
871  auto min_bnd_bx = m_ps_mf[iplane]->boxArray().minimalBox();
872  amrex::Box bnd_bx = getIndexBox(bnd_rbx, geom[ilev]);
873  if (bnd_bx == min_bnd_bx) { break; }
874 
875  } // ilev
876  }// iplane
877  }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:81
#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 RhoQ1_comp
Definition: ERF_IndexDefines.H:42
ParallelFor(grown_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
@ xvel
Definition: ERF_IndexDefines.H:175
@ cons
Definition: ERF_IndexDefines.H:174
@ zvel
Definition: ERF_IndexDefines.H:177
@ yvel
Definition: ERF_IndexDefines.H:176
amrex::Box getIndexBox(const amrex::RealBox &real_box, const amrex::Geometry &geom)
Definition: ERF_SampleData.H:685
Here is the call graph for this function:

◆ getIndexBox()

amrex::Box PlaneSampler::getIndexBox ( const amrex::RealBox &  real_box,
const amrex::Geometry &  geom 
)
inline
686  {
687  amrex::IntVect slice_lo, slice_hi;
688 
689  AMREX_D_TERM(slice_lo[0]=static_cast<int>(std::floor((real_box.lo(0) - geom.ProbLo(0))/geom.CellSize(0)));,
690  slice_lo[1]=static_cast<int>(std::floor((real_box.lo(1) - geom.ProbLo(1))/geom.CellSize(1)));,
691  slice_lo[2]=static_cast<int>(std::floor((real_box.lo(2) - geom.ProbLo(2))/geom.CellSize(2))););
692 
693  AMREX_D_TERM(slice_hi[0]=static_cast<int>(std::floor((real_box.hi(0) - geom.ProbLo(0))/geom.CellSize(0)));,
694  slice_hi[1]=static_cast<int>(std::floor((real_box.hi(1) - geom.ProbLo(1))/geom.CellSize(1)));,
695  slice_hi[2]=static_cast<int>(std::floor((real_box.hi(2) - geom.ProbLo(2))/geom.CellSize(2))););
696 
697  return amrex::Box(slice_lo, slice_hi) & geom.Domain();
698  }

Referenced by get_sample_data(), and write_sample_data().

Here is the caller graph for this function:

◆ write_sample_data()

void PlaneSampler::write_sample_data ( amrex::Vector< amrex::Real > &  time,
amrex::Vector< int > &  level_steps,
amrex::Vector< amrex::IntVect > &  ref_ratio,
amrex::Vector< amrex::Geometry > &  geom 
)
inline
884  {
885  int nplane = m_ps_mf.size();
886  for (int iplane(0); iplane<nplane; ++iplane) {
887  // Data members that can be used as-is
888  int dir = m_dir[iplane];
889  int lev = m_lev[iplane];
890  amrex::Real m_time = time[lev];
891  amrex::Vector<int> m_level_steps = {level_steps[lev]};
892  amrex::Vector<amrex::IntVect> m_ref_ratio = {ref_ratio[lev]};
893 
894  // Create modified geometry object corresponding to the plane
895  amrex::RealBox m_rb = m_bnd_rbx[iplane];
896  amrex::Box m_dom = getIndexBox(m_rb, geom[lev]);
897  amrex::Real point = m_rb.hi(dir);
898  amrex::Vector<int> is_per(AMREX_SPACEDIM,0);
899  for (int d(0); d<AMREX_SPACEDIM; ++d) {
900  if (d==dir) {
901  m_rb.setLo(d,point-myhalf*geom[lev].CellSize(d));
902  m_rb.setHi(d,point+myhalf*geom[lev].CellSize(d));
903  }
904  is_per[d] = geom[lev].isPeriodic(d);
905  }
906  amrex::Vector<amrex::Geometry> m_geom; m_geom.resize(1);
907  m_geom[0].define(m_dom, &m_rb, geom[lev].Coord(), is_per.data());
908 
909  // Create plotfile name
910  std::string name_plane = m_name[iplane];
911  name_plane += "_step_";
912  std::string plotfilename = amrex::Concatenate(name_plane, m_level_steps[0], 5);
913 
914  // Get the data
915  amrex::Vector<const amrex::MultiFab*> mf = {m_ps_mf[iplane].get()};
916 
917  // Write each plane
918  WriteMultiLevelPlotfile(plotfilename, 1, mf,
919  m_varnames, m_geom, m_time,
920  m_level_steps, m_ref_ratio);
921  } // iplane
922  }
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:11
Coord
Definition: ERF_DataStruct.H:92
Here is the call graph for this function:

Member Data Documentation

◆ m_bnd_rbx

amrex::Vector<amrex::RealBox> PlaneSampler::m_bnd_rbx

◆ m_dir

amrex::Vector<int> PlaneSampler::m_dir

◆ m_lev

amrex::Vector<int> PlaneSampler::m_lev

◆ m_name

amrex::Vector<std::string> PlaneSampler::m_name

Referenced by PlaneSampler(), and write_sample_data().

◆ m_ps_mf

amrex::Vector<std::unique_ptr<amrex::MultiFab> > PlaneSampler::m_ps_mf

◆ m_varnames

amrex::Vector<std::string> PlaneSampler::m_varnames {"magvel","theta"}

The documentation for this struct was generated from the following file: