MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
LPTBase< nDim > Class Template Referenceabstract

#include <lptbase.h>

Inheritance diagram for LPTBase< nDim >:
[legend]
Collaboration diagram for LPTBase< nDim >:
[legend]

Public Types

using BitsetType = maia::lpt::baseProperty::BitsetType
 

Public Member Functions

virtual ~LPTBase ()=default
 
BitsetType::reference hasProperty (const LptBaseProperty p)
 Accessor for properties. More...
 
MBool hasProperty (const LptBaseProperty p) const
 Accessor for properties (const version). More...
 
BitsetType::reference isWindow ()
 
MBool isWindow () const
 
BitsetType::reference reqSend ()
 
MBool reqSend () const
 
BitsetType::reference reqBroadcast ()
 
MBool reqBroadcast () const
 
BitsetType::reference isInvalid ()
 
MBool isInvalid () const
 
BitsetType::reference hasCollided ()
 
MBool hasCollided () const
 
BitsetType::reference hadWallColl ()
 
MBool hadWallColl () const
 
BitsetType::reference firstStep ()
 
MBool firstStep () const
 
BitsetType::reference toBeDeleted ()
 
MBool toBeDeleted () const
 
BitsetType::reference wasSend ()
 
MBool wasSend () const
 
BitsetType::reference toBeRespawn ()
 
MBool toBeRespawn () const
 
BitsetType::reference fullyEvaporated ()
 
MBool fullyEvaporated () const
 
void getNghbrList (std::vector< MInt > &, const MInt)
 
template<MInt a, MInt b>
void interpolateAndCalcWeights (const MInt cellId, const MFloat *const x, MFloat *const result, std::vector< MFloat > &weight, MFloat *const gradientResult=nullptr)
 
virtual void energyEquation ()=0
 
virtual void coupling ()=0
 
virtual void motionEquation ()=0
 
virtual void advanceParticle ()=0
 
virtual void resetWeights ()=0
 
virtual void particleWallCollision ()
 particle-wall collision step More...
 
virtual void wallParticleCollision ()
 wall-particle collision step More...
 
void initProperties ()
 
void checkCellChange (const MFloat *oldPosition, const MBool allowHaloNonLeaf=false)
 Checks whether position is within cell with number cellId if not, cellId is updated. More...
 
void updateProperties (const MBool init=true)
 Update particle properties. More...
 
virtual MFloat effectiveWallCollisionRadius () const
 

Public Attributes

std::array< MFloat, nDim > m_position {}
 
std::array< MFloat, nDim > m_velocity {}
 
std::array< MFloat, nDim > m_accel {}
 
std::array< MFloat, nDim > m_oldPos {}
 particle position of the last time step More...
 
std::array< MFloat, nDim > m_oldVel {}
 particle velocity of the last time step More...
 
MFloat m_densityRatio = -2
 
MLong m_partId = -2
 
MInt m_cellId = -2
 
MInt m_oldCellId = -2
 
MFloat m_creationTime = std::numeric_limits<MFloat>::quiet_NaN()
 creation time modifier More...
 
BitsetType m_properties
 
std::vector< MIntm_neighborList
 

Static Public Attributes

static MInt s_interpolationOrder = 0
 
static MInt s_interpolationMethod = 0
 
static MFloat s_distFactorImp = 0.0
 
static LPT< nDim > * s_backPtr = nullptr
 
static constexpr MInt s_floatElements = 3 * nDim + 1
 
static constexpr MInt s_intElements = 5
 

Detailed Description

template<MInt nDim>
class LPTBase< nDim >

Definition at line 20 of file lptbase.h.

Member Typedef Documentation

◆ BitsetType

template<MInt nDim>
using LPTBase< nDim >::BitsetType = maia::lpt::baseProperty::BitsetType

Definition at line 24 of file lptbase.h.

Constructor & Destructor Documentation

◆ ~LPTBase()

template<MInt nDim>
virtual LPTBase< nDim >::~LPTBase ( )
virtualdefault

Member Function Documentation

◆ advanceParticle()

template<MInt nDim>
virtual void LPTBase< nDim >::advanceParticle ( )
pure virtual

◆ checkCellChange()

template<MInt nDim>
void LPTBase< nDim >::checkCellChange ( const MFloat oldPosition,
const MBool  allowHaloNonLeaf = false 
)
Author
Rudie Kunnen, Sven Berger, Tim Wegmann

Definition at line 233 of file lptbase.cpp.

