REMORA
Energy Research and Forecasting: An Atmospheric Modeling Code
TracerPC Class Reference

#include <TracerPC.H>

Inheritance diagram for TracerPC:
Collaboration diagram for TracerPC:

Public Member Functions

 TracerPC (amrex::ParGDBBase *gdb)
 
 TracerPC (const amrex::Geometry &geom, const amrex::DistributionMapping &dmap, const amrex::BoxArray &ba)
 
void InitParticles (const amrex::MultiFab &a_z_height)
 
void AdvectWithUmac (amrex::Array< amrex::MultiFab const *, AMREX_SPACEDIM > umac, int level, amrex::Real dt, bool use_terrain, amrex::MultiFab &a_z_height)
 

Constructor & Destructor Documentation

◆ TracerPC() [1/2]

TracerPC::TracerPC ( amrex::ParGDBBase *  gdb)
inline
51  : amrex::ParticleContainer<TracerRealIdx::ncomps, TracerIntIdx::ncomps, 0, 0,
52  amrex::DefaultAllocator, TracerAssignor>(gdb)
53  {}
Definition: TracerPC.H:25
@ ncomps
Definition: TracerPC.H:20
@ ncomps
Definition: TracerPC.H:12

◆ TracerPC() [2/2]

TracerPC::TracerPC ( const amrex::Geometry &  geom,
const amrex::DistributionMapping &  dmap,
const amrex::BoxArray &  ba 
)
inline
58  : amrex::ParticleContainer<TracerRealIdx::ncomps, TracerIntIdx::ncomps, 0, 0,
59  amrex::DefaultAllocator, TracerAssignor>(geom, dmap, ba)
60  {}

Member Function Documentation

◆ AdvectWithUmac()

void TracerPC::AdvectWithUmac ( amrex::Array< amrex::MultiFab const *, AMREX_SPACEDIM >  umac,
int  level,
amrex::Real  dt,
bool  use_terrain,
amrex::MultiFab &  a_z_height 
)
80 {
81  BL_PROFILE("TracerPC::AdvectWithUmac()");
82  AMREX_ASSERT(OK(lev, lev, umac[0]->nGrow()-1));
83  AMREX_ASSERT(lev >= 0 && lev < GetParticles().size());
84 
85  AMREX_D_TERM(AMREX_ASSERT(umac[0]->nGrow() >= 1);,
86  AMREX_ASSERT(umac[1]->nGrow() >= 1);,
87  AMREX_ASSERT(umac[2]->nGrow() >= 1););
88 
89  AMREX_D_TERM(AMREX_ASSERT(!umac[0]->contains_nan());,
90  AMREX_ASSERT(!umac[1]->contains_nan());,
91  AMREX_ASSERT(!umac[2]->contains_nan()););
92 
93  const auto strttime = amrex::second();
94  const Geometry& geom = m_gdb->Geom(lev);
95  const Box& domain = geom.Domain();
96  const auto plo = geom.ProbLoArray();
97  const auto dxi = geom.InvCellSizeArray();
98  const auto dx = geom.CellSizeArray();
99 
100  Vector<std::unique_ptr<MultiFab> > raii_umac(AMREX_SPACEDIM);
101  Vector<MultiFab const*> umac_pointer(AMREX_SPACEDIM);
102  AMREX_ALWAYS_ASSERT(OnSameGrids(lev, *umac[0]));
103 
104  for (int i = 0; i < AMREX_SPACEDIM; i++) {
105  umac_pointer[i] = umac[i];
106  }
107 
108  for (int ipass = 0; ipass < 2; ipass++)
109  {
110 #ifdef AMREX_USE_OMP
111 #pragma omp parallel if (Gpu::notInLaunchRegion())
112 #endif
113  for (ParIterType pti(*this, lev); pti.isValid(); ++pti)
114  {
115  int grid = pti.index();
116  auto& ptile = ParticlesAt(lev, pti);
117  auto& aos = ptile.GetArrayOfStructs();
118  const int n = aos.numParticles();
119  auto *p_pbox = aos().data();
120  const FArrayBox* fab[AMREX_SPACEDIM] = { AMREX_D_DECL(&((*umac_pointer[0])[grid]),
121  &((*umac_pointer[1])[grid]),
122  &((*umac_pointer[2])[grid])) };
123 
124  //array of these pointers to pass to the GPU
125  GpuArray<Array4<const Real>, AMREX_SPACEDIM>
126  const umacarr {{AMREX_D_DECL((*fab[0]).array(),
127  (*fab[1]).array(),
128  (*fab[2]).array() )}};
129 
130  auto zheight = use_terrain ? a_z_height[grid].array() : Array4<Real>{};
131 
132  ParallelFor(n,
133  [=] AMREX_GPU_DEVICE (int i)
134  {
135  ParticleType& p = p_pbox[i];
136  if (p.id() <= 0) { return; }
137  ParticleReal v[AMREX_SPACEDIM];
138  mac_interpolate(p, plo, dxi, umacarr, v);
139  if (ipass == 0)
140  {
141  for (int dim=0; dim < AMREX_SPACEDIM; dim++)
142  {
143  p.rdata(dim) = p.pos(dim);
144  p.pos(dim) += static_cast<ParticleReal>(ParticleReal(0.5)*dt*v[dim]);
145  }
146  }
147  else
148  {
149  for (int dim=0; dim < AMREX_SPACEDIM; dim++)
150  {
151  p.pos(dim) = p.rdata(dim) + static_cast<ParticleReal>(dt*v[dim]);
152  p.rdata(dim) = v[dim];
153  }
154 
155  // also update z-coordinate here
156  IntVect iv(
157  AMREX_D_DECL(int(amrex::Math::floor((p.pos(0)-plo[0])*dxi[0])),
158  int(amrex::Math::floor((p.pos(1)-plo[1])*dxi[1])),
159  p.idata(0)));
160  iv[0] += domain.smallEnd()[0];
161  iv[1] += domain.smallEnd()[1];
162  ParticleReal zlo, zhi;
163  if (use_terrain) {
164  zlo = zheight(iv[0], iv[1], iv[2]);
165  zhi = zheight(iv[0], iv[1], iv[2]+1);
166  } else {
167  zlo = iv[2] * dx[2];
168  zhi = (iv[2]+1) * dx[2];
169  }
170  if (p.pos(2) > zhi) { // need to be careful here
171  p.idata(0) += 1;
172  } else if (p.pos(2) <= zlo) {
173  p.idata(0) -= 1;
174  }
175  }
176  });
177  }
178  }
179 
180  if (m_verbose > 1)
181  {
182  auto stoptime = amrex::second() - strttime;
183 
184 #ifdef AMREX_LAZY
185  Lazy::QueueReduction( [=] () mutable {
186 #endif
187  ParallelReduce::Max(stoptime, ParallelContext::IOProcessorNumberSub(),
188  ParallelContext::CommunicatorSub());
189 
190  amrex::Print() << "TracerParticleContainer::AdvectWithUmac() time: " << stoptime << '\n';
191 #ifdef AMREX_LAZY
192  });
193 #endif
194  }
195 }
@ v
Definition: IndexDefines.H:35

