MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
LPTEllipsoidal< nDim > Class Template Reference

#include <lptellipsoidal.h>

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

Public Member Functions

 LPTEllipsoidal ()
 constructor of ellipsoidal particles More...
 
 ~LPTEllipsoidal () override=default
 
 LPTEllipsoidal (const LPTEllipsoidal &)=default
 
LPTEllipsoidaloperator= (const LPTEllipsoidal &)=default
 
void motionEquation () override
 
void energyEquation () override
 
void coupling () override
 single particle coupling terms More...
 
void advanceParticle () override
 advance to new timeStep More...
 
void resetWeights () override
 
void calculateMajorAxisOrientation (MFloat *majorAxis)
 Calculate the orientation of the major axis in the world coordinate system. More...
 
MFloat dragFactor (const MFloat partRe, const MFloat beta=1, const MFloat inclinationAngle=0, const MFloat K0=0, const MFloat K2=0)
 Calculates the drag factor for current particle with given Re number, aspect ratio and inclination angle. More...
 
MFloat liftFactor (const MFloat partRe, const MFloat beta, const MFloat inclinationAngle, const MFloat K0, const MFloat K2)
 Calculates the lift factor for current particle with given Re number, aspect ratio, and inclination angle. More...
 
MFloat torqueFactor (const MFloat partRe, const MFloat beta, const MFloat inclinationAngle)
 Calculates the torque factor for current particle with given Re number, aspect ratio and inclination angle. More...
 
void setParticleFluidVelocities (MInt cellId, MFloat *position, MFloat *quaternions, MFloat *fluidVel, MFloat *fluidVelGrad)
 
MFloat maxParticleRadius () const
 Returns the largest radius. More...
 
MFloat minParticleRadius () const
 Returns the smallest radius. More...
 
MFloat particleRadius (MInt direction) const
 Returns the radius in direction d. More...
 
MFloat equivalentRadius () const
 Returns the equivalent radius. More...
 
MFloat equivalentDiameter () const
 Returns the equivalent diameter. More...
 
MFloat particleVolume () const
 Calculates the current volume. More...
 
MFloat particleMass () const
 Calculates the current mass. More...
 
MFloat magRelVel (const MFloat *const velocity1, const MFloat *const velocity2) const
 Calculates the magnitude of the relative velocity of the two given velocity vectors. More...
 
MFloat particleRe (const MFloat velocity, const MFloat density, const MFloat dynamicViscosity)
 Calculates the particle Reynolds number. More...
 
MFloat fParticleRelTime (const MFloat dynamicViscosity)
 Calculates the reciprocal of the particle relaxation time. More...
 
MFloat effectiveWallCollisionRadius () const override
 Returns the relevant particle radius for the wall collision. More...
 
void initEllipsoialProperties ()
 
void initVelocityAndDensity ()
 
- Public Member Functions inherited from LPTBase< nDim >
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_angularVel {}
 particle angular velocity More...
 
std::array< MFloat, nDim > m_angularAccel {}
 particle angular acceleration More...
 
std::array< MFloat, nDim > m_fluidVel {}
 fluid velocity More...
 
MFloat m_fluidDensity = std::numeric_limits<MFloat>::quiet_NaN()
 fluid density More...
 
std::array< MFloat, nDim > m_oldAccel {}
 particle acceleration of the last time step More...
 
std::array< MFloat, nDim > m_oldAngularVel {}
 particle angular velocity of the last time step More...
 
std::array< MFloat, nDim > m_oldAngularAccel {}
 particle angular acceleration of the last time step More...
 
std::array< MFloat, nDim > m_oldFluidVel {}
 fluid velocity of the last time step More...
 
std::array< MFloat, nDim *nDim > m_velocityGradientFluid {}
 gradient of fluid velocity in the particle fixed coordinate system More...
 
MFloat m_oldFluidDensity = std::numeric_limits<MFloat>::quiet_NaN()
 old fluid density More...
 
MFloat m_aspectRatio = std::numeric_limits<MFloat>::quiet_NaN()
 aspect ratio a/c of ellipsoidal: 0 < oblate < 1, =1 spherical, >1 prolate More...
 
MFloat m_semiMinorAxis = std::numeric_limits<MFloat>::quiet_NaN()
 semi minor axis a More...
 
std::array< MFloat, 4 > m_shapeParams {std::numeric_limits<MFloat>::quiet_NaN()}
 Shape parameters for ellipsoid. More...
 
std::array< MFloat, 4 > m_quaternion {}
 
std::array< MFloat, 4 > m_oldQuaternion {}
 
MFloat m_temperature = std::numeric_limits<MFloat>::quiet_NaN()
 temperature More...
 
MFloat m_fluidVelMag = std::numeric_limits<MFloat>::quiet_NaN()
 fluid velocity magnitude More...
 
MFloat m_heatFlux = std::numeric_limits<MFloat>::quiet_NaN()
 heat flux to cell More...
 
MInt m_particleMajorAxis = 2
 
std::vector< MFloatm_redistWeight {}
 
- Public Attributes inherited from LPTBase< nDim >
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 constexpr MInt s_floatElements = 7 + 8 * nDim + 4 * 2
 
static constexpr MInt s_intElements = 0
 
static MFloat s_lengthFactor = F1
 
static MFloat s_Re = F1
 
static MFloat s_Pr = F1
 
static MFloat s_Sc = F1
 
static MFloat s_We
 
static std::array< MFloat, nDim > s_Frm {}
 
- Static Public Attributes inherited from LPTBase< nDim >
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
 

Private Member Functions

void initShapeParams ()
 Calcultes shape parameters for current particle (see Siewert, 2014) More...
 
void initEqDiameter ()
 
void interpolateVelocityAndDensity (const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, std::vector< MFloat > &weights)
 
void interpolateVelocityAndVelocitySlopes (const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat *const velocityGradient, std::vector< MFloat > &weights)
 
void momentumCoupling ()
 add the momentum flux from the particle to the cell/all surrounding cells More...
 
void heatCoupling ()
 add the heat flux from the particle to the cell/all surrounding cells More...
 
void massCoupling ()
 add the mass flux from the particle to the cell/all surrounding cells More...
 

Private Attributes

MFloat m_eqDiameter = std::numeric_limits<MFloat>::quiet_NaN()
 equivalent particle diameter More...
 

Friends

template<MInt >
std::ostream & operator<< (std::ostream &os, const LPTEllipsoidal &m)
 

Additional Inherited Members

- Public Types inherited from LPTBase< nDim >
using BitsetType = maia::lpt::baseProperty::BitsetType
 

Detailed Description

template<MInt nDim>
class LPTEllipsoidal< nDim >

Definition at line 21 of file lptellipsoidal.h.

Constructor & Destructor Documentation

◆ LPTEllipsoidal() [1/2]

template<MInt nDim>
LPTEllipsoidal< nDim >::LPTEllipsoidal
Author
Laurent Andre

Definition at line 40 of file lptellipsoidal.cpp.

40 {
41 const auto nan = std::numeric_limits<MFloat>::quiet_NaN();
42 for(MInt i = 0; i < nDim; i++) {
43 m_fluidVel[i] = nan;
44 m_oldFluidVel[i] = nan;
45 m_velocity[i] = nan;
46 m_oldVel[i] = nan;
47 m_position[i] = nan;
48 m_oldPos[i] = nan;
49 m_accel[i] = nan;
50 m_oldAccel[i] = nan;
51 m_angularVel[i] = nan;
52 m_oldAngularVel[i] = nan;
53 m_angularAccel[i] = nan;
54 m_oldAngularAccel[i] = nan;
55 }
56 for(MInt i = 0; i < 4; i++) {
57 m_quaternion[i] = nan;
58 m_oldQuaternion[i] = nan;
59 }
60}
std::array< MFloat, nDim > m_position
Definition: lptbase.h:34
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
std::array< MFloat, nDim > m_oldVel
particle velocity of the last time step
Definition: lptbase.h:41
std::array< MFloat, nDim > m_accel
Definition: lptbase.h:36
std::array< MFloat, 4 > m_oldQuaternion
std::array< MFloat, nDim > m_oldAccel
particle acceleration of the last time step
std::array< MFloat, nDim > m_oldAngularAccel
particle angular acceleration of the last time step
std::array< MFloat, nDim > m_fluidVel
fluid velocity
std::array< MFloat, nDim > m_angularAccel
particle angular acceleration
std::array< MFloat, nDim > m_oldFluidVel
fluid velocity of the last time step
std::array< MFloat, nDim > m_oldAngularVel
particle angular velocity of the last time step
std::array< MFloat, nDim > m_angularVel
particle angular velocity
std::array< MFloat, 4 > m_quaternion
int32_t MInt
Definition: maiatypes.h:62