233 {
234 TRACE();
235
236 // no cell change when the position is identical
237 if(oldPosition != nullptr
238 && std::abs(m_position[0] - oldPosition[0]) + std::abs(m_position[1] - oldPosition[1])
239 + std::abs(m_position[2] - oldPosition[2])
240 < 1E-12) {
241 return;
242 }
243
244 if(m_cellId != -1) m_cellId = s_backPtr->grid().findContainingLeafCell(m_position.data(), m_cellId, true);
245
246 if(allowHaloNonLeaf && m_cellId < 0) {
247 mTerm(1, AT_, "Invalid cell during injection! Send not possible, broadcast required!");
248 }
249
250 if(m_cellId > 0 && !s_backPtr->c_isLeafCell(m_cellId)) {
251 if(!allowHaloNonLeaf) {
252 m_cellId = -1;
253 } else {
254 reqSend() = true;
255 isInvalid() = false;
256 return;
257 }
258 }
259
260 // a ghost particle may never become a real particle!
261 auto partWasHalo = wasSend();
262 // no valid cell found left geometry
263 if(m_cellId < 0 || (!partWasHalo && !s_backPtr->a_isValidCell(m_cellId))) {
264 toBeDeleted() = true;
265 toBeRespawn() = true;
266 isInvalid() = true;
267 return;
268 }
269
270 // for multisolver, check whether the current cellId is a solver interface cell
271 const MBool origCellIsHaloCell = s_backPtr->a_isHalo(m_cellId);
272 const MBool origCellIsPeriodicHaloCell = s_backPtr->grid().isPeriodic(m_cellId);
273 if(globalNoDomains() > 1) {
274 // active particles may move to other solvers
275 if(!isInvalid()) {
276 // check whether particle changes solvers
277 if(origCellIsHaloCell) {
278 reqSend() = true;
279 isWindow() = false;
280 }
281
282 // check whether particle changes solvers in periodic direction
283 if(origCellIsPeriodicHaloCell) {
284 isWindow() = false;
285 isInvalid() = true;
286 reqSend() = true;
287 }
288
289 isWindow() = s_backPtr->a_isWindow(m_cellId);
290 }
291 }
292}
BitsetType::reference toBeRespawn()
Definition: lptbase.h:208
static LPT< nDim > * s_backPtr
Definition: lptbase.h:29
std::array< MFloat, nDim > m_position
Definition: lptbase.h:34
BitsetType::reference wasSend()
Definition: lptbase.h:199
BitsetType::reference isWindow()
Definition: lptbase.h:124
BitsetType::reference toBeDeleted()
Definition: lptbase.h:189
BitsetType::reference reqSend()
Definition: lptbase.h:133
MInt m_cellId
Definition: lptbase.h:46
BitsetType::reference isInvalid()
Definition: lptbase.h:151
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
MInt globalNoDomains()
Return global number of domains.
bool MBool
Definition: maiatypes.h:58

◆ coupling()

template<MInt nDim>
virtual void LPTBase< nDim >::coupling ( )
pure virtual

◆ effectiveWallCollisionRadius()

template<MInt nDim>
virtual MFloat LPTBase< nDim >::effectiveWallCollisionRadius ( ) const
inlinevirtual

Reimplemented in LPTEllipsoidal< nDim >, and LPTSpherical< nDim >.

Definition at line 104 of file lptbase.h.

104{ TERMM(-1, "Effective wall collision radius not implemented!"); }

◆ energyEquation()

template<MInt nDim>
virtual void LPTBase< nDim >::energyEquation ( )
pure virtual

◆ firstStep() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::firstStep

Definition at line 179 of file lptbase.h.

179 {
180 return hasProperty(LptBaseProperty::FirstStep);
181}
BitsetType::reference hasProperty(const LptBaseProperty p)
Accessor for properties.
Definition: lptbase.h:109

◆ firstStep() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::firstStep

Definition at line 174 of file lptbase.h.

174 {
175 return hasProperty(LptBaseProperty::FirstStep);
176}

◆ fullyEvaporated() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::fullyEvaporated

Definition at line 218 of file lptbase.h.

218 {
219 return hasProperty(LptBaseProperty::FullyEvaporated);
220}

◆ fullyEvaporated() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::fullyEvaporated

Definition at line 213 of file lptbase.h.

213 {
214 return hasProperty(LptBaseProperty::FullyEvaporated);
215}

◆ getNghbrList()

template<MInt nDim>
void LPTBase< nDim >::getNghbrList ( std::vector< MInt > &  neighborList,
const MInt  cellId 
)

Get the neighborlist from the Lagrange particle container object

Parameters
neighborListList of the neighboring cells
cellIdGet neighbors of this cell

Definition at line 183 of file lptbase.cpp.

183 {
184 ASSERT(cellId >= 0, "Invalid cellId!");
185
186 static const MInt noOfRedistLayers = (s_backPtr->m_noRedistLayer > 0) ? s_backPtr->m_noRedistLayer : 2;
187
188 MUint additionalLayers = 0;
189
190 if(s_backPtr->a_volumeFraction(m_cellId) > 0.75) {
191 // use further redistribution of source-terms for packed cells
192 // TODO labels:LPT otherwise include particel-particle interaction and shift particles into neighboring cells!
193 additionalLayers = 1;
194 } else if(!m_neighborList.empty() && m_neighborList[0] == cellId && !s_backPtr->a_isBndryCell(cellId)) {
195 // still current no need to update
196 return;
197 }
198
199
200#ifdef _OPENMP
201#pragma omp critical
202#endif
203 {
204 if(s_backPtr->m_cellToNghbrHood.count(cellId) > 0
205 && s_backPtr->m_cellToNghbrHood[cellId].size() >= 50 * additionalLayers) {
206 // cell neighbor cells are already known, including additionalLayers
207 neighborList = s_backPtr->m_cellToNghbrHood[cellId];
208 } else {
209 if(s_backPtr->m_cellToNghbrHood.count(cellId) > 0 && additionalLayers > 0) {
210 // cell neighbors known, but increased to consider additional layers
211 s_backPtr->m_cellToNghbrHood.erase(cellId);
212 }
213 neighborList.clear();
214
215 // cells neighbor's are unknown
216 std::vector<MInt> neighborListGrid;
217 s_backPtr->grid().findNeighborHood(cellId, noOfRedistLayers + additionalLayers, neighborListGrid);
218 for(MInt i = 0; i < (signed)neighborListGrid.size(); i++) {
219 if(s_backPtr->a_isValidCell(neighborListGrid[i])) {
220 neighborList.push_back(neighborListGrid[i]);
221 }
222 }
223 s_backPtr->m_cellToNghbrHood.emplace(make_pair(cellId, neighborList));
224 }
225 }
226}
std::vector< MInt > m_neighborList
Definition: lptbase.h:82
int32_t MInt
Definition: maiatypes.h:62
uint32_t MUint
Definition: maiatypes.h:63
void const MInt cellId
Definition: collector.h:239

◆ hadWallColl() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::hadWallColl

Definition at line 169 of file lptbase.h.

