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
55  : m_geom(geom)
56 {
57  ParmParse pp("erf");
58 
59  // Get the radius inside the domain
60  pp.query("in_rad",m_in_rad);
61 
62  // User-specified region is given in physical coordinates, not index space
63  std::vector<Real> box_lo(3), box_hi(3);
64  pp.getarr("bndry_output_box_lo",box_lo,0,2);
65  pp.getarr("bndry_output_box_hi",box_hi,0,2);
66 
67  // If the target area is contained at a finer level, use the finest data possible.
68  // target_box is expressed in the index space of bndry_lev, so it must only be set
69  // together with bndry_lev; each level's candidate box is kept in a local variable.
70  for (int ilev = 0; ilev < grids.size(); ilev++) {
71 
72  const Real* xLo = m_geom[ilev].ProbLo();
73  auto const dxi = geom[ilev].InvCellSizeArray();
74  const Box& domain = m_geom[ilev].Domain();
75 
76  // We create the smallest box that contains all of the cell centers
77  // in the physical region specified
78  int ilo = static_cast<int>(Math::floor((box_lo[0] - xLo[0]) * dxi[0])+Real(.5));
79  int jlo = static_cast<int>(Math::floor((box_lo[1] - xLo[1]) * dxi[1])+Real(.5));
80  int ihi = static_cast<int>(Math::floor((box_hi[0] - xLo[0]) * dxi[0])+Real(.5))-1;
81  int jhi = static_cast<int>(Math::floor((box_hi[1] - xLo[1]) * dxi[1])+Real(.5))-1;
82 
83  // Map this to index space -- for now we do no interpolation
84  Box box_this_lev(IntVect(ilo,jlo,0),
85  IntVect(ihi,jhi,domain.bigEnd(2)));
86 
87  // Test if the target box at this level fits in the grids at this level
88  Box gbx = box_this_lev; gbx.grow(IntVect(1,1,0));
89 
90  // Ensure that the box is no larger than can fit in the (periodically grown) domain
91  // at level 0
92  if (ilev == 0) {
93  Box per_grown_domain(domain);
94  int growx = (geom[0].isPeriodic(0)) ? 1 : 0;
95  int growy = (geom[0].isPeriodic(1)) ? 1 : 0;
96  per_grown_domain.grow(IntVect(growx,growy,0));
97  /*
98  if (!per_grown_domain.contains(gbx))
99  Error("WriteBndryPlanes: Requested box is too large to fill");
100  */
101 
102  // Default to level 0
103  target_box = box_this_lev;
104  }
105 
106  // Use this level's data only if its grids fully contain the requested region
107  if (grids[ilev].contains(gbx)) {
108  bndry_lev = ilev;
109  target_box = box_this_lev;
110  }
111  }
112 
113  // The folder "m_filename" will contain the time series of data and the time.dat file
114  pp.get("bndry_output_planes_file", m_filename);
115 
116  m_time_file = m_filename + "/time.dat";
117 
118  if (pp.contains("bndry_output_var_names"))
119  {
120  int num_vars = pp.countval("bndry_output_var_names");
121  m_var_names.resize(num_vars);
122  pp.queryarr("bndry_output_var_names",m_var_names,0,num_vars);
123  }
124 }
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:30
int m_in_rad
controls extents on native bndry output
Definition: ERF_WriteBndryPlanes.H:50
static int bndry_lev
Definition: ERF_WriteBndryPlanes.H:47
amrex::Box target_box
IO output box region.
Definition: ERF_WriteBndryPlanes.H:27
amrex::Vector< std::string > m_var_names
Variables for IO.
Definition: ERF_WriteBndryPlanes.H:39
std::string m_time_file
File name for Native time file.
Definition: ERF_WriteBndryPlanes.H:36
std::string m_filename
File name for IO.
Definition: ERF_WriteBndryPlanes.H:33
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
136 {
137  BL_PROFILE("ERF::WriteBndryPlanes::write_planes");
138 
139  MultiFab& S = vars_new[bndry_lev][Vars::cons];
140  MultiFab& xvel = vars_new[bndry_lev][Vars::xvel];
141  MultiFab& yvel = vars_new[bndry_lev][Vars::yvel];
142  MultiFab& zvel = vars_new[bndry_lev][Vars::zvel];
143 
144  const std::string chkname =
145  m_filename + Concatenate("/bndry_output", t_step);
146 
147  //Print() << "Writing boundary planes at time " << time_d << std::endl;
148 
149  const std::string level_prefix = "Level_";
150  PreBuildDirectorHierarchy(chkname, level_prefix, 1, true);
151 
152  // note: by using the entire domain box we end up using 1 processor
153  // to hold all boundaries
154  BoxArray ba(target_box);
155  DistributionMapping dm{ba};
156 
157  IntVect new_hi = target_box.bigEnd() - target_box.smallEnd();
158  Box target_box_shifted(IntVect(0,0,0),new_hi);
159  BoxArray ba_shifted(target_box_shifted);
160 
161  for (int i = 0; i < m_var_names.size(); i++)
162  {
163  std::string var_name = m_var_names[i];
164  std::string filename = MultiFabFileFullPrefix(bndry_lev, chkname, level_prefix, var_name);
165 
166  int ncomp;
167  if (var_name == "velocity") {
168  ncomp = AMREX_SPACEDIM;
169  } else {
170  ncomp = 1;
171  }
172 
173  BndryRegister bndry (ba , dm, m_in_rad, m_out_rad, m_extent_rad, ncomp);
174  BndryRegister bndry_shifted(ba_shifted, dm, m_in_rad, m_out_rad, m_extent_rad, ncomp);
175 
176  int nghost = 0;
177  if (var_name == "density")
178  {
179  bndry.copyFrom(S, nghost, Rho_comp, 0, ncomp, m_geom[bndry_lev].periodicity());
180 
181  } else if (var_name == "temperature") {
182  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
183  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
184  {
185  const Box& bx = mfi.tilebox();
186  Real time = static_cast<Real>(time_d);
187  if (is_moist) {
188  // 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
189  derived::erf_dermoisttemp(bx, Temp[mfi], 0, 1, S[mfi], S[mfi], m_geom[bndry_lev], time, nullptr, bndry_lev);
190  } else {
191  // 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
192  derived::erf_dertemp(bx, Temp[mfi], 0, 1, S[mfi], S[mfi], m_geom[bndry_lev], time, nullptr, bndry_lev);
193  }
194  }
195  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
196  } else if (var_name == "theta") {
197  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
198  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
199  {
200  const Box& bx = mfi.tilebox();
201  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoTheta_comp);
202  }
203  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
204  } else if (var_name == "scalar") {
205  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
206  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
207  {
208  const Box& bx = mfi.tilebox();
209  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoScalar_comp);
210  }
211  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
212  } else if (var_name == "ke") {
213  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
214  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
215  {
216  const Box& bx = mfi.tilebox();
217  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoKE_comp);
218  }
219  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
220  } else if (var_name == "qv") {
221  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
222  if (S.nComp() > RhoQ2_comp) {
223  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
224  {
225  const Box& bx = mfi.tilebox();
226  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoQ1_comp);
227  }
228  } else {
229  Temp.setVal(0.);
230  }
231  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
232  } else if (var_name == "qc") {
233  MultiFab Temp(S.boxArray(),S.DistributionMap(),ncomp,0);
234  if (S.nComp() > RhoQ2_comp) {
235  for (MFIter mfi(Temp, TilingIfNotGPU()); mfi.isValid(); ++mfi)
236  {
237  const Box& bx = mfi.tilebox();
238  derived::erf_derrhodivide(bx, Temp[mfi], S[mfi], RhoQ2_comp);
239  }
240  } else {
241  Temp.setVal(0.);
242  }
243  bndry.copyFrom(Temp, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
244  } else if (var_name == "velocity") {
245  MultiFab Vel(S.boxArray(), S.DistributionMap(), 3, m_out_rad);
246  average_face_to_cellcenter(Vel,0,Array<const MultiFab*,3>{&xvel,&yvel,&zvel});
247  bndry.copyFrom(Vel, nghost, 0, 0, ncomp, m_geom[bndry_lev].periodicity());
248  } else {
249  //Print() << "Trying to write planar output for " << var_name << std::endl;
250  Error("Don't know how to output this variable");
251  }
252 
253  for (OrientationIter oit; oit != nullptr; ++oit) {
254  auto ori = oit();
255  if (ori.coordDir() < 2) {
256  std::string facename = Concatenate(filename + '_', ori, 1);
257  br_shift(oit, bndry, bndry_shifted);
258  bndry_shifted[ori].write(facename);
259  }
260  }
261 
262  } // loop over num_vars
263 
264  // Writing time.dat
265  if (ParallelDescriptor::IOProcessor()) {
266  std::ofstream oftime(m_time_file, std::ios::out | std::ios::app);
267  oftime << std::setprecision(17) << t_step << ' ' << time_d << '\n';
268  oftime.close();
269  }
270 }
struct @29 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:18
const int m_out_rad
Definition: ERF_WriteBndryPlanes.H:51
const int m_extent_rad
Definition: ERF_WriteBndryPlanes.H:52
@ xvel
Definition: ERF_IndexDefines.H:176
@ cons
Definition: ERF_IndexDefines.H:175
@ zvel
Definition: ERF_IndexDefines.H:178
@ yvel
Definition: ERF_IndexDefines.H:177
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: