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

#include <ERF_WriteBndryPlanes.H>

Collaboration diagram for WriteBndryPlanes:

Public Member Functions

 WriteBndryPlanes (amrex::Vector< amrex::BoxArray > &grids, amrex::Vector< amrex::Geometry > &geom)
 
void write_planes (int t_step, double time, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_new, bool is_moist)
 

Private Attributes

amrex::Box target_box
 IO output box region. More...
 
amrex::Vector< amrex::Geometry > & m_geom
 Geometry objects for all levels. More...
 
std::string m_filename {""}
 File name for IO. More...
 
std::string m_time_file {""}
 File name for Native time file. More...
 
amrex::Vector< std::string > m_var_names
 Variables for IO. More...
 
amrex::Vector< double > m_in_times
 Timestep and times to be stored in time.dat. More...
 
amrex::Vector< int > m_in_timesteps
 
int m_in_rad = 1
 controls extents on native bndry output More...
 
const int m_out_rad = 1
 
const int m_extent_rad = 0
 

Static Private Attributes

static int bndry_lev = 0
 

Detailed Description

Interface for writing boundary planes

This class performs the necessary file operations to write boundary planes

Constructor & Destructor Documentation

◆ WriteBndryPlanes()

WriteBndryPlanes::WriteBndryPlanes ( amrex::Vector< amrex::BoxArray > &  grids,
amrex::Vector< amrex::Geometry > &  geom 
)
explicit

Constructor for the WriteBndryPlanes class for writing the contents of boundary planes to an output file

Parameters
gridsVector of BoxArrays containing the grids at each level in the AMR
geomVector of Geometry containing the geometry at each level in the AMR
58  : m_geom(geom)
59 {
60  ParmParse pp("erf");
61 
62  // Get the radius inside the domain
63  pp.query("in_rad",m_in_rad);
64 
65  // User-specified region is given in physical coordinates, not index space
66  std::vector<Real> box_lo(3), box_hi(3);
67  pp.getarr("bndry_output_box_lo",box_lo,0,2);
68  pp.getarr("bndry_output_box_hi",box_hi,0,2);
69 
70  // If the target area is contained at a finer level, use the finest data possible.
71  // target_box is expressed in the index space of bndry_lev, so it must only be set
72  // together with bndry_lev; each level's candidate box is kept in a local variable.
73  for (int ilev = 0; ilev < grids.size(); ilev++) {
74 
75  const Real* xLo = m_geom[ilev].ProbLo();
76  auto const dxi = geom[ilev].InvCellSizeArray();
77  const Box& domain = m_geom[ilev].Domain();
78 
79  // We create the smallest box that contains all of the cell centers
80  // in the physical region specified
81  int ilo = static_cast<int>(Math::floor((box_lo[0] - xLo[0]) * dxi[0])+Real(.5));
82  int jlo = static_cast<int>(Math::floor((box_lo[1] - xLo[1]) * dxi[1])+Real(.5));
83  int ihi = static_cast<int>(Math::floor((box_hi[0] - xLo[0]) * dxi[0])+Real(.5))-1;
84  int jhi = static_cast<int>(Math::floor((box_hi[1] - xLo[1]) * dxi[1])+Real(.5))-1;
85 
86  // Map this to index space -- for now we do no interpolation
87  Box box_this_lev(IntVect(ilo,jlo,0),
88  IntVect(ihi,jhi,domain.bigEnd(2)));
89 
90  // Test if the target box at this level fits in the grids at this level
91  Box gbx = box_this_lev; gbx.grow(IntVect(1,1,0));
92 
93  // Ensure that the box is no larger than can fit in the (periodically grown) domain
94  // at level 0
95  if (ilev == 0) {
96  Box per_grown_domain(domain);
97  int growx = (geom[0].isPeriodic(0)) ? 1 : 0;
98  int growy = (geom[0].isPeriodic(1)) ? 1 : 0;
99  per_grown_domain.grow(IntVect(growx,growy,0));
100  /*
101  if (!per_grown_domain.contains(gbx))
102  Error("WriteBndryPlanes: Requested box is too large to fill");
103  */
104 
105  // Default to level 0
106  target_box = box_this_lev;
107  }
108 
109  // Use this level's data only if its grids fully contain the requested region
110  if (grids[ilev].contains(gbx)) {
111  bndry_lev = ilev;
112  target_box = box_this_lev;
113  }
114  }
115 
116  // The folder "m_filename" will contain the time series of data and the time.dat file
117  pp.get("bndry_output_planes_file", m_filename);
118 
119  m_time_file = m_filename + "/time.dat";
120 
121  if (pp.contains("bndry_output_var_names"))
122  {
123  int num_vars = pp.countval("bndry_output_var_names");
124  m_var_names.resize(num_vars);
125  pp.queryarr("bndry_output_var_names",m_var_names,0,num_vars);
126  }
127 }
ParmParse pp("prob")
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Vector< amrex::Geometry > & m_geom
Geometry objects for all levels.
Definition: ERF_WriteBndryPlanes.H:33
int m_in_rad
controls extents on native bndry output
Definition: ERF_WriteBndryPlanes.H:53
static int bndry_lev
Definition: ERF_WriteBndryPlanes.H:50
amrex::Box target_box
IO output box region.
Definition: ERF_WriteBndryPlanes.H:30
amrex::Vector< std::string > m_var_names
Variables for IO.
Definition: ERF_WriteBndryPlanes.H:42
std::string m_time_file
File name for Native time file.
Definition: ERF_WriteBndryPlanes.H:39
std::string m_filename
File name for IO.
Definition: ERF_WriteBndryPlanes.H:36
Here is the call graph for this function:

Member Function Documentation

◆ write_planes()

void WriteBndryPlanes::write_planes ( int  t_step,
double  time,
amrex::Vector< amrex::Vector< amrex::MultiFab >> &  vars_new,
bool  is_moist 
)

Function to write the specified grid data to an output file

Parameters
t_stepTimestep number
timeCurrent time
vars_newGrid data for all variables across the AMR hierarchy
is_moistWhether moist state components are included in the output
140 {
141  BL_PROFILE("ERF::WriteBndryPlanes::write_planes");
142 
143  MultiFab& S = vars_new[bndry_lev][Vars::cons];
144  MultiFab& xvel = vars_new[bndry_lev][Vars::xvel];
145  MultiFab& yvel = vars_new[bndry_lev][Vars::yvel];
146  MultiFab& zvel = vars_new[bndry_lev][Vars::zvel];
147 
148  const std::string chkname =
149  m_filename + Concatenate("/bndry_output", t_step);
150 
151  //Print() << "Writing boundary planes at time " << time_d << std::endl;
152 
153  const std::string level_prefix = "Level_";
154  PreBuildDirectorHierarchy(chkname, level_prefix, 1, true);
155 
156  // note: by using the entire domain box we end up using 1 processor
157  // to hold all boundaries
158  BoxArray ba(target_box);
159  DistributionMapping dm{ba};
160 
161  IntVect new_hi = target_box.bigEnd() - target_box.smallEnd();
162  Box target_box_shifted(IntVect(0,0,0),new_hi);
163  BoxArray ba_shifted(target_box_shifted);
164 
165  for (int i = 0; i < m_var_names.size(); i++)
166  {
167  std::string var_name = m_var_names[i];
168  std::string filename = MultiFabFileFullPrefix(bndry_lev, chkname, level_prefix, var_name);
169 
170  int ncomp;
171  if (var_name == "velocity") {
172  ncomp = AMREX_SPACEDIM;
173  } else {
174  ncomp = 1;
175  }
176 
177  BndryRegister bndry (ba , dm, m_in_rad, m_out_rad, m_extent_rad, ncomp);
178  BndryRegister bndry_shifted(ba_shifted, dm, m_in_rad, m_out_rad, m_extent_rad, ncomp);
179 
180  int nghost = 0;
181  if (var_name == "density")
182  {
183  bndry.copyFrom(S, nghost, Rho_comp, 0, ncomp, m_geom[bndry_lev].periodicity());
184 
185  } else if (var_name == "temperature") {
186  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
187  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
188  {
189  const Box& bx = mfi.tilebox();
190  Real time = static_cast<Real>(time_d);
191  if (is_moist) {
192  // NOTE: we send in S[mfi] where we should send in (*z_phys_cc[lev])[mfi] because we know this routine doesn't use it
193  derived::erf_dermoisttemp(bx, Temp[mfi], 0, 1, S[mfi], S[mfi], m_geom[bndry_lev], time, nullptr, bndry_lev);
194  } else {
195  // NOTE: we send in S[mfi] where we should send in (*z_phys_cc[lev])[mfi] because we know this routine doesn't use it
196  derived::erf_dertemp(bx, Temp[mfi], 0, 1, S[mfi], S[mfi], m_geom[bndry_lev], time, nullptr, bndry_lev);
197  }
198  }
199  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
200  } else if (var_name == "theta") {
201  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
202  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
203  {
204  const Box& bx = mfi.tilebox();
205  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoTheta_comp);
206  }
207  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
208  } else if (var_name == "scalar") {
209  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
210  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
211  {
212  const Box& bx = mfi.tilebox();
213  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoScalar_comp);
214  }
215  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
216  } else if (var_name == "ke") {
217  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
218  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
219  {
220  const Box& bx = mfi.tilebox();
221  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoKE_comp);
222  }
223  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
224  } else if (var_name == "qv") {
225  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
226  if (S.nComp() > RhoQ2_comp) {
227  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
228  {
229  const Box& bx = mfi.tilebox();
230  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoQ1_comp);
231  }
232  } else {
233  Temp.setVal(0.);
234  }
235  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
236  } else if (var_name == "qc") {
237  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
238  if (S.nComp() > RhoQ2_comp) {
239  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
240  {
241  const Box& bx = mfi.tilebox();
242  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoQ2_comp);
243  }
244  } else {
245  Temp.setVal(0.);
246  }
247  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
248  } else if (var_name == "velocity") {
249  MultiFab Vel(S.boxArray(), S.DistributionMap(), 3, m_out_rad);
250  average_face_to_cellcenter(Vel,0,Array<const MultiFab*,3>{&xvel,&yvel,&zvel});
251  bndry.copyFrom(Vel, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
252  } else {
253  //Print() << "Trying to write planar output for " << var_name << std::endl;
254  Error("Don't know how to output this variable");
255  }
256 
257  for (OrientationIter oit; oit != nullptr; ++oit) {
258  auto ori = oit();
259  if (ori.coordDir() < 2) {
260  std::string facename = Concatenate(filename + '_', ori, 1);
261  br_shift(oit, bndry, bndry_shifted);
262  bndry_shifted[ori].write(facename);
263  }
264  }
265 
266  } // loop over num_vars
267 
268  // Writing time.dat
269  if (ParallelDescriptor::IOProcessor()) {
270  std::ofstream oftime(m_time_file, std::ios::out | std::ios::app);
271  oftime << std::setprecision(17) << t_step << ' ' << time_d << '\n';
272  oftime.close();
273  }
274 }
struct @28 out
#define RhoScalar_comp
Definition: ERF_IndexDefines.H:40
#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
#define RhoKE_comp
Definition: ERF_IndexDefines.H:38
void br_shift(OrientationIter oit, const BndryRegister &b1, BndryRegister &b2)
Definition: ERF_WriteBndryPlanes.cpp:21
const int m_out_rad
Definition: ERF_WriteBndryPlanes.H:54
const int m_extent_rad
Definition: ERF_WriteBndryPlanes.H:55
@ xvel
Definition: ERF_IndexDefines.H:177
@ cons
Definition: ERF_IndexDefines.H:176
@ zvel
Definition: ERF_IndexDefines.H:179
@ yvel
Definition: ERF_IndexDefines.H:178
void erf_derrhodivide(const Box &bx, FArrayBox &derfab, const FArrayBox &datfab, const int scalar_index)
Definition: ERF_Derive.cpp:168
void erf_dermoisttemp(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const FArrayBox &, const Geometry &, Real, const int *, const int)
Definition: ERF_Derive.cpp:266
void erf_dertemp(const Box &bx, FArrayBox &derfab, int, int, const FArrayBox &datfab, const FArrayBox &, const Geometry &, Real, const int *, const int)
Definition: ERF_Derive.cpp:243
Here is the call graph for this function:

Member Data Documentation

◆ bndry_lev

int WriteBndryPlanes::bndry_lev = 0
staticprivate

Referenced by write_planes(), and WriteBndryPlanes().

◆ m_extent_rad

const int WriteBndryPlanes::m_extent_rad = 0
private

Referenced by write_planes().

◆ m_filename

std::string WriteBndryPlanes::m_filename {""}
private

File name for IO.

Referenced by write_planes(), and WriteBndryPlanes().

◆ m_geom

amrex::Vector<amrex::Geometry>& WriteBndryPlanes::m_geom
private

Geometry objects for all levels.

Referenced by write_planes(), and WriteBndryPlanes().

◆ m_in_rad

int WriteBndryPlanes::m_in_rad = 1
private

controls extents on native bndry output

Referenced by write_planes(), and WriteBndryPlanes().

◆ m_in_times

amrex::Vector<double> WriteBndryPlanes::m_in_times
private

Timestep and times to be stored in time.dat.

◆ m_in_timesteps

amrex::Vector<int> WriteBndryPlanes::m_in_timesteps
private

◆ m_out_rad

const int WriteBndryPlanes::m_out_rad = 1
private

Referenced by write_planes().

◆ m_time_file

std::string WriteBndryPlanes::m_time_file {""}
private

File name for Native time file.

Referenced by write_planes(), and WriteBndryPlanes().

◆ m_var_names

amrex::Vector<std::string> WriteBndryPlanes::m_var_names
private

Variables for IO.

Referenced by write_planes(), and WriteBndryPlanes().

◆ target_box

amrex::Box WriteBndryPlanes::target_box
private

IO output box region.

Referenced by write_planes(), and WriteBndryPlanes().


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