◆ ~LPTEllipsoidal()

template<MInt nDim>
LPTEllipsoidal< nDim >::~LPTEllipsoidal ( )
overridedefault

◆ LPTEllipsoidal() [2/2]

template<MInt nDim>
LPTEllipsoidal< nDim >::LPTEllipsoidal ( const LPTEllipsoidal< nDim > &  )
default

Member Function Documentation

◆ advanceParticle()

template<MInt nDim>
void LPTEllipsoidal< nDim >::advanceParticle
overridevirtual
Author
Tim Wegmann

Implements LPTBase< nDim >.

Definition at line 68 of file lptellipsoidal.cpp.

68 {
69 firstStep() = false;
70 hasCollided() = false;
71 hadWallColl() = false;
72 for(MInt i = 0; i < nDim; i++) {
73 ASSERT(!isnan(m_fluidVel[i]), "");
75 }
76 ASSERT(m_fluidDensity > 0, "");
78}
BitsetType::reference firstStep()
Definition: lptbase.h:179
BitsetType::reference hadWallColl()
Definition: lptbase.h:169
BitsetType::reference hasCollided()
Definition: lptbase.h:160
MFloat m_oldFluidDensity
old fluid density
MFloat m_fluidDensity
fluid density

◆ calculateMajorAxisOrientation()

template<MInt nDim>
void LPTEllipsoidal< nDim >::calculateMajorAxisOrientation ( MFloat majorAxis)
Parameters
majorAxis- output array to store the major axis

Definition at line 896 of file lptellipsoidal.cpp.

896 {
897 std::array<MFloat, nDim> majorAxisParticleFixed{}; // major axis in particle fixed coordinate system
898 for(MInt i = 0; i < nDim; i++) {
899 i == m_particleMajorAxis ? majorAxisParticleFixed[i] = maxParticleRadius() : majorAxisParticleFixed[i] = F0;
900 }
901 MFloatScratchSpace R(3, 3, AT_, "R");
903 maia::math::matrixVectorProductTranspose(majorAxis, R, majorAxisParticleFixed.begin());
904}
MFloat maxParticleRadius() const
Returns the largest radius.
This class is a ScratchSpace.
Definition: scratch.h:758
void computeRotationMatrix(MFloatScratchSpace &R, MFloat *q)
rotation matrix co-rotating(~inertial) frame -> body-fixed frame
Definition: maiamath.h:533
void matrixVectorProductTranspose(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A^t*b
Definition: maiamath.h:574

◆ coupling()

template<MInt nDim>
void LPTEllipsoidal< nDim >::coupling
overridevirtual
Author
Tim Wegmann

Implements LPTBase< nDim >.

Definition at line 85 of file lptellipsoidal.cpp.

85 {
86 if(m_cellId < 0) {
87 mTerm(1, AT_, "coupling of invalid particle?");
88 }
89
90 if(!s_backPtr->m_heatCoupling && !s_backPtr->m_evaporation) {
91 m_redistWeight.clear();
93 }
94
95 // check that all variables have been exchanged/set correctly
96 for(MInt i = 0; i < nDim; i++) {
97 ASSERT(!isnan(m_oldFluidVel[i]), "");
98 }
99 ASSERT(m_oldFluidDensity > 0, "");
100
101 // check all source terms
102#ifdef LPT_DEBUG
103 for(MInt i = 0; i < nDim; i++) {
104 if(std::isnan(m_accel[i])) {
105 cerr << "Invalid motion equation! " << m_partId << " " << m_position[0] << " " << m_position[1] << " "
106 << m_position[2] << endl;
107 isInvalid() = true;
108 return;
109 }
110 if(std::isnan(m_velocity[i])) {
111 cerr << "Invalid motion equation2! " << m_partId << " " << m_position[0] << " " << m_position[1] << " "
112 << m_position[2] << " " << m_densityRatio << " " << hadWallColl() << endl;
113 isInvalid() = true;
114 return;
115 }
116 }
117#endif
118
119 if(s_backPtr->m_momentumCoupling) momentumCoupling();
120 if(s_backPtr->m_heatCoupling) heatCoupling();
121 if(s_backPtr->m_massCoupling) massCoupling();
122}
static LPT< nDim > * s_backPtr
Definition: lptbase.h:29
MLong m_partId
Definition: lptbase.h:45
MFloat m_densityRatio
Definition: lptbase.h:44
MInt m_cellId
Definition: lptbase.h:46
BitsetType::reference isInvalid()
Definition: lptbase.h:151
void interpolateVelocityAndDensity(const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, std::vector< MFloat > &weights)
void heatCoupling()
add the heat flux from the particle to the cell/all surrounding cells
std::vector< MFloat > m_redistWeight
void momentumCoupling()
add the momentum flux from the particle to the cell/all surrounding cells
void massCoupling()
add the mass flux from the particle to the cell/all surrounding cells
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29

◆ dragFactor()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::dragFactor ( const MFloat  partRe,
const MFloat  beta = 1,
const MFloat  inclinationAngle = 0,
const MFloat  K0 = 0,
const MFloat  K2 = 0 
)
Author
Laurent Andre
Date
August 2022

Definition at line 741 of file lptellipsoidal.cpp.

742 {
743 MFloat result = NAN;
744 switch(s_backPtr->m_dragModelType) {
745 case 0: { // drag force switched off
746 result = F0;
747 break;
748 }
749 case 1: { // linear Stokes drag
750 result = F1;
751 break;
752 }
753 case 2: { // nonlinear drag according to Schiller & Naumann
754 result = 1.0 + 0.15 * pow(partRe, 0.687);
755 break;
756 }
757 case 3: { // new correlations by Konstantin (2020)
758 std::array<MFloat, 8> dCorrs{-0.007, 1.0, 1.17, -0.07, 0.047, 1.14, 0.7, -0.008};
759 MFloat fd0 = F1;
760 MFloat fd90 = F1;
761 fd0 = 1.0 + 0.15 * pow(partRe, 0.687)
762 + dCorrs[0] * pow(std::log(beta), dCorrs[1]) * pow(partRe, dCorrs[2] + dCorrs[3] * std::log(beta));
763 fd90 = 1.0 + 0.15 * pow(partRe, 0.687)
764 + dCorrs[4] * pow(log(beta), dCorrs[5]) * pow(partRe, dCorrs[6] + dCorrs[7] * log(beta));
765
766 MFloat fd0K2 = fd0 * K2;
767 MFloat f90K0 = fd90 * K0;
768 result = fd0K2 + (f90K0 - fd0K2) * POW2(sin(inclinationAngle));
769 break;
770 }
771 default: {
772 mTerm(1, AT_, "Unknown particle drag method");
773 }
774 }
775 return result;
776}
constexpr Real POW2(const Real x)
Definition: functions.h:119
double MFloat
Definition: maiatypes.h:52

◆ effectiveWallCollisionRadius()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::effectiveWallCollisionRadius ( ) const
inlineoverridevirtual

Reimplemented from LPTBase< nDim >.

Definition at line 186 of file lptellipsoidal.h.

186{ return equivalentRadius(); }
MFloat equivalentRadius() const
Returns the equivalent radius.

◆ energyEquation()

template<MInt nDim>
void LPTEllipsoidal< nDim >::energyEquation
overridevirtual

Implements LPTBase< nDim >.

Definition at line 885 of file lptellipsoidal.cpp.

885 {
886 mTerm(1, AT_, "Not yet implemented");
887}

◆ equivalentDiameter()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::equivalentDiameter ( ) const
inline

Definition at line 156 of file lptellipsoidal.h.

156{ return m_eqDiameter; }
MFloat m_eqDiameter
equivalent particle diameter

◆ equivalentRadius()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::equivalentRadius ( ) const
inline

Definition at line 153 of file lptellipsoidal.h.

153{ return F1B2 * m_eqDiameter; }

◆ fParticleRelTime()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::fParticleRelTime ( const MFloat  dynamicViscosity)
inline

Definition at line 181 of file lptellipsoidal.h.

181 {
182 return 18.0 * dynamicViscosity / (m_eqDiameter * m_eqDiameter * s_backPtr->m_material->density());
183 }

◆ heatCoupling()

template<MInt nDim>
void LPTEllipsoidal< nDim >::heatCoupling
private
Author
Sven Berger, Tim Wegmann

Definition at line 179 of file lptellipsoidal.cpp.

179 {
180 mTerm(1, AT_, "Heat coupling not tested for ellipsoidal particles");
181}

◆ initEllipsoialProperties()

template<MInt nDim>
void LPTEllipsoidal< nDim >::initEllipsoialProperties ( )
inline

Definition at line 188 of file lptellipsoidal.h.

188 {
189 ASSERT(!std::isnan(m_aspectRatio), "Aspect Ratio not set!");
190 ASSERT(!std::isnan(m_semiMinorAxis), "Semi Minor Axis not set!");
193 }
void initShapeParams()
Calcultes shape parameters for current particle (see Siewert, 2014)
MFloat m_aspectRatio
aspect ratio a/c of ellipsoidal: 0 < oblate < 1, =1 spherical, >1 prolate
MFloat m_semiMinorAxis
semi minor axis a

◆ initEqDiameter()

template<MInt nDim>
void LPTEllipsoidal< nDim >::initEqDiameter ( )
inlineprivate

Definition at line 212 of file lptellipsoidal.h.

212{ m_eqDiameter = 2 * m_semiMinorAxis * pow(m_aspectRatio, F1B3); }

◆ initShapeParams()

template<MInt nDim>
void LPTEllipsoidal< nDim >::initShapeParams
private
Author
Laurent Andre
Date
August 2022

Definition at line 854 of file lptellipsoidal.cpp.

854 {
855 MFloat beta = m_aspectRatio;
856 MFloat beta2 = beta * beta;
857 if(fabs(beta - F1) < 1e-14) {
858 // spherical
860 m_shapeParams[1] = F2B3;
861 m_shapeParams[2] = F2B3;
862 m_shapeParams[3] = F2B3;
863 } else if(beta > F1) {
864 // prolate
865 MFloat kappa = log((beta - sqrt(beta2 - F1)) / (beta + sqrt(beta2 - F1)));
866 m_shapeParams[0] = -beta * POW2(m_semiMinorAxis) * kappa / sqrt(beta2 - F1);
867 m_shapeParams[1] = beta2 / (beta2 - F1) + beta * kappa / (F2 * pow(beta2 - F1, F3B2));
868 m_shapeParams[2] = beta2 / (beta2 - F1) + beta * kappa / (F2 * pow(beta2 - F1, F3B2));
869 m_shapeParams[3] = -F2 / (beta2 - F1) - beta * kappa / (pow(beta2 - F1, F3B2));
870 } else if(beta < F1) {
871 // oblate
872 MFloat kappa = F2 * atan2(beta, sqrt(F1 - beta2));
873 m_shapeParams[0] = beta * POW2(m_semiMinorAxis) * (PI - kappa) / sqrt(F1 - beta2);
874 m_shapeParams[1] = -beta * (kappa - PI + F2 * beta * sqrt(F1 - beta2)) / (F2 * pow(F1 - beta2, F3B2));
875 m_shapeParams[1] = -beta * (kappa - PI + F2 * beta * sqrt(F1 - beta2)) / (F2 * pow(F1 - beta2, F3B2));
876 m_shapeParams[1] = (beta * kappa - beta * PI + F2 * sqrt(F1 - beta2)) / (pow(F1 - beta2, F3B2));
877 } else {
878 // general triaxial ellipsoid
879 mTerm(1, "Generalize here");
880 }
881}
std::array< MFloat, 4 > m_shapeParams
Shape parameters for ellipsoid.

◆ initVelocityAndDensity()

template<MInt nDim>
void LPTEllipsoidal< nDim >::initVelocityAndDensity ( )
inline

Definition at line 195 of file lptellipsoidal.h.

195 {
196 std::array<MFloat, nDim + 1> result{};
197 std::vector<MFloat> weights;
198 this->template interpolateAndCalcWeights<0, nDim + 1>(m_cellId, m_position.data(), result.data(), weights);
199 for(MInt i = 0; i < nDim; i++) {
200 m_oldFluidVel[i] = result[i];
201 m_fluidVel[i] = result[i];
202 }
203 m_oldFluidDensity = result[nDim];
204 m_fluidDensity = result[nDim];
205 }

◆ interpolateVelocityAndDensity()

template<MInt nDim>
void LPTEllipsoidal< nDim >::interpolateVelocityAndDensity ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  velocity,
MFloat density,
std::vector< MFloat > &  weights 
)
inlineprivate

Definition at line 214 of file lptellipsoidal.h.

215 {
216 std::array<MFloat, nDim + 1> result{};
217 this->template interpolateAndCalcWeights<0, nDim + 1>(cellId, position, result.data(), weights);
218 for(MInt n = 0; n < nDim; n++) {
219 velocity[n] = result[n];
220 }
221 density = result[nDim];
222 }

◆ interpolateVelocityAndVelocitySlopes()

template<MInt nDim>
void LPTEllipsoidal< nDim >::interpolateVelocityAndVelocitySlopes ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  velocity,
MFloat *const  velocityGradient,
std::vector< MFloat > &  weights 
)
inlineprivate

Definition at line 224 of file lptellipsoidal.h.

225 {
226 std::array<MFloat, nDim> result{};
227 std::array<MFloat, nDim * nDim> gradientResult{};
228 this->template interpolateAndCalcWeights<0, nDim>(cellId, position, result.data(), weights, gradientResult.data());
229 for(MInt n = 0; n < nDim; n++) {
230 velocity[n] = result[n];
231 }
232 for(MInt n = 0; n < nDim * nDim; n++) {
233 velocityGradient[n] = gradientResult[n];
234 }
235 }

◆ liftFactor()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::liftFactor ( const MFloat  partRe,
const MFloat  beta,
const MFloat  inclinationAngle,
const MFloat  K0,
const MFloat  K2 
)
Author
Laurent Andre
Date
August 2022

Definition at line 784 of file lptellipsoidal.cpp.

785 {
786 MFloat result = NAN;
787 switch(s_backPtr->m_liftModelType) {
788 case 0: { // lift force switched off
789 result = F0;
790 break;
791 }
792 case 1: { // linear
793 result = F1;
794 break;
795 }
796 case 2: { // new correlations by Konstantin (2020)
797 std::array<MFloat, 6> lCorrs{0.01, 0.86, 1.77, 0.34, 0.88, -0.05};
798 MFloat flMax = F1;
799 MFloat flShift = F1;
800 if(partRe > 1) flShift += lCorrs[0] * pow(log(beta), lCorrs[1]) * pow(log(partRe), lCorrs[2]);
801 MFloat psi = F1B2 * M_PI * pow(inclinationAngle / M_PI * F2, flShift);
802 flMax = F1 + lCorrs[3] * pow(partRe, lCorrs[4] + lCorrs[5]);
803 MFloat ClMax = F1B2 * flMax * (K0 - K2);
804 MFloat Cl = F2 * sin(psi) * cos(psi) * ClMax;
805 result = Cl;
806 break;
807 }
808 default: {
809 mTerm(1, AT_, "Unknown particle drag method");
810 }
811 }
812 return result;
813}
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125

◆ magRelVel()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::magRelVel ( const MFloat *const  velocity1,
const MFloat *const  velocity2 
) const
inline

Definition at line 167 of file lptellipsoidal.h.

167 {
168 MFloat magnitude = 0.0;
169 for(MInt i = 0; i < nDim; i++) {
170 magnitude += POW2(velocity1[i] - velocity2[i]);
171 }
172 return sqrt(magnitude);
173 }