169 {
170 return hasProperty(LptBaseProperty::HadWallColl);
171}

◆ hadWallColl() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::hadWallColl

Definition at line 164 of file lptbase.h.

164 {
165 return hasProperty(LptBaseProperty::HadWallColl);
166}

◆ hasCollided() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::hasCollided

Definition at line 160 of file lptbase.h.

160 {
161 return hasProperty(LptBaseProperty::HasCollided);
162}

◆ hasCollided() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::hasCollided

Definition at line 155 of file lptbase.h.

155 {
156 return hasProperty(LptBaseProperty::HasCollided);
157}

◆ hasProperty() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::hasProperty ( const LptBaseProperty  p)

Definition at line 109 of file lptbase.h.

109 {
111}
BitsetType m_properties
Definition: lptbase.h:52
constexpr std::underlying_type< LptBaseProperty >::type p(const LptBaseProperty property)
Converts property name to underlying integer value.

◆ hasProperty() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::hasProperty ( const LptBaseProperty  p) const

Definition at line 114 of file lptbase.h.

114 {
116}

◆ initProperties()

template<MInt nDim>
void LPTBase< nDim >::initProperties

Definition at line 223 of file lptbase.h.

223 {
224 isWindow() = false;
225 reqSend() = false;
226 reqBroadcast() = false;
227 isInvalid() = false;
228 hasCollided() = false;
229 firstStep() = false;
230 toBeDeleted() = false;
231 wasSend() = false;
232 toBeRespawn() = false;
233 fullyEvaporated() = false;
234 hadWallColl() = false;
235}
BitsetType::reference firstStep()
Definition: lptbase.h:179
BitsetType::reference hadWallColl()
Definition: lptbase.h:169
BitsetType::reference hasCollided()
Definition: lptbase.h:160
BitsetType::reference reqBroadcast()
Definition: lptbase.h:142
BitsetType::reference fullyEvaporated()
Definition: lptbase.h:218

◆ interpolateAndCalcWeights()

template<MInt nDim>
template<MInt a, MInt b>
template void LPTBase< nDim >::interpolateAndCalcWeights< 0, 7 > ( const MInt  cellId,
const MFloat *const  x,
MFloat *const  result,
std::vector< MFloat > &  weight,
MFloat *const  gradientResult = nullptr 
)

Definition at line 24 of file lptbase.cpp.

25 {
26 std::vector<MInt>* nghbrL = nullptr;
27 std::vector<MInt> tmp;
28 if(cellId == m_cellId) {
30 nghbrL = &m_neighborList;
31 } else {
32 getNghbrList(tmp, cellId);
33 nghbrL = &tmp;
34 }
35
36
37 // calculate weights
38 if(s_interpolationOrder > 0 || s_backPtr->m_couplingRedist) {
39 // calculate weights of the redistribution
40 const auto noNghbr = static_cast<MUint>(nghbrL->size());
41
42 // higher values means a sharper fall off
43 // static constexpr MFloat distFactorImp = 0.5;
44 // static constexpr MInt s_interpolationMethod = 2;//default was 1;
45
46 if(noNghbr > 0 && (s_interpolationMethod > 0 || noNghbr != weight.size())) {
47 MFloat sumImp = 0.0;
48 weight.clear();
49 for(MUint n = 0; n < noNghbr; n++) {
50 MFloat dx = 0;
51 if(s_interpolationMethod > 0) {
52 for(MInt i = 0; i < nDim; i++) {
53 const MFloat coord = s_backPtr->a_coordinate(nghbrL->at(n), i);
54 dx += POW2(coord - x[i]) + MFloatEps;
55 }
56 }
57
58 switch(s_interpolationMethod) {
59 case 0:
60 // average overall cells
61 weight.push_back(1.0);
62 break;
63 case 1:
64 // linear
65 weight.push_back(1.0 / dx);
66 break;
67 case 2: {
68 // normal distribution
69 const MFloat cellLength = s_backPtr->c_cellLengthAtLevel(s_backPtr->c_level(m_cellId));
70 // higher values means a sharper fall off
71 MFloat distFactorImp = s_distFactorImp;
72 if(s_backPtr->m_engineSetup && s_backPtr->a_coordinate(m_cellId, 1) > 0.05) {
73 distFactorImp = 0.25;
74 }
75 weight.push_back(exp(-distFactorImp * dx / POW2(cellLength)));
76 break;
77 }
78 default:
79 TERMM(-1, "Invalid interpolation method.");
80 }
81 sumImp += weight.back();
82 ASSERT(!std::isnan(weight.back()), "ERROR: Weight is NaN with dx = " + std::to_string(dx) + "!");
83 }
84
85 // normalize weights
86 for(MUint n = 0; n < noNghbr; n++) {
87 weight.at(n) /= sumImp;
88 }
89 }
90 }
91
92 if(b == 0) return;
93
94 MInt c = b;
95 if(b > s_backPtr->PV.noVars()) {
96 c = b - 1;
97 }
98
99 switch(s_interpolationOrder) {
100 case 0:
101 // use current cell value
102 for(MInt i = a; i < c; i++) {
103 result[i] = s_backPtr->a_fluidVariable(cellId, i);
104 }
105 if(b > s_backPtr->PV.noVars()) {
106 result[c] = s_backPtr->a_fluidSpecies(cellId);
107 }
108 break;
109 case 1: {
110 // linear interpolation
111 MUint n = 0;
112 for(auto nghbrId : *nghbrL) {
113 for(MInt i = a; i < c; i++) {
114 result[i] += weight[n] * s_backPtr->a_fluidVariable(nghbrId, i);
115 }
116 if(b > s_backPtr->PV.noVars()) {
117 result[c] += weight[n] * s_backPtr->a_fluidSpecies(nghbrId);
118 }
119 n++;
120 }
121 break;
122 }
123 case 2:
124 case 3:
125 // is used by ellipsoids
126 // least-square interpolation
127 {
128 if(b > s_backPtr->PV.noVars()) mTerm(1, AT_, "Not implemented yet!");
129 if(gradientResult) {
130 std::array<MFloat, b + nDim * nDim> tempResults;
131 s_backPtr->template interpolateVariablesLS<a, b, true>(cellId, x, tempResults.data());
132 for(MInt i = a; i < c; i++) {
133 result[i - a] = tempResults[i];
134 }
135 for(MInt i = 0; i < nDim * nDim; i++) {
136 gradientResult[i] = tempResults[c + i];
137 }
138 } else
139 s_backPtr->template interpolateVariablesLS<a, b>(cellId, x, result);
140 }
141 break;
142 default:
143 TERMM(-1, "Invalid interpolation order.");
144 }
145}
static MInt s_interpolationOrder
Definition: lptbase.h:26
static MInt s_interpolationMethod
Definition: lptbase.h:27
void getNghbrList(std::vector< MInt > &, const MInt)
Definition: lptbase.cpp:183
static MFloat s_distFactorImp
Definition: lptbase.h:28
constexpr Real POW2(const Real x)
Definition: functions.h:119
double MFloat
Definition: maiatypes.h:52
Definition: contexttypes.h:19

◆ isInvalid() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::isInvalid

Definition at line 151 of file lptbase.h.

151 {
152 return hasProperty(LptBaseProperty::IsInvalid);
153}

◆ isInvalid() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::isInvalid

Definition at line 146 of file lptbase.h.

146 {
147 return hasProperty(LptBaseProperty::IsInvalid);
148}

◆ isWindow() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::isWindow

Definition at line 124 of file lptbase.h.

124 {
125 return hasProperty(LptBaseProperty::IsWindow);
126}

◆ isWindow() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::isWindow

Definition at line 119 of file lptbase.h.

119 {
120 return hasProperty(LptBaseProperty::IsWindow);
121}

◆ motionEquation()

template<MInt nDim>
virtual void LPTBase< nDim >::motionEquation ( )
pure virtual

◆ particleWallCollision()

template<MInt nDim>
void LPTBase< nDim >::particleWallCollision
virtual
Author
Sven Berger , Tim Wegmann, Laurent Andre
Date
June 2016, Jan 2021, Nov 2023

Definition at line 319 of file lptbase.cpp.

319 {
320#ifdef LPT_DEBUG
321 MLong debugPartId = -1;
322#endif
323
324 const MFloat dt = s_backPtr->m_timeStep - m_creationTime;
325
326 const MInt bndId = s_backPtr->a_bndryCellId(m_cellId) > -1 ? s_backPtr->a_bndryCellId(m_cellId)
327 : s_backPtr->a_bndryCellId(m_oldCellId);
328
329 if(bndId < 0) return;
330
331 const MInt lastValidCellId =
332 s_backPtr->a_isValidCell(m_cellId) ? m_cellId : s_backPtr->a_isValidCell(m_oldCellId) ? m_oldCellId : -1;
333
334 const MFloat radius = effectiveWallCollisionRadius();
335
336 std::array<MFloat, nDim> bodyVel{};
337 MFloat nBodyVel = 0;
338 for(MInt i = 0; i < nDim; i++) {
339 nBodyVel += s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i]
340 * s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i];
341 }
342 if(nBodyVel > 0) {
343 for(MInt i = 0; i < nDim; i++) {
344 bodyVel[i] = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i];
345 }
346 } else {
347 for(MInt i = 0; i < nDim; i++) {
348 bodyVel[i] = 0.0;
349 }
350 }
351
352 MFloat nx0 = 0.0;
353 MFloat na = 0.0;
354 MFloat nb = 0.0;
355
356 ASSERT(s_backPtr->m_bndryCells->a[bndId].m_noSrfcs == 1, "Not implemented for multiple surfaces yet!");
357
358 std::array<MFloat, nDim> deltaX{};
359 for(MInt i = 0; i < nDim; i++) {
360 deltaX[i] = m_position[i] - m_oldPos[i];
361 nx0 += s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i]
362 * s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[i];
363 na += s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i] * m_oldPos[i];
364 nb += s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i] * deltaX[i];
365 }
366
367 // We have a geometrical overlap if (x(t) - x_surf)*normal_surf < particle radius for t in [0, dt].
368 // Using for x(t) = x_oldPos + t * deltaX/dt and solving for lambda=t/dt
369 MFloat lambda = (nx0 - na + radius) / nb;
370
371 // 1) check if a wall-collision happened within the timestep (lambda < 1.0)
372 // meaning that the oldPosition and position lie on different sides of the wall
373 // * lambda > 1.0 means the collision will not happen in this timestep
374 // * lambda < 0.0 means the particle is outside might need to be pushed back inside
375 // * nb > 0.0, means particle is already moving back in
376 if(lambda > 1.0 || nb > 0.0) {
377 return;
378 }
379
380 const MFloat calculatedLambda = lambda;
381 // If collision happened already, limit lamba= to -1 (i.e. one timestep)
382 if(lambda < -1.0) lambda = -1.0;
383
384 // position of the particle-wall collision
385 std::array<MFloat, nDim> oldC{};
386 for(MInt i = 0; i < nDim; i++) {
387 oldC[i] = m_oldPos[i] + lambda * deltaX[i];
388 }
389
390 // considered particle velocity for the wall-collision step
391 std::array<MFloat, nDim> usedVel{};
392 MFloat velMag = 0;
393 for(MInt i = 0; i < nDim; i++) {
394 usedVel[i] = deltaX[i] / dt;
395 velMag += POW2(usedVel[i]);
396 }
397 velMag = sqrt(velMag);
398
399#ifdef LPT_DEBUG
400 if(m_partId == debugPartId) {
401 if(velMag > 0.65) {
402 std::cerr << "Large velocity!" << velMag << " " << m_partId << " " << m_position[0] << " " << m_position[1] << " "
403 << m_position[2] << " " << m_velocity[0] << " " << m_velocity[1] << " " << m_velocity[2] << " "
404 << radius << std::endl;
405 }
406 }
407#endif
408
409 // 2) compute the basis w.r.t. the boundary surface and its inverse
410 // for the coordinate transformations
411 std::array<MFloat, nDim> n{};
412 std::array<MFloat, nDim> u{};
413 std::array<MFloat, nDim> v{};
414 for(MInt i = 0; i < nDim; i++) {
415 n[i] = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i];
416 u[i] = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_planeCoordinates[1][i]
417 - s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_planeCoordinates[0][i];
418 v[i] = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_planeCoordinates[2][i]
419 - s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_planeCoordinates[0][i];
420 }
421 // normalize the basis vector (normal vector n is already normalized)
422 maia::math::normalize(u.data(), nDim);
423 maia::math::normalize(v.data(), nDim);
424 // gram-schmidt orthogonalization of u and v
425 MFloat dotProductUV = std::inner_product(u.begin(), u.end(), v.begin(), 0.0);
426 for(MInt i = 0; i < nDim; ++i) {
427 v[i] -= dotProductUV * u[i];
428 }
429 // normalize v again
430 maia::math::normalize(v.data(), nDim);
431
432 // construct the basis matrix and its inverse
433 std::array<std::array<MFloat, nDim>, nDim> bndryBasis{};
434 MFloatScratchSpace inverse(nDim, nDim, AT_, "inverse");
435 for(MInt i = 0; i < nDim; i++) {
436 bndryBasis[i][0] = n[i];
437 bndryBasis[i][1] = u[i];
438 bndryBasis[i][2] = v[i];
439 for(MInt j = 0; j < nDim; j++) {
440 inverse(i, j) = bndryBasis[i][j];
441 }
442 }
443 // NOTE: inverse might not be normalized correctly, i.e. magnitude is not conserved!
444 maia::math::invert(&inverse(0, 0), 3, 3);
445
446#ifdef LPT_DEBUG
447 if(m_partId == debugPartId) {
448 std::cerr << "Basis: " << std::endl;
449 std::cerr << " " << bndryBasis[0][0] << " " << bndryBasis[0][1] << " " << bndryBasis[0][2] << std::endl;
450 std::cerr << " " << bndryBasis[1][0] << " " << bndryBasis[1][1] << " " << bndryBasis[1][2] << std::endl;
451 std::cerr << " " << bndryBasis[2][0] << " " << bndryBasis[2][1] << " " << bndryBasis[2][2] << std::endl;
452
453 std::cerr << "Invert: " << std::endl;
454 std::cerr << " " << inverse(0, 0) << " " << inverse(0, 1) << " " << inverse(0, 2) << std::endl;
455 std::cerr << " " << inverse(1, 0) << " " << inverse(1, 1) << " " << inverse(1, 2) << std::endl;
456 std::cerr << " " << inverse(2, 0) << " " << inverse(2, 1) << " " << inverse(2, 2) << std::endl;
457
458 std::array<MFloat, nDim> a1{};
459 std::array<MFloat, nDim> a2{};
460 std::array<MFloat, nDim> a3{};
461
462 for(MInt i = 0; i < nDim; i++) {
463 a1[i] = inverse(i, 0);
464 a2[i] = inverse(i, 1);
465 a3[i] = inverse(i, 2);
466 }
467
468 maia::math::normalize(&a1[0], nDim);
469 maia::math::normalize(&a2[0], nDim);
470 maia::math::normalize(&a3[0], nDim);
471
472
473 MFloatScratchSpace inverse2(nDim, nDim, AT_, "inverse");
474 // for(MInt i = 0; i < nDim; i++){
475 // for(MInt j = 0; j < nDim; j++){
476 // inverse2(i,j) = inverse(i,j);
477 // }
478 //}
479
480 for(MInt i = 0; i < nDim; i++) {
481 inverse2(i, 0) = a1[i];
482 inverse2(i, 1) = a2[i];
483 inverse2(i, 2) = a3[i];
484 }
485
486 std::cerr << "Invert2:" << std::endl;
487 std::cerr << " " << inverse2(0, 0) << " " << inverse2(0, 1) << " " << inverse2(0, 2) << std::endl;
488 std::cerr << " " << inverse2(1, 0) << " " << inverse2(1, 1) << " " << inverse2(1, 2) << std::endl;
489 std::cerr << " " << inverse2(2, 0) << " " << inverse2(2, 1) << " " << inverse2(2, 2) << std::endl;
490
491 maia::math::invert(&inverse2(0, 0), 3, 3);
492
493 std::cerr << "Invert3:" << std::endl;
494 std::cerr << " " << inverse2(0, 0) << " " << inverse2(0, 1) << " " << inverse2(0, 2) << std::endl;
495 std::cerr << " " << inverse2(1, 0) << " " << inverse2(1, 1) << " " << inverse2(1, 2) << std::endl;
496 std::cerr << " " << inverse2(2, 0) << " " << inverse2(2, 1) << " " << inverse2(2, 2) << std::endl;
497 }
498#endif
499
500 // 3) transform the particle velocity into the boundary coordinate system (forward transformation)
501 std::array<MFloat, nDim> localVel{};
502 for(MInt i = 0; i < nDim; i++) {
503 localVel[i] = 0;
504 }
505 for(MInt i = 0; i < nDim; i++) {
506 for(MInt j = 0; j < nDim; j++) {
507 localVel[i] += inverse(i, j) * usedVel[j];
508 }
509 }
510
511 // 4) Compute rebound velocity by mirrowing the component normal to the boundary
512 // and adding the slip velocity of the wall
513 std::array<MFloat, nDim> localReboundVel{};
514 localReboundVel[0] = -localVel[0];
515 for(MInt i = 1; i < nDim; i++) {
516 localReboundVel[i] = localVel[i];
517 }
518
519#ifdef LPT_DEBUG
520 if(m_partId == debugPartId) {
521 std::cerr << "RB " << localReboundVel[0] << " " << localReboundVel[1] << " " << localReboundVel[nDim - 1] << " "
522 << velMag << std::endl;
523 }
524#endif
525
526 // 5) Backwards transformation of the rebound velocity into the x,y,z coordinate system
527 std::array<MFloat, nDim> reboundVel{};
528 for(MInt i = 0; i < nDim; i++) {
529 reboundVel[i] = 0.0;
530 for(MInt j = 0; j < nDim; j++) {
531 reboundVel[i] += bndryBasis[i][j] * localReboundVel[j];
532 }
533 }
534 maia::math::normalize(reboundVel.data(), nDim);
535 for(MInt i = 0; i < nDim; i++) {
536 reboundVel[i] *= velMag;
537 }
538 for(MInt i = 0; i < nDim; i++) {
539 m_oldVel[i] = reboundVel[i] + bodyVel[i];
540 m_velocity[i] = reboundVel[i] + bodyVel[i];
541 m_accel[i] = 0.0;
542 }
543
544 // 6) Computation of the new particle position
545 if(lambda > 0.0) { // and < 1.0
546 for(MInt i = 0; i < nDim; i++) {
547 m_position[i] = oldC[i] + (1.0 - lambda) * dt * m_oldVel[i];
548 }
549 } else {
550 // Particle is outside domain or at least overlapping with the surface
551 // --> move particle back to the surface using translation in normal direction
552 MFloat normalDistance = F0;
553 for(MInt i = 0; i < nDim; i++) {
554 MFloat surfNormal = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i];
555 MFloat surfCoord = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[i];
556 normalDistance += surfNormal * (m_oldPos[i] - surfCoord);
557 }
558 for(MInt i = 0; i < nDim; i++) {
559 MFloat surfNormal = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i];
560 m_position[i] = m_oldPos[i] + (radius - normalDistance) * surfNormal;
561 }
562 }
563
564 // 7) update the new cellId and check if the particle should be communicated
565 this->initProperties();
566 hadWallColl() = true;
568
569 // if the push-back is over-extended and the particle moves out-side of an opposide surface/cell
570 // the push-back is reduced to the surface
571 if(lambda <= 0.0 && (m_cellId < 0 || m_cellId > s_backPtr->a_noCells() - 1 || !s_backPtr->a_isValidCell(m_cellId))) {
572 m_cellId = lastValidCellId;
573 for(MInt i = 0; i < nDim; i++) {
574 m_position[i] = oldC[i];
575 }
576 this->initProperties();
577 hadWallColl() = true;
579 std::cerr << "Push back failed for particle " << m_partId << ". Reducing it to surface."
580 << " newPos: " << m_cellId << " " << m_position[0] << " " << m_position[1] << " " << m_position[nDim - 1]
581 << std::endl;
582
583 // if new position is still invalid but old position was valid, move the particle back to that position
584 if(s_backPtr->a_isValidCell(m_oldCellId)
585 && (m_cellId < 0 || m_cellId > s_backPtr->a_noCells() - 1 || !s_backPtr->a_isValidCell(m_cellId))) {
586 m_cellId = lastValidCellId;
587 for(MInt i = 0; i < nDim; i++) {
588 m_position[i] = m_oldPos[i];
589 }
590 this->initProperties();
591 hadWallColl() = true;
593 std::cerr << "Push back failed again for particle " << m_partId << ". Resetting particle to old position."
594 << " newPos: " << m_cellId << " " << m_position[0] << " " << m_position[1] << " "
595 << m_position[nDim - 1] << std::endl;
596
597 if(m_cellId < 0 || m_cellId > s_backPtr->a_noCells() - 1 || !s_backPtr->a_isValidCell(m_cellId)) {
598 std::cerr << "Push back for particle " << m_partId << " kept failing. Particle could not be rescued."
599 << std::endl;
600 }
601 }
602 }
603
604 // 8) compute old particle coordinate, based on backwards movement from the collision
605 // meaning the position, the particle would have had with current velocity and
606 // without wall interaction
607 for(MInt i = 0; i < nDim; i++) {
608 if(lambda > 0.0) {
609 m_oldPos[i] = oldC[i] + (lambda - 1.0) * dt * m_oldVel[i];
610 } else {
611 m_oldPos[i] = m_position[i] - dt * m_oldVel[i];
612 }
613 }
614
615#ifdef LPT_DEBUG
616 if(m_partId == debugPartId) {
617 std::cerr << "AC " << m_velocity[0] << " " << m_velocity[1] << " " << m_velocity[2] << std::endl;
618 }
619#endif
620
621 if(m_cellId < 0 || m_cellId > s_backPtr->a_noCells() - 1 || !s_backPtr->a_isValidCell(m_cellId)) {
622 std::cerr << "Particle at invalid cell after collision " << m_cellId << std::endl;
623 if(m_cellId > 0 && m_cellId < s_backPtr->a_noCells()) {
624 std::cerr << s_backPtr->a_isValidCell(m_cellId) << std::endl;
625 }
626 std::cerr << " " << lastValidCellId << " " << s_backPtr->a_isValidCell(m_oldCellId) << " " << calculatedLambda
627 << " newPos " << m_position[0] << " " << m_position[1] << " " << m_position[nDim - 1] << " "
628 << s_backPtr->domainId() << " " << m_partId << std::endl;
629 std::cerr << "new-OldPos " << m_oldPos[0] << " " << m_oldPos[1] << " " << m_oldPos[nDim - 1] << std::endl;
630 std::cerr << "Surface " << s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[0] << " "
631 << s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[1] << " "
632 << s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[nDim - 1] << std::endl;
633 std::cerr << "S-n " << s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[0] << " "
634 << s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[1] << " "
635 << s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[nDim - 1] << std::endl;
636 std::cerr << "CollP " << oldC[0] << " " << oldC[1] << " " << oldC[nDim - 1] << std::endl;
637 std::cerr << " deltaX " << deltaX[0] << " " << deltaX[1] << " " << deltaX[nDim - 1] << std::endl;
638 std::cerr << "Vel1 " << usedVel[0] << " " << usedVel[1] << " " << usedVel[nDim - 1] << std::endl;
639 std::cerr << "Vel2 " << m_oldVel[0] << " " << m_oldVel[1] << " " << m_oldVel[nDim - 1] << std::endl;
640 std::cerr << "RbVel " << reboundVel[0] << " " << reboundVel[1] << " " << reboundVel[nDim - 1] << std::endl;
641 isInvalid() = true;
642 reqSend() = false;
643 } else {
644 // ensure communication even-though the particle was already in a halo-cell
645 if(s_backPtr->a_isHalo(m_cellId)) {
646 reqSend() = true;
647 isWindow() = false;
648 }
649 }
650}
virtual MFloat effectiveWallCollisionRadius() const
Definition: lptbase.h:104
MFloat m_creationTime
creation time modifier
Definition: lptbase.h:50
MLong m_partId
Definition: lptbase.h:45
std::array< MFloat, nDim > m_velocity
Definition: lptbase.h:35
std::array< MFloat, nDim > m_oldPos
particle position of the last time step
Definition: lptbase.h:39
MInt m_oldCellId
Definition: lptbase.h:47
std::array< MFloat, nDim > m_oldVel
particle velocity of the last time step
Definition: lptbase.h:41
void initProperties()
Definition: lptbase.h:223
void checkCellChange(const MFloat *oldPosition, const MBool allowHaloNonLeaf=false)
Checks whether position is within cell with number cellId if not, cellId is updated.
Definition: lptbase.cpp:233
std::array< MFloat, nDim > m_accel
Definition: lptbase.h:36
This class is a ScratchSpace.
Definition: scratch.h:758
int64_t MLong
Definition: maiatypes.h:64
void invert(MFloat *A, const MInt m, const MInt n)
Definition: maiamath.cpp:171
void normalize(std::array< T, N > &u)
Definition: maiamath.h:191
MInt inverse(MFloat **a, MFloat **ainv, MInt n, const MFloat epsilon)
Definition: maiamath.h:587

