ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SampleData.H
Go to the documentation of this file.
1 #ifndef ERF_SAMPLEDATA_H
2 #define ERF_SAMPLEDATA_H
3 
4 #include <memory>
5 
6 #include <AMReX_ParmParse.H>
7 #include <AMReX_MultiFab.H>
8 #include <AMReX_MultiFabUtil.H>
9 #include <AMReX_PlotFileUtil.H>
10 
11 #include <ERF_IndexDefines.H>
12 
14 {
16  {
17  amrex::ParmParse pp("erf");
18 
19  // Count number of lo and hi points define the line
20  int n_line_lo = pp.countval("sample_line_lo") / AMREX_SPACEDIM;
21  int n_line_hi = pp.countval("sample_line_hi") / AMREX_SPACEDIM;
22  int n_line_dir = pp.countval("sample_line_dir");
23  AMREX_ALWAYS_ASSERT( (n_line_lo==n_line_hi ) &&
24  (n_line_lo==n_line_dir) );
25 
26  // Parse the data
27  if (n_line_lo > 0) {
28  // Parse lo
29  amrex::Vector<int> idx_lo; idx_lo.resize(n_line_lo*AMREX_SPACEDIM);
30  amrex::Vector<amrex::IntVect> iv_lo; iv_lo.resize(n_line_lo);
31  pp.queryarr("sample_line_lo",idx_lo,0,n_line_lo*AMREX_SPACEDIM);
32  for (int i(0); i < n_line_lo; i++) {
33  amrex::IntVect iv(idx_lo[AMREX_SPACEDIM*i+0],
34  idx_lo[AMREX_SPACEDIM*i+1],
35  idx_lo[AMREX_SPACEDIM*i+2]);
36  iv_lo[i] = iv;
37  }
38 
39  // Parse hi
40  amrex::Vector<int> idx_hi; idx_hi.resize(n_line_hi*AMREX_SPACEDIM);
41  amrex::Vector<amrex::IntVect> iv_hi; iv_hi.resize(n_line_hi);
42  pp.queryarr("sample_line_hi",idx_hi,0,n_line_hi*AMREX_SPACEDIM);
43  for (int i(0); i < n_line_hi; i++) {
44  amrex::IntVect iv(idx_hi[AMREX_SPACEDIM*i+0],
45  idx_hi[AMREX_SPACEDIM*i+1],
46  idx_hi[AMREX_SPACEDIM*i+2]);
47  iv_hi[i] = iv;
48  }
49 
50  // Construct vector of bounding boxes
51  m_bnd_bx.resize(n_line_lo);
52  for (int i = 0; i < n_line_hi; i++){
53  amrex::Box lbx(iv_lo[i],iv_hi[i]);
54  m_bnd_bx[i] = lbx;
55  }
56 
57  // Parse directionality
58  m_dir.resize(n_line_dir);
59  pp.queryarr("sample_line_dir",m_dir,0,n_line_dir);
60 
61  // Allocate space for level indicator
62  m_lev.resize(n_line_dir,0);
63 
64  // Allocate space for MF pointers
65  m_ls_mf.resize(n_line_lo);
66  }
67  }
68 
69  void
70  get_line_mfs (amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars_new)
71  {
72  int nlev = vars_new.size();
73  int nline = m_bnd_bx.size();
74  int ncomp = 2;
75 
76  // Loop over each line
77  for (int iline(0); iline<nline; ++iline) {
78  int dir = m_dir[iline];
79  amrex::Box bnd_bx = m_bnd_bx[iline];
80  amrex::IntVect cell = bnd_bx.smallEnd();
81 
82  // Search each level to get the finest data possible
83  for (int ilev(nlev-1); ilev>=0; --ilev) {
84 
85  // Construct CC velocities
86  amrex::MultiFab mf_cc_vel;
87  auto ba = vars_new[ilev][Vars::cons].boxArray();
88  auto dm = vars_new[ilev][Vars::cons].DistributionMap();
89  mf_cc_vel.define(ba, dm, AMREX_SPACEDIM, amrex::IntVect(1,1,1));
90  average_face_to_cellcenter(mf_cc_vel,0,
91  amrex::Array<const amrex::MultiFab*,3>{&vars_new[ilev][Vars::xvel],
92  &vars_new[ilev][Vars::yvel],
93  &vars_new[ilev][Vars::zvel]});
94 
95  // Construct vector of MFs holding T and WSP
96  amrex::MultiFab mf_cc_data;
97  mf_cc_data.define(ba, dm, ncomp, 1);
98 #ifdef _OPENMP
99 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
100 #endif
101  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
102  const amrex::Box& tbx = mfi.tilebox();
103  auto const& dfab = mf_cc_data.array(mfi);
104  auto const& tfab = vars_new[ilev][Vars::cons].array(mfi);
105  auto const& wfab = mf_cc_vel.array(mfi);
106  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
107  {
108  dfab(i,j,k,0) = tfab(i,j,k,1)/tfab(i,j,k,0);
109  dfab(i,j,k,1) = std::sqrt(wfab(i,j,k,0)*wfab(i,j,k,0)
110  + wfab(i,j,k,1)*wfab(i,j,k,1)
111  + wfab(i,j,k,2)*wfab(i,j,k,2)) ;
112  });
113 
114  }
115 
116  m_lev[iline] = ilev;
117  m_ls_mf[iline] = get_line_data(mf_cc_data, dir, cell, bnd_bx);
118 
119  // We can stop if we got the entire line
120  auto min_bnd_bx = m_ls_mf[iline].boxArray().minimalBox();
121  if (bnd_bx == min_bnd_bx) { continue; }
122 
123  } // ilev
124  }// iline
125  }
126 
127  void
128  write_line_mfs (amrex::Vector<amrex::Real>& time,
129  amrex::Vector<int>& level_steps,
130  amrex::Vector<amrex::IntVect>& ref_ratio,
131  amrex::Vector<amrex::Geometry>& geom)
132  {
133  std::string name_base = "plt_line_";
134  amrex::Vector<std::string> varnames = {"T", "Wsp"};
135 
136  int nline = m_ls_mf.size();
137  for (int iline(0); iline<nline; ++iline) {
138  // Data members that can be used as-is
139  int dir = m_dir[iline];
140  int lev = m_lev[iline];
141  amrex::Real m_time = time[lev];
142  amrex::Vector<int> m_level_steps = {level_steps[lev]};
143  amrex::Vector<amrex::IntVect> m_ref_ratio = {ref_ratio[lev]};
144 
145  // Create modified geometry object corresponding to the line
146  auto plo = geom[lev].ProbLo();
147  auto dx = geom[lev].CellSize();
148  amrex::Vector<amrex::Geometry> m_geom; m_geom.resize(1);
149  amrex::Vector<int> is_per(AMREX_SPACEDIM,0);
150  amrex::Box m_dom = m_bnd_bx[iline];
151  amrex::RealBox m_rb;
152  for (int d(0); d<AMREX_SPACEDIM; ++d) {
153  amrex::Real offset = (d==dir) ? 0 : 0.5;
154  amrex::Real lo = plo[d] + ( m_dom.smallEnd(d) - offset ) * dx[d];
155  amrex::Real hi = plo[d] + ( m_dom.bigEnd(d) + offset ) * dx[d];
156 
157  m_rb.setLo(d,lo);
158  m_rb.setHi(d,hi);
159 
160  is_per[d] = geom[lev].isPeriodic(d);
161  }
162  m_geom[0].define(m_dom, &m_rb, geom[lev].Coord(), is_per.data());
163 
164  // Create plotfile name
165  std::string name_line = amrex::Concatenate(name_base, iline , 5);
166  name_line += "_step_";
167  std::string plotfilename = amrex::Concatenate(name_line, m_level_steps[0], 5);
168 
169  // Get the data
170  amrex::Vector<const amrex::MultiFab*> mf = {&(m_ls_mf[iline])};
171 
172  // Write each line
173  WriteMultiLevelPlotfile(plotfilename, 1, mf,
174  varnames, m_geom, m_time,
175  m_level_steps, m_ref_ratio);
176  }
177  }
178 
179  amrex::Vector<int> m_dir;
180  amrex::Vector<int> m_lev;
181  amrex::Vector<amrex::Box> m_bnd_bx;
182  amrex::Vector<amrex::MultiFab> m_ls_mf;
183 };
184 
185 
187 {
189  {
190  amrex::ParmParse pp("erf");
191 
192  // Count number of lo and hi points define the plane
193  int n_plane_lo = pp.countval("sample_plane_lo") / AMREX_SPACEDIM;
194  int n_plane_hi = pp.countval("sample_plane_hi") / AMREX_SPACEDIM;
195  int n_plane_dir = pp.countval("sample_plane_dir");
196  AMREX_ALWAYS_ASSERT( (n_plane_lo==n_plane_hi ) &&
197  (n_plane_lo==n_plane_dir) );
198 
199  // Parse the data
200  if (n_plane_lo > 0) {
201  // Parse lo
202  amrex::Vector<amrex::Real> r_lo; r_lo.resize(n_plane_lo*AMREX_SPACEDIM);
203  amrex::Vector<amrex::Vector<amrex::Real>> rv_lo;
204  pp.queryarr("sample_plane_lo",r_lo,0,n_plane_lo*AMREX_SPACEDIM);
205  for (int i(0); i < n_plane_lo; i++) {
206  amrex::Vector<amrex::Real> rv = {r_lo[AMREX_SPACEDIM*i+0],
207  r_lo[AMREX_SPACEDIM*i+1],
208  r_lo[AMREX_SPACEDIM*i+2]};
209  rv_lo.push_back(rv);
210  }
211 
212  // Parse hi
213  amrex::Vector<amrex::Real> r_hi; r_hi.resize(n_plane_hi*AMREX_SPACEDIM);
214  amrex::Vector<amrex::Vector<amrex::Real>> rv_hi;
215  pp.queryarr("sample_plane_hi",r_hi,0,n_plane_hi*AMREX_SPACEDIM);
216  for (int i(0); i < n_plane_hi; i++) {
217  amrex::Vector<amrex::Real> rv = {r_hi[AMREX_SPACEDIM*i+0],
218  r_hi[AMREX_SPACEDIM*i+1],
219  r_hi[AMREX_SPACEDIM*i+2]};
220  rv_hi.push_back(rv);
221  }
222 
223  // Construct vector of bounding real boxes
224  m_bnd_rbx.resize(n_plane_lo);
225  for (int i(0); i < n_plane_hi; i++){
226  amrex::RealBox rbx(rv_lo[i].data(),rv_hi[i].data());
227  m_bnd_rbx[i] = rbx;
228  }
229 
230  // Parse directionality
231  m_dir.resize(n_plane_dir);
232  pp.queryarr("sample_plane_dir",m_dir,0,n_plane_dir);
233 
234  // Allocate space for level indicator
235  m_lev.resize(n_plane_dir,0);
236 
237  // Allocate space for MF pointers
238  m_ps_mf.resize(n_plane_lo);
239  }
240  }
241 
242  // This must match what is in AMReX_MultiFabUtil.H
243  amrex::Box
244  getIndexBox (const amrex::RealBox& real_box,
245  const amrex::Geometry& geom) {
246  amrex::IntVect slice_lo, slice_hi;
247 
248  AMREX_D_TERM(slice_lo[0]=static_cast<int>(std::floor((real_box.lo(0) - geom.ProbLo(0))/geom.CellSize(0)));,
249  slice_lo[1]=static_cast<int>(std::floor((real_box.lo(1) - geom.ProbLo(1))/geom.CellSize(1)));,
250  slice_lo[2]=static_cast<int>(std::floor((real_box.lo(2) - geom.ProbLo(2))/geom.CellSize(2))););
251 
252  AMREX_D_TERM(slice_hi[0]=static_cast<int>(std::floor((real_box.hi(0) - geom.ProbLo(0))/geom.CellSize(0)));,
253  slice_hi[1]=static_cast<int>(std::floor((real_box.hi(1) - geom.ProbLo(1))/geom.CellSize(1)));,
254  slice_hi[2]=static_cast<int>(std::floor((real_box.hi(2) - geom.ProbLo(2))/geom.CellSize(2))););
255 
256  return amrex::Box(slice_lo, slice_hi) & geom.Domain();
257  }
258 
259  void
260  get_plane_mfs (amrex::Vector<amrex::Geometry>& geom,
261  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars_new)
262  {
263  int nlev = vars_new.size();
264  int nplane = m_bnd_rbx.size();
265  int ncomp = 2;
266  bool interpolate = true;
267 
268  // Loop over each plane
269  for (int iplane(0); iplane<nplane; ++iplane) {
270  int dir = m_dir[iplane];
271  amrex::RealBox bnd_rbx = m_bnd_rbx[iplane];
272  amrex::Real point = bnd_rbx.lo(dir);
273 
274  // Search each level to get the finest data possible
275  for (int ilev(nlev-1); ilev>=0; --ilev) {
276 
277  // Construct CC velocities
278  amrex::MultiFab mf_cc_vel;
279  auto ba = vars_new[ilev][Vars::cons].boxArray();
280  auto dm = vars_new[ilev][Vars::cons].DistributionMap();
281  mf_cc_vel.define(ba, dm, AMREX_SPACEDIM, amrex::IntVect(1,1,1));
282  average_face_to_cellcenter(mf_cc_vel,0,
283  amrex::Array<const amrex::MultiFab*,3>{&vars_new[ilev][Vars::xvel],
284  &vars_new[ilev][Vars::yvel],
285  &vars_new[ilev][Vars::zvel]});
286 
287  // Construct vector of MFs holding T and WSP
288  amrex::MultiFab mf_cc_data;
289  mf_cc_data.define(ba, dm, ncomp, 1);
290 #ifdef _OPENMP
291 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
292 #endif
293  for (amrex::MFIter mfi(mf_cc_data, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi) {
294  const amrex::Box& tbx = mfi.tilebox();
295  auto const& dfab = mf_cc_data.array(mfi);
296  auto const& tfab = vars_new[ilev][Vars::cons].array(mfi);
297  auto const& wfab = mf_cc_vel.array(mfi);
298  amrex::ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
299  {
300  dfab(i,j,k,0) = tfab(i,j,k,1)/tfab(i,j,k,0);
301  dfab(i,j,k,1) = std::sqrt(wfab(i,j,k,0)*wfab(i,j,k,0)
302  + wfab(i,j,k,1)*wfab(i,j,k,1)
303  + wfab(i,j,k,2)*wfab(i,j,k,2)) ;
304  });
305 
306  }
307 
308  m_lev[iplane] = ilev;
309  m_ps_mf[iplane] = get_slice_data(dir, point, mf_cc_data, geom[ilev],
310  0, ncomp, interpolate, bnd_rbx);
311 
312  // We can stop if we got the entire plane
313  auto min_bnd_bx = m_ps_mf[iplane]->boxArray().minimalBox();
314  amrex::Box bnd_bx = getIndexBox(bnd_rbx, geom[ilev]);
315  if (bnd_bx == min_bnd_bx) { continue; }
316 
317  } // ilev
318  }// iplane
319  }
320 
321  void
322  write_plane_mfs (amrex::Vector<amrex::Real>& time,
323  amrex::Vector<int>& level_steps,
324  amrex::Vector<amrex::IntVect>& ref_ratio,
325  amrex::Vector<amrex::Geometry>& geom)
326  {
327  std::string name_base = "plt_plane_";
328  amrex::Vector<std::string> varnames = {"T", "Wsp"};
329 
330  int nplane = m_ps_mf.size();
331  for (int iplane(0); iplane<nplane; ++iplane) {
332  // Data members that can be used as-is
333  int dir = m_dir[iplane];
334  int lev = m_lev[iplane];
335  amrex::Real m_time = time[lev];
336  amrex::Vector<int> m_level_steps = {level_steps[lev]};
337  amrex::Vector<amrex::IntVect> m_ref_ratio = {ref_ratio[lev]};
338 
339  // Create modified geometry object corresponding to the plane
340  amrex::RealBox m_rb = m_bnd_rbx[iplane];
341  amrex::Box m_dom = getIndexBox(m_rb, geom[lev]);
342  amrex::Real point = m_rb.hi(dir);
343  amrex::Vector<int> is_per(AMREX_SPACEDIM,0);
344  for (int d(0); d<AMREX_SPACEDIM; ++d) {
345  if (d==dir) {
346  m_rb.setLo(d,point-0.5*geom[lev].CellSize(d));
347  m_rb.setHi(d,point+0.5*geom[lev].CellSize(d));
348  }
349  is_per[d] = geom[lev].isPeriodic(d);
350  }
351  amrex::Vector<amrex::Geometry> m_geom; m_geom.resize(1);
352  m_geom[0].define(m_dom, &m_rb, geom[lev].Coord(), is_per.data());
353 
354  // Create plotfile name
355  std::string name_plane = amrex::Concatenate(name_base, iplane , 5);
356  name_plane += "_step_";
357  std::string plotfilename = amrex::Concatenate(name_plane, m_level_steps[0], 5);
358 
359  // Get the data
360  amrex::Vector<const amrex::MultiFab*> mf = {m_ps_mf[iplane].get()};
361 
362  // Write each plane
363  WriteMultiLevelPlotfile(plotfilename, 1, mf,
364  varnames, m_geom, m_time,
365  m_level_steps, m_ref_ratio);
366  } // iplane
367  }
368 
369  amrex::Vector<int> m_dir;
370  amrex::Vector<int> m_lev;
371  amrex::Vector<amrex::RealBox> m_bnd_rbx;
372  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_ps_mf;
373 };
374 
375 
377 {
378 public:
379  explicit SampleData (bool do_line=false,
380  bool do_plane=false)
381  {
382  if(do_line) m_ls = std::make_unique<LineSampler >();
383  if(do_plane) m_ps = std::make_unique<PlaneSampler>();
384  }
385 
386  void
387  get_sample_data (amrex::Vector<amrex::Geometry>& geom,
388  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars_new)
389  {
390  if (m_ls) m_ls->get_line_mfs(vars_new);
391  if (m_ps) m_ps->get_plane_mfs(geom, vars_new);
392  }
393 
394  void
395  write_sample_data (amrex::Vector<amrex::Real>& time,
396  amrex::Vector<int>& level_steps,
397  amrex::Vector<amrex::IntVect>& ref_ratio,
398  amrex::Vector<amrex::Geometry>& geom)
399  {
400  if (m_ls) m_ls->write_line_mfs(time, level_steps, ref_ratio, geom);
401  if (m_ls) m_ps->write_plane_mfs(time, level_steps, ref_ratio, geom);
402  }
403 
404 private:
405 
406  // Structures for getting line MFs
407  std::unique_ptr<LineSampler> m_ls = nullptr;
408 
409  // Structures for getting plane MFs
410  std::unique_ptr<PlaneSampler> m_ps = nullptr;
411 };
412 #endif
Coord
Definition: ERF_DataStruct.H:64
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:219
AMREX_FORCE_INLINE IntVect offset(const int face_dir, const int normal)
Definition: ERF_ReadBndryPlanes.cpp:28
Definition: ERF_SampleData.H:377
std::unique_ptr< LineSampler > m_ls
Definition: ERF_SampleData.H:407
void get_sample_data(amrex::Vector< amrex::Geometry > &geom, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_new)
Definition: ERF_SampleData.H:387
SampleData(bool do_line=false, bool do_plane=false)
Definition: ERF_SampleData.H:379
std::unique_ptr< PlaneSampler > m_ps
Definition: ERF_SampleData.H:410
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)
Definition: ERF_SampleData.H:395
@ xvel
Definition: ERF_IndexDefines.H:130
@ cons
Definition: ERF_IndexDefines.H:129
@ zvel
Definition: ERF_IndexDefines.H:132
@ yvel
Definition: ERF_IndexDefines.H:131
Definition: ERF_SampleData.H:14
amrex::Vector< amrex::MultiFab > m_ls_mf
Definition: ERF_SampleData.H:182
void get_line_mfs(amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_new)
Definition: ERF_SampleData.H:70
amrex::Vector< int > m_dir
Definition: ERF_SampleData.H:179
LineSampler()
Definition: ERF_SampleData.H:15
amrex::Vector< amrex::Box > m_bnd_bx
Definition: ERF_SampleData.H:181
void write_line_mfs(amrex::Vector< amrex::Real > &time, amrex::Vector< int > &level_steps, amrex::Vector< amrex::IntVect > &ref_ratio, amrex::Vector< amrex::Geometry > &geom)
Definition: ERF_SampleData.H:128
amrex::Vector< int > m_lev
Definition: ERF_SampleData.H:180
Definition: ERF_SampleData.H:187
amrex::Vector< int > m_dir
Definition: ERF_SampleData.H:369
amrex::Box getIndexBox(const amrex::RealBox &real_box, const amrex::Geometry &geom)
Definition: ERF_SampleData.H:244
amrex::Vector< int > m_lev
Definition: ERF_SampleData.H:370
void get_plane_mfs(amrex::Vector< amrex::Geometry > &geom, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_new)
Definition: ERF_SampleData.H:260
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_ps_mf
Definition: ERF_SampleData.H:372
amrex::Vector< amrex::RealBox > m_bnd_rbx
Definition: ERF_SampleData.H:371
PlaneSampler()
Definition: ERF_SampleData.H:188
void write_plane_mfs(amrex::Vector< amrex::Real > &time, amrex::Vector< int > &level_steps, amrex::Vector< amrex::IntVect > &ref_ratio, amrex::Vector< amrex::Geometry > &geom)
Definition: ERF_SampleData.H:322