◆ massCoupling()

template<MInt nDim>
void LPTEllipsoidal< nDim >::massCoupling
private
Author
Sven Berger, Tim Wegmann

Definition at line 129 of file lptellipsoidal.cpp.

129 {
130 mTerm(1, AT_, "Mass coupling not implemented for ellipsoidal particles");
131}

◆ maxParticleRadius()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::maxParticleRadius ( ) const
inline

Definition at line 141 of file lptellipsoidal.h.

141{ return m_semiMinorAxis * m_aspectRatio; }

◆ minParticleRadius()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::minParticleRadius ( ) const
inline

Definition at line 143 of file lptellipsoidal.h.

143{ return m_semiMinorAxis; }

◆ momentumCoupling()

template<MInt nDim>
void LPTEllipsoidal< nDim >::momentumCoupling
private
Author
Sven Berger, Tim Wegmann

Definition at line 138 of file lptellipsoidal.cpp.

138 {
139 const MFloat relT = (s_backPtr->m_timeStep - m_creationTime) / s_backPtr->m_timeStep;
140
141 const MFloat mass = particleMass();
142
143 array<MFloat, nDim> force{};
144
145 for(MInt i = 0; i < nDim; i++) {
146 // momentum flux due to drag force
147 const MFloat invDensityRatio = (abs(m_densityRatio) <= MFloatEps) ? 1.0 : 1.0 / m_densityRatio;
148 force[i] = mass * (m_accel[i] - ((1.0 - invDensityRatio) * s_Frm[i])) * relT;
149 }
150
151 // work done by the momentum
152 const MFloat work = std::inner_product(force.begin(), force.end(), m_oldVel.begin(), 0.0);
153
154
155 if(!s_backPtr->m_couplingRedist) {
156 for(MInt i = 0; i < nDim; i++) {
157 s_backPtr->a_momentumFlux(m_cellId, i) += (force[i]);
158 }
159 s_backPtr->a_workFlux(m_cellId) += work;
160
161 } else {
162 ASSERT(m_redistWeight.size() == m_neighborList.size(),
163 "Invalid " + to_string(m_redistWeight.size()) + "!=" + to_string(m_neighborList.size()));
164 for(MInt n = 0; n < (signed)m_neighborList.size(); n++) {
165 // a weightHeat is used to distribute the source term to multiple cells...
166 for(MInt i = 0; i < nDim; i++) {
167 s_backPtr->a_momentumFlux(m_neighborList[n], i) += m_redistWeight.at(n) * (force[i]);
168 }
169 s_backPtr->a_workFlux(m_neighborList[n]) += m_redistWeight.at(n) * work;
170 }
171 }
172}
std::vector< MInt > m_neighborList
Definition: lptbase.h:82
MFloat m_creationTime
creation time modifier
Definition: lptbase.h:50
static std::array< MFloat, nDim > s_Frm
MFloat particleMass() const
Calculates the current mass.

◆ motionEquation()

template<MInt nDim>
void LPTEllipsoidal< nDim >::motionEquation
overridevirtual
  1. Predictor step
  2. get velocity, density and velocity magnitude at the predicted position
  3. corrector step

Implements LPTBase< nDim >.

Definition at line 185 of file lptellipsoidal.cpp.