◆ InitParticles()

void TracerPC::InitParticles ( const amrex::MultiFab &  a_z_height)
10 {
11  BL_PROFILE("TracerPC::InitParticles");
12 
13  const int lev = 0;
14  const Real* dx = Geom(lev).CellSize();
15  const Real* plo = Geom(lev).ProbLo();
16 
17  for(MFIter mfi = MakeMFIter(lev); mfi.isValid(); ++mfi)
18  {
19  const Box& tile_box = mfi.tilebox();
20  const auto& height = a_z_height[mfi];
21  const FArrayBox* height_ptr = nullptr;
22 #ifdef AMREX_USE_GPU
23  std::unique_ptr<FArrayBox> hostfab;
24  if (height.arena()->isManaged() || height.arena()->isDevice()) {
25  hostfab = std::make_unique<FArrayBox>(height.box(), height.nComp(),
26  The_Pinned_Arena());
27  Gpu::dtoh_memcpy_async(hostfab->dataPtr(), height.dataPtr(),
28  height.size()*sizeof(Real));
29  Gpu::streamSynchronize();
30  height_ptr = hostfab.get();
31  }
32 #else
33  height_ptr = &height;
34 #endif
35  Gpu::HostVector<ParticleType> host_particles;
36  for (IntVect iv = tile_box.smallEnd(); iv <= tile_box.bigEnd(); tile_box.next(iv)) {
37  if (iv[0] == 3) {
38  Real r[3] = {0.5, 0.5, 0.5}; // this means place at cell center
39 
40  Real x = plo[0] + (iv[0] + r[0])*dx[0];
41  Real y = plo[1] + (iv[1] + r[1])*dx[1];
42  Real z = (*height_ptr)(iv) + r[2]*((*height_ptr)(iv + IntVect(AMREX_D_DECL(0, 0, 1))) - (*height_ptr)(iv));
43 
44  ParticleType p;
45  p.id() = ParticleType::NextID();
46  p.cpu() = ParallelDescriptor::MyProc();
47  p.pos(0) = x;
48  p.pos(1) = y;
49  p.pos(2) = z;
50 
51  p.rdata(TracerRealIdx::old_x) = p.pos(0);
52  p.rdata(TracerRealIdx::old_y) = p.pos(1);
53  p.rdata(TracerRealIdx::old_z) = p.pos(2);
54 
55  p.idata(TracerIntIdx::k) = iv[2]; // particles carry their z-index
56 
57  host_particles.push_back(p);
58  }
59  }
60 
61  auto& particles = GetParticles(lev);
62  auto& particle_tile = particles[std::make_pair(mfi.index(), mfi.LocalTileIndex())];
63  auto old_size = particle_tile.GetArrayOfStructs().size();
64  auto new_size = old_size + host_particles.size();
65  particle_tile.resize(new_size);
66 
67  Gpu::copy(Gpu::hostToDevice,
68  host_particles.begin(),
69  host_particles.end(),
70  particle_tile.GetArrayOfStructs().begin() + old_size);
71  }
72 }
@ k
Definition: TracerPC.H:19
@ old_z
Definition: TracerPC.H:11
@ old_x
Definition: TracerPC.H:9
@ old_y
Definition: TracerPC.H:10

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