◆ reqBroadcast() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::reqBroadcast

Definition at line 142 of file lptbase.h.

142 {
143 return hasProperty(LptBaseProperty::ReqBroadcast);
144}

◆ reqBroadcast() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::reqBroadcast

Definition at line 137 of file lptbase.h.

137 {
138 return hasProperty(LptBaseProperty::ReqBroadcast);
139}

◆ reqSend() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::reqSend

Definition at line 133 of file lptbase.h.

133 {
134 return hasProperty(LptBaseProperty::ReqSend);
135}

◆ reqSend() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::reqSend

Definition at line 128 of file lptbase.h.

128 {
129 return hasProperty(LptBaseProperty::ReqSend);
130}

◆ resetWeights()

template<MInt nDim>
virtual void LPTBase< nDim >::resetWeights ( )
pure virtual

◆ toBeDeleted() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::toBeDeleted

Definition at line 189 of file lptbase.h.

189 {
190 return hasProperty(LptBaseProperty::ToBeDeleted);
191}

◆ toBeDeleted() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::toBeDeleted

Definition at line 184 of file lptbase.h.

184 {
185 return hasProperty(LptBaseProperty::ToBeDeleted);
186}

◆ toBeRespawn() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::toBeRespawn

Definition at line 208 of file lptbase.h.

208 {
209 return hasProperty(LptBaseProperty::ToBeRespawn);
210}

◆ toBeRespawn() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::toBeRespawn

Definition at line 203 of file lptbase.h.

203 {
204 return hasProperty(LptBaseProperty::ToBeRespawn);
205}

◆ updateProperties()

template<MInt nDim>
void LPTBase< nDim >::updateProperties ( const MBool  init = true)
Author
Tim Wegmann
Date
Aug 2021

Definition at line 299 of file lptbase.cpp.

299 {
300 if(init) {
302 }
303
304
305 if(s_backPtr->noDomains() > 1) {
306 if(s_backPtr->a_isHalo(m_cellId)) {
307 reqSend() = true;
308 isInvalid() = true;
309 } else if(s_backPtr->a_isWindow(m_cellId)) {
310 isWindow() = true;
311 }
312 }
313}

◆ wallParticleCollision()

template<MInt nDim>
void LPTBase< nDim >::wallParticleCollision
virtual
Author
Tim Wegmann
Date
Sep 2022

Definition at line 656 of file lptbase.cpp.

656 {
657 const MFloat dt = s_backPtr->m_timeStep;
658
659 const MInt bndId = s_backPtr->a_bndryCellId(m_cellId) > -1 ? s_backPtr->a_bndryCellId(m_cellId)
660 : s_backPtr->a_bndryCellId(m_oldCellId);
661
662 if(bndId < 0) return;
663 if(isInvalid()) return;
664 if(hadWallColl()) return;
665
666 MFloat bodyVelMag = 0;
667 MFloat nBodyVel = 0;
668 for(MInt i = 0; i < nDim; i++) {
669 bodyVelMag += POW2(s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i]);
670 nBodyVel += s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i]
671 * s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i];
672 }
673 bodyVelMag = sqrt(bodyVelMag);
674
675 // stationary or out-ward moving body
676 // body-velocity is only added when moving inward i.e. during compression stroke!
677 if(bodyVelMag < MFloatEps || nBodyVel < 0) return;
678
679 MFloat nx0 = 0.0;
680
681 std::array<MFloat, nDim> deltaS{};
682 std::array<MFloat, nDim> vecSx{};
683 for(MInt i = 0; i < nDim; i++) {
684 deltaS[i] = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i] * dt;
685 vecSx[i] = m_position[i] - s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[i];
686 }
687
688 maia::math::normalize(vecSx.data(), nDim);
689 for(MInt i = 0; i < nDim; i++) {
690 nx0 += s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_normal[i] * vecSx[i];
691 }
692
693 if(nx0 > 0) return;
694
695 // simply add surface velocity to the particle and apply shift
696 for(MInt i = 0; i < nDim; i++) {
697 m_oldPos[i] = m_position[i];
698 m_position[i] = s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_coordinates[i] + deltaS[i];
699 m_velocity[i] = m_velocity[i] + s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i];
700 m_oldVel[i] = m_oldVel[i] + s_backPtr->m_bndryCells->a[bndId].m_srfcs[0]->m_velocity[i];
701 }
702
703 // 6) update the new cellId and check if the particle should be communicated
704 this->initProperties();
705 hadWallColl() = true;
707
708 if(m_cellId < 0 || m_cellId > s_backPtr->a_noCells() - 1 || !s_backPtr->a_isValidCell(m_cellId)) {
709 std::cerr << "Particle at invalid cell after collision-2 " << m_cellId << std::endl;
710 isInvalid() = true;
711 reqSend() = false;
712 } else {
713 // ensure communication even-though the particle was already in a halo-cell
714 if(s_backPtr->a_isHalo(m_cellId)) {
715 reqSend() = true;
716 isWindow() = false;
717 }
718 }
719}

