REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_PC_Evolve.cpp
Go to the documentation of this file.
1#ifdef REMORA_USE_PARTICLES
2
3#include <REMORA_PC.H>
5#include <REMORA_Constants.H>
6#include <AMReX_TracerParticle_mod_K.H>
7
8using namespace amrex;
9
10/**
11 * @param a_lev level at which to evolve particles
12 * @param a_dt_lev time step
13 * @param a_flow_vel flow velocities
14 * @param a_z_phys_nd z nodal positions of grid
15 */
16void REMORAPC::EvolveParticles ( int a_lev,
17 Real a_dt_lev,
18 Vector<MultiFab const*>& a_flow_vel,
19 const Vector<std::unique_ptr<MultiFab>>& a_z_phys_nd )
20{
21 BL_PROFILE("REMORAPCPC::EvolveParticles()");
22
23 if (m_advect_w_flow) {
24 AdvectWithFlow( a_lev, a_dt_lev, a_flow_vel, a_z_phys_nd[a_lev] );
25 }
26
27 Redistribute();
28 return;
29}
30
31/**
32 * @param a_lev level at which to evolve particles
33 * @param a_dt time step
34 * @param a_umac flow velocities
35 * @param a_z_height z nodal positions of grid
36 */
37void REMORAPC::AdvectWithFlow ( int a_lev,
38 Real a_dt,
39 Vector<MultiFab const*>& a_umac,
40 const std::unique_ptr<MultiFab>& a_z_height )
41{
42 BL_PROFILE("REMORAPCPC::AdvectWithUmac()");
43 AMREX_ASSERT(OK(a_lev, a_lev, a_umac[0]->nGrow()-1));
44 AMREX_ASSERT(a_lev >= 0 && a_lev < GetParticles().size());
45
46 AMREX_D_TERM(AMREX_ASSERT(a_umac[0]->nGrow() >= 1);,
47 AMREX_ASSERT(a_umac[1]->nGrow() >= 1);,
48 AMREX_ASSERT(a_umac[2]->nGrow() >= 1););
49
50 AMREX_D_TERM(AMREX_ASSERT(!a_umac[0]->contains_nan());,
51 AMREX_ASSERT(!a_umac[1]->contains_nan());,
52 AMREX_ASSERT(!a_umac[2]->contains_nan()););
53
54 const auto strttime = amrex::second();
55 const Geometry& geom = m_gdb->Geom(a_lev);
56 const auto plo = geom.ProbLoArray();
57 const auto dxi = geom.InvCellSizeArray();
58
59 for (int ipass = 0; ipass < 2; ipass++)
60 {
61#ifdef AMREX_USE_OMP
62#pragma omp parallel if (Gpu::notInLaunchRegion())
63#endif
64 for (ParIterType pti(*this, a_lev); pti.isValid(); ++pti)
65 {
66 int grid = pti.index();
67 auto& ptile = ParticlesAt(a_lev, pti);
68 auto& aos = ptile.GetArrayOfStructs();
69 auto& soa = ptile.GetStructOfArrays();
70 const int n = aos.numParticles();
71 auto *p_pbox = aos().data();
72
73 Array<ParticleReal*,AMREX_SPACEDIM> v_ptr;
74 v_ptr[0] = soa.GetRealData(REMORAParticlesRealIdxSoA::vx).data();
75 v_ptr[1] = soa.GetRealData(REMORAParticlesRealIdxSoA::vy).data();
76 v_ptr[2] = soa.GetRealData(REMORAParticlesRealIdxSoA::vz).data();
77
78 const FArrayBox* fab[AMREX_SPACEDIM] = { AMREX_D_DECL(&((*a_umac[0])[grid]),
79 &((*a_umac[1])[grid]),
80 &((*a_umac[2])[grid])) };
81
82 // Array of these pointers to pass to the GPU
83 GpuArray<Array4<const Real>, AMREX_SPACEDIM>
84 const umacarr {fab[0]->array(), fab[1]->array(), fab[2]->array()};
85
86 bool use_terrain = (a_z_height != nullptr);
87 auto zheight = use_terrain ? (*a_z_height)[grid].array() : Array4<Real>{};
88
89 ParallelFor(n, [=] AMREX_GPU_DEVICE (int i)
90 {
91 ParticleType& p = p_pbox[i];
92 if (p.id() <= 0) { return; }
93
94 ParticleReal v[AMREX_SPACEDIM];
95 if (use_terrain) {
96 mac_interpolate_mapped_z(p, plo, dxi, umacarr, zheight, v);
97 } else {
98 mac_interpolate(p, plo, dxi, umacarr, v);
99 }
100
101 if (ipass == 0) {
102 for (int dim=0; dim < AMREX_SPACEDIM; dim++)
103 {
104 v_ptr[dim][i] = p.pos(dim);
105 p.pos(dim) += static_cast<ParticleReal>(ParticleReal(0.5)*a_dt*v[dim]);
106 }
107 // Update z-coordinate carried by the particle
108 update_location_idata(p,plo,dxi,zheight);
109 } else {
110 for (int dim=0; dim < AMREX_SPACEDIM; dim++)
111 {
112 p.pos(dim) = v_ptr[dim][i] + static_cast<ParticleReal>(a_dt*v[dim]);
113 v_ptr[dim][i] = v[dim];
114 }
115 // Update z-coordinate carried by the particle
116 update_location_idata(p,plo,dxi,zheight);
117 }
118 });
119 }
120 }
121
122 if (m_verbose > 1)
123 {
124 auto stoptime = amrex::second() - strttime;
125
126#ifdef AMREX_LAZY
127 Lazy::QueueReduction( [=] () mutable {
128#endif
129 ParallelReduce::Max(stoptime, ParallelContext::IOProcessorNumberSub(),
130 ParallelContext::CommunicatorSub());
131
132 Print() << "REMORAPC::AdvectWithFlow() time: " << stoptime << '\n';
133#ifdef AMREX_LAZY
134 });
135#endif
136 }
137}
138
139#endif