185 {
186 const MFloat dt = s_backPtr->m_timeStep - m_creationTime;
187 ASSERT(dt > 0, "Timestep < 0");
188
189 // NOTE: at this point old means 1 time-Step ago and the current values will be updated below!
197
198 if(firstStep()) {
199 for(MInt i = 0; i < nDim; i++) {
200 m_accel[i] = s_Frm[i];
201 m_oldAccel[i] = s_Frm[i];
202 }
203 }
204
205 for(MInt i = 0; i < nDim; i++) {
206 ASSERT(!isnan(m_oldFluidVel[i]), "");
207 }
208 ASSERT(m_oldFluidDensity > 0, "");
209
210 // reduce variance between runs (round to 9 decimal places)
211 // TODO-timw labels:LPT,totest check if rounding is still necessary?
212 const MFloat invDensityRatio =
213 F1 / (static_cast<MFloat>(ceil(s_backPtr->m_material->density() / m_oldFluidDensity * 1E9)) / 1E9);
214
215 m_densityRatio = 1 / invDensityRatio;
216
218 array<MFloat, nDim> predictedPos{};
219 array<MFloat, nDim> predictedVel{};
220 array<MFloat, nDim> predictedAngularVel{};
221 array<MFloat, nDim + 1> predictedQuaternion{};
222
223 MFloat q[3];
224 MFloat q0[3];
225 MFloat tq[3];
226 MFloat tq0[3];
227 MFloat w = m_oldQuaternion[0];
228 MFloat x = m_oldQuaternion[1];
230 MFloat z = m_oldQuaternion[3];
231 for(MInt i = 0; i < 3; i++) {
232 q0[i] = m_oldAngularVel[i];
233 }
234
235 // predict position, velocity, orientation and angular velocity
236 for(MInt i = 0; i < nDim; i++) {
237 predictedVel[i] = m_oldVel[i] + dt * m_oldAccel[i];
238 predictedPos[i] = m_oldPos[i] + dt * (m_oldVel[i]) + F1B2 * POW2(dt) * (m_oldAccel[i]);
239 }
240 predictedQuaternion[0] = w + F1B2 * dt * (-x * q0[0] - y * q0[1] - z * q0[2]);
241 predictedQuaternion[1] = x + F1B2 * dt * (w * q0[0] - z * q0[1] + y * q0[2]);
242 predictedQuaternion[2] = y + F1B2 * dt * (z * q0[0] + w * q0[1] - x * q0[2]);
243 predictedQuaternion[3] = z + F1B2 * dt * (-y * q0[0] + x * q0[1] + w * q0[2]);
244 for(MInt i = 0; i < 3; i++) {
245 predictedAngularVel[i] = m_oldAngularVel[i] + dt * m_oldAngularAccel[i];
246 }
247
249 // find the predicted CellId at the predicted position around the previous cellId
250 const MInt predictedCellId = s_backPtr->grid().findContainingLeafCell(&predictedPos[0], m_cellId);
251
252 ASSERT(m_cellId > -1, "Invalid cell!");
253 ASSERT(predictedCellId > -1, "Invalid cell!");
254 ASSERT(s_backPtr->c_isLeafCell(predictedCellId), "Invalid cell!");
255
256 vector<MFloat> predictedWeights(0);
257 array<MFloat, nDim> fluidVel{};
258 array<MFloat, nDim * nDim> fluidVelGradient{};
259 array<MFloat, nDim * nDim> fluidVelGradientHat{};
260 std::fill(fluidVel.begin(), fluidVel.end(), std::numeric_limits<MFloat>::quiet_NaN());
261 std::fill(fluidVelGradient.begin(), fluidVelGradient.end(), std::numeric_limits<MFloat>::quiet_NaN());
262 std::fill(fluidVelGradientHat.begin(), fluidVelGradientHat.end(), std::numeric_limits<MFloat>::quiet_NaN());
263 interpolateVelocityAndVelocitySlopes(predictedCellId, predictedPos.data(), fluidVel.data(), fluidVelGradient.data(),
264 predictedWeights);
265
266 // calculate gradients according to principle axes of ellipsoid
267 MFloatScratchSpace R(3, 3, AT_, "R");
269 for(MInt i = 0; i < nDim; i++) {
270 maia::math::matrixVectorProduct(&fluidVelGradientHat[nDim * i], R, &fluidVelGradient[nDim * i]);
271 }
272
273 m_fluidVelMag = sqrt(std::inner_product(fluidVel.begin(), fluidVel.end(), fluidVel.begin(), F0));
274
275 const MFloat T = s_backPtr->a_fluidTemperature(m_cellId);
276
277 MFloat fluidViscosity = s_backPtr->m_material->dynViscosityFun(T);
278
280 if(s_backPtr->m_dragModelType == 0) {
281 // no drag or neglible small (are going to be deleted...)
282 for(MInt i = 0; i < nDim; i++) {
283 m_velocity[i] = predictedVel[i];
284 m_position[i] = predictedPos[i];
285 m_angularVel[i] = predictedAngularVel[i];
286 m_quaternion[i] = predictedQuaternion[i];
287 m_accel[i] = m_oldAccel[i];
289 }
290 } else {
291 switch(s_backPtr->m_motionEquationType) {
292 case 0: {
293 // particle moves with fluid velocity, no rotational motion
294 for(MInt i = 0; i < nDim; i++) {
295 m_position[i] = m_oldPos[i] + F1B2 * dt * (fluidVel[i] + m_oldVel[i]) * s_lengthFactor;
296 m_velocity[i] = fluidVel[i];
297 m_accel[i] = (m_velocity[i] - m_oldVel[i]) / dt;
298 m_angularVel[i] = F0;
299 m_angularAccel[i] = F0;
300 }
301 break;
302 }
303 case 1: {
304 // spherical case copied from lptspherical
305 // serves for debugging to have a version independant of the strain, vorticity
306 const MFloat relVel = magRelVel(&fluidVel[0], &predictedVel[0]);
307
308 const MFloat Rep = particleRe(relVel, m_oldFluidDensity, fluidViscosity) * s_Re;
309
310 const MFloat CD = dragFactor(Rep) / s_Re * fParticleRelTime(fluidViscosity);
311
312 for(MInt i = 0; i < nDim; i++) {
313 m_accel[i] = CD * (fluidVel[i] - predictedVel[i]) + (1.0 - invDensityRatio) * s_Frm[i];
314 m_velocity[i] = m_oldVel[i] + dt * F1B2 * (m_accel[i] + m_oldAccel[i]);
315 m_position[i] = m_oldPos[i] + dt * F1B2 * (m_velocity[i] + m_oldVel[i]) * s_lengthFactor;
316 }
317 break;
318 }
319 case 2: {
320 // case derived for creeping flow
321 const MFloat fdtB2 = F1B2 * dt;
322 MFloatScratchSpace K(3, 3, AT_, "K");
323 MFloatScratchSpace W(4, 4, AT_, "W");
324 MFloatScratchSpace iW(4, 4, AT_, "iW");
325 MFloatScratchSpace rhs(4, AT_, "rhs");
326
327 MFloat vrel[3];
328 MFloat vrelhat[3];
329 MFloat tmp[3];
330 MFloat vort[3];
331 MFloat strain[3];
332
333 const MFloat beta = m_aspectRatio;
334 const MFloat beta2 = POW2(beta);
335 const MFloat fTauP = fParticleRelTime(fluidViscosity) / s_Re;
336
337 const MFloat linAccFac = (8.0 / 3.0) * pow(beta, F2B3) * fTauP;
338 const MFloat angAccFac = (40.0 / 9.0) * pow(beta, F2B3) * fTauP;
339
340 // integrate angular velocity
341 const MInt maxit = 100;
342 MFloat delta = F1;
343 MInt it = 0;
344
345 // set temporary variables for angular velocity (q) and acceleration (tq)
346 for(MInt i = 0; i < 3; i++) {
347 tq0[i] = m_oldAngularAccel[i];
348 q0[i] = m_oldAngularVel[i];
349 tq[i] = tq0[i];
350 q[i] = q0[i];
351 }
352
353 // compute vorticity and strain
354 for(MInt i = 0; i < 3; i++) {
355 MInt id0 = (i + 1) % 3;
356 MInt id1 = (id0 + 1) % 3;
357 strain[i] = F1B2 * (fluidVelGradientHat[3 * id1 + id0] + fluidVelGradientHat[3 * id0 + id1]);
358 vort[i] = F1B2 * (fluidVelGradientHat[3 * id1 + id0] - fluidVelGradientHat[3 * id0 + id1]);
359 }
360
361 W(0, 0) = F1 + fdtB2 * angAccFac / (m_shapeParams[1] + beta2 * m_shapeParams[3]);
362 W(1, 1) = F1 + fdtB2 * angAccFac / (m_shapeParams[1] + beta2 * m_shapeParams[3]);
363 W(2, 2) = F1 + fdtB2 * angAccFac / (F2 * m_shapeParams[1]);
364 W(2, 0) = F0;
365 W(2, 1) = F0;
366
367 // Newton iterations
368 while(delta > 1e-10 && it < maxit) {
369 W(0, 1) = -fdtB2 * q[2] * (beta2 - F1) / (beta2 + F1);
370 W(0, 2) = -fdtB2 * q[1] * (beta2 - F1) / (beta2 + F1);
371 W(1, 0) = -fdtB2 * q[2] * (F1 - beta2) / (beta2 + F1);
372 W(1, 2) = -fdtB2 * q[0] * (F1 - beta2) / (beta2 + F1);
373
374 maia::math::invert(W, iW, 3, 3);
375
376 // compute angular acceleration tq
377 tq[0] = q[1] * q[2] * (beta2 - F1) / (beta2 + F1)
378 + angAccFac * (((F1 - beta2) / (F1 + beta2)) * strain[0] + vort[0] - q[0])
379 / (m_shapeParams[1] + beta2 * m_shapeParams[3]);
380 tq[1] = q[0] * q[2] * (F1 - beta2) / (beta2 + F1)
381 + angAccFac * (((beta2 - F1) / (F1 + beta2)) * strain[1] + vort[1] - q[1])
382 / (m_shapeParams[1] + beta2 * m_shapeParams[3]);
383 tq[2] = angAccFac * (vort[2] - q[2]) / (F2 * m_shapeParams[1]);
384
385 for(MInt i = 0; i < 3; i++)
386 rhs[i] = q[i] - q0[i] - fdtB2 * (tq0[i] + tq[i]);
387
388 delta = F0;
389 for(MInt i = 0; i < 3; i++) {
390 const MFloat qq = q[i];
391 for(MInt j = 0; j < 3; j++) {
392 q[i] -= iW(i, j) * rhs(j);
393 }
394 delta = mMax(delta, fabs(q[i] - qq));
395 }
396 it++;
397 }
398
399 if(it >= maxit || it <= 0) {
400 cerr << "Newton iterations did not converge " << m_partId << endl;
401 }
402
403 for(MInt i = 0; i < 3; i++) {
404 m_angularVel[i] = q[i];
405 m_angularAccel[i] = tq[i];
406 }
407
408 // integrate quaternions
409 w = m_oldQuaternion[0];
410 x = m_oldQuaternion[1];
411 y = m_oldQuaternion[2];
412 z = m_oldQuaternion[3];
413
414 W(0, 0) = F0;
415 W(0, 1) = -q[0];
416 W(0, 2) = -q[1];
417 W(0, 3) = -q[2];
418 W(1, 0) = q[0];
419 W(1, 1) = F0;
420 W(1, 2) = q[2];
421 W(1, 3) = -q[1];
422 W(2, 0) = q[1];
423 W(2, 1) = -q[2];
424 W(2, 2) = F0;
425 W(2, 3) = q[0];
426 W(3, 0) = q[2];
427 W(3, 1) = q[1];
428 W(3, 2) = -q[0];
429 W(3, 3) = F0;
430
431 for(MInt i = 0; i < 4; i++) {
432 for(MInt j = 0; j < 4; j++) {
433 W(i, j) = -F1B2 * fdtB2 * W(i, j);
434 }
435 W(i, i) = F1;
436 }
437
438 rhs(0) = w + F1B2 * fdtB2 * (-x * q0[0] - y * q0[1] - z * q0[2]);
439 rhs(1) = x + F1B2 * fdtB2 * (w * q0[0] - z * q0[1] + y * q0[2]);
440 rhs(2) = y + F1B2 * fdtB2 * (z * q0[0] + w * q0[1] - x * q0[2]);
441 rhs(3) = z + F1B2 * fdtB2 * (-y * q0[0] + x * q0[1] + w * q0[2]);
442
443 maia::math::invert(W, iW, 4, 4);
444
445 for(MInt i = 0; i < 4; i++) {
446 m_quaternion[i] = F0;
447 for(MInt j = 0; j < 4; j++) {
448 m_quaternion[i] += iW(i, j) * rhs(j);
449 }
450 }
451
452 MFloat abs = F0;
453 for(MInt i = 0; i < 4; i++)
454 abs += POW2(m_quaternion[i]);
455 for(MInt i = 0; i < 4; i++)
456 m_quaternion[i] /= sqrt(abs);
457
458 // integrate linear motion
459 K.fill(F0);
460 K(0, 0) = F1 / (m_shapeParams[0] / POW2(m_semiMinorAxis) + m_shapeParams[1]);
461 K(1, 1) = K(0, 0);
462 K(2, 2) = F1 / (m_shapeParams[0] / POW2(m_semiMinorAxis) + beta2 * m_shapeParams[3]);
464
465 for(MInt i = 0; i < nDim; i++) {
466 vrel[i] = fluidVel[i] - predictedVel[i];
467 }
468
469 maia::math::matrixVectorProduct(vrelhat, R, vrel); // principal axes frame relative velocity
470 maia::math::matrixVectorProduct(tmp, K, vrelhat);
472
473 for(MInt i = 0; i < nDim; i++) {
474 m_accel[i] = linAccFac * vrel[i] + (1.0 - invDensityRatio) * s_Frm[i];
475 m_velocity[i] = m_oldVel[i] + dt * F1B2 * (m_accel[i] + m_oldAccel[i]);
476 m_position[i] = m_oldPos[i] + dt * F1B2 * (m_velocity[i] + m_oldVel[i]) * s_lengthFactor
477 + F1B4 * POW2(dt) * (m_accel[i] + m_oldAccel[i]);
478 }
479 break;
480 }
481 case 3: {
482 // case using new correlations functions by Konstantin (2020)
483 const MFloat fdtB2 = F1B2 * dt;
484 MFloatScratchSpace K(3, 3, AT_, "K");
485 MFloatScratchSpace W(4, 4, AT_, "W");
486 MFloatScratchSpace iW(4, 4, AT_, "iW");
487 MFloatScratchSpace rhs(4, AT_, "rhs");
488
489 MFloat vrel[3];
490 MFloat vrelhat[3];
491 MFloat tmp[3];
492 MFloat vort[3];
493 MFloat strain[3];
494
495 const MFloat beta = m_aspectRatio;
496 const MFloat beta2 = POW2(beta);
497 const MFloat eqRadius = F1B2 * m_eqDiameter;
498 const MFloat fTauP = fParticleRelTime(fluidViscosity) / s_Re;
499 const MFloat magRelVeloc = magRelVel(&fluidVel[0], &predictedVel[0]);
500 const MFloat Rep = particleRe(magRelVeloc, m_oldFluidDensity, fluidViscosity) * s_Re;
501
502 const MFloat angAccFac = (40.0 / 9.0) * pow(beta, F2B3) * fTauP;
503 const MFloat pitchingTorqueFac = (15.0 / 8.0) * invDensityRatio * pow(beta, F2B3) / POW2(eqRadius);
504 const MFloat addFacCd =
505 48.0 * fluidViscosity / (s_Re * s_backPtr->m_material->density() * POW2(m_eqDiameter)) * pow(beta, F2B3);
506 const MFloat momI[3] = {1.0 + POW2(beta), 1.0 + POW2(beta), 2.0}; // factors for moments of inertia
507
509
510 for(MInt i = 0; i < nDim; i++) {
511 vrel[i] = fluidVel[i] - predictedVel[i];
512 }
513
514 maia::math::matrixVectorProduct(vrelhat, R, vrel); // principal axes frame relative velocity
515 maia::math::matrixVectorProduct(tmp, K, vrelhat);
517
518 const MFloat magRelVelHat = sqrt(POW2(vrelhat[0]) + POW2(vrelhat[1]) + POW2(vrelhat[2]));
519
520 const auto nan = std::numeric_limits<MFloat>::quiet_NaN();
521 MFloat inclinationAngle = nan;
522 std::array<MFloat, 3> accHat = {nan, nan, nan};
523 std::array<MFloat, 3> accDragHat = {nan, nan, nan};
524 std::array<MFloat, 3> accLiftHat = {nan, nan, nan};
525 std::array<MFloat, 3> dirDHat = {nan, nan, nan};
526 std::array<MFloat, 3> dirTHat = {nan, nan, nan};
527 std::array<MFloat, 3> dirLHat = {nan, nan, nan};
528 std::array<MFloat, 3> dirDCrossZ = {nan, nan, nan};
529 std::array<MFloat, 3> dirZHat{nan, nan, nan};
530
531 // dirZHat
532 for(MInt i = 0; i < nDim; i++) {
533 i == m_particleMajorAxis ? dirZHat[i] = F1 : dirZHat[i] = F0;
534 }
535 // dirDhat
536 for(MInt i = 0; i < nDim; i++) {
537 dirDHat[i] = vrelhat[i] / magRelVelHat;
538 }
539 // dirDcrossZ = dirDhat x dirZhat
540 maia::math::cross(&dirDHat[0], &dirZHat[0], &dirDCrossZ[0]);
541 const MFloat dotProduct = std::inner_product(dirDHat.begin(), dirDHat.end(), dirZHat.begin(), F0);
542 inclinationAngle = acos(fabs(dotProduct));
543 MInt sgn = (dotProduct > 0 ? 1 : -1);
544 for(MInt i = 0; i < nDim; i++) {
545 dirTHat[i] = dirDCrossZ[i] / sqrt(POW2(dirDCrossZ[0]) + POW2(dirDCrossZ[1]) + POW2(dirDCrossZ[2])) * sgn;
546 }
547 // dirLHat = dirDhat x dirThat
548 maia::math::cross(&dirDHat[0], &dirTHat[0], &dirLHat[0]);
549
550 // integrate angular velocity
551 const MInt maxit = 100;
552 MFloat delta = F1;
553 MInt it = 0;
554
555 W(0, 0) = F1 + fdtB2 * angAccFac / (m_shapeParams[1] + beta2 * m_shapeParams[3]);
556 W(1, 1) = F1 + fdtB2 * angAccFac / (m_shapeParams[1] + beta2 * m_shapeParams[3]);
557 W(2, 2) = F1 + fdtB2 * angAccFac / (F2 * m_shapeParams[1]);
558 W(2, 0) = F0;
559 W(2, 1) = F0;
560
561 // set temporary variables for angular velocity (q) and acceleration (tq)
562 for(MInt i = 0; i < 3; i++) {
563 tq0[i] = m_oldAngularAccel[i];
564 q0[i] = m_oldAngularVel[i];
565 tq[i] = tq0[i];
566 q[i] = q0[i];
567 }
568
569 // compute pitching torque unless torque modelling is turned off
570 MFloat pitch[3] = {F0};
571 if(s_backPtr->m_torqueModelType > 0 && Rep > 1e-8) {
572 MFloat CT = torqueFactor(Rep, beta, inclinationAngle);
573 for(MInt i = 0; i < 3; i++) {
574 pitch[i] = pitchingTorqueFac * POW2(magRelVelHat) * CT / momI[i] * dirTHat[i];
575 if(pitchingTorqueFac <= F0 || CT <= F0 || momI[i] <= F0)
576 cout << "Calc pitching torque " << pitchingTorqueFac << " " << CT << " " << momI[i] << endl;
577 }
578 }
579
580 // compute vorticity and strain
581 for(MInt i = 0; i < 3; i++) {
582 MInt id0 = (i + 1) % 3;
583 MInt id1 = (id0 + 1) % 3;
584 strain[i] = F1B2 * (fluidVelGradientHat[3 * id1 + id0] + fluidVelGradientHat[3 * id0 + id1]);
585 vort[i] = F1B2 * (fluidVelGradientHat[3 * id1 + id0] - fluidVelGradientHat[3 * id0 + id1]);
586 }
587
588 // Newton iterations
589 while(delta > 1e-10 && it < maxit) {
590 W(0, 1) = -fdtB2 * q[2] * (beta2 - F1) / (beta2 + F1);
591 W(0, 2) = -fdtB2 * q[1] * (beta2 - F1) / (beta2 + F1);
592 W(1, 0) = -fdtB2 * q[2] * (F1 - beta2) / (beta2 + F1);
593 W(1, 2) = -fdtB2 * q[0] * (F1 - beta2) / (beta2 + F1);
594
595 maia::math::invert(W, iW, 3, 3);
596
597 tq[0] = q[1] * q[2] * (beta2 - F1) / (beta2 + F1)
598 + angAccFac * (((F1 - beta2) / (F1 + beta2)) * strain[0] + vort[0] - q[0])
599 / (m_shapeParams[1] + beta2 * m_shapeParams[3])
600 + pitch[0];
601 tq[1] = q[0] * q[2] * (F1 - beta2) / (beta2 + F1)
602 + angAccFac * (((beta2 - F1) / (F1 + beta2)) * strain[1] + vort[1] - q[1])
603 / (m_shapeParams[1] + beta2 * m_shapeParams[3])
604 + pitch[1];
605 tq[2] = angAccFac * (vort[2] - q[2]) / (F2 * m_shapeParams[1]) + pitch[2];
606
607 for(MInt i = 0; i < 3; i++)
608 rhs[i] = q[i] - q0[i] - fdtB2 * (tq0[i] + tq[i]);
609
610 delta = F0;
611 for(MInt i = 0; i < 3; i++) {
612 const MFloat qq = q[i];
613 for(MInt j = 0; j < 3; j++) {
614 q[i] -= iW(i, j) * rhs(j);
615 }
616 delta = mMax(delta, fabs(q[i] - qq));
617 }
618 it++;
619 }
620
621 if(it >= maxit || it <= 0) {
622 cerr << "Newton iterations did not converge " << m_partId << endl;
623 }
624
625 for(MInt i = 0; i < 3; i++) {
626 m_angularVel[i] = q[i];
627 m_angularAccel[i] = tq[i];
628 }
629
630 // integrate quaternions
631 w = m_oldQuaternion[0];
632 x = m_oldQuaternion[1];
633 y = m_oldQuaternion[2];
634 z = m_oldQuaternion[3];
635
636 W(0, 0) = F0;
637 W(0, 1) = -q[0];
638 W(0, 2) = -q[1];
639 W(0, 3) = -q[2];
640 W(1, 0) = q[0];
641 W(1, 1) = F0;
642 W(1, 2) = q[2];
643 W(1, 3) = -q[1];
644 W(2, 0) = q[1];
645 W(2, 1) = -q[2];
646 W(2, 2) = F0;
647 W(2, 3) = q[0];
648 W(3, 0) = q[2];
649 W(3, 1) = q[1];
650 W(3, 2) = -q[0];
651 W(3, 3) = F0;
652
653 for(MInt i = 0; i < 4; i++) {
654 for(MInt j = 0; j < 4; j++) {
655 W(i, j) = -F1B2 * fdtB2 * W(i, j);
656 }
657 W(i, i) = F1;
658 }
659
660 rhs(0) = w + F1B2 * fdtB2 * (-x * q0[0] - y * q0[1] - z * q0[2]);
661 rhs(1) = x + F1B2 * fdtB2 * (w * q0[0] - z * q0[1] + y * q0[2]);
662 rhs(2) = y + F1B2 * fdtB2 * (z * q0[0] + w * q0[1] - x * q0[2]);
663 rhs(3) = z + F1B2 * fdtB2 * (-y * q0[0] + x * q0[1] + w * q0[2]);
664
665 maia::math::invert(W, iW, 4, 4);
666
667 for(MInt i = 0; i < 4; i++) {
668 m_quaternion[i] = F0;
669 for(MInt j = 0; j < 4; j++) {
670 m_quaternion[i] += iW(i, j) * rhs(j);
671 }
672 }
673
674 MFloat abs = F0;
675 for(MInt i = 0; i < 4; i++)
676 abs += POW2(m_quaternion[i]);
677 for(MInt i = 0; i < 4; i++)
678 m_quaternion[i] /= sqrt(abs);
679
680 // integrate linear motion
681 K.fill(F0);
682 K(0, 0) = F1 / (m_shapeParams[0] / POW2(m_semiMinorAxis) + m_shapeParams[1]);
683 K(1, 1) = K(0, 0);
684 K(2, 2) = F1 / (m_shapeParams[0] / POW2(m_semiMinorAxis) + beta2 * m_shapeParams[3]);
685
686 // new drag correlations
687 MFloatScratchSpace accDrag(3, AT_, "accDrag");
688 accDrag.fill(F0);
689 MFloat facCL = liftFactor(Rep, beta, inclinationAngle, K(0, 0), K(2, 2));
690 MFloat facCD = dragFactor(Rep, beta, inclinationAngle, K(0, 0), K(2, 2));
691 for(MInt i = 0; i < nDim; i++) {
692 accLiftHat[i] = addFacCd * facCL * magRelVelHat * dirLHat[i];
693 accDragHat[i] = addFacCd * facCD * magRelVelHat * dirDHat[i];
694 accHat[i] = accDragHat[i] + accLiftHat[i];
695 }
696 maia::math::matrixVectorProductTranspose(&accDrag[0], R, &accHat[0]);
697
698 for(MInt i = 0; i < nDim; i++) {
699 m_accel[i] = accDrag[i] + (1.0 - invDensityRatio) * s_Frm[i];
700 m_velocity[i] = m_oldVel[i] + dt * F1B2 * (m_accel[i] + m_oldAccel[i]);
701 m_position[i] = m_oldPos[i] + dt * F1B2 * (m_velocity[i] + m_oldVel[i]) * s_lengthFactor
702 + F1B4 * POW2(dt) * (m_accel[i] + m_oldAccel[i]);
703 }
704 break;
705 }
706 default: {
707 mTerm(1, AT_, "Unknown particle corrector equation type!");
708 }
709 }
710 }
711
712#ifdef LPT_DEBUG
713 if(m_partId == debugPartId) {
714 cerr << "AT " << m_velocity[0] << " " << m_velocity[1] << " " << m_velocity[2] << endl;
715 }
716#endif
717
718 // 3. update cellId based on the corrected position and set the new status!
720
721#ifdef LPT_DEBUG
722 for(MInt i = 0; i < nDim; i++) {
723 if(std::isnan(m_accel[i])) {
724 cerr << "Nan acc. for " << s_backPtr->domainId() << " " << m_partId << " " << m_position[0] << " "
725 << m_position[1] << " " << m_position[nDim - 1] << " " << s_backPtr->a_isValidCell(m_cellId) << " "
726 << m_oldPos[0] << " " << m_oldPos[1] << " " << m_oldPos[nDim - 1] << " " << m_creationTime << " "
727 << fluidVel[0] << " " << fluidVel[1] << " " << fluidVel[nDim - 1] << fluidDensity << " " << T << " "
728 << fluidViscosity << " " << m_oldVel[0] << " " << m_oldVel[1] << " " << m_oldVel[nDim - 1] << endl;
729 }
730 }
731#endif
732}
MInt m_oldCellId
Definition: lptbase.h:47
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
MFloat liftFactor(const MFloat partRe, const MFloat beta, const MFloat inclinationAngle, const MFloat K0, const MFloat K2)
Calculates the lift factor for current particle with given Re number, aspect ratio,...
static MFloat s_lengthFactor
MFloat fParticleRelTime(const MFloat dynamicViscosity)
Calculates the reciprocal of the particle relaxation time.
MFloat torqueFactor(const MFloat partRe, const MFloat beta, const MFloat inclinationAngle)
Calculates the torque factor for current particle with given Re number, aspect ratio and inclination ...
static MFloat s_Re
void interpolateVelocityAndVelocitySlopes(const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat *const velocityGradient, std::vector< MFloat > &weights)
MFloat m_fluidVelMag
fluid velocity magnitude
MFloat particleRe(const MFloat velocity, const MFloat density, const MFloat dynamicViscosity)
Calculates the particle Reynolds number.
MFloat magRelVel(const MFloat *const velocity1, const MFloat *const velocity2) const
Calculates the magnitude of the relative velocity of the two given velocity vectors.
MFloat dragFactor(const MFloat partRe, const MFloat beta=1, const MFloat inclinationAngle=0, const MFloat K0=0, const MFloat K2=0)
Calculates the drag factor for current particle with given Re number, aspect ratio and inclination an...
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
void cross(const T *const u, const T *const v, T *const c)
Definition: maiamath.h:101
MInt sgn(T val)
Definition: maiamath.h:495
void matrixVectorProduct(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A*b
Definition: maiamath.h:561
void invert(MFloat *A, const MInt m, const MInt n)
Definition: maiamath.cpp:171
define array structures

◆ operator=()

template<MInt nDim>
LPTEllipsoidal & LPTEllipsoidal< nDim >::operator= ( const LPTEllipsoidal< nDim > &  )
default

◆ particleMass()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::particleMass ( ) const
inline

Definition at line 162 of file lptellipsoidal.h.

162 {
163 return F4B3 * PI * POW3(m_semiMinorAxis) * m_aspectRatio * s_backPtr->m_material->density();
164 }
constexpr Real POW3(const Real x)
Definition: functions.h:123

◆ particleRadius()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::particleRadius ( MInt  direction) const
inline

Definition at line 145 of file lptellipsoidal.h.

145 {
146 if(direction == m_particleMajorAxis) {
147 return maxParticleRadius();
148 }
149 return minParticleRadius();
150 }
MFloat minParticleRadius() const
Returns the smallest radius.

◆ particleRe()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::particleRe ( const MFloat  velocity,
const MFloat  density,
const MFloat  dynamicViscosity 
)
inline

Definition at line 176 of file lptellipsoidal.h.

176 {
177 return density * velocity * m_eqDiameter / dynamicViscosity;
178 }

◆ particleVolume()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::particleVolume ( ) const
inline

Definition at line 159 of file lptellipsoidal.h.

159{ return F4B3 * PI * POW3(m_semiMinorAxis) * m_aspectRatio; }

◆ resetWeights()

template<MInt nDim>
void LPTEllipsoidal< nDim >::resetWeights ( )
inlineoverridevirtual

Implements LPTBase< nDim >.

Definition at line 121 of file lptellipsoidal.h.

121 {
122 m_neighborList.clear();
123 this->template interpolateAndCalcWeights<0, 0>(m_cellId, m_position.data(), nullptr, m_redistWeight);
124 };

◆ setParticleFluidVelocities()

template<MInt nDim>
void LPTEllipsoidal< nDim >::setParticleFluidVelocities ( MInt  cellId,
MFloat position,
MFloat quaternions,
MFloat fluidVel,
MFloat fluidVelGrad 
)

◆ torqueFactor()

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::torqueFactor ( const MFloat  partRe,
const MFloat  beta,
const MFloat  inclinationAngle 
)
Author
Laurent Andre
Date
August 2022

Definition at line 821 of file lptellipsoidal.cpp.

821 {
822 MFloat result = NAN;
823 switch(s_backPtr->m_torqueModelType) {
824 case 0: { // torque switched off
825 result = F0;
826 break;
827 }
828 case 1: { // linear
829 result = F1;
830 break;
831 }
832 case 2: { // new correlations by Konstantin (2020)
833 std::array<MFloat, 7> tCorrs{0.931, 0.675, 0.162, 0.657, 2.77, 0.178, 0.177};
834 MFloat CTMax = tCorrs[0] * pow(log(beta), tCorrs[1]) / pow(partRe, tCorrs[2])
835 + tCorrs[3] * pow(log(beta), tCorrs[4]) / pow(partRe, tCorrs[5] + tCorrs[6] * log(beta));
836 MFloat CT = F2 * sin(inclinationAngle) * cos(inclinationAngle) * CTMax;
837 result = CT;
838 break;
839 }
840 default: {
841 mTerm(1, AT_, "Unknown particle torque method");
842 }
843 }
844 return result;
845}

Friends And Related Function Documentation

◆ operator<<

template<MInt nDim>
template<MInt >
std::ostream & operator<< ( std::ostream &  os,
const LPTEllipsoidal< nDim > &  m 
)
friend

Definition at line 243 of file lptellipsoidal.h.

243 {
244 return os << m.m_partId;
245}

Member Data Documentation

◆ m_angularAccel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_angularAccel {}

Definition at line 63 of file lptellipsoidal.h.

◆ m_angularVel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_angularVel {}

Definition at line 61 of file lptellipsoidal.h.

◆ m_aspectRatio

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_aspectRatio = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 85 of file lptellipsoidal.h.

◆ m_eqDiameter

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_eqDiameter = std::numeric_limits<MFloat>::quiet_NaN()
private

Definition at line 209 of file lptellipsoidal.h.

◆ m_fluidDensity

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_fluidDensity = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 67 of file lptellipsoidal.h.

◆ m_fluidVel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_fluidVel {}

Definition at line 65 of file lptellipsoidal.h.

◆ m_fluidVelMag

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_fluidVelMag = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 98 of file lptellipsoidal.h.

◆ m_heatFlux

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_heatFlux = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 100 of file lptellipsoidal.h.

◆ m_oldAccel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_oldAccel {}

Definition at line 70 of file lptellipsoidal.h.

◆ m_oldAngularAccel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_oldAngularAccel {}

Definition at line 74 of file lptellipsoidal.h.

◆ m_oldAngularVel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_oldAngularVel {}

Definition at line 72 of file lptellipsoidal.h.

◆ m_oldFluidDensity

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_oldFluidDensity = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 82 of file lptellipsoidal.h.

◆ m_oldFluidVel

template<MInt nDim>
std::array<MFloat, nDim> LPTEllipsoidal< nDim >::m_oldFluidVel {}

Definition at line 76 of file lptellipsoidal.h.

◆ m_oldQuaternion

template<MInt nDim>
std::array<MFloat, 4> LPTEllipsoidal< nDim >::m_oldQuaternion {}

Definition at line 93 of file lptellipsoidal.h.

◆ m_particleMajorAxis

template<MInt nDim>
MInt LPTEllipsoidal< nDim >::m_particleMajorAxis = 2

Definition at line 105 of file lptellipsoidal.h.

◆ m_quaternion

template<MInt nDim>
std::array<MFloat, 4> LPTEllipsoidal< nDim >::m_quaternion {}

Definition at line 92 of file lptellipsoidal.h.

◆ m_redistWeight

template<MInt nDim>
std::vector<MFloat> LPTEllipsoidal< nDim >::m_redistWeight {}

Definition at line 115 of file lptellipsoidal.h.

◆ m_semiMinorAxis

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_semiMinorAxis = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 87 of file lptellipsoidal.h.

◆ m_shapeParams

template<MInt nDim>
std::array<MFloat, 4> LPTEllipsoidal< nDim >::m_shapeParams {std::numeric_limits<MFloat>::quiet_NaN()}

Definition at line 89 of file lptellipsoidal.h.

◆ m_temperature

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::m_temperature = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 96 of file lptellipsoidal.h.

◆ m_velocityGradientFluid

template<MInt nDim>
std::array<MFloat, nDim * nDim> LPTEllipsoidal< nDim >::m_velocityGradientFluid {}

Definition at line 79 of file lptellipsoidal.h.

◆ s_floatElements

template<MInt nDim>
constexpr MInt LPTEllipsoidal< nDim >::s_floatElements = 7 + 8 * nDim + 4 * 2
staticconstexpr

Definition at line 102 of file lptellipsoidal.h.

◆ s_Frm

template<MInt nDim>
std::array< MFloat, nDim > LPTEllipsoidal< nDim >::s_Frm {}
static

Definition at line 112 of file lptellipsoidal.h.

◆ s_intElements

template<MInt nDim>
constexpr MInt LPTEllipsoidal< nDim >::s_intElements = 0
staticconstexpr

Definition at line 103 of file lptellipsoidal.h.

◆ s_lengthFactor

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::s_lengthFactor = F1
static

Definition at line 107 of file lptellipsoidal.h.

◆ s_Pr

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::s_Pr = F1
static

Definition at line 109 of file lptellipsoidal.h.

◆ s_Re

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::s_Re = F1
static

Definition at line 108 of file lptellipsoidal.h.

◆ s_Sc

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::s_Sc = F1
static

Definition at line 110 of file lptellipsoidal.h.

◆ s_We

template<MInt nDim>
MFloat LPTEllipsoidal< nDim >::s_We
static

Definition at line 111 of file lptellipsoidal.h.


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