◆ wasSend() [1/2]

template<MInt nDim>
LPTBase< nDim >::BitsetType::reference LPTBase< nDim >::wasSend

Definition at line 199 of file lptbase.h.

199 {
200 return hasProperty(LptBaseProperty::WasSend);
201}

◆ wasSend() [2/2]

template<MInt nDim>
MBool LPTBase< nDim >::wasSend

Definition at line 194 of file lptbase.h.

194 {
195 return hasProperty(LptBaseProperty::WasSend);
196}

Member Data Documentation

◆ m_accel

template<MInt nDim>
std::array<MFloat, nDim> LPTBase< nDim >::m_accel {}

Definition at line 36 of file lptbase.h.

◆ m_cellId

template<MInt nDim>
MInt LPTBase< nDim >::m_cellId = -2

Definition at line 46 of file lptbase.h.

◆ m_creationTime

template<MInt nDim>
MFloat LPTBase< nDim >::m_creationTime = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 50 of file lptbase.h.

◆ m_densityRatio

template<MInt nDim>
MFloat LPTBase< nDim >::m_densityRatio = -2

Definition at line 44 of file lptbase.h.

◆ m_neighborList

template<MInt nDim>
std::vector<MInt> LPTBase< nDim >::m_neighborList

Definition at line 82 of file lptbase.h.

