chombo-discharge
Loading...
Searching...
No Matches
CD_EBParticleMeshImplem.H
Go to the documentation of this file.
1/* chombo-discharge
2 * Copyright © 2021 SINTEF Energy Research.
3 * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4 */
5
12#ifndef CD_EBParticleMeshImplem_H
13#define CD_EBParticleMeshImplem_H
14
15// Chombo includes
16#include <CH_Timer.H>
17
18// Our includes
19#include <CD_EBParticleMesh.H>
20#include <CD_BoxLoops.H>
21#include <CD_ParticleOps.H>
22#include <CD_NamespaceHeader.H>
23
24template <class P, class Ret, Ret (P::*MemberFunc)() const>
25void
27 const List<P>& a_particles,
29 const Real a_widthScale,
30 const bool a_forceIrregNGP) const
31{
32 CH_TIME("EBParticleMesh::deposit");
33 if (m_verbose) {
34 pout() << "EBParticleMesh::deposit" << endl;
35 }
36
37 constexpr int numComp = EBParticleMesh::sanitize<Ret>();
38
39 Real invVol = 1.0;
40 for (int dir = 0; dir < SpaceDim; dir++) {
41 invVol /= m_dx[dir];
42 }
43
44 // These are the default _total_ particle widths.
47
48 const Box cicBox(-1 * IntVect::Unit, 1 * IntVect::Unit);
49 const Box tscBox(-2 * IntVect::Unit, 2 * IntVect::Unit);
50
54
55 // Various scaling factors since particle deposition functions require different normalizations.
56 for (int dir = 0; dir < SpaceDim; dir++) {
57 cicFactor *= 1.0 / cicWidth[dir];
58 tscFactor *= 2.0 / tscWidth[dir];
59 }
60
61 // Switch between deposition types.
62 switch (a_depositionType) {
63 case DepositionType::NGP: {
64 for (ListIterator<P> lit(a_particles); lit.ok(); ++lit) {
65 const Ret w = (lit().*MemberFunc)();
66
67 this->depositParticleNGP(a_meshData, lit().position(), ngpFactor, &w, numComp);
68 }
69
70 break;
71 }
72 case DepositionType::CIC: {
73 for (ListIterator<P> lit(a_particles); lit.ok(); ++lit) {
74 const Ret w = (lit().*MemberFunc)();
75
76 this->depositParticleCIC(a_meshData, lit().position(), cicWidth, cicBox, cicFactor, &w, numComp, a_forceIrregNGP);
77 }
78
79 break;
80 }
81 case DepositionType::TSC: {
82 for (ListIterator<P> lit(a_particles); lit.ok(); ++lit) {
83 const Ret w = (lit().*MemberFunc)();
84
85 this->depositParticleTSC(a_meshData, lit().position(), tscWidth, tscBox, tscFactor, &w, numComp, a_forceIrregNGP);
86 }
87
88 break;
89 }
90 default: {
91 MayDay::Abort("EBParticleMesh::deposit -- logic bust");
92
93 break;
94 }
95 }
96}
97
98template <class P, class Ret, Ret (P::*MemberFunc)()>
99void
101 const EBCellFAB& a_meshData,
103 const bool a_forceIrregNGP) const
104{
105 CH_TIME("EBParticleMesh::interpolate(Real)");
106
107 static_assert(std::is_same<Ret, Real&>::value || std::is_same<Ret, RealVect&>::value,
108 "Ret should be Real& or RealVect&");
109
110 constexpr int numComp = std::is_same<Ret, Real&>::value ? 1 : SpaceDim;
111
112 CH_assert(a_meshData.nComp() == numComp);
113
114 const Interval variables = Interval(0, numComp - 1);
115
116 // validBox is the domain in which we can use the specified interpolation scheme. E.g., TSC fails nears the domain boundaries
117 // since we don't have enough ghost cells to interpolate from.
118 //
119 // gatherBox is the box from which we gather the field.
120 //
123
124 switch (a_interpType) {
125 case DepositionType::NGP: {
126 validBox = m_domain.domainBox();
128
129 break;
130 }
131 case DepositionType::CIC: {
132 validBox = grow(m_domain.domainBox(), -1);
134
135 break;
136 }
137 case DepositionType::TSC: {
138 validBox = grow(m_domain.domainBox(), -2);
140
141 break;
142 }
143 default: {
144 MayDay::Error("EBParticleMesh::interpolate - logic bust");
145 }
146 }
147
152 struct GetPointer
153 {
157 Real*
158 operator()(Real& r) const
159 {
160 return &r;
161 }
162
166 auto
167 operator()(RealVect& r) const
168 {
169 return r.dataPtr();
170 }
171 };
172
173 switch (a_interpType) {
174 case DepositionType::NGP: {
176 auto& p = lit();
177 auto&& w = (p.*MemberFunc)();
178 const auto& x = p.position();
179
181 }
182
183 break;
184 }
185 case DepositionType::CIC: {
187 auto& p = lit();
188 auto&& w = (p.*MemberFunc)();
189 const auto& x = p.position();
190
192 }
193
194 break;
195 }
196 case DepositionType::TSC: {
198 auto& p = lit();
199 auto&& w = (p.*MemberFunc)();
200 const auto& x = p.position();
201
203 }
204
205 break;
206 }
207 default: {
208 MayDay::Abort("EBParticleMesh::interpolate -- logic bust");
209
210 break;
211 }
212 }
213}
214
215inline void
217 const RealVect& a_position,
218 const Real& a_volumeFactor,
219 const Real* a_strength,
220 const int& a_numComp) const noexcept
221{
222 CH_TIME("EBParticleMesh::depositParticleNGP");
223
225
226 CH_assert(m_region.contains(particleIV));
227
228 FArrayBox& rho = a_rho.getFArrayBox();
229
230 for (int comp = 0; comp < a_numComp; comp++) {
232 }
233}
234
235inline void
237 const RealVect& a_position,
239 const Box& a_particleBox,
240 const Real& a_volumeFactor,
241 const Real* a_strength,
242 const int& a_numComp,
243 const bool a_forceIrregNGP) const noexcept
244{
245 CH_TIME("EBParticleMesh::depositParticleCIC");
246
248
249 CH_assert(m_region.contains(particleIV));
250
251 FArrayBox& rho = a_rho.getFArrayBox();
252
253 if (m_ebisbox.isIrregular(particleIV) && a_forceIrregNGP) {
254 for (int comp = 0; comp < a_numComp; comp++) {
256 }
257 }
258 else {
259 auto cicKernel = [&](const IntVect& iv) -> void {
260 Real weight = a_volumeFactor;
261
262 // Below, we've transformed the coordinates so that the cell center of cell iv is at the origin.
263 for (int dir = 0; dir < SpaceDim; dir++) {
264 const Real a = (m_probLo[dir] - a_position[dir]) / m_dx[dir] + iv[dir];
265 const Real b = a + 1.0;
266 const Real L = 0.5 * a_particleWidth[dir];
267
268 weight *= std::max(0.0, std::min(b, L) - std::max(a, -L));
269 }
270
271 for (int comp = 0; comp < a_numComp; comp++) {
272 rho(iv, comp) += weight * a_strength[comp];
273 }
274 };
275
277
279 }
280}
281
282inline void
284 const RealVect& a_position,
286 const Box& a_particleBox,
287 const Real& a_volumeFactor,
288 const Real* a_strength,
289 const int& a_numComp,
290 const bool a_forceIrregNGP) const noexcept
291{
292 CH_TIME("EBParticleMesh::depositParticleTSC");
293
295
296 CH_assert(m_region.contains(particleIV));
297
298 FArrayBox& rho = a_rho.getFArrayBox();
299
300 auto F = [](const Real x) -> Real {
301 const Real a = (x <= 0.0) ? 2 * x * (1 + x) : 2 * x * (1 - x);
302
303 return (std::abs(x) <= 0.5) ? a : 0.0;
304 };
305
306 if (m_ebisbox.isIrregular(particleIV) && a_forceIrregNGP) {
307 for (int comp = 0; comp < a_numComp; comp++) {
309 }
310 }
311 else {
312 auto tscKernel = [&](const IntVect& iv) -> void {
313 Real weight = a_volumeFactor;
314
315 for (int dir = 0; dir < SpaceDim; dir++) {
316 const Real a = (m_probLo[dir] - a_position[dir]) / m_dx[dir] + iv[dir];
317 const Real b = a + 1.0;
318 const Real L = a_particleWidth[dir];
319
320 const Real alpha = std::max(a, -0.5 * L);
321 const Real beta = std::min(b, +0.5 * L);
322 const Real factor = (alpha < beta) ? 1.0 : 0.0;
323
324 weight *= factor * (beta - alpha) - (beta * std::abs(beta) - alpha * std::abs(alpha)) / L;
325 }
326
327 for (int comp = 0; comp < a_numComp; comp++) {
328 rho(iv, comp) += weight * a_strength[comp];
329 }
330 };
331
333
335 }
336}
337
338inline void
340 const EBCellFAB& a_meshData,
341 const RealVect& a_position,
342 const int& a_numComp) const noexcept
343{
344 CH_TIME("EBParticleMesh::interpolateParticleNGP");
345
347 const FArrayBox& meshData = a_meshData.getFArrayBox();
348 const Real factor = m_ebisbox.isCovered(particleIV) ? 0.0 : 1.0;
349
350 for (int comp = 0; comp < a_numComp; comp++) {
352 }
353}
354
355inline void
357 const EBCellFAB& a_meshData,
358 const Box& a_validBox,
359 const Box& a_gatherBox,
360 const RealVect& a_position,
361 const int& a_numComp,
362 const bool a_forceIrregNGP) const noexcept
363{
364 CH_TIME("EBParticleMesh::interpolateParticleCIC");
365
366 // particleIV is the cell index where the particle center lies.
367 // loIndex is the cell index of the lower-left corner of the particle.
369 const IntVect loIndex = ParticleOps::getParticleCellIndex(a_position - 0.5 * m_dx, m_probLo, m_dx);
370
371 CH_assert(m_region.contains(particleIV));
372
373 // Get regular data.
374 const FArrayBox& meshData = a_meshData.getFArrayBox();
375
376 // Reset the particle field.
377 for (int comp = 0; comp < a_numComp; comp++) {
378 a_particleField[comp] = 0.0;
379 }
380
381 // NGP interpolation if called for it, or particle abuts the domain boundary.
382 if ((m_ebisbox.isIrregular(particleIV) && a_forceIrregNGP) || !(a_validBox.contains(particleIV))) {
383 for (int comp = 0; comp < a_numComp; comp++) {
385 }
386 }
387 else if (!(m_ebisbox.isCovered(particleIV))) {
388 auto cicKernel = [&](const IntVect& iv) -> void {
389 Real weight = 1.0;
390
391 const RealVect L = (m_probLo - a_position) / m_dx + (RealVect(iv) + 0.5 * RealVect::Unit);
392
393 for (int dir = 0; dir < SpaceDim; dir++) {
394 weight *= (1. - std::abs(L[dir]));
395 }
396
397 for (int comp = 0; comp < a_numComp; comp++) {
398 a_particleField[comp] += weight * meshData(iv, comp);
399 }
400 };
401
403
405 }
406}
407
408inline void
410 const EBCellFAB& a_meshData,
411 const Box& a_validBox,
412 const Box& a_gatherBox,
413 const RealVect& a_position,
414 const int& a_numComp,
415 const bool a_forceIrregNGP) const noexcept
416{
417 CH_TIME("EBParticleMesh::interpolateParticleTSC");
418
419 // particleIV is the cell index where the particle center lies.
420 // loIndex is the cell index of the lower-left corner of the particle.
422 const IntVect loIndex = ParticleOps::getParticleCellIndex(a_position - m_dx, m_probLo, m_dx);
423
424 CH_assert(m_region.contains(particleIV));
425
426 // Get regular data.
427 const FArrayBox& meshData = a_meshData.getFArrayBox();
428
429 // Reset the particle field.
430 for (int comp = 0; comp < a_numComp; comp++) {
431 a_particleField[comp] = 0.0;
432 }
433
434 // NGP interpolation if called for it, or particle abuts the domain boundary.
435 if ((m_ebisbox.isIrregular(particleIV) && a_forceIrregNGP) || !(a_validBox.contains(particleIV))) {
436 for (int comp = 0; comp < a_numComp; comp++) {
438 }
439 }
440 else if (!(m_ebisbox.isCovered(particleIV))) {
441 auto tscKernel = [&](const IntVect& iv) -> void {
442 Real weight = 1.0;
443
444 const RealVect L = (m_probLo - a_position) / m_dx + (RealVect(iv) + 0.5 * RealVect::Unit);
445
446 for (int dir = 0; dir < SpaceDim; dir++) {
447 const Real& l = std::abs(L[dir]);
448
449 if (l < 0.5) {
450 weight *= 0.75 - l * l;
451 }
452 else {
453 weight *= 0.5 * (1.5 - l) * (1.5 - l);
454 }
455 }
456
457 for (int comp = 0; comp < a_numComp; comp++) {
458 a_particleField[comp] += weight * meshData(iv, comp);
459 }
460 };
461
463
465 }
466}
467
468#include <CD_NamespaceFooter.H>
469
470#endif
Declaration of a namespace for proto-typing grid and EB loops.
DepositionType
Deposition types.
Definition CD_DepositionType.H:23
Declaration of a class for handling particle-mesh interpolation and deposition.
Declaration of a static class containing some common useful particle routines that would otherwise be...
bool m_verbose
Verbose or not.
Definition CD_EBParticleMesh.H:133
void depositParticleCIC(EBCellFAB &a_rho, const RealVect &a_position, const RealVect &a_particleWidth, const Box &a_particleBox, const Real &a_volumeFactor, const Real *a_strength, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
Function for depositing a single particle with a CIC scheme.
Definition CD_EBParticleMeshImplem.H:236
void interpolateParticleNGP(Real *a_particleField, const EBCellFAB &a_meshData, const RealVect &a_position, const int &a_numComp) const noexcept
Particle interpolation function using an NGP scheme.
Definition CD_EBParticleMeshImplem.H:339
void interpolateParticleTSC(Real *a_particleField, const EBCellFAB &a_meshData, const Box &a_validBox, const Box &a_gatherBox, const RealVect &a_position, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
Particle interpolation function using a TSC scheme.
Definition CD_EBParticleMeshImplem.H:409
void depositParticleNGP(EBCellFAB &a_rho, const RealVect &a_position, const Real &a_volumeFactor, const Real *a_strength, const int &a_numComp) const noexcept
Wrapper function for depositing a single particle with a standard NGP scheme.
Definition CD_EBParticleMeshImplem.H:216
void interpolate(List< P > &a_particles, const EBCellFAB &a_meshData, const DepositionType a_interpType, const bool a_forceIrregNGP=false) const
Interpolate mesh data onto a particle.
Definition CD_EBParticleMeshImplem.H:100
void interpolateParticleCIC(Real *a_particleField, const EBCellFAB &a_meshData, const Box &a_validBox, const Box &a_gatherBox, const RealVect &a_position, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
Particle interpolation function using a CIC scheme.
Definition CD_EBParticleMeshImplem.H:356
void depositParticleTSC(EBCellFAB &a_rho, const RealVect &a_position, const RealVect &a_particleWidth, const Box &a_particleBox, const Real &a_volumeFactor, const Real *a_strength, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
Function for depositing a single particle with a TSC scheme.
Definition CD_EBParticleMeshImplem.H:283
RealVect m_dx
Grid resolution.
Definition CD_EBParticleMesh.H:148
ProblemDomain m_domain
Problem domain.
Definition CD_EBParticleMesh.H:128
void deposit(EBCellFAB &a_meshData, const List< P > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP=false) const
Deposit a particle onto the mesh.
Definition CD_EBParticleMeshImplem.H:26
static IntVect getParticleCellIndex(const RealVect &a_particlePosition, const RealVect &a_probLo, const Real &a_dx) noexcept
Get the cell index corresponding to the particle position.
Definition CD_ParticleOpsImplem.H:30
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:37
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:25
ALWAYS_INLINE void loop(const Box &a_computeBox, Functor &&kernel, const IntVect &a_stride=IntVect::Unit)
Launch a C++ kernel over a regular grid.
Definition CD_BoxLoopsImplem.H:20