◆ m_oldCellId

template<MInt nDim>
MInt LPTBase< nDim >::m_oldCellId = -2

Definition at line 47 of file lptbase.h.

◆ m_oldPos

template<MInt nDim>
std::array<MFloat, nDim> LPTBase< nDim >::m_oldPos {}

Definition at line 39 of file lptbase.h.

◆ m_oldVel

template<MInt nDim>
std::array<MFloat, nDim> LPTBase< nDim >::m_oldVel {}

Definition at line 41 of file lptbase.h.

◆ m_partId

template<MInt nDim>
MLong LPTBase< nDim >::m_partId = -2

Definition at line 45 of file lptbase.h.

◆ m_position

template<MInt nDim>
std::array<MFloat, nDim> LPTBase< nDim >::m_position {}

Definition at line 34 of file lptbase.h.

◆ m_properties

template<MInt nDim>
BitsetType LPTBase< nDim >::m_properties

Definition at line 52 of file lptbase.h.

◆ m_velocity

template<MInt nDim>
std::array<MFloat, nDim> LPTBase< nDim >::m_velocity {}

Definition at line 35 of file lptbase.h.

◆ s_backPtr

template<MInt nDim>
LPT< nDim > * LPTBase< nDim >::s_backPtr = nullptr
static

Definition at line 29 of file lptbase.h.

◆ s_distFactorImp

template<MInt nDim>
MFloat LPTBase< nDim >::s_distFactorImp = 0.0
static

Definition at line 28 of file lptbase.h.

◆ s_floatElements

template<MInt nDim>
constexpr MInt LPTBase< nDim >::s_floatElements = 3 * nDim + 1
staticconstexpr

Definition at line 31 of file lptbase.h.

◆ s_intElements

template<MInt nDim>
constexpr MInt LPTBase< nDim >::s_intElements = 5
staticconstexpr

Definition at line 32 of file lptbase.h.

◆ s_interpolationMethod

template<MInt nDim>
MInt LPTBase< nDim >::s_interpolationMethod = 0
static

Definition at line 27 of file lptbase.h.

◆ s_interpolationOrder

template<MInt nDim>
MInt LPTBase< nDim >::s_interpolationOrder = 0
static

Definition at line 26 of file lptbase.h.


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