MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
LbSolverDxQy< nDim, nDist, SysEqn > Class Template Reference

This class represents all LB models. More...

#include <lbsolverdxqy.h>

Inheritance diagram for LbSolverDxQy< nDim, nDist, SysEqn >:
[legend]
Collaboration diagram for LbSolverDxQy< nDim, nDist, SysEqn >:
[legend]

Public Types

using Base = LbSolver< nDim >
 
using GridProxy = typename LbSolver< nDim >::GridProxy
 
using LbBndCnd = LbBndCndDxQy< nDim, nDist, SysEqn >
 
using Ld = LbLatticeDescriptor< nDim, nDist >
 

Public Member Functions

 LbSolverDxQy (MInt id, MInt noDistributions, GridProxy &gridProxy_, Geometry< nDim > &geometry_, const MPI_Comm comm)
 
 ~LbSolverDxQy ()
 
constexpr SysEqn sysEqn () const
 
virtual void initializeLatticeBgk ()
 Initializes standard Lattice BGK. More...
 
void initLatticeBgkFftPipe ()
 
void initLatticeBgkFftChannel ()
 
void initLatticeBgkFftMixing ()
 
void initLatticeBgkFftMixingFilter ()
 
void initLatticeBgkFftIsotropicTurbulence ()
 
virtual void initLatticeBgkLaminarChannel ()
 
virtual void initLatticeBgkTurbulentChannel ()
 
virtual void initLatticeBgkTurbulentMixing ()
 
virtual void initLatticeBgkTurbulentBoundary ()
 
virtual void initLatticeBgkTurbulentPipe ()
 
virtual void initLatticeBgkTurbulentDuct ()
 
virtual void initLatticeBgkLaminarPipe ()
 
virtual void initLatticeBgkVortex ()
 
virtual void initLatticeBgkTGV ()
 
void initLatticeBgkSpinningVorticies ()
 
void initLatticeBgkGaussPulse ()
 
void initLatticeBgkGaussDiffusion ()
 
void initLatticeBgkGaussAdvection ()
 
void initLatticeBgkLaminarCylinder ()
 
virtual void initLatticeBgkLaminarDir (MInt dir)
 Initializes standard Lattice BGK laminar with or without a direction. More...
 
virtual void initLatticeBgkLaminar ()
 
void initEqDistFunctions ()
 Calculates equilibrium distribution functions after initialization of macroscopic variables. More...
 
void initNonEqDistFunctions ()
 
virtual void initThermalEqDistFunctions ()
 Calculates equilibrium distribution functions after initialization of macroscopic variables. More...
 
virtual void initTransportEqDistFunctions ()
 Calculates equilibrium distribution functions after initialization of macroscopic variables. More...
 
virtual void restartInitLb ()
 
virtual void propagation_step () override
 standard OpenMP propagation step More...
 
virtual void propagation_step_vol () override
 This function propagates the locally calculated PPDFs to the neighboring cells after the collision step. The volumetric refinement scheme requires prolongation to take place before propagation. More...
 
virtual void propagation_step_thermal () override
 
virtual void propagation_step_thermal_vol () override
 Propagation step for Thermal Lattice-Boltzmann. More...
 
virtual void propagation_step_transport () override
 Propagation step for Transport Lattice-Boltzmann. More...
 
virtual void propagation_step_transport_vol () override
 Propagation step for Transport Lattice-Boltzmann. More...
 
virtual void propagation_step_thermaltransport () override
 Propagation step for coupled Thermal Transport Lattice-Boltzmann. More...
 
virtual void propagation_step_thermaltransport_vol () override
 Propagation step for coupled Thermal Transport Lattice-Boltzmann. More...
 
template<MInt timeStepOffset = 0>
void updateVariablesFromOldDist_ ()
 
virtual void updateVariablesFromOldDist () override
 
virtual void updateVariablesFromOldDist_preCollision () override
 
virtual void volumeForces ()
 apply volumeForces to the oldDistributions More...
 
virtual void controlVelocity ()
 control velocity of a periodic channel flow via volume forces More...
 
virtual void averageGlobalVelocity (const MInt dir)
 calculate average velocity of velocity component dir More...
 
virtual void removeChildsLb (const MInt parentId)
 : Initialize parent variables from children More...
 
virtual void refineCellLb (const MInt parentId, const MInt *childIds)
 : Initialize child variables from parent More...
 
virtual void restartBndCnd ()
 Restart bndCnd object. More...
 
void sensorVorticity (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 
void sensorDivergence (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 
void sensorTotalPressure (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 
void sensorInterface (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 Simple boundary sensor for ensuring boundary refinement during adaptation. More...
 
void sensorMeanStress (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 
template<MBool useSmagorinsky>
void clb_collision_step_base ()
 
void clb_collision_step () override
 
void clb_smagorinsky_collision_step () override
 
void cumulant_collision_step () override
 
virtual void bgki_collision_step ()
 
virtual void bgki_thermal_collision_step ()
 
virtual void bgki_innerEnergy_collision_step ()
 
virtual void bgki_totalEnergy_collision_step ()
 
virtual void bgkc_transport_collision_step ()
 Collision step for Transport Lattice-Boltzmann. More...
 
virtual void bgkc_thermal_transport_collision_step ()
 Collision step for coupled Thermal Transport Lattice-Boltzmann. More...
 
virtual void bgkc_innerenergy_transport_collision_step ()
 Collision step for coupled Thermal Transport Lattice-Boltzmann. More...
 
virtual void bgkc_totalenergy_transport_collision_step ()
 Collision step for coupled Thermal Transport Lattice-Boltzmann. More...
 
void bgki_collision_step_Guo_forcing () override
 
template<MBool compressible = false>
void calculateMomentumFlux (const MInt pCellId)
 Calculate and set momentum flux for a given cell. More...
 
template<MBool compressible = false>
void calculateMomentumFlux (const MInt pCellId, MFloat *const momentumFlux)
 Calculate and set momentum flux for a given cell. More...
 
template<MBool compressible = false>
void calculateMacroscopicVariables (const MInt cellId, MFloat &rho, MFloat *const u)
 Calculate macroscopic variables for a given cell. More...
 
void calculateDissipation ()
 Calculate total energy, dissipation, and subgrid dissipation for Smagorinsky. More...
 
template<MBool optimized, MBool useSmagorinsky>
void mrt_collision_step_base ()
 Collision step for the MRT-Algorithm. More...
 
void mrt_collision_step () override
 
void mrt2_collision_step () override
 
void mrt_smagorinsky_collision_step () override
 
void bgki_euler_collision_step () override
 
void bgki_init_collision_step () override
 Consistent initialization step of the LBGK algorithm. More...
 
void bgkc_collision_step () override
 
void bgki_dynamic_smago_collision_step () override
 
template<MInt mode>
void bgki_smagorinsky_collision_step_base ()
 
template<MInt thermalMode>
void bgki_thermal_collision_step_base ()
 
template<MInt thermalMode>
void bgki_thermal_and_transport_collision_step_base ()
 Collision step for coupled Thermal Transport Lattice-Boltzmann. More...
 
void bgki_smagorinsky_collision_step () override
 
void bgki_smagorinsky_collision_step2 () override
 
void bgki_smago_wall_collision_step () override
 
template<MBool useSmagorinsky>
void rbgk_collision_step_base ()
 
void rbgk_collision_step () override
 
void rbgk_smagorinsky_collision_step () override
 
void rbgk_dynamic_smago_collision_step () override
 
virtual void calculateResidual ()
 Calculates residuals and prints to file. More...
 
void initSrcTermController () override
 Initialize the source term controller. More...
 
void initSrcTerms () override
 Initialize the source term controller. More...
 
void preCollisionSrcTerm () override
 Calls the pre collision routine of the source term controller. More...
 
void postCollisionSrcTerm () override
 Calls the post collision routine of the source term controller. More...
 
void postPropagationSrcTerm () override
 Calls the post collision routine of the source term controller. More...
 
void postCollisionBc () override
 
void postPropagationBc () override
 
virtual void calcNodalLsValues ()
 
virtual MBool maxResidual ()
 
void averageSGSTensors (const MInt direction, MInt &count, std::vector< MFloat > &meanTensors)
 Calculate average SGS tensor. More...
 
void updateMacroscopicVariables ()
 Update macroscopic variables according to incoming PPDF. More...
 
void updateViscosity () override
 Update viscosity (a_nu and a_oldNu) More...
 
void calculateSGSTensors ()
 Calculate tensors for dynamic Smagorinsky constant. More...
 
void initArraysForPSTL ()
 
void setEqDists (const MInt cellId, const MFloat rho, const MFloat *const velocity)
 Set BOTH distributions to equilibrium. More...
 
void setEqDists (const MInt cellId, const MFloat rho, const MFloat squaredVelocity, const MFloat *const velocity)
 Set BOTH distributions to equilibrium. More...
 
void setEqDistsThermal (const MInt cellId, const MFloat T, const MFloat rho, const MFloat *const velocity)
 Calls function for setting thermal distributions to equilibrium. More...
 
void setEqDistsThermal (const MInt cellId, const MFloat T, const MFloat rho, const MFloat squaredVelocity, const MFloat *const velocity)
 Calls function for setting thermal distributions to equilibrium. More...
 
template<MInt thermalMode>
void setEqDistsThermal_ (const MInt cellId, const MFloat T, const MFloat rho, const MFloat *const velocity)
 Set BOTH thermal distributions to equilibrium. More...
 
template<MInt thermalMode>
void setEqDistsThermal_ (const MInt cellId, const MFloat T, const MFloat rho, const MFloat squaredVelocity, const MFloat *const velocity)
 Set BOTH thermal distributions to equilibrium. More...
 
void setEqDistsTransport (const MInt cellId, const MFloat C, const MFloat *const velocity)
 Set BOTH transport distributions to equilibrium. More...
 
void setEqDistsTransport (const MInt cellId, const MFloat C, const MFloat squaredVelocity, const MFloat *const velocity)
 Set BOTH transport distributions to equilibrium. More...
 
std::array< MFloat, nDist > getEqDists (const MFloat rho, const MFloat *const velocity)
 Calls function to return the equilibrium distribution. More...
 
std::array< MFloat, nDist > getEqDists (const MFloat rho, const MFloat squaredVelocity, const MFloat *const velocity)
 Calls function to return the equilibrium distribution. More...
 
std::array< MFloat, nDist > getEqDistsThermal (const MFloat t, const MFloat rho, const MFloat *const velocity)
 Calls function to return the thermal equilibrium distribution. More...
 
std::array< MFloat, nDist > getEqDistsThermal (const MFloat t, const MFloat rho, const MFloat squaredVelocity, const MFloat *const velocity)
 Calls function to return the thermal equilibrium distribution. More...
 
template<MInt thermalMode>
std::array< MFloat, nDist > getEqDistsThermal_ (const MFloat t, const MFloat rho, const MFloat *const velocity)
 Return thermal distributions to equilibrium. More...
 
template<MInt thermalMode>
std::array< MFloat, nDist > getEqDistsThermal_ (const MFloat t, const MFloat rho, const MFloat squaredVelocity, const MFloat *const velocity)
 Return thermal distributions to equilibrium. More...
 
std::array< MFloat, nDist > getEqDistsTransport (const MFloat c, const MFloat *const velocity)
 Return transport distributions to equilibrium. More...
 
std::array< MFloat, nDist > getEqDistsTransport (const MFloat c, const MFloat squaredVelocity, const MFloat *const velocity)
 Return transport distributions to equilibrium. More...
 
void clb_collision_step_base ()
 
void clb_collision_step_base ()
 
void clb_collision_step_base ()
 
void cumulant_collision_step ()
 
void mrt_collision_step_base ()
 
void mrt_collision_step_base ()
 
void initLatticeBgkFftChannel ()
 
void initLatticeBgkFftPipe ()
 
void initLatticeBgkFftMixing ()
 
void initLatticeBgkFftMixingFilter ()
 
void initLatticeBgkFftIsotropicTurbulence ()
 

Public Attributes

const SysEqn m_sysEqn {}
 
std::mt19937 randNumGen
 
std::uniform_real_distribution distrib {0.0, 1.0}
 

Static Public Attributes

static constexpr MInt m_noDistributions = nDist
 

Protected Attributes

LbBndCndm_bndCnd
 Pointers for the Boundary Conditions, for flow solving. More...
 
maia::lb::LbSrcTermController< nDim, nDist, SysEqn > m_srcTermController
 
LbInterfaceDxQy< nDim, nDist, SysEqn > * m_interface
 
void(LbSolverDxQy< nDim, nDist, SysEqn >::* m_initMethodPtr )()
 Pointers for the Boundary Conditions, for flow solving. More...
 

Private Member Functions

void prolongation ()
 
void restriction ()
 
void initPressureForce () override
 
void initVolumeForces () override
 
template<MBool compressible>
void initRunCorrection_ ()
 Iterative initialize routine to obtained a valid density and non-eq field. More...
 
void initRunCorrection () override
 

Private Attributes

MFloat m_smallestCellLength {}
 
const MFloat C1
 
const MFloat C2
 
const MFloat C3
 
const MFloat C4
 

Friends

template<MInt nDim_, MInt nDist_, class SysEqn_ >
class LbBndCndDxQy
 
template<MInt nDim_, MInt nDist_, class SysEqn_ >
class LbInterfaceDxQy
 
template<MInt nDim_>
class LbInterface
 
template<MInt nDim_, MInt nDist_, class SysEqn_ >
class CouplingLB
 

Detailed Description

template<MInt nDim, MInt nDist, class SysEqn>
class LbSolverDxQy< nDim, nDist, SysEqn >

Definition at line 29 of file lbsolverdxqy.h.

Member Typedef Documentation

◆ Base

template<MInt nDim, MInt nDist, class SysEqn >
using LbSolverDxQy< nDim, nDist, SysEqn >::Base = LbSolver<nDim>

Definition at line 33 of file lbsolverdxqy.h.

◆ GridProxy

template<MInt nDim, MInt nDist, class SysEqn >
using LbSolverDxQy< nDim, nDist, SysEqn >::GridProxy = typename LbSolver<nDim>::GridProxy

Definition at line 34 of file lbsolverdxqy.h.

◆ LbBndCnd

template<MInt nDim, MInt nDist, class SysEqn >
using LbSolverDxQy< nDim, nDist, SysEqn >::LbBndCnd = LbBndCndDxQy<nDim, nDist, SysEqn>

Definition at line 35 of file lbsolverdxqy.h.

◆ Ld

template<MInt nDim, MInt nDist, class SysEqn >
using LbSolverDxQy< nDim, nDist, SysEqn >::Ld = LbLatticeDescriptor<nDim, nDist>

Definition at line 179 of file lbsolverdxqy.h.

Constructor & Destructor Documentation

◆ LbSolverDxQy()

template<MInt nDim, MInt nDist, class SysEqn >
LbSolverDxQy< nDim, nDist, SysEqn >::LbSolverDxQy ( MInt  id,
MInt  noDistributions,
GridProxy gridProxy_,
Geometry< nDim > &  geometry_,
const MPI_Comm  comm 
)

Definition at line 25 of file lbsolverdxqy.cpp.

27 : LbSolver<nDim>(id, noDistributions, gridProxy_, geometry_, comm),
29 C1(5.0),
30 C2(-3.05),
31 C3(2.5),
32 C4(5.5) // Constants for Law of the Wall
33{
34 TRACE();
35
36 if(m_isRefined || this->m_adaptation) m_interface = new LbInterfaceDxQy<nDim, nDist, SysEqn>(this);
37
38 m_bndCnd = new LbBndCnd(this);
40
41 if(grid().isActive()) {
42 this->prepareCommunication();
43 if(m_geometry->m_parallelGeometry) {
44 this->receiveWindowTriangles();
45 }
46 }
47
48 m_log << "noCells(offset) =" << this->noInternalCells() << endl;
49 m_log << "noCells(size) =" << this->m_cells.size() << endl;
50
51#ifdef WAR_NVHPC_PSTL
53#endif
54}
Interface class holding all relevant data and methods for treating prolongation, restriction and init...
const MFloat C2
Definition: lbsolverdxqy.h:354
void initArraysForPSTL()
const MFloat C4
Definition: lbsolverdxqy.h:354
const MFloat C3
Definition: lbsolverdxqy.h:354
LbInterfaceDxQy< nDim, nDist, SysEqn > * m_interface
Definition: lbsolverdxqy.h:334
LbBndCndDxQy< nDim, nDist, SysEqn > LbBndCnd
Definition: lbsolverdxqy.h:35
LbBndCnd * m_bndCnd
Pointers for the Boundary Conditions, for flow solving.
Definition: lbsolverdxqy.h:332
maia::lb::LbSrcTermController< nDim, nDist, SysEqn > m_srcTermController
Definition: lbsolverdxqy.h:333
const MFloat C1
Definition: lbsolverdxqy.h:354
InfoOutFile m_log

◆ ~LbSolverDxQy()

template<MInt nDim, MInt nDist, class SysEqn >
LbSolverDxQy< nDim, nDist, SysEqn >::~LbSolverDxQy

Definition at line 60 of file lbsolverdxqy.cpp.

60 {
61 TRACE();
62 if(m_isRefined || this->m_adaptation) delete m_interface;
63 delete m_bndCnd;
64}

Member Function Documentation

◆ averageGlobalVelocity()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::averageGlobalVelocity ( const MInt  dir)
virtual
Author
Daniel Lauwers
Date
June 2021

This function calculates the average velocity of all leaf cells (weighted by their volume) thoughout all domains. The value is saved to m_velocityControl.lastGlobalAvgV

Parameters
[in]dirthe velocity component to average

Definition at line 563 of file lbsolverdxqy.cpp.

563 {
564 MFloat sumV[2] = {}; // Sum of {velocity * cellVolume, cellVolume}
565 MFloat c1 = 0.0;
566
567 // the velocity component of sumV is summed by Kahan summation because of potential for different orders of magnitude
568 // for the cell volume normal summation is used
569 for(MInt cellId = 0; cellId < this->grid().noInternalCells(); cellId++) {
570 if(this->c_noChildren(cellId) != 0) continue;
571 const MFloat cellVolume = this->grid().cellVolumeAtLevel(this->c_level(cellId));
572
573 const MFloat y1 = a_variable(cellId, dir) * cellVolume - c1;
574 const MFloat t1 = sumV[0] + y1;
575 c1 = (t1 - sumV[0]) - y1;
576 sumV[0] = t1;
577 sumV[1] += cellVolume;
578 }
579 MPI_Allreduce(MPI_IN_PLACE, &sumV, 2, maia::type_traits<MFloat>::mpiType(), MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
580 "sumV");
581
582 m_velocityControl.lastGlobalAvgV = sumV[0] / sumV[1];
583}
int32_t MInt
Definition: maiatypes.h:62
double MFloat
Definition: maiatypes.h:52
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
void const MInt cellId
Definition: collector.h:239

◆ averageSGSTensors()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::averageSGSTensors ( const MInt  direction,
MInt count,
std::vector< MFloat > &  meanTensors 
)
Parameters
[in]directiondirection of the line
[out]countnumber of points in direction
[out]meanTensorsMean SGS tensor

Calculate average values for Cs along a line in chosen direction and return mean tensor and number of points of the line.

Definition at line 4578 of file lbsolverdxqy.cpp.

4579 {
4580 TRACE();
4581
4582 // MInt tmpId;
4583 // MInt saveId;
4584 // MInt tmpCt[3];
4585 // MFloat tmpMin[3];
4586 // MFloat tmpLength[3];
4587 //
4588 // /***********************************************/
4589 // /* Count all cells in x,y, and z-direction*/
4590 // for(MInt i=0; i < this->grid().noInternalCells(); i++){
4591 // // Ignore halo cells
4592 // if(cells[i].m_level < 0 )
4593 // continue;
4594 // if(this->c_noChildren(i)==0){
4595 // tmpId=i;
4596 // // Go to lowest level
4597 // while(c_parentId(tmpId) > -1){
4598 // tmpId=c_parentId(tmpId);
4599 // }
4600 // saveId = tmpId;
4601 // for(MInt j=0; j < 2*nDim; j+=2){
4602 // tmpId = saveId;
4603 // // Go to the last cell in current direction
4604 // while(a_hasNeighbor(tmpId, j)){
4605 // if( a_coordinate(c_neighborId(tmpId, j), j/2) < a_coordinate(tmpId, j/2) ){
4606 // tmpId=c_neighborId(tmpId, j);
4607 // }
4608 // else
4609 // break;
4610 // }
4611 //
4612 // tmpMin[j/2] = a_coordinate(tmpId, j/2);
4613 // tmpLength[j/2] = a_coordinate(tmpId, j/2);
4614 // // Go to the first cell in current direction
4615 // tmpCt[j/2] = 1;
4616 // while(a_hasNeighbor(tmpId, Ld::oppositeDist(j))){
4617 // if( a_coordinate(c_neighborId(tmpId, Ld::oppositeDist(j)), j/2) > a_coordinate(tmpId, j/2) ){
4618 // tmpId=c_neighborId(tmpId, Ld::oppositeDist(j));
4619 // tmpCt[j/2]++;
4620 // }
4621 // else
4622 // break;
4623 // }
4624 //
4625 // tmpLength[j/2] = (a_coordinate(tmpId, j/2) - tmpLength[j/2]);
4626 // }
4627 // }
4628 // break;
4629 // }
4630
4631 const MInt(&tmpCt)[nDim] = m_arraySize;
4632 count = tmpCt[direction];
4633
4634 ScratchSpace<MFloat> ML(tmpCt[direction], AT_, "ML");
4635 ScratchSpace<MFloat> MM(tmpCt[direction], AT_, "MM");
4636 meanTensors.resize(tmpCt[direction]);
4637
4638 for(MInt i = 0; i < tmpCt[direction]; i++) {
4639 MM[i] = F0;
4640 ML[i] = F0;
4641 meanTensors[i] = F0;
4642 }
4643
4644 // Sum up values
4645 for(MInt i = 0; i < this->grid().noInternalCells(); i++) {
4646 const MFloat actualCellLength = this->grid().cellLengthAtCell(i);
4647
4648 // const MInt index = (MInt)((a_coordinate(i, direction) - tmpMin[direction]) / (MFloat)tmpLength[direction]
4649 // * MFloat(tmpCt[direction] - 1) + 0.5);
4650
4651 const MInt index =
4652 floor((F1B2 * tmpCt[direction]
4653 + (a_coordinate(i, direction) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
4654 + 0.1);
4655
4656 if(index < 0 || index >= tmpCt[direction]) {
4657 cerr << "error: index=" << index << endl;
4658 m_log << "error: index=" << index << endl;
4659 }
4660
4661 ML[index] += m_MijLij[i];
4662 MM[index] += m_MijMij[i];
4663 }
4664
4665 m_log.precision(12);
4666
4667 // Sum-Up over all domains
4668 MPI_Allreduce(MPI_IN_PLACE, MM.data(), count, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "MM");
4669 MPI_Allreduce(MPI_IN_PLACE, ML.data(), count, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "ML");
4670
4671 // // Normalize
4672 // for(MInt i=0; i < tmpCt[direction]; i++){
4673 // MM[i] *= ((MFloat)tmpCt[direction] / (MFloat)(tmpCt[0]*tmpCt[1]*tmpCt[2])) ;
4674 // ML[i] *= ((MFloat)tmpCt[direction] / (MFloat)(tmpCt[0]*tmpCt[1]*tmpCt[2])) ;
4675 // }
4676
4677 // Divide
4678 for(MInt i = 2; i < tmpCt[direction] - 2; i++) {
4679 if(MM[i] > 1e-12) meanTensors[i] = ML[i] / MM[i];
4680 }
4681}
This class is a ScratchSpace.
Definition: scratch.h:758
IdType index(const FloatType *const x, const IdType level)
Return Hilbert index for given location and level in 2D or 3D.
Definition: hilbert.h:165

◆ bgkc_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgkc_collision_step
override
Author
Ludwig Eduard Boltzmann
Date
20.2.1844
Property value solverMethod
MAIA_LATTICE_BGKC

Common BGK collision step.

Definition at line 1737 of file lbsolverdxqy.cpp.

1737 {
1738 TRACE();
1739 const MInt globalTimeStep_ = globalTimeStep;
1740 // loop over all cells
1741 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt i) {
1742 const MInt pCellId = m_activeCellList[i];
1743 const MInt lvlDiff = maxLevel() - this->a_level(pCellId);
1744 if((globalTimeStep_ - 1) % IPOW2(lvlDiff) != 0) return;
1745 // Load macroscopic variables
1746 const MFloat rho = a_variable(pCellId, PV->RHO);
1747 std::array<MFloat, nDim> uu;
1748 for(MInt j = 0; j < nDim; j++) {
1749 uu[j] = a_variable(pCellId, PV->U + j);
1750 }
1751 // Collision
1752 const MFloat omega = 1.0 / (0.5 + F1BCSsq * a_nu(pCellId) * FFPOW2(lvlDiff));
1753 std::array<MFloat, nDist> eqDist;
1754 eqDist = getEqDists(rho, uu.data());
1755 for(MInt j = 0; j < nDist; j++) {
1756 a_distribution(pCellId, j) = a_oldDistribution(pCellId, j) + omega * (eqDist[j] - a_oldDistribution(pCellId, j));
1757 }
1758 });
1759}
std::array< MFloat, nDist > getEqDists(const MFloat rho, const MFloat *const velocity)
Calls function to return the equilibrium distribution.
Definition: lbsolverdxqy.h:668
MInt globalTimeStep
constexpr MLong IPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)

◆ bgkc_innerenergy_transport_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgkc_innerenergy_transport_collision_step
virtual
Author
Moritz Waldmann
Date
09.10.23

Definition at line 2616 of file lbsolverdxqy.cpp.

2616 {
2617 TRACE();
2618
2619 bgki_thermal_and_transport_collision_step_base<1>();
2620}

◆ bgkc_thermal_transport_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgkc_thermal_transport_collision_step
virtual
Author
Shota Ito
Date
13.06.22

Definition at line 2604 of file lbsolverdxqy.cpp.

2604 {
2605 TRACE();
2606
2607 bgki_thermal_and_transport_collision_step_base<0>();
2608}

◆ bgkc_totalenergy_transport_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgkc_totalenergy_transport_collision_step
virtual
Author
Moritz Waldmann
Date
09.10.23

Definition at line 2628 of file lbsolverdxqy.cpp.

2628 {
2629 TRACE();
2630
2631 bgki_thermal_and_transport_collision_step_base<2>();
2632}

◆ bgkc_transport_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgkc_transport_collision_step
virtual
Author
Shota Ito
Date
07.06.22

Definition at line 2111 of file lbsolverdxqy.cpp.

2111 {
2112 TRACE();
2113
2114 const MInt pvrho = PV->RHO;
2115 const MInt pvc = PV->C;
2116
2117 constexpr MInt fldlen = Ld::dxQyFld();
2118
2119 // Update the global Reynolds number if we use the tanh-adaption
2120 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
2121 const MFloat scale =
2122 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
2123 + 0.5;
2124
2125 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
2126
2127 // final timestep reached
2128 if(globalTimeStep == m_initStartTime + m_initTime) {
2129 m_Re = m_finalRe;
2130 m_tanhInit = 0;
2131 }
2132 }
2133
2134 // Update the according nu
2135 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
2136
2137 // Calculate heat diffusion coefficient
2138 m_diffusivity = m_nu * (m_Re / m_Pe);
2139
2140#ifndef WAR_NVHPC_PSTL
2141 // inner loop references
2142 const MInt* const RESTRICT activeCellList = ALIGNED_I(m_activeCellList);
2143 MFloat* const RESTRICT cnu = ALIGNED_MF(&(a_nu(0)));
2144 MFloat* const RESTRICT cdiffusivity = ALIGNED_MF(&(a_diffusivity(0)));
2145 const MInt* const RESTRICT clevel = ALIGNED_I(&(this->m_cells.level(0)));
2146 MFloat* const RESTRICT oldDistributions = ALIGNED_MF(&(a_oldDistribution(0, 0)));
2147 MFloat* const RESTRICT distributions = ALIGNED_MF(&(a_distribution(0, 0)));
2148 MFloat* const RESTRICT oldDistributionsTransport = ALIGNED_MF(&(a_oldDistributionTransport(0, 0)));
2149 MFloat* const RESTRICT distributionsTransport = ALIGNED_MF(&(a_distributionTransport(0, 0)));
2150 MFloat* const RESTRICT variables = ALIGNED_MF(&(a_variable(0, 0)));
2151
2152 // members and globals
2153 const MInt maxLevel_ = maxLevel();
2154 // distances
2155 const MInt distNu = &a_nu(1) - &a_nu(0);
2156 const MInt distDiffusivity = &a_diffusivity(1) - &a_diffusivity(0);
2157 const MInt distLevel = &(this->m_cells.level(1)) - &(this->m_cells.level(0));
2158 const MInt distVars = &(a_variable(1, 0)) - &(a_variable(0, 0));
2159#endif
2160 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
2161 const MInt gTS = globalTimeStep;
2162
2163 // loop over all cells
2164 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt i) {
2165#ifdef WAR_NVHPC_PSTL
2166 const MInt pCellId = m_activeCellList[i];
2167 const MInt index = maxLevel() - this->a_level(pCellId);
2168#else
2169 const MInt pCellId = activeCellList[i];
2170 const MInt index = maxLevel_ - clevel[pCellId * distLevel];
2171#endif
2172
2173 // perform collision on finest level in every timestep,
2174 // on the next coarser level every second timestep, and so on
2175 if((gTS - 1) % IPOW2(index) == 0) {
2176 // save nu for bndcnd and interface interpolation
2177#ifndef WAR_NVHPC_PSTL
2178 cnu[pCellId * distNu] = m_nu;
2179 cdiffusivity[pCellId * distDiffusivity] = m_diffusivity;
2180
2181 const MInt distStart = pCellId * nDist;
2182 // varStart = (pCellId * distVars) + (distVarOldVar *
2183 // !((MInt)floor((MFloat)localGlobalTimeStep/fpow2[index]) % 2));
2184 const MInt varStart = pCellId * distVars;
2185
2186 MFloat* const oldDistributionsStart = &oldDistributions[distStart];
2187 MFloat* const distributionsStart = &distributions[distStart];
2188 MFloat* const oldDistributionsTransportStart = &oldDistributionsTransport[distStart];
2189 MFloat* const distributionsTransportStart = &distributionsTransport[distStart];
2190
2191 MFloat* const variablesStart = &variables[varStart];
2192#else
2193 a_nu(pCellId) = m_nu;
2194 a_kappa(pCellId) = m_kappa;
2195#endif
2196
2197 const MFloat tmp_FFPOW2 = FFPOW2(index);
2198 const MFloat l_omega = 2.0 / (1.0 + 6.0 * m_nu * tmp_FFPOW2);
2199 const MFloat l_omegaD = 2.0 / (1.0 + 6.0 * m_diffusivity * tmp_FFPOW2);
2200
2201 swap_variables(pCellId);
2202
2203 // Reinit macroscopic variables before recalculation
2204 MFloat l_v[nDim] = {0.0};
2205 MFloat l_rho = 0.0;
2206 MFloat l_c = 0.0;
2207
2208#ifdef WAR_NVHPC_PSTL
2209 // Add forcing term and calculate density rho
2210 for(MInt j = 0; j < nDist - 1; j++) {
2211 // Add forcing term and calculate density rho
2212 l_rho += a_oldDistribution(pCellId, j);
2213 l_c += a_oldDistributionTransport(pCellId, j);
2214 }
2215 // Do not forget the last distribution
2216 l_rho += a_oldDistribution(pCellId, nDist - 1);
2217 l_c += a_oldDistributionTransport(pCellId, nDist - 1);
2218#else
2219 // Add forcing term and calculate density rho
2220 for(MInt j = 0; j < nDist - 1; j++) {
2221 l_rho += oldDistributionsStart[j];
2222 l_c += oldDistributionsTransportStart[j];
2223 }
2224 // Do not forget the last distribution
2225 l_rho += oldDistributionsStart[nDist - 1];
2226 l_c += oldDistributionsTransportStart[nDist - 1];
2227#endif
2228
2229 // Calculate macroscopic variables
2230#ifndef WAR_NVHPC_PSTL
2231 if constexpr(nDim == 2) {
2232 // WARNING!!! The velocity should be calculated as in 3d
2233 // However, result is correct
2234 // calculation of u
2235 l_v[0] = oldDistributionsStart[1] + oldDistributionsStart[4] + oldDistributionsStart[5]
2236 - oldDistributionsStart[7] - oldDistributionsStart[6] - oldDistributionsStart[0];
2237 // calculation of v
2238 l_v[1] = oldDistributionsStart[7] + oldDistributionsStart[3] + oldDistributionsStart[4]
2239 - oldDistributionsStart[6] - oldDistributionsStart[2] - oldDistributionsStart[5];
2240 } else {
2241#endif
2242 for(MInt j = 0; j < fldlen; j++) {
2243 for(MInt d = 0; d < nDim; d++) {
2244#ifdef WAR_NVHPC_PSTL
2245 l_v[d] += a_oldDistribution(pCellId, m_pFld[d * fldlen + j]);
2246 l_v[d] -= a_oldDistribution(pCellId, m_nFld[d * fldlen + j]);
2247#else
2248 l_v[d] += oldDistributionsStart[Ld::pFld(d, j)];
2249 l_v[d] -= oldDistributionsStart[Ld::nFld(d, j)];
2250#endif
2251 }
2252 }
2253#ifndef WAR_NVHPC_PSTL
2254 }
2255#endif
2256
2257 // Save new macroscopic variables in cell
2258#ifdef WAR_NVHPC_PSTL
2259 for(MInt d = 0; d < nDim; d++) {
2260 a_variable(pCellId, d) = l_v[d];
2261 }
2262 a_variable(pCellId, pvrho) = l_rho;
2263 a_variable(pCellId, pvc) = l_c;
2264#else
2265 for(MInt d = 0; d < nDim; d++) {
2266 variablesStart[d] = l_v[d];
2267 }
2268 variablesStart[pvrho] = l_rho;
2269 variablesStart[pvc] = l_c;
2270#endif
2271
2272 MFloat u[nDim] = {0.0};
2273 for(MInt d = 0; d < nDim; d++) {
2274 u[d] = l_v[d] / l_rho;
2275 }
2276
2277 std::array<MFloat, nDist> eqDist;
2278 eqDist = getEqDists(l_rho, u);
2279 std::array<MFloat, nDist> eqDistC;
2280 eqDistC = getEqDistsTransport(l_c, u);
2281
2282 // Calculation of new distributions
2283 for(MInt j = 0; j < nDist; j++) {
2284#ifdef WAR_NVHPC_PSTL
2285 a_distribution(pCellId, j) =
2286 a_oldDistribution(pCellId, j) + l_omega * (eqDist[j] - a_oldDistribution(pCellId, j));
2287 a_distributionTransport(pCellId, j) =
2288 a_oldDistributionTransport(pCellId, j) + l_omegaD * (eqDistC[j] - a_oldDistributionTransport(pCellId, j));
2289#else
2290 distributionsStart[j] = oldDistributionsStart[j] + l_omega * (eqDist[j] - oldDistributionsStart[j]);
2291 distributionsTransportStart[j] = oldDistributionsTransportStart[j] + l_omegaD * (eqDistC[j] - oldDistributionsTransportStart[j]);
2292#endif
2293 }
2294 }
2295 });
2296}
std::array< MFloat, nDist > getEqDistsTransport(const MFloat c, const MFloat *const velocity)
Return transport distributions to equilibrium.
Definition: lbsolverdxqy.h:849
static constexpr MInt pFld(MInt i, MInt j)
static constexpr MInt nFld(MInt i, MInt j)
static constexpr MInt dxQyFld()

◆ bgki_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_collision_step
virtual
Author
Ludwig Eduard Boltzmann
Date
20.2.1844
Property value solverMethod
MAIA_LATTICE_BGK

Collision step of the incompressible LBGK algorithm

Definition at line 1770 of file lbsolverdxqy.cpp.

1770 {
1771 TRACE();
1772
1773 const MInt pvrho = PV->RHO;
1774
1775 constexpr MInt fldlen = Ld::dxQyFld();
1776
1777 // Update the global Reynolds number if we use the tanh-adaption
1778 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
1779 const MFloat scale =
1780 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
1781 + 0.5;
1782
1783 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
1784
1785 // final timestep reached
1786 if(globalTimeStep == m_initStartTime + m_initTime) {
1787 m_Re = m_finalRe;
1788 m_tanhInit = 0;
1789 }
1790 }
1791
1792 // Update the according nu
1793 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
1794
1795#ifndef WAR_NVHPC_PSTL
1796 // inner loop references
1797 const MInt* const RESTRICT activeCellList = ALIGNED_I(m_activeCellList);
1798 MFloat* const RESTRICT cnu = ALIGNED_MF(&(a_nu(0)));
1799 const MInt* const RESTRICT clevel = ALIGNED_I(&(this->m_cells.level(0)));
1800 MFloat* const RESTRICT oldDistributions = ALIGNED_MF(&(a_oldDistribution(0, 0)));
1801 MFloat* const RESTRICT distributions = ALIGNED_MF(&(a_distribution(0, 0)));
1802 MFloat* const RESTRICT variables = ALIGNED_MF(&(a_variable(0, 0)));
1803 // members and globals
1804 const MInt maxLevel_ = maxLevel();
1805 // distances
1806 const MInt distNu = &a_nu(1) - &a_nu(0);
1807 const MInt distLevel = &(this->m_cells.level(1)) - &(this->m_cells.level(0));
1808 const MInt distVars = &(a_variable(1, 0)) - &(a_variable(0, 0));
1809#endif
1810 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
1811 const MInt gTS = globalTimeStep;
1812
1813 // loop over all cells
1814 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt i) {
1815#ifdef WAR_NVHPC_PSTL
1816 const MInt pCellId = m_activeCellList[i];
1817 const MInt index = maxLevel() - this->a_level(pCellId);
1818#else
1819 const MInt pCellId = activeCellList[i];
1820 const MInt index = maxLevel_ - clevel[pCellId * distLevel];
1821#endif
1822
1823 // perform collision on finest level in every timestep,
1824 // on the next coarser level every second timestep, and so on
1825 if((gTS - 1) % IPOW2(index) == 0) {
1826 // save nu for bndcnd and interface interpolation
1827#ifndef WAR_NVHPC_PSTL
1828 cnu[pCellId * distNu] = m_nu;
1829
1830 const MInt distStart = pCellId * nDist;
1831 // varStart = (pCellId * distVars) + (distVarOldVar *
1832 // !((MInt)floor((MFloat)localGlobalTimeStep/fpow2[index]) % 2));
1833 const MInt varStart = pCellId * distVars;
1834
1835 MFloat* const oldDistributionsStart = &oldDistributions[distStart];
1836 MFloat* const distributionsStart = &distributions[distStart];
1837 MFloat* const variablesStart = &variables[varStart];
1838#else
1839 a_nu(pCellId) = m_nu;
1840#endif
1841
1842 const MFloat tmp_FPOW2 = FPOW2(index);
1843 const MFloat tmp_FFPOW2 = FFPOW2(index);
1844 const MFloat l_omega = 2.0 / (1.0 + 6.0 * m_nu * tmp_FFPOW2);
1845
1846 swap_variables(pCellId);
1847
1848 // Reinit macroscopic variables before recalculation
1849 MFloat l_v[nDim] = {0.0};
1850 MFloat l_rho = 0.0;
1851 std::array<MFloat, nDist - 1> externalForcing{};
1852
1853 if(m_particleMomentumCoupling) {
1854 for(MInt dir = 0; dir < nDim; dir++) {
1855 for(MInt mi = 0; mi < fldlen; mi++) {
1856#ifdef WAR_NVHPC_PSTL
1857 externalForcing[m_nFld[dir * fldlen + mi]] +=
1858 m_tp[m_distType[m_nFld[dir * fldlen + mi]]] * -1.0 * a_externalForces(pCellId, dir) * F1BCSsq;
1859 externalForcing[m_pFld[dir * fldlen + mi]] +=
1860 m_tp[m_distType[m_pFld[dir * fldlen + mi]]] * 1.0 * a_externalForces(pCellId, dir) * F1BCSsq;
1861#else
1862 externalForcing.at(Ld::nFld(dir, mi)) +=
1863 Ld::tp(Ld::distType(Ld::nFld(dir, mi))) * -1.0 * a_externalForces(pCellId, dir) * F1BCSsq;
1864 externalForcing.at(Ld::pFld(dir, mi)) +=
1865 Ld::tp(Ld::distType(Ld::pFld(dir, mi))) * 1.0 * a_externalForces(pCellId, dir) * F1BCSsq;
1866#endif
1867 }
1868 }
1869 }
1870#ifdef WAR_NVHPC_PSTL
1871 // Add forcing term and calculate density rho
1872 for(MInt j = 0; j < nDist - 1; j++) {
1873 if(m_particleMomentumCoupling) {
1874 a_oldDistribution(pCellId, j) += tmp_FPOW2 * externalForcing[j];
1875 }
1876 // Add forcing term and calculate density rho
1877 l_rho += a_oldDistribution(pCellId, j);
1878 }
1879 // Do not forget the last distribution
1880 l_rho += a_oldDistribution(pCellId, nDist - 1);
1881#else
1882 // Add forcing term and calculate density rho
1883 for(MInt j = 0; j < nDist - 1; j++) {
1884 if(m_particleMomentumCoupling) {
1885 oldDistributionsStart[j] += tmp_FPOW2 * externalForcing.at(j);
1886 }
1887 // Add forcing term and calculate density rho
1888 l_rho += oldDistributionsStart[j];
1889 }
1890 // Do not forget the last distribution
1891 l_rho += oldDistributionsStart[nDist - 1];
1892#endif
1893
1894
1895 // Calculate macroscopic variables
1896#ifndef WAR_NVHPC_PSTL
1897 if constexpr(nDim == 2) {
1898 // WARNING!!! The velocity should be calculated as in 3d
1899 // However, result is correct
1900 // calculation of u
1901 l_v[0] = oldDistributionsStart[1] + oldDistributionsStart[4] + oldDistributionsStart[5]
1902 - oldDistributionsStart[7] - oldDistributionsStart[6] - oldDistributionsStart[0];
1903 // calculation of v
1904 l_v[1] = oldDistributionsStart[7] + oldDistributionsStart[3] + oldDistributionsStart[4]
1905 - oldDistributionsStart[6] - oldDistributionsStart[2] - oldDistributionsStart[5];
1906 } else {
1907#endif
1908 for(MInt j = 0; j < fldlen; j++) {
1909 for(MInt d = 0; d < nDim; d++) {
1910#ifdef WAR_NVHPC_PSTL
1911 l_v[d] += a_oldDistribution(pCellId, m_pFld[d * fldlen + j]);
1912 l_v[d] -= a_oldDistribution(pCellId, m_nFld[d * fldlen + j]);
1913#else
1914 l_v[d] += oldDistributionsStart[Ld::pFld(d, j)];
1915 l_v[d] -= oldDistributionsStart[Ld::nFld(d, j)];
1916#endif
1917 }
1918 }
1919#ifndef WAR_NVHPC_PSTL
1920 }
1921#endif
1922
1923 // Save new macroscopic variables in cell
1924#ifdef WAR_NVHPC_PSTL
1925 for(MInt d = 0; d < nDim; d++) {
1926 a_variable(pCellId, d) = l_v[d];
1927 }
1928 a_variable(pCellId, nDim) = l_rho;
1929#else
1930 for(MInt d = 0; d < nDim; d++) {
1931 variablesStart[d] = l_v[d];
1932 }
1933 variablesStart[pvrho] = l_rho;
1934#endif
1935
1936 const MFloat sqVel = std::inner_product(&l_v[0], &l_v[nDim], &l_v[0], F0);
1937
1938 std::array<MFloat, nDist> eqDist;
1939 eqDist = getEqDists(l_rho, sqVel, l_v);
1940
1941 // Calculation of new distributions
1942#ifdef WAR_NVHPC_PSTL
1943 for(MInt j = 0; j < nDist; j++) {
1944 a_distribution(pCellId, j) =
1945 a_oldDistribution(pCellId, j) + l_omega * (eqDist[j] - a_oldDistribution(pCellId, j));
1946 }
1947#else
1948 for(MInt j = 0; j < nDist; j++) {
1949 distributionsStart[j] = oldDistributionsStart[j] + l_omega * (eqDist[j] - oldDistributionsStart[j]);
1950 }
1951#endif
1952 }
1953 });
1954}
constexpr MFloat FPOW2(MInt x)
static constexpr MInt distType(MInt i)
Type of the distribution (0:rest, 1:face, 2:edge, 3:corner)
static constexpr MFloat tp(MInt i)

◆ bgki_collision_step_Guo_forcing()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_collision_step_Guo_forcing
override
Author
Johannes Grafen
Property value solverMethod
MAIA_LATTICE_BGK_GUO_FORCING

Collision step of the incompressible LBGK algorithm with forcing method of Guo et al.

adapted from conventional bgki-collision step Discrete lattice effects on the forcing term in the lattice Boltzmann method DOI: 0.1103/PhysRevE.65.046308

Definition at line 1968 of file lbsolverdxqy.cpp.

1968 {
1969 TRACE();
1970
1971 if(!m_particleMomentumCoupling)
1972 std::cerr << "Momentum Coupling is not activated, use MAIA_LATTIC_BGK instead!" << std::endl;
1973
1974 const MInt pvrho = PV->RHO;
1975
1976 constexpr MInt fldlen = Ld::dxQyFld();
1977
1978 // Update the global Reynolds number if we use the tanh-adaption
1979 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
1980 const MFloat scale =
1981 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
1982 + 0.5;
1983
1984 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
1985
1986 // final timestep reached
1987 if(globalTimeStep == m_initStartTime + m_initTime) {
1988 m_Re = m_finalRe;
1989 m_tanhInit = 0;
1990 }
1991 }
1992
1993 // Update the according nu
1994 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
1995
1996 // inner loop references
1997 const MInt* const RESTRICT activeCellList = ALIGNED_I(m_activeCellList);
1998 MFloat* const RESTRICT cnu = ALIGNED_MF(&(a_nu(0)));
1999 const MInt* const RESTRICT clevel = ALIGNED_I(&(this->m_cells.level(0)));
2000 MFloat* const RESTRICT oldDistributions = ALIGNED_MF(&(a_oldDistribution(0, 0)));
2001 MFloat* const RESTRICT distributions = ALIGNED_MF(&(a_distribution(0, 0)));
2002 MFloat* const RESTRICT variables = ALIGNED_MF(&(a_variable(0, 0)));
2003
2004 // members and globals
2005 const MFloat nu = m_nu;
2006
2007 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
2008 const MInt gTS = globalTimeStep;
2009 const MInt maxLevel_ = maxLevel();
2010
2011 // distances
2012 const MInt distNu = &a_nu(1) - &a_nu(0);
2013 const MInt distLevel = &(this->m_cells.level(1)) - &(this->m_cells.level(0));
2014 const MInt distVars = &(a_variable(1, 0)) - &(a_variable(0, 0));
2015
2016 // loop over all cells
2017 maia::parallelFor<false>(0, m_currentMaxNoCells, [=](MInt i) {
2018 const MInt pCellId = activeCellList[i];
2019 const MInt index = maxLevel_ - clevel[pCellId * distLevel];
2020
2021 // perform collision on finest level in every timestep,
2022 // on the next coarser level every second timestep, and so on
2023 if((gTS - 1) % IPOW2(index) == 0) {
2024 // save nu for bndcnd and interface interpolation
2025 cnu[pCellId * distNu] = nu;
2026
2027 const MInt distStart = pCellId * nDist;
2028 // varStart = (pCellId * distVars) + (distVarOldVar *
2029 // !((MInt)floor((MFloat)localGlobalTimeStep/fpow2[index]) % 2));
2030 const MInt varStart = pCellId * distVars;
2031
2032 MFloat* const oldDistributionsStart = &oldDistributions[distStart];
2033 MFloat* const distributionsStart = &distributions[distStart];
2034
2035 MFloat* const variablesStart = &variables[varStart];
2036
2037 const MFloat tmp_FPOW2 = FPOW2(index);
2038 const MFloat tmp_FFPOW2 = FFPOW2(index);
2039 const MFloat l_omega = 2.0 / (1.0 + 6.0 * nu * tmp_FFPOW2);
2040
2041 swap_variables(pCellId);
2042
2043 // Reinit macroscopic variables before recalculation
2044 MFloat l_v[nDim] = {0.0};
2045 MFloat l_rho = 0.0;
2046 std::array<MFloat, nDist> externalForcing{0.0};
2047
2048 // calculate density rho and velocity
2049 for(MInt j = 0; j < nDist - 1; j++) {
2050 // Add forcing term and calculate density rho
2051 l_rho += oldDistributionsStart[j];
2052 }
2053 // Do not forget the last distribution
2054 l_rho += oldDistributionsStart[nDist - 1];
2055
2056 for(MInt j = 0; j < fldlen; j++) {
2057 for(MInt d = 0; d < nDim; d++) {
2058 l_v[d] += oldDistributionsStart[Ld::pFld(d, j)];
2059 l_v[d] -= oldDistributionsStart[Ld::nFld(d, j)];
2060 }
2061 }
2062
2063 // add forcing term to velocity
2064 for(MInt d = 0; d < nDim; d++) {
2065 l_v[d] += tmp_FPOW2 * F1B2 * a_externalForces(pCellId, d);
2066 }
2067
2068 // Save new macroscopic variables in cell
2069 for(MInt d = 0; d < nDim; d++) {
2070 variablesStart[d] = l_v[d];
2071 }
2072 variablesStart[pvrho] = l_rho;
2073
2074 const MFloat sqVel = std::inner_product(&l_v[0], &l_v[nDim], &l_v[0], F0);
2075
2076 // Compute Sourceterm:
2077 for(MInt j = 0; j < nDist - 1; j++) {
2078 // precompute
2079 std::array<MFloat, nDim> velDiff{};
2080 MFloat scalarProductVel{};
2081 for(MInt dir = 0; dir < nDim; dir++) {
2082 velDiff.at(dir) = Ld::ppdfDir(j, dir) - l_v[dir];
2083 scalarProductVel += Ld::ppdfDir(j, dir) * l_v[dir];
2084 }
2085 for(MInt dir = 0; dir < nDim; dir++) {
2086 externalForcing.at(j) +=
2087 tmp_FPOW2 * (F1 - F1B2 * l_omega) * Ld::tp(Ld::distType(j))
2088 * (F1BCSsq * velDiff.at(dir) + POW2(F1BCSsq) * scalarProductVel * Ld::ppdfDir(j, dir))
2089 * a_externalForces(pCellId, dir);
2090 }
2091 }
2092
2093 std::array<MFloat, nDist> eqDist;
2094 eqDist = getEqDists(l_rho, sqVel, l_v);
2095
2096 // Calculation of new distributions
2097 for(MInt j = 0; j < nDist; j++) {
2098 distributionsStart[j] =
2099 oldDistributionsStart[j] + l_omega * (eqDist[j] - oldDistributionsStart[j]) + externalForcing.at(j);
2100 }
2101 }
2102 });
2103}
constexpr Real POW2(const Real x)
Definition: functions.h:119
static constexpr MFloat ppdfDir(MInt i, MInt j)

◆ bgki_dynamic_smago_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_dynamic_smago_collision_step
override
Property value solverMethod
MAIA_LATTICE_BGKI_DYNAMIC_SMAGO

Collision step of the incompressible LBGK algorithm with SGS modelling

only for D3Q19

Definition at line 3334 of file lbsolverdxqy.cpp.

3334 {
3335 TRACE();
3336
3338 for(MInt i = 0; i < this->noInternalCells(); i++) {
3340 }
3342
3343 std::vector<MFloat> dynamicCs;
3344 constexpr MInt direction = 1;
3345 MInt count = 0;
3346 averageSGSTensors(direction, count, dynamicCs);
3347
3348 for(MInt i = 0; i < count; i++) {
3349 if(dynamicCs[i] < 0.0) dynamicCs[i] = 0.0;
3350 }
3351
3352
3353 // For now testing only the D3Q19 algorithm
3354 MFloat rho = F1;
3355 MFloat u[nDim] = {F0};
3356 MFloat tau = F0;
3357
3358 MFloat Q = F0;
3359 MInt index = 0;
3360 MFloat actualCellLength = F0;
3361
3362 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
3363 MFloat scale =
3364 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
3365 + 0.5;
3366
3367 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
3368
3369 // final timestep reached
3370 if(globalTimeStep == m_initStartTime + m_initTime) {
3371 m_Re = m_finalRe;
3372 m_tanhInit = 0;
3373 }
3374 }
3375 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
3376
3377 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
3378 const MInt pCellId = m_activeCellList[i];
3379
3380 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
3381 rho = a_variable(pCellId, PV->RHO);
3382
3383 for(MInt d = 0; d < nDim; d++) {
3384 u[d] = a_variable(pCellId, d);
3385 }
3386
3387 // Calculation of equilibrium and non-equilibrium distribution
3388 std::array<MFloat, nDist> eqDist;
3389 eqDist = getEqDists(rho, u);
3390 MFloat nonEqDist[nDist];
3391 for(MInt j = 0; j < nDist; j++) {
3392 nonEqDist[j] = a_oldDistribution(pCellId, j) - eqDist[j];
3393 }
3394
3395 //--------------------------------------------
3396 // Calculation of overall viscosity
3397 // according to Hu, Sterling, Chen 1994
3398
3399 // Calculation of original relaxation time (on current level)
3400 tau = F1B2 + 3.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId));
3401
3402 // Calculate square of momentum flux tensor
3403 Q = 0.0;
3404 for(MInt k = 0; k < nDim * nDim; k++) {
3405 Q += m_momentumFlux[pCellId][k] * m_momentumFlux[pCellId][k];
3406 }
3407 Q = sqrt(2.0 * Q);
3408
3409 // Calculation of new relaxation time
3410
3411 // index = (MInt)((a_coordinate(pCellId, direction) - minCoord) / length * MFloat(count - 1) + 0.5);
3412 index = floor((F1B2 * count
3413 + (a_coordinate(pCellId, 1) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
3414 + 0.1);
3415
3416 tau += F1B2
3417 * (sqrt(tau * tau
3418 + 2.0 * SQRT2 * dynamicCs[index] * m_deltaX * m_deltaX * (F1BCSsq * F1BCSsq) * Q
3419 * FPOW2(maxLevel() - this->a_level(pCellId)))
3420 - tau);
3421
3422 m_omega = 1.0 / tau;
3423
3424 // save total nu for bndcnd and interface interpolation (save on finest level)
3425 a_nu(pCellId) = FPOW2(maxLevel() - this->a_level(pCellId)) * (tau - F1B2) / 3.0;
3426
3427 // perform relaxation
3428 for(MInt j = 0; j < nDist; j++) {
3429 a_distribution(pCellId, j) = a_oldDistribution(pCellId, j) - m_omega * nonEqDist[j];
3430 }
3431 }
3432 }
3433}
void calculateSGSTensors()
Calculate tensors for dynamic Smagorinsky constant.
void updateMacroscopicVariables()
Update macroscopic variables according to incoming PPDF.
void calculateMomentumFlux(const MInt pCellId)
Calculate and set momentum flux for a given cell.
Definition: lbsolverdxqy.h:950
void averageSGSTensors(const MInt direction, MInt &count, std::vector< MFloat > &meanTensors)
Calculate average SGS tensor.

◆ bgki_euler_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_euler_collision_step
override
Property value solverMethod
MAIA_LATTICE_BGKI_EULER_2D

The collision step for the Euler BGK-Algorithm Why is the equilibrium set if Q < eps??? Not tested yet, use with caution!!!!

Definition at line 3445 of file lbsolverdxqy.cpp.

3445 {
3446 TRACE();
3447
3448 const MInt pvrho = PV->RHO;
3449
3450 constexpr MInt fldlen = Ld::dxQyFld();
3451
3452 MFloat l_rho = 1.0;
3453 MFloat l_v[nDim] = {0.0};
3454
3455 MFloat eps = 1e-4;
3456
3457 // Update the global Reynolds number if we use the tanh-adaption
3458 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
3459 const MFloat scale =
3460 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
3461 + 0.5;
3462
3463 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
3464
3465 // final timestep reached
3466 if(globalTimeStep == m_initStartTime + m_initTime) {
3467 m_Re = m_finalRe;
3468 m_tanhInit = 0;
3469 }
3470 }
3471
3472 // Update the according nu
3473 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
3474
3475
3476 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
3477 const MInt pCellId = m_activeCellList[i];
3478
3479 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
3480 a_oldVariable(i, PV->RHO) = a_variable(i, PV->RHO);
3481 a_oldVariable(i, PV->U) = a_variable(i, PV->U);
3482 a_oldVariable(i, PV->V) = a_variable(i, PV->V);
3483
3484 // Add forcing term and calculate density rho
3485 l_rho = F0;
3486 for(MInt j = 0; j < nDist - 1; j++) {
3487 l_rho += a_oldDistribution(pCellId, j);
3488 }
3489 // Do not forget the last distribution
3490 l_rho += a_oldDistribution(pCellId, nDist - 1);
3491
3492
3493 // Calculate macroscopic variables
3494 l_v[0] = F0;
3495 l_v[1] = F0;
3496 if constexpr(nDim == 3) l_v[2] = F0;
3497
3498 if constexpr(nDim == 2) {
3499 // WARNING!!! The velocity should be calculated as in 3d
3500 // However, result is correct
3501 // calculation of u
3502 l_v[0] = a_oldDistribution(pCellId, 1) + a_oldDistribution(pCellId, 4) + a_oldDistribution(pCellId, 5)
3503 - a_oldDistribution(pCellId, 7) - a_oldDistribution(pCellId, 6) - a_oldDistribution(pCellId, 0);
3504 // calculation of v
3505 l_v[1] = a_oldDistribution(pCellId, 7) + a_oldDistribution(pCellId, 3) + a_oldDistribution(pCellId, 4)
3506 - a_oldDistribution(pCellId, 6) - a_oldDistribution(pCellId, 2) - a_oldDistribution(pCellId, 5);
3507 } else {
3508 for(MInt j = 0; j < fldlen; j++) {
3509 for(MInt d = 0; d < nDim; d++) {
3510 l_v[d] += a_oldDistribution(pCellId, Ld::pFld(d, j));
3511 l_v[d] -= a_oldDistribution(pCellId, Ld::nFld(d, j));
3512 }
3513 }
3514 }
3515
3516 // Save new macroscopic variables in cell
3517 for(MInt d = 0; d < nDim; d++) {
3518 a_variable(pCellId, d) = l_v[d];
3519 }
3520 a_variable(pCellId, pvrho) = l_rho;
3521
3522 calculateMomentumFlux(pCellId);
3523
3524 // 3. Calculation of the filtered mean momentum flux
3525 MFloat Q = 0.0;
3526 for(MInt k = 0; k < nDim * nDim; k++) {
3527 Q += m_momentumFlux[pCellId][k] * m_momentumFlux[pCellId][k];
3528 }
3529 Q = sqrt(2.0 * Q);
3530
3531 for(MInt d = 0; d < nDim; d++) {
3532 l_v[d] = a_variable(pCellId, d);
3533 }
3534 l_rho = a_variable(pCellId, pvrho);
3535
3536 const MFloat sqVel = std::inner_product(&l_v[0], &l_v[nDim], &l_v[0], F0);
3537
3538 std::array<MFloat, nDist> eqDist;
3539 eqDist = getEqDists(l_rho, sqVel, l_v);
3540
3541 // Calculation of new distributions
3542 if(fabs(Q) > eps) {
3543 const MFloat l_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
3544
3545 // Calculation of new distributions
3546 for(MInt j = 0; j < nDist; j++) {
3547 a_distribution(pCellId, j) =
3548 a_oldDistribution(pCellId, j) + l_omega * (eqDist[j] - a_oldDistribution(pCellId, j));
3549 }
3550 } else {
3551 // Calculation of new distributions
3552 for(MInt j = 0; j < nDist; j++) {
3553 a_distribution(pCellId, j) = eqDist[j];
3554 }
3555 }
3556 }
3557 }
3558}

◆ bgki_init_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_init_collision_step
override

The initial velocity field is held constant. Only the pressure is changed by collision. (Mei et al. 2006)

Regularized pre-collision functions are used for sake of stability and accuracy !!!

Definition at line 4505 of file lbsolverdxqy.cpp.

4505 {
4506 TRACE();
4507
4508 // capable of D3Q19 and D3Q27
4509 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
4510 const MInt pCellId = m_activeCellList[i];
4511
4512 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
4513 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
4514
4515 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
4516
4517 swap_variables(pCellId);
4518
4519 // Calculate macroscopic density
4520 a_variable(pCellId, PV->RHO) = 0.0;
4521 for(MInt j = 0; j < nDist; j++) {
4522 a_variable(pCellId, PV->RHO) += a_oldDistribution(pCellId, j);
4523 }
4524
4525 const MFloat rho = a_variable(pCellId, PV->RHO);
4526 MFloat u[nDim];
4527 for(MInt d = 0; d < nDim; d++) {
4528 u[d] = a_variable(pCellId, d);
4529 }
4530
4531 // Calculation of equilibrium and non-equilibrium distribution
4532 std::array<MFloat, nDist> eqDist;
4533 eqDist = getEqDists(rho, u);
4534
4535 // Calculation of momentum flux tensor for non-equilibrium parts
4536 //--------------------------------------------
4537 // \Pi_{\alpha,\beta} = \sum_i f_i \cdot c_{i,\alpha}c_{i,\beta}
4538 calculateMomentumFlux(pCellId);
4539
4540 // Calculation of new distributions for directions with at least one component
4541 MFloat trace = F0;
4542
4543 if constexpr(nDim == 2) {
4544 trace = m_momentumFlux[pCellId][0] + m_momentumFlux[pCellId][3];
4545 } else {
4546 trace = m_momentumFlux[pCellId][0] + m_momentumFlux[pCellId][4] + m_momentumFlux[pCellId][8];
4547 }
4548
4549 for(MInt j = 0; j < (nDist - 1); j++) {
4550 const MFloat t = Ld::tp(Ld::distType(j));
4551
4552 a_distribution(pCellId, j) = eqDist[j] - (1.0 - m_omega) * t * F1BCSsq * F1B2 * trace;
4553
4554 for(MInt k = 0; k < nDim; k++) {
4555 for(MInt l = 0; l < nDim; l++) {
4556 a_distribution(pCellId, j) += (1.0 - m_omega) * t * F1BCSsq * F1BCSsq * F1B2 * (Ld::idFld(j, k) - 1)
4557 * (Ld::idFld(j, l) - 1) * m_momentumFlux[pCellId][l + nDim * k];
4558 }
4559 }
4560 }
4561 // Calculation of new distribution for rest particle distribution (center)
4562 a_distribution(pCellId, Ld::lastId()) =
4563 eqDist[Ld::lastId()] - (1.0 - m_omega) * Ld::tp(0) * F1BCSsq * F1B2 * trace;
4564 }
4565 }
4566}
static constexpr MInt idFld(MInt i, MInt j)
static constexpr MInt lastId()

◆ bgki_innerEnergy_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_innerEnergy_collision_step
virtual
Author
Moritz Waldmann
Date
23.02.2019
Property value solverMethod
MAIA_LATTICE_BGK_INNERENERGY

Collision step of the incompressible LBGK algorithm with TLBGK extension using an inner energy distribution function approach

Performs the collision step for the BGK method with TLBGK extension:

  • the macroscopic variables are obtained by evaluating the moments of the PPDFs.
  • seperate local velocities are calculated by dividing by the density \(\rho\).
  • Recalculation of the PPDFs for all directions for the LBGK and TLBGK. Note, that the density \(rho\) has been moved outside the inner brackets of the equilibrium distribution function and that different collision frequencies \(\omega\) and \(\omega_T\) are used for the LBGK and the TLBGK, respectively. The velocities of the TLBGK are used from that one obtained from the moments of the LBGK.


Todo:
labels:LB natural convection

Definition at line 3035 of file lbsolverdxqy.cpp.

3035 {
3036 TRACE();
3037
3038 bgki_thermal_collision_step_base<1>();
3039}

◆ bgki_smago_wall_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_smago_wall_collision_step
override
Property value solverMethod
MAIA_LATTICE_BGKI_SMAGO_WALL

Collision step of the incompressible LBGK algorithm with SGS modelling and van Driest damping function

only for D3Q19 and channel flow

Definition at line 3090 of file lbsolverdxqy.cpp.

3090 {
3091 bgki_smagorinsky_collision_step_base<1>();
3092}

◆ bgki_smagorinsky_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_smagorinsky_collision_step
override
Property value solverMethod
MAIA_LATTICE_BGKI_SMAGORINSKY

Collision step of the incompressible LBGK algorithm with SGS modelling

only for D3Q19

Definition at line 3076 of file lbsolverdxqy.cpp.

3076 {
3077 bgki_smagorinsky_collision_step_base<0>();
3078}

◆ bgki_smagorinsky_collision_step2()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_smagorinsky_collision_step2
override
Property value solverMethod
MAIA_LATTICE_BGKI_SMAGORINSKY2

Collision step of the incompressible LBGK algorithm with SGS modelling and calculation of sgs terms along y axis

only for D3Q19

Definition at line 3104 of file lbsolverdxqy.cpp.

3104 {
3105 bgki_smagorinsky_collision_step_base<2>();
3106}

◆ bgki_smagorinsky_collision_step_base()

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt mode>
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_smagorinsky_collision_step_base

Definition at line 3110 of file lbsolverdxqy.cpp.

3110 {
3111 TRACE();
3112
3113 // For now testing only the D3Q19 algorithm
3114 MFloat rho = F0;
3115 MFloat Q = F0;
3116 MFloat tau = F0;
3117 MFloat S = F0;
3118
3119 MInt index = 0;
3120 MFloat actualCellLength = F0;
3121 constexpr MInt direction = 1;
3122
3123 MChar buf[10];
3124 MString fileName;
3125 ofstream ofl;
3126
3127 ScratchSpace<MFloat> diss(m_arraySize[direction], AT_, "diss");
3128 ScratchSpace<MFloat> totalDiss(m_arraySize[direction], AT_, "totalDiss");
3129 ScratchSpace<MFloat> SGSDiss(m_arraySize[direction], AT_, "SGSDiss");
3130 ScratchSpace<MFloat> totalSGSDiss(m_arraySize[direction], AT_, "totalSGSDiss");
3131 MFloat energy;
3132
3133 // reset dissipation and energy values
3134 for(MInt i = 0; i < m_arraySize[direction]; i++) {
3135 diss[i] = F0;
3136 SGSDiss[i] = F0;
3137 }
3138
3139 energy = F0;
3140
3141 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
3142 MFloat scale =
3143 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
3144 + 0.5;
3145
3146 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
3147
3148 // final timestep reached
3149 if(globalTimeStep == m_initStartTime + m_initTime) {
3150 m_Re = m_finalRe;
3151 m_tanhInit = 0;
3152 }
3153 }
3154 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
3155
3156 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
3157 const MInt pCellId = m_activeCellList[i];
3158
3159 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId))
3160 == 0) { // perform collision on finest level in every timestep, // on the next coarser level every second
3161 // timestep, and so on
3162
3163 swap_variables(pCellId);
3164
3165 // Calculate macroscopic variables
3166 a_variable(pCellId, PV->RHO) = 0.0;
3167 for(MInt j = 0; j < nDist; j++) {
3168 a_variable(pCellId, PV->RHO) += a_oldDistribution(pCellId, j);
3169 }
3170 rho = a_variable(pCellId, PV->RHO);
3171
3172 MFloat u[nDim];
3173 for(MInt j = 0; j < nDim; j++) {
3174 u[j] = F0;
3175 }
3176
3177 if constexpr(nDim == 2) {
3178 // warning!!! the velocity should be calculated as in 3d
3179 // however, result is correct
3180 // calculation of u
3181 u[0] = a_oldDistribution(pCellId, 1) + a_oldDistribution(pCellId, 4) + a_oldDistribution(pCellId, 5)
3182 - a_oldDistribution(pCellId, 7) - a_oldDistribution(pCellId, 6) - a_oldDistribution(pCellId, 0);
3183 // calculation of v
3184 u[1] = a_oldDistribution(pCellId, 7) + a_oldDistribution(pCellId, 3) + a_oldDistribution(pCellId, 4)
3185 - a_oldDistribution(pCellId, 6) - a_oldDistribution(pCellId, 2) - a_oldDistribution(pCellId, 5);
3186 } else {
3187 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
3188 for(MInt d = 0; d < nDim; d++) {
3189 u[d] += a_oldDistribution(pCellId, Ld::pFld(d, j));
3190 u[d] -= a_oldDistribution(pCellId, Ld::nFld(d, j));
3191 }
3192 }
3193 }
3194
3195 for(MInt j = 0; j < nDim; j++) {
3196 a_variable(pCellId, j) = u[j];
3197 }
3198
3199 // Calculation of equilibrium and non-equilibrium distribution
3200 std::array<MFloat, nDist> eqDist;
3201 eqDist = getEqDists(rho, u);
3202
3203 MFloat nonEqDist[nDist];
3204 for(MInt j = 0; j < nDist; j++) {
3205 nonEqDist[j] = a_oldDistribution(pCellId, j) - eqDist[j];
3206 }
3207
3208 //--------------------------------------------
3209 // Calculation of overall viscosity
3210 // according to Hu, Sterling, Chen 1994
3211
3212 // 1. Calculation of original relaxation time (on current level)
3213 tau = F1B2 + 3.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId));
3214
3215 // 2. Calculation of momentum flux tensor from non-equilibrium parts
3216 calculateMomentumFlux(pCellId);
3217
3218 // 3. Calculation of the filtered mean momentum flux
3219 Q = 0.0;
3220 for(MInt k = 0; k < nDim * nDim; k++) {
3221 Q += m_momentumFlux[pCellId][k] * m_momentumFlux[pCellId][k];
3222 }
3223 Q = sqrt(2.0 * Q);
3224
3225 // 4. Calculation of new relaxation time
3226 if(mode == 1) {
3227 const MFloat aPlus = 26.0;
3228 MFloat tmpWidth = m_referenceLength * m_smallestCellLength;
3229 MFloat yPlus = m_ReTau * (1.0 - fabs(a_coordinate(pCellId, 1)) / tmpWidth);
3230 MFloat lambda = m_Cs * m_deltaX * (F1 - exp(-yPlus / aPlus));
3231 tau += F1B2
3232 * (sqrt(tau * tau
3233 + 2.0 * SQRT2 * lambda * lambda * (F1BCSsq * F1BCSsq) * Q
3234 * FPOW2(maxLevel() - this->a_level(pCellId)))
3235 - tau);
3236 } else {
3237 tau += F1B2
3238 * (sqrt(tau * tau
3239 + 2.0 * SQRT2 * m_Cs * m_Cs * m_deltaX * m_deltaX * (F1BCSsq * F1BCSsq) * Q
3240 * FPOW2(maxLevel() - this->a_level(pCellId)))
3241 - tau);
3242 }
3243
3244 m_omega = 1.0 / tau;
3245
3246 // save total nu for bndcnd and interface interpolation (save on finest level)
3247 a_nu(pCellId) = FPOW2(maxLevel() - this->a_level(pCellId)) * (tau - F1B2) / 3.0;
3248
3249 //--------------------------------------------
3250
3251 // perform relaxation
3252 for(MInt j = 0; j < nDist; j++) {
3253 a_distribution(pCellId, j) = a_oldDistribution(pCellId, j) - m_omega * nonEqDist[j];
3254 }
3255
3256
3257 //---------------------------
3258 // save dissipation values
3259 if(mode == 2) {
3260 actualCellLength = this->c_cellLengthAtLevel(this->a_level(pCellId));
3261 index = floor(
3262 (F1B2 * m_arraySize[direction]
3263 + (a_coordinate(pCellId, direction) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
3264 + 0.1);
3265
3266 // Calculate characteristic filtered rate of strain
3267 S = F1B2 * F1BCSsq * m_omega * Q;
3268
3269 // Calculate molecular- and subgrid dissipation
3270 if(pCellId < this->grid().noInternalCells()) {
3271 diss[index] += m_nu * S * S;
3272 SGSDiss[index] += m_Cs * m_Cs * m_deltaX * m_deltaX * S * S * S * FPOW4(maxLevel() - this->a_level(pCellId));
3273 for(MInt d = 0; d < nDim; d++) {
3274 energy += F1B2 * (a_variable(pCellId, d) * a_variable(pCellId, d));
3275 }
3276 }
3277 }
3278 }
3279 }
3280
3281 // write dissipation values
3282 if(mode == 2 && globalTimeStep % m_solutionInterval == 0) {
3283 // for (MInt i=0; i<m_arraySize[direction]; i++){
3284 // m_log <<"cs["<<i<<"]="<<dynamicCs[i]<<endl;
3285 // }
3286
3287 // all domains send their information to domain_0
3288 if(domainId() != 0) {
3289 MPI_Send(&(diss[0]), m_arraySize[direction], MPI_DOUBLE, 0, 0, mpiComm(), AT_, "(diss[0])");
3290 MPI_Send(&(SGSDiss[0]), m_arraySize[direction], MPI_DOUBLE, 0, 0, mpiComm(), AT_, "(SGSDiss[0])");
3291 MPI_Send(&energy, 1, MPI_DOUBLE, 0, 0, mpiComm(), AT_, "energy");
3292 }
3293
3294 if(domainId() == 0) {
3295 MPI_Status status;
3296
3297 for(MInt i = 0; i < m_arraySize[direction]; i++) {
3298 totalDiss[i] = diss[i];
3299 totalSGSDiss[i] = SGSDiss[i];
3300 }
3301
3302 for(MInt j = 1; j < noDomains(); j++) {
3303 MPI_Recv(&(diss[0]), m_arraySize[direction], MPI_DOUBLE, j, 0, mpiComm(), &status, AT_, "(diss[0])");
3304 MPI_Recv(&(SGSDiss[0]), m_arraySize[direction], MPI_DOUBLE, j, 0, mpiComm(), &status, AT_, "(SGSDiss[0])");
3305 MPI_Recv(&energy, 1, MPI_DOUBLE, j, 0, mpiComm(), &status, AT_, "energy");
3306 for(MInt i = 0; i < m_arraySize[direction]; i++) {
3307 totalDiss[i] += diss[i];
3308 totalSGSDiss[i] += SGSDiss[i];
3309 }
3310 }
3311
3312 fileName = "totalDiss_";
3313 sprintf(buf, "%d", globalTimeStep);
3314 fileName += buf;
3315 fileName += ".dat";
3316 m_log << "writing diss file: " << fileName << endl;
3317 ofl.open(fileName.c_str(), ios_base::out);
3318 for(MInt i = 0; i < m_arraySize[direction]; i++)
3319 ofl << globalTimeStep << " " << i << " " << totalDiss[i] << " " << totalSGSDiss[i] << " " << energy << endl;
3320 ofl.close();
3321 }
3322 }
3323}
void open(const MString &filename, const MString &projectName, MInt fileType=0, MPI_Comm mpiComm=MPI_COMM_WORLD, MBool rootOnlyHardwired=false)
Opens a file by passing the parameters to InfoOut_<xyz>FileBuffer::open(...).
Definition: infoout.cpp:975
MFloat m_smallestCellLength
Definition: lbsolverdxqy.h:351
constexpr MFloat FPOW4(MInt x)
std::basic_string< char > MString
Definition: maiatypes.h:55
char MChar
Definition: maiatypes.h:56
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Send

◆ bgki_thermal_and_transport_collision_step_base()

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt thermalMode>
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_thermal_and_transport_collision_step_base
Author
Shota Ito
Date
13.06.22

Definition at line 2305 of file lbsolverdxqy.cpp.

2305 {
2306 TRACE();
2307
2308 const MInt pvrho = PV->RHO;
2309 const MInt pvt = PV->T;
2310 const MInt pvc = PV->C;
2311
2312 constexpr MInt fldlen = Ld::dxQyFld();
2313
2314 // Update the global Reynolds number if we use the tanh-adaption
2315 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
2316 const MFloat scale =
2317 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
2318 + 0.5;
2319
2320 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
2321
2322 // final timestep reached
2323 if(globalTimeStep == m_initStartTime + m_initTime) {
2324 m_Re = m_finalRe;
2325 m_tanhInit = 0;
2326 }
2327 }
2328
2329 // Update the according nu
2330 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
2331
2332 // Calculate heat diffusion coefficient
2333 m_kappa = m_nu / m_Pr;
2334 m_diffusivity = m_nu * (m_Re / m_Pe);
2335
2336#ifndef WAR_NVHPC_PSTL
2337 // inner loop references
2338 const MInt* const RESTRICT activeCellList = ALIGNED_I(m_activeCellList);
2339 MFloat* const RESTRICT cnu = ALIGNED_MF(&(a_nu(0)));
2340 MFloat* const RESTRICT ckappa = ALIGNED_MF(&(a_kappa(0)));
2341 MFloat* const RESTRICT cdiffusivity = ALIGNED_MF(&(a_diffusivity(0)));
2342 const MInt* const RESTRICT clevel = ALIGNED_I(&(this->m_cells.level(0)));
2343 MFloat* const RESTRICT oldDistributions = ALIGNED_MF(&(a_oldDistribution(0, 0)));
2344 MFloat* const RESTRICT distributions = ALIGNED_MF(&(a_distribution(0, 0)));
2345 MFloat* const RESTRICT oldDistributionsThermal = ALIGNED_MF(&(a_oldDistributionThermal(0, 0)));
2346 MFloat* const RESTRICT distributionsThermal = ALIGNED_MF(&(a_distributionThermal(0, 0)));
2347 MFloat* const RESTRICT oldDistributionsTransport = ALIGNED_MF(&(a_oldDistributionTransport(0, 0)));
2348 MFloat* const RESTRICT distributionsTransport = ALIGNED_MF(&(a_distributionTransport(0, 0)));
2349 MFloat* const RESTRICT variables = ALIGNED_MF(&(a_variable(0, 0)));
2350
2351 // members and globals
2352 const MInt maxLevel_ = maxLevel();
2353 // distances
2354 const MInt distNu = &a_nu(1) - &a_nu(0);
2355 const MInt distKappa = &a_kappa(1) - &a_kappa(0);
2356 const MInt distDiffusivity = &a_diffusivity(1) - &a_diffusivity(0);
2357 const MInt distLevel = &(this->m_cells.level(1)) - &(this->m_cells.level(0));
2358 const MInt distVars = &(a_variable(1, 0)) - &(a_variable(0, 0));
2359#endif
2360 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
2361 const MInt gTS = globalTimeStep;
2362
2363 const MFloat factor = (thermalMode == 1) ? ((nDim == 2) ? 3.0 : 18.0 / 5.0) : F6;
2364
2365 // loop over all cells
2366 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt i) {
2367#ifdef WAR_NVHPC_PSTL
2368 const MInt pCellId = m_activeCellList[i];
2369 const MInt index = maxLevel() - this->a_level(pCellId);
2370#else
2371 const MInt pCellId = activeCellList[i];
2372 const MInt index = maxLevel_ - clevel[pCellId * distLevel];
2373#endif
2374
2375 // perform collision on finest level in every timestep,
2376 // on the next coarser level every second timestep, and so on
2377 if((gTS - 1) % IPOW2(index) == 0) {
2378 // save nu for bndcnd and interface interpolation
2379#ifndef WAR_NVHPC_PSTL
2380 cnu[pCellId * distNu] = m_nu;
2381 ckappa[pCellId * distKappa] = m_kappa;
2382 cdiffusivity[pCellId * distDiffusivity] = m_diffusivity;
2383
2384 const MInt distStart = pCellId * nDist;
2385 // varStart = (pCellId * distVars) + (distVarOldVar *
2386 // !((MInt)floor((MFloat)localGlobalTimeStep/fpow2[index]) % 2));
2387 const MInt varStart = pCellId * distVars;
2388
2389 MFloat* const oldDistributionsStart = &oldDistributions[distStart];
2390 MFloat* const distributionsStart = &distributions[distStart];
2391 MFloat* const oldDistributionsTStart = &oldDistributionsThermal[distStart];
2392 MFloat* const distributionsTStart = &distributionsThermal[distStart];
2393 MFloat* const oldDistributionsTransportStart = &oldDistributionsTransport[distStart];
2394 MFloat* const distributionsTransportStart = &distributionsTransport[distStart];
2395
2396 MFloat* const variablesStart = &variables[varStart];
2397#else
2398 a_nu(pCellId) = m_nu;
2399 a_kappa(pCellId) = m_kappa;
2400 a_diffusivity(pCellId) = m_diffusivity;
2401#endif
2402
2403 const MFloat tmp_FFPOW2 = FFPOW2(index);
2404 const MFloat l_omega = 2.0 / (1.0 + 6.0 * m_nu * tmp_FFPOW2);
2405 const MFloat l_omegaT = 2.0 / (1.0 + factor * m_kappa * tmp_FFPOW2);
2406 const MFloat l_omegaD = 2.0 / (1.0 + 6.0 * m_diffusivity * tmp_FFPOW2);
2407
2408 swap_variables(pCellId);
2409
2410 // Reinit macroscopic variables before recalculation
2411 MFloat l_v[nDim] = {0.0};
2412 MFloat l_rho = 0.0;
2413 MFloat l_t = 0.0;
2414 MFloat l_c = 0.0;
2415
2416#ifdef WAR_NVHPC_PSTL
2417 // Add forcing term and calculate density rho
2418 for(MInt j = 0; j < nDist - 1; j++) {
2419 // Add forcing term and calculate density rho
2420 l_rho += a_oldDistribution(pCellId, j);
2421 l_t += a_oldDistributionThermal(pCellId, j);
2422 l_c += a_oldDistributionTransport(pCellId, j);
2423 }
2424 // Do not forget the last distribution
2425 l_rho += a_oldDistribution(pCellId, nDist - 1);
2426 l_t += a_oldDistributionThermal(pCellId, nDist - 1);
2427 l_c += a_oldDistributionTransport(pCellId, nDist - 1);
2428#else
2429 // Add forcing term and calculate density rho
2430 for(MInt j = 0; j < nDist - 1; j++) {
2431 l_rho += oldDistributionsStart[j];
2432 l_t += oldDistributionsTStart[j];
2433 l_c += oldDistributionsTransportStart[j];
2434 }
2435 // Do not forget the last distribution
2436 l_rho += oldDistributionsStart[nDist - 1];
2437 l_t += oldDistributionsTStart[nDist - 1];
2438 l_c += oldDistributionsTransportStart[nDist - 1];
2439#endif
2440
2441 // Calculate macroscopic variables
2442#ifndef WAR_NVHPC_PSTL
2443 if constexpr(nDim == 2) {
2444 // WARNING!!! The velocity should be calculated as in 3d
2445 // However, result is correct
2446 // calculation of u
2447 l_v[0] = oldDistributionsStart[1] + oldDistributionsStart[4] + oldDistributionsStart[5]
2448 - oldDistributionsStart[7] - oldDistributionsStart[6] - oldDistributionsStart[0];
2449 // calculation of v
2450 l_v[1] = oldDistributionsStart[7] + oldDistributionsStart[3] + oldDistributionsStart[4]
2451 - oldDistributionsStart[6] - oldDistributionsStart[2] - oldDistributionsStart[5];
2452 } else {
2453#endif
2454 for(MInt j = 0; j < fldlen; j++) {
2455 for(MInt d = 0; d < nDim; d++) {
2456#ifdef WAR_NVHPC_PSTL
2457 l_v[d] += a_oldDistribution(pCellId, m_pFld[d * fldlen + j]);
2458 l_v[d] -= a_oldDistribution(pCellId, m_nFld[d * fldlen + j]);
2459#else
2460 l_v[d] += oldDistributionsStart[Ld::pFld(d, j)];
2461 l_v[d] -= oldDistributionsStart[Ld::nFld(d, j)];
2462#endif
2463 }
2464 }
2465#ifndef WAR_NVHPC_PSTL
2466 }
2467#endif
2468
2469 std::array<MFloat, nDim> u{};
2470 for(MInt d = 0; d < nDim; d++) {
2471 u[d] = l_v[d] / l_rho;
2472 }
2473
2474 // Save new macroscopic variables in cell
2475#ifdef WAR_NVHPC_PSTL
2476 for(MInt d = 0; d < nDim; d++) {
2477 a_variable(pCellId, d) = l_v[d];
2478 }
2479 a_variable(pCellId, pvrho) = l_rho;
2480 a_variable(pCellId, pvc) = l_c;
2481 IF_CONSTEXPR(thermalMode == 0) { a_variable(pCellId, pvt) = l_t; }
2482 IF_CONSTEXPR(thermalMode == 1) {
2483 const MFloat D = (MFloat)nDim;
2484 const MFloat l_ie_rho = l_t;
2485 l_t = l_ie_rho * F2 / (D * l_rho);
2486 a_variable(pCellId, pvt) = l_t;
2487 }
2488 IF_CONSTEXPR(thermalMode == 2) {
2489 const MFloat D = (MFloat)nDim;
2490 const MFloat sqVel = std::inner_product(&u[0], &u[nDim], &u[0], F0);
2491 const MFloat l_te_rho = l_t;
2492 l_t = (l_te_rho / l_rho - sqVel * F1B2) * F2 / D;
2493 a_variable(pCellId, pvt) = l_t;
2494 for(MInt d = 0; d < nDim; d++) {
2495 a_variable(pCellId, d) = l_v[d];
2496 }
2497 }
2498#else
2499 for(MInt d = 0; d < nDim; d++) {
2500 variablesStart[d] = l_v[d];
2501 }
2502 variablesStart[pvrho] = l_rho;
2503 variablesStart[pvc] = l_c;
2504 IF_CONSTEXPR(thermalMode == 0) { variablesStart[pvt] = l_t; }
2505 IF_CONSTEXPR(thermalMode == 1) {
2506 const MFloat D = (MFloat)nDim;
2507 const MFloat l_ie_rho = l_t;
2508 l_t = l_ie_rho * F2 / (D * l_rho);
2509 variablesStart[pvt] = l_t;
2510 }
2511 IF_CONSTEXPR(thermalMode == 2) {
2512 const MFloat D = (MFloat)nDim;
2513 const MFloat sqVel = std::inner_product(&u[0], &u[nDim], &u[0], F0);
2514 const MFloat l_te_rho = l_t;
2515 l_t = (l_te_rho / l_rho - sqVel * F1B2) * F2 / D;
2516 variablesStart[pvt] = l_t;
2517 for(MInt d = 0; d < nDim; d++) {
2518 variablesStart[d] = l_v[d];
2519 }
2520 }
2521#endif
2522
2523 std::array<MFloat, nDist> eqDist;
2524 eqDist = getEqDists(l_rho, u.data());
2525 std::array<MFloat, nDist> eqDistT;
2526 eqDistT = getEqDistsThermal_<thermalMode>(l_t, l_rho, u.data());
2527 std::array<MFloat, nDist> eqDistC;
2528 eqDistC = getEqDistsTransport(l_c, u.data());
2529
2530 std::array<MFloat, nDist> Sj;
2531 IF_CONSTEXPR(thermalMode == 2) {
2532 std::array<MFloat, 2 * nDim> b{};
2533 for(MInt d = 0; d < nDim; d++) {
2534 b[2 * d] = -u[d];
2535 b[2 * d + 1] = u[d];
2536 }
2537 const MFloat sqVel = std::inner_product(&u[0], &u[nDim], &u[0], F0);
2538#ifdef WAR_NVHPC_PSTL
2539 for(MInt j = 0; j < m_distFld[0]; j++) {
2540 Sj[j] = (l_omegaT - l_omega) * (b[j] - sqVel * F1B2) * (a_oldDistribution(pCellId, j) - eqDist[j]);
2541 }
2542 for(MInt j = 0; j < m_distFld[1]; j++) {
2543 const MInt p = 2 * j;
2544 const MInt pos = j + m_distFld[0];
2545 const MFloat tmp = (b[m_mFld1[p]] + b[m_mFld1[p + 1]]);
2546 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2) * (a_oldDistribution(pCellId, pos) - eqDist[pos]);
2547 }
2548 for(MInt j = 0; j < m_distFld[2]; j++) {
2549 const MInt p = 3 * j;
2550 const MInt pos = j + m_distFld[0] + m_distFld[1];
2551 const MFloat tmp = (b[m_mFld2[p]] + b[m_mFld2[p + 1]] + b[m_mFld2[p + 2]]);
2552 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2) * (a_oldDistribution(pCellId, pos) - eqDist[pos]);
2553 }
2554 Sj[Ld::lastId()] = (l_omegaT - l_omega) * (F0 - sqVel * F1B2)
2555 * (a_oldDistribution(pCellId, Ld::lastId()) - eqDist[Ld::lastId()]);
2556#else
2557 for(MInt j = 0; j < Ld::distFld(0); j++) {
2558 Sj[j] = (l_omegaT - l_omega) * (b[j] - sqVel * F1B2) * (oldDistributionsStart[j] - eqDist[j]);
2559 }
2560 for(MInt j = 0; j < Ld::distFld(1); j++) {
2561 const MInt p = 2 * j;
2562 const MInt pos = j + Ld::distFld(0);
2563 const MFloat tmp = (b[Ld::mFld1(p)] + b[Ld::mFld1(p + 1)]);
2564 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2) * (oldDistributionsStart[pos] - eqDist[pos]);
2565 }
2566 for(MInt j = 0; j < Ld::distFld(2); j++) {
2567 const MInt p = 3 * j;
2568 const MInt pos = j + Ld::distFld(0) + Ld::distFld(1);
2569 const MFloat tmp = (b[Ld::mFld2(p)] + b[Ld::mFld2(p + 1)] + b[Ld::mFld2(p + 2)]);
2570 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2) * (oldDistributionsStart[pos] - eqDist[pos]);
2571 }
2572 Sj[Ld::lastId()] =
2573 (l_omegaT - l_omega) * (F0 - sqVel * F1B2) * (oldDistributionsStart[Ld::lastId()] - eqDist[Ld::lastId()]);
2574#endif
2575 }
2576
2577 // Calculation of new distributions
2578 for(MInt j = 0; j < nDist; j++) {
2579#ifdef WAR_NVHPC_PSTL
2580 a_distribution(pCellId, j) =
2581 a_oldDistribution(pCellId, j) + l_omega * (eqDist[j] - a_oldDistribution(pCellId, j));
2582 a_distributionThermal(pCellId, j) =
2583 a_oldDistributionThermal(pCellId, j) + l_omegaT * (eqDistT[j] - a_oldDistributionThermal(pCellId, j));
2584 a_distributionTransport(pCellId, j) =
2585 a_oldDistributionTransport(pCellId, j) + l_omegaD * (eqDistC[j] - a_oldDistributionTransport(pCellId, j));
2586 IF_CONSTEXPR(thermalMode == 2) { a_distributionThermal(pCellId, j) += Sj[j]; }
2587#else
2588 distributionsStart[j] = oldDistributionsStart[j] + l_omega * (eqDist[j] - oldDistributionsStart[j]);
2589 distributionsTStart[j] = oldDistributionsTStart[j] + l_omegaT * (eqDistT[j] - oldDistributionsTStart[j]);
2590 IF_CONSTEXPR(thermalMode == 2) { distributionsTStart[j] += Sj[j]; }
2591 distributionsTransportStart[j] = oldDistributionsTransportStart[j] + l_omegaD * (eqDistC[j] - oldDistributionsTransportStart[j]);
2592#endif
2593 }
2594 }
2595 });
2596}
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.
static constexpr MInt mFld1(MInt i)
static constexpr MInt mFld2(MInt i)
static constexpr MInt distFld(MInt i)

◆ bgki_thermal_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_thermal_collision_step
virtual
Author
Ludwig Eduard Boltzmann
Date
20.2.1844
Property value solverMethod
MAIA_LATTICE_BGK_THERMAL

Collision step of the incompressible LBGK algorithm for thermal LB

Definition at line 3004 of file lbsolverdxqy.cpp.

3004 {
3005 TRACE();
3006
3007 bgki_thermal_collision_step_base<0>();
3008}

◆ bgki_thermal_collision_step_base()

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt thermalMode>
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_thermal_collision_step_base

Definition at line 2636 of file lbsolverdxqy.cpp.

2636 {
2637 TRACE();
2638
2639 const MInt pvrho = PV->RHO;
2640 const MInt pvt = PV->T;
2641
2642 constexpr MInt fldlen = Ld::dxQyFld();
2643
2644 // Update the global Reynolds number if we use the tanh-adaption
2645 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
2646 const MFloat scale =
2647 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
2648 + 0.5;
2649
2650 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
2651
2652 // final timestep reached
2653 if(globalTimeStep == m_initStartTime + m_initTime) {
2654 m_Re = m_finalRe;
2655 m_tanhInit = 0;
2656 }
2657 }
2658
2659 // Update the according nu
2660 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
2661
2662 // Calculate heat diffusion coefficient
2663 m_kappa = m_nu / m_Pr;
2664
2665#ifndef WAR_NVHPC_PSTL
2666 // inner loop references
2667 const MInt* const RESTRICT activeCellList = ALIGNED_I(m_activeCellList);
2668 MFloat* const RESTRICT cnu = ALIGNED_MF(&(a_nu(0)));
2669 MFloat* const RESTRICT ckappa = ALIGNED_MF(&(a_kappa(0)));
2670 const MInt* const RESTRICT clevel = ALIGNED_I(&(this->m_cells.level(0)));
2671 MFloat* const RESTRICT oldDistributions = ALIGNED_MF(&(a_oldDistribution(0, 0)));
2672 MFloat* const RESTRICT distributions = ALIGNED_MF(&(a_distribution(0, 0)));
2673 MFloat* const RESTRICT oldDistributionsThermal = ALIGNED_MF(&(a_oldDistributionThermal(0, 0)));
2674 MFloat* const RESTRICT distributionsThermal = ALIGNED_MF(&(a_distributionThermal(0, 0)));
2675 MFloat* const RESTRICT variables = ALIGNED_MF(&(a_variable(0, 0)));
2676 const MFloat* const Fp = ALIGNED_MF(m_Fext);
2677 // members and globals
2678 const MInt maxLevel_ = maxLevel();
2679 // distances
2680 const MInt distNu = &a_nu(1) - &a_nu(0);
2681 const MInt distKappa = &a_kappa(1) - &a_kappa(0);
2682 const MInt distLevel = &(this->m_cells.level(1)) - &(this->m_cells.level(0));
2683 const MInt distVars = &(a_variable(1, 0)) - &(a_variable(0, 0));
2684#endif
2685 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
2686 const MInt gTS = globalTimeStep;
2687
2688 const MFloat factor = (thermalMode == 1) ? ((nDim == 2) ? 3.0 : 18.0 / 5.0) : F6;
2689
2690 // loop over all cells
2691 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt i) {
2692#ifdef WAR_NVHPC_PSTL
2693 const MInt pCellId = m_activeCellList[i];
2694 const MInt index = maxLevel() - this->a_level(pCellId);
2695#else
2696 const MInt pCellId = activeCellList[i];
2697 const MInt index = maxLevel_ - clevel[pCellId * distLevel];
2698#endif
2699
2700 // perform collision on finest level in every timestep,
2701 // on the next coarser level every second timestep, and so on
2702 if((gTS - 1) % IPOW2(index) == 0) {
2703 // save nu for bndcnd and interface interpolation
2704#ifndef WAR_NVHPC_PSTL
2705 cnu[pCellId * distNu] = m_nu;
2706 ckappa[pCellId * distKappa] = m_kappa;
2707
2708 const MInt distStart = pCellId * nDist;
2709 // varStart = (pCellId * distVars) + (distVarOldVar *
2710 // !((MInt)floor((MFloat)localGlobalTimeStep/fpow2[index]) % 2));
2711 const MInt varStart = pCellId * distVars;
2712
2713 MFloat* const oldDistributionsStart = &oldDistributions[distStart];
2714 MFloat* const distributionsStart = &distributions[distStart];
2715 MFloat* const oldDistributionsTStart = &oldDistributionsThermal[distStart];
2716 MFloat* const distributionsTStart = &distributionsThermal[distStart];
2717
2718 MFloat* const variablesStart = &variables[varStart];
2719#else
2720 a_nu(pCellId) = m_nu;
2721 a_kappa(pCellId) = m_kappa;
2722#endif
2723
2724 const MFloat tmp_FPOW2 = FPOW2(index);
2725 const MFloat tmp_FFPOW2 = FFPOW2(index);
2726 const MFloat l_omega = 2.0 / (1.0 + 6.0 * m_nu * tmp_FFPOW2);
2727 const MFloat l_omegaT = 2.0 / (1.0 + factor * m_kappa * tmp_FFPOW2);
2728
2729 swap_variables(pCellId);
2730
2731 // Reinit macroscopic variables before recalculation
2732 MFloat l_v[nDim] = {0.0};
2733 MFloat l_rho = 0.0;
2734 MFloat l_t = 0.0;
2735
2736#ifdef WAR_NVHPC_PSTL
2737 // Add forcing term and calculate density rho
2738 for(MInt j = 0; j < nDist - 1; j++) {
2739 IF_CONSTEXPR(thermalMode != 2) a_oldDistribution(pCellId, j) += tmp_FPOW2 * m_Fext[j];
2740 // Add forcing term and calculate density rho
2741 l_rho += a_oldDistribution(pCellId, j);
2742 l_t += a_oldDistributionThermal(pCellId, j);
2743 }
2744 // Do not forget the last distribution
2745 l_rho += a_oldDistribution(pCellId, nDist - 1);
2746 l_t += a_oldDistributionThermal(pCellId, nDist - 1);
2747#else
2748 // Add forcing term and calculate density rho
2749 for(MInt j = 0; j < nDist - 1; j++) {
2750 IF_CONSTEXPR(thermalMode != 2) oldDistributionsStart[j] += tmp_FPOW2 * Fp[j];
2751 l_rho += oldDistributionsStart[j];
2752 l_t += oldDistributionsTStart[j];
2753 }
2754 // Do not forget the last distribution
2755 l_rho += oldDistributionsStart[nDist - 1];
2756 l_t += oldDistributionsTStart[nDist - 1];
2757#endif
2758
2759 // Calculate macroscopic variables
2760#ifndef WAR_NVHPC_PSTL
2761 if constexpr(nDim == 2) {
2762 // WARNING!!! The velocity should be calculated as in 3d
2763 // However, result is correct
2764 // calculation of u
2765 l_v[0] = oldDistributionsStart[1] + oldDistributionsStart[4] + oldDistributionsStart[5]
2766 - oldDistributionsStart[7] - oldDistributionsStart[6] - oldDistributionsStart[0];
2767 // calculation of v
2768 l_v[1] = oldDistributionsStart[7] + oldDistributionsStart[3] + oldDistributionsStart[4]
2769 - oldDistributionsStart[6] - oldDistributionsStart[2] - oldDistributionsStart[5];
2770 } else {
2771#endif
2772 for(MInt j = 0; j < fldlen; j++) {
2773 for(MInt d = 0; d < nDim; d++) {
2774#ifdef WAR_NVHPC_PSTL
2775 l_v[d] += a_oldDistribution(pCellId, m_pFld[d * fldlen + j]);
2776 l_v[d] -= a_oldDistribution(pCellId, m_nFld[d * fldlen + j]);
2777#else
2778 l_v[d] += oldDistributionsStart[Ld::pFld(d, j)];
2779 l_v[d] -= oldDistributionsStart[Ld::nFld(d, j)];
2780#endif
2781 }
2782 }
2783#ifndef WAR_NVHPC_PSTL
2784 }
2785#endif
2786
2787 std::array<MFloat, nDim> u{};
2788 for(MInt d = 0; d < nDim; d++) {
2789 u[d] = l_v[d] / l_rho;
2790 }
2791
2792 // Save new macroscopic variables in cell
2793#ifdef WAR_NVHPC_PSTL
2794 for(MInt d = 0; d < nDim; d++) {
2795 a_variable(pCellId, d) = l_v[d];
2796 }
2797 a_variable(pCellId, pvrho) = l_rho;
2798 IF_CONSTEXPR(thermalMode == 0) { a_variable(pCellId, pvt) = l_t; }
2799 IF_CONSTEXPR(thermalMode == 1) {
2800 const MFloat D = (MFloat)nDim;
2801 const MFloat l_ie_rho = l_t;
2802 l_t = l_ie_rho * F2 / (D * l_rho);
2803 a_variable(pCellId, pvt) = l_t;
2804 }
2805 IF_CONSTEXPR(thermalMode == 2) {
2806 const MFloat accelerationForce = (this->m_externalForcing) ? m_densityGradient * F1B3 : F0;
2807 const MFloat D = (MFloat)nDim;
2808 // Set the external acceleratrion vector
2809 // So far only for a channel in x-direction
2810 std::array<MFloat, nDim> a{};
2811 a[0] = accelerationForce;
2812 for(MInt d = 0; d < nDim; d++) {
2813 l_v[d] += l_rho * tmp_FPOW2 * a[d] * F1B2;
2814 u[d] = l_v[d] / l_rho;
2815 }
2816 const MFloat sqVel = std::inner_product(&u[0], &u[nDim], &u[0], F0);
2817
2818 MFloat u_x_a = F0;
2819 for(MInt d = 0; d < nDim; d++) {
2820 u_x_a += u[d] * a[d];
2821 }
2822 const MFloat l_te_rho = l_t + F1B2 * tmp_FPOW2 * l_rho * u_x_a;
2823 l_t = (l_te_rho / l_rho - sqVel * F1B2) * F2 / D;
2824 a_variable(pCellId, pvt) = l_t;
2825 for(MInt d = 0; d < nDim; d++) {
2826 a_variable(pCellId, d) = l_v[d];
2827 }
2828 }
2829#else
2830 for(MInt d = 0; d < nDim; d++) {
2831 variablesStart[d] = l_v[d];
2832 }
2833 variablesStart[pvrho] = l_rho;
2834 IF_CONSTEXPR(thermalMode == 0) { variablesStart[pvt] = l_t; }
2835 IF_CONSTEXPR(thermalMode == 1) {
2836 const MFloat D = (MFloat)nDim;
2837 const MFloat l_ie_rho = l_t;
2838 l_t = l_ie_rho * F2 / (D * l_rho);
2839 variablesStart[pvt] = l_t;
2840 }
2841 IF_CONSTEXPR(thermalMode == 2) {
2842 const MFloat accelerationForce = (this->m_externalForcing) ? m_densityGradient * F1B3 : F0;
2843 const MFloat D = (MFloat)nDim;
2844 // Set the external acceleratrion vector
2845 // So far only for a channel in x-direction
2846 std::array<MFloat, nDim> a{};
2847 a[0] = accelerationForce;
2848 for(MInt d = 0; d < nDim; d++) {
2849 l_v[d] += l_rho * tmp_FPOW2 * a[d] * F1B2;
2850 u[d] = l_v[d] / l_rho;
2851 }
2852 const MFloat sqVel = std::inner_product(&u[0], &u[nDim], &u[0], F0);
2853
2854 MFloat u_x_a = F0;
2855 for(MInt d = 0; d < nDim; d++) {
2856 u_x_a += u[d] * a[d];
2857 }
2858 const MFloat l_te_rho = l_t + F1B2 * tmp_FPOW2 * l_rho * u_x_a;
2859 l_t = (l_te_rho / l_rho - sqVel * F1B2) * F2 / D;
2860 variablesStart[pvt] = l_t;
2861 for(MInt d = 0; d < nDim; d++) {
2862 variablesStart[d] = l_v[d];
2863 }
2864 }
2865#endif
2866
2867 std::array<MFloat, nDist> eqDist;
2868 eqDist = getEqDists(l_rho, u.data());
2869 std::array<MFloat, nDist> eqDistT;
2870 eqDistT = getEqDistsThermal_<thermalMode>(l_t, l_rho, u.data());
2871
2872 std::array<MFloat, nDist> forcing;
2873 std::array<MFloat, nDist> forcingT;
2874 std::array<MFloat, nDist> Sj;
2875 IF_CONSTEXPR(thermalMode == 2) {
2876 const MFloat accelerationForce = (this->m_externalForcing) ? m_densityGradient * F1B3 : F0;
2877 std::array<MFloat, 2 * nDim> a{};
2878 a[0] = -accelerationForce;
2879 a[1] = accelerationForce;
2880 MFloat u_x_a = F0;
2881 std::array<MFloat, 2 * nDim> b;
2882 for(MInt d = 0; d < nDim; d++) {
2883 b[2 * d] = -u[d];
2884 b[2 * d + 1] = u[d];
2885 u_x_a += b[d * 2 + 1] * a[d * 2 + 1];
2886 }
2887 const MFloat D = (MFloat)nDim;
2888 const MFloat sqVel = std::inner_product(&u[0], &u[nDim], &u[0], F0);
2889 const MFloat l_te_rho = (l_t * D * F1B2 + sqVel * F1B2) * l_rho;
2890#ifdef WAR_NVHPC_PSTL
2891 for(MInt j = 0; j < m_distFld[0]; j++) {
2892 forcing[j] = m_tp[1] * F1BCSsq * l_rho * (a[j] + a[j] * b[j] * F1BCSsq - u_x_a);
2893 Sj[j] = (l_omegaT - l_omega) * (b[j] - sqVel * F1B2)
2894 * (a_oldDistribution(pCellId, j) - eqDist[j] + F1B2 * tmp_FPOW2 * forcing[j]);
2895 forcingT[j] = m_tp[1] * F1BCSsq * l_te_rho * a[j] + a_oldDistribution(pCellId, j) * a[j];
2896 forcing[j] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2897 forcingT[j] *= tmp_FPOW2 * (F1 - l_omegaT * F1B2);
2898 }
2899 for(MInt j = 0; j < m_distFld[1]; j++) {
2900 const MInt p = 2 * j;
2901 const MInt pos = j + m_distFld[0];
2902 const MFloat tmp = (b[m_mFld1[p]] + b[m_mFld1[p + 1]]);
2903 const MFloat tmpT = (a[m_mFld1[p]] + a[m_mFld1[p + 1]]);
2904 forcing[pos] = m_tp[2] * F1BCSsq * l_rho * (tmpT + tmpT * tmp * F1BCSsq - u_x_a);
2905 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2)
2906 * (a_oldDistribution(pCellId, pos) - eqDist[pos] + F1B2 * tmp_FPOW2 * forcing[pos]);
2907 forcingT[pos] = m_tp[2] * F1BCSsq * l_te_rho * tmpT + a_oldDistribution(pCellId, pos) * tmpT;
2908 forcing[pos] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2909 forcingT[pos] *= tmp_FPOW2 * (F1 - l_omegaT * F1B2);
2910 }
2911 for(MInt j = 0; j < m_distFld[2]; j++) {
2912 const MInt p = 3 * j;
2913 const MInt pos = j + m_distFld[0] + m_distFld[1];
2914 const MFloat tmp = (b[m_mFld2[p]] + b[m_mFld2[p + 1]] + b[m_mFld2[p + 2]]);
2915 const MFloat tmpT = (a[m_mFld2[p]] + a[m_mFld2[p + 1]] + a[m_mFld2[p + 2]]);
2916 forcing[pos] = m_tp[3] * F1BCSsq * l_rho * (tmpT + tmpT * tmp * F1BCSsq - u_x_a);
2917 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2)
2918 * (a_oldDistribution(pCellId, pos) - eqDist[pos] + F1B2 * tmp_FPOW2 * forcing[pos]);
2919 forcingT[pos] = m_tp[3] * F1BCSsq * l_te_rho * tmpT + a_oldDistribution(pCellId, pos) * tmpT;
2920 forcing[pos] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2921 forcingT[pos] *= tmp_FPOW2 * (F1 - l_omegaT * F1B2);
2922 }
2923 forcing[Ld::lastId()] = m_tp[0] * l_rho * (-F1BCSsq * u_x_a);
2924 Sj[Ld::lastId()] = (l_omegaT - l_omega) * (F0 - sqVel * F1B2)
2925 * (a_oldDistribution(pCellId, Ld::lastId()) - eqDist[Ld::lastId()]
2926 + F1B2 * tmp_FPOW2 * forcing[Ld::lastId()]);
2927 forcingT[Ld::lastId()] = F0;
2928 forcing[Ld::lastId()] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2929#else
2930 for(MInt j = 0; j < Ld::distFld(0); j++) {
2931 forcing[j] = Ld::tp(1) * F1BCSsq * l_rho * (a[j] + a[j] * b[j] * F1BCSsq - u_x_a);
2932 Sj[j] = (l_omegaT - l_omega) * (b[j] - sqVel * F1B2)
2933 * (oldDistributionsStart[j] - eqDist[j] + F1B2 * tmp_FPOW2 * forcing[j]);
2934 forcingT[j] = Ld::tp(1) * F1BCSsq * l_te_rho * a[j] + oldDistributionsStart[j] * a[j];
2935 forcing[j] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2936 forcingT[j] *= tmp_FPOW2 * (F1 - l_omegaT * F1B2);
2937 }
2938 for(MInt j = 0; j < Ld::distFld(1); j++) {
2939 const MInt p = 2 * j;
2940 const MInt pos = j + Ld::distFld(0);
2941 const MFloat tmp = (b[Ld::mFld1(p)] + b[Ld::mFld1(p + 1)]);
2942 const MFloat tmpT = (a[Ld::mFld1(p)] + a[Ld::mFld1(p + 1)]);
2943 forcing[pos] = Ld::tp(2) * F1BCSsq * l_rho * (tmpT + tmpT * tmp * F1BCSsq - u_x_a);
2944 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2)
2945 * (oldDistributionsStart[pos] - eqDist[pos] + F1B2 * tmp_FPOW2 * forcing[pos]);
2946 forcingT[pos] = Ld::tp(2) * F1BCSsq * l_te_rho * tmpT + oldDistributionsStart[pos] * tmpT;
2947 forcing[pos] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2948 forcingT[pos] *= tmp_FPOW2 * (F1 - l_omegaT * F1B2);
2949 }
2950 for(MInt j = 0; j < Ld::distFld(2); j++) {
2951 const MInt p = 3 * j;
2952 const MInt pos = j + Ld::distFld(0) + Ld::distFld(1);
2953 const MFloat tmp = (b[Ld::mFld2(p)] + b[Ld::mFld2(p + 1)] + b[Ld::mFld2(p + 2)]);
2954 const MFloat tmpT = (a[Ld::mFld2(p)] + a[Ld::mFld2(p + 1)] + a[Ld::mFld2(p + 2)]);
2955 forcing[pos] = Ld::tp(3) * F1BCSsq * l_rho * (tmpT + tmpT * tmp * F1BCSsq - u_x_a);
2956 Sj[pos] = (l_omegaT - l_omega) * (tmp - sqVel * F1B2)
2957 * (oldDistributionsStart[pos] - eqDist[pos] + F1B2 * tmp_FPOW2 * forcing[pos]);
2958 forcingT[pos] = Ld::tp(3) * F1BCSsq * l_te_rho * tmpT + oldDistributionsStart[pos] * tmpT;
2959 forcing[pos] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2960 forcingT[pos] *= tmp_FPOW2 * (F1 - l_omegaT * F1B2);
2961 }
2962 forcing[Ld::lastId()] = Ld::tp(0) * l_rho * (-F1BCSsq * u_x_a);
2963 Sj[Ld::lastId()] =
2964 (l_omegaT - l_omega) * (F0 - sqVel * F1B2)
2965 * (oldDistributionsStart[Ld::lastId()] - eqDist[Ld::lastId()] + F1B2 * tmp_FPOW2 * forcing[Ld::lastId()]);
2966 forcingT[Ld::lastId()] = F0;
2967 forcing[Ld::lastId()] *= tmp_FPOW2 * (F1 - l_omega * F1B2);
2968#endif
2969 }
2970
2971 // Calculation of new distributions
2972 for(MInt j = 0; j < nDist; j++) {
2973#ifdef WAR_NVHPC_PSTL
2974 a_distribution(pCellId, j) =
2975 a_oldDistribution(pCellId, j) + l_omega * (eqDist[j] - a_oldDistribution(pCellId, j));
2976 a_distributionThermal(pCellId, j) =
2977 a_oldDistributionThermal(pCellId, j) + l_omegaT * (eqDistT[j] - a_oldDistributionThermal(pCellId, j));
2978 IF_CONSTEXPR(thermalMode == 2) {
2979 a_distribution(pCellId, j) += forcing[j];
2980 a_distributionThermal(pCellId, j) += forcingT[j] + Sj[j];
2981 }
2982#else
2983 distributionsStart[j] = oldDistributionsStart[j] + l_omega * (eqDist[j] - oldDistributionsStart[j]);
2984 distributionsTStart[j] = oldDistributionsTStart[j] + l_omegaT * (eqDistT[j] - oldDistributionsTStart[j]);
2985 IF_CONSTEXPR(thermalMode == 2) {
2986 distributionsStart[j] += forcing[j];
2987 distributionsTStart[j] += forcingT[j] + Sj[j];
2988 }
2989#endif
2990 }
2991 }
2992 });
2993}
Definition: contexttypes.h:19

◆ bgki_totalEnergy_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::bgki_totalEnergy_collision_step
virtual
Property value solverMethod
MAIA_LATTICE_BGK_TOTALENERGY

Collision step of the incompressible LBGK algorithm with TLBGK extension using a total energy distribution function approach

Performs the collision step for the BGK method with TLBGK extension:

  • the macroscopic variables are obtained by evaluating the moments of the PPDFs.
  • seperate local velocities are calculated by dividing by the density \(\rho\).
  • Recalculation of the PPDFs for all directions for the LBGK and TLBGK. Note, that the density \(rho\) has been moved outside the inner brackets of the equilibrium distribution function and that different collision frequencies \(\omega\) and \(\omega_T\) are used for the LBGK and the TLBGK, respectively. The velocities of the TLBGK are used from that one obtained from the moments of the LBGK.


Definition at line 3061 of file lbsolverdxqy.cpp.

3061 {
3062 TRACE();
3063
3064 bgki_thermal_collision_step_base<2>();
3065}

◆ calcNodalLsValues()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::calcNodalLsValues
virtual

Definition at line 7137 of file lbsolverdxqy.cpp.

7137 {
7138 TRACE();
7139
7140 // TODO labels:LB Unify for 2D/3D (as far as possible).
7141
7142 if constexpr(nDim == 3) {
7143 MInt startSet = this->m_levelSetId;
7144 static constexpr MInt maxNoDistributions = IPOW3[nDim];
7145 static constexpr MInt firstCornerDist = 18;
7146 static constexpr MInt firstEdgeDist = 6;
7147 static constexpr MInt noEdges = 12;
7148
7149 // TODO labels:LB Use lattice descriptor.
7150
7151 static constexpr MInt lb_CornerMappingForSurfaces[6][4] = {{18, 19, 20, 21}, {22, 23, 24, 25}, {18, 19, 22, 23},
7152 {20, 21, 24, 25}, {18, 20, 22, 24}, {19, 21, 23, 25}};
7153
7154 static constexpr MInt lb_CornerMappingForEdges[12][2] = {{18, 19}, {20, 21}, {22, 23}, {24, 25},
7155 {18, 20}, {19, 21}, {22, 24}, {23, 25},
7156 {18, 22}, {19, 23}, {20, 24}, {21, 25}};
7157
7158 static constexpr MInt lb_geomIntersToLb[8] = {0, 4, 2, 6, 1, 5, 3, 7};
7159
7160 static constexpr MFloat factor[26] = {F1, F1, F1, F1, F1, F1, SQRT2, SQRT2, SQRT2,
7161 SQRT2, SQRT2, SQRT2, SQRT2, SQRT2, SQRT2, SQRT2, SQRT2, SQRT2,
7162 SQRT3, SQRT3, SQRT3, SQRT3, SQRT3, SQRT3, SQRT3, SQRT3};
7163
7164 // 1. Get the nodal Ls values form the CutCandidates Class
7165 // 2. Find the Cut Cells and calculate the missing Ls values
7166 // at the cell surfaces and cell edges for those
7167 // 3. Calculate the Wall distances
7168 this->m_currentNoG0Cells = 0;
7170 m_bndCnd->m_boundaryCellsMb.reset(this->m_noG0CandidatesTotal);
7172
7173 for(MInt candidate = 0; candidate < this->m_noG0CandidatesTotal; candidate++) {
7174 for(MInt set = startSet; set < this->m_maxNoSets; set++) {
7175 const MInt arrayPosNGV = set * (maxNoDistributions - 1);
7176 for(MInt i = 0; i < IPOW2(nDim); i++) {
7177 this->m_nodalGValues[candidate][arrayPosNGV + firstCornerDist + lb_geomIntersToLb[i]] =
7178 this->m_G0Candidates[candidate].nodalValues[set][i];
7179 }
7180
7181 // Step a: Find Edges with a cut, i.e. the nodes of the edge have opposite signs in m_nodalGValues
7182 MInt edgeCounter = 0;
7183 for(MInt edge = 0; edge < noEdges; edge++) {
7184 MFloat edgeGValue = this->m_nodalGValues[candidate][arrayPosNGV + Ld::nodalConnectivityVector(edge, 0)]
7185 * this->m_nodalGValues[candidate][arrayPosNGV + Ld::nodalConnectivityVector(edge, 1)];
7186
7187 if(edgeGValue < 0) edgeCounter++;
7188 }
7189
7190 // Step b: If there are less than two cuts for a G0Candidate it is not a G0 Cell. Skip that cell!!
7191 const MInt pCellId = this->m_G0Candidates[candidate].cellId;
7192 const MInt actualSet = set - startSet;
7193 if(edgeCounter < 2) {
7194 this->a_isG0CandidateOfSet(pCellId, actualSet) = false;
7195 continue;
7196 } else {
7197 this->a_isG0CandidateOfSet(pCellId, actualSet) = true;
7198 this->m_G0CellMapping[pCellId] = this->m_currentNoG0Cells;
7199 // Use new mapping in bndCnd
7200 m_bndCnd->m_boundaryCellMappingMb[pCellId] = this->m_currentNoG0Cells;
7201 }
7202
7203 // Add relevant information to G0 boundary cell collector
7204 // Cell is a G0 boundary cell
7205 const MInt boundaryCellId = m_bndCnd->m_boundaryCellsMb.size();
7207 m_bndCnd->m_boundaryCellsMb.cellId(boundaryCellId) = pCellId;
7208
7209 // Step c: Calculate the missing Ls values at the cell surfaces and cell edges
7210 this->m_G0CellList[this->m_currentNoG0Cells] = pCellId;
7211 for(MInt dist = 0; dist < firstEdgeDist; dist++) {
7212 for(MInt i = 0; i < 4; i++) {
7213 this->m_nodalGValues[candidate][arrayPosNGV + dist] +=
7214 this->m_nodalGValues[candidate][arrayPosNGV + lb_CornerMappingForSurfaces[dist][i]];
7215 }
7216 this->m_nodalGValues[candidate][arrayPosNGV + dist] /= F4;
7217 }
7218 for(MInt dist = firstEdgeDist; dist < firstCornerDist; dist++) {
7219 for(MInt i = 0; i < 2; i++) {
7220 this->m_nodalGValues[candidate][arrayPosNGV + dist] +=
7221 this->m_nodalGValues[candidate][arrayPosNGV + lb_CornerMappingForEdges[dist - firstEdgeDist][i]];
7222 }
7223 this->m_nodalGValues[candidate][arrayPosNGV + dist] /= F2;
7224 }
7225
7226
7227 MInt arrayPosWallDists = (set - startSet) * (nDist - 1);
7228 // Step d: Check which distributions are cutted and calculate the Wall distance for those
7229 for(MInt dir = 0; dir < nDist - 1; dir++) {
7230 if((this->a_levelSetFunctionMB(pCellId, set) * this->m_nodalGValues[candidate][arrayPosNGV + dir]) > 0) {
7231 // TODO labels:LB Remove offset and use set as third index ...
7232 m_bndCnd->m_boundaryCellsMb.distance(boundaryCellId, arrayPosWallDists + dir) = F2;
7233 } else {
7234 MFloat levelSetRatio =
7235 abs(this->m_nodalGValues[candidate][arrayPosNGV + dir] / this->a_levelSetFunctionMB(pCellId, set));
7236 MFloat cellLength = this->c_cellLengthAtLevel(this->a_level(pCellId)) * F1B2 * factor[dir];
7237 m_bndCnd->m_boundaryCellsMb.distance(boundaryCellId, arrayPosWallDists + dir) =
7238 cellLength / (levelSetRatio + F1);
7239 }
7240
7241 // Determine surface center
7242 // TODO labels:LB Fix very bad estimate by boundary cell center using approx normal (minWallDist)
7243 for(MInt n = 0; n < nDim; n++) {
7244 m_bndCnd->m_boundaryCellsMb.surfaceCenter(boundaryCellId, dir, n) =
7245 a_coordinate(pCellId, n)
7246 + m_bndCnd->m_boundaryCellsMb.distance(boundaryCellId, dir) * Ld::ppdfDir(dir, n) * 1 / factor[dir];
7247 }
7248 }
7249 for(MInt n = 0; n < nDim; n++) {
7250 m_bndCnd->m_boundaryCellsMb.cellCenter(boundaryCellId, n) = a_coordinate(pCellId, n);
7251 }
7252
7253 this->m_currentNoG0Cells++;
7254 }
7255 }
7256 } else {
7257 // D2Q9 Stencil for Cut Cells including the edges:
7258 //
7259 // 14 15
7260 // 7 -- 3 -- 4
7261 // |\ | /|
7262 // 9 | \ | / | 11
7263 // | \ | / |
7264 // 0 -- * -- 1
7265 // | / | \ |
7266 // 8 | / | \ | 10
7267 // |/ | \|
7268 // 6 -- 2 -- 5
7269 // 12 13
7270 //
7271 // 1. Get the nodal Ls values form the CutCandidates Class
7272 // m_nodelGValues holds the LS values for each candidate in the order of the distributions for each set
7273
7274 // 2. Find the Cut Cells by multipling the nodal LS values of the 4 corners
7275 // If the two LS values have opposite signs the edge has a cut if the product is exaktly 0 the cell has to
7276 // be considered, since it is still a boundary cell.
7277 // Furthermore, the cutPoints are calculated for all edges with a cut. The eges are seperated in two part
7278 // which is needed for the calculation of the cut cell volume fraction
7279
7280 // 3. Calculate the missing Ls values at the cell surfaces and cell edges for the cut cells
7281 // by calculating the mean values of the surrounding corners.
7282
7283 // 4. Calculate the Wall distances using the formular x2 = cellLength / (1 + LS2/LS1)
7284
7285 const MInt startSet = this->m_levelSetId;
7286 constexpr MInt maxNoDistributions = 9;
7287 constexpr MInt firstCornerDist = 4;
7288 constexpr MInt noEdges = 4;
7289 // 1. Get the nodal Ls values form the CutCandidates Class
7290 // 2. Find the Cut Cells and calculate the missing Ls values
7291 // at the cell surfaces and cell edges for those
7292 // 3. Calculate the Wall distances
7294 m_bndCnd->m_boundaryCellsMb.reset(this->m_noG0CandidatesTotal);
7295 constexpr MInt lb_CornerMappingForEdges[4][2] = {{6, 7}, {4, 5}, {5, 6}, {7, 4}};
7296 constexpr MFloat factor[8] = {F1, F1, F1, F1, SQRT2, SQRT2, SQRT2, SQRT2};
7297 // 1. Get the nodal Ls values form the CutCandidates Class
7298 // 2. Find the Cut Cells and calculate the missing Ls values
7299 // at the cell surfaces and cell edges for those
7300 // 3. Calculate the Wall distances
7301
7302 // Reset data structure
7303 this->m_currentNoG0Cells = 0;
7305 m_bndCnd->m_boundaryCellsMb.reset(this->m_noG0CandidatesTotal);
7307
7308 for(MInt candidate = 0; candidate < this->m_noG0CandidatesTotal; candidate++) {
7309 for(MInt set = startSet; set < this->m_maxNoSets; set++) {
7310 MInt arrayPosNGV = set * (maxNoDistributions - 1);
7311 this->m_nodalGValues[candidate][arrayPosNGV + firstCornerDist + 2] =
7312 this->m_G0Candidates[candidate].nodalValues[set][0];
7313 this->m_nodalGValues[candidate][arrayPosNGV + firstCornerDist + 1] =
7314 this->m_G0Candidates[candidate].nodalValues[set][1];
7315 this->m_nodalGValues[candidate][arrayPosNGV + firstCornerDist + 3] =
7316 this->m_G0Candidates[candidate].nodalValues[set][2];
7317 this->m_nodalGValues[candidate][arrayPosNGV + firstCornerDist + 0] =
7318 this->m_G0Candidates[candidate].nodalValues[set][3];
7319
7320 // Step a: Find Edges with a cut,
7321 // i.e. the nodes of the edge have opposite signs in m_nodalGValues
7322 MInt edgeCounter = 0;
7323 for(MInt edge = 0; edge < noEdges; edge++) {
7324 MFloat edgeGValue = this->m_nodalGValues[candidate][arrayPosNGV + Ld::nodalConnectivityVector(edge, 0)]
7325 * this->m_nodalGValues[candidate][arrayPosNGV + Ld::nodalConnectivityVector(edge, 1)];
7326 if(edgeGValue <= 0) edgeCounter++;
7327 }
7328
7329 // Step b: If there are less than two cuts for a G0Candidate it is not a G0 Cell.
7330 // Skip that cell!!
7331 MInt pCellId = this->m_G0Candidates[candidate].cellId;
7332 MInt actualSet = set - startSet;
7333 if(edgeCounter < 2) {
7334 this->a_isG0CandidateOfSet(pCellId, actualSet) = false;
7335 continue;
7336 } else {
7337 this->a_isG0CandidateOfSet(pCellId, actualSet) = true;
7338 this->m_G0CellMapping[pCellId] = this->m_currentNoG0Cells;
7339 // Use new mapping in bndCnd
7340 m_bndCnd->m_boundaryCellMappingMb[pCellId] = this->m_currentNoG0Cells;
7341 }
7342
7343 // Add relevant information to G0 boundary cell collector
7344 // Cell is a G0 boundary cell
7345 const MInt boundaryCellId = m_bndCnd->m_boundaryCellsMb.size();
7347 m_bndCnd->m_boundaryCellsMb.cellId(boundaryCellId) = pCellId;
7348
7349 // Step c: Calculate the missing Ls values at the cell edges
7350 this->m_G0CellList[this->m_currentNoG0Cells] = pCellId;
7351 for(MInt dist = 0; dist < firstCornerDist; dist++) {
7352 for(MInt i = 0; i < 2; i++) {
7353 this->m_nodalGValues[candidate][arrayPosNGV + dist] +=
7354 this->m_nodalGValues[candidate][arrayPosNGV + lb_CornerMappingForEdges[dist][i]];
7355 }
7356 this->m_nodalGValues[candidate][arrayPosNGV + dist] /= F2;
7357 }
7358
7359 MInt arrayPosWallDists = (set - startSet) * (nDist - 1);
7360 // Step d: Check which distributions are cutted and calculate the Wall distance for those
7361 for(MInt dir = 0; dir < nDist - 1; dir++) {
7362 if((this->a_levelSetFunctionMB(pCellId, set) * this->m_nodalGValues[candidate][arrayPosNGV + dir]) > 0) {
7363 // TODO labels:LB Remove offset and use set as third index ...
7364 m_bndCnd->m_boundaryCellsMb.distance(boundaryCellId, arrayPosWallDists + dir) = F2;
7365 } else {
7366 const MFloat levelSetRatio =
7367 abs(this->m_nodalGValues[candidate][arrayPosNGV + dir] / this->a_levelSetFunctionMB(pCellId, set));
7368 const MFloat cellLength = this->c_cellLengthAtLevel(this->a_level(pCellId)) * F1B2 * factor[dir];
7369 // TODO labels:LB Remove offset and use set as third index ...
7370 m_bndCnd->m_boundaryCellsMb.distance(boundaryCellId, arrayPosWallDists + dir) =
7371 cellLength / (levelSetRatio + F1);
7372 }
7373
7374 // Determine surface center
7375 // TODO labels:LB Fix very bad estimate by boundary cell center using approx normal (minWallDist)
7376 // OR: Store cross-over point of every cut-direction to make the
7377 // angular momentum exchange even better!
7378 for(MInt n = 0; n < nDim; n++) {
7379 m_bndCnd->m_boundaryCellsMb.surfaceCenter(boundaryCellId, dir, n) =
7380 a_coordinate(pCellId, n)
7381 + m_bndCnd->m_boundaryCellsMb.distance(boundaryCellId, n) * Ld::ppdfDir(dir, n) * 1 / factor[dir];
7382 }
7383 }
7384 for(MInt n = 0; n < nDim; n++) {
7385 m_bndCnd->m_boundaryCellsMb.cellCenter(boundaryCellId, n) = a_coordinate(pCellId, n);
7386 }
7387
7388 this->m_currentNoG0Cells++;
7389 }
7390 }
7391 }
7392}
MbCellCollector m_boundaryCellsMb
Definition: lbbndcnd.h:57
std::map< MInt, MInt > m_boundaryCellMappingMb
Definition: lbbndcnd.h:71
constexpr MInt size() const
Return size (i.e., currently used number of nodes)
Definition: container.h:89
void append(const MInt count)
Append nodes to end of tree.
Definition: container.h:223
MFloat & surfaceCenter(const MInt id, const MInt did, const MInt dim)
Accessor for surfaceCenter.
void reset()
Reset tree, re-create data structures with given capacity, and set size to zero.
MFloat & distance(const MInt id, const MInt did)
Accessor for distances.
MFloat & cellCenter(const MInt id, const MInt dim)
Accessor for cellCenter.
constexpr MInt noDistances() const
Number of distances.
MInt & cellId(const MInt id)
Accessor for cellId.
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54
static constexpr MInt nodalConnectivityVector(MInt i, MInt j)

◆ calculateDissipation()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::calculateDissipation
Note
Only on highest refinement-level !!!

Definition at line 3564 of file lbsolverdxqy.cpp.

3564 {
3565 TRACE();
3566
3567 if(globalTimeStep % 5 != 0) {
3568 return;
3569 }
3570
3571 constexpr MInt nDimSqr = nDim * nDim;
3572 constexpr MInt direction = 1;
3573
3574 // reset dissipation and energy values
3575 ScratchSpace<MFloat> diss(m_arraySize[direction], AT_, "diss");
3576 ScratchSpace<MFloat> SGSDiss(m_arraySize[direction], AT_, "SGSDiss");
3577 diss.fill(F0);
3578 SGSDiss.fill(F0);
3579 MFloat energy = 0.0;
3580
3581 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
3582
3583 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
3584 const MInt pCellId = m_activeCellList[i];
3585
3586 calculateMomentumFlux(pCellId);
3587
3588 // skip lower levels
3589 if(this->a_level(pCellId) < maxLevel()) continue;
3590
3591 // // Calculate gradients
3592 // for(MInt var = 0; var < nDim; var++) {
3593 // for(MInt dir = 0; dir < nDim; dir++) {
3594 // L = c;
3595 // R = c;
3596 // if(a_hasNeighbor(c, 2 * dir) > 0) L = c_neighborId(c, 2 * dir);
3597 // if(a_hasNeighbor(c, 2 * dir + 1) > 0) R = c_neighborId(c, 2 * dir + 1);
3598 // if(L == c) {
3599 // gradV[var + 3 * dir] = (a_variable(R, var) - a_variable(c, var));
3600 // continue;
3601 // }
3602 // if(R == c) {
3603 // gradV[var + 3 * dir] = (a_variable(c, var) - a_variable(L, var));
3604 // continue;
3605 // }
3606 // gradV[var + 3 * dir] = (a_variable(R, var) - a_variable(L, var)) / 2.0;
3607 // }
3608 // }
3609
3610 // Calculate strain rate tensor
3611 // S_{ij} = \frac{1}{2} \partial_j u_i \partial_i u_j
3612 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FPOW2(maxLevel() - this->a_level(pCellId)));
3613 MFloat Sij[nDimSqr];
3614 for(MInt k = 0; k < nDimSqr; k++) {
3615 Sij[k] = -F1B2 * F1BCSsq * m_omega * m_momentumFlux[i][k];
3616 }
3617
3618 // Calculate characteristic filtered rate of strain
3619 const MFloat Ssqr = 2.0 * std::inner_product(&Sij[0], &Sij[nDimSqr], &Sij[0], .0);
3620 const MFloat S = sqrt(Ssqr);
3621
3622 // Calculate molecular- and subgrid dissipation
3623 const MInt actualCellLength = this->c_cellLengthAtLevel(this->a_level(pCellId));
3624 const MInt index = floor(
3625 (F1B2 * m_arraySize[direction]
3626 + (a_coordinate(pCellId, direction) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
3627 + 0.1);
3628 diss[index] += m_nu * Ssqr;
3629 SGSDiss[index] += m_Cs * m_Cs * m_deltaX * m_deltaX * S * S * S * FPOW4(maxLevel() - this->a_level(pCellId));
3630
3631 // energy
3632 MFloat tmp = 0.0;
3633 for(MInt k = 0; k < nDim; k++) {
3634 tmp += a_variable(pCellId, k) * a_variable(pCellId, k);
3635 }
3636 energy += F1B2 * tmp;
3637 }
3638
3639 // Sum-up on root domain
3640 constexpr MInt rootId = 0;
3641 MPI_Reduce(MPI_IN_PLACE, &diss[0], m_arraySize[direction], MPI_DOUBLE, MPI_SUM, rootId, mpiComm(), AT_,
3642 "MPI_IN_PLACE", "diss");
3643 MPI_Reduce(MPI_IN_PLACE, &SGSDiss[0], m_arraySize[direction], MPI_DOUBLE, MPI_SUM, rootId, mpiComm(), AT_,
3644 "MPI_IN_PLACE", "SGSDiss");
3645 MPI_Reduce(MPI_IN_PLACE, &energy, m_arraySize[direction], MPI_DOUBLE, MPI_SUM, rootId, mpiComm(), AT_, "MPI_IN_PLACE",
3646 "energy");
3647
3648 // Write out data from root process
3649 if(domainId() == rootId) {
3650 ofstream ofl;
3651 MString fileName = "totalDiss_";
3652 MChar buf[10];
3653 sprintf(buf, "%d", globalTimeStep);
3654 fileName += buf;
3655 fileName += ".dat";
3656 m_log << "writing diss file: " << fileName << endl;
3657 ofl.open(fileName.c_str(), ios_base::out);
3658 for(MInt i = 0; i < m_arraySize[direction]; i++)
3659 ofl << globalTimeStep << " " << i << " " << diss[i] << " " << SGSDiss[i] << " " << energy << endl;
3660 ofl.close();
3661 }
3662}
int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Reduce

◆ calculateMacroscopicVariables()

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool compressible>
void LbSolverDxQy< nDim, nDist, SysEqn >::calculateMacroscopicVariables ( const MInt  cellId,
MFloat rho,
MFloat *const  u 
)
inline
Author
Julian Vorspohl j.vor.nosp@m.spoh.nosp@m.l@aia.nosp@m..rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de
Parameters
[in]cellIdCell id for which the macroscopic variables are calculated
[out]rhoMacroscopic density
[out]uMacroscopic velocity

Definition at line 898 of file lbsolverdxqy.h.

899 {
900#ifdef WAR_NVHPC_PSTL
901 std::array<MFloat, nDist> oldDist;
902 for(MInt dist = 0; dist < nDist; dist++) {
903 oldDist[dist] = a_oldDistribution(cellId, dist);
904 }
905 const MInt fldlen = Ld::dxQyFld();
906 lbfunc::calcMacroVars<nDim, nDist, compressible>(oldDist.data(), rho, u, m_pFld.data(), m_nFld.data(), fldlen);
907#else
908 const MFloat* const dist = &a_oldDistribution(cellId, 0);
909 lbfunc::calcMacroVars<nDim, nDist, compressible>(dist, rho, u);
910#endif
911}

◆ calculateMomentumFlux() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool compressible>
void LbSolverDxQy< nDim, nDist, SysEqn >::calculateMomentumFlux ( const MInt  pCellId)
inline
Author
Julian Vorspohl j.vor.nosp@m.spoh.nosp@m.l@aia.nosp@m..rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de
Parameters
[in]pCellIdCell id for which the momentum flux is calculated

Definition at line 950 of file lbsolverdxqy.h.

950 {
951 TRACE();
952
953 calculateMomentumFlux<compressible>(pCellId, m_momentumFlux[pCellId]);
954}

◆ calculateMomentumFlux() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool compressible>
void LbSolverDxQy< nDim, nDist, SysEqn >::calculateMomentumFlux ( const MInt  pCellId,
MFloat *const  momentumFlux 
)
inline
Author
Miro Gondrum
Parameters
[in]pCellIdCell id for which the momentum flux is calculated
[out]momentumFluxmomentumFlux tensor

Definition at line 920 of file lbsolverdxqy.h.

920 {
921 TRACE();
922
923 const MFloat rho = a_variable(pCellId, PV->RHO);
924#ifndef WAR_NVHPC_PSTL
925 const MFloat* const u = &a_variable(pCellId, PV->U);
926 const MFloat* const dist = &a_oldDistribution(pCellId, 0);
927 sysEqn().calcMomentumFlux(rho, u, dist, momentumFlux);
928#else
929 std::array<MFloat, nDim> u;
930 std::array<MFloat, nDist> dist;
931 for(MInt d = 0; d < nDim; d++) {
932 u[d] = a_variable(pCellId, d);
933 }
934 for(MInt d = 0; d < nDist; d++) {
935 dist[d] = a_oldDistribution(pCellId, d);
936 }
937 sysEqn().calcMomentumFlux(rho, u.data(), dist.data(), momentumFlux);
938#endif
939}
constexpr SysEqn sysEqn() const
Definition: lbsolverdxqy.h:194

◆ calculateResidual()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::calculateResidual
virtual
Author
Andreas Lintermann
Date
13.08.2012

Calculates the local max. and averaged max. residual for this process. The maximum over all processes is found by using a MPI_Allreduce with the MAX_LOC option. Only the processor with the max. of all values writes to disk. The averaged max. resiudal is found by averaging over the number of cells per process and then summing up and collecting the information on proc. 0 by using MPI_Reduce with the SUM option. Then this residual is additionally averaged by the number of processes.

Definition at line 6340 of file lbsolverdxqy.cpp.

6340 {
6341 TRACE();
6342
6343 if(domainId() == 0) mRes.open(m_resFileName, std::ofstream::app);
6344
6345 constexpr MInt noVars = 1 + nDim;
6346 for(MInt v = 0; v < noVars; v++) {
6347 m_residual[v] = F0;
6348 m_tmpResidual[v] = F0;
6349 m_tmpResidualLvl[v] = 0;
6350 m_maxResId[v] = -1;
6351 }
6352
6353 MInt count = 0;
6354 MInt sumCount = 0;
6355
6356 for(MInt id = 0; id < m_currentMaxNoCells; id++) {
6357 MInt l_id = m_activeCellList[id];
6358
6359 // skip halo cells
6360 if(l_id >= this->grid().noInternalCells()) continue;
6361
6362 const MInt pCellId = l_id;
6363
6364 // skip interfacechildren
6365 if(a_isInterfaceChild(pCellId)) continue;
6366
6367 MFloat diff[noVars] = {F0};
6368 const MFloat* const pcoordinates = &a_coordinate(pCellId, 0);
6369 MInt level = this->a_level(pCellId);
6370
6371 for(MInt v = 0; v < noVars; v++) {
6372 diff[v] = fabs(a_variable(pCellId, v) - a_oldVariable(pCellId, v));
6373 m_residual[v] += diff[v];
6374 if(m_tmpResidual[v] * m_tmpResidual[v] <= diff[v] * diff[v]) {
6375 m_tmpResidual[v] = diff[v];
6376 m_maxResId[v] = l_id;
6377 for(MInt d = 0; d < nDim; d++) {
6378 m_rescoordinates[v][d] = pcoordinates[d];
6379 }
6380 m_tmpResidualLvl[v] = level;
6381 }
6382 }
6383 count++;
6384 }
6385 cerr.precision(7);
6386
6387 stringstream res_t;
6388 res_t << globalTimeStep;
6389 MString res_t_f = res_t.str();
6390
6391 stringstream res_Re;
6392 res_Re << (m_referenceLength * m_Ma * LBCS / m_nu);
6393 MString res_Re_f = res_Re.str();
6394
6395 struct {
6396 MFloat val;
6397 MInt rank;
6398 } sendBufRes[noVars], rcvBufRes[noVars];
6399
6400 MFloat sendBufResAvg[noVars] = {0.0};
6401 for(MInt v = 0; v < noVars; v++) {
6402 sendBufResAvg[v] = m_residual[v];
6403 sendBufRes[v].val = m_tmpResidual[v];
6404 }
6405 MFloat rcvBufResAvg[noVars];
6406
6407 for(MInt i = 0; i < noVars; i++)
6408 sendBufRes[i].rank = domainId();
6409
6410 MString strs[noVars] = {};
6411 strs[0] = "U";
6412 strs[1] = "V";
6413 if constexpr(nDim == 3) strs[2] = "W";
6414 strs[nDim] = "RHO";
6415
6416 MPI_Allreduce(sendBufRes, rcvBufRes, noVars, MPI_DOUBLE_INT, MPI_MAXLOC, mpiComm(), AT_, "sendBufRes", "rcvBufRes");
6417 MPI_Reduce(sendBufResAvg, rcvBufResAvg, noVars, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_, "sendBufResAvg",
6418 "rcvBufResAvg");
6419
6420 // To calculate the avagare residual, get total number of cells without the halo cells
6421 if(noDomains() == 1) {
6422 // When serial, then just use the counted number of cells of the root process
6423 sumCount = count;
6424 } else {
6425 // When parallel, then sum up all counted number of cells of each process
6426 MPI_Reduce(&count, &sumCount, 1, MPI_INT, MPI_SUM, 0, mpiComm(), AT_, "count", "sumCount");
6427 }
6428
6429 // all max. averaged residuals
6430 if(domainId() == 0) {
6431 mRes << std::endl;
6432 mRes << "#------------------------------" << std::endl;
6433 mRes << "In timestep: " << res_t_f << ", with Re: " << res_Re_f << ";" << std::endl;
6434 mRes << "\n";
6435 for(MInt i = 0; i < noVars; i++)
6436 mRes << " Max. averaged residual found for " << strs[i] << " is " << (rcvBufResAvg[i] / sumCount) << "\n";
6437 }
6438
6439 if(noDomains() > 1) {
6440 for(MInt i = 0; i < noVars; i++) {
6441 MInt noElements2Snd = 0;
6442 std::array<MFloat, nDim> sndBufFloat;
6443 std::array<MInt, 2> sndBufInt;
6444 std::array<MFloat, nDim> recvElementsF;
6445 std::array<MInt, 2> recvElementsI;
6446 MIntScratchSpace noElements2SndPerCPU(noDomains(), AT_, "noElements2SndPerCPU");
6447 MIntScratchSpace posElements2SndPerCPU(noDomains(), AT_, "posElements2SndPerCPU");
6448
6449 for(MInt dom = 0; dom < noDomains(); dom++) {
6450 noElements2SndPerCPU[dom] = 0;
6451 posElements2SndPerCPU[dom] = 0;
6452 if(rcvBufRes[i].rank == dom) {
6453 noElements2SndPerCPU[dom] = nDim;
6454 }
6455 if(dom > 0) {
6456 posElements2SndPerCPU[dom] = posElements2SndPerCPU[dom - 1] + noElements2SndPerCPU[dom - 1];
6457 }
6458 }
6459
6460 if(rcvBufRes[i].rank == domainId() && m_maxResId[i] != -1) {
6461 noElements2Snd = nDim;
6462 for(MInt d = 0; d < nDim; d++) {
6463 sndBufFloat[d] = m_rescoordinates[i][d];
6464 }
6465 }
6466
6467 MPI_Gatherv(sndBufFloat.data(), noElements2Snd, MPI_DOUBLE, recvElementsF.data(), noElements2SndPerCPU.data(),
6468 posElements2SndPerCPU.data(), MPI_DOUBLE, 0, mpiComm(), AT_, "sndBufFloat.data()",
6469 "recvElementsF.data()");
6470
6471 for(MInt dom = 0; dom < noDomains(); dom++) {
6472 noElements2SndPerCPU[dom] = 0;
6473 posElements2SndPerCPU[dom] = 0;
6474 if(rcvBufRes[i].rank == dom) {
6475 noElements2SndPerCPU[dom] = 2;
6476 }
6477 if(dom > 0) {
6478 posElements2SndPerCPU[dom] = posElements2SndPerCPU[dom - 1] + noElements2SndPerCPU[dom - 1];
6479 }
6480 }
6481
6482 if(rcvBufRes[i].rank == domainId() && m_maxResId[i] != -1) {
6483 noElements2Snd = 2;
6484 sndBufInt[0] = m_tmpResidualLvl[i];
6485 sndBufInt[1] = m_maxResId[i];
6486 }
6487
6488 MPI_Gatherv(&sndBufInt, noElements2Snd, MPI_INT, recvElementsI.data(), noElements2SndPerCPU.data(),
6489 posElements2SndPerCPU.data(), MPI_INT, 0, mpiComm(), AT_, "sndBufInt", "recvElementsI.data()");
6490
6491 // all max. local residuals
6492 if(domainId() == 0) {
6493 mRes << "\n Max. local residual found for " << strs[i] << " on proc.: " << rcvBufRes[i].rank << " with "
6494 << rcvBufRes[i].val << "\n"
6495 << " Level: " << recvElementsI[0] << "\n"
6496 << " ID: " << recvElementsI[1] << "\n"
6497 << " Coordinates: (";
6498 for(MInt d = 0; d < nDim - 1; d++) {
6499 mRes << recvElementsF[d] << ", ";
6500 }
6501 mRes << recvElementsF[nDim - 1] << ")" << endl;
6502 }
6503 }
6504 } else {
6505 // Print residual for the only process that is running
6506 // No communication required
6507 for(MInt i = 0; i < noVars; i++) {
6508 mRes << "\n Max. local residual found for " << strs[i] << " on proc.: " << domainId() << " with "
6509 << rcvBufRes[i].val << "\n"
6510 << " Level: " << m_tmpResidualLvl[i] << "\n"
6511 << " ID: " << m_maxResId[i] << "\n"
6512 << " Coordinates: (";
6513 for(MInt d = 0; d < nDim - 1; d++) {
6514 mRes << m_rescoordinates[i][d] << ", ";
6515 }
6516 mRes << m_rescoordinates[i][nDim - 1] << ")" << endl;
6517 }
6518 }
6519
6520 // Close Residual file
6521 if(domainId() == 0) {
6522 mRes << std::endl;
6523 mRes.close();
6524 }
6525}
MInt id
Definition: maiatypes.h:71
int MPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gatherv

◆ calculateSGSTensors()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::calculateSGSTensors

only for D3Q19 and uniform grids

Calculation of MijMij and MijLij according to Pope p.620. The test filter is a box filter with a width 2*m_deltaX.

Definition at line 4761 of file lbsolverdxqy.cpp.

4761 {
4762 TRACE();
4763
4764 constexpr MFloat coefficients[4] = {F1B8, F1B16, F1B32, F1B64};
4765 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
4766
4767 for(MInt id = 0; id < this->grid().noInternalCells(); id++) {
4768 //----------------------------------------
4769 // 1. calculate amount from actual cell
4770 // Calculate strain rate tensor
4771 // S_{ij} = \frac{1}{2} (\partial_j u_i + \partial_i u_j)
4772 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FPOW2(maxLevel() - this->a_level(id)));
4773 MFloat Sij[9];
4774 for(MInt k = 0; k < 9; k++) {
4775 Sij[k] = -F1B2 * F1BCSsq * m_omega * m_momentumFlux[id][k];
4776 }
4777 // Calculate caracteristic filtered rate of strain
4778 MFloat S = sqrt(2.0 * std::inner_product(&Sij[0], &Sij[9], &Sij[0], .0));
4779
4780 // add values to sum
4781 MFloat Mij[9]{};
4782 MFloat SijTilde[9]{};
4783 for(MInt j = 0; j < 9; j++) {
4784 Mij[j] += coefficients[0] * 2.0 * m_deltaX * m_deltaX * S * Sij[j];
4785 SijTilde[j] += coefficients[0] * Sij[j];
4786 }
4787 MFloat uuTilde[9]{};
4788 for(MInt k = 0; k < 3; k++) {
4789 for(MInt l = 0; l < 3; l++) {
4790 uuTilde[l + 3 * k] += coefficients[0] * a_variable(id, k) * a_variable(id, l);
4791 }
4792 }
4793 MFloat uTilde[3]{};
4794 for(MInt k = 0; k < 3; k++) {
4795 uTilde[k] += coefficients[0] * a_variable(id, k);
4796 }
4797 MFloat STilde = coefficients[0] * S;
4798
4799 //----------------------------------------
4800 // 2. add amount from neighbor cells
4801 // neighbors in direction with one component
4802 for(MInt j = 0; j < Ld::distFld(0); j++) {
4803 if(!a_hasNeighbor(id, j)) continue;
4804
4805 const MInt currentNghbr = c_neighborId(id, j);
4806
4807 // Calculate strain rate tensor
4808 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FPOW2(maxLevel() - this->a_level(currentNghbr)));
4809 for(MInt k = 0; k < 9; k++) {
4810 Sij[k] = -F1B2 * F1BCSsq * m_omega * m_momentumFlux[currentNghbr][k];
4811 }
4812 // Calculate caracteristic filtered rate of strain
4813 S = sqrt(2.0 * std::inner_product(&Sij[0], &Sij[9], &Sij[0], .0));
4814
4815 // add values to sum
4816 for(MInt k = 0; k < 9; k++) {
4817 Mij[k] += coefficients[1] * 2.0 * m_deltaX * m_deltaX * S * Sij[k];
4818 SijTilde[k] += coefficients[1] * Sij[k];
4819 }
4820 for(MInt k = 0; k < 3; k++) {
4821 for(MInt l = 0; l < 3; l++) {
4822 uuTilde[l + 3 * k] += coefficients[1] * a_variable(id, k) * a_variable(id, l);
4823 }
4824 }
4825 for(MInt k = 0; k < 3; k++) {
4826 uTilde[k] += coefficients[1] * a_variable(id, k);
4827 }
4828 STilde += coefficients[1] * S;
4829 }
4830 // neighbors in direction with two components
4831 MInt tmpDir = Ld::distFld(0);
4832 for(MInt j = 0; j < Ld::distFld(1); j++) {
4833 if(!a_hasNeighbor(id, tmpDir + j)) continue;
4834
4835 const MInt currentNghbr = c_neighborId(id, tmpDir + j);
4836
4837 // Calculate strain rate tensor
4838 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FPOW2(maxLevel() - this->a_level(currentNghbr)));
4839 for(MInt k = 0; k < 9; k++) {
4840 Sij[k] = -F1B2 * F1BCSsq * m_omega * m_momentumFlux[currentNghbr][k];
4841 }
4842 // Calculate caracteristic filtered rate of strain
4843 S = sqrt(2.0 * std::inner_product(&Sij[0], &Sij[9], &Sij[0], .0));
4844
4845 // add values to sum
4846 for(MInt i = 0; i < 9; i++) {
4847 Mij[i] += coefficients[2] * 2.0 * m_deltaX * m_deltaX * S * Sij[i];
4848 SijTilde[i] += coefficients[2] * Sij[i];
4849 }
4850 for(MInt k = 0; k < 3; k++) {
4851 for(MInt l = 0; l < 3; l++) {
4852 uuTilde[l + 3 * k] += coefficients[2] * a_variable(id, k) * a_variable(id, l);
4853 }
4854 }
4855 for(MInt k = 0; k < 3; k++) {
4856 uTilde[k] += coefficients[2] * a_variable(id, k);
4857 }
4858 STilde += coefficients[2] * S;
4859 }
4860 // neighbors in direction with three components
4861 tmpDir = Ld::distFld(0) + Ld::distFld(1);
4862 for(MInt j = 0; j < Ld::distFld(2); j++) {
4863 if(!a_hasNeighbor(id, tmpDir + j)) continue;
4864
4865 const MInt currentNghbr = c_neighborId(id, tmpDir + j);
4866
4867 // Calculate strain rate tensor
4868 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FPOW2(maxLevel() - this->a_level(currentNghbr)));
4869 for(MInt k = 0; k < 9; k++) {
4870 Sij[k] = -F1B2 * F1BCSsq * m_omega * m_momentumFlux[currentNghbr][k];
4871 }
4872 // Calculate caracteristic filtered rate of strain
4873 S = sqrt(2.0 * std::inner_product(&Sij[0], &Sij[9], &Sij[0], .0));
4874
4875 // add values to sum
4876 for(MInt k = 0; k < 9; k++) {
4877 Mij[k] += coefficients[3] * 2.0 * m_deltaX * m_deltaX * S * Sij[k];
4878 SijTilde[k] += coefficients[3] * Sij[k];
4879 }
4880 for(MInt k = 0; k < 3; k++) {
4881 for(MInt l = 0; l < 3; l++) {
4882 uuTilde[l + 3 * k] += coefficients[3] * a_variable(id, k) * a_variable(id, l);
4883 }
4884 }
4885 for(MInt k = 0; k < 3; k++) {
4886 uTilde[k] += coefficients[3] * a_variable(id, k);
4887 }
4888 STilde += coefficients[3] * S;
4889 }
4890 //----------------------------------------
4891
4892
4893 // finalize Mij and Lij
4894 for(MInt j = 0; j < 9; j++) {
4895 Mij[j] -= 2.0 * 4.0 * m_deltaX * m_deltaX * STilde * SijTilde[j];
4896 }
4897
4898 MFloat Lij[9]{};
4899 for(MInt k = 0; k < 3; k++) {
4900 for(MInt l = 0; l < 3; l++) {
4901 Lij[l + 3 * k] += uuTilde[l + 3 * k] - uTilde[k] * uTilde[l];
4902 }
4903 }
4904
4905 // Multiply Mij by itself
4906 m_MijMij[id] = 0.0;
4907 for(MInt k = 0; k < 9; k++) {
4908 m_MijMij[id] += Mij[k] * Mij[k];
4909 }
4910
4911 // Multiply Mij by Lij
4912 m_MijLij[id] = 0.0;
4913 for(MInt k = 0; k < 9; k++) {
4914 m_MijLij[id] += Mij[k] * Lij[k];
4915 }
4916 }
4917}

◆ clb_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::clb_collision_step
override
Author
Miro Gondrum (Refactored)
Date
03.11.2021
Property value solverMethod
MAIA_LATTICE_CLB

This function wraps clb_collision_step_base to access CLB-Algorithm without a Smagorisnky turbulence model.

Definition at line 1338 of file lbsolverdxqy.cpp.

1338 {
1339 clb_collision_step_base<false>();
1340}

◆ clb_collision_step_base() [1/4]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::clb_collision_step_base< false > ( )

Definition at line 600 of file lbsolverdxqy.cpp.

600 {
601 TRACE();
602 constexpr MInt nDist = 9;
603
604 constexpr MLongFloat K[9][9] = {
605 {1.0, 0.0, 0.0, -4.0, 0.0, 0.0, 0.0, 0.0, 4.0}, {1.0, -1.0, 1.0, 2.0, 0.0, 1.0, -1.0, 1.0, 1.0},
606 {1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 0.0, -2.0, -2.0}, {1.0, -1.0, -1.0, 2.0, 0.0, -1.0, 1.0, 1.0, 1.0},
607 {1.0, 0.0, -1.0, -1.0, -1.0, 0.0, -2.0, 0.0, -2.0}, {1.0, 1.0, -1.0, 2.0, 0.0, 1.0, 1.0, -1.0, 1.0},
608 {1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, 2.0, -2.0}, {1.0, 1.0, 1.0, 2.0, 0.0, -1.0, -1.0, -1.0, 1.0},
609 {1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 2.0, 0.0, -2.0}};
610
611 for(MInt id = 0; id < a_noCells(); id++) {
612 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(id)) == 0) {
613 m_nu = m_Ma * LBCS / m_Re * m_referenceLength * FFPOW2(maxLevel() - this->a_level(id));
614
615 MLongFloat omega[9] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
616 m_omega = 2.0 / (1.0 + 6.0 * m_nu);
617 omega[4] = m_omega;
618 omega[5] = m_omega;
619
620 swap_variables(id);
621
622 // Calculation of macroscopic variables + forcing term
623 for(MInt j = 0; j < nDist; j++) {
624 a_variable(id, PV->RHO) += a_oldDistribution(id, j);
625 }
626 const MFloat rho = a_variable(id, PV->RHO);
627
628 a_variable(id, PV->U) = (a_oldDistribution(id, 1) + a_oldDistribution(id, 4) + a_oldDistribution(id, 5)
629 - a_oldDistribution(id, 7) - a_oldDistribution(id, 6) - a_oldDistribution(id, 0))
630 / rho;
631
632 a_variable(id, PV->V) = (a_oldDistribution(id, 7) + a_oldDistribution(id, 3) + a_oldDistribution(id, 4)
633 - a_oldDistribution(id, 6) - a_oldDistribution(id, 2) - a_oldDistribution(id, 5))
634 / rho;
635
636 const MFloat u = a_variable(id, PV->U);
637 const MFloat v = a_variable(id, PV->V);
638
639 const MFloat r = a_oldDistribution(id, 8);
640 const MFloat nw = a_oldDistribution(id, 7);
641 const MFloat w = a_oldDistribution(id, 0);
642 const MFloat sw = a_oldDistribution(id, 6);
643 const MFloat s = a_oldDistribution(id, 2);
644 const MFloat se = a_oldDistribution(id, 5);
645 const MFloat e = a_oldDistribution(id, 1);
646 const MFloat ne = a_oldDistribution(id, 4);
647 const MFloat n = a_oldDistribution(id, 3);
648
649 // Calculate equilibrium moments...
650 MLongFloat keq[9];
651 keq[0] = 0.0;
652 keq[1] = 0.0;
653 keq[2] = 0.0;
654 keq[3] = omega[3] * (rho * (u * u + v * v) - e - n - s - w - 2.0 * (se + sw + ne + nw - F1B3 * rho)) / 12.0;
655
656 keq[4] = omega[4] * (n + s - e - w + rho * (u * u - v * v)) / 4.0;
657
658 keq[5] = omega[5] * ((ne + sw - nw - se) - u * v * rho) / 4.0;
659
660 keq[6] = omega[6]
661 * (-1.0
662 * ((se + sw - ne - nw - 2 * u * u * v * rho + v * (rho - n - s - r)) / 4.0
663 + u / 2.0 * (ne - nw - se + sw)))
664 - v / 2.0 * (-3.0 * keq[3] - keq[4]) - 2.0 * u * keq[5];
665 keq[7] = omega[7]
666 * (-1.0
667 * ((sw + nw - se - ne - 2 * v * v * u * rho + u * (rho - w - e - r)) / 4.0
668 + v / 2.0 * (ne - nw - se + sw) / 2.0))
669 - u / 2.0 * (-3.0 * keq[3] + keq[4]) - 2.0 * v * keq[5];
670 keq[8] = omega[8]
671 * (F1B4
672 * (F1B9 * rho - ne - nw - se - sw + 2.0 * (u * (ne - nw + se - sw) + v * (ne + nw - se - sw))
673 + 4.0 * u * v * (nw - ne + se - sw) - u * u * (n + ne + nw + s + se + sw)
674 + v * v * (3.0 * u * u * rho - e - ne - nw - se - sw - w)))
675 - 2.0 * keq[3] - 2.0 * u * keq[7] - 2.0 * v * keq[6] + 4 * u * v * keq[5]
676 - (1.5 * keq[3] - F1B2 * keq[4]) * (u * u + v * v);
677
678 // Matrix vector multiplication (must be optimized)
679 MLongFloat k[9];
680 for(MInt l = 0; l < 9; l++) {
681 k[l] = std::inner_product(&K[l][0], &K[l][9], &keq[0], F0);
682 }
683
684 a_distribution(id, 8) = a_oldDistribution(id, 8) + k[0];
685 a_distribution(id, 7) = a_oldDistribution(id, 7) + k[1];
686 a_distribution(id, 0) = a_oldDistribution(id, 0) + k[2];
687 a_distribution(id, 6) = a_oldDistribution(id, 6) + k[3];
688 a_distribution(id, 2) = a_oldDistribution(id, 2) + k[4];
689 a_distribution(id, 5) = a_oldDistribution(id, 5) + k[5];
690 a_distribution(id, 1) = a_oldDistribution(id, 1) + k[6];
691 a_distribution(id, 4) = a_oldDistribution(id, 4) + k[7];
692 a_distribution(id, 3) = a_oldDistribution(id, 3) + k[8];
693 }
694 }
695}
long double MLongFloat
Definition: maiatypes.h:53

◆ clb_collision_step_base() [2/4]

void LbSolverDxQy< 3, 19, maia::lb::LbSysEqnIncompressible< 3, 19 > >::clb_collision_step_base< false > ( )

Definition at line 699 of file lbsolverdxqy.cpp.

699 {
700 TRACE();
701 constexpr MInt nDist = 19;
702
703 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
704 const MInt pCellId = m_activeCellList[i];
705
706 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
707 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
708
709 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
710 MFloat omega = m_omega;
711
712 swap_variables(pCellId);
713
714 // Calculate macroscopic variables
715 a_variable(pCellId, PV->RHO) = 0.0;
716 for(MInt j = 0; j < nDist; j++) {
717 a_variable(pCellId, PV->RHO) += a_oldDistribution(pCellId, j);
718 }
719
720 a_variable(pCellId, PV->U) = 0.0;
721 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
722 a_variable(pCellId, PV->U) += a_oldDistribution(pCellId, Ld::pFld(0, j));
723 a_variable(pCellId, PV->U) -= a_oldDistribution(pCellId, Ld::nFld(0, j));
724 }
725 a_variable(pCellId, PV->U) /= a_variable(pCellId, PV->RHO);
726
727 a_variable(pCellId, PV->V) = 0.0;
728 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
729 a_variable(pCellId, PV->V) += a_oldDistribution(pCellId, Ld::pFld(1, j));
730 a_variable(pCellId, PV->V) -= a_oldDistribution(pCellId, Ld::nFld(1, j));
731 }
732 a_variable(pCellId, PV->V) /= a_variable(pCellId, PV->RHO);
733
734 a_variable(pCellId, PV->W) = 0.0;
735 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
736 a_variable(pCellId, PV->W) += a_oldDistribution(pCellId, Ld::pFld(2, j));
737 a_variable(pCellId, PV->W) -= a_oldDistribution(pCellId, Ld::nFld(2, j));
738 }
739 a_variable(pCellId, PV->W) /= a_variable(pCellId, PV->RHO);
740
741 const MFloat R = a_oldDistribution(pCellId, 18);
742 const MFloat Nw = a_oldDistribution(pCellId, 7);
743 const MFloat W = a_oldDistribution(pCellId, 0);
744 const MFloat Sw = a_oldDistribution(pCellId, 6);
745 const MFloat S = a_oldDistribution(pCellId, 2);
746 const MFloat Se = a_oldDistribution(pCellId, 8);
747 const MFloat E = a_oldDistribution(pCellId, 1);
748 const MFloat Ne = a_oldDistribution(pCellId, 9);
749 const MFloat N = a_oldDistribution(pCellId, 3);
750 const MFloat Nf = a_oldDistribution(pCellId, 17);
751 const MFloat Nb = a_oldDistribution(pCellId, 16);
752 const MFloat Sf = a_oldDistribution(pCellId, 15);
753 const MFloat Sb = a_oldDistribution(pCellId, 14);
754 const MFloat Ef = a_oldDistribution(pCellId, 13);
755 const MFloat Eb = a_oldDistribution(pCellId, 12);
756 const MFloat Wf = a_oldDistribution(pCellId, 11);
757 const MFloat Wb = a_oldDistribution(pCellId, 10);
758 const MFloat F = a_oldDistribution(pCellId, 5);
759 const MFloat B = a_oldDistribution(pCellId, 4);
760
761 const MFloat rho = Nw + W + Sw + S + Se + E + Ne + N + R + Nf + Nb + Sf + Sb + Ef + Eb + Wf + Wb + F + B;
762 const MFloat pi_x = (Ne + E + Se + Ef + Eb - Nw - W - Sw - Wf - Wb);
763 const MFloat pi_y = (Ne + N + Nw + Nf + Nb - Se - S - Sw - Sf - Sb);
764 const MFloat pi_z = (Nf + Sf + Wf + Ef + F - Nb - Sb - Wb - Eb - B);
765 const MFloat vv_x = pi_x / rho;
766 const MFloat vv_y = pi_y / rho;
767 const MFloat vv_z = pi_z / rho;
768 const MFloat vx2 = vv_x * vv_x;
769 const MFloat vy2 = vv_y * vv_y;
770 const MFloat vz2 = vv_z * vv_z;
771 const MFloat uxy = (omega * (Ne - Nw - Se + Sw + vv_x * vv_y * rho - pi_x * vv_y - pi_y * vv_x) * 0.25);
772 const MFloat uxz = (omega * (-Eb + Ef + Wb - Wf + vv_x * vv_z * rho - pi_x * vv_z - pi_z * vv_x) * 0.25);
773 const MFloat uyz = (omega * (-Nb + Nf + Sb - Sf + vv_z * vv_y * rho - pi_z * vv_y - pi_y * vv_z) * 0.25);
774
775 const MFloat vxy = (omega * (1. / 6.)
776 * (-B - E - F + Nb + Ne + Nf + Nw + Sb + Se + Sf + Sw - W + 2 * (-Eb - Ef + N + S - Wb - Wf)
777 + 2 * (-2 * pi_y * vv_y + pi_x * vv_x + pi_z * vv_z) - rho * (vz2 - 2 * vy2 + vx2)));
778 const MFloat vxz = (omega * (1. / 6.)
779 * (-E + Eb + Ef - N + Nb + Nf - S + Sb + Sf - W + Wb + Wf + 2 * (B + F - Ne - Nw - Se - Sw)
780 + 2 * (-2 * pi_z * vv_z + pi_x * vv_x + pi_y * vv_y) - rho * (vx2 + vy2 - 2 * vz2)));
781 const MFloat pe = ((1. / 126.)
782 * (-B - E - F - N - S - W + 2 * (-Eb - Ef - Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw - Wb - Wf)
783 + (rho + vv_y * (2 * pi_y - vv_y * rho) + vv_z * (2 * pi_z - vv_z * rho)
784 + vv_x * (2 * pi_x - vv_x * rho))));
785
786 const MFloat UXY = -Ne + Nw + Se - Sw + 4 * uxy;
787 const MFloat UXZ = Eb - Ef - Wb + Wf + 4 * uxz;
788 const MFloat UYZ = Nb - Nf - Sb + Sf + 4 * uyz;
789
790 const MFloat x = ((0.125
791 * (Nw + Sw + Wf + Wb - Eb - Ef - Ne - Se
792 + vv_x
793 * (B + Eb + Ef + 84 * pe + F + N + Ne + Nw + S + Se + Sw + Wb + Wf
794 + 2 * (Nb + Nf + Sb + Sf - vxy - vxz)))
795 + 0.25 * (-vv_y * UXY - vv_z * UXZ) - 0.25 * vv_x * (vv_y * pi_y + vv_z * pi_z)
796 + 0.125 * (vy2 + vz2) * (vv_x * rho - pi_x)));
797 const MFloat y = ((0.125
798 * (Sb + Sf + Se + Sw - Nw - Ne - Nf - Nb
799 + vv_y
800 * (B + E + 84 * pe + F + Nb + Ne + Nf + Nw + Sb + Se + Sf + Sw + W
801 + 2 * (Eb + Ef + Wb + Wf + vxy)))
802 + 0.25 * (-vv_x * UXY - vv_z * UYZ) - 0.25 * vv_y * (vv_z * pi_z + vv_x * pi_x)
803 + 0.125 * (vx2 + vz2) * (vv_y * rho - pi_y)));
804 const MFloat z = ((0.125
805 * (Eb + Nb + Sb + Wb - Ef - Nf - Sf - Wf
806 + vv_z
807 * (E + Eb + Ef + N + Nb + Nf + S + Sb + Sf + W + Wb + Wf + 84 * pe
808 + 2 * (Ne + Nw + Se + Sw + vxz)))
809 + 0.25 * (-vv_x * UXZ - vv_y * UYZ) - 0.25 * vv_z * (vv_x * pi_x + vv_y * pi_y)
810 + 0.125 * (vx2 + vy2) * (vv_z * rho - pi_z)));
811
812 const MFloat xxx = ((0.125
813 * (Eb + Ef - Ne + Nw - Se + Sw - Wb - Wf
814 + vv_x * (-B - Eb - Ef - F + N + Ne + Nw + S + Se + Sw - Wb - Wf + 2 * (vxz - vxy)))
815 + 0.25 * (vv_z * UXZ - vv_y * UXY + vv_x * (vv_z * pi_z - vv_y * pi_y))
816 + 0.125 * ((pi_x - vv_x * rho) * (vz2 - vy2))));
817 const MFloat yyy =
818 ((0.125
819 * (Ne - Nb - Nf + Nw + Sb - Se + Sf - Sw
820 + vv_y * (-E + B + F + Nb - Ne + Nf - Nw + Sb - Se + Sf - Sw - W + 2 * (-vxy - 2 * vxz)))
821 + 0.25 * (vv_x * UXY - vv_z * UYZ + vv_y * (vv_x * pi_x - vv_z * pi_z))
822 + 0.125 * ((pi_y - vv_y * rho) * (vx2 - vz2))));
823 const MFloat zzz =
824 ((0.125
825 * (Eb - Ef - Nb + Nf - Sb + Sf + Wb - Wf
826 + vv_z * (E + Eb + Ef - N - Nb - Nf - S - Sb - Sf + W + Wb + Wf + 2 * (vxz + 2 * vxy)))
827 + 0.25 * (vv_y * UYZ - vv_x * UXZ + vv_z * (vv_y * pi_y - vv_x * pi_x))
828 + 0.125 * ((pi_z - vv_z * rho) * (vy2 - vx2))));
829
830 // xyz=(0.125*(Neb-Nef-Nwb+Nwf-Seb+Sef+Swb-Swf-vv_x*UYZ-vv_y*UXZ-vv_z*UXY+rho*vv_x*vv_y*vv_z-(vv_x*vv_y*pi_z+vv_x*pi_y*vv_z+pi_x*vv_y*vv_z)));
831
832 const MFloat X_ = (Eb + Ef + Ne - Nw + Se - Sw - Wb - Wf + 8 * x);
833 const MFloat Y_ = (Nb + Ne + Nf + Nw - Sb - Se - Sf - Sw + 8 * y);
834 const MFloat Z_ = (Ef - Eb - Nb + Nf - Sb + Sf - Wb + Wf + 8 * z);
835
836 // XnXXX=Eb+Ef-Wb-Wf+4*(x-xxx);
837 // XpXXX=Ne-Nw+Se-Sw+4*(x+xxx);
838 // YnYYY=Ne+Nw-Se-Sw+4*(y-yyy);
839 // YpYYY=Nb+Nf-Sb-Sf+4*(y+yyy);
840 // ZnZZZ=-Nb+Nf-Sb+Sf+4*(z-zzz);
841 // ZpZZZ=-Eb+Ef-Wb+Wf+4*(z+zzz);
842
843 // XYZ= 8*xyz;
844 // EPa=-42*pe-E-Eb-Ef-Ne-Nw-Se-Sw-W-Wb-Wf-2*(vxy+vxz);
845 // EPb=-42*pe-B-Eb-Ef-F-Nb-Nf-Sb-Sf-Wb-Wf+2*vxz;
846 // EPc=-42*pe-N-Nb-Ne-Nf-Nw-S-Sb-Se-Sf-Sw+2*vxy;
847
848 const MFloat p = ((1. / 12.)
849 * (rho / (3.) - 96 * pe - Eb - Ef - Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw - Wb - Wf
850 + 2 * (+vv_x * X_ + vv_y * Y_ + vv_z * Z_)
851 + vx2
852 * (-84 * pe - B - Eb - Ef - F - N - Ne - Nw - S - Se - Sw - Wb - Wf
853 + 2 * (vxy + vxz - Nb - Nf - Sb - Sf))
854 + vy2
855 * (-84 * pe - B - E - F - Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw - W
856 + 2 * (-vxy - Eb - Ef - Wb - Wf))
857 + vz2
858 * (-84 * pe - E - Eb - Ef - N - Nb - Nf - S - Sb - Sf - W - Wb - Wf
859 + 2 * (-vxz - Ne - Nw - Se - Sw))
860 + 4 * (vv_x * vv_y * UXY + vv_x * vv_z * UXZ + vv_y * vv_z * UYZ)
861 - rho * (vx2 * vy2 + vx2 * vz2 + vy2 * vz2)
862 + 2 * (pi_y * vv_y * (vx2 + vz2) + pi_x * vv_x * (vy2 + vz2) + pi_z * vv_z * (vx2 + vy2))));
863
864 const MFloat a =
865 ((1. / 12.)
866 * (-Eb - Ef - Ne - Nw - Se - Sw - Wb - Wf
867 + 2
868 * (Nb + Nf + Sb + Sf + vv_x * X_
869 + vv_y * (Ne + Nw - Se - Sw + 2 * (Sf + Sb - Nb - Nf - 2 * y - 6 * yyy))
870 + vv_z * (Ef - Eb - Wb + Wf + 2 * (Nb - Nf + Sb - Sf - 2 * z + 6 * zzz)))
871 + vx2
872 * (-B - Eb - Ef - F - N - Ne - Nw - S - Se - Sw - Wb - Wf - 84 * pe
873 - 2 * (Nb + Nf + Sb + Sf - vxy - vxz))
874 + vy2
875 * (Eb - E + Ef - Ne - Nw - Se - Sw - W + Wb + Wf + 42 * pe
876 + 2 * (B + F + Nb + Nf + Sb + Sf - vxy - 3 * vxz))
877 + vz2
878 * (Ne - E - Eb - Ef + Nw + Se + Sw - W - Wb - Wf + 42 * pe
879 + 2 * (N + Nb + Nf + S + Sb + Sf - vxz - 3 * vxy))
880 + 4 * (vv_x * (vv_y * UXY + vv_z * UXZ)) - 8 * vv_y * vv_z * UYZ
881 + (2 * vy2 * vz2 - vx2 * (vy2 + vz2)) * rho
882 + 2 * (pi_y * vv_y * (vx2 - 2 * vz2) + pi_z * vv_z * (vx2 - 2 * vy2) + pi_x * vv_x * (vy2 + vz2))));
883 const MFloat c =
884 ((1. / 12.)
885 * (-Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw
886 + 2
887 * (Eb + Ef + Wb + Wf + vv_x * (Ne - Nw + Se - Sw + 2 * (Wb + Wf - Eb - Ef - 2 * x + 6 * xxx))
888 + vv_y * Y_ + vv_z * (Nf - Nb - Sb + Sf + 2 * (Eb - Ef + Wb - Wf - 2 * z - 6 * zzz)))
889 + vx2
890 * (Nb - N - Ne + Nf - Nw - S + Sb - Se + Sf - Sw + 42 * pe
891 + 2 * (B + Eb + Ef + F + Wb + Wf + vxy - 2 * vxz))
892 - vy2 * (B + E + F + Nb + Ne + Nf + Nw + Sb + Se + Sf + Sw + W + 84 * pe + 2 * (Eb + Ef + Wb + Wf + vxy))
893 + vz2
894 * (Ne - N - Nb - Nf + Nw - S - Sb + Se - Sf + Sw + 42 * pe
895 + 2 * (E + Eb + Ef + W + Wb + Wf + 3 * vxy + 2 * vxz))
896 + 4 * vv_y * (vv_x * UXY + vv_z * UYZ) - 8 * vv_x * vv_z * UXZ + (2 * vx2 * vz2 - (vx2 + vz2) * vy2) * rho
897 + 2 * (pi_x * vv_x * (vy2 - 2 * vz2) + pi_z * vv_z * (vy2 - 2 * vx2) + pi_y * vv_y * (vx2 + vz2))));
898
899 a_distribution(pCellId, 18) = R + (12 * p - 30 * pe);
900 a_distribution(pCellId, 7) = Nw + c + a - xxx - yyy - x + y + uxy + p + 8 * pe;
901 a_distribution(pCellId, 0) = W - 2 * a + 4 * x - 11 * pe + vxy + vxz - 4 * p;
902 a_distribution(pCellId, 6) = Sw + a + c - xxx + yyy - x - y - uxy + p + 8 * pe;
903 a_distribution(pCellId, 2) = S - 2 * c + 4 * y - 11 * pe - vxy - 4 * p;
904 a_distribution(pCellId, 8) = Se + a + c + xxx + yyy + x - y + uxy + p + 8 * pe;
905 a_distribution(pCellId, 1) = E - 2 * a - 4 * x - 11 * pe + vxy + vxz - 4 * p;
906 a_distribution(pCellId, 9) = Ne + c + a + x + y + xxx - yyy - uxy + p + 8 * pe;
907 a_distribution(pCellId, 3) = N - 2 * c - 4 * y - 11 * pe - vxy - 4 * p; // s_n;
908 a_distribution(pCellId, 17) = Nf - a + yyy - zzz + y + z - uyz + p + 8 * pe;
909 a_distribution(pCellId, 16) = Nb - a + yyy + zzz + y - z + uyz + p + 8 * pe;
910 a_distribution(pCellId, 15) = Sf - a - yyy - zzz - y + z + uyz + p + 8 * pe;
911 a_distribution(pCellId, 14) = Sb - a - yyy + zzz - y - z - uyz + p + 8 * pe;
912 a_distribution(pCellId, 13) = Ef - c - xxx + zzz + x + z - uxz + p + 8 * pe;
913 a_distribution(pCellId, 12) = Eb - c - xxx - zzz + x - z + uxz + p + 8 * pe;
914 a_distribution(pCellId, 11) = Wf - c + xxx + zzz - x + z + uxz + p + 8 * pe;
915 a_distribution(pCellId, 10) = Wb - c + xxx - zzz - x - z - uxz + p + 8 * pe;
916 a_distribution(pCellId, 5) = F + 2 * a + 2 * c - 4 * z - 11 * pe - vxz - 4 * p;
917 a_distribution(pCellId, 4) = B + 2 * a + 2 * c + 4 * z - 11 * pe - vxz - 4 * p;
918 }
919 }
920 if(m_calculateDissipation && globalTimeStep % m_solutionInterval == 0) {
922 }
923}
void calculateDissipation()
Calculate total energy, dissipation, and subgrid dissipation for Smagorinsky.
define array structures

◆ clb_collision_step_base() [3/4]

void LbSolverDxQy< 3, 27, maia::lb::LbSysEqnIncompressible< 3, 27 > >::clb_collision_step_base ( )

Smagorinsky constant

Definition at line 927 of file lbsolverdxqy.cpp.

927 {
928 TRACE();
929 constexpr MInt nDist = 27;
930 constexpr MInt nDim = 3;
931 constexpr MInt nDimSqr = 9;
932
933 [[maybe_unused]] constexpr MFloat C_s = 0.1;
934
935 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
936 const MInt pCellId = m_activeCellList[i];
937
938 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
939 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
940
941 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
942 swap_variables(pCellId);
943
944 // Calculate macroscopic variables
945 a_variable(pCellId, PV->RHO) = 0.0;
946 for(MInt j = 0; j < nDist; j++) {
947 a_variable(pCellId, PV->RHO) += a_oldDistribution(pCellId, j);
948 }
949
950 a_variable(pCellId, PV->U) = 0.0;
951 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
952 a_variable(pCellId, PV->U) += a_oldDistribution(pCellId, Ld::pFld(0, j));
953 a_variable(pCellId, PV->U) -= a_oldDistribution(pCellId, Ld::nFld(0, j));
954 }
955 a_variable(pCellId, PV->U) /= a_variable(pCellId, PV->RHO);
956
957 a_variable(pCellId, PV->V) = 0.0;
958 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
959 a_variable(pCellId, PV->V) += a_oldDistribution(pCellId, Ld::pFld(1, j));
960 a_variable(pCellId, PV->V) -= a_oldDistribution(pCellId, Ld::nFld(1, j));
961 }
962 a_variable(pCellId, PV->V) /= a_variable(pCellId, PV->RHO);
963
964 a_variable(pCellId, PV->W) = 0.0;
965 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
966 a_variable(pCellId, PV->W) += a_oldDistribution(pCellId, Ld::pFld(2, j));
967 a_variable(pCellId, PV->W) -= a_oldDistribution(pCellId, Ld::nFld(2, j));
968 }
969 a_variable(pCellId, PV->W) /= a_variable(pCellId, PV->RHO);
970
971 if constexpr(useSmagorinsky) {
972 // Calculation of equilibrium and non-equilibrium distribution
973 std::array<MFloat, nDist> eqDist{};
974 std::array<MFloat, nDist> d{};
975 std::array<MFloat, nDim> u{};
976 for(MInt dim = 0; dim < nDim; dim++) {
977 u[dim] = a_variable(pCellId, dim);
978 }
979 eqDist = getEqDists(a_variable(pCellId, PV->RHO), u.data());
980
981 for(MInt j = 0; j < nDist; j++) {
982 d[j] = a_oldDistribution(pCellId, j) - eqDist[j];
983 }
984
985 // Calculation of strain rate tensor (stress tensor)
986 std::array<MFloat, nDimSqr> Q{};
987 Q[0] = F2B3
988 * (d[0] + d[1] + d[6] + d[7] + d[8] + d[9] + d[10] + d[11] + d[12] + d[13] + d[18] + d[19] + d[20]
989 + d[21] + d[22] + d[23] + d[24] + d[25])
990 - F1B3 * (d[2] + d[3] + d[4] + d[5] + d[14] + d[15] + d[16] + d[17] + d[26]);
991 Q[1] = (d[6] - d[7] - d[8] + d[9] + d[18] + d[19] - d[20] - d[21] - d[22] - d[23] + d[24] + d[25]);
992 Q[2] = (d[10] - d[11] - d[12] + d[13] + d[18] - d[19] + d[20] - d[21] - d[22] + d[23] - d[24] + d[25]);
993 Q[3] = Q[1];
994 Q[4] = F2B3
995 * (d[2] + d[3] + d[6] + d[7] + d[8] + d[9] + d[14] + d[15] + d[16] + d[17] + d[18] + d[19] + d[20]
996 + d[21] + d[22] + d[23] + d[24] + d[25])
997 - F1B3 * (d[0] + d[1] + d[4] + d[5] + d[10] + d[11] + d[12] + d[13] + d[26]);
998 Q[5] = (d[14] - d[15] - d[16] + d[17] + d[18] - d[19] - d[20] + d[21] + d[22] - d[23] - d[24] + d[25]);
999 Q[6] = Q[2];
1000 Q[7] = Q[5];
1001 Q[8] = F2B3
1002 * (d[4] + d[5] + d[10] + d[11] + d[12] + d[13] + d[14] + d[15] + d[16] + d[17] + d[18] + d[19]
1003 + d[20] + d[21] + d[22] + d[23] + d[24] + d[25])
1004 - F1B3 * (d[0] + d[1] + d[2] + d[3] + d[6] + d[7] + d[8] + d[9] + d[26]);
1005
1006 const MFloat Q_mean = sqrt(2.0 * std::inner_product(&Q[0], &Q[nDimSqr], &Q[0], .0));
1007
1008 // eddy viscosity
1009 const MFloat nu_t = C_s * C_s * Q_mean;
1010
1011 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
1012 m_nu += nu_t; // this has to adapted for refined grids !!!
1013 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
1014 }
1015
1016 const MFloat R = a_oldDistribution(pCellId, 26);
1017 const MFloat Nw = a_oldDistribution(pCellId, 7);
1018 const MFloat W = a_oldDistribution(pCellId, 0);
1019 const MFloat Sw = a_oldDistribution(pCellId, 6);
1020 const MFloat S = a_oldDistribution(pCellId, 2);
1021 const MFloat Se = a_oldDistribution(pCellId, 8);
1022 const MFloat E = a_oldDistribution(pCellId, 1);
1023 const MFloat Ne = a_oldDistribution(pCellId, 9);
1024 const MFloat N = a_oldDistribution(pCellId, 3);
1025 const MFloat Nf = a_oldDistribution(pCellId, 17);
1026 const MFloat Nb = a_oldDistribution(pCellId, 16);
1027 const MFloat Sf = a_oldDistribution(pCellId, 15);
1028 const MFloat Sb = a_oldDistribution(pCellId, 14);
1029 const MFloat Ef = a_oldDistribution(pCellId, 13);
1030 const MFloat Eb = a_oldDistribution(pCellId, 12);
1031 const MFloat Wf = a_oldDistribution(pCellId, 11);
1032 const MFloat Wb = a_oldDistribution(pCellId, 10);
1033 const MFloat F = a_oldDistribution(pCellId, 5);
1034 const MFloat B = a_oldDistribution(pCellId, 4);
1035 const MFloat Nwf = a_oldDistribution(pCellId, 21);
1036 const MFloat Nwb = a_oldDistribution(pCellId, 20);
1037 const MFloat Nef = a_oldDistribution(pCellId, 25);
1038 const MFloat Neb = a_oldDistribution(pCellId, 24);
1039 const MFloat Swf = a_oldDistribution(pCellId, 19);
1040 const MFloat Swb = a_oldDistribution(pCellId, 18);
1041 const MFloat Sef = a_oldDistribution(pCellId, 23);
1042 const MFloat Seb = a_oldDistribution(pCellId, 22);
1043
1044 const MFloat rho = Nw + W + Sw + S + Se + E + Ne + N + R + Nf + Nb + Sf + Sb + Ef + Eb + Wf + Wb + Nwf + Nwb + Nef
1045 + Neb + Swf + Swb + Sef + Seb + F + B;
1046 const MFloat pi_x =
1047 (Ne + E + Se + Ef + Eb - Nw - W - Sw - Wf - Wb + Nef + Neb + Sef + Seb - Nwf - Nwb - Swf - Swb);
1048 const MFloat pi_y =
1049 (Ne + N + Nw + Nf + Nb - Se - S - Sw - Sf - Sb + Nef + Neb + Nwf + Nwb - Sef - Seb - Swf - Swb);
1050 const MFloat pi_z =
1051 (Nf + Sf + Wf + Ef + F - Nb - Sb - Wb - Eb - B + Nef + Nwf + Sef + Swf - Neb - Nwb - Seb - Swb);
1052 const MFloat vv_x = pi_x / rho;
1053 const MFloat vv_y = pi_y / rho;
1054 const MFloat vv_z = pi_z / rho;
1055 const MFloat vx2 = vv_x * vv_x;
1056 const MFloat vy2 = vv_y * vv_y;
1057 const MFloat vz2 = vv_z * vv_z;
1058 const MFloat uxy = (m_omega
1059 * (Ne + Neb + Nef - Nw - Nwb - Nwf - Se - Seb - Sef + Sw + Swb + Swf + vv_x * vv_y * rho
1060 - pi_x * vv_y - pi_y * vv_x)
1061 * 0.25);
1062 const MFloat uxz = (m_omega
1063 * (-Eb + Ef - Neb + Nef + Nwb - Nwf - Seb + Sef + Swb - Swf + Wb - Wf + vv_x * vv_z * rho
1064 - pi_x * vv_z - pi_z * vv_x)
1065 * 0.25);
1066 const MFloat uyz = (m_omega
1067 * (-Nb - Neb + Nef + Nf - Nwb + Nwf + Sb + Seb - Sef - Sf + Swb - Swf + vv_z * vv_y * rho
1068 - pi_z * vv_y - pi_y * vv_z)
1069 * 0.25);
1070
1071 const MFloat vxy = (m_omega * (1. / 6.)
1072 * (-B - E - F + Nb + Ne + Nf + Nw + Sb + Se + Sf + Sw - W + 2 * (-Eb - Ef + N + S - Wb - Wf)
1073 + 2 * (-2 * pi_y * vv_y + pi_x * vv_x + pi_z * vv_z) - rho * (vz2 - 2 * vy2 + vx2)));
1074 const MFloat vxz = (m_omega * (1. / 6.)
1075 * (-E + Eb + Ef - N + Nb + Nf - S + Sb + Sf - W + Wb + Wf + 2 * (B + F - Ne - Nw - Se - Sw)
1076 + 2 * (-2 * pi_z * vv_z + pi_x * vv_x + pi_y * vv_y) - rho * (vx2 + vy2 - 2 * vz2)));
1077 const MFloat pe = ((1. / 126.)
1078 * (-B - E - F - N - S - W + 2 * (-Eb - Ef - Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw - Wb - Wf)
1079 + 3 * (-Neb - Nef - Nwb - Nwf - Seb - Sef - Swb - Swf)
1080 + (rho + vv_y * (2 * pi_y - vv_y * rho) + vv_z * (2 * pi_z - vv_z * rho)
1081 + vv_x * (2 * pi_x - vv_x * rho))));
1082
1083 const MFloat UXY = -Ne - Neb - Nef + Nw + Nwb + Nwf + Se + Seb + Sef - Sw - Swb - Swf + 4 * uxy;
1084 const MFloat UXZ = Eb - Ef + Neb - Nef - Nwb + Nwf + Seb - Sef - Swb + Swf - Wb + Wf + 4 * uxz;
1085 const MFloat UYZ = Nb + Neb - Nef - Nf + Nwb - Nwf - Sb - Seb + Sef + Sf - Swb + Swf + 4 * uyz;
1086
1087 const MFloat x =
1088 ((0.125
1089 * (Nw + Sw + Wf + Wb - Eb - Ef - Ne - Se
1090 + vv_x
1091 * (B + Eb + Ef + 84 * pe + F + N + Ne + Nw + S + Se + Sw + Wb + Wf
1092 + 2 * (Nb + Neb + Nef + Nf + Nwb + Nwf + Sb + Seb + Sef + Sf + Swb + Swf - vxy - vxz)))
1093 + 0.25 * (-Neb - Nef + Nwb + Nwf - Seb - Sef + Swb + Swf - vv_y * UXY - vv_z * UXZ)
1094 - 0.25 * vv_x * (vv_y * pi_y + vv_z * pi_z) + 0.125 * (vy2 + vz2) * (vv_x * rho - pi_x)));
1095 const MFloat y =
1096 ((0.125
1097 * (Sb + Sf + Se + Sw - Nw - Ne - Nf - Nb
1098 + vv_y
1099 * (B + E + 84 * pe + F + Nb + Ne + Nf + Nw + Sb + Se + Sf + Sw + W
1100 + 2 * (Eb + Ef + Neb + Nef + Nwb + Nwf + Seb + Sef + Swb + Swf + Wb + Wf + vxy)))
1101 + 0.25 * (-Neb - Nef - Nwb - Nwf + Seb + Sef + Swb + Swf - vv_x * UXY - vv_z * UYZ)
1102 - 0.25 * vv_y * (vv_z * pi_z + vv_x * pi_x) + 0.125 * (vx2 + vz2) * (vv_y * rho - pi_y)));
1103 const MFloat z =
1104 ((0.125
1105 * (Eb + Nb + Sb + Wb - Ef - Nf - Sf - Wf
1106 + vv_z
1107 * (E + Eb + Ef + N + Nb + Nf + S + Sb + Sf + W + Wb + Wf + 84 * pe
1108 + 2 * (Ne + Neb + Nef + Nw + Nwb + Nwf + Se + Seb + Sef + Sw + Swb + Swf + vxz)))
1109 + 0.25 * (-Nef + Neb + Nwb - Nwf + Seb - Sef + Swb - Swf - vv_x * UXZ - vv_y * UYZ)
1110 - 0.25 * vv_z * (vv_x * pi_x + vv_y * pi_y) + 0.125 * (vx2 + vy2) * (vv_z * rho - pi_z)));
1111
1112 const MFloat xxx = ((0.125
1113 * (Eb + Ef - Ne + Nw - Se + Sw - Wb - Wf
1114 + vv_x * (-B - Eb - Ef - F + N + Ne + Nw + S + Se + Sw - Wb - Wf + 2 * (vxz - vxy)))
1115 + 0.25 * (vv_z * UXZ - vv_y * UXY + vv_x * (vv_z * pi_z - vv_y * pi_y))
1116 + 0.125 * ((pi_x - vv_x * rho) * (vz2 - vy2))));
1117 const MFloat yyy =
1118 ((0.125
1119 * (Ne - Nb - Nf + Nw + Sb - Se + Sf - Sw
1120 + vv_y * (-E + B + F + Nb - Ne + Nf - Nw + Sb - Se + Sf - Sw - W + 2 * (-vxy - 2 * vxz)))
1121 + 0.25 * (vv_x * UXY - vv_z * UYZ + vv_y * (vv_x * pi_x - vv_z * pi_z))
1122 + 0.125 * ((pi_y - vv_y * rho) * (vx2 - vz2))));
1123 const MFloat zzz =
1124 ((0.125
1125 * (Eb - Ef - Nb + Nf - Sb + Sf + Wb - Wf
1126 + vv_z * (E + Eb + Ef - N - Nb - Nf - S - Sb - Sf + W + Wb + Wf + 2 * (vxz + 2 * vxy)))
1127 + 0.25 * (vv_y * UYZ - vv_x * UXZ + vv_z * (vv_y * pi_y - vv_x * pi_x))
1128 + 0.125 * ((pi_z - vv_z * rho) * (vy2 - vx2))));
1129
1130 const MFloat xyz =
1131 (0.125
1132 * (Neb - Nef - Nwb + Nwf - Seb + Sef + Swb - Swf - vv_x * UYZ - vv_y * UXZ - vv_z * UXY
1133 + rho * vv_x * vv_y * vv_z - (vv_x * vv_y * pi_z + vv_x * pi_y * vv_z + pi_x * vv_y * vv_z)));
1134
1135 const MFloat X_ =
1136 (Eb + Ef + Ne - Nw + Se - Sw - Wb - Wf + 2 * (Neb + Nef - Nwb - Nwf + Seb + Sef - Swb - Swf) + 8 * x);
1137 const MFloat Y_ =
1138 (Nb + Ne + Nf + Nw - Sb - Se - Sf - Sw + 2 * (Neb + Nef + Nwb + Nwf - Seb - Sef - Swb - Swf) + 8 * y);
1139 const MFloat Z_ =
1140 (Ef - Eb - Nb + Nf - Sb + Sf - Wb + Wf + 2 * (Nef - Neb - Nwb + Nwf - Seb + Sef - Swb + Swf) + 8 * z);
1141
1142 const MFloat XnXXX = Eb + Ef + Neb + Nef - Nwb - Nwf + Seb + Sef - Swb - Swf - Wb - Wf + 4 * (x - xxx);
1143 const MFloat XpXXX = Ne + Neb + Nef - Nw - Nwb - Nwf + Se + Seb + Sef - Sw - Swb - Swf + 4 * (x + xxx);
1144 const MFloat YnYYY = Ne + Neb + Nef + Nw + Nwb + Nwf - Se - Seb - Sef - Sw - Swb - Swf + 4 * (y - yyy);
1145 const MFloat YpYYY = Nb + Neb + Nef + Nf + Nwb + Nwf - Sb - Seb - Sef - Sf - Swb - Swf + 4 * (y + yyy);
1146 const MFloat ZnZZZ = Nef - Nb - Neb + Nf - Nwb + Nwf - Sb - Seb + Sef + Sf - Swb + Swf + 4 * (z - zzz);
1147 const MFloat ZpZZZ = Nef - Eb + Ef - Neb - Nwb + Nwf - Seb + Sef - Swb + Swf - Wb + Wf + 4 * (z + zzz);
1148
1149 const MFloat XYZ = -Neb + Nef + Nwb - Nwf + Seb - Sef - Swb + Swf + 8 * xyz;
1150 const MFloat EPa = -42 * pe - E - Eb - Ef - Ne - Neb - Nef - Nw - Nwb - Nwf - Se - Seb - Sef - Sw - Swb - Swf - W
1151 - Wb - Wf - 2 * (vxy + vxz);
1152 const MFloat EPb = -42 * pe - B - Eb - Ef - F - Nb - Neb - Nef - Nf - Nwb - Nwf - Sb - Seb - Sef - Sf - Swb - Swf
1153 - Wb - Wf + 2 * vxz;
1154 const MFloat EPc = -42 * pe - N - Nb - Ne - Neb - Nef - Nf - Nw - Nwb - Nwf - S - Sb - Se - Seb - Sef - Sf - Sw
1155 - Swb - Swf + 2 * vxy;
1156
1157 const MFloat p =
1158 ((1. / 12.)
1159 * (rho / (3.) - 96 * pe - Eb - Ef - Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw - Wb - Wf
1160 - 3 * (Nwf + Nwb + Nef + Neb + Swf + Swb + Sef + Seb) + 2 * (+vv_x * X_ + vv_y * Y_ + vv_z * Z_)
1161 + vx2
1162 * (-84 * pe - B - Eb - Ef - F - N - Ne - Nw - S - Se - Sw - Wb - Wf
1163 + 2 * (vxy + vxz - Nb - Neb - Nef - Nf - Nwb - Nwf - Sb - Seb - Sef - Sf - Swb - Swf))
1164 + vy2
1165 * (-84 * pe - B - E - F - Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw - W
1166 + 2 * (-vxy - Eb - Ef - Neb - Nef - Nwb - Nwf - Seb - Sef - Swb - Swf - Wb - Wf))
1167 + vz2
1168 * (-84 * pe - E - Eb - Ef - N - Nb - Nf - S - Sb - Sf - W - Wb - Wf
1169 + 2 * (-vxz - Ne - Neb - Nef - Nw - Nwb - Nwf - Se - Seb - Sef - Sw - Swb - Swf))
1170 + 4 * (vv_x * vv_y * UXY + vv_x * vv_z * UXZ + vv_y * vv_z * UYZ)
1171 - rho * (vx2 * vy2 + vx2 * vz2 + vy2 * vz2)
1172 + 2 * (pi_y * vv_y * (vx2 + vz2) + pi_x * vv_x * (vy2 + vz2) + pi_z * vv_z * (vx2 + vy2))));
1173 const MFloat a =
1174 ((1. / 12.)
1175 * (-Eb - Ef - Ne - Nw - Se - Sw - Wb - Wf
1176 + 2
1177 * (Nb + Nf + Sb + Sf + vv_x * X_
1178 + vv_y
1179 * (Ne - Neb - Nef + Nw - Nwb - Nwf - Se + Seb + Sef - Sw + Swb + Swf
1180 + 2 * (Sf + Sb - Nb - Nf - 2 * y - 6 * yyy))
1181 + vv_z
1182 * (Ef - Eb + Neb - Nef + Nwb - Nwf + Seb - Sef + Swb - Swf - Wb + Wf
1183 + 2 * (Nb - Nf + Sb - Sf - 2 * z + 6 * zzz)))
1184 + vx2
1185 * (-B - Eb - Ef - F - N - Ne - Nw - S - Se - Sw - Wb - Wf - 84 * pe
1186 - 2 * (Nb + Neb + Nef + Nf + Nwb + Nwf + Sb + Seb + Sef + Sf + Swb + Swf - vxy - vxz))
1187 + vy2
1188 * (Eb - E + Ef - Ne + Neb + Nef - Nw + Nwb + Nwf - Se + Seb + Sef - Sw + Swb + Swf - W + Wb + Wf
1189 + 42 * pe + 2 * (B + F + Nb + Nf + Sb + Sf - vxy - 3 * vxz))
1190 + vz2
1191 * (Ne - E - Eb - Ef + Neb + Nef + Nw + Nwb + Nwf + Se + Seb + Sef + Sw + Swb + Swf - W - Wb - Wf
1192 + 42 * pe + 2 * (N + Nb + Nf + S + Sb + Sf - vxz - 3 * vxy))
1193 + 4 * (vv_x * (vv_y * UXY + vv_z * UXZ)) - 8 * vv_y * vv_z * UYZ
1194 + (2 * vy2 * vz2 - vx2 * (vy2 + vz2)) * rho
1195 + 2 * (pi_y * vv_y * (vx2 - 2 * vz2) + pi_z * vv_z * (vx2 - 2 * vy2) + pi_x * vv_x * (vy2 + vz2))));
1196 const MFloat c =
1197 ((1. / 12.)
1198 * (-Nb - Ne - Nf - Nw - Sb - Se - Sf - Sw
1199 + 2
1200 * (Eb + Ef + Wb + Wf
1201 + vv_x
1202 * (Ne - Neb - Nef - Nw + Nwb + Nwf + Se - Seb - Sef - Sw + Swb + Swf
1203 + 2 * (Wb + Wf - Eb - Ef - 2 * x + 6 * xxx))
1204 + vv_y * Y_
1205 + vv_z
1206 * (Nf - Nb + Neb - Nef + Nwb - Nwf - Sb + Seb - Sef + Sf + Swb - Swf
1207 + 2 * (Eb - Ef + Wb - Wf - 2 * z - 6 * zzz)))
1208 + vx2
1209 * (Nb - N - Ne + Neb + Nef + Nf - Nw + Nwb + Nwf - S + Sb - Se + Seb + Sef + Sf - Sw + Swb + Swf
1210 + 42 * pe + 2 * (B + Eb + Ef + F + Wb + Wf + vxy - 2 * vxz))
1211 - vy2
1212 * (B + E + F + Nb + Ne + Nf + Nw + Sb + Se + Sf + Sw + W + 84 * pe
1213 + 2 * (Eb + Ef + Neb + Nef + Nwb + Nwf + Seb + Sef + Swb + Swf + Wb + Wf + vxy))
1214 + vz2
1215 * (Ne - N - Nb + Neb + Nef - Nf + Nw + Nwb + Nwf - S - Sb + Se + Seb + Sef - Sf + Sw + Swb + Swf
1216 + 42 * pe + 2 * (E + Eb + Ef + W + Wb + Wf + 3 * vxy + 2 * vxz))
1217 + 4 * vv_y * (vv_x * UXY + vv_z * UYZ) - 8 * vv_x * vv_z * UXZ + (2 * vx2 * vz2 - (vx2 + vz2) * vy2) * rho
1218 + 2 * (pi_x * vv_x * (vy2 - 2 * vz2) + pi_z * vv_z * (vy2 - 2 * vx2) + pi_y * vv_y * (vx2 + vz2))));
1219 const MFloat uxxyz = ((1. / 8.)
1220 * (Neb - Nef + Nwb - Nwf - Seb + Sef - Swb + Swf + vv_y * ZpZZZ + vv_z * YnYYY
1221 + 2 * vv_x * (XYZ + vv_y * UXZ + vv_z * UXY) + vx2 * UYZ + vv_y * vv_z * EPa
1222 + (2 * pi_x - rho * vv_x) * vv_x * vv_y * vv_z + vx2 * (pi_y * vv_z + pi_z * vv_y)));
1223 const MFloat uxyyz = ((1. / 8.)
1224 * (Neb - Nef - Nwb + Nwf + Seb - Sef - Swb + Swf + vv_x * ZnZZZ /*YnYYY*/ + vv_z * XpXXX
1225 + 2 * vv_y * (XYZ + vv_x * UYZ + vv_z * UXY) + vy2 * UXZ
1226 + vv_x * vv_z * EPc
1227 //+rho*3*vy2*vv_x*vv_z
1228 + (2 * pi_y - vv_y * rho) * vv_y * vv_x * vv_z + vy2 * (pi_x * vv_z + pi_z * vv_x)));
1229 const MFloat uxyzz = ((1. / 8.)
1230 * (Nwb - Neb - Nef + Nwf + Seb + Sef - Swb - Swf + vv_x * YpYYY + vv_y * XnXXX
1231 + 2 * vv_z * (XYZ + vv_y * UXZ + vv_x * UYZ) + vz2 * UXY + vv_x * vv_y * EPb
1232 + (2 * pi_z - vv_z * rho) * vv_x * vv_y * vv_z + vz2 * (pi_y * vv_x + pi_x * vv_y)));
1233
1234 const MFloat A = 4 * a - 32 * pe - Nb - Neb - Nef - Nf - Nwb - Nwf - 4 * p - Sb - Seb - Sef - Sf - Swb - Swf;
1235 const MFloat C = 4 * (c - p) - Eb - Ef - 32 * pe - Neb - Nef - Nwb - Nwf - Seb - Sef - Swb - Swf - Wb - Wf;
1236 const MFloat CA = -4 * (a + c + p) - 32 * pe - Ne - Neb - Nef - Nw - Nwb - Nwf - Se - Seb - Sef - Sw - Swb - Swf;
1237 const MFloat UXYZZ = Nwb - Neb - Nef + Nwf + Seb + Sef - Swb - Swf - 8 * uxyzz;
1238 const MFloat UXYYZ = Neb - Nef - Nwb + Nwf + Seb - Sef - Swb + Swf - 8 * uxyyz;
1239 const MFloat UXXYZ = Neb - Nef + Nwb - Nwf - Seb + Sef - Swb + Swf - 8 * uxxyz;
1240
1241 const MFloat xyyzz =
1242 ((1. / 8.)
1243 * (Nwb - Neb - Nef + Nwf - Seb - Sef + Swb + Swf - vv_x * A - 2 * (vv_y * UXYZZ + vv_z * UXYYZ) - vy2 * XnXXX
1244 - vz2 * XpXXX + 2 * vv_x * (-vv_y * YpYYY - vv_z * ZnZZZ) - 4 * vv_y * vv_z * (XYZ + vv_x * UYZ)
1245 - vv_x * (vz2 * EPc + vy2 * EPb)
1246 - 2 * (vy2 * vv_z * UXZ + vv_y * vz2 * UXY)
1247 //-4*vv_x*vy2*vz2*rho
1248 - 2 * vv_x * vv_y * vv_z * (pi_y * vv_z + pi_z * vv_y) + vy2 * vz2 * (vv_x * rho - pi_x)));
1249 const MFloat xxyzz =
1250 ((1. / 8.)
1251 * (Seb - Neb - Nef - Nwb - Nwf + Sef + Swb + Swf - vv_y * C - 2 * (vv_x * UXYZZ + vv_z * UXXYZ) - vx2 * YpYYY
1252 - vz2 * YnYYY + 2 * vv_y * (-vv_x * XnXXX - vv_z * ZpZZZ) - 4 * vv_x * vv_z * (XYZ + vv_y * UXZ)
1253 - vv_y * (vx2 * EPb + vz2 * EPa)
1254 - 2 * (vx2 * vv_z * UYZ + vv_x * vz2 * UXY)
1255 //-4*vv_y*vx2*vz2*rho
1256 - 2 * vv_x * vv_y * vv_z * (pi_x * vv_z + pi_z * vv_x) + vx2 * vz2 * (vv_y * rho - pi_y)));
1257 const MFloat xxyyz =
1258 ((1. / 8.)
1259 * (Neb - Nef + Nwb - Nwf + Seb - Sef + Swb - Swf - vv_z * CA - 2 * (vv_x * UXYYZ + vv_y * UXXYZ)
1260 - vx2 * ZnZZZ - vy2 * ZpZZZ + 2 * vv_z * (-vv_x * XpXXX - vv_y * YnYYY)
1261 - 4 * vv_x * vv_y * (XYZ + vv_z * UXY) - vv_z * (vx2 * EPc + vy2 * EPa)
1262 - 2 * (vx2 * vv_y * UYZ + vv_x * vy2 * UXZ)
1263 //-4*vx2*vy2*vv_z*rho
1264 - 2 * vv_x * vv_y * vv_z * (pi_x * vv_y + pi_y * vv_x) + vx2 * vy2 * (vv_z * rho - pi_z)));
1265
1266 const MFloat xxyyzz =
1267 ((1. / 8.)
1268 * (rho / 27. - Neb - Nef - Nwb - Nwf - Seb - Sef - Swb - Swf
1269 + 2
1270 * (+vv_x * (Neb + Nef - Nwb - Nwf + Seb + Sef - Swb - Swf + 8 * xyyzz)
1271 + vv_y * (Neb + Nef + Nwb + Nwf - Seb - Sef - Swb - Swf + 8 * xxyzz)
1272 + vv_z * (-Neb + Nef - Nwb + Nwf - Seb + Sef - Swb + Swf + 8 * xxyyz))
1273 + vx2 * A + vy2 * C + vz2 * CA + 4 * (vv_x * vv_y * UXYZZ + vv_x * vv_z * UXYYZ + vv_y * vv_z * UXXYZ)
1274 + 2
1275 * (vx2 * vv_y * YpYYY + vx2 * vv_z * ZnZZZ + vy2 * vv_z * ZpZZZ + vv_x * vy2 * XnXXX
1276 + vv_x * vz2 * XpXXX + vz2 * vv_y * YnYYY)
1277 + 8 * vv_x * vv_y * vv_z * XYZ + vx2 * vz2 * EPc + vx2 * vy2 * EPb + vy2 * vz2 * EPa
1278 + 4 * vv_x * vv_y * vv_z * (vv_z * UXY + vv_y * UXZ + vv_x * UYZ)
1279 + 2 * (vx2 * vy2 * vv_z * pi_z + vx2 * vv_y * pi_y * vz2 + vv_x * pi_x * vy2 * vz2)
1280 - rho * vx2 * vy2 * vz2));
1281
1282 a_distribution(pCellId, 26) = R + (12 * p - 30 * pe - 8 * xxyyzz);
1283 a_distribution(pCellId, 7) =
1284 Nw + c + a - xxx - yyy - x + y + uxy + p + 8 * pe + 2 * (-xxyyzz - xxyzz + xyyzz + uxyzz);
1285 a_distribution(pCellId, 0) = W - 2 * a + 4 * x - 11 * pe + vxy + vxz - 4 * p + 4 * (-xyyzz + xxyyzz);
1286 a_distribution(pCellId, 6) =
1287 Sw + a + c - xxx + yyy - x - y - uxy + p + 8 * pe + 2 * (-xxyyzz + xxyzz + xyyzz - uxyzz);
1288 a_distribution(pCellId, 2) = S - 2 * c + 4 * y - 11 * pe - vxy - 4 * p + 4 * (-xxyzz + xxyyzz);
1289 a_distribution(pCellId, 8) =
1290 Se + a + c + xxx + yyy + x - y + uxy + p + 8 * pe + 2 * (-xxyyzz + xxyzz - xyyzz + uxyzz);
1291 a_distribution(pCellId, 1) = E - 2 * a - 4 * x - 11 * pe + vxy + vxz - 4 * p + 4 * (xyyzz + xxyyzz);
1292 a_distribution(pCellId, 9) =
1293 Ne + c + a + x + y + xxx - yyy - uxy + p + 8 * pe + 2 * (-xxyyzz - xxyzz - xyyzz - uxyzz);
1294 a_distribution(pCellId, 3) = N - 2 * c - 4 * y - 11 * pe - vxy - 4 * p + 4 * (xxyzz + xxyyzz); // s_n;
1295 a_distribution(pCellId, 17) =
1296 Nf - a + yyy - zzz + y + z - uyz + p + 8 * pe + 2 * (-xxyyzz - xxyzz - xxyyz - uxxyz);
1297 a_distribution(pCellId, 16) =
1298 Nb - a + yyy + zzz + y - z + uyz + p + 8 * pe + 2 * (-xxyyzz - xxyzz + xxyyz + uxxyz);
1299 a_distribution(pCellId, 15) =
1300 Sf - a - yyy - zzz - y + z + uyz + p + 8 * pe + 2 * (-xxyyzz + xxyzz - xxyyz + uxxyz);
1301 a_distribution(pCellId, 14) =
1302 Sb - a - yyy + zzz - y - z - uyz + p + 8 * pe + 2 * (-xxyyzz + xxyzz + xxyyz - uxxyz);
1303 a_distribution(pCellId, 13) =
1304 Ef - c - xxx + zzz + x + z - uxz + p + 8 * pe + 2 * (-xxyyzz - xyyzz - xxyyz - uxyyz);
1305 a_distribution(pCellId, 12) =
1306 Eb - c - xxx - zzz + x - z + uxz + p + 8 * pe + 2 * (-xxyyzz - xyyzz + xxyyz + uxyyz);
1307 a_distribution(pCellId, 11) =
1308 Wf - c + xxx + zzz - x + z + uxz + p + 8 * pe + 2 * (-xxyyzz + xyyzz - xxyyz + uxyyz);
1309 a_distribution(pCellId, 10) =
1310 Wb - c + xxx - zzz - x - z - uxz + p + 8 * pe + 2 * (-xxyyzz + xyyzz + xxyyz - uxyyz);
1311 a_distribution(pCellId, 5) = F + 2 * a + 2 * c - 4 * z - 11 * pe - vxz - 4 * p + 4 * (xxyyzz + xxyyz);
1312 a_distribution(pCellId, 4) = B + 2 * a + 2 * c + 4 * z - 11 * pe - vxz - 4 * p + 4 * (-xxyyz + xxyyzz);
1313 a_distribution(pCellId, 21) = Nwf - xyz + uxxyz - uxyyz - uxyzz - (-xxyyz + xyyzz - xxyzz) + xxyyzz;
1314 a_distribution(pCellId, 20) = Nwb + xyz - uxxyz + uxyyz - uxyzz - (xxyyz + xyyzz - xxyzz) + xxyyzz;
1315 a_distribution(pCellId, 25) = Nef + xyz + uxxyz + uxyyz + uxyzz - (-xxyyz - xyyzz - xxyzz) + xxyyzz;
1316 a_distribution(pCellId, 24) = Neb - xyz - uxxyz - uxyyz + uxyzz - (xxyyz - xyyzz - xxyzz) + xxyyzz;
1317 a_distribution(pCellId, 19) = Swf + xyz - uxxyz - uxyyz + uxyzz - (-xxyyz + xyyzz + xxyzz) + xxyyzz;
1318 a_distribution(pCellId, 18) = Swb - xyz + uxxyz + uxyyz + uxyzz - (xxyyz + xyyzz + xxyzz) + xxyyzz;
1319 a_distribution(pCellId, 23) = Sef - xyz - uxxyz + uxyyz - uxyzz - (-xxyyz - xyyzz + xxyzz) + xxyyzz;
1320 a_distribution(pCellId, 22) = Seb + xyz + uxxyz - uxyyz - uxyzz - (xxyyz - xyyzz + xxyzz) + xxyyzz;
1321 }
1322 }
1323 if(m_calculateDissipation && globalTimeStep % m_solutionInterval == 0) {
1325 }
1326}

◆ clb_collision_step_base() [4/4]

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool useSmagorinsky>
void LbSolverDxQy< nDim, nDist, SysEqn >::clb_collision_step_base

Definition at line 587 of file lbsolverdxqy.cpp.

587 {
588 TRACE();
589 std::stringstream ss;
590 if constexpr(useSmagorinsky) {
591 ss << "CLB_SMAGORINSKY collision step not defined for d" << nDim << "q" << nDist << " !";
592 } else {
593 ss << "CLB collision step not defined for d" << nDim << "q" << nDist << " !";
594 }
595 TERMM(1, ss.str());
596}

◆ clb_smagorinsky_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::clb_smagorinsky_collision_step
override
Author
Miro Gondrum (Refactored)
Date
03.11.2021
Property value solverMethod
MAIA_LATTICE_CLB_SMAGORINSKY

This function wraps clb_collision_step_base to access CLB-Algorithm with a Smagorisnky turbulence model.

Definition at line 1352 of file lbsolverdxqy.cpp.

1352 {
1353 clb_collision_step_base<true>();
1354}

◆ controlVelocity()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::controlVelocity
virtual
Author
Daniel Lauwers
Date
June 2021

This function determines the necessary volume forces to keep periodic channel flow at a bulk velocity of u_inf.

Definition at line 504 of file lbsolverdxqy.cpp.

504 {
505 if(globalTimeStep % m_velocityControl.interval != 0) return;
506
508 m_velocityControl.dir); // m_velocityControl.dir defines the component of the velocity that is averaged
509 const MFloat velocityGoal = m_Ma / F1BCS;
510 if((m_velocityControl.lastGlobalAvgV > 5.0 * velocityGoal) || (m_velocityControl.lastGlobalAvgV < 0.0)
511 || !std::isfinite(m_velocityControl.lastGlobalAvgV)) {
512 if(domainId() == 0) cerr << "TS " << globalTimeStep << " avVel " << m_velocityControl.lastGlobalAvgV << endl;
513 m_log << "TS " << globalTimeStep << " avVel " << m_velocityControl.lastGlobalAvgV << endl;
514 TERMM(1, "Velocity control failed!");
515 }
516 const MFloat error = (m_velocityControl.lastGlobalAvgV - velocityGoal) / velocityGoal;
517 m_velocityControl.integratedError += (error + m_velocityControl.previousError) / 2.0 * m_velocityControl.interval;
518 m_velocityControl.derivedError = (error - m_velocityControl.previousError) / m_velocityControl.interval;
519
520 MFloat controlSignal = m_velocityControl.KT
521 * (error + F1 / m_velocityControl.KI * m_velocityControl.integratedError
522 + m_velocityControl.KD * m_velocityControl.derivedError);
523
524 controlSignal = mMax(mMin(controlSignal, 100.0), -100.0);
525
526 m_volumeAccel[m_velocityControl.dir] =
527 m_volumeAccelBase[m_velocityControl.dir] - controlSignal * m_volumeAccelBase[m_velocityControl.dir];
528
529 this->initVolumeForces();
530
531 stringstream ss;
532 ss << "Average velocity at TS " << globalTimeStep << " is " << m_velocityControl.lastGlobalAvgV
533 << " (goal: " << velocityGoal << ") accel set to: [" << m_volumeAccel[0] << ", " << m_volumeAccel[1];
534 if(nDim == 3) {
535 ss << ", " << m_volumeAccel[2];
536 }
537 ss << "] (base was [" << m_volumeAccelBase[0] << ", " << m_volumeAccelBase[1];
538 if(nDim == 3) {
539 ss << ", " << m_volumeAccelBase[2];
540 }
541 ss << "])" << endl;
542 ss << "Error: " << error << " previousError: " << m_velocityControl.previousError
543 << " integratedError: " << m_velocityControl.integratedError
544 << " derivedError: " << m_velocityControl.derivedError << endl;
545 if(domainId() == 0) {
546 cerr << ss.str();
547 }
548 m_log << ss.str();
549
550 m_velocityControl.previousError = error;
551}
virtual void averageGlobalVelocity(const MInt dir)
calculate average velocity of velocity component dir
void initVolumeForces() override
constexpr T mMin(const T &x, const T &y)
Definition: functions.h:90
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94

◆ cumulant_collision_step() [1/2]

void LbSolverDxQy< 3, 27, maia::lb::LbSysEqnCompressible< 3, 27 > >::cumulant_collision_step ( )

Definition at line 1371 of file lbsolverdxqy.cpp.

1371 {
1372 TRACE();
1373
1374 constexpr MInt nDist = 27;
1375
1376 constexpr MFloat omega2 = F1;
1377 constexpr MFloat omega3 = F1;
1378 constexpr MFloat omega4 = F1;
1379 constexpr MFloat omega5 = F1;
1380 constexpr MFloat omega6 = F1;
1381 constexpr MFloat omega7 = F1;
1382 constexpr MFloat omega8 = F1;
1383 constexpr MFloat omega9 = F1;
1384 constexpr MFloat omega10 = F1;
1385
1386 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
1387 const MInt gTS = globalTimeStep;
1388 const MInt maxLevel_ = maxLevel();
1389
1390 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
1391 const MInt pCellId = m_activeCellList[index];
1392 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
1393 if((gTS - 1) % IPOW2(lvlDiff) != 0) return;
1394
1395 const MFloat l_u = a_variable(pCellId, PV->U);
1396 const MFloat l_v = a_variable(pCellId, PV->V);
1397 const MFloat l_w = a_variable(pCellId, PV->W);
1398 const MFloat l_rho = a_variable(pCellId, PV->RHO);
1399
1400 // Calculation of relaxation rate
1401 //-----------------------------------------------------------------------------
1402 const MFloat tau = F1B2 + F1BCSsq * a_nu(pCellId) * FFPOW2(lvlDiff); // tau_0
1403 const MFloat omega1 = 1.0 / tau;
1404
1405 // Calculation of the central moments
1406 //-----------------------------------------------------------------------------
1407 const MFloat F1Brho = F1 / l_rho;
1408 const MFloat u[3] = {l_u, l_v, l_w};
1409 const MFloat uSq[3] = {u[0] * u[0], u[1] * u[1], u[2] * u[2]};
1410
1411 MFloat centralMoments[3][3][3] = {{{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}},
1412 {{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}},
1413 {{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}}};
1414
1415 // info: these loops are consuming (~50%)
1416 for(MInt dist = 0; dist < 27; dist++) {
1417#ifdef WAR_NVHPC_PSTL
1418 const MFloat xDir = (m_idFld[dist][0] - F1) - u[0];
1419 const MFloat yDir = (m_idFld[dist][1] - F1) - u[1];
1420 const MFloat zDir = (m_idFld[dist][2] - F1) - u[2];
1421#else
1422 const MFloat xDir = (Ld::idFld(dist, 0) - F1) - u[0];
1423 const MFloat yDir = (Ld::idFld(dist, 1) - F1) - u[1];
1424 const MFloat zDir = (Ld::idFld(dist, 2) - F1) - u[2];
1425#endif
1426 const MFloat oldDist = a_oldDistribution(pCellId, dist);
1427 const MFloat pow012[3][3] = {{F1, xDir, xDir * xDir}, {F1, yDir, yDir * yDir}, {F1, zDir, zDir * zDir}};
1428
1429 for(MInt i = 0; i < 3; i++) {
1430 for(MInt j = 0; j < 3; j++) {
1431 const MFloat tmp = pow012[0][i] * pow012[1][j] * oldDist;
1432 centralMoments[i][j][0] += pow012[2][0] * tmp;
1433 centralMoments[i][j][1] += pow012[2][1] * tmp;
1434 centralMoments[i][j][2] += pow012[2][2] * tmp;
1435 }
1436 }
1437 }
1438
1439 // Transformation of central moments in cumulants
1440 //-----------------------------------------------------------------------------
1441 MFloat cumulants[3][3][3];
1442
1443 cumulants[0][0][0] = centralMoments[0][0][0];
1444 cumulants[1][0][0] = centralMoments[1][0][0];
1445 cumulants[0][1][0] = centralMoments[0][1][0];
1446 cumulants[0][0][1] = centralMoments[0][0][1];
1447 cumulants[2][0][0] = centralMoments[2][0][0];
1448 cumulants[0][2][0] = centralMoments[0][2][0];
1449 cumulants[0][0][2] = centralMoments[0][0][2];
1450 cumulants[1][1][0] = centralMoments[1][1][0];
1451 cumulants[1][0][1] = centralMoments[1][0][1];
1452 cumulants[0][1][1] = centralMoments[0][1][1];
1453 cumulants[1][2][0] = centralMoments[1][2][0];
1454 cumulants[1][0][2] = centralMoments[1][0][2];
1455 cumulants[0][1][2] = centralMoments[0][1][2];
1456 cumulants[2][0][1] = centralMoments[2][0][1];
1457 cumulants[2][1][0] = centralMoments[2][1][0];
1458 cumulants[0][2][1] = centralMoments[0][2][1];
1459 cumulants[1][1][1] = centralMoments[1][1][1];
1460
1461 cumulants[2][1][1] =
1462 (centralMoments[2][1][1]
1463 - (centralMoments[2][0][0] * centralMoments[0][1][1] + F2 * centralMoments[1][1][0] * centralMoments[1][0][1])
1464 * F1Brho);
1465 cumulants[1][2][1] =
1466 (centralMoments[1][2][1]
1467 - (centralMoments[0][2][0] * centralMoments[1][0][1] + F2 * centralMoments[1][1][0] * centralMoments[0][1][1])
1468 * F1Brho);
1469 cumulants[1][1][2] =
1470 (centralMoments[1][1][2]
1471 - (centralMoments[0][0][2] * centralMoments[1][1][0] + F2 * centralMoments[0][1][1] * centralMoments[1][0][1])
1472 * F1Brho);
1473
1474 cumulants[2][2][0] =
1475 (centralMoments[2][2][0]
1476 - (centralMoments[2][0][0] * centralMoments[0][2][0] + F2 * centralMoments[1][1][0] * centralMoments[1][1][0])
1477 * F1Brho);
1478 cumulants[2][0][2] =
1479 (centralMoments[2][0][2]
1480 - (centralMoments[2][0][0] * centralMoments[0][0][2] + F2 * centralMoments[1][0][1] * centralMoments[1][0][1])
1481 * F1Brho);
1482 cumulants[0][2][2] =
1483 (centralMoments[0][2][2]
1484 - (centralMoments[0][0][2] * centralMoments[0][2][0] + F2 * centralMoments[0][1][1] * centralMoments[0][1][1])
1485 * F1Brho);
1486
1487 cumulants[1][2][2] =
1488 (centralMoments[1][2][2]
1489 - (centralMoments[0][0][2] * centralMoments[1][2][0] + centralMoments[0][2][0] * centralMoments[1][0][2]
1490 + F4 * centralMoments[0][1][1] * centralMoments[1][1][1]
1491 + F2
1492 * (centralMoments[1][0][1] * centralMoments[0][2][1]
1493 + centralMoments[1][1][0] * centralMoments[0][1][2]))
1494 * F1Brho);
1495 cumulants[2][1][2] =
1496 (centralMoments[2][1][2]
1497 - (centralMoments[2][0][0] * centralMoments[0][1][2] + centralMoments[0][0][2] * centralMoments[2][1][0]
1498 + F4 * centralMoments[1][0][1] * centralMoments[1][1][1]
1499 + F2
1500 * (centralMoments[1][1][0] * centralMoments[1][0][2]
1501 + centralMoments[0][1][1] * centralMoments[2][0][1]))
1502 * F1Brho);
1503 cumulants[2][2][1] =
1504 (centralMoments[2][2][1]
1505 - (centralMoments[2][0][0] * centralMoments[0][2][1] + centralMoments[0][2][0] * centralMoments[2][0][1]
1506 + F4 * centralMoments[1][1][0] * centralMoments[1][1][1]
1507 + F2
1508 * (centralMoments[1][0][1] * centralMoments[1][2][0]
1509 + centralMoments[0][1][1] * centralMoments[2][1][0]))
1510 * F1Brho);
1511
1512 const MFloat B0 =
1513 F4 * centralMoments[1][1][1] * centralMoments[1][1][1] + centralMoments[2][0][0] * centralMoments[0][2][2]
1514 + centralMoments[0][2][0] * centralMoments[2][0][2] + centralMoments[0][0][2] * centralMoments[2][2][0];
1515
1516 const MFloat B1 = centralMoments[0][1][1] * centralMoments[2][1][1]
1517 + centralMoments[1][0][1] * centralMoments[1][2][1]
1518 + centralMoments[1][1][0] * centralMoments[1][1][2];
1519
1520 const MFloat B2 = centralMoments[1][2][0] * centralMoments[1][0][2]
1521 + centralMoments[2][1][0] * centralMoments[0][1][2]
1522 + centralMoments[2][0][1] * centralMoments[0][2][1];
1523
1524 const MFloat B3 = centralMoments[1][1][0] * centralMoments[1][0][1] * centralMoments[0][1][1];
1525
1526 const MFloat B4 = centralMoments[1][0][1] * centralMoments[1][0][1] * centralMoments[0][2][0]
1527 + centralMoments[1][1][0] * centralMoments[1][1][0] * centralMoments[0][0][2]
1528 + centralMoments[0][1][1] * centralMoments[0][1][1] * centralMoments[2][0][0];
1529
1530 const MFloat B5 = centralMoments[2][0][0] * centralMoments[0][2][0] * centralMoments[0][0][2];
1531
1532 cumulants[2][2][2] = (centralMoments[2][2][2] - (F1 * B0 + F4 * B1 + F2 * B2) * F1Brho
1533 + (16.0 * B3 + F4 * B4 + F2 * B5) * F1Brho * F1Brho);
1534
1535 // Cumulant collision
1536 //-----------------------------------------------------------------------------
1537 const MFloat sum = cumulants[2][0][0] + cumulants[0][2][0] + cumulants[0][0][2];
1538 const MFloat diff1 = cumulants[2][0][0] - cumulants[0][2][0];
1539 const MFloat diff2 = cumulants[2][0][0] - cumulants[0][0][2];
1540 const MFloat Dxu =
1541 -omega1 * F1Brho * F1B2 * (diff1 + diff2) - omega2 * F1Brho * F1B2 * (sum - centralMoments[0][0][0]);
1542 const MFloat Dyv = Dxu + F3B2 * omega1 * F1Brho * diff1;
1543 const MFloat Dzw = Dxu + F3B2 * omega1 * F1Brho * diff2;
1544 const MFloat A1 = (F1 - omega1) * diff1 - F3 * l_rho * (F1 - F1B2 * omega1) * (uSq[0] * Dxu - uSq[1] * Dyv);
1545 const MFloat A2 = (F1 - omega1) * diff2 - F3 * l_rho * (F1 - F1B2 * omega1) * (uSq[0] * Dxu - uSq[2] * Dzw);
1546 const MFloat A3 = (F1 - omega2) * sum
1547 - F3 * l_rho * (F1 - F1B2 * omega2) * (uSq[0] * Dxu + uSq[1] * Dyv + uSq[2] * Dzw)
1548 + omega2 * centralMoments[0][0][0];
1549
1550 const MFloat A4 = (F1 - omega3) * (cumulants[1][2][0] + cumulants[1][0][2]);
1551 const MFloat A5 = (F1 - omega3) * (cumulants[2][1][0] + cumulants[0][1][2]);
1552 const MFloat A6 = (F1 - omega3) * (cumulants[2][0][1] + cumulants[0][2][1]);
1553 const MFloat A7 = (F1 - omega4) * (cumulants[1][2][0] - cumulants[1][0][2]);
1554 const MFloat A8 = (F1 - omega4) * (cumulants[2][1][0] - cumulants[0][1][2]);
1555 const MFloat A9 = (F1 - omega4) * (cumulants[2][0][1] - cumulants[0][2][1]);
1556
1557 const MFloat A10 = (F1 - omega6) * (cumulants[2][2][0] - F2 * cumulants[2][0][2] + cumulants[0][2][2]);
1558 const MFloat A11 = (F1 - omega6) * (cumulants[2][2][0] + cumulants[2][0][2] - F2 * cumulants[0][2][2]);
1559 const MFloat A12 = (F1 - omega7) * (cumulants[2][2][0] + cumulants[2][0][2] + cumulants[0][2][2]);
1560
1561 cumulants[1][1][0] *= (F1 - omega1);
1562 cumulants[0][1][1] *= (F1 - omega1);
1563 cumulants[1][0][1] *= (F1 - omega1);
1564 cumulants[2][0][0] = (A1 + A2 + A3) * F1B3;
1565 cumulants[0][0][2] = (A1 - F2 * A2 + A3) * F1B3;
1566 cumulants[0][2][0] = (-F2 * A1 + A2 + A3) * F1B3;
1567 cumulants[1][2][0] = (A4 + A5) * F1B2;
1568 cumulants[1][0][2] = (A4 - A5) * F1B2;
1569 cumulants[2][1][0] = (A6 + A7) * F1B2;
1570 cumulants[0][1][2] = (A6 - A7) * F1B2;
1571 cumulants[2][0][1] = (A8 + A9) * F1B2;
1572 cumulants[0][2][1] = (A8 - A9) * F1B2;
1573 cumulants[1][1][1] *= (F1 - omega5);
1574 cumulants[2][2][0] = F1B3 * (A10 + A11 + A12);
1575 cumulants[2][0][2] = F1B3 * (A12 - A10);
1576 cumulants[0][2][2] = F1B3 * (A12 - A11);
1577 cumulants[2][1][1] *= (F1 - omega8);
1578 cumulants[1][2][1] *= (F1 - omega8);
1579 cumulants[1][1][2] *= (F1 - omega8);
1580 cumulants[2][2][1] *= (F1 - omega9);
1581 cumulants[2][1][2] *= (F1 - omega9);
1582 cumulants[1][2][2] *= (F1 - omega9);
1583 cumulants[2][2][2] *= (F1 - omega10);
1584
1585 // Transformation of the cumulants in central moments
1586 //-----------------------------------------------------------------------------
1587 centralMoments[0][0][0] = cumulants[0][0][0];
1588 centralMoments[1][0][0] = -cumulants[1][0][0];
1589 centralMoments[0][1][0] = -cumulants[0][1][0];
1590 centralMoments[0][0][1] = -cumulants[0][0][1];
1591 centralMoments[1][1][0] = cumulants[1][1][0];
1592 centralMoments[1][0][1] = cumulants[1][0][1];
1593 centralMoments[0][1][1] = cumulants[0][1][1];
1594 centralMoments[2][0][0] = cumulants[2][0][0];
1595 centralMoments[0][2][0] = cumulants[0][2][0];
1596 centralMoments[0][0][2] = cumulants[0][0][2];
1597 centralMoments[2][1][0] = cumulants[2][1][0];
1598 centralMoments[2][0][1] = cumulants[2][0][1];
1599 centralMoments[0][2][1] = cumulants[0][2][1];
1600 centralMoments[1][2][0] = cumulants[1][2][0];
1601 centralMoments[1][0][2] = cumulants[1][0][2];
1602 centralMoments[0][1][2] = cumulants[0][1][2];
1603 centralMoments[1][1][1] = cumulants[1][1][1];
1604
1605 centralMoments[2][1][1] =
1606 (cumulants[2][1][1]
1607 + (centralMoments[2][0][0] * centralMoments[0][1][1] + F2 * centralMoments[1][1][0] * centralMoments[1][0][1])
1608 * F1Brho);
1609 centralMoments[1][2][1] =
1610 (cumulants[1][2][1]
1611 + (centralMoments[0][2][0] * centralMoments[1][0][1] + F2 * centralMoments[1][1][0] * centralMoments[0][1][1])
1612 * F1Brho);
1613 centralMoments[1][1][2] =
1614 (cumulants[1][1][2]
1615 + (centralMoments[0][0][2] * centralMoments[1][1][0] + F2 * centralMoments[0][1][1] * centralMoments[1][0][1])
1616 * F1Brho);
1617
1618 centralMoments[2][2][0] =
1619 (cumulants[2][2][0]
1620 + (centralMoments[2][0][0] * centralMoments[0][2][0] + F2 * centralMoments[1][1][0] * centralMoments[1][1][0])
1621 * F1Brho);
1622 centralMoments[2][0][2] =
1623 (cumulants[2][0][2]
1624 + (centralMoments[2][0][0] * centralMoments[0][0][2] + F2 * centralMoments[1][0][1] * centralMoments[1][0][1])
1625 * F1Brho);
1626 centralMoments[0][2][2] =
1627 (cumulants[0][2][2]
1628 + (centralMoments[0][0][2] * centralMoments[0][2][0] + F2 * centralMoments[0][1][1] * centralMoments[0][1][1])
1629 * F1Brho);
1630
1631 centralMoments[1][2][2] =
1632 (cumulants[1][2][2]
1633 + (centralMoments[0][0][2] * centralMoments[1][2][0] + centralMoments[0][2][0] * centralMoments[1][0][2]
1634 + F4 * centralMoments[0][1][1] * centralMoments[1][1][1]
1635 + F2
1636 * (centralMoments[1][0][1] * centralMoments[0][2][1]
1637 + centralMoments[1][1][0] * centralMoments[0][1][2]))
1638 * F1Brho);
1639 centralMoments[2][1][2] =
1640 (cumulants[2][1][2]
1641 + (centralMoments[2][0][0] * centralMoments[0][1][2] + centralMoments[0][0][2] * centralMoments[2][1][0]
1642 + F4 * centralMoments[1][0][1] * centralMoments[1][1][1]
1643 + F2
1644 * (centralMoments[1][1][0] * centralMoments[1][0][2]
1645 + centralMoments[0][1][1] * centralMoments[2][0][1]))
1646 * F1Brho);
1647 centralMoments[2][2][1] =
1648 (cumulants[2][2][1]
1649 + (centralMoments[2][0][0] * centralMoments[0][2][1] + centralMoments[0][2][0] * centralMoments[2][0][1]
1650 + F4 * centralMoments[1][1][0] * centralMoments[1][1][1]
1651 + F2
1652 * (centralMoments[1][0][1] * centralMoments[1][2][0]
1653 + centralMoments[0][1][1] * centralMoments[2][1][0]))
1654 * F1Brho);
1655
1656 const MFloat D0 =
1657 F4 * centralMoments[1][1][1] * centralMoments[1][1][1] + centralMoments[2][0][0] * centralMoments[0][2][2]
1658 + centralMoments[0][2][0] * centralMoments[2][0][2] + centralMoments[0][0][2] * centralMoments[2][2][0];
1659
1660 const MFloat D1 = centralMoments[0][1][1] * centralMoments[2][1][1]
1661 + centralMoments[1][0][1] * centralMoments[1][2][1]
1662 + centralMoments[1][1][0] * centralMoments[1][1][2];
1663
1664 const MFloat D2 = centralMoments[1][2][0] * centralMoments[1][0][2]
1665 + centralMoments[2][1][0] * centralMoments[0][1][2]
1666 + centralMoments[2][0][1] * centralMoments[0][2][1];
1667
1668 const MFloat D3 = centralMoments[1][1][0] * centralMoments[1][0][1] * centralMoments[0][1][1];
1669
1670 const MFloat D4 = centralMoments[1][0][1] * centralMoments[1][0][1] * centralMoments[0][2][0]
1671 + centralMoments[1][1][0] * centralMoments[1][1][0] * centralMoments[0][0][2]
1672 + centralMoments[0][1][1] * centralMoments[0][1][1] * centralMoments[2][0][0];
1673
1674 const MFloat D5 = centralMoments[2][0][0] * centralMoments[0][2][0] * centralMoments[0][0][2];
1675
1676 centralMoments[2][2][2] = (cumulants[2][2][2] + (F1 * D0 + F4 * D1 + F2 * D2) * F1Brho
1677 - (16.0 * D3 + F4 * D4 + F2 * D5) * F1Brho * F1Brho);
1678
1679 const MFloat coeff0[3][3] = {{(uSq[0] - u[0]) * F1B2, u[0] - F1B2, F1B2},
1680 {F1 - uSq[0], -F2 * u[0], -F1},
1681 {(uSq[0] + u[0]) * F1B2, u[0] + F1B2, F1B2}};
1682 const MFloat coeff1[3][3] = {{(uSq[1] - u[1]) * F1B2, u[1] - F1B2, F1B2},
1683 {F1 - uSq[1], -F2 * u[1], -F1},
1684 {(uSq[1] + u[1]) * F1B2, u[1] + F1B2, F1B2}};
1685 const MFloat coeff2[3][3] = {{(uSq[2] - u[2]) * F1B2, u[2] - F1B2, F1B2},
1686 {F1 - uSq[2], -F2 * u[2], -F1},
1687 {(uSq[2] + u[2]) * F1B2, u[2] + F1B2, F1B2}};
1688
1689 // info: this loop is very consuming (~30%)
1690 for(MInt dist = 0; dist < nDist; dist++) {
1691#ifdef WAR_NVHPC_PSTL
1692 const MInt i = m_idFld[dist][0];
1693 const MInt j = m_idFld[dist][1];
1694 const MInt k = m_idFld[dist][2];
1695#else
1696 const MInt i = Ld::idFld(dist, 0);
1697 const MInt j = Ld::idFld(dist, 1);
1698 const MInt k = Ld::idFld(dist, 2);
1699#endif
1700 const MFloat ki_00 = coeff0[i][0] * centralMoments[0][0][0] + coeff0[i][1] * centralMoments[1][0][0]
1701 + coeff0[i][2] * centralMoments[2][0][0];
1702 const MFloat ki_01 = coeff0[i][0] * centralMoments[0][0][1] + coeff0[i][1] * centralMoments[1][0][1]
1703 + coeff0[i][2] * centralMoments[2][0][1];
1704 const MFloat ki_02 = coeff0[i][0] * centralMoments[0][0][2] + coeff0[i][1] * centralMoments[1][0][2]
1705 + coeff0[i][2] * centralMoments[2][0][2];
1706 const MFloat ki_10 = coeff0[i][0] * centralMoments[0][1][0] + coeff0[i][1] * centralMoments[1][1][0]
1707 + coeff0[i][2] * centralMoments[2][1][0];
1708 const MFloat ki_11 = coeff0[i][0] * centralMoments[0][1][1] + coeff0[i][1] * centralMoments[1][1][1]
1709 + coeff0[i][2] * centralMoments[2][1][1];
1710 const MFloat ki_12 = coeff0[i][0] * centralMoments[0][1][2] + coeff0[i][1] * centralMoments[1][1][2]
1711 + coeff0[i][2] * centralMoments[2][1][2];
1712 const MFloat ki_20 = coeff0[i][0] * centralMoments[0][2][0] + coeff0[i][1] * centralMoments[1][2][0]
1713 + coeff0[i][2] * centralMoments[2][2][0];
1714 const MFloat ki_21 = coeff0[i][0] * centralMoments[0][2][1] + coeff0[i][1] * centralMoments[1][2][1]
1715 + coeff0[i][2] * centralMoments[2][2][1];
1716 const MFloat ki_22 = coeff0[i][0] * centralMoments[0][2][2] + coeff0[i][1] * centralMoments[1][2][2]
1717 + coeff0[i][2] * centralMoments[2][2][2];
1718
1719 const MFloat kij_0 = coeff1[j][0] * ki_00 + coeff1[j][1] * ki_10 + coeff1[j][2] * ki_20;
1720 const MFloat kij_1 = coeff1[j][0] * ki_01 + coeff1[j][1] * ki_11 + coeff1[j][2] * ki_21;
1721 const MFloat kij_2 = coeff1[j][0] * ki_02 + coeff1[j][1] * ki_12 + coeff1[j][2] * ki_22;
1722
1723 a_distribution(pCellId, dist) = coeff2[k][0] * kij_0 + coeff2[k][1] * kij_1 + coeff2[k][2] * kij_2;
1724 }
1725 });
1726}

◆ cumulant_collision_step() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::cumulant_collision_step
override
Author
Max Mustermann
Date
1.1.1870
Property value solverMethod
MAIA_LATTICE_CUMULANT

Collision step based on countable cumulants.
Ref: Geier et al. 2015, https://doi.org/10.1016/j.camwa.2015.05.001

Definition at line 1366 of file lbsolverdxqy.cpp.

1366 {
1367 TERMM(1, "Cumulant collision step only available for D3Q27, yet!");
1368}

◆ getEqDists() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDists ( const MFloat  rho,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is not already precomputed

Author
Moritz Waldmann
Parameters
[in]rhoMacroscopic density
[in]velocityMacroscopic velocity

Definition at line 668 of file lbsolverdxqy.h.

669 {
670 std::array<MFloat, nDist> eqDist{};
671#ifdef WAR_NVHPC_PSTL
672 sysEqn().calcEqDists(rho, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(), m_distFld.data());
673#else
674 sysEqn().calcEqDists(rho, velocity, eqDist.data());
675#endif
676 return eqDist;
677}

◆ getEqDists() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDists ( const MFloat  rho,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is already precomputed

Author
Moritz Waldmann
Parameters
[in]rhoMacroscopic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 691 of file lbsolverdxqy.h.

692 {
693 std::array<MFloat, nDist> eqDist{};
694#ifdef WAR_NVHPC_PSTL
695 sysEqn().calcEqDists(rho, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(),
696 m_distFld.data());
697#else
698 sysEqn().calcEqDists(rho, squaredVelocity, velocity, eqDist.data());
699#endif
700 return eqDist;
701}

◆ getEqDistsThermal() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDistsThermal ( const MFloat  t,
const MFloat  rho,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is not already precomputed

Author
Moritz Waldmann
Parameters
[in]tMacroscopic temperature
[in]rhoMacroscopic density
[in]velocityMacroscopic velocity

Definition at line 715 of file lbsolverdxqy.h.

716 {
717 if(m_innerEnergy) {
718 return getEqDistsThermal_<1>(t, rho, velocity);
719 } else if(m_totalEnergy) {
720 return getEqDistsThermal_<2>(t, rho, velocity);
721 } else {
722 return getEqDistsThermal_<0>(t, rho, velocity);
723 }
724}

◆ getEqDistsThermal() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDistsThermal ( const MFloat  t,
const MFloat  rho,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is already precomputed

Author
Moritz Waldmann
Parameters
[in]tMacroscopic temperature
[in]rhoMacroscopic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 778 of file lbsolverdxqy.h.

780 {
781 if(m_innerEnergy) {
782 return getEqDistsThermal_<1>(t, rho, squaredVelocity, velocity);
783 } else if(m_totalEnergy) {
784 return getEqDistsThermal_<2>(t, rho, squaredVelocity, velocity);
785 } else {
786 return getEqDistsThermal_<0>(t, rho, squaredVelocity, velocity);
787 }
788}

◆ getEqDistsThermal_() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt thermalMode>
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDistsThermal_ ( const MFloat  t,
const MFloat  rho,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is not already precomputed

Author
Moritz Waldmann
Template Parameters
thermalModeDetermines which equilibrium formulation is used
Parameters
[in]tMacroscopic temperature
[in]rhoMacroscopic density
[in]velocityMacroscopic velocity

Definition at line 741 of file lbsolverdxqy.h.

742 {
743 std::array<MFloat, nDist> eqDist;
744#ifdef WAR_NVHPC_PSTL
745 IF_CONSTEXPR(thermalMode == 0) {
746 lbfunc::calcEqDistsThermal<nDim, nDist>(t, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(),
747 m_distFld.data());
748 }
749 IF_CONSTEXPR(thermalMode == 1) {
750 lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(t, rho, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
751 m_tp.data(), m_distFld.data());
752 }
753 IF_CONSTEXPR(thermalMode == 2) {
754 lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(t, rho, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
755 m_tp.data(), m_distFld.data());
756 }
757#else
758 IF_CONSTEXPR(thermalMode == 0) { lbfunc::calcEqDistsThermal<nDim, nDist>(t, velocity, eqDist.data()); }
759 IF_CONSTEXPR(thermalMode == 1) { lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(t, rho, velocity, eqDist.data()); }
760 IF_CONSTEXPR(thermalMode == 2) { lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(t, rho, velocity, eqDist.data()); }
761#endif
762 return eqDist;
763}

◆ getEqDistsThermal_() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt thermalMode>
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDistsThermal_ ( const MFloat  t,
const MFloat  rho,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is already precomputed

Author
Moritz Waldmann
Template Parameters
thermalModeDetermines which equilibrium formulation is used
Parameters
[in]tMacroscopic temperature
[in]rhoMacroscopic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 806 of file lbsolverdxqy.h.

808 {
809 std::array<MFloat, nDist> eqDist;
810#ifdef WAR_NVHPC_PSTL
811 IF_CONSTEXPR(thermalMode == 0) {
812 lbfunc::calcEqDistsThermal<nDim, nDist>(t, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
813 m_tp.data(), m_distFld.data());
814 }
815 IF_CONSTEXPR(thermalMode == 1) {
816 lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(t, rho, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(),
817 m_mFld2.data(), m_tp.data(), m_distFld.data());
818 }
819 IF_CONSTEXPR(thermalMode == 2) {
820 lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(t, rho, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(),
821 m_mFld2.data(), m_tp.data(), m_distFld.data());
822 }
823#else
824 IF_CONSTEXPR(thermalMode == 0) {
825 lbfunc::calcEqDistsThermal<nDim, nDist>(t, squaredVelocity, velocity, eqDist.data());
826 }
827 IF_CONSTEXPR(thermalMode == 1) {
828 lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(t, rho, squaredVelocity, velocity, eqDist.data());
829 }
830 IF_CONSTEXPR(thermalMode == 2) {
831 lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(t, rho, squaredVelocity, velocity, eqDist.data());
832 }
833#endif
834 return eqDist;
835}

◆ getEqDistsTransport() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDistsTransport ( const MFloat  c,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is not already precomputed

Author
Moritz Waldmann
Parameters
[in]cMacroscopic transport quantity
[in]rhoMacroscopic density
[in]velocityMacroscopic velocity

Definition at line 849 of file lbsolverdxqy.h.

850 {
851 std::array<MFloat, nDist> eqDist;
852#ifdef WAR_NVHPC_PSTL
853 lbfunc::calcEqDistsTransport<nDim, nDist>(c, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(),
854 m_distFld.data());
855#else
856 lbfunc::calcEqDistsTransport<nDim, nDist>(c, velocity, eqDist.data());
857#endif
858 return eqDist;
859}

◆ getEqDistsTransport() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
std::array< MFloat, nDist > LbSolverDxQy< nDim, nDist, SysEqn >::getEqDistsTransport ( const MFloat  c,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)

Use this version if the squaredVelocity is already precomputed

Author
Moritz Waldmann
Parameters
[in]cMacroscopic transport quantity
[in]rhoMacroscopic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 874 of file lbsolverdxqy.h.

876 {
877 std::array<MFloat, nDist> eqDist;
878#ifdef WAR_NVHPC_PSTL
879 lbfunc::calcEqDistsTransport<nDim, nDist>(c, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
880 m_tp.data(), m_distFld.data());
881#else
882 lbfunc::calcEqDistsTransport<nDim, nDist>(c, squaredVelocity, velocity, eqDist.data());
883#endif
884 return eqDist;
885}

◆ initArraysForPSTL()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initArraysForPSTL

Definition at line 8853 of file lbsolverdxqy.cpp.

8853 {
8854 TRACE();
8855
8856 m_faculty.fill(-1);
8857 m_nFld.fill(-1);
8858 m_pFld.fill(-1);
8859 m_mFld1.fill(-1);
8860 m_mFld2.fill(-1);
8861 m_oppositeDist.fill(-1);
8862
8863 for(MInt i = 0; i < 50; i++) {
8864 m_faculty[i] = faculty[i];
8865 }
8866
8867 MInt fldlen = Ld::dxQyFld();
8868 for(MInt i = 0; i < fldlen; i++) {
8869 for(MInt d = 0; d < nDim; d++) {
8870 m_nFld[d * fldlen + i] = Ld::nFld(d, i);
8871 m_pFld[d * fldlen + i] = Ld::pFld(d, i);
8872 }
8873 }
8874
8875 for(MInt i = 0; i < POWX(3, nDim); i++) {
8876 for(MInt j = 0; j < POWX(3, nDim); j++) {
8877 m_idFld[i][j] = Ld::idFld(i, j);
8878 }
8879 }
8880
8881 for(MInt i = 0; i < 24; i++) {
8882 m_mFld1[i] = Ld::mFld1(i);
8883 m_mFld2[i] = Ld::mFld2(i);
8884 }
8885
8886 for(MInt i = 0; i < nDist; i++) {
8887 m_oppositeDist[i] = Ld::oppositeDist(i);
8888 }
8889
8890 for(MInt i = 0; i < 4; i++) {
8891 m_tp[i] = Ld::tp(i);
8892 }
8893
8894 for(MInt i = 0; i < 3; i++) {
8895 m_distFld[i] = Ld::distFld(i);
8896 }
8897
8898 for(MInt i = 0; i < nDist; i++) {
8899 for(MInt j = 0; j < nDim; j++) {
8900 m_ppdfDir[i * nDim + j] = Ld::ppdfDir(i, j);
8901 }
8902 }
8903
8904 for(MInt i = 0; i < nDist; i++) {
8905 m_distType[i] = Ld::distType(i);
8906 }
8907}
T constexpr POWX(T base, MUint exponent)
Compile time power calculation.
Definition: functions.h:146
static constexpr MInt oppositeDist(MInt i)

◆ initEqDistFunctions()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initEqDistFunctions
Author
Andreas Lintermann
Date
24.01.2011

Definition at line 6224 of file lbsolverdxqy.cpp.

6224 {
6225 TRACE();
6226
6227 for(MInt i = 0; i < a_noCells(); i++) {
6228 const MFloat rho = a_variable(i, PV->RHO);
6229 std::array<MFloat, nDim> u;
6230 for(MInt d = 0; d < nDim; d++) {
6231 u[d] = a_variable(i, d);
6232 }
6233 setEqDists(i, rho, u.data());
6234 }
6235}
void setEqDists(const MInt cellId, const MFloat rho, const MFloat *const velocity)
Set BOTH distributions to equilibrium.
Definition: lbsolverdxqy.h:401

◆ initializeLatticeBgk()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initializeLatticeBgk
virtual
Author
Andreas Lintermann
Date
24.01.2011

This function sets a function pointer for the right initailization method and then finally calls that method. The decision is based on the property "initMethod" and decides between an initialization with and without FFT.

Definition at line 5014 of file lbsolverdxqy.cpp.

5014 {
5015 TRACE();
5016
5017 m_log << " + Initializing flow field..." << endl;
5018 m_log << " - init method: " << m_initMethod << endl;
5019
5020 m_smallestCellLength = (this->c_cellLengthAtLevel(maxLevel())); // macroscopic cell-Length on highest level
5021 m_nu = m_Ma * LBCS / m_Re * m_referenceLength; // viscosity on highest level
5022 m_omega = 2.0 / (1.0 + 6.0 * m_nu);
5023
5024 if(m_FftInit) {
5025 m_log << " - flow init: turbulent" << endl;
5026
5027 switch(string2enum(m_initMethod)) {
5030 break;
5033 break;
5036 break;
5039 break;
5042 break;
5043 default: {
5044 m_log << "lbsolverdxqy::() unknown Init-Method type in combination with FftInit" << endl;
5045 cerr << "lbsolverdxqy::() unknown Init-Method type in combination with FftInit" << endl;
5046 DEBUG("lbsolverdxqy::() unknown Init-Method type in combination with FftInit" << endl, MAIA_DEBUG_ASSERTION);
5047 TERMM(1, "unknown Init-Method type in combination with FftInit");
5048 }
5049 }
5050 } else {
5051 m_log << " - flow init: laminar" << endl;
5052
5053 switch(string2enum(m_initMethod)) {
5056 break;
5059 break;
5062 break;
5065 break;
5068 break;
5071 break;
5072 case LB_FROM_ZERO_INIT:
5073 case LB_LAMINAR_INIT_PX:
5074 case LB_LAMINAR_INIT_MX:
5075 case LB_LAMINAR_INIT_PY:
5076 case LB_LAMINAR_INIT_MY:
5077 case LB_LAMINAR_INIT_PZ:
5078 case LB_LAMINAR_INIT_MZ:
5080 break;
5083 break;
5084 case LB_TGV_INIT:
5086 break;
5089 break;
5092 break;
5095 break;
5098 break;
5101 break;
5104 break;
5107 break;
5108 default: {
5109 m_log << "lbsolverdxqy::() unknown Init-Method type" << endl;
5110 cerr << "lbsolverdxqy::() unknown Init-Method type" << endl;
5111 DEBUG("lbsolverdxqy::() unknown Init-Method type" << endl, MAIA_DEBUG_ASSERTION);
5112 TERMM(1, "unknown Init-Method type");
5113 }
5114 }
5115 }
5116
5117 if(m_densityFluctuations)
5118 m_log << " - init density: fluctuations enanbled" << endl;
5119 else
5120 m_log << " - init density: absolute" << endl;
5121
5122 (this->*m_initMethodPtr)();
5123}
void initLatticeBgkGaussDiffusion()
virtual void initLatticeBgkTurbulentDuct()
void initLatticeBgkFftMixingFilter()
void(LbSolverDxQy< nDim, nDist, SysEqn >::* m_initMethodPtr)()
Pointers for the Boundary Conditions, for flow solving.
Definition: lbsolverdxqy.h:339
void initLatticeBgkFftChannel()
void initLatticeBgkLaminarCylinder()
virtual void initLatticeBgkTurbulentMixing()
virtual void initLatticeBgkLaminar()
virtual void initLatticeBgkTurbulentPipe()
void initLatticeBgkFftPipe()
void initLatticeBgkFftMixing()
void initLatticeBgkFftIsotropicTurbulence()
virtual void initLatticeBgkTGV()
void initLatticeBgkGaussAdvection()
virtual void initLatticeBgkVortex()
void initLatticeBgkGaussPulse()
void initLatticeBgkSpinningVorticies()
virtual void initLatticeBgkTurbulentBoundary()
virtual void initLatticeBgkLaminarChannel()
virtual void initLatticeBgkLaminarPipe()
virtual void initLatticeBgkTurbulentChannel()
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ LB_TURBULENT_MIXING_FILTER_INIT
Definition: enums.h:233
@ LB_LAMINAR_CYLINDER_INIT
Definition: enums.h:246
@ LB_GAUSS_PULSE_INIT
Definition: enums.h:250
@ LB_GAUSS_DIFFUSION_INIT
Definition: enums.h:251
@ LB_TURBULENT_BOUNDARY
Definition: enums.h:235
@ LB_TURBULENCE_ISOTROPIC_INIT
Definition: enums.h:234
@ LB_TURBULENT_CHANNEL_INIT
Definition: enums.h:231
@ LB_TURBULENT_PIPE_INIT
Definition: enums.h:236
@ LB_GAUSS_ADVECTION_INIT
Definition: enums.h:252
@ LB_LAMINAR_INIT_MX
Definition: enums.h:240
@ LB_LAMINAR_PIPE_INIT
Definition: enums.h:247
@ LB_FROM_ZERO_INIT
Definition: enums.h:238
@ LB_TURBULENT_DUCT_INIT
Definition: enums.h:237
@ LB_SPINNING_VORTICIES_INIT
Definition: enums.h:253
@ LB_CONVECTING_VORTEX_INIT
Definition: enums.h:255
@ LB_LAMINAR_INIT_PZ
Definition: enums.h:243
@ LB_TURBULENT_MIXING_INIT
Definition: enums.h:232
@ LB_TGV_INIT
Definition: enums.h:249
@ LB_LAMINAR_INIT_MY
Definition: enums.h:242
@ LB_STEADY_VORTEX_INIT
Definition: enums.h:254
@ LB_LAMINAR_INIT_MZ
Definition: enums.h:244
@ LB_LAMINAR_INIT_PY
Definition: enums.h:241
@ LB_LAMINAR_CHANNEL_INIT
Definition: enums.h:245
@ LB_LAMINAR_INIT_PX
Definition: enums.h:239

◆ initLatticeBgkFftChannel() [1/2]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::initLatticeBgkFftChannel ( )

Definition at line 7815 of file lbsolverdxqy.cpp.

7815 {
7816 TERMM(1, "Init method only available for D3Qy, yet!");
7817}

◆ initLatticeBgkFftChannel() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkFftChannel
inline
Author
Andreas Lintermann
Date
24.01.2011
Property value initMethod
LB_TURBULENT_CHANNEL_INIT

Initializes standard Lattice BGK Turbulent channel with FFT initialization. Set property "initMethod" to "LB_TURBULENT_CHANNEL_INIT" and the property "FFTInit" to "1" to use this function.

\LBIC{LbSolverDxQy::initLatticeBgkFftChannel(), initLatticeBgkFftChannel, FftChannelInit}

Definition at line 7660 of file lbsolverdxqy.cpp.

7660 {
7661 TRACE();
7662
7663 MInt xPos, yPos, zPos;
7664 MInt lx = 0, ly = 0, lz = 0;
7665
7666 // fft-domain dimensions
7667 // this holds the size of the domain in number of cells on lowest level
7668 lx = m_arraySize[0] / FPOW2(maxLevel() - minLevel());
7669 ly = m_arraySize[1] / FPOW2(maxLevel() - minLevel());
7670 if(nDim == 3) lz = m_arraySize[2] / FPOW2(maxLevel() - minLevel());
7671
7672 fftw_complex *uPhysField, *vPhysField, *wPhysField;
7673
7674 // field of velocities from positve frequencies
7675 uPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
7676 vPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
7677 wPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
7678
7679 // in multisolver mode the velocity field is created in solver 0 and broadcasted to all others
7680 ScratchSpace<MFloat> sendRecvBufferU(lx * ly * lz, AT_, "sendRecvBufferU");
7681 ScratchSpace<MFloat> sendRecvBufferV(lx * ly * lz, AT_, "sendRecvBufferV");
7682 ScratchSpace<MFloat> sendRecvBufferW(lx * ly * lz, AT_, "sendRecvBufferW");
7683
7684 if(domainId() == 0) {
7685 // create velocity field
7686 maia::math::initFft(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes, m_Ma);
7687
7688 // copy values to buffer
7689 for(MInt p = 0; p < lx; p++) {
7690 for(MInt q = 0; q < ly; q++) {
7691 for(MInt r = 0; r < lz; r++) {
7692 sendRecvBufferU[r + lz * (q + ly * p)] = uPhysField[r + lz * (q + ly * p)][0];
7693 sendRecvBufferV[r + lz * (q + ly * p)] = vPhysField[r + lz * (q + ly * p)][0];
7694 sendRecvBufferW[r + lz * (q + ly * p)] = wPhysField[r + lz * (q + ly * p)][0];
7695 }
7696 }
7697 }
7698 }
7699
7700 MPI_Bcast(&sendRecvBufferU[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferU[0]");
7701 MPI_Bcast(&sendRecvBufferV[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferV[0]");
7702 MPI_Bcast(&sendRecvBufferW[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferW[0]");
7703
7704 if(domainId() != 0) {
7705 // copy values from buffer
7706 for(MInt p = 0; p < lx; p++) {
7707 for(MInt q = 0; q < ly; q++) {
7708 for(MInt r = 0; r < lz; r++) {
7709 uPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferU[r + lz * (q + ly * p)];
7710 vPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferV[r + lz * (q + ly * p)];
7711 wPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferW[r + lz * (q + ly * p)];
7712 }
7713 }
7714 }
7715 }
7716
7717 MFloat actualCellLength;
7718 MFloat rho, u[3] = {0.0, 0.0, 0.0}, uTau, yPlus;
7719
7720 // all cells have the same density
7721 if(m_densityFluctuations)
7722 rho = 0.0;
7723 else
7724 rho = 1.0;
7725
7726 uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
7727
7728 // tmpwidth equals diameter(in cells) * cellLength on maxLevel
7729 // diameter is half the channel height!
7730 MFloat tmpWidth = m_referenceLength * m_smallestCellLength;
7731 // tmpWidth = 0.5 * fabs(bBox[4]-bBox[1]);
7732
7733 cerr << " --- prescribing mean velocity profile for turbulent channel ---" << endl;
7734 for(MInt i = 0; i < a_noCells(); i++) {
7735 initNu(i, m_nu);
7736
7737 yPlus = m_ReTau * (1.0 - fabs(a_coordinate(i, 1)) / tmpWidth);
7738
7739 // debug:
7740 if(yPlus < 0 || yPlus > m_ReTau) {
7741 stringstream errorMessage;
7742 errorMessage << "incorrect value for yPlus: " << yPlus << " exiting...";
7743 TERMM(1, errorMessage.str());
7744 }
7745
7746 // set the mean velocity profile
7747 if(yPlus <= 5.0) {
7748 u[0] = uTau * yPlus;
7749 } else {
7750 if(yPlus <= 30 && yPlus > 5.0) {
7751 u[0] = uTau * (C1 * log(yPlus) + C2);
7752 } else {
7753 if(yPlus > 30) {
7754 u[0] = uTau * (C3 * log(yPlus) + C4);
7755 }
7756 }
7757 }
7758
7759 u[1] = 0.0;
7760 u[2] = 0.0;
7761
7762 actualCellLength = this->grid().cellLengthAtCell(i);
7763
7764 xPos = floor(
7765 (F1B2 * lx + (a_coordinate(i, 0) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
7766 yPos = floor(
7767 (F1B2 * ly + (a_coordinate(i, 1) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
7768 zPos = floor(
7769 (F1B2 * lz + (a_coordinate(i, 2) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
7770
7771 if(xPos > lx - 1 || xPos < 0 || yPos > ly - 1 || yPos < 0 || zPos > lz - 1 || zPos < 0) {
7772 cerr << "ERROR: wrong array position!" << endl;
7773 cerr << "pos=" << xPos << ", " << yPos << ", " << zPos << endl;
7774 cerr << "coorda = (" << a_coordinate(i, 2) << ", " << a_coordinate(i, 2) << ", " << a_coordinate(i, 2) << ")"
7775 << endl;
7776 cerr << "actuallength=" << actualCellLength << ", smallestlength=" << m_smallestCellLength << endl;
7777 cerr << "minlevel=" << minLevel() << ", maxLevel=" << maxLevel() << endl;
7778 cerr << "lenght on level0=" << this->c_cellLengthAtLevel(0) << endl;
7779 TERMM(1, "Wrong array position");
7780 }
7781
7782 // add normalized real parts of fluctuations
7783 u[0] += uPhysField[zPos + lz * (yPos + ly * xPos)][0];
7784 u[1] += vPhysField[zPos + lz * (yPos + ly * xPos)][0];
7785 u[2] += wPhysField[zPos + lz * (yPos + ly * xPos)][0];
7786
7787 // // add normalized real parts of fluctuations factorized by u_mean/u_max
7788 // u[0] += uPhysField[zPos+lz*(yPos+ly*xPos)][0] * u[0]/(uTau * (C3*log(m_ReTau)+C4));
7789 // u[1] += vPhysField[zPos+lz*(yPos+ly*xPos)][0] * u[0]/(uTau * (C3*log(m_ReTau)+C4));
7790 // u[2] += wPhysField[zPos+lz*(yPos+ly*xPos)][0] * u[0]/(uTau * (C3*log(m_ReTau)+C4));
7791
7792 a_variable(i, PV->RHO) = rho;
7793 a_oldVariable(i, PV->RHO) = rho;
7794 // cells[i].m_oldVariablesT1[PV->RHO] = rho;
7795 a_variable(i, PV->U) = u[0];
7796 a_oldVariable(i, PV->U) = u[0];
7797 // cells[i].m_oldVariablesT1[PV->U] = u[0];
7798 a_variable(i, PV->V) = u[1];
7799 a_oldVariable(i, PV->V) = u[1];
7800 // cells[i].m_oldVariablesT1[PV->V] = u[1];
7801 a_variable(i, PV->W) = u[2];
7802 a_oldVariable(i, PV->W) = u[2];
7803 // cells[i].m_oldVariablesT1[PV->W] = u[2];
7804 }
7805
7806 // initialize distr. functions
7808
7809 // Free the FFTW memory
7810 fftw_free(uPhysField);
7811 fftw_free(vPhysField);
7812 fftw_free(wPhysField);
7813}
void initEqDistFunctions()
Calculates equilibrium distribution functions after initialization of macroscopic variables.
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
void initFft(fftw_complex *uPhysField, fftw_complex *vPhysField, fftw_complex *wPhysField, MInt lx, MInt ly, MInt lz, MInt noPeakModes, const MFloat Ma)
Generates a velocity field from Fourier-modes using FFTW.
Definition: maiafftw.h:892

◆ initLatticeBgkFftIsotropicTurbulence() [1/2]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::initLatticeBgkFftIsotropicTurbulence ( )

Definition at line 8847 of file lbsolverdxqy.cpp.

8847 {
8848 mTerm(1, AT_, "Init method only available for D3Qy, yet!");
8849}
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29

◆ initLatticeBgkFftIsotropicTurbulence() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkFftIsotropicTurbulence
inline
Author
Johannes Grafen adapeted from version of Lennart Schneiders
Date
10.02.2022
Property value initMethod
LB_TURBULENCE_ISOTROPIC_INIT

Creates isotropic Turbulence in box shaped domain, adapted from FV In comparison to FV, where the pressure field is calulated by solving a poisson equation for the pressure in fourier-transformed wavespace, an iterative initialization run for the initialization of the pressure/density field is necessary. See function: initRunCorrection()

\LBIC{LbSolverDxQy::initLatticeBgkFftIsotropicTurbulence(), initLatticeBgkFftIsotropicTurbulence, FftIsotropicTurbulenceInit}

Definition at line 8341 of file lbsolverdxqy.cpp.

8341 {
8342 TRACE();
8343 // adapted from FV:
8344 IF_CONSTEXPR(nDim == 2) TERMM(-1, "Only works for 3D!");
8345 const MFloat time0 = MPI_Wtime();
8346 const MInt fftLevel = grid().maxUniformRefinementLevel();
8347 const MFloat DX = c_cellLengthAtLevel(fftLevel);
8348 if(fftLevel > grid().maxUniformRefinementLevel()) {
8349 mTerm(1, AT_, "Isotropic mesh expected (0).");
8350 }
8351 MInt noVars = nDim + 1; // U, V, W, RHO
8352
8353 std::array<MFloat, nDim * 2> bBox;
8354 m_geometry->getBoundingBox(bBox.data());
8355
8356 /* if(Context::propertyExists("cutOffCoordinates", m_solverId)) {
8357 for(MInt i = 0; i < nDim; i++) {
8358 bBox[i] = numeric_limits<MInt>::max();
8359 bBox[nDim + i] = numeric_limits<MInt>::min();
8360 }
8361 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8362 if(a_isHalo(cellId)) continue;
8363 //if(a_isPeriodic(cellId)) continue;
8364 if(a_isBndryGhostCell(cellId)) continue;
8365 for(MInt i = 0; i < nDim; i++) {
8366 bBox[i] = mMin(bBox[i], a_coordinate(cellId, i) - F1B2 * c_cellLengthAtCell(cellId));
8367 bBox[nDim + i] = mMax(bBox[nDim + i], a_coordinate(cellId, i) + F1B2 * c_cellLengthAtCell(cellId));
8368 }
8369 }
8370 MPI_Allreduce(MPI_IN_PLACE, &bBox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE", "bBox[0]");
8371 MPI_Allreduce(MPI_IN_PLACE, &bBox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
8372 "bBox[nDim]");
8373 } */
8374
8375 // fft-domain dimensions
8376 // this holds the size of the domain in number of cells on lowest level
8377
8378 const MFloat dxeps = 0.1 * DX;
8379 MInt nx = (bBox[3] - bBox[0] + dxeps) / DX;
8380 MInt ny = (bBox[4] - bBox[1] + dxeps) / DX;
8381 MInt nz = (bBox[5] - bBox[2] + dxeps) / DX;
8382 const MInt size = nx * ny * nz;
8383
8384 getReLambdaAndUrmsInit();
8385 if(domainId() == 0) cerr << "UrmsInit: " << m_UrmsInit << endl << "ReLambdaInit: " << m_ReLambda << endl;
8386
8387 // consistency check
8388 const MFloat nuCheck = m_referenceLength * m_UrmsInit / m_Re;
8389 if(abs(nuCheck - m_nu) > 0.01 * m_nu) // 1% difference is tolerated between nuCheck and nuLb
8390 mTerm(1, AT_, "nu_LB and nu_check are not consistent! Check Re, Ma and UrmsInit");
8391
8392 MFloat rhoInfinity = F1;
8393 MFloat UInfinity = m_UrmsInit; // equal to m_Ma * LBCS
8394
8395 MBool goodSpectrum = false;
8396 MUlong seed = 0;
8397
8398 MInt spectrumId = 2; // prescribed energy spectrum, see maiamath.cpp
8399 spectrumId = Context::getSolverProperty<MInt>("spectrumId", this->m_solverId, AT_, &spectrumId);
8400 MFloat kpRatio = F4; // peak wave number of prescribed spectrum
8401 kpRatio = Context::getSolverProperty<MFloat>("kpRatio", this->m_solverId, AT_, &kpRatio);
8402
8403 while(!goodSpectrum) {
8404 fftw_complex* uPhysField;
8405 fftw_complex* nabla2P = nullptr;
8406 MIntScratchSpace fftInfo(4, AT_, "fftInfo");
8407
8408 seed = maia::math::initFft(uPhysField, nabla2P, nx, ny, nz, kpRatio, spectrumId, fftInfo, mpiComm(),
8409 false); // Using method of Lennart Schneiders, not Ma-number dependent
8410
8411 if(domainId() == 0) {
8412 std::cerr << "Theoretical SPECTRUM: kinetic energy: " << 1.5 * POW2(m_UrmsInit)
8413 << ", dissipation rate * Box length / Urms,0^3: "
8414 << 72.0 * POW2(kpRatio * PI) * m_nu / (m_UrmsInit * nx) << ")"
8415 << ", integral length/unit length: " << F3B8 / kpRatio << ")" << std::endl;
8416 }
8417
8418 MInt maxRank = fftInfo[0];
8419 MInt local_n0 = fftInfo[1];
8420 MInt local_0_start = fftInfo[2];
8421 MInt alloc_local = fftInfo[3];
8422
8423 MIntScratchSpace noSendIds(globalNoDomains(), AT_, "noSendIds");
8424 MInt sendIdsSize = 0;
8425 MIntScratchSpace offsetsIds(globalNoDomains() + 1, AT_, "offsetsIds");
8426 MInt locOffsetIds = (globalDomainId() < maxRank) ? ((MInt)local_0_start) * ny * nz : size;
8427 MPI_Allgather(&locOffsetIds, 1, MPI_INT, &offsetsIds[0], 1, MPI_INT, mpiComm(), AT_, "locOffsetIds",
8428 "offsetsIds[0]");
8429 offsetsIds(globalNoDomains()) = size;
8430 noSendIds.fill(0);
8431
8432 // Count no of sendIds
8433 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8434 if(a_isHalo(cellId)) continue;
8435 if(a_isBndryGhostCell(cellId)) continue;
8436 if(a_level(cellId) != fftLevel) continue;
8437 MFloat actualCellLength = grid().cellLengthAtLevel(a_level(cellId));
8438 MInt xPos = floor((F1B2 * nx + (a_coordinate(cellId, 0) - F1B2 * (actualCellLength)) / DX) + 0.1);
8439 MInt yPos = floor((F1B2 * ny + (a_coordinate(cellId, 1) - F1B2 * (actualCellLength)) / DX) + 0.1);
8440 MInt zPos = floor((F1B2 * nz + (a_coordinate(cellId, 2) - F1B2 * (actualCellLength)) / DX) + 0.1);
8441 MInt pos = maia::math::getGlobalPosFFTW(xPos, yPos, zPos, ny, nz);
8442 MInt nghbrDomain = mMin(maxRank - 1, pos / (size / maxRank));
8443 while(pos < offsetsIds(nghbrDomain) || pos >= offsetsIds(nghbrDomain + 1)) {
8444 if(pos < offsetsIds(nghbrDomain)) nghbrDomain--;
8445 if(pos >= offsetsIds(nghbrDomain + 1)) nghbrDomain++;
8446 }
8447 if(nghbrDomain >= maxRank) mTerm(1, AT_, "wrong domain");
8448 noSendIds(nghbrDomain)++;
8449 sendIdsSize++;
8450 }
8451 MIntScratchSpace sendIdsOffsets(globalNoDomains(), AT_, "sendIdsOffsets");
8452 MIntScratchSpace sendIdsOffsetsTmp(globalNoDomains(), AT_, "sendIdsOffsetsTmp");
8453 sendIdsOffsets[0] = 0;
8454 sendIdsOffsetsTmp[0] = 0;
8455 for(MInt nghbrDomain = 0; nghbrDomain < globalNoDomains() - 1; nghbrDomain++) {
8456 sendIdsOffsets[nghbrDomain + 1] = sendIdsOffsets[nghbrDomain] + noSendIds[nghbrDomain];
8457 sendIdsOffsetsTmp[nghbrDomain + 1] = sendIdsOffsets[nghbrDomain] + noSendIds[nghbrDomain];
8458 }
8459 MIntScratchSpace sendIds(sendIdsSize, AT_, "sendIdsSize");
8460
8461 // Fill sendIds
8462 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8463 if(a_isHalo(cellId)) continue;
8464 if(a_isBndryGhostCell(cellId)) continue;
8465 if(a_level(cellId) != fftLevel) continue;
8466 MFloat actualCellLength = grid().cellLengthAtLevel(a_level(cellId));
8467 MInt xPos = floor((F1B2 * nx + (a_coordinate(cellId, 0) - F1B2 * (actualCellLength)) / DX) + 0.1);
8468 MInt yPos = floor((F1B2 * ny + (a_coordinate(cellId, 1) - F1B2 * (actualCellLength)) / DX) + 0.1);
8469 MInt zPos = floor((F1B2 * nz + (a_coordinate(cellId, 2) - F1B2 * (actualCellLength)) / DX) + 0.1);
8470 MInt pos = maia::math::getGlobalPosFFTW(xPos, yPos, zPos, nx, ny);
8471 MInt nghbrDomain = mMin(maxRank - 1, pos / (size / maxRank));
8472 while(pos < offsetsIds(nghbrDomain) || pos >= offsetsIds(nghbrDomain + 1)) {
8473 if(pos < offsetsIds(nghbrDomain)) nghbrDomain--;
8474 if(pos >= offsetsIds(nghbrDomain + 1)) nghbrDomain++;
8475 }
8476 if(nghbrDomain >= maxRank) mTerm(1, AT_, "wrong domain");
8477 sendIds[sendIdsOffsetsTmp[nghbrDomain]++] = pos;
8478 }
8479 MIntScratchSpace noRecvIds(globalNoDomains(), AT_, "noRecvIds");
8480 noRecvIds.fill(0);
8481 MPI_Alltoall(&noSendIds[0], 1, MPI_INT, &noRecvIds[0], 1, MPI_INT, mpiComm(), AT_, "noSendIds[0]", "noRecvIds[0]");
8482
8483 MIntScratchSpace recvIdsOffsets(globalNoDomains(), AT_, "recvIdsOffsets");
8484 recvIdsOffsets[0] = 0;
8485 MInt recvIdsSize = 0;
8486 for(MInt nghbrDomain = 0; nghbrDomain < globalNoDomains() - 1; nghbrDomain++) {
8487 recvIdsOffsets[nghbrDomain + 1] = recvIdsOffsets[nghbrDomain] + noRecvIds[nghbrDomain];
8488 recvIdsSize += noRecvIds[nghbrDomain];
8489 }
8490 recvIdsSize += noRecvIds[globalNoDomains() - 1];
8491
8492 // Exchange Ids
8493 MIntScratchSpace recvIds(mMax(1, recvIdsSize), AT_, "recvIds");
8494 MPI_Alltoallv(&sendIds[0], &noSendIds[0], &sendIdsOffsets[0], MPI_INT, &recvIds[0], &noRecvIds[0],
8495 &recvIdsOffsets[0], MPI_INT, mpiComm(), AT_, "sendIds[0]", "recvIds[0]");
8496
8497 MIntScratchSpace sendVarsOffsets(globalNoDomains(), AT_, "sendVarsOffsets");
8498 MIntScratchSpace sendVarsOffsetsTmp(globalNoDomains(), AT_, "sendVarsOffsetsTmp");
8499 MIntScratchSpace noSendVars(globalNoDomains(), AT_, "noSendVars");
8500 sendVarsOffsets[0] = 0;
8501 sendVarsOffsetsTmp[0] = 0;
8502 MInt sendVarsSize = 0;
8503 for(MInt i = 0; i < globalNoDomains() - 1; i++) {
8504 sendVarsOffsets[i + 1] = sendVarsOffsets[i] + noRecvIds[i] * 3;
8505 sendVarsOffsetsTmp[i + 1] = sendVarsOffsetsTmp[i] + noRecvIds[i] * 3;
8506 noSendVars[i] = noRecvIds[i] * 3;
8507 sendVarsSize += noRecvIds[i] * 3;
8508 }
8509 if(recvIdsSize != 0) {
8510 noSendVars[globalNoDomains() - 1] = noRecvIds[globalNoDomains() - 1] * 3;
8511 sendVarsSize += noRecvIds[globalNoDomains() - 1] * 3;
8512 }
8513
8514 // Fill sendVars: for each Id received 3 variables have to be send
8515 MFloatScratchSpace sendVars(mMax(1, sendVarsSize), AT_, "sendVars");
8516 sendVars.fill(0);
8517 MFloat cnt = F0;
8518 MFloat upr[3] = {F0, F0, F0};
8519 for(MInt i = 0; i < recvIdsSize; i++) {
8520 MInt pos = recvIds[i];
8521 ASSERT(pos > -1 && pos < size, "");
8522 if(!(pos >= ((MInt)local_0_start) * nx * ny && pos < ((MInt)(local_0_start + local_n0) * ny * nx))) {
8523 mTerm(1, AT_, "Position not available on this domain(1).");
8524 }
8525 MInt localPos = pos - (((MInt)local_0_start) * ny * nz);
8526 if(3 * localPos + 2 > alloc_local) {
8527 mTerm(1, AT_, "index exceeds array(1)");
8528 }
8529 sendVars[i * 3] = uPhysField[3 * localPos][0];
8530 sendVars[i * 3 + 1] = uPhysField[3 * localPos + 1][0];
8531 sendVars[i * 3 + 2] = uPhysField[3 * localPos + 2][0];
8532
8533 MFloat u = uPhysField[3 * localPos][0];
8534 MFloat v = uPhysField[3 * localPos + 1][0];
8535 MFloat w = uPhysField[3 * localPos + 2][0];
8536 upr[0] += POW2(u);
8537 upr[1] += POW2(v);
8538 upr[2] += POW2(w);
8539 cnt++;
8540 }
8541
8542 MPI_Allreduce(MPI_IN_PLACE, &cnt, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "cnt");
8543 MPI_Allreduce(MPI_IN_PLACE, &upr, 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "upr");
8544
8545 MFloat uprime0 = sqrt(F1B3 * (upr[0] + upr[1] + upr[2]) / cnt);
8546
8547 fftw_free(uPhysField);
8548
8549 MIntScratchSpace recvVarsOffsets(globalNoDomains(), AT_, "recvVarsOffsets");
8550 MIntScratchSpace noRecvVars(globalNoDomains(), AT_, "noRecvVars");
8551 recvVarsOffsets[0] = 0;
8552 MInt recvVarsSize = 0;
8553 for(MInt i = 0; i < globalNoDomains() - 1; i++) {
8554 recvVarsOffsets[i + 1] = recvVarsOffsets[i] + noSendIds[i] * 3;
8555 noRecvVars[i] = noSendIds[i] * 3;
8556 recvVarsSize += noSendIds[i] * 3;
8557 }
8558 recvVarsSize += noSendIds[globalNoDomains() - 1] * 3;
8559 noRecvVars[globalNoDomains() - 1] = noSendIds[globalNoDomains() - 1] * 3;
8560
8561 // Exchange Variables
8562 MFloatScratchSpace recvVars(recvVarsSize, AT_, "recvVars");
8563 recvVars.fill(0);
8564 MPI_Alltoallv(&sendVars[0], &noSendVars[0], &sendVarsOffsets[0], MPI_DOUBLE, &recvVars[0], &noRecvVars[0],
8565 &recvVarsOffsets[0], MPI_DOUBLE, mpiComm(), AT_, "sendVars[0]", "recvVars[0]");
8566
8567 cnt = F0;
8568 upr[0] = 0;
8569 upr[1] = 0;
8570 upr[2] = 0;
8571 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8572 if(a_isHalo(cellId)) continue;
8573 if(a_isBndryGhostCell(cellId)) continue;
8574 if(a_level(cellId) != fftLevel) continue;
8575 MFloat actualCellLength = grid().cellLengthAtLevel(a_level(cellId));
8576 MInt xPos = floor((F1B2 * nx + (a_coordinate(cellId, 0) - F1B2 * (actualCellLength)) / DX) + 0.1);
8577 MInt yPos = floor((F1B2 * ny + (a_coordinate(cellId, 1) - F1B2 * (actualCellLength)) / DX) + 0.1);
8578 MInt zPos = floor((F1B2 * nz + (a_coordinate(cellId, 2) - F1B2 * (actualCellLength)) / DX) + 0.1);
8579 MInt pos = maia::math::getGlobalPosFFTW(xPos, yPos, zPos, nx, ny);
8580 MInt nghbrDomain = mMin(maxRank - 1, pos / (size / maxRank));
8581 while(pos < offsetsIds(nghbrDomain) || pos >= offsetsIds(nghbrDomain + 1)) {
8582 if(pos < offsetsIds(nghbrDomain)) nghbrDomain--;
8583 if(pos >= offsetsIds(nghbrDomain + 1)) nghbrDomain++;
8584 }
8585 if(nghbrDomain >= maxRank) mTerm(1, AT_, "wrong domain");
8586 if(sendIds[sendIdsOffsets[nghbrDomain]] != pos) mTerm(1, AT_, "pos mismatch");
8587 MFloat u = recvVars[sendIdsOffsets[nghbrDomain] * 3];
8588 MFloat v = recvVars[sendIdsOffsets[nghbrDomain] * 3 + 1];
8589 MFloat w = recvVars[sendIdsOffsets[nghbrDomain] * 3 + 2];
8590
8591 sendIdsOffsets[nghbrDomain]++;
8592 upr[0] += POW2(u);
8593 upr[1] += POW2(v);
8594 upr[2] += POW2(w);
8595 a_variable(cellId, PV->U) = u;
8596 a_variable(cellId, PV->V) = v;
8597 a_variable(cellId, PV->W) = w;
8598 a_variable(cellId, PV->RHO) = rhoInfinity; // is going to be iterated
8599 cnt++;
8600 }
8601
8602
8603 MPI_Allreduce(MPI_IN_PLACE, &cnt, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "cnt");
8604 MPI_Allreduce(MPI_IN_PLACE, &upr, 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "upr");
8605
8606 MFloat uprime1 = sqrt(F1B3 * (upr[0] + upr[1] + upr[2]) / cnt);
8607 upr[0] = sqrt(upr[0] / cnt);
8608 upr[1] = sqrt(upr[1] / cnt);
8609 upr[2] = sqrt(upr[2] / cnt);
8610
8611 if(fabs(uprime0 - uprime1) > exp(-10)) mTerm(1, AT_, "Communication went wrong.");
8612
8613 if(domainId() == 0)
8614 cerr << "initial urpime: " << upr[0] << " " << upr[1] << " " << upr[2] << " (" << uprime1 << ")" << endl;
8615
8616 // for LES: The initial spectrum is cut off for coarse LES grids which
8617 // results into a lower energy level. If uprime != 1, this energy
8618 // will be modified such that all resolved scales have the DNS-energy,
8619 // i.e. large scales get the energy which have been cut off at the small
8620 // scales.
8621
8622 // uprime1 = F1;
8623
8624 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8625 if(a_isHalo(cellId)) continue;
8626 if(a_isBndryGhostCell(cellId)) continue;
8627 if(a_level(cellId) != fftLevel) continue;
8628 // scale velocities such that mean urms is UInfinity, scaling with velocity magnitude of UrmsInit
8629 MFloat u = a_variable(cellId, PV->U) * UInfinity / uprime1;
8630 MFloat v = a_variable(cellId, PV->V) * UInfinity / uprime1;
8631 MFloat w = a_variable(cellId, PV->W) * UInfinity / uprime1;
8632
8633 a_variable(cellId, PV->U) = u;
8634 a_variable(cellId, PV->V) = v;
8635 a_variable(cellId, PV->W) = w;
8636 }
8637
8638 exchangeData(&a_variable(0, 0), noVars);
8639
8640 MFloat umean[3] = {F0, F0, F0};
8641 MFloat urms[6] = {F0, F0, F0, F0, F0, F0};
8642 MFloat reyn[6] = {F0, F0, F0, F0, F0, F0};
8643 MFloat aniso[6] = {F0, F0, F0, F0, F0, F0};
8644 MFloat dudx[3] = {F0, F0, F0};
8645 MFloat skew[4] = {F0, F0, F0, F0};
8646 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8647 if(a_isHalo(cellId)) continue;
8648 if(a_isBndryGhostCell(cellId)) continue;
8649 if(a_level(cellId) != fftLevel) continue;
8650 MFloat u = a_variable(cellId, PV->U);
8651 MFloat v = a_variable(cellId, PV->V);
8652 MFloat w = a_variable(cellId, PV->W);
8653 for(MInt i = 0; i < nDim; i++) {
8654 MInt n0 = (a_hasNeighbor(cellId, 2 * i) > 0) ? c_neighborId(cellId, 2 * i) : cellId;
8655 MInt n1 = (a_hasNeighbor(cellId, 2 * i + 1) > 0) ? c_neighborId(cellId, 2 * i + 1) : cellId;
8656 if(n0 == n1) continue;
8657 dudx[i] += POW2((a_variable(n1, PV->VV[i]) - a_variable(n0, PV->VV[i]))
8658 / ((a_coordinate(n1, i) - a_coordinate(n0, i)) / DX));
8659 skew[i] += POW3((a_variable(n1, PV->VV[i]) - a_variable(n0, PV->VV[i]))
8660 / ((a_coordinate(n1, i) - a_coordinate(n0, i)) / DX));
8661 }
8662 urms[0] += POW2(u);
8663 urms[1] += POW2(v);
8664 urms[2] += POW2(w);
8665 urms[3] += u * v;
8666 urms[4] += u * w;
8667 urms[5] += v * w;
8668 umean[0] += u;
8669 umean[1] += v;
8670 umean[2] += w;
8671 }
8672 MPI_Allreduce(MPI_IN_PLACE, &urms[0], 6, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "urms[0]");
8673 MPI_Allreduce(MPI_IN_PLACE, &umean[0], 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "umean[0]");
8674 MPI_Allreduce(MPI_IN_PLACE, &dudx[0], 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "dudx[0]");
8675 MPI_Allreduce(MPI_IN_PLACE, &skew[0], 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "skew[0]");
8676 skew[3] = ((skew[0] + skew[1] + skew[2]) / (F3 * cnt)) / pow((dudx[0] + dudx[1] + dudx[2]) / (F3 * cnt), 1.5);
8677 for(MInt i = 0; i < 3; i++)
8678 skew[i] = (skew[i] / cnt) / pow(dudx[i] / cnt, 1.5);
8679 for(MInt i = 0; i < 6; i++)
8680 reyn[i] = urms[i] / cnt;
8681 for(MInt i = 0; i < 6; i++)
8682 aniso[i] = urms[i] / (urms[0] + urms[1] + urms[2]);
8683 for(MInt i = 0; i < 3; i++)
8684 aniso[i] -= F1B3;
8685 for(MInt i = 0; i < 6; i++)
8686 urms[i] = sqrt(fabs(urms[i]) / cnt);
8687 for(MInt i = 0; i < 3; i++)
8688 umean[i] /= cnt;
8689 for(MInt i = 0; i < 3; i++)
8690 dudx[i] /= cnt;
8691 MFloat lambda[3];
8692 MFloat Rel[4];
8693 MFloat eps[3];
8694 for(MInt i = 0; i < 3; i++)
8695 lambda[i] = urms[i] / sqrt(dudx[i]); // Eq. 6.56 Turbulent Flows Pope two-point correlation
8696
8697 if(domainId() == 0)
8698 cerr << "u_mean: " << umean[0] << " " << umean[1] << " " << umean[2] << " (" << (MInt)cnt << ")" << endl;
8699 if(domainId() == 0)
8700 cerr << "u_rms/u_inf: " << urms[0] / UInfinity << " " << urms[1] / UInfinity << " " << urms[2] / UInfinity << " "
8701 << urms[3] / UInfinity << " " << urms[4] / UInfinity << " " << urms[5] / UInfinity << " ("
8702 << F1B3 * (urms[0] + urms[1] + urms[2]) / UInfinity << ")" << endl;
8703 if(domainId() == 0)
8704 cerr << "skewness: " << skew[0] << " " << skew[1] << " " << skew[2] << " (" << skew[3] << ")" << endl;
8705 if(domainId() == 0)
8706 cerr << "Anisotropy: " << aniso[0] << " " << aniso[1] << " " << aniso[2] << " " << aniso[3] << " " << aniso[4]
8707 << " " << aniso[5] << endl;
8708 if(domainId() == 0)
8709 cerr << "Reynolds stress: " << reyn[0] << " " << reyn[1] << " " << reyn[2] << " " << reyn[3] << " " << reyn[4]
8710 << " " << reyn[5] << endl;
8711 if(domainId() == 0)
8712 cerr << "Realizability 1: " << reyn[3] * reyn[3] << " <= " << reyn[0] * reyn[1] << ", " << reyn[4] * reyn[4]
8713 << " <= " << reyn[0] * reyn[2] << ", " << reyn[5] * reyn[5] << " <= " << reyn[1] * reyn[2] << endl;
8714 if(domainId() == 0)
8715 cerr << "Realizability 2: det = "
8716 << reyn[0] * reyn[1] * reyn[2] + F2 * reyn[3] * reyn[4] * reyn[5] - reyn[0] * reyn[5] * reyn[5]
8717 - reyn[1] * reyn[4] * reyn[4] - reyn[2] * reyn[4] * reyn[4]
8718 << " >= 0" << endl;
8719
8720 // prescribe Taylor microscale Reynolds number
8721 // for LES: ReLambda is unkown in LES and has to be defined to get the
8722 // same viscosity as in the DNS.
8723 const MFloat time1 = MPI_Wtime();
8724 m_log << "initFFT time " << time1 - time0 << endl;
8725
8726 /*if(nx < 64) { // nx < 256 -> for LES, DNS requires refinement level of 8 or higher?
8727 ! \page propertyPage1
8728 \section ReLambdaOverwrite
8729 <code>MInt FvCartesianSolverXD::m_Re</code>\n
8730 default = <code>none</code>\n \n
8731 Overwrite Reynolds number for FV isotropic turbulence spectrum initial condition (case
8732 16). \n \n
8733 Possible values are:
8734 <ul>
8735 <li>Any positive floating point value</li>
8736 </ul>
8737 Keywords: <i>FINITE_VOLUME, INITIAL_CONDITION, ISOTROPIC, TURBULENCE</i>
8738
8739 if(!Context::propertyExists("ReLambdaOverwrite", this->m_solverId)) {
8740 mTerm(1, AT_, "Undefined ReLambda for LES grid.");
8741 }
8742 m_Re = Context::getSolverProperty<MFloat>("ReLambdaOverwrite", this->m_solverId, AT_) / m_referenceLength;
8743 Re0 = m_Re * m_nu * rhoInfinity / (rhoInfinity * UInfinity);
8744 m_log << "Overwritten Reynolds number: " << setprecision(15) << m_Re
8745 << " (Re_L=" << m_Re * (bBox[3] - bBox[0]) << ")"
8746 << " " << Re0 << endl;
8747 break;
8748 }*/
8749
8750 for(MInt i = 0; i < 3; i++)
8751 Rel[i] = urms[i] * lambda[i] / m_nu;
8752 Rel[3] = F1B3 * (urms[0] + urms[1] + urms[2]) * F1B3 * (lambda[0] + lambda[1] + lambda[2]) / m_nu;
8753
8754 if(domainId() == 0) {
8755 cerr << "Re_lambda: " << Rel[0] << " " << Rel[1] << " " << Rel[2] << " (" << Rel[3] << ", "
8756 << F1B3 * (Rel[0] + Rel[1] + Rel[2]) << ")" << endl;
8757
8758 const MFloat lambdaAvg = F1B3 * (lambda[0] + lambda[1] + lambda[2]);
8759 cerr << "lambda: " << lambda[0] << " " << lambda[1] << " " << lambda[2] << " (" << lambdaAvg << ") "
8760 << "lambda / Lb: " << lambdaAvg / m_referenceLength << endl;
8761 }
8762
8763 MFloat eps2[3];
8764 for(MInt i = 0; i < 3; i++) {
8765 eps[i] = (15.0 * m_nu * dudx[i]) * m_referenceLength / POW3(urms[i]);
8766 eps2[i] = 15.0 * m_nu * POW2(urms[i] / lambda[i]); // Eq. 6.58 Turbulent Flows Pope two-point correlation
8767 }
8768
8769 if(domainId() == 0) {
8770 cerr << "eps: " << eps[0] << " " << eps[1] << " " << eps[2] << " (" << F1B3 * (eps[0] + eps[1] + eps[2]) << ")"
8771 << endl;
8772
8773 const MFloat eps2Avg = F1B3 * (eps2[0] + eps2[1] + eps2[2]);
8774 cerr << "eps2: " << eps2[0] << " " << eps2[1] << " " << eps2[2] << " (" << eps2Avg << ")"
8775 << " eps2 * Box length / Urms,0^3: " << eps2Avg * m_referenceLength / POW3(m_UrmsInit) << endl;
8776
8777 const MFloat eta =
8778 pow(m_nu, 0.75)
8779 / pow(F1B3 * (eps2[0] + eps2[1] + eps2[2]), 0.25); // Eq. 6.1 Turbulent Flows Pope two-point correlation
8780 cerr << "Kolmogorov length: " << eta << " Kolmogorov length / Lb: " << eta / m_referenceLength << endl;
8781 }
8782 MFloat maxd = mMax(fabs(Rel[0] - Rel[1]), mMax(fabs(Rel[0] - Rel[2]), fabs(Rel[1] - Rel[2])));
8783 if(maxd < F1) m_log << "spectrum " << maxd << " " << F1B3 * (Rel[0] + Rel[1] + Rel[2]) << " " << seed << endl;
8784 // if ( maxd < 0.3 && F1B3*(Rel[0]+Rel[1]+Rel[2]) > 79.1 ) {
8785 // if ( maxd < 0.3 ) {
8786 goodSpectrum = true;
8787 if(domainId() == 0) m_log << "spectrum " << seed << endl;
8788 //}
8789 //}
8790 }
8791 if(domainId() == 0) cerr << "seed " << seed << endl;
8792 MPI_Barrier(mpiComm(), AT_);
8793
8794 // TODO: grid().maxUniformRefinementLevel() has to be replaced with maxRefinementLevel() for adaptive meshes with
8795 // local ref
8796 if(fftLevel < grid().maxUniformRefinementLevel()) {
8797 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8798 if(a_isHalo(cellId)) continue;
8799 if(a_isBndryGhostCell(cellId)) continue;
8800 if(a_level(cellId) <= fftLevel) continue;
8801 if(c_noChildren(cellId) > 0) continue;
8802 MInt parentId = c_parentId(cellId);
8803 while(a_level(parentId) != fftLevel) {
8804 parentId = c_parentId(parentId);
8805 }
8806 if(a_level(parentId) == fftLevel) {
8807 for(MInt varId = 0; varId < noVars; varId++) {
8808 a_variable(cellId, varId) = a_variable(parentId, varId);
8809 std::cout << "a_variable(" << cellId << "," << varId << "): " << a_variable(parentId, varId) << std::endl;
8810 }
8811 }
8812 }
8813 }
8814 exchangeData(&a_variable(0, 0), noVars);
8815
8816 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
8817 for(MInt varId = 0; varId < noVars; varId++) {
8818 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
8819 }
8820 }
8821
8822 // initialize distr. functions
8824
8825 m_log << "**************************" << endl;
8826 m_log << "Initial Condition summary" << endl;
8827 m_log << "**************************" << endl;
8828 m_log << "Re = " << m_Re << endl;
8829 m_log << "Ma = " << m_Ma << endl;
8830 m_log << "UInfinity = " << UInfinity << endl;
8831 m_log << "rhoInfinity = " << rhoInfinity << endl;
8832
8833 // check initial condition
8834 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
8835 for(MInt v = 0; v < PV->noVariables; v++) {
8836 if(std::isnan(a_variable(cellId, v))) {
8837 cerr << "Variable " << v << " cellId : " << cellId << endl;
8838 mTerm(1, AT_, "Invalid initialcondition formulation!");
8839 }
8840 }
8841 }
8842
8843 // compute initial values for spectrum
8844 computeFFTStatistics();
8845}
constexpr Real POW3(const Real x)
Definition: functions.h:123
MInt globalNoDomains()
Return global number of domains.
MInt globalDomainId()
Return global domain id.
bool MBool
Definition: maiatypes.h:58
uint64_t MUlong
Definition: maiatypes.h:65
int MPI_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
int MPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Alltoall
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
int MPI_Alltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Alltoallv
MInt getGlobalPosFFTW(MInt i0, MInt i1, MInt i2, MInt ny, MInt nz)
Definition: maiafftw.h:59
void exchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const, const MInt *const noWindowCells, const MInt **const windowCells, const MPI_Comm comm, const U *const data, U *const haloBuffer, const MInt noDat=1)
Generic exchange of data.
Definition: mpiexchange.h:295

◆ initLatticeBgkFftMixing() [1/2]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::initLatticeBgkFftMixing ( )

Definition at line 8148 of file lbsolverdxqy.cpp.

8148 {
8149 TERMM(1, "Init method only available for D3Qy, yet!");
8150}

◆ initLatticeBgkFftMixing() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkFftMixing
inline
Author
Georg
Date
08.12.2011
Property value initMethod
LB_TURBULENT_MIXING_FILTER_INIT

Initializes standard Lattice BGK Turbulent Boundary with FFT initialization. Set property "initMethod" to "LB_TURBULENT_MIXING_INIT" and the property "FFTInit" to "1" to use this function.

\LBIC{LbSolverDxQy::initLatticeBgkFftMixing(), initLatticeBgkFftMixing, FftMixingInit}

Definition at line 7997 of file lbsolverdxqy.cpp.

7997 {
7998 TRACE();
7999 MInt xPos, yPos, zPos;
8000 MInt lx = 0, ly = 0, lz = 0;
8001
8002 MFloat actualCellLength;
8003 MFloat GaussFactor, sigma, deltaOmega0;
8004
8005 MFloat rho = 1.0, u[3] = {0.0, 0.0, 0.0};
8006
8007 // fft-domain dimensions
8008 // this holds the size of the domain in number of cells on lowest level
8009 lx = m_arraySize[0] / FPOW2(maxLevel() - minLevel());
8010 ly = m_arraySize[1] / FPOW2(maxLevel() - minLevel());
8011 if(nDim == 3) lz = m_arraySize[2] / FPOW2(maxLevel() - minLevel());
8012
8013 fftw_complex *uPhysField, *vPhysField, *wPhysField;
8014
8015 // field of velocities from positve frequencies (is deleted at the end of the method)
8016 uPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
8017 vPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
8018 wPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
8019
8020 // in multisolver mode the velocity field is created in solver 0 and broadcasted to all others
8021 ScratchSpace<MFloat> sendRecvBufferU(lx * ly * lz, AT_, "sendRecvBufferU");
8022 ScratchSpace<MFloat> sendRecvBufferV(lx * ly * lz, AT_, "sendRecvBufferV");
8023 ScratchSpace<MFloat> sendRecvBufferW(lx * ly * lz, AT_, "sendRecvBufferW");
8024 if(domainId() == 0) {
8025 // create velocity field
8026 maia::math::initFft(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes, m_Ma);
8027
8028 // copy values to buffer
8029 for(MInt p = 0; p < lx; p++) {
8030 for(MInt q = 0; q < ly; q++) {
8031 for(MInt r = 0; r < lz; r++) {
8032 sendRecvBufferU[r + lz * (q + ly * p)] = uPhysField[r + lz * (q + ly * p)][0];
8033 sendRecvBufferV[r + lz * (q + ly * p)] = vPhysField[r + lz * (q + ly * p)][0];
8034 sendRecvBufferW[r + lz * (q + ly * p)] = wPhysField[r + lz * (q + ly * p)][0];
8035 }
8036 }
8037 }
8038 }
8039
8040 MPI_Bcast(&sendRecvBufferU[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferU[0]");
8041 MPI_Bcast(&sendRecvBufferV[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferV[0]");
8042 MPI_Bcast(&sendRecvBufferW[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferW[0]");
8043
8044 if(domainId() != 0) {
8045 // copy values from buffer
8046 for(MInt p = 0; p < lx; p++) {
8047 for(MInt q = 0; q < ly; q++) {
8048 for(MInt r = 0; r < lz; r++) {
8049 uPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferU[r + lz * (q + ly * p)];
8050 vPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferV[r + lz * (q + ly * p)];
8051 wPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferW[r + lz * (q + ly * p)];
8052 }
8053 }
8054 }
8055 }
8056
8057
8058 ScratchSpace<MFloat> bBox(6, AT_, "bBox");
8059 MFloat* bBoxPtr = &bBox[0];
8060
8061 m_geometry->getBoundingBox(bBoxPtr);
8062
8063 // all cells have the same density
8064 if(m_densityFluctuations)
8065 rho = 0.0;
8066 else
8067 rho = 1.0;
8068
8069 // initial vorticity thickness [cells]
8070 deltaOmega0 = m_referenceLength * m_smallestCellLength;
8071
8072 // width of the Gaussian distribution for perturbation scaling
8073 // depends on initial vorticity thickness
8074 sigma = F1B2 * deltaOmega0;
8075
8076 m_log << " initial macroscopic vorticity thickness: " << deltaOmega0 << endl;
8077
8078 cerr << " --- prescribing mean velocity profile for turbulent mixing layer ---" << endl;
8079 for(MInt i = 0; i < a_noCells(); i++) {
8080 initNu(i, m_nu);
8081
8082 GaussFactor = exp(-(a_coordinate(i, 1) / sigma) * (a_coordinate(i, 1) / sigma) * F1B2);
8083
8084 u[0] = m_Ma * LBCS * tanh(2.0 * a_coordinate(i, 1) / deltaOmega0);
8085 u[1] = 0.0;
8086 u[2] = 0.0;
8087
8088 actualCellLength = this->grid().cellLengthAtCell(i);
8089
8090 xPos = floor(
8091 (F1B2 * lx + (a_coordinate(i, 0) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
8092 yPos = floor(
8093 (F1B2 * ly + (a_coordinate(i, 1) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
8094
8095 zPos = floor(
8096 (F1B2 * lz + (a_coordinate(i, 2) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
8097
8098 if(xPos > lx - 1 || xPos < 0 || yPos > ly - 1 || yPos < 0 || zPos > lz - 1 || zPos < 0) {
8099 stringstream errorMessage;
8100 errorMessage << "ERROR: wrong array position!" << endl;
8101 errorMessage << "pos=" << xPos << ", " << yPos << ", " << zPos << endl;
8102 errorMessage << "coorda = (" << a_coordinate(i, 2) << ", " << a_coordinate(i, 2) << ", " << a_coordinate(i, 2)
8103 << ")" << endl;
8104 errorMessage << "actuallength=" << actualCellLength << ", smallestlength=" << m_smallestCellLength << endl;
8105 errorMessage << "minlevel=" << minLevel() << ", maxLevel=" << maxLevel() << endl;
8106 errorMessage << "lenght on level0=" << this->c_cellLengthAtLevel(0) << endl;
8107 TERMM(1, errorMessage.str());
8108 }
8109
8110 // m_log <<"pos="<<xPos<<", "<<yPos<<", "<<zPos<<endl;
8111 // m_log <<"uvw="<<uPhysField[zPos+lz*(yPos+ly*xPos)][0]<<", "<<vPhysField[zPos+lz*(yPos+ly*xPos)][0]<<",
8112 // "<<wPhysField[zPos+lz*(yPos+ly*xPos)][0]<<endl;
8113
8114 // add normalized real parts of fluctuations factorized by Gaussian
8115 u[0] += uPhysField[zPos + lz * (yPos + ly * xPos)][0] * GaussFactor;
8116 u[1] += vPhysField[zPos + lz * (yPos + ly * xPos)][0] * GaussFactor;
8117 u[2] += wPhysField[zPos + lz * (yPos + ly * xPos)][0] * GaussFactor;
8118
8119 a_variable(i, PV->RHO) = rho;
8120 a_variable(i, PV->U) = u[0];
8121 a_variable(i, PV->V) = u[1];
8122 a_variable(i, PV->W) = u[2];
8123
8124 a_oldVariable(i, PV->RHO) = rho;
8125 // cells[i].m_oldVariablesT1[PV->RHO] = rho;
8126
8127 a_oldVariable(i, PV->U) = u[0];
8128 // cells[i].m_oldVariablesT1[PV->U] = u[0];
8129
8130 a_oldVariable(i, PV->V) = u[1];
8131 // cells[i].m_oldVariablesT1[PV->V] = u[1];
8132
8133 a_oldVariable(i, PV->W) = u[2];
8134 // cells[i].m_oldVariablesT1[PV->W] = u[2];
8135 }
8136
8137 // takeCurl();
8138
8139 // initialize distr. functions
8141
8142 // Free the FFTW memory
8143 fftw_free(uPhysField);
8144 fftw_free(vPhysField);
8145 fftw_free(wPhysField);
8146}
void initNonEqDistFunctions()

◆ initLatticeBgkFftMixingFilter() [1/2]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::initLatticeBgkFftMixingFilter ( )

Definition at line 8322 of file lbsolverdxqy.cpp.

8322 {
8323 TERMM(1, "Init method only available for D3Qy, yet!");
8324}

◆ initLatticeBgkFftMixingFilter() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkFftMixingFilter
inline
Author
Georg
Date
08.12.2011
Property value initMethod
LB_TURBULENT_MIXING_FILTER_INIT

Initializes standard Lattice BGK Turbulent Boundary with FFT initialization. The disturbances are filtered to a resolution 4 times lower than the resolution of the disturbance field. Set property "initMethod" to "LB_TURBULENT_MIXING_FILTER_INIT" and the property "FFTInit" to "1" to use this function.

\LBIC{LbSolverDxQy::initLatticeBgkFftMixingFilter(), initLatticeBgkFftMixingFilter, FftMixingFilterInit}

Definition at line 8165 of file lbsolverdxqy.cpp.

8165 {
8166 TRACE();
8167
8168 MInt xPos, yPos, zPos;
8169 MInt lx = 0, ly = 0, lz = 0;
8170 MInt lxCoarse = 0, lyCoarse = 0, lzCoarse = 0;
8171
8172 MFloat actualCellLength;
8173 MFloat GaussFactor, sigma, deltaOmega0;
8174
8175 MFloat rho, u[3] = {0.0, 0.0, 0.0};
8176
8177 // all cells have the same density
8178 if(m_densityFluctuations)
8179 rho = 0.0;
8180 else
8181 rho = 1.0;
8182
8183 // fft-domain dimensions
8184 // this holds the size of the domain in number of cells on highest level
8185 lx = m_arraySize[0];
8186 ly = m_arraySize[1];
8187 if(nDim == 3) lz = m_arraySize[2];
8188
8189 // size of the filtered domain
8190 lxCoarse = lx / 2;
8191 lyCoarse = ly / 2;
8192 lzCoarse = lz / 2;
8193
8194 // field of velocities filtered to coarse grid (is deleted at the end of the method)
8195 ScratchSpace<MFloat> uPhysFieldCoarse(lxCoarse * lyCoarse * lzCoarse, AT_, "uPhysFieldCoarse");
8196 ScratchSpace<MFloat> vPhysFieldCoarse(lxCoarse * lyCoarse * lzCoarse, AT_, "vPhysFieldCoarse");
8197 ScratchSpace<MFloat> wPhysFieldCoarse(lxCoarse * lyCoarse * lzCoarse, AT_, "wPhysFieldCoarse");
8198
8199 // in multisolver mode the velocity field is created in solver 0 and broadcasted to all others
8200 ScratchSpace<MFloat> sendRecvBufferU(lxCoarse * lyCoarse * lzCoarse, AT_, "sendRecvBufferU");
8201 ScratchSpace<MFloat> sendRecvBufferV(lxCoarse * lyCoarse * lzCoarse, AT_, "sendRecvBufferV");
8202 ScratchSpace<MFloat> sendRecvBufferW(lxCoarse * lyCoarse * lzCoarse, AT_, "sendRecvBufferW");
8203
8204 if(domainId() == 0) {
8205 // create velocity field
8206 MFloat* uPhysFieldCoarsePtr = &uPhysFieldCoarse[0];
8207 MFloat* vPhysFieldCoarsePtr = &vPhysFieldCoarse[0];
8208 MFloat* wPhysFieldCoarsePtr = &wPhysFieldCoarse[0];
8209 maia::math::initFftFilter(uPhysFieldCoarsePtr, vPhysFieldCoarsePtr, wPhysFieldCoarsePtr, lx, ly, lz, lxCoarse,
8210 lyCoarse, lzCoarse, m_noPeakModes, m_Ma);
8211
8212 // copy values to buffer
8213 for(MInt p = 0; p < lxCoarse; p++) {
8214 for(MInt q = 0; q < lyCoarse; q++) {
8215 for(MInt r = 0; r < lzCoarse; r++) {
8216 sendRecvBufferU[r + lzCoarse * (q + lyCoarse * p)] = uPhysFieldCoarse[r + lzCoarse * (q + lyCoarse * p)];
8217 sendRecvBufferV[r + lzCoarse * (q + lyCoarse * p)] = vPhysFieldCoarse[r + lzCoarse * (q + lyCoarse * p)];
8218 sendRecvBufferW[r + lzCoarse * (q + lyCoarse * p)] = wPhysFieldCoarse[r + lzCoarse * (q + lyCoarse * p)];
8219 }
8220 }
8221 }
8222 }
8223
8224 MPI_Bcast(&sendRecvBufferU[0], lxCoarse * lyCoarse * lzCoarse, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferU[0]");
8225 MPI_Bcast(&sendRecvBufferV[0], lxCoarse * lyCoarse * lzCoarse, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferV[0]");
8226 MPI_Bcast(&sendRecvBufferW[0], lxCoarse * lyCoarse * lzCoarse, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferW[0]");
8227
8228 if(domainId() != 0) {
8229 // copy values from buffer
8230 for(MInt p = 0; p < lxCoarse; p++) {
8231 for(MInt q = 0; q < lyCoarse; q++) {
8232 for(MInt r = 0; r < lzCoarse; r++) {
8233 uPhysFieldCoarse[r + lzCoarse * (q + lyCoarse * p)] = sendRecvBufferU[r + lzCoarse * (q + lyCoarse * p)];
8234 vPhysFieldCoarse[r + lzCoarse * (q + lyCoarse * p)] = sendRecvBufferV[r + lzCoarse * (q + lyCoarse * p)];
8235 wPhysFieldCoarse[r + lzCoarse * (q + lyCoarse * p)] = sendRecvBufferW[r + lzCoarse * (q + lyCoarse * p)];
8236 }
8237 }
8238 }
8239 }
8240
8241 ScratchSpace<MFloat> bBox(6, AT_, "bBox");
8242 MFloat* bBoxPtr = &bBox[0];
8243 m_geometry->getBoundingBox(bBoxPtr);
8244
8245 // initial vorticity thickness [cells]
8246 deltaOmega0 = m_referenceLength * m_smallestCellLength;
8247
8248 // width of the Gaussian distribution for perturbation scaling
8249 // depends on initial vorticity thickness
8250 sigma = deltaOmega0;
8251
8252 m_log << " initial macroscopic vorticity thickness: " << deltaOmega0 << endl;
8253
8254 cerr << " --- prescribing mean velocity profile for turbulent mixing layer ---" << endl;
8255 for(MInt i = 0; i < a_noCells(); i++) {
8256 initNu(i, m_nu);
8257
8258 GaussFactor = exp(-(a_coordinate(i, 1) / sigma) * (a_coordinate(i, 1) / sigma) * F1B2);
8259
8260 u[0] = m_Ma * LBCS * tanh(2.0 * a_coordinate(i, 1) / deltaOmega0);
8261 u[1] = 0.0;
8262 u[2] = 0.0;
8263
8264 actualCellLength = this->grid().cellLengthAtCell(i);
8265
8266 xPos = floor(
8267 (F1B2 * lxCoarse + (a_coordinate(i, 0) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
8268 + 0.1);
8269 yPos = floor(
8270 (F1B2 * lyCoarse + (a_coordinate(i, 1) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
8271 + 0.1);
8272
8273 zPos = floor(
8274 (F1B2 * lzCoarse + (a_coordinate(i, 2) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
8275 + 0.1);
8276
8277 if(xPos > lxCoarse - 1 || xPos < 0 || yPos > lyCoarse - 1 || yPos < 0 || zPos > lzCoarse - 1 || zPos < 0) {
8278 cerr << "ERROR: wrong array position!" << endl;
8279 cerr << "pos=" << xPos << ", " << yPos << ", " << zPos << endl;
8280 cerr << "coorda = (" << a_coordinate(i, 2) << ", " << a_coordinate(i, 2) << ", " << a_coordinate(i, 2) << ")"
8281 << endl;
8282 cerr << "actuallength=" << actualCellLength << ", smallestlength=" << m_smallestCellLength << endl;
8283 cerr << "minlevel=" << minLevel() << ", maxLevel=" << maxLevel() << endl;
8284 cerr << "lenght on level0=" << this->c_cellLengthAtLevel(0) << endl;
8285 TERMM(1, "Wrong array position");
8286 }
8287
8288 // m_log <<"pos="<<xPos<<", "<<yPos<<", "<<zPos<<endl;
8289 // m_log <<"uvw="<<uPhysField[zPos+lz*(yPos+ly*xPos)][0]<<", "<<vPhysField[zPos+lz*(yPos+ly*xPos)][0]<<",
8290 // "<<wPhysField[zPos+lz*(yPos+ly*xPos)][0]<<endl;
8291
8292 // add normalized real parts of fluctuations factorized by Gaussian
8293 u[0] += uPhysFieldCoarse[zPos + lzCoarse * (yPos + lyCoarse * xPos)] * GaussFactor;
8294 u[1] += vPhysFieldCoarse[zPos + lzCoarse * (yPos + lyCoarse * xPos)] * GaussFactor;
8295 u[2] += wPhysFieldCoarse[zPos + lzCoarse * (yPos + lyCoarse * xPos)] * GaussFactor;
8296
8297 a_variable(i, PV->RHO) = rho;
8298 a_variable(i, PV->U) = u[0];
8299 a_variable(i, PV->V) = u[1];
8300 a_variable(i, PV->W) = u[2];
8301
8302 a_oldVariable(i, PV->RHO) = rho;
8303 // cells[i].m_oldVariablesT1[PV->RHO] = rho;
8304
8305 a_oldVariable(i, PV->U) = u[0];
8306 // cells[i].m_oldVariablesT1[PV->U] = u[0];
8307
8308 a_oldVariable(i, PV->V) = u[1];
8309 // cells[i].m_oldVariablesT1[PV->V] = u[1];
8310
8311 a_oldVariable(i, PV->W) = u[2];
8312 // cells[i].m_oldVariablesT1[PV->W] = u[2];
8313 }
8314
8315 // takeCurl();
8316
8317 // initialize distr. functions
8319 // initEqDistFunctions();
8320}
void initFftFilter(MFloat *uPhysFieldCoarse, MFloat *vPhysFieldCoarse, MFloat *wPhysFieldCoarse, MInt lx, MInt ly, MInt lz, MInt lxCoarse, MInt lyCoarse, MInt lzCoarse, MInt noPeakModes, const MFloat Ma)
Generates a velocity field from Fourier-modes using FFTW The disturbances are generated and filtered ...
Definition: maiafftw.h:681

◆ initLatticeBgkFftPipe() [1/2]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::initLatticeBgkFftPipe ( )

Definition at line 7981 of file lbsolverdxqy.cpp.

7981 {
7982 TERMM(1, "Init method only available for D3Qy, yet!");
7983}

◆ initLatticeBgkFftPipe() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkFftPipe
inline
Author
Andreas Lintermann
Date
24.01.2011
Property value initMethod
LB_TURBULENT_PIPE_INIT

Initializes standard Lattice BGK Turbulent Pipe with FFT initialization. Set property "initMethod" to "LB_TURBULENT_PIPE_INIT" and the property "FFTInit" to "1" to use this function.

\LBIC{LbSolverDxQy::initLatticeBgkFftPipe(), initLatticeBgkFftPipe, FftPipeInit}

Definition at line 7830 of file lbsolverdxqy.cpp.

7830 {
7831 TRACE();
7832 MInt xPos, yPos, zPos;
7833 MInt lx = 0, ly = 0, lz = 0;
7834
7835 // fft-domain dimensions
7836 // this holds the size of the domain in number of cells on lowest level
7837 lx = m_arraySize[0] / FPOW2(maxLevel() - minLevel());
7838 ly = m_arraySize[1] / FPOW2(maxLevel() - minLevel());
7839 if(nDim == 3) lz = m_arraySize[2] / FPOW2(maxLevel() - minLevel());
7840
7841 fftw_complex *uPhysField, *vPhysField, *wPhysField;
7842
7843 // field of velocities from positve frequencies
7844 uPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
7845 vPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
7846 wPhysField = (fftw_complex*)fftw_malloc(lx * ly * lz * sizeof(fftw_complex));
7847
7848 // in multisolver mode the velocity field is created in solver 0 and broadcasted to all others
7849 ScratchSpace<MFloat> sendRecvBufferU(lx * ly * lz, AT_, "sendRecvBufferU");
7850 ScratchSpace<MFloat> sendRecvBufferV(lx * ly * lz, AT_, "sendRecvBufferV");
7851 ScratchSpace<MFloat> sendRecvBufferW(lx * ly * lz, AT_, "sendRecvBufferW");
7852
7853
7854 if(domainId() == 0) {
7855 // create velocity field
7856 maia::math::initFft(uPhysField, vPhysField, wPhysField, lx, ly, lz, m_noPeakModes, m_Ma);
7857
7858 // copy values to buffer
7859 for(MInt p = 0; p < lx; p++) {
7860 for(MInt q = 0; q < ly; q++) {
7861 for(MInt r = 0; r < lz; r++) {
7862 sendRecvBufferU[r + lz * (q + ly * p)] = uPhysField[r + lz * (q + ly * p)][0];
7863 sendRecvBufferV[r + lz * (q + ly * p)] = vPhysField[r + lz * (q + ly * p)][0];
7864 sendRecvBufferW[r + lz * (q + ly * p)] = wPhysField[r + lz * (q + ly * p)][0];
7865 }
7866 }
7867 }
7868 }
7869
7870 MPI_Bcast(&sendRecvBufferU[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferU[0]");
7871 MPI_Bcast(&sendRecvBufferV[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferV[0]");
7872 MPI_Bcast(&sendRecvBufferW[0], lx * ly * lz, MPI_DOUBLE, 0, mpiComm(), AT_, "sendRecvBufferW[0]");
7873
7874 if(domainId() != 0) {
7875 // copy values from buffer
7876 for(MInt p = 0; p < lx; p++) {
7877 for(MInt q = 0; q < ly; q++) {
7878 for(MInt r = 0; r < lz; r++) {
7879 uPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferU[r + lz * (q + ly * p)];
7880 vPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferV[r + lz * (q + ly * p)];
7881 wPhysField[r + lz * (q + ly * p)][0] = sendRecvBufferW[r + lz * (q + ly * p)];
7882 }
7883 }
7884 }
7885 }
7886
7887 MFloat actualCellLength;
7888
7889 MFloat rho, u[3] = {0.0, 0.0, 0.0}, uTau, yPlus;
7890 MFloat radius = 0.0;
7891
7892 // all cells have the same density
7893 if(m_densityFluctuations)
7894 rho = 0.0;
7895 else
7896 rho = 1.0;
7897
7898 uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
7899
7900 // tmpwidth equals pipe-radius (in cells) * cellLength on maxLevel
7901 MFloat tmpWidth = F1B2 * m_referenceLength * m_smallestCellLength;
7902
7903 cerr << " --- prescribing mean velocity profile for turbulent pipe ---" << endl;
7904 for(MInt i = 0; i < a_noCells(); i++) {
7905 initNu(i, m_nu);
7906
7907 radius = sqrt(a_coordinate(i, 0) * a_coordinate(i, 0) + a_coordinate(i, 1) * a_coordinate(i, 1));
7908
7909 yPlus = m_ReTau * (1.0 - radius / tmpWidth);
7910
7911 u[0] = 0.0;
7912 u[1] = 0.0;
7913
7914 if(yPlus <= 5.0) {
7915 u[2] = uTau * yPlus;
7916 } else {
7917 if(yPlus <= 30 && yPlus > 5.0) {
7918 u[2] = uTau * (C1 * log(yPlus) + C2);
7919 } else {
7920 if(yPlus > 30) {
7921 u[2] = uTau * (C3 * log(yPlus) + C4);
7922 }
7923 }
7924 }
7925
7926 actualCellLength = this->grid().cellLengthAtCell(i);
7927
7928 xPos = floor(
7929 (F1B2 * lx + (a_coordinate(i, 0) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
7930 yPos = floor(
7931 (F1B2 * ly + (a_coordinate(i, 1) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
7932
7933 // zero z at the inlet
7934 zPos = floor(((a_coordinate(i, 2) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(minLevel()))) + 0.1);
7935
7936 if(xPos > lx - 1 || xPos < 0 || yPos > ly - 1 || yPos < 0 || zPos > lz - 1 || zPos < 0) {
7937 stringstream errorMessage;
7938 errorMessage << "ERROR: wrong array position!" << endl;
7939 errorMessage << "pos=" << xPos << ", " << yPos << ", " << zPos << endl;
7940 errorMessage << "coorda = (" << a_coordinate(i, 2) << ", " << a_coordinate(i, 2) << ", " << a_coordinate(i, 2)
7941 << ")" << endl;
7942 errorMessage << "actuallength=" << actualCellLength << ", smallestlength=" << m_smallestCellLength << endl;
7943 errorMessage << "minlevel=" << minLevel() << ", maxLevel=" << maxLevel() << endl;
7944 errorMessage << "length on level0=" << this->c_cellLengthAtLevel(0) << endl;
7945 TERMM(1, errorMessage.str());
7946 }
7947
7948
7949 // m_log <<"pos="<<xPos<<", "<<yPos<<", "<<zPos<<endl;
7950 // m_log <<"uvw="<<uPhysField[zPos+lz*(yPos+ly*xPos)][0]<<", "<<vPhysField[zPos+lz*(yPos+ly*xPos)][0]<<",
7951 // "<<wPhysField[zPos+lz*(yPos+ly*xPos)][0]<<endl;
7952
7953 // add normalized real parts of fluctuations factorized by u_mean/u_max
7954 u[0] += 2.0 * uPhysField[zPos + lz * (yPos + ly * xPos)][0] * u[2] / (uTau * (C3 * log(m_ReTau) + C4));
7955 u[1] += 2.0 * vPhysField[zPos + lz * (yPos + ly * xPos)][0] * u[2] / (uTau * (C3 * log(m_ReTau) + C4));
7956 u[2] += 2.0 * wPhysField[zPos + lz * (yPos + ly * xPos)][0] * u[2] / (uTau * (C3 * log(m_ReTau) + C4));
7957
7958 a_variable(i, PV->RHO) = rho;
7959 a_oldVariable(i, PV->RHO) = rho;
7960 // cells[i].m_oldVariablesT1[PV->RHO] = rho;
7961 a_variable(i, PV->U) = u[0];
7962 a_oldVariable(i, PV->U) = u[0];
7963 // cells[i].m_oldVariablesT1[PV->U] = u[0];
7964 a_variable(i, PV->V) = u[1];
7965 a_oldVariable(i, PV->V) = u[1];
7966 // cells[i].m_oldVariablesT1[PV->V] = u[1];
7967 a_variable(i, PV->W) = u[2];
7968 a_oldVariable(i, PV->W) = u[2];
7969 // cells[i].m_oldVariablesT1[PV->W] = u[2];
7970 }
7971
7972 // initialize distr. functions
7974
7975 // Free the FftW memory
7976 fftw_free(uPhysField);
7977 fftw_free(vPhysField);
7978 fftw_free(wPhysField);
7979}

◆ initLatticeBgkGaussAdvection()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkGaussAdvection

Definition at line 6037 of file lbsolverdxqy.cpp.

6037 {
6038 TRACE();
6039
6040 const MFloat origin[2] = {F0, F0}; // center of the hill
6041 const MFloat width = 20.0 * this->c_cellLengthAtLevel(this->maxLevel());
6042 const MFloat maxConcentration = this->m_initCon;
6043 const MFloat maxTemp = this->m_initTemperatureKelvin;
6044
6045 maia::parallelFor<false>(0, a_noCells(), [&](MInt i) {
6046 // Initialize zero velocity
6047 MFloat velocity = m_Ma * LBCS;
6048 a_variable(i, PV->U) = velocity;
6049 a_variable(i, PV->V) = velocity;
6050 a_oldVariable(i, PV->U) = velocity;
6051 a_oldVariable(i, PV->V) = velocity;
6052
6053 // Inizialize density
6054 MFloat rho = 1.0;
6055 a_variable(i, PV->RHO) = rho;
6056 a_oldVariable(i, PV->RHO) = rho;
6057
6058 // Initialize a Gaussian hill for the conzentration.
6059 if((m_isTransport) && nDim == 2) {
6060 MFloat r[nDim];
6061 for(MInt d = 0; d < nDim; d++)
6062 r[d] = a_coordinate(i, d) - origin[d];
6063 const MFloat distSq = pow(r[0], 2) + pow(r[1], 2);
6064 const MFloat C = maxConcentration * exp(-(distSq) / (2 * pow(width, 2)));
6065 a_variable(i, PV->C) = C;
6066 a_oldVariable(i, PV->C) = C;
6067 }
6068
6069 if((m_isThermal) && nDim == 2) {
6070 MFloat r[nDim];
6071 for(MInt d = 0; d < nDim; d++)
6072 r[d] = a_coordinate(i, d) - origin[d];
6073 const MFloat distSq = pow(r[0], 2) + pow(r[1], 2);
6074 const MFloat T = maxTemp * exp(-(distSq) / (2 * pow(width, 2)));
6075 a_variable(i, PV->T) = T;
6076 a_oldVariable(i, PV->T) = T;
6077 }
6078
6079 // the viscosity is saved for each cell
6080 // this is needed for subgrid modelling
6081 initNu(i, m_nu);
6082 });
6083
6084 // Compute the equilibrium distributions
6086
6087 if(m_isThermal) {
6089 }
6090 if(m_isTransport) {
6092 }
6093}
virtual void initTransportEqDistFunctions()
Calculates equilibrium distribution functions after initialization of macroscopic variables.
virtual void initThermalEqDistFunctions()
Calculates equilibrium distribution functions after initialization of macroscopic variables.
const MInt width
Definition: logtable.h:21

◆ initLatticeBgkGaussDiffusion()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkGaussDiffusion

Definition at line 5975 of file lbsolverdxqy.cpp.

5975 {
5976 TRACE();
5977
5978 const MFloat origin[2] = {F0, F0}; // center of the hill
5979 const MFloat width = 20.0 * this->c_cellLengthAtLevel(this->maxLevel());
5980 const MFloat maxConcentration = this->m_initCon;
5981 const MFloat maxTemp = this->m_initTemperatureKelvin;
5982
5983 maia::parallelFor<false>(0, a_noCells(), [=](MInt i) {
5984 // Initialize zero velocity
5985 a_variable(i, PV->U) = F0;
5986 a_variable(i, PV->V) = F0;
5987 a_oldVariable(i, PV->U) = F0;
5988 a_oldVariable(i, PV->V) = F0;
5989
5990 // Inizialize density
5991 MFloat rho = 1.0;
5992 a_variable(i, PV->RHO) = rho;
5993 a_oldVariable(i, PV->RHO) = rho;
5994
5995 // Initialize a Gaussian hill for the conzentration.
5996 if((m_isTransport) && nDim == 2) {
5997 MFloat r[nDim];
5998 for(MInt d = 0; d < nDim; d++)
5999 r[d] = a_coordinate(i, d) - origin[d];
6000 const MFloat distSq = pow(r[0], 2) + pow(r[1], 2);
6001 const MFloat C = maxConcentration * exp(-(distSq) / (2 * pow(width, 2)));
6002 a_variable(i, PV->C) = C;
6003 a_oldVariable(i, PV->C) = C;
6004 }
6005
6006 if((m_isThermal) && nDim == 2) {
6007 MFloat r[nDim];
6008 for(MInt d = 0; d < nDim; d++)
6009 r[d] = a_coordinate(i, d) - origin[d];
6010 const MFloat distSq = pow(r[0], 2) + pow(r[1], 2);
6011 const MFloat T = maxTemp * exp(-(distSq) / (2 * pow(width, 2)));
6012 a_variable(i, PV->T) = T;
6013 a_oldVariable(i, PV->T) = T;
6014 }
6015
6016 // the viscosity is saved for each cell
6017 // this is needed for subgrid modelling
6018 initNu(i, m_nu);
6019 });
6020
6021 // Compute the equilibrium distributions
6023
6024 if(m_isThermal) {
6026 }
6027 if(m_isTransport) {
6029 }
6030}

◆ initLatticeBgkGaussPulse()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkGaussPulse
Author
Miro Gondrum
Date
17.03.2020
Property value initMethod
LB_GAUSS_PULSE_INIT

Initializes a Gaussian pulse. Set property "initMethod" to "LB_GAUSS_PULSE_INIT" to use this function.

\LBIC{LbSolverDxQy::initLatticeBgkGaussPulse(), initLatticeBgkGaussPulse, GaussPulseInit}

Definition at line 5949 of file lbsolverdxqy.cpp.

5949 {
5950 TRACE();
5951
5952 const MFloat rho0 = (m_densityFluctuations) ? 0.0 : 1.0;
5953 const MFloat origin[3] = {F0, F0, F0};
5954 const MFloat amp = 1e-8;
5955 const MFloat radius = 0.01;
5956
5957 initLatticeBgkLaminarDir(-1); // normal zero init
5958 maia::parallelFor<false>(0, a_noCells(), [&](MInt i) {
5959 MFloat r[nDim];
5960 for(MInt j = 0; j < nDim; j++)
5961 r[j] = a_coordinate(i, j) - origin[j];
5962 const MFloat distance = std::sqrt(std::inner_product(&r[0], &r[nDim], &r[0], .0));
5963 const MFloat rhoFluct = amp * std::exp(-(distance * distance) / radius);
5964 a_variable(i, PV->RHO) = rho0 + rhoFluct;
5965 a_oldVariable(i, PV->RHO) = a_variable(i, PV->RHO);
5966 });
5968}
virtual void initLatticeBgkLaminarDir(MInt dir)
Initializes standard Lattice BGK laminar with or without a direction.
MFloat distance(const MFloat *a, const MFloat *b)
Definition: maiamath.h:249

◆ initLatticeBgkLaminar()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkLaminar
virtual
Author
Andreas Lintermann
Date
24.01.2011
Property value initMethod
LB_FROM_ZERO_INIT
Property value initMethod
LB_LAMINAR_INIT_[PM][XYZ]

Set property "initMethod" to "LB_FROM_ZERO_INIT" or to "LB_LAMINAR_INIT_[PM][XYZ]" to use this function. Simply calls initLatticeBgkLaminarDir(...) with a velocity direction or -1 for zero velocity.

\LBIC{LbSolverDxQy::initLatticeBgkLaminar(), initLatticeBgkLaminar, LaminarInit}

Definition at line 5846 of file lbsolverdxqy.cpp.

5846 {
5847 TRACE();
5848
5849 switch(string2enum(m_initMethod)) {
5850 case LB_FROM_ZERO_INIT:
5851 if constexpr(nDim == 2) {
5852 m_log << " - parameters: u=0.0, v=0.0, " << (m_densityFluctuations ? "rho=0.0" : "rho=1.0")
5853 << ((m_isThermal) ? ", T=1.0" : "") << ((m_isTransport) ? ", C=1.0" : "") << endl;
5854 } else {
5855 m_log << " - parameters: u=0.0, v=0.0, w=0, " << (m_densityFluctuations ? "rho=0.0" : "rho=1.0")
5856 << ((m_isThermal) ? ", T=1.0" : "") << ((m_isTransport) ? ", C=1.0" : "") << endl;
5857 }
5859 break;
5860 case LB_LAMINAR_INIT_PX:
5861 if constexpr(nDim == 2) {
5862 m_log << " - parameters: u=" << m_Ma * LBCS << ", v=0.0, "
5863 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5864 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5865 } else {
5866 m_log << " - parameters: u=" << m_Ma * LBCS << ", v=0.0, w=0, "
5867 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5868 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5869 }
5871 break;
5872 case LB_LAMINAR_INIT_MX:
5873 if constexpr(nDim == 2) {
5874 m_log << " - parameters: u=-" << m_Ma * LBCS << ", v=0.0, "
5875 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5876 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5877 } else {
5878 m_log << " - parameters: u=-" << m_Ma * LBCS << ", v=0.0, w=0, "
5879 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5880 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5881 }
5883 break;
5884 case LB_LAMINAR_INIT_PY:
5885 if constexpr(nDim == 2) {
5886 m_log << " - parameters: u=0.0, v=" << m_Ma * LBCS << ", "
5887 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5888 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5889 } else {
5890 m_log << " - parameters: u=0.0, v=" << m_Ma * LBCS << ", w=0.0, "
5891 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5892 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5893 }
5895 break;
5896 case LB_LAMINAR_INIT_MY:
5897 if constexpr(nDim == 2) {
5898 m_log << " - parameters: u=0.0, v=-" << m_Ma * LBCS << ", "
5899 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5900 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5901 } else {
5902 m_log << " - parameters: u=0.0, v=-" << m_Ma * LBCS << ", w=0.0, "
5903 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5904 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5905 }
5907 break;
5908 case LB_LAMINAR_INIT_PZ:
5909 if constexpr(nDim == 2) {
5910 m_log << " - parameters: u=0.0, v=0.0, " << (m_densityFluctuations ? "rho=0.0" : "rho=1.0")
5911 << ((m_isThermal) ? ", T=1.0" : "") << ((m_isTransport) ? ", C=1.0" : "") << endl;
5913 } else {
5914 m_log << " - parameters: u=0.0, v=0.0, w=" << m_Ma * LBCS << ", "
5915 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5916 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5918 }
5919 break;
5920 case LB_LAMINAR_INIT_MZ:
5921 if constexpr(nDim == 2) {
5922 m_log << " - parameters: u=0.0, v=0.0, " << (m_densityFluctuations ? "rho=0.0" : "rho=1.0")
5923 << ((m_isThermal) ? ", T=1.0" : "") << ((m_isTransport) ? ", C=1.0" : "") << endl;
5925 } else {
5926 m_log << " - parameters: u=0.0, v=0.0, w=-" << m_Ma * LBCS << ", "
5927 << (m_densityFluctuations ? "rho=0.0" : "rho=1.0") << ((m_isThermal) ? ", T=1.0" : "")
5928 << ((m_isTransport) ? ", C=1.0" : "") << endl;
5930 }
5931 break;
5932 default:
5933 break;
5934 }
5935}

◆ initLatticeBgkLaminarChannel()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkLaminarChannel
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_LAMINAR_CHANNEL_INIT

Initializes standard Lattice BGK Laminar Channel. Set property "initMethod" to "LB_LAMINAR_CHANNEL_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkLaminarChannel(), initLatticeBgkLaminarChannel, LaminarChannelInit}

Definition at line 5137 of file lbsolverdxqy.cpp.

5137 {
5138 TRACE();
5139
5140 // all cells have the same density
5141 const MFloat rho = (m_densityFluctuations) ? 0.0 : 1.0;
5142
5143 for(MInt i = 0; i < a_noCells(); i++) {
5144 a_variable(i, PV->RHO) = rho;
5145 a_oldVariable(i, PV->RHO) = rho;
5146
5147 // the viscosity is saved for each cell
5148 // this is needed for subgrid modelling
5149 initNu(i, m_nu);
5150 if(m_isThermal) {
5151 a_kappa(i) = m_kappa;
5152 a_variable(i, PV->T) = 1.0;
5153 a_oldVariable(i, PV->T) = 1.0;
5154 }
5155 if(m_isTransport) {
5156 a_diffusivity(i) = m_diffusivity;
5157 a_variable(i, PV->C) = 1.0;
5158 a_oldVariable(i, PV->C) = 1.0;
5159 }
5160
5161 for(MInt dir = 1; dir < nDim; dir++) {
5162 a_variable(i, PV->VV[dir]) = 0.0;
5163 }
5164
5165 std::array<MFloat, 2 * nDim> bBox{};
5166 this->m_geometry->getBoundingBox(bBox.data());
5167 if(this->m_nonNewtonian) {
5168 const MFloat tmpWidth = fabs(bBox[nDim + 1] - bBox[1]) * F1B2;
5169 const MFloat exp = F1 + F1 / this->m_n;
5170
5171 const MFloat relPos = fabs(a_coordinate(i, 1) / tmpWidth - F1);
5172 const MFloat parabola = F1 - pow(relPos, exp);
5173
5174 a_variable(i, PV->VV[0]) = m_Ma * LBCS * parabola;
5175 } else {
5176 const MFloat halfWidth = std::max(fabs(bBox[1 + nDim]), fabs(bBox[1]));
5177 a_variable(i, PV->VV[0]) =
5178 m_Ma * LBCS
5179 * ((1 - this->m_CouettePoiseuilleRatio) * a_coordinate(i, 1) / halfWidth + this->m_CouettePoiseuilleRatio
5180 - this->m_CouettePoiseuilleRatio * (a_coordinate(i, 1) / halfWidth) * (a_coordinate(i, 1) / halfWidth));
5181 a_oldVariable(i, PV->VV[0]) = a_variable(i, PV->VV[0]);
5182 }
5183
5184 for(MInt d = 0; d < nDim; d++) {
5185 a_oldVariable(i, PV->VV[d]) = a_variable(i, PV->VV[d]);
5186 }
5187 }
5188
5190
5191 if(m_isThermal) {
5193 }
5194 if(m_isTransport) {
5196 }
5197
5198 if(this->m_nonNewtonian) {
5200 this->exchange();
5201 this->exchangeOldDistributions();
5202 }
5203}

◆ initLatticeBgkLaminarCylinder()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkLaminarCylinder
Author
Miro Gondrum
Date
31.03.2022
Property value initMethod
LB_LAMINAR_CYLINDER_INIT

Initializes a laminar cylinder with perturbation. Set property "initMethod" to "LB_LAMINAR_CYLINDER_INIT" to use this function. Perturbation forces a shorter transient.

\LBIC{LbSolverDxQy::initLatticeBgkLaminarCylinder(), initLatticeBgkLaminarCylinder, LaminarCylinderInit}

Definition at line 6108 of file lbsolverdxqy.cpp.

6108 {
6109 // normal init in pos +x direction
6111 // now add perturbation to force faster transient
6112 constexpr MFloat factor = 0.1;
6113 const MFloat bb = 2.0; // bounding box where perturbation is applied
6114 maia::parallelFor<false>(0, a_noCells(), [=](MInt i) {
6115 const MFloat x = a_coordinate(i, 0);
6116 const MFloat y = a_coordinate(i, 1);
6117 // (x,y) in bb
6118 if(-bb < x && x < bb && -bb < y && y < bb) {
6119 const MFloat pertFactor = (1.0 + factor * std::sin(y / 2.0 * PI));
6120 a_variable(i, PV->U) *= pertFactor;
6121 }
6122 });
6124}

◆ initLatticeBgkLaminarDir()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkLaminarDir ( MInt  dir)
virtual
Author
Andreas Lintermann
Date
10.04.2017

The direction parameter is given by:

  • -1 : set zero velocity
  • 0/1: positive / negative x
  • 2/3: positive / negative y
  • 4/5: positive / negative z
Parameters
[in]dirthe direction to set

Definition at line 6141 of file lbsolverdxqy.cpp.

6141 {
6142 TRACE();
6143
6144 MFloat value = m_Ma * LBCS;
6145 std::array<MInt, nDim - 1> o_dirs{};
6146 o_dirs[0] = PV->V;
6147 if constexpr(nDim == 3) o_dirs[1] = PV->W;
6148
6149 if(dir < 0) {
6150 dir = PV->U;
6151 value = 0.0;
6152 } else {
6153 if(dir % 2) value *= -1.0;
6154
6155 switch(dir) {
6156 case 0:
6157 case 1:
6158 dir = PV->U;
6159 break;
6160 case 2:
6161 case 3:
6162 dir = PV->V;
6163 o_dirs[0] = PV->U;
6164 break;
6165 case 4:
6166 case 5:
6167 dir = PV->W;
6168 o_dirs[0] = PV->U;
6169 if constexpr(nDim == 3) o_dirs[1] = PV->V;
6170 break;
6171 default:
6172 break;
6173 }
6174 }
6175
6176 maia::parallelFor<false>(0, a_noCells(), [=](MInt i) {
6177 a_variable(i, dir) = value;
6178 a_oldVariable(i, dir) = value;
6179 for(MInt j = 0; j < nDim - 1; j++) {
6180 a_variable(i, o_dirs[j]) = 0.0;
6181 a_oldVariable(i, o_dirs[j]) = 0.0;
6182 }
6183
6184 MFloat rho = m_densityFluctuations ? 0.0 : 1.0;
6185 if(m_initDensityGradient) {
6186 for(MInt j = 0; j < nDim; j++) {
6187 rho += a_coordinate(i, j) / this->c_cellLengthAtLevel(maxLevel()) * m_volumeAccel[j] * F1BCSsq;
6188 }
6189 }
6190 a_variable(i, PV->RHO) = rho;
6191 a_oldVariable(i, PV->RHO) = rho;
6192
6193 if(m_isThermal) {
6194 a_kappa(i) = m_kappa;
6195 a_variable(i, PV->T) = 1.0;
6196 a_oldVariable(i, PV->T) = 1.0;
6197 }
6198 if(m_isTransport) {
6199 a_variable(i, PV->C) = 0.0;
6200 a_oldVariable(i, PV->C) = 0.0;
6201 }
6202
6203 // the viscosity is saved for each cell
6204 // this is needed for subgrid modelling
6205 initNu(i, m_nu);
6206 });
6207
6209
6210 if(m_isThermal) {
6212 }
6213 if(m_isTransport) {
6215 }
6216}

◆ initLatticeBgkLaminarPipe()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkLaminarPipe
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_LAMINAR_PIPE_INIT

Initializes standard Lattice BGK Laminar Pipe. Set property "initMethod" to "LB_LAMINAR_PIPE_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkLaminarPipe(), initLatticeBgkLaminarPipe, LaminarPipeInit}

Definition at line 5217 of file lbsolverdxqy.cpp.

5217 {
5218 TRACE();
5219
5220 MFloat yPlus;
5221
5222 ScratchSpace<MFloat> bBox(nDim * 2, AT_, "bBox");
5223 MIntScratchSpace o_dirs(nDim - 1, AT_, "o_dirs");
5224 MFloat* bBoxPtr = &bBox[0];
5225 m_geometry->getBoundingBox(bBoxPtr);
5226
5227 MFloat rho;
5228
5229 MInt mainDir = 0;
5230 MInt otherDirs = 0;
5231 MFloat maxLength = F0;
5232 for(MInt d = 0; d < nDim; d++) {
5233 if(fabs(bBox[d + nDim] - bBox[d]) > maxLength) {
5234 mainDir = d;
5235 maxLength = fabs(bBox[d + nDim] - bBox[d]);
5236 } else {
5237 o_dirs[otherDirs] = d;
5238 otherDirs++;
5239 }
5240 }
5241
5242 // all cells have the same density
5243 if(m_densityFluctuations)
5244 rho = 0.0;
5245 else
5246 rho = 1.0;
5247
5248 for(MInt i = 0; i < a_noCells(); i++) {
5249 MFloat radius = 0.0;
5250 for(MInt dir = 0; dir < nDim; dir++) {
5251 if(dir == mainDir) continue;
5252 radius += a_coordinate(i, dir) * a_coordinate(i, dir);
5253 }
5254 radius = sqrt(radius);
5255
5256 const MFloat tmpWidth = 0.5 * fabs(bBox[o_dirs[0] + nDim] - bBox[o_dirs[0]]);
5257
5258 yPlus = radius / tmpWidth;
5259
5260 for(MInt dir = 0; dir < nDim; dir++) {
5261 a_variable(i, PV->VV[dir]) = 0.0;
5262 }
5263 a_variable(i, PV->VV[mainDir]) = 2.0 * (1.0 - yPlus * yPlus) * m_Ma * LBCS; // v_max = 2*v_mean
5264 if(m_isThermal) {
5265 a_variable(i, PV->T) =
5266 this->m_initTemperatureKelvin - (this->m_initTemperatureKelvin - F1) * (1.0 - yPlus * yPlus);
5267 }
5268 if(m_isTransport) {
5269 a_variable(i, PV->C) = this->m_initCon - (this->m_initCon - F1) * (1.0 - yPlus * yPlus);
5270 }
5271
5272 a_variable(i, PV->RHO) = rho;
5273
5274 // the viscosity is saved for each cell
5275 // this is needed for subgrid modelling
5276 if(m_isThermal) {
5277 a_kappa(i) = m_kappa;
5278 a_variable(i, PV->T) = 1.0;
5279 a_oldVariable(i, PV->T) = 1.0;
5280 }
5281 initNu(i, m_nu);
5282 }
5283
5285
5286 if(m_isThermal) {
5288 }
5289 if(m_isTransport) {
5291 }
5292}

◆ initLatticeBgkSpinningVorticies()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkSpinningVorticies
Author
Miro Gondrum
Date
23.06.2021
Property value initMethod
LB_SPINNING_VORTICIES_INIT

Initializes standard Lattice BGK spinning vorticies. Set property "initMethod" to "LB_SPINNING_VORTICIES_INIT" to use this function.

\LBIC{LbSolverDxQy::initLatticeBgkSpinningVorticies(), initLatticeBgkSpinningVorticies, SpinningVorticiesInit}

Definition at line 5762 of file lbsolverdxqy.cpp.

5762 {
5763 TRACE();
5764
5765 // normal zero init
5766 // initLatticeBgkLaminarDir(-1);
5767
5768 // Fixed values for initial time and density
5769 const MFloat t = 0.0;
5770 // const MFloat gamma = Context::getSolverProperty<MFloat>("circulation", this->m_solverId, AT_);
5771 const MFloat r0 = Context::getSolverProperty<MFloat>("r0", this->m_solverId, AT_);
5772 const MFloat rC = Context::getSolverProperty<MFloat>("coreRadius", this->m_solverId, AT_);
5773 // Vatistas vortex core model (nC = 1 corresponds to Scully model)
5774 MInt nC = 1;
5775 nC = Context::getSolverProperty<MInt>("coreModelExponent", this->m_solverId, AT_, &nC);
5776 // Calculate rotation frequency and offsets
5777 const MFloat gamma = m_Ma * LBCS * 4.0 * PI * r0; // units !: [u_lb * l_stl]
5778 const MFloat dx = (this->c_cellLengthAtLevel(maxLevel()));
5779 const MFloat omega = m_Ma * LBCS / (r0 / dx);
5780 const MFloat bx = r0 * cos(omega * t);
5781 const MFloat by = r0 * sin(omega * t);
5782
5783 const MFloat periode = 2.0 * PI / omega;
5784 m_log << " Info spinning vorticities init: " << std::endl
5785 << " * Iterations for one full rotation: " << periode << std::endl;
5786 const MFloat resolutionFactor = rC / dx;
5787 m_log << " * coreRadius / dx_maxLevel = " << resolutionFactor << std::endl;
5788
5789
5790 // Set initial condition for all cells
5791 maia::parallelFor<false>(0, a_noCells(), [=](MInt cellId) {
5792 // Calculate vortex-local coordinates
5793 const MFloat x = a_coordinate(cellId, 0);
5794 const MFloat y = a_coordinate(cellId, 1);
5795 const MFloat rPos = std::sqrt(POW2(x - bx) + POW2(y - by));
5796 const MFloat thetaPos = std::atan2(y - by, x - bx);
5797 const MFloat rNeg = std::sqrt(POW2(x + bx) + POW2(y + by));
5798 const MFloat thetaNeg = std::atan2(y + by, x + bx);
5799
5800 // Determine velocity from potential flow theory (x and y direction)
5801 MFloat u[2] = {0.0, 0.0};
5802 {
5803 const MFloat factorPos = (nC == 1) ? rPos / (rC * rC + rPos * rPos)
5804 : rPos / std::pow(std::pow(rC, 2 * nC) + std::pow(rPos, 2 * nC), 1.0 / nC);
5805 const MFloat factorNeg = (nC == 1) ? rNeg / (rC * rC + rNeg * rNeg)
5806 : rNeg / std::pow(std::pow(rC, 2 * nC) + std::pow(rNeg, 2 * nC), 1.0 / nC);
5807 u[0] = (factorPos * std::sin(thetaPos) + factorNeg * std::sin(thetaNeg)) * (-gamma / 2.0 / PI);
5808 u[1] = (factorPos * std::cos(thetaPos) + factorNeg * std::cos(thetaNeg)) * (gamma / 2.0 / PI);
5809 }
5810
5811 // Set macroscopic variables
5812 // Determine pressure using steady-state Bernoulli equation
5813 const MFloat usqrB2 = 0.5 * (u[0] * u[0] + u[1] * u[1]);
5814 // const MFloat rho = 1.0 - usqrB2 / (CSsq + usqrB2);
5815 const MFloat rho = 1.0 / (1.0 + usqrB2 * F1BCSsq);
5816 a_variable(cellId, PV->RHO) = rho;
5817 a_variable(cellId, PV->U) = rho * u[0];
5818 a_variable(cellId, PV->V) = rho * u[1];
5819 a_oldVariable(cellId, PV->U) = a_variable(cellId, PV->U);
5820 a_oldVariable(cellId, PV->V) = a_variable(cellId, PV->V);
5821 if constexpr(nDim == 3) {
5822 a_variable(cellId, PV->W) = 0.0;
5823 a_oldVariable(cellId, PV->W) = 0.0;
5824 }
5825 initNu(cellId, m_nu);
5826 });
5827
5829}
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125

◆ initLatticeBgkTGV()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkTGV
virtual
Author
Moritz Waldmann
Date
29.11.2019
Property value initMethod
LB_TGV_INIT

Initializes standard Lattice BGK TGV. Set property "initMethod" to "LB_TGV_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkTGV(), initLatticeBgkTGV, TGVlInit}

Definition at line 5306 of file lbsolverdxqy.cpp.

5306 {
5307 TRACE();
5308 IF_CONSTEXPR(nDim != 3) TERMM(1, "Only implemented for 3D");
5309
5310 MFloat rho, rho0, u[3];
5311 MFloat p, p0;
5312
5313 // all cells have the same density
5314 rho0 = F1;
5315 p0 = rho0 * F1B3;
5316
5317 for(MInt i = 0; i < a_noCells(); i++) {
5318 const MFloat xCoord = a_coordinate(i, 0);
5319 const MFloat yCoord = a_coordinate(i, 1);
5320 const MFloat zCoord = a_coordinate(i, 2);
5321
5322 const MFloat x = (cos(F2 * zCoord) + F2) * (cos(F2 * xCoord) + cos(F2 * yCoord));
5323 const MFloat y = sin(xCoord) * cos(yCoord) * cos(zCoord);
5324 const MFloat z = cos(xCoord) * sin(yCoord) * cos(zCoord);
5325
5326 p = p0 + rho0 * (m_Ma * m_Ma) * F1B3 / 16.0 * x;
5327 rho = F3 * p;
5328 u[0] = m_Ma * LBCS * y;
5329 u[1] = -m_Ma * LBCS * z;
5330 u[2] = F0;
5331
5332 a_variable(i, PV->RHO) = rho;
5333
5334 // the viscosity is saved for each cell
5335 // this is necessary for subgrid modelling
5336 initNu(i, m_nu);
5337
5338 a_variable(i, PV->U) = u[0];
5339 a_variable(i, PV->V) = u[1];
5340 a_variable(i, PV->W) = u[2];
5341 }
5343}

◆ initLatticeBgkTurbulentBoundary()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkTurbulentBoundary
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_TURBULENT_BOUNDARY

Initializes standard Lattice BGK Turbulent Boundary. Set property "initMethod" to "LB_TURBULENT_BOUNDARY"

\LBIC{LbSolverDxQy::initLatticeBgkTurbulentBoundary(), initLatticeBgkTurbulentBoundary, TurbulentBoundaryInit}

Definition at line 5357 of file lbsolverdxqy.cpp.

5357 {
5358 TRACE();
5359
5360 MFloat yPlus;
5361 MFloat amp = 0.1;
5362 MFloat uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
5363 ScratchSpace<MFloat> bBox(nDim * 2, AT_, "bBox");
5364 MFloat* bBoxPtr = &bBox[0];
5365 m_geometry->getBoundingBox(bBoxPtr);
5366
5367 MFloat rho;
5368
5369 // all cells have the same density
5370 if(m_densityFluctuations)
5371 rho = 0.0;
5372 else
5373 rho = 1.0;
5374
5375 const MFloat tmpWidth = fabs(bBox[1 + nDim] - bBox[1]);
5376
5377 for(MInt i = 0; i < a_noCells(); i++) {
5378 a_variable(i, PV->RHO) = rho;
5379
5380 yPlus = m_ReTau * (fabs(a_coordinate(i, 1)) / tmpWidth + 0.5);
5381
5382 if(yPlus <= 5.0) {
5383 a_variable(i, PV->U) = uTau * yPlus;
5384 } else {
5385 if(yPlus <= 30 && yPlus > 5.0) {
5386 a_variable(i, PV->U) = uTau * (C1 * log(yPlus) + C2);
5387 } else {
5388 if(yPlus > 30) {
5389 a_variable(i, PV->U) = uTau * (C3 * log(yPlus) + C4);
5390 }
5391 }
5392 }
5393
5394 // deltaU =amp * 2.0 * (0.5 - 0.2*(MFloat) (1.0*rand()/(RAND_MAX+1.0))) * u[0];
5395 a_variable(i, PV->U) += amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->U);
5396
5397 for(MInt dir = 1; dir < nDim; dir++) {
5398 a_variable(i, PV->VV[dir]) = amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->U);
5399 }
5400
5401 // the viscosity is saved for each cell
5402 // this is needed for subgrid modelling
5403 initNu(i, m_nu);
5404 }
5406}

◆ initLatticeBgkTurbulentChannel()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkTurbulentChannel
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_TURBULENT_CHANNEL_INIT

Initializes standard Lattice BGK Turbulent Channel. Set property "initMethod" to "LB_TURBULENT_CHANNEL_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkTurbulentChannel(), initLatticeBgkTurbulentChannel, TurbulentChannelInit}

Definition at line 5420 of file lbsolverdxqy.cpp.

5420 {
5421 TRACE();
5422
5423 MFloat yPlus;
5424 MFloat amp = 0.1;
5425 MFloat uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
5426
5427 MFloat rho;
5428
5429 // all cells have the same density
5430 if(m_densityFluctuations)
5431 rho = 0.0;
5432 else
5433 rho = 1.0;
5434
5435 // tmpWidth = 0.5 * fabs(bBox[1 + nDim]-bBox[1]);
5436 // tmpwidth equals diameter * cellLength (on maxLevel)
5437 const MFloat tmpWidth = m_referenceLength * this->c_cellLengthAtLevel(maxLevel());
5438
5439 for(MInt i = 0; i < a_noCells(); i++) {
5440 a_variable(i, PV->RHO) = rho;
5441
5442 yPlus = m_ReTau * (1.0 - fabs(a_coordinate(i, 1)) / tmpWidth);
5443
5444 if(yPlus <= 5.0) {
5445 a_variable(i, PV->U) = uTau * yPlus;
5446 } else {
5447 if(yPlus <= 30 && yPlus > 5.0) {
5448 a_variable(i, PV->U) = uTau * (C1 * log(yPlus) + C2);
5449 } else {
5450 if(yPlus > 30) {
5451 a_variable(i, PV->U) = uTau * (C3 * log(yPlus) + C4);
5452 }
5453 }
5454 }
5455
5456 // deltaU =amp * 2.0 * (0.5 - 0.2*(MFloat) (1.0*rand()/(RAND_MAX+1.0))) * u[0];
5457 a_variable(i, PV->U) += amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->U);
5458
5459 for(MInt dir = 1; dir < nDim; dir++) {
5460 a_variable(i, PV->VV[dir]) = amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->U);
5461 }
5462
5463 // the viscosity is saved for each cell
5464 // this is needed for subgrid modelling
5465 initNu(i, m_nu);
5466 }
5468}

◆ initLatticeBgkTurbulentDuct()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkTurbulentDuct
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_TURBULENT_DUCT_INIT

Initializes standard Lattice BGK Turbulent Duct. Set property "initMethod" to "LB_TURBULENT_DUCT_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkTurbulentDuct(), initLatticeBgkTurbulentDuct, TurbulentDuctInit}

Definition at line 5482 of file lbsolverdxqy.cpp.

5482 {
5483 TRACE();
5484 IF_CONSTEXPR(nDim != 3) TERMM(1, "Only implemented for 3D. For 2D use a channel!");
5485
5486 MFloat deltaU, deltaW; // deltaV;
5487 MFloat yPlus;
5488 MFloat amp = 0.1;
5489 MFloat uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
5490 MFloat radius = 0;
5491
5492 ScratchSpace<MFloat> bBox(nDim * 2, AT_, "bBox");
5493 MFloat* bBoxPtr = &bBox[0];
5494 m_geometry->getBoundingBox(bBoxPtr);
5495
5496 MFloat rho;
5497
5498 // all cells have the same density
5499 if(m_densityFluctuations)
5500 rho = 0.0;
5501 else
5502 rho = 1.0;
5503
5504 const MFloat tmpWidth = fabs(bBox[1 + nDim] - bBox[1]);
5505
5506 for(MInt i = 0; i < a_noCells(); i++) {
5507 radius = sqrt(a_coordinate(i, 1) * a_coordinate(i, 1) + a_coordinate(i, 2) * a_coordinate(i, 2));
5508
5509 yPlus = (1.0 - radius / tmpWidth * 2.0) * m_ReTau;
5510 if(yPlus <= 5.0) {
5511 a_variable(i, PV->U) = uTau * yPlus;
5512 } else {
5513 if(yPlus <= 30 && yPlus > 5.0) {
5514 a_variable(i, PV->U) = uTau * (C1 * log(yPlus) + C2);
5515 } else {
5516 if(yPlus > 30) {
5517 a_variable(i, PV->U) = uTau * (C3 * log(yPlus) + C4);
5518 }
5519 }
5520 }
5521
5522 deltaU = amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->U);
5523 a_variable(i, PV->U) += deltaU;
5524
5525 // deltaV =amp * 2.0 * (0.5 - (MFloat) (1.0*rand()/(RAND_MAX+1.0))) * a_variable(i, PV->U);
5526
5527 deltaW = amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->U);
5528 a_variable(i, PV->V) = 0.0;
5529 a_variable(i, PV->W) = deltaW;
5530 a_variable(i, PV->RHO) = rho;
5531
5532 // the viscosity is saved for each cell
5533 // this is needed for subgrid modelling
5534 initNu(i, m_nu);
5535 }
5537}

◆ initLatticeBgkTurbulentMixing()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkTurbulentMixing
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_TURBULENT_MIXING_INIT

Initializes standard Lattice BGK Turbulent Mixing Layer. Set property "initMethod" to "LB_TURBULENT_MIXING_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkTurbulentMixing(), initLatticeBgkTurbulentMixing, TurbulentMixingInit}

Definition at line 5551 of file lbsolverdxqy.cpp.

5551 {
5552 TRACE();
5553 IF_CONSTEXPR(nDim != 3) mTerm(1, AT_, "Only implemented for 3D. For 2D use a channel!");
5554
5555 MFloat amp = 0.2 * m_Ma * LBCS;
5556 MFloat GaussFactor, sigma, deltaOmega0;
5557 MFloat rho;
5558
5559 ScratchSpace<MFloat> bBox(nDim * 2, AT_, "bBox");
5560 MFloat* bBoxPtr = &bBox[0];
5561 m_geometry->getBoundingBox(bBoxPtr);
5562
5563 // all cells have the same density
5564 if(m_densityFluctuations)
5565 rho = 0.0;
5566 else
5567 rho = 1.0;
5568
5569 // initial vorticity thickness
5570 deltaOmega0 = m_referenceLength * m_smallestCellLength;
5571
5572 m_log << " initial macroscopic vorticity thickness: " << deltaOmega0 << endl;
5573
5574 // width of the Gaussian distribution for perturbation scaling
5575 // depends on initial vorticity thickness
5576 sigma = deltaOmega0;
5577
5578 for(MInt i = 0; i < a_noCells(); i++) {
5579 // set the mean velocity profile
5580 a_variable(i, PV->U) = m_Ma * LBCS * tanh(2.0 * a_coordinate(i, 1) / deltaOmega0);
5581 for(MInt dir = 1; dir < nDim; dir++) {
5582 a_variable(i, PV->VV[dir]) = 0.0;
5583 }
5584 a_variable(i, PV->RHO) = rho;
5585
5586 GaussFactor = exp(-(a_coordinate(i, 1) / sigma) * (a_coordinate(i, 1) / sigma) * F1B2);
5587
5588 a_variable(i, PV->U) += amp * F2 * (distrib(randNumGen) - F1B2) * GaussFactor;
5589
5590 for(MInt dir = 1; dir < nDim; dir++) {
5591 a_variable(i, PV->VV[dir]) = amp * F2 * (distrib(randNumGen) - F1B2) * GaussFactor;
5592 }
5593
5594 // the viscosity is saved for each cell
5595 // this is needed for subgrid modelling
5596 initNu(i, m_nu);
5597 }
5598
5599
5601}
std::uniform_real_distribution distrib
Definition: lbsolverdxqy.h:323
std::mt19937 randNumGen
Definition: lbsolverdxqy.h:322

◆ initLatticeBgkTurbulentPipe()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkTurbulentPipe
virtual
Author
Andreas Lintermann
Date
24.01.2014
Property value initMethod
LB_TURBULENT_PIPE_INIT

Initializes standard Lattice BGK Turbulent Pipe. Set property "initMethod" to "LB_TURBULENT_PIPE_INIT"

\LBIC{LbSolverDxQy::initLatticeBgkTurbulentPipe(), initLatticeBgkTurbulentPipe, TurbulentPipeInit}

Definition at line 5615 of file lbsolverdxqy.cpp.

5615 {
5616 TRACE();
5617
5618 MFloat yPlus;
5619 MFloat amp = 0.1;
5620 MFloat uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
5621 MFloat radius = 0;
5622 ScratchSpace<MFloat> bBox(nDim * 2, AT_, "bBox");
5623 MFloat* bBoxPtr = &bBox[0];
5624
5625 m_geometry->getBoundingBox(bBoxPtr);
5626
5627 MFloat rho;
5628
5629 // all cells have the same density
5630 if(m_densityFluctuations)
5631 rho = 0.0;
5632 else
5633 rho = 1.0;
5634
5635 // since interpolated bounce back is used, this is the real half diameter
5636 const MFloat tmpWidth = 0.5 * fabs(bBox[1 + nDim] - bBox[1]);
5637
5638 for(MInt i = 0; i < a_noCells(); i++) {
5639 for(MInt dir = 0; dir < nDim - 1; dir++) {
5640 radius += a_coordinate(i, dir) * a_coordinate(i, dir);
5641 }
5642 radius = sqrt(radius);
5643
5644 yPlus = m_ReTau * (1.0 - radius / tmpWidth);
5645
5646 if(yPlus <= 5.0) {
5647 a_variable(i, PV->VV[nDim - 1]) = uTau * yPlus;
5648 } else {
5649 if(yPlus <= 30 && yPlus > 5.0) {
5650 a_variable(i, PV->VV[nDim - 1]) = uTau * (C1 * log(yPlus) + C2);
5651 } else {
5652 if(yPlus > 30) {
5653 a_variable(i, PV->VV[nDim - 1]) = uTau * (C3 * log(yPlus) + C4);
5654 }
5655 }
5656 }
5657
5658 for(MInt dir = 0; dir < nDim - 1; dir++) {
5659 a_variable(i, PV->VV[dir]) =
5660 amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->VV[nDim - 1]);
5661 }
5662 a_variable(i, PV->VV[nDim - 1]) +=
5663 amp * 2.0 * (0.5 - (MFloat)(1.0 * rand() / (RAND_MAX + 1.0))) * a_variable(i, PV->VV[nDim - 1]);
5664 a_variable(i, PV->RHO) = rho;
5665
5666 // the viscosity is saved for each cell
5667 // this is needed for subgrid modelling
5668 initNu(i, m_nu);
5669 }
5671}

◆ initLatticeBgkVortex()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initLatticeBgkVortex
virtual
Author
Miro Gondrum
Date
15.05.2021
Property value initMethod
LB_STEADY_VORTEX_INIT
Property value initMethod
LB_CONVECTING_VORTEX_INIT

Initializes standard Lattice BGK Vortex (at rest or convecting). Set property "initMethod" to "LB_SPINNING_VORTICIES_INIT" or "LB_CONVECTING_VORTEX_INIT" to use this function.

Vortex is represented by vortex core model A. Najafi-Yazdi, 2012. (http://dx.doi.org/10.1016/j.compfluid.2012.07.017)

\LBIC{LbSolverDxQy::initLatticeBgkVortex(), initLatticeBgkVortex, VortexInit}

Definition at line 5690 of file lbsolverdxqy.cpp.

5690 {
5691 TRACE();
5692
5693 MFloat coreRadius = 0.2;
5694 std::array<MFloat, 2> position;
5695 MBool eqInit = false;
5696 position.fill(0.0);
5697
5698 coreRadius = Context::getSolverProperty<MFloat>("vortexCoreRadius", this->m_solverId, AT_, &coreRadius);
5699 const MFloat umax = Context::getSolverProperty<MFloat>("vortexMachMax", this->m_solverId, AT_, &m_Ma) * LBCS;
5700 eqInit = Context::getSolverProperty<MBool>("vortexEqInit", this->m_solverId, AT_, &eqInit);
5701 if(Context::propertyExists("vortexPosition", this->m_solverId)) {
5702 for(MInt d = 0; d < 2; d++) {
5703 position[d] = Context::getSolverProperty<MFloat>("vortexPosition", this->m_solverId, AT_, d);
5704 }
5705 }
5706
5707 std::array<MFloat, 2> u_b = {0.0, 0.0};
5708 if(string2enum(m_initMethod) == LB_CONVECTING_VORTEX_INIT) {
5709 u_b[0] = m_Ma * LBCS;
5710 }
5711
5712 if(domainId() == 0) {
5713 std::stringstream ss;
5714 ss << "Info: " << string2enum(m_initMethod) << std::endl;
5715 ss << " vortexCoreRadius : " << coreRadius << std::endl;
5716 ss << " vortexUmax : " << umax << std::endl;
5717 ss << " vortexPosition : " << position[0] << ", " << position[1] << std::endl;
5718 std::cout << ss.str();
5719 }
5720
5721 maia::parallelFor<false>(0, a_noCells(), [=](MInt cellId) {
5722 const MFloat x = a_coordinate(cellId, 0) - position[0];
5723 const MFloat y = a_coordinate(cellId, 1) - position[1];
5724 const MFloat r_rel = std::sqrt(POW2(x) + POW2(y)) / coreRadius;
5725 const MFloat theta = std::atan2(y, x);
5726 const MFloat factor = umax * std::exp(0.5);
5727 // Determine velocity from potential flow theory (x and y direction)
5728 MFloat up[2] = {0.0, 0.0};
5729 {
5730 const MFloat u_tan = factor * r_rel * std::exp(-0.5 * POW2(r_rel));
5731 up[0] = -std::sin(theta) * u_tan;
5732 up[1] = std::cos(theta) * u_tan;
5733 }
5734 const MFloat rho0 = 1.0;
5735 // const MFloat rho = rho0 * std::exp(-POW2(factor) / (2.0 * CSsq) * std::exp(1.0 - POW2(r_rel)));
5736 const MFloat rho = rho0 * std::exp(-0.5 * POW2(factor * F1BCS) * std::exp(-POW2(r_rel)));
5737 a_variable(cellId, PV->RHO) = rho;
5738 a_variable(cellId, PV->U) = (u_b[0] + up[0]);
5739 a_variable(cellId, PV->V) = (u_b[1] + up[1]);
5740 if constexpr(nDim == 3) a_variable(cellId, PV->W) = 0.0;
5741 initNu(cellId, m_nu);
5742 });
5743 if(eqInit) {
5745 } else {
5747 }
5748}
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494

◆ initNonEqDistFunctions()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initNonEqDistFunctions

Definition at line 6238 of file lbsolverdxqy.cpp.

6238 {
6239 TRACE();
6240 // first init equilibrium everywhere
6242
6243 // now add non-equilibrium part
6244 maia::parallelFor<false>(0, a_noCells(), [&](MInt i) {
6245 // calculate spatial derivatives of velocity vector in the current cell center
6246 MFloat c[nDim][nDim]; // dv/dz = c[1][2]
6247 this->calculateVelocityDerivative(i, c);
6248
6249 MFloat trace = 0.0;
6250 for(MInt d = 0; d < nDim; d++) {
6251 trace += c[d][d];
6252 }
6253
6254 // add non-eq parts
6255 // cf. Eq (5.88), Krueger et al., 2017, https://doi.org/10.1007/978-3-319-44649-3 .
6256 const MInt lvlDiff = maxLevel() - a_level(i);
6257 const MFloat tau = F1B2 + F1BCSsq * a_nu(i) * FFPOW2(lvlDiff); // tau_0
6258 const MFloat tauRho = tau * a_variable(i, PV->RHO);
6259 for(MInt dist = 0; dist < nDist - 1; dist++) {
6260 const MFloat t = Ld::tp(Ld::distType(dist));
6261 a_distribution(i, dist) += t * tauRho * trace;
6262 for(MInt k = 0; k < nDim; k++) {
6263 for(MInt l = 0; l < nDim; l++) {
6264 a_distribution(i, dist) -=
6265 t * tauRho * F1BCSsq * (Ld::idFld(dist, k) - 1) * (Ld::idFld(dist, l) - 1) * c[l][k];
6266 }
6267 }
6268 }
6269 a_distribution(i, Ld::lastId()) += Ld::tp(0) * tauRho * trace;
6270
6271 // oldDist = dist
6272 for(MInt j = 0; j < Ld::lastId() + 1; j++) {
6273 a_oldDistribution(i, j) = a_distribution(i, j);
6274 }
6275 });
6276}

◆ initPressureForce()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initPressureForce
overrideprivate

brief activate all cells, but the halo cells

The pressure force is calculated on the lowest level of Refinement. One half of the forcing term is added after the collision, and the other half is added after streaming. This ensures correct forcing at half-way bounce-back boundaries.

Definition at line 7413 of file lbsolverdxqy.cpp.

7413 {
7414 TRACE();
7415
7416 /*********************************************/
7417 /* 2D LAMINAR CHANNEL INITIALIZATION */
7418 /* m_referenceLength must be channel half width !!! */
7419 /* Ma refers to velocity on centerline !!! */
7420 /*********************************************/
7421 if(string2enum(m_initMethod) == LB_LAMINAR_CHANNEL_INIT) {
7422 // Re must be defined for channel half height
7423
7424 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
7425
7426 m_densityGradient = m_Ma * LBCS * 9.0 * m_nu / (m_referenceLength * m_referenceLength);
7427
7428 constexpr MInt dir = 0;
7429 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7430 m_Fext[Ld::nFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * -1.0 * m_densityGradient;
7431 m_Fext[Ld::pFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * 1.0 * m_densityGradient;
7432 }
7433 }
7434
7435 /*********************************************/
7436 /* TURBULENT CHANNEL INITIALIZATION */
7437 /* m_referenceLength must be channel half width !!! */
7438 /* Ma refers to velocity on centerline !!! */
7439 /*********************************************/
7440 if(string2enum(m_initMethod) == LB_TURBULENT_CHANNEL_INIT) {
7441 // For now testing only the D3Q19 algorithm
7442 MFloat uTau;
7443
7444 // Re must be defined for channel half width
7445 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
7446 uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
7447
7448 // The ratio between the turb. channel length and channel half width : ratio = L/H
7449 // MFloat ratio = m_domainLength/m_referenceLength;
7450
7451 m_densityGradient = 3.0 * uTau * uTau / m_referenceLength;
7452
7453 constexpr MInt dir = 0;
7454 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7455 m_Fext[Ld::nFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * -1.0 * m_densityGradient;
7456 m_Fext[Ld::pFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * 1.0 * m_densityGradient;
7457 }
7458 }
7459
7460 /**************************************/
7461 /* TURBULENT DUCT INITIALIZATION */
7462 /**************************************/
7463 if(string2enum(m_initMethod) == LB_TURBULENT_DUCT_INIT) {
7464 // For now testing only the D3Q19 algorithm
7465 MFloat uTau;
7466
7467 uTau = (MFloat)m_ReTau / m_Re * m_Ma * LBCS;
7468 MFloat ratio = m_domainLength / (m_referenceLength * F1B2);
7469
7470 m_densityGradient = 3.0 * uTau * uTau * ratio / m_domainLength;
7471
7472 constexpr MInt dir = 0;
7473 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7474 m_Fext[Ld::nFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * -1.0 * m_densityGradient;
7475 m_Fext[Ld::pFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * 1.0 * m_densityGradient;
7476 }
7477 }
7478
7479 /*************************************************/
7480 /* TURBULENT PIPE INITIALIZATION */
7481 /* m_referenceLength must be pipe diameter !!! */
7482 /* Ma refers to the maximum streamwise velocity !!! */
7483 /* u_mean = 0.816 * u_max */
7484 /*************************************************/
7485 if(string2enum(m_initMethod) == LB_TURBULENT_PIPE_INIT) {
7486 // For now testing only the D3Q19 algorithm
7487 MFloat uTau;
7488
7489 // uTau = (MFloat)m_ReTau/m_Re * m_Ma * LBCS ;
7490 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
7491 uTau = (MFloat)m_ReTau * m_nu / m_referenceLength;
7492
7493 /*
7494 MFloat ratio = m_domainLength/m_referenceLength;
7495 // pressure drop over entire length according to Blasius law (IN THIS CASE Ma DEFINES THE MEAN VELOCITY!)
7496 m_gradient = 0.3164 * pow(m_Re,-0.25) * ratio * (m_Ma*LBCS) * (m_Ma*LBCS) / 2;//rho=1
7497 */
7498
7499 // density drop per cell
7500 m_densityGradient = 3.0 * 2.0 * uTau * uTau / (F1B2 * m_referenceLength); // Pope, p.293
7501
7502 if constexpr(nDim != 3) {
7503 std::stringstream ss;
7504 ss << "Init method " << m_initMethod << " is only available for 3D." << std::endl;
7505 TERMM(1, ss.str());
7506 }
7507 constexpr MInt dir = 2;
7508 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7509 m_Fext[Ld::nFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * -1.0 * m_densityGradient;
7510 m_Fext[Ld::pFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * 1.0 * m_densityGradient;
7511 }
7512 }
7513
7514 /*******************************/
7515 /* LAMINAR PIPE INITIALIZATION */
7516 /*******************************/
7517 if(string2enum(m_initMethod) == LB_LAMINAR_PIPE_INIT) {
7518 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
7519
7520 // law of Hagen Poiseuille
7521 // The pressure gradient is one third of the density gradient !
7522 // m_gradient = 3*F1B2*(m_Ma*LBCS)*m_domainLength/m_referenceLength/m_referenceLength*64.0*m_nu;
7523 m_densityGradient =
7524 3.0 * 8.0 * (m_Ma * LBCS) * m_nu / ((F1B2 * m_referenceLength) * (F1B2 * m_referenceLength)); // rho=1
7525
7526 if constexpr(nDim != 3) {
7527 std::stringstream ss;
7528 ss << "Init method " << m_initMethod << " is only available for 3D." << std::endl;
7529 TERMM(1, ss.str());
7530 }
7531 constexpr MInt dir = 2;
7532 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7533 m_Fext[Ld::nFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * -1.0 * m_densityGradient;
7534 m_Fext[Ld::pFld(dir, mi)] = Ld::tp(Ld::distType(mi)) * 1.0 * m_densityGradient;
7535 }
7536 }
7537}

◆ initRunCorrection()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initRunCorrection
overrideprivate

Definition at line 7641 of file lbsolverdxqy.cpp.

7641 {
7642 if(this->isCompressible()) {
7643 initRunCorrection_<true>();
7644 } else {
7645 initRunCorrection_<false>();
7646 }
7647}

◆ initRunCorrection_()

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool compressible>
void LbSolverDxQy< nDim, nDist, SysEqn >::initRunCorrection_
private
Author
Miro Gondrum
Date
19.01.2022

For the init method following Mei et al. the initial velocity field is kept constant and only density/pressure and the non-equilibrium field is updated. This function does the correction independent of chosen methods. This is done by Resetting 1) .. macroscopic state from (rho, u) to (rho, u0) 2) .. mesoscopic state from f=f_neq + f_eq(rho,u) to f=f_neq + f_eq(rho,u0) Thus, LBM solves only a Poisson equation for the pressure. ref.: Mei et al. 2006: https://doi.org/10.1016/j.compfluid.2005.08.008

Definition at line 7586 of file lbsolverdxqy.cpp.

7586 {
7587 TRACE();
7588 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
7589 const MInt gTS = globalTimeStep;
7590
7591 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt i) {
7592 const MInt pCellId = m_activeCellList[i];
7593 const MInt lvlDiff = maxLevel() - c_level(pCellId);
7594 if((gTS) % IPOW2(lvlDiff) != 0) return;
7595 // In the following step only rho is updated while u is kept
7596 // constant with its initial state u0.
7597 // 1) Calculate rho, rho*u and the associated f_eq(rho, u)
7598#ifdef WAR_NVHPC_PSTL
7599 MFloat u[nDim] = {F0};
7600 for(MInt d = 0; d < nDim; d++) {
7601 u[d] = a_variable(pCellId, d);
7602 }
7603 calculateMacroscopicVariables<compressible>(pCellId, a_variable(pCellId, PV->RHO), u);
7604 for(MInt d = 0; d < nDim; d++) {
7605 a_variable(pCellId, d) = u[d];
7606 }
7607#else
7608 calculateMacroscopicVariables<compressible>(pCellId, a_variable(pCellId, PV->RHO), &a_variable(pCellId, PV->U));
7609#endif
7610 MFloat eqDist[nDist], trgEqDist[nDist];
7611#ifdef WAR_NVHPC_PSTL
7612 for(MInt d = 0; d < nDim; d++) {
7613 u[d] = a_variable(pCellId, d);
7614 }
7615 sysEqn().calcEqDists(a_variable(pCellId, PV->RHO), u, &eqDist[0], m_mFld1.data(), m_mFld2.data(), m_tp.data(),
7616 m_distFld.data());
7617#else
7618 sysEqn().calcEqDists(a_variable(pCellId, PV->RHO), &a_variable(pCellId, PV->U), &eqDist[0]);
7619#endif
7620 // 2) Set state to (rho, u0) and calculate associated f_eq(rho, u0)
7621 for(MInt d = 0; d < nDim; d++) {
7622 a_variable(pCellId, PV->U + d) = a_oldVariable(pCellId, PV->U + d);
7623 }
7624#ifdef WAR_NVHPC_PSTL
7625 for(MInt d = 0; d < nDim; d++) {
7626 u[d] = a_variable(pCellId, d);
7627 }
7628 sysEqn().calcEqDists(a_variable(pCellId, PV->RHO), u, &trgEqDist[0], m_mFld1.data(), m_mFld2.data(), m_tp.data(),
7629 m_distFld.data());
7630#else
7631 sysEqn().calcEqDists(a_variable(pCellId, PV->RHO), &a_variable(pCellId, PV->U), &trgEqDist[0]);
7632#endif
7633 // 3) Reset f such that: f_new = f_eq(rho, u0) + f_neq(rho, u)
7634 for(MInt j = 0; j < nDist; j++) {
7635 a_oldDistribution(pCellId, j) = a_oldDistribution(pCellId, j) + trgEqDist[j] - eqDist[j];
7636 }
7637 });
7638}

◆ initSrcTermController()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initSrcTermController
override
Author
Miro Gondrum
Date
01.02.2022

Definition at line 4924 of file lbsolverdxqy.cpp.

4924 {
4925 TRACE();
4926 m_srcTermController.init();
4927}

◆ initSrcTerms()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initSrcTerms
override
Author
Julian Vorspohl
Date
01.05.2024

Definition at line 4934 of file lbsolverdxqy.cpp.

4934 {
4935 TRACE();
4936 m_srcTermController.initSrcTerms();
4937}

◆ initThermalEqDistFunctions()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initThermalEqDistFunctions
virtual
Author
Andreas Lintermann
Date
23.02.2011

This is pretty much the same function as initEqDistFunctions(), except that the thermal macroscopic variable \(T\) (temperature) is initilized as well with \(T = 1.0\). After that, the equilibrium distribution functions are calculated for all the LBGK- and the TLBGK-case.

Definition at line 6288 of file lbsolverdxqy.cpp.

6288 {
6289 TRACE();
6290
6291 for(MInt i = 0; i < a_noCells(); i++) {
6292 const MFloat rho = a_variable(i, PV->RHO);
6293 const MFloat t = a_variable(i, PV->T);
6294 std::array<MFloat, nDim> u;
6295 for(MInt d = 0; d < nDim; d++) {
6296 u[d] = a_variable(i, d);
6297 }
6298
6299 setEqDistsThermal(i, t, rho, u.data());
6300 }
6301}
void setEqDistsThermal(const MInt cellId, const MFloat T, const MFloat rho, const MFloat *const velocity)
Calls function for setting thermal distributions to equilibrium.
Definition: lbsolverdxqy.h:462

◆ initTransportEqDistFunctions()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initTransportEqDistFunctions
virtual
Author
Shota Ito
Date
07.06.2022

This is pretty much the same function as initEqDistFunctions(), except that the transport macroscopic variable \(C\) (concentration) is initilized as well with \(C = 1.0\). After that, the equilibrium distribution functions are calculated for all the LBGK- and the Transport-LBGK-case.

Definition at line 6313 of file lbsolverdxqy.cpp.

6313 {
6314 TRACE();
6315
6316 for(MInt i = 0; i < a_noCells(); i++) {
6317 const MFloat c = a_variable(i, PV->C);
6318 std::array<MFloat, nDim> u;
6319 for(MInt d = 0; d < nDim; d++) {
6320 u[d] = a_variable(i, d);
6321 }
6322
6323 setEqDistsTransport(i, c, u.data());
6324 }
6325}
void setEqDistsTransport(const MInt cellId, const MFloat C, const MFloat *const velocity)
Set BOTH transport distributions to equilibrium.
Definition: lbsolverdxqy.h:607

◆ initVolumeForces()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::initVolumeForces
overrideprivate

Definition at line 7540 of file lbsolverdxqy.cpp.

7540 {
7541 static MBool firstCall = true;
7542 static MFloat origFext[nDist];
7543 if(firstCall) {
7544 // save the incoming m_Fext to recall them at re-initializations triggered by velocity control
7545 firstCall = false;
7546 for(MInt i = 0; i < nDist; i++) {
7547 origFext[i] = m_Fext[i];
7548 }
7549 }
7550 for(MInt dir = 0; dir < nDim; dir++) {
7551 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7552 m_Fext[Ld::nFld(dir, mi)] =
7553 origFext[Ld::nFld(dir, mi)] + Ld::tp(Ld::distType(Ld::nFld(dir, mi))) * -1.0 * m_volumeAccel[dir] * 3.0;
7554 m_Fext[Ld::pFld(dir, mi)] =
7555 origFext[Ld::pFld(dir, mi)] + Ld::tp(Ld::distType(Ld::pFld(dir, mi))) * 1.0 * m_volumeAccel[dir] * 3.0;
7556 }
7557 }
7558
7559 if(m_isEELiquid) {
7560 for(MInt dir = 0; dir < nDim; dir++) {
7561 for(MInt mi = 0; mi < Ld::dxQyFld(); mi++) {
7562 m_EELiquid.Fg[Ld::nFld(dir, mi)] =
7563 Ld::tp(Ld::distType(Ld::nFld(dir, mi))) * -1.0 * m_EELiquid.gravityAccelM[dir] * 3.0;
7564 m_EELiquid.Fg[Ld::pFld(dir, mi)] =
7565 Ld::tp(Ld::distType(Ld::pFld(dir, mi))) * 1.0 * m_EELiquid.gravityAccelM[dir] * 3.0;
7566 }
7567 }
7568 }
7569}

◆ maxResidual()

template<MInt nDim, MInt nDist, class SysEqn >
MBool LbSolverDxQy< nDim, nDist, SysEqn >::maxResidual
virtual

Definition at line 7395 of file lbsolverdxqy.cpp.

7395 {
7396 TRACE();
7397
7398 if(globalTimeStep % m_residualInterval == 0) {
7400 }
7401
7402 return true;
7403}
virtual void calculateResidual()
Calculates residuals and prints to file.

◆ mrt2_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::mrt2_collision_step
override
Author
Miro Gondrum (Refactored)
Date
03.11.2021
Property value solverMethod
MAIA_LATTICE_MRT2

Collision step for the MRT-Algorithm with optimized parameters This function wraps mrt_collision_step_base to access MRT-Algorithm with optimized parameters.

Definition at line 4104 of file lbsolverdxqy.cpp.

4104 {
4105 mrt_collision_step_base<true, false>();
4106}

◆ mrt_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::mrt_collision_step
override
Author
Miro Gondrum (Refactored)
Date
03.11.2021
Property value solverMethod
MAIA_LATTICE_MRT

Collision step for the MRT-Algorithm with standard parameters This function wraps mrt_collision_step_base to access MRT-Algorithm with standard parameters.

Definition at line 4089 of file lbsolverdxqy.cpp.

4089 {
4090 mrt_collision_step_base<false, false>();
4091}

◆ mrt_collision_step_base() [1/3]

void LbSolverDxQy< 2, 9, maia::lb::LbSysEqnIncompressible< 2, 9 > >::mrt_collision_step_base ( )

Definition at line 3682 of file lbsolverdxqy.cpp.

3682 {
3683 TRACE();
3684 constexpr MInt nDist = 9;
3685 // constexpr MInt nDim = 2;
3686
3687 constexpr MFloat c1 = -2.0, alpha2 = -8.0, alpha3 = 4.0, gamma1 = F2B3, gamma3 = F2B3, gamma2 = 18.0, gamma4 = -18.0;
3688
3689 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
3690 const MInt pCellId = m_activeCellList[i];
3691 const MInt lvlDiff = maxLevel() - this->a_level(pCellId);
3692 if((globalTimeStep - 1) % IPOW2(lvlDiff) == 0) {
3693 std::array<MFloat, nDist> d{};
3694 for(MInt j = 0; j < nDist; j++) {
3695 d[j] = a_oldDistribution(pCellId, j);
3696 }
3697
3698 std::array<MFloat, nDist> m{};
3699 m[0] = d[8] + d[1] + d[3] + d[0] + d[2] + d[4] + d[7] + d[6] + d[5];
3700 m[1] = -4 * d[8] - d[1] - d[3] - d[0] - d[2] + 2 * (d[4] + d[7] + d[6] + d[5]);
3701 m[2] = 4 * d[8] + 2 * (-d[1] - d[3] - d[0] - d[2]) + d[4] + d[7] + d[6] + d[5];
3702 m[3] = d[1] - d[0] + d[4] - d[7] - d[6] + d[5];
3703 m[4] = -2 * (d[1] - d[0]) + d[4] - d[7] - d[6] + d[5];
3704 m[5] = d[3] - d[2] + d[4] + d[7] - d[6] - d[5];
3705 m[6] = -2 * (d[3] - d[2]) + d[4] + d[7] - d[6] - d[5];
3706 m[7] = d[1] - d[3] + d[0] - d[2];
3707 m[8] = d[4] - d[7] + d[6] - d[5];
3708
3709 // Relaxation in moment space
3710 // 1. Set relaxation parameters
3711 std::array<MFloat, nDist> omega{};
3712 omega[0] = 0.0;
3713 omega[1] = 1.63;
3714 omega[2] = 1.14;
3715 omega[3] = 0.0;
3716 omega[5] = 0.0;
3717 omega[6] = 1.92;
3718 omega[7] = (2.0 - c1) / (12.0 * a_nu(pCellId) * FFPOW2(lvlDiff) + 1.0 - c1 / 2.0);
3719 omega[8] = 1.0 / ((2.0 / omega[7] - 1.0) * ((c1 + 4.0) / (2.0 - c1)) + 0.5);
3720 omega[4] = 3.0 * (2.0 - omega[7]) / (3.0 - omega[7]);
3721
3722 // 2. Calculate equilibrium Moments
3723 std::array<MFloat, nDist> EqM{};
3724 EqM[0] = m[0];
3725 EqM[3] = m[3];
3726 EqM[5] = m[5];
3727 EqM[1] = 0.25 * alpha2 * m[0] + F1B6 * gamma2 * (m[3] * m[3] + m[5] * m[5]);
3728 EqM[2] = 0.25 * alpha3 * m[0] + F1B6 * gamma4 * (m[3] * m[3] + m[5] * m[5]);
3729 EqM[4] = 0.5 * c1 * m[3];
3730 EqM[6] = 0.5 * c1 * m[5];
3731 EqM[7] = F3B2 * gamma1 * (m[3] * m[3] - m[5] * m[5]);
3732 EqM[8] = F3B2 * gamma3 * (m[3] * m[5]);
3733
3734 // 3. Relax Moments
3735 for(MInt j = 0; j < nDist; j++) {
3736 m[j] = m[j] - omega[j] * (m[j] - EqM[j]);
3737 }
3738
3739 a_distribution(pCellId, 8) = F1B9 * m[0] - F1B9 * m[1] + F1B9 * m[2];
3740 a_distribution(pCellId, 1) = F1B9 * m[0] - F1B36 * m[1] - F1B18 * m[2] + F1B6 * m[3] - F1B6 * m[4] + F1B4 * m[7];
3741 a_distribution(pCellId, 3) = F1B9 * m[0] - F1B36 * m[1] - F1B18 * m[2] + F1B6 * m[5] - F1B6 * m[6] - F1B4 * m[7];
3742 a_distribution(pCellId, 0) = F1B9 * m[0] - F1B36 * m[1] - F1B18 * m[2] - F1B6 * m[3] + F1B6 * m[4] + F1B4 * m[7];
3743 a_distribution(pCellId, 2) = F1B9 * m[0] - F1B36 * m[1] - F1B18 * m[2] - F1B6 * m[5] + F1B6 * m[6] - F1B4 * m[7];
3744 a_distribution(pCellId, 4) = F1B9 * m[0] + F1B18 * m[1] + F1B36 * m[2] + F1B6 * m[3] + F1B12 * m[4] + F1B6 * m[5]
3745 + F1B12 * m[6] + F1B4 * m[8];
3746 a_distribution(pCellId, 7) = F1B9 * m[0] + F1B18 * m[1] + F1B36 * m[2] - F1B6 * m[3] - F1B12 * m[4] + F1B6 * m[5]
3747 + F1B12 * m[6] - F1B4 * m[8];
3748 a_distribution(pCellId, 6) = F1B9 * m[0] + F1B18 * m[1] + F1B36 * m[2] - F1B6 * m[3] - F1B12 * m[4] - F1B6 * m[5]
3749 - F1B12 * m[6] + F1B4 * m[8];
3750 a_distribution(pCellId, 5) = F1B9 * m[0] + F1B18 * m[1] + F1B36 * m[2] + F1B6 * m[3] + F1B12 * m[4] - F1B6 * m[5]
3751 - F1B12 * m[6] - F1B4 * m[8];
3752 }
3753 }
3754}

◆ mrt_collision_step_base() [2/3]

void LbSolverDxQy< 3, 19, maia::lb::LbSysEqnIncompressible< 3, 19 > >::mrt_collision_step_base ( )

Definition at line 3758 of file lbsolverdxqy.cpp.

3758 {
3759 TRACE();
3760 constexpr MInt nDist = 19;
3761 constexpr MInt nDim = 3;
3762 constexpr MInt nDimSqr = nDim * nDim;
3763
3764 const MFloat rho_offset = (m_densityFluctuations) ? 1.0 : 0.0;
3765
3766 // Only relevant for Smagorinsky model
3767 [[maybe_unused]] const MFloat tmpWidth = m_referenceLength * m_smallestCellLength;
3768 [[maybe_unused]] constexpr MFloat aPlus = 26.0;
3769
3770 for(MInt id = 0; id < m_currentMaxNoCells; id++) {
3771 const MInt pCellId = m_activeCellList[id];
3772
3773 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
3774 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
3775
3776 MFloat d[nDist];
3777 for(MInt j = 0; j < nDist; j++) {
3778 d[j] = a_oldDistribution(pCellId, j);
3779 }
3780
3781 // Set old variables (for residual calculation)
3782 for(MInt j = 0; j < nDim + 1; j++) {
3783 a_oldVariable(pCellId, j) = a_variable(pCellId, j);
3784 }
3785
3786 MFloat m[nDist];
3787 m[0] = d[18] + d[1] + d[0] + d[3] + d[2] + d[5] + d[4] + d[9] + d[7] + d[8] + d[6] + d[13] + d[11] + d[12] + d[10]
3788 + d[17] + d[15] + d[16] + d[14];
3789 m[1] = -30 * d[18] - 11 * (d[1] + d[0] + d[3] + d[2] + d[5] + d[4])
3790 + 8 * (d[9] + d[7] + d[8] + d[6] + d[13] + d[11] + d[12] + d[10] + d[17] + d[15] + d[16] + d[14]);
3791 m[2] = 12 * d[18] - 4 * (d[1] + d[0] + d[3] + d[2] + d[5] + d[4]) + d[9] + d[7] + d[8] + d[6] + d[13] + d[11]
3792 + d[12] + d[10] + d[17] + d[15] + d[16] + d[14];
3793 m[3] = d[1] - d[0] + d[9] - d[7] + d[8] - d[6] + d[13] - d[11] + d[12] - d[10];
3794 m[4] = -4 * (d[1] - d[0]) + d[9] - d[7] + d[8] - d[6] + d[13] - d[11] + d[12] - d[10];
3795 m[5] = d[3] - d[2] + d[9] + d[7] - d[8] - d[6] + d[17] - d[15] + d[16] - d[14];
3796 m[6] = -4 * (d[3] - d[2]) + d[9] + d[7] - d[8] - d[6] + d[17] - d[15] + d[16] - d[14];
3797 m[7] = d[5] - d[4] + d[13] + d[11] - d[12] - d[10] + d[17] + d[15] - d[16] - d[14];
3798 m[8] = -4 * (d[5] - d[4]) + d[13] + d[11] - d[12] - d[10] + d[17] + d[15] - d[16] - d[14];
3799 m[9] = 2 * (d[1] + d[0] - d[15] - d[16] - d[14]) - d[3] - d[2] - d[5] - d[4] + d[9] + d[7] + d[8] + d[6] + d[13]
3800 + d[11] + d[12] + d[10] - 2 * d[17];
3801 m[10] = -4 * (d[1] + d[0]) + 2 * (d[3] + d[2] + d[5] + d[4] - d[17] - d[15] - d[16] - d[14]) + d[9] + d[7] + d[8]
3802 + d[6] + d[13] + d[11] + d[12] + d[10];
3803 m[11] = d[3] + d[2] - d[5] - d[4] + d[9] + d[7] + d[8] + d[6] - d[13] - d[11] - d[12] - d[10];
3804 m[12] = -2 * (d[3] + d[2] - d[5] - d[4]) + d[9] + d[7] + d[8] + d[6] - d[13] - d[11] - d[12] - d[10];
3805 m[13] = d[9] - d[7] - d[8] + d[6];
3806 m[14] = d[17] - d[15] - d[16] + d[14];
3807 m[15] = d[13] - d[11] - d[12] + d[10];
3808 m[16] = d[9] - d[7] + d[8] - d[6] - d[13] + d[11] - d[12] + d[10];
3809 m[17] = -d[9] - d[7] + d[8] + d[6] + d[17] - d[15] + d[16] - d[14];
3810 m[18] = d[13] + d[11] - d[12] - d[10] - d[17] - d[15] + d[16] + d[14];
3811
3812 // Relaxation in moment space
3813 // 1. Set relaxation parameters
3814 MFloat P[nDist];
3815 const MFloat tmp = (optimized) ? 0.0 : 1.0;
3816 P[0] = tmp;
3817 P[1] = 1.19;
3818 P[2] = 1.4;
3819 P[3] = tmp;
3820 P[4] = 1.2;
3821 P[5] = tmp;
3822 P[6] = P[4];
3823 P[7] = tmp;
3824 P[8] = P[4];
3825 P[9] = 2.0 / (FFPOW2(maxLevel() - this->a_level(pCellId)) * 6.0 * m_nu + 1.0);
3826 P[10] = P[2];
3827 P[11] = P[9];
3828 P[12] = P[2];
3829 P[13] = P[9];
3830 P[14] = P[9];
3831 P[15] = P[9];
3832 P[16] = 1.98;
3833 P[17] = P[16];
3834 P[18] = P[16];
3835
3836 // 2. Calculate equilibrium Moments
3837 MFloat EqM[nDist];
3838 EqM[0] = m[0]; // rho
3839 EqM[3] = m[3]; // j_x
3840 EqM[5] = m[5]; // j_y
3841 EqM[7] = m[7]; // j_z
3842
3843 //---------------------------------------------------------------------------------
3844 // d'Humieres et al., 2002 (standard/optimized parameters)
3845 // compressible form
3846 EqM[1] = -11.0 * m[0] + 19.0 * (m[3] * m[3] + m[5] * m[5] + m[7] * m[7]) / (m[0] + rho_offset); // e
3847
3848 if constexpr(optimized) {
3849 EqM[2] = -F475B63 * (m[3] * m[3] + m[5] * m[5] + m[7] * m[7]) / (m[0] + rho_offset); // epsilon
3850 } else {
3851 EqM[2] = 3.0 * m[0] - 5.5 * (m[3] * m[3] + m[5] * m[5] + m[7] * m[7]) / (m[0] + rho_offset); // epsilon
3852 }
3853
3854 EqM[4] = -F2B3 * m[3]; // q_x
3855 EqM[6] = -F2B3 * m[5]; // q_y
3856 EqM[8] = -F2B3 * m[7]; // q_z
3857
3858 EqM[9] = (2 * m[3] * m[3] - (m[5] * m[5] + m[7] * m[7])) / (m[0] + rho_offset); // 3*p_xx
3859
3860 if constexpr(optimized) {
3861 EqM[10] = 0.0;
3862 } else {
3863 EqM[10] = -0.5 * EqM[9]; // 3*pi_xx
3864 }
3865 EqM[11] = (m[5] * m[5] - m[7] * m[7]) / (m[0] + rho_offset); // p_ww
3866 if constexpr(optimized) {
3867 EqM[12] = 0.0;
3868 } else {
3869 EqM[12] = -0.5 * EqM[11]; // pi_ww
3870 }
3871 EqM[13] = m[3] * m[5] / (m[0] + rho_offset); // p_xy
3872 EqM[14] = m[5] * m[7] / (m[0] + rho_offset); // p_yz
3873 EqM[15] = m[3] * m[7] / (m[0] + rho_offset); // p_xz
3874 EqM[16] = 0;
3875 EqM[17] = 0;
3876 EqM[18] = 0;
3877
3878 // // incompressible form assuming <rho> = 1
3879 // EqM[1] = -11.0 * m[0] + 19.0 * ( m[3] * m[3] + m[5] * m[5] + m[7] * m[7] ); // e
3880
3881 // EqM[2] = 3.0 * m[0] - 5.5 * ( m[3] * m[3] + m[5] * m[5] + m[7] * m[7] ); // epsilon
3882
3883 // EqM[4] = -F2B3 * m[3] ; // q_x
3884 // EqM[6] = -F2B3 * m[5] ; // q_y
3885 // EqM[8] = -F2B3 * m[7] ; // q_z
3886
3887 // EqM[9] = ( 2*m[3]*m[3] - (m[5] * m[5] + m[7] * m[7]) ); // 3*p_xx
3888
3889 // EqM[10] = -0.5 * EqM[9] ; // 3*pi_xx
3890 // EqM[11] = ( m[5] * m[5] - m[7] * m[7] ); // p_ww
3891 // EqM[12] = -0.5 * EqM[11] ; // pi_ww
3892 // EqM[13] = m[3] * m[5]; // p_xy
3893 // EqM[14] = m[5] * m[7]; // p_yz
3894 // EqM[15] = m[3] * m[7]; // p_xz
3895 // EqM[16] = 0 ;
3896 // EqM[17] = 0 ;
3897 // EqM[18] = 0 ;
3898
3899 //---------------------------------------------------------------------------------
3900
3901 // 2b. Determine macroscopic variables and calculate residual
3902 a_variable(pCellId, PV->RHO) = EqM[0];
3903 for(MInt i = 0; i < nDim; i++) {
3904 a_variable(pCellId, PV->VV[i]) = EqM[3 + i * 2] / EqM[0];
3905 }
3906
3907 // 2c. Smagorinsky model
3908 if constexpr(useSmagorinsky) {
3909 // Calculation of equilibrium and non-equilibrium distribution
3910 MFloat nonEq[nDist];
3911#ifdef WAR_NVHPC_PSTL
3912 MFloat dist[nDist] = {F0};
3913 MFloat u[nDim] = {F0};
3914 for(MInt dir = 0; dir < nDist; dir++) {
3915 dist[dir] = a_oldDistribution(pCellId, dir);
3916 }
3917 for(MInt dir = 0; dir < nDim; dir++) {
3918 u[dir] = a_variable(pCellId, dir);
3919 }
3920 MFloat l_rho = a_variable(pCellId, PV->RHO);
3921 lbfunc::calcNonEqDists<nDim, nDist>(l_rho, u, dist, &nonEq[0]);
3922#else
3923 lbfunc::calcNonEqDists<nDim, nDist>(a_variable(pCellId, PV->RHO), &a_variable(pCellId, PV->U),
3924 &a_oldDistribution(pCellId, 0), &nonEq[0]);
3925#endif
3926
3927 // Smagorinsky model
3928 const MFloat yPlus = m_ReTau * (1.0 - fabs(a_coordinate(pCellId, 1)) / tmpWidth);
3929 const MFloat lambda = m_Cs * m_deltaX * (F1 - exp(-yPlus / aPlus));
3930
3931 // Calculation of momentum flux tensor from non-equilibrium parts
3932 MFloat c[nDimSqr];
3933 c[0] = (nonEq[0] + nonEq[1] + nonEq[6] + nonEq[7] + nonEq[8] + nonEq[9] + nonEq[10] + nonEq[11] + nonEq[12]
3934 + nonEq[13]);
3935 c[1] = (nonEq[6] - nonEq[7] - nonEq[8] + nonEq[9]);
3936 c[2] = (nonEq[10] - nonEq[11] - nonEq[12] + nonEq[13]);
3937 c[3] = c[1];
3938 c[4] = (nonEq[2] + nonEq[3] + nonEq[6] + nonEq[7] + nonEq[8] + nonEq[9] + nonEq[14] + nonEq[15] + nonEq[16]
3939 + nonEq[17]);
3940 c[5] = (nonEq[14] - nonEq[15] - nonEq[16] + nonEq[17]);
3941 c[6] = c[2];
3942 c[7] = c[5];
3943 c[8] = (nonEq[4] + nonEq[5] + nonEq[10] + nonEq[11] + nonEq[12] + nonEq[13] + nonEq[14] + nonEq[15] + nonEq[16]
3944 + nonEq[17]);
3945
3946 // Calculation of the filtered mean momentum flux
3947 const MFloat Q = sqrt(2.0 * std::inner_product(&c[0], &c[nDimSqr], &c[0], .0));
3948
3949 // Calculation of new relaxation time
3950 // ..original relaxation time (on current level)
3951 MFloat tau = F1B2 + 3.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId));
3952 // ..new
3953 tau += F1B2
3954 * (sqrt(tau * tau
3955 + 2.0 * SQRT2 * lambda * lambda * (F1BCSsq * F1BCSsq) * Q
3956 * FPOW2(maxLevel() - this->a_level(pCellId)))
3957 - tau);
3958
3959 m_omega = 1.0 / tau;
3960
3961 // save total nu for bndcnd and interface interpolation (save on finest level)
3962 a_nu(pCellId) = FPOW2(maxLevel() - this->a_level(pCellId)) * (tau - F1B2) / 3.0;
3963
3964 // set new relaxation time
3965 P[9] = m_omega;
3966 }
3967
3968 // 3. Relax Moments
3969 for(MInt i = 0; i < nDist; i++) {
3970 m[i] = m[i] - P[i] * (m[i] - EqM[i]);
3971 }
3972
3973 const MFloat ra = F1B19 * m[0];
3974 const MFloat rb = F11B2394 * m[1];
3975 const MFloat rc = F1B63 * m[2];
3976 const MFloat rd = F4B1197 * m[1];
3977 const MFloat re = F1B252 * m[2];
3978 const MFloat rf = F1B12 * m[11];
3979 const MFloat rg = F1B24 * m[12];
3980 const MFloat rh = 0.25 * m[13];
3981 const MFloat ri = 0.25 * m[15];
3982 const MFloat rj = F1B36 * m[9];
3983 const MFloat rk = 2.0 * rj;
3984 const MFloat rl = F1B72 * m[10];
3985 const MFloat rm = 2.0 * rl;
3986 const MFloat rn = 0.1 * (m[3] - m[4]);
3987 const MFloat ro = 0.1 * (m[5] - m[6]);
3988 const MFloat rp = 0.1 * (m[7] - m[8]);
3989 const MFloat rq = F1B18 * (m[9] - m[10]);
3990 const MFloat rr = F1B12 * (m[11] - m[12]);
3991 const MFloat rs = 0.25e-1 * (m[4] + m[6]);
3992 const MFloat rt = 0.25e-1 * (m[4] - m[6]);
3993 const MFloat ru = 0.25e-1 * (m[4] - m[8]);
3994 const MFloat rv = 0.25e-1 * (m[4] + m[8]);
3995 const MFloat rw = 0.25e-1 * (m[6] + m[8]);
3996 const MFloat rx = 0.25e-1 * (m[6] - m[8]);
3997 const MFloat ry = 0.125 * (m[16] - m[17]);
3998 const MFloat rz = 0.125 * (m[16] + m[17]);
3999 const MFloat r0 = 0.125 * (m[16] - m[18]);
4000 const MFloat r1 = 0.125 * (m[16] + m[18]);
4001 const MFloat r2 = 0.125 * (m[17] + m[18]);
4002 const MFloat r3 = 0.125 * (m[17] - m[18]);
4003 const MFloat r4 = 0.1 * (m[5] + m[7]);
4004 const MFloat r5 = 0.1 * (m[5] - m[7]);
4005 const MFloat r6 = 0.1 * (m[3] + m[5]);
4006 const MFloat r7 = 0.1 * (m[3] - m[5]);
4007 const MFloat r8 = 0.5 * rq;
4008 const MFloat r9 = 0.1 * (m[3] + m[7]);
4009 const MFloat r10 = 0.1 * (m[3] - m[7]);
4010 const MFloat r11 = 0.25 * m[14];
4011
4012 // ra = 0.5263157895e-1*m[0];
4013 // rb = 0.4594820384e-2*m[1];
4014 // rc = 0.1587301587e-1*m[2];
4015 // rd = 0.3341687552e-2*m[1];
4016 // re = 0.3968253968e-2*m[2];
4017 // rf = 0.8333333333e-1*m[11];
4018 // rg = 0.4166666667e-1*m[12];
4019 // rh = 0.250*m[13];
4020 // ri = 0.250*m[15];
4021 // rj = 0.2777777778e-1*m[9];
4022 // rk = 2*rj;
4023 // rl = 0.1388888889e-1*m[10];
4024 // rm = 2*rl;
4025 // rn = 0.10*(m[3]-m[4]);
4026 // ro = 0.10*(m[5]-m[6]);
4027 // rp = 0.10*(m[7]-m[8]);
4028 // rq = 0.5555555556e-1*(m[9]-m[10]);
4029 // rr = 0.8333333333e-1*(m[11]-m[12]);
4030 // rs = 0.250e-1*(m[4]+m[6]);
4031 // rt = 0.250e-1*(m[4]-m[6]);
4032 // ru = 0.250e-1*(m[4]-m[8]);
4033 // rv = 0.250e-1*(m[4]+m[8]);
4034 // rw = 0.250e-1*(m[6]+m[8]);
4035 // rx = 0.250e-1*(m[6]-m[8]);
4036 // ry = 0.1250*(m[16]-m[17]);
4037 // rz = 0.1250*(m[16]+m[17]);
4038 // r0 = 0.1250*(m[16]-m[18]);
4039 // r1 = 0.1250*(m[16]+m[18]);
4040 // r2 = 0.1250*(m[17]+m[18]);
4041 // r3 = 0.1250*(m[17]-m[18]);
4042 // r4 = 0.10*(m[5]+m[7]);
4043 // r5 = 0.10*(m[5]-m[7]);
4044 // r6 = 0.10*(m[3]+m[5]);
4045 // r7 = 0.10*(m[3]-m[5]);
4046 // r8 = 0.5*rq;
4047 // r9 = 0.10*(m[3]+m[7]);
4048 // r10= 0.10*(m[3]-m[7]);
4049 // r11= 0.250*m[14];
4050
4051 a_distribution(pCellId, 18) = ra - F5B399 * m[1] + F1B21 * m[2];
4052 a_distribution(pCellId, 1) = ra - rb - rc + rn + rq;
4053 a_distribution(pCellId, 0) = ra - rb - rc - rn + rq;
4054 a_distribution(pCellId, 3) = ra - rb - rc + ro - r8 + rr;
4055 a_distribution(pCellId, 2) = ra - rb - rc - ro - r8 + rr;
4056 a_distribution(pCellId, 5) = ra - rb - rc + rp - r8 - rr;
4057 a_distribution(pCellId, 4) = ra - rb - rc - rp - r8 - rr;
4058 a_distribution(pCellId, 9) = ra + rd + re + r6 + rs + rj + rl + rf + rg + rh + ry;
4059 a_distribution(pCellId, 7) = ra + rd + re - r7 - rt + rj + rl + rf + rg - rh - rz;
4060 a_distribution(pCellId, 8) = ra + rd + re + r7 + rt + rj + rl + rf + rg - rh + rz;
4061 a_distribution(pCellId, 6) = ra + rd + re - r6 - rs + rj + rl + rf + rg + rh - ry;
4062 a_distribution(pCellId, 13) = ra + rd + re + r9 + rv + rj + rl - rf - rg + ri - r0;
4063 a_distribution(pCellId, 11) = ra + rd + re - r10 - ru + rj + rl - rf - rg - ri + r1;
4064 a_distribution(pCellId, 12) = ra + rd + re + r10 + ru + rj + rl - rf - rg - ri - r1;
4065 a_distribution(pCellId, 10) = ra + rd + re - r9 - rv + rj + rl - rf - rg + ri + r0;
4066 a_distribution(pCellId, 17) = ra + rd + re + r4 + rw - rk - rm + r11 + r3;
4067 a_distribution(pCellId, 15) = ra + rd + re - r5 - rx - rk - rm - r11 - r2;
4068 a_distribution(pCellId, 16) = ra + rd + re + r5 + rx - rk - rm - r11 + r2;
4069 a_distribution(pCellId, 14) = ra + rd + re - r4 - rw - rk - rm + r11 - r3;
4070 }
4071 }
4072
4073 if(m_calculateDissipation && globalTimeStep % m_solutionInterval == 0) {
4075 }
4076}

◆ mrt_collision_step_base() [3/3]

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool optimized, MBool useSmagorinsky>
void LbSolverDxQy< nDim, nDist, SysEqn >::mrt_collision_step_base
Author
Miro Gondrum (Refactored)
Date
03.11.2021

This function provides a collision step based on the MRT-Algorithm. It provides a version based on standard and optimized parameters Ref. :

Definition at line 3676 of file lbsolverdxqy.cpp.

3676 {
3677 TERMM(1, "MRT collision step only available for D2Q9 and D3Q19 !");
3678}

◆ mrt_smagorinsky_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::mrt_smagorinsky_collision_step
override
Author
Miro Gondrum (Refactored)
Date
03.11.2021
Property value solverMethod
MAIA_LATTICE_MRT_SMAGORINSKY

Collision step for the MRT-Algorithm + Smagorinsky turbulence model This function wraps mrt_collision_step_base to access MRT-Algorithm with standard parameters. It features a Smagorinsky turbulence model for calculating the turbulent viscosity with a van-Driest damping for turbulent channel.

Definition at line 4121 of file lbsolverdxqy.cpp.

4121 {
4122 if constexpr(nDim == 3 || nDist == 19) {
4123 mrt_collision_step_base<false, true>();
4124 } else {
4125 TERMM(1, "MRT_SMAGORINSKY collision step only available for D3Q19!");
4126 }
4127}

◆ postCollisionBc()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::postCollisionBc
override

Definition at line 4973 of file lbsolverdxqy.cpp.

4973 {
4974 TRACE();
4975
4977}
virtual void updateVariables()
Dereferences bndCndHandlerVariables.
Definition: lbbndcnd.cpp:3174

◆ postCollisionSrcTerm()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::postCollisionSrcTerm
override
Author
Miro Gondrum
Date
01.02.2022

Definition at line 4954 of file lbsolverdxqy.cpp.

4954 {
4955 TRACE();
4956 m_srcTermController.apply_postCollision();
4957}

◆ postPropagationBc()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::postPropagationBc
override

Definition at line 4983 of file lbsolverdxqy.cpp.

4983 {
4984 TRACE();
4985
4987}
virtual void updateRHS()
Dereferences bndCndHandlerRHS.
Definition: lbbndcnd.cpp:3185

◆ postPropagationSrcTerm()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::postPropagationSrcTerm
override
Author
Julian Vorspohl
Date
01.05.2024

Definition at line 4964 of file lbsolverdxqy.cpp.

4964 {
4965 TRACE();
4966 m_srcTermController.apply_postPropagation();
4967}

◆ preCollisionSrcTerm()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::preCollisionSrcTerm
override
Author
Miro Gondrum
Date
01.02.2022

Definition at line 4944 of file lbsolverdxqy.cpp.

4944 {
4945 TRACE();
4946 m_srcTermController.apply_preCollision();
4947}

◆ prolongation()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::prolongation
private

Definition at line 6529 of file lbsolverdxqy.cpp.

6529 {
6530 TRACE();
6531 m_interface->prolongation();
6532}

◆ propagation_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step
overridevirtual
Author
Andreas Lintermann
Date
03.04.2017

This function propagates the locally calculated PPDFs to the neighboring cells after the collision step.

Definition at line 74 of file lbsolverdxqy.cpp.

74 {
75 TRACE();
76
77 // MInt distStart, distNeighStart, n1Start, n2Start;
78 // inner loop references
79 const MInt noCells = a_noCells();
80
81 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
82 const MInt gTS = globalTimeStep;
83 const MInt maxLevel_ = maxLevel();
84
85 maia::parallelFor<true>(0, noCells, [=](MInt i) {
86 if(gTS % IPOW2(maxLevel_ - this->a_level(i)) != 0) return;
87 const MInt lastId = nDist - 1;
88 for(MInt j = 0; j < lastId; ++j) {
89 if(auto n = c_neighborId(i, j); n > -1) {
90 a_oldDistribution(n, j) = a_distribution(i, j);
91 }
92 }
93 a_oldDistribution(i, lastId) = a_distribution(i, lastId);
94 });
95
98
99 if(m_isRefined) {
100 restriction();
101 prolongation();
102 }
103}
void postPropagationSrcTerm() override
Calls the post collision routine of the source term controller.
virtual void volumeForces()
apply volumeForces to the oldDistributions

◆ propagation_step_thermal()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_thermal
overridevirtual

Definition at line 160 of file lbsolverdxqy.cpp.

160 {
161 TRACE();
162
163 // MInt distStart, distNeighStart, n1Start, n2Start;
164 // inner loop references
165 const MInt noCells = a_noCells();
166
167 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
168 const MInt gTS = globalTimeStep;
169 const MInt maxLevel_ = maxLevel();
170
171 maia::parallelFor<true>(0, noCells, [=](MInt i) {
172 if(gTS % IPOW2(maxLevel_ - this->a_level(i)) != 0) return;
173 const MInt lastId = nDist - 1;
174 for(MInt j = 0; j < lastId; ++j) {
175 if(auto n = c_neighborId(i, j); n > -1) {
176 a_oldDistribution(n, j) = a_distribution(i, j);
177 a_oldDistributionThermal(n, j) = a_distributionThermal(i, j);
178 }
179 }
180 a_oldDistribution(i, lastId) = a_distribution(i, lastId);
181 a_oldDistributionThermal(i, lastId) = a_distributionThermal(i, lastId);
182 });
183
184 if(m_isRefined) {
185 restriction();
186 prolongation();
187 }
188}

◆ propagation_step_thermal_vol()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_thermal_vol
overridevirtual
Author
Andreas Lintermann
Date
23.02.2011

This function propagates the locally calculated PPDFs to the neighboring cells after the collision step. The volumetric refinement scheme requires prolongation to take place before propagation

Definition at line 277 of file lbsolverdxqy.cpp.

277 {
278 TRACE();
279
280 MInt nghbrId, nghbrId2;
281
282 if(m_isRefined) prolongation();
283
284 for(MInt i = 0; i < a_noCells(); i++) {
285 if((globalTimeStep) % IPOW2(maxLevel() - this->a_level(i)) == 0) {
286 for(MInt j = 0; j < nDist - 1; j += 2) {
287 nghbrId = c_neighborId(i, j);
288 nghbrId2 = c_neighborId(i, j + 1);
289 if(nghbrId > -1) {
290 a_oldDistribution(nghbrId, j) = a_distribution(i, j);
291 a_oldDistributionThermal(nghbrId, j) = a_distributionThermal(i, j);
292 }
293 if(nghbrId2 > -1) {
294 a_oldDistribution(nghbrId2, j + 1) = a_distribution(i, j + 1);
295 a_oldDistributionThermal(nghbrId2, j + 1) = a_distributionThermal(i, j + 1);
296 }
297 }
298 a_oldDistribution(i, nDist - 1) = a_distribution(i, nDist - 1);
299 a_oldDistributionThermal(i, nDist - 1) = a_distributionThermal(i, nDist - 1);
300 }
301 }
302
303 restriction();
304}

◆ propagation_step_thermaltransport()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_thermaltransport
overridevirtual
Author
Shota Ito
Date
13.06.22

This function propagates the locally computed PPDFs to the neighboring cells after the collision step.

Definition at line 236 of file lbsolverdxqy.cpp.

236 {
237 TRACE();
238
239 // MInt distStart, distNeighStart, n1Start, n2Start;
240 // inner loop references
241 const MInt noCells = a_noCells();
242
243 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
244 const MInt gTS = globalTimeStep;
245 const MInt maxLevel_ = maxLevel();
246
247 maia::parallelFor<true>(0, noCells, [=](MInt i) {
248 if(gTS % IPOW2(maxLevel_ - this->a_level(i)) != 0) return;
249 const MInt lastId = nDist - 1;
250 for(MInt j = 0; j < lastId; ++j) {
251 if(auto n = c_neighborId(i, j); n > -1) {
252 a_oldDistribution(n, j) = a_distribution(i, j);
253 a_oldDistributionThermal(n, j) = a_distributionThermal(i, j);
254 a_oldDistributionTransport(n, j) = a_distributionTransport(i, j);
255 }
256 }
257 a_oldDistribution(i, lastId) = a_distribution(i, lastId);
258 a_oldDistributionThermal(i, lastId) = a_distributionThermal(i, lastId);
259 a_oldDistributionTransport(i, lastId) = a_distributionTransport(i, lastId);
260 });
261
262 if(m_isRefined) {
263 restriction();
264 prolongation();
265 }
266}

◆ propagation_step_thermaltransport_vol()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_thermaltransport_vol
overridevirtual
Author
Shota Ito
Date
13.06.22

Definition at line 349 of file lbsolverdxqy.cpp.

349 {
350 TRACE();
351
352 MInt nghbrId, nghbrId2;
353
354 if(m_isRefined) prolongation();
355
356 for(MInt i = 0; i < a_noCells(); i++) {
357 if((globalTimeStep) % IPOW2(maxLevel() - this->a_level(i)) == 0) {
358 for(MInt j = 0; j < nDist - 1; j += 2) {
359 nghbrId = c_neighborId(i, j);
360 nghbrId2 = c_neighborId(i, j + 1);
361 if(nghbrId > -1) {
362 a_oldDistribution(nghbrId, j) = a_distribution(i, j);
363 a_oldDistributionThermal(nghbrId, j) = a_distributionThermal(i, j);
364 a_oldDistributionTransport(nghbrId, j) = a_distributionTransport(i, j);
365 }
366 if(nghbrId2 > -1) {
367 a_oldDistribution(nghbrId2, j + 1) = a_distribution(i, j + 1);
368 a_oldDistributionThermal(nghbrId2, j + 1) = a_distributionThermal(i, j + 1);
369 a_oldDistributionTransport(nghbrId2, j + 1) = a_distributionTransport(i, j + 1);
370 }
371 }
372 a_oldDistribution(i, nDist - 1) = a_distribution(i, nDist - 1);
373 a_oldDistributionThermal(i, nDist - 1) = a_distributionThermal(i, nDist - 1);
374 a_oldDistributionTransport(i, nDist - 1) = a_distributionTransport(i, nDist - 1);
375 }
376 }
377
378 restriction();
379}

◆ propagation_step_transport()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_transport
overridevirtual
Author
Shota Ito
Date
07.06.22

This function propagates the locally computed PPDFs to the neighboring cells after the collision step.

Definition at line 198 of file lbsolverdxqy.cpp.

198 {
199 TRACE();
200
201 // MInt distStart, distNeighStart, n1Start, n2Start;
202 // inner loop references
203 const MInt noCells = a_noCells();
204
205 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
206 const MInt gTS = globalTimeStep;
207 const MInt maxLevel_ = maxLevel();
208
209 maia::parallelFor<true>(0, noCells, [=](MInt i) {
210 if(gTS % IPOW2(maxLevel_ - this->a_level(i)) != 0) return;
211 const MInt lastId = nDist - 1;
212 for(MInt j = 0; j < lastId; ++j) {
213 if(auto n = c_neighborId(i, j); n > -1) {
214 a_oldDistribution(n, j) = a_distribution(i, j);
215 a_oldDistributionTransport(n, j) = a_distributionTransport(i, j);
216 }
217 }
218 a_oldDistribution(i, lastId) = a_distribution(i, lastId);
219 a_oldDistributionTransport(i, lastId) = a_distributionTransport(i, lastId);
220 });
221
222 if(m_isRefined) {
223 restriction();
224 prolongation();
225 }
226}

◆ propagation_step_transport_vol()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_transport_vol
overridevirtual
Author
Shota Ito
Date
07.06.22

This function does the same as the propagation_step_thermal_vol but for Transport Lattice Boltzmann.

Definition at line 314 of file lbsolverdxqy.cpp.

314 {
315 TRACE();
316
317 MInt nghbrId, nghbrId2;
318
319 if(m_isRefined) prolongation();
320
321 for(MInt i = 0; i < a_noCells(); i++) {
322 if((globalTimeStep) % IPOW2(maxLevel() - this->a_level(i)) == 0) {
323 for(MInt j = 0; j < nDist - 1; j += 2) {
324 nghbrId = c_neighborId(i, j);
325 nghbrId2 = c_neighborId(i, j + 1);
326 if(nghbrId > -1) {
327 a_oldDistribution(nghbrId, j) = a_distribution(i, j);
328 a_oldDistributionTransport(nghbrId, j) = a_distributionTransport(i, j);
329 }
330 if(nghbrId2 > -1) {
331 a_oldDistribution(nghbrId2, j + 1) = a_distribution(i, j + 1);
332 a_oldDistributionTransport(nghbrId2, j + 1) = a_distributionTransport(i, j + 1);
333 }
334 }
335 a_oldDistribution(i, nDist - 1) = a_distribution(i, nDist - 1);
336 a_oldDistributionTransport(i, nDist - 1) = a_distributionTransport(i, nDist - 1);
337 }
338 }
339
340 restriction();
341}

◆ propagation_step_vol()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::propagation_step_vol
overridevirtual

Definition at line 113 of file lbsolverdxqy.cpp.

113 {
114 TRACE();
115
116 MInt nghbrId, nghbrId2;
117
118 if(m_isRefined) prolongation();
119
120 for(MInt i = 0; i < a_noCells(); i++) {
121 if((globalTimeStep) % IPOW2(maxLevel() - this->a_level(i)) == 0) {
122 for(MInt j = 0; j < nDist - 1; j += 2) {
123 nghbrId = c_neighborId(i, j);
124 nghbrId2 = c_neighborId(i, j + 1);
125
126 if(nghbrId > -1) a_oldDistribution(nghbrId, j) = a_distribution(i, j);
127 if(nghbrId2 > -1) a_oldDistribution(nghbrId2, j + 1) = a_distribution(i, j + 1);
128 }
129 a_oldDistribution(i, nDist - 1) = a_distribution(i, nDist - 1);
130 }
131 }
132
133 restriction();
134
135 //--
136
137 // #define WRITECELLVALUES
138#ifdef WRITECELLVALUES
139 ofstream ofl;
140
141 if((globalTimeStep) % 40 == 0) {
142 if(domainId() == 7) {
143 ofl.open("x0p75.dat", ios_base::app);
144 ofl << globalTimeStep << " " << a_variable(212707, 0) << " " << a_variable(212707, 1) << " "
145 << a_variable(212707, 2) << " " << a_variable(212707, 3) << endl;
146 ofl.close();
147
148 ofl.open("x1p5.dat", ios_base::app);
149 ofl << globalTimeStep << " " << a_variable(235107, 0) << " " << a_variable(235107, 1) << " "
150 << a_variable(235107, 2) << " " << a_variable(235107, 3) << endl;
151 ofl.close();
152 }
153 }
154#endif
155
156 //--
157}

◆ rbgk_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::rbgk_collision_step
override
Property value solverMethod
MAIA_LATTICE_RBGK

Collision step for the regularized LBGK-Algorithm

Definition at line 4270 of file lbsolverdxqy.cpp.

4270 {
4271 rbgk_collision_step_base<false>();
4272}

◆ rbgk_collision_step_base()

template<MInt nDim, MInt nDist, class SysEqn >
template<MBool useSmagorinsky>
void LbSolverDxQy< nDim, nDist, SysEqn >::rbgk_collision_step_base

Definition at line 4131 of file lbsolverdxqy.cpp.

4131 {
4132 TRACE();
4133
4134 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
4135 MFloat scale =
4136 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
4137 + 0.5;
4138
4139 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
4140
4141 // final timestep reached
4142 if(globalTimeStep == m_initStartTime + m_initTime) {
4143 m_Re = m_finalRe;
4144 m_tanhInit = 0;
4145 }
4146 }
4147 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
4148
4149 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
4150 const MInt pCellId = m_activeCellList[i];
4151
4152 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
4153 // save nu for bndcnd and interface interpolation
4154 a_nu(pCellId) = m_nu;
4155
4156 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
4157 swap_variables(pCellId);
4158
4159 // Calculate macroscopic variables
4160 a_variable(pCellId, PV->RHO) = 0.0;
4161 for(MInt j = 0; j < nDist; j++) {
4162 a_variable(pCellId, PV->RHO) += a_oldDistribution(pCellId, j);
4163 }
4164
4165 const MFloat rho = a_variable(pCellId, PV->RHO);
4166
4167 MFloat u[nDim];
4168 for(MInt j = 0; j < nDim; j++) {
4169 u[j] = F0;
4170 }
4171
4172 if constexpr(nDim == 2) {
4173 // warning!!! the velocity should be calculated as in 3d
4174 // however, result is correct
4175 // calculation of u
4176 u[0] = a_oldDistribution(pCellId, 1) + a_oldDistribution(pCellId, 4) + a_oldDistribution(pCellId, 5)
4177 - a_oldDistribution(pCellId, 7) - a_oldDistribution(pCellId, 6) - a_oldDistribution(pCellId, 0);
4178 // calculation of v
4179 u[1] = a_oldDistribution(pCellId, 7) + a_oldDistribution(pCellId, 3) + a_oldDistribution(pCellId, 4)
4180 - a_oldDistribution(pCellId, 6) - a_oldDistribution(pCellId, 2) - a_oldDistribution(pCellId, 5);
4181 } else {
4182 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
4183 for(MInt d = 0; d < nDim; d++) {
4184 u[d] += a_oldDistribution(pCellId, Ld::pFld(d, j));
4185 u[d] -= a_oldDistribution(pCellId, Ld::nFld(d, j));
4186 }
4187 }
4188 }
4189
4190 for(MInt j = 0; j < nDim; j++) {
4191 a_variable(pCellId, j) = u[j];
4192 }
4193
4194 // Calculation of equilibrium and non-equilibrium distribution
4195 std::array<MFloat, nDist> eqDist;
4196 eqDist = getEqDists(rho, u);
4197
4198 // Calculation of momentum flux tensor for non-equilibrium parts
4199 //--------------------------------------------
4200 // \Pi_{\alpha,\beta} = \sum_i f_i \cdot c_{i,\alpha}c_{i,\beta}
4201
4202 calculateMomentumFlux(pCellId);
4203
4204 if constexpr(useSmagorinsky) {
4205 // Calculation of overall viscosity
4206 // according to Hu, Sterling, Chen 1994
4207
4208 // 1. Calculation of original relaxation time (on current level)
4209 MFloat tau = F1B2 + 3.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId));
4210
4211 // 2. Calculation of the filtered mean momentum flux
4212 MFloat Q = F0;
4213 for(MInt l = 0; l < nDim * nDim; l++) {
4214 Q += m_momentumFlux[pCellId][l] * m_momentumFlux[pCellId][l];
4215 }
4216 Q = sqrt(2 * Q);
4217
4218 // 3. Calculation of new relaxation time
4219 tau += F1B2
4220 * (sqrt(tau * tau
4221 + 2.0 * SQRT2 * m_Cs * m_Cs * m_deltaX * m_deltaX * (F1BCSsq * F1BCSsq) * Q
4222 * FPOW2(maxLevel() - this->a_level(pCellId)))
4223 - tau);
4224
4225 m_omega = 1.0 / tau;
4226
4227 // save total nu for bndcnd and interface interpolation (save on finest level)
4228 a_nu(pCellId) = FPOW2(maxLevel() - this->a_level(pCellId)) * (tau - F1B2) / 3.0;
4229 }
4230
4231 // Calculation of new distributions for directions with at least one component
4232 MFloat trace = F0;
4233
4234 if constexpr(nDim == 2) {
4235 trace = m_momentumFlux[pCellId][0] + m_momentumFlux[pCellId][3];
4236 } else {
4237 trace = m_momentumFlux[pCellId][0] + m_momentumFlux[pCellId][4] + m_momentumFlux[pCellId][8];
4238 }
4239
4240 for(MInt j = 0; j < nDist - 1; j++) {
4241 const MInt t = Ld::tp(Ld::distType(j));
4242
4243 a_distribution(pCellId, j) = eqDist[j] - (1.0 - m_omega) * t * F1BCSsq * F1B2 * trace;
4244
4245 for(MInt k = 0; k < nDim; k++) {
4246 for(MInt l = 0; l < nDim; l++) {
4247 a_distribution(pCellId, j) += (1.0 - m_omega) * t * F1BCSsq * F1BCSsq * F1B2 * (Ld::idFld(j, k) - 1)
4248 * (Ld::idFld(j, l) - 1) * m_momentumFlux[pCellId][l + nDim * k];
4249 }
4250 }
4251 }
4252 // Calculation of new distribution for rest particle distribution (center)
4253 a_distribution(pCellId, Ld::lastId()) =
4254 eqDist[Ld::lastId()] - (1.0 - m_omega) * Ld::tp(0) * F1BCSsq * F1B2 * trace;
4255 }
4256 }
4257
4258 if(m_calculateDissipation && globalTimeStep % m_solutionInterval == 0) {
4260 }
4261}

◆ rbgk_dynamic_smago_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::rbgk_dynamic_smago_collision_step
override
Property value solverMethod
MAIA_LATTICE_RBGK_DYNAMIC_SMAGO

Collision step for the regularized LBGK-Algorithm + dynamic Smagorinsky turbulence model

Definition at line 4292 of file lbsolverdxqy.cpp.

4292 {
4293 TRACE();
4294
4296 for(MInt i = 0; i < this->noInternalCells(); i++) {
4298 }
4300
4301 std::vector<MFloat> dynamicCs;
4302 constexpr MInt direction = 1;
4303 MInt count = 0;
4304 averageSGSTensors(direction, count, dynamicCs);
4305
4306 for(MInt i = 0; i < count; i++) {
4307 if(dynamicCs[i] < 0.0) dynamicCs[i] = 0.0;
4308 // if(dynamicCs[i]>0.04)
4309 // dynamicCs[i] = 0.04;
4310 }
4311
4312 MFloat rho = F0;
4313 MFloat u[nDim];
4314 MFloat Q = F0;
4315 MFloat tau = F0;
4316 MFloat S = F0;
4317
4318 MInt index = 0;
4319 MFloat actualCellLength = F0;
4320
4321 MChar buf[10];
4322 MString fileName;
4323 ofstream ofl;
4324
4325 // dissipation values
4326 ScratchSpace<MFloat> diss(m_arraySize[direction], AT_, "diss");
4327 ScratchSpace<MFloat> totalDiss(m_arraySize[direction], AT_, "totalDiss");
4328 ScratchSpace<MFloat> SGSDiss(m_arraySize[direction], AT_, "SGSDiss");
4329 ScratchSpace<MFloat> totalSGSDiss(m_arraySize[direction], AT_, "totalSGSDiss");
4330 MFloat energy;
4331
4332 // reset dissipation and energy values
4333 for(MInt i = 0; i < count; i++) {
4334 diss[i] = F0;
4335 SGSDiss[i] = F0;
4336 }
4337 energy = F0;
4338
4339 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
4340 MFloat scale =
4341 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
4342 + 0.5;
4343
4344 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
4345
4346 // final timestep reached
4347 if(globalTimeStep == m_initStartTime + m_initTime) {
4348 m_Re = m_finalRe;
4349 m_tanhInit = 0;
4350 }
4351 }
4352 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
4353
4354 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
4355 const MInt pCellId = m_activeCellList[i];
4356
4357 if((globalTimeStep - 1) % IPOW2(maxLevel() - this->a_level(pCellId)) == 0) {
4358 rho = a_variable(pCellId, PV->RHO);
4359
4360 for(MInt d = 0; d < nDim; d++) {
4361 u[d] = a_variable(pCellId, d);
4362 }
4363
4364 // Calculation of equilibrium and non-equilibrium distribution
4365 std::array<MFloat, nDist> eqDist;
4366 eqDist = getEqDists(rho, u);
4367
4368 //--------------------------------------------
4369 // Calculation of overall viscosity
4370 // according to Hu, Sterling, Chen 1994
4371
4372 // 1. Calculation of original relaxation time (on current level)
4373 tau = F1B2 + 3.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId));
4374
4375 // 2. Calculation of the filtered mean momentum flux
4376 Q = 0.0;
4377 for(MInt k = 0; k < nDim * nDim; k++) {
4378 Q += m_momentumFlux[pCellId][k] * m_momentumFlux[pCellId][k];
4379 }
4380 Q = sqrt(2.0 * Q);
4381
4382 // 3. Calculation of new relaxation time
4383 // index = (MInt)((a_coordinate(pCellId, direction) - minCoord) / length * MFloat(count - 1) + 0.5);
4384 index = floor(
4385 (F1B2 * count
4386 + (a_coordinate(pCellId, direction) - F1B2 * (actualCellLength)) / (this->c_cellLengthAtLevel(maxLevel())))
4387 + 0.1);
4388
4389 tau += F1B2
4390 * (sqrt(tau * tau
4391 + 2.0 * SQRT2 * dynamicCs[index] * m_deltaX * m_deltaX * (F1BCSsq * F1BCSsq) * Q
4392 * FPOW2(maxLevel() - this->a_level(pCellId)))
4393 - tau);
4394
4395 m_omega = 1.0 / tau;
4396
4397 // save total nu for bndcnd and interface interpolation (save on finest level)
4398 a_nu(pCellId) = FPOW2(maxLevel() - this->a_level(pCellId)) * (tau - F1B2) / 3.0;
4399
4400 //--------------------------------------------
4401
4402 // Calculation of new distributions for directions with at least one component
4403 MFloat trace = F0;
4404
4405 if constexpr(nDim == 2) {
4406 trace = m_momentumFlux[pCellId][0] + m_momentumFlux[pCellId][3];
4407 } else {
4408 trace = m_momentumFlux[pCellId][0] + m_momentumFlux[pCellId][4] + m_momentumFlux[pCellId][8];
4409 }
4410
4411 for(MInt j = 0; j < (nDist - 1); j++) {
4412 MFloat t = F0;
4413 if(j < Ld::distFld(0)) {
4414 t = Ld::tp(1);
4415 } else if(j < Ld::distFld(1) + Ld::distFld(0)) {
4416 t = Ld::tp(2);
4417 } else {
4418 t = Ld::tp(3);
4419 }
4420
4421 a_distribution(pCellId, j) = eqDist[j] - (1.0 - m_omega) * t * F1BCSsq * F1B2 * trace;
4422
4423 for(MInt k = 0; k < nDim; k++) {
4424 for(MInt l = 0; l < nDim; l++) {
4425 a_distribution(pCellId, j) += (1.0 - m_omega) * t * F1BCSsq * F1BCSsq * F1B2 * (Ld::idFld(j, k) - 1)
4426 * (Ld::idFld(j, l) - 1) * m_momentumFlux[pCellId][l + nDim * k];
4427 }
4428 }
4429 }
4430 // Calculation of new distribution for rest particle distribution (center)
4431 a_distribution(pCellId, Ld::lastId()) =
4432 eqDist[Ld::lastId()] - (1.0 - m_omega) * Ld::tp(0) * F1BCSsq * F1B2 * trace;
4433
4434 //---------------------------
4435 // save dissipation values
4436
4437 // Calculate characteristic filtered rate of strain using original viscosity
4438 m_omega = 2.0 / (1.0 + 6.0 * m_nu * FFPOW2(maxLevel() - this->a_level(pCellId)));
4439 S = -F1B2 * F1BCSsq * m_omega * Q;
4440
4441 // Calculate molecular- and subgrid dissipation
4442 diss[index] += m_nu * S * S;
4443 SGSDiss[index] += dynamicCs[index] * m_deltaX * m_deltaX * S * S * S * FPOW4(maxLevel() - this->a_level(pCellId));
4444 for(MInt d = 0; d < nDim; d++) {
4445 energy += F1B2 * (a_variable(pCellId, d) * a_variable(pCellId, d));
4446 }
4447 //---------------------------
4448 }
4449 }
4450
4451 // write dissipation values
4452 if(m_calculateDissipation && globalTimeStep % m_solutionInterval == 0) {
4453 // for (MInt i=0; i<count; i++){
4454 // m_log <<"cs["<<i<<"]="<<dynamicCs[i]<<endl;
4455 // }
4456
4457 // all domains send their information to domain_0
4458 if(domainId() != 0) {
4459 MPI_Send(&(diss[0]), count, MPI_DOUBLE, 0, 0, mpiComm(), AT_, "(diss[0])");
4460 MPI_Send(&(SGSDiss[0]), count, MPI_DOUBLE, 0, 0, mpiComm(), AT_, "(SGSDiss[0])");
4461 MPI_Send(&energy, 1, MPI_DOUBLE, 0, 0, mpiComm(), AT_, "energy");
4462 }
4463
4464 if(domainId() == 0) {
4465 MPI_Status status;
4466
4467 for(MInt i = 0; i < count; i++) {
4468 totalDiss[i] = diss[i];
4469 totalSGSDiss[i] = SGSDiss[i];
4470 }
4471
4472 for(MInt j = 1; j < noDomains(); j++) {
4473 MPI_Recv(&(diss[0]), count, MPI_DOUBLE, j, 0, mpiComm(), &status, AT_, "(diss[0])");
4474 MPI_Recv(&(SGSDiss[0]), count, MPI_DOUBLE, j, 0, mpiComm(), &status, AT_, "(SGSDiss[0])");
4475 MPI_Recv(&energy, 1, MPI_DOUBLE, j, 0, mpiComm(), &status, AT_, "energy");
4476 for(MInt i = 0; i < count; i++) {
4477 totalDiss[i] += diss[i];
4478 totalSGSDiss[i] += SGSDiss[i];
4479 }
4480 }
4481
4482 fileName = "totalDiss_";
4483 sprintf(buf, "%d", globalTimeStep);
4484 fileName += buf;
4485 fileName += ".dat";
4486 m_log << "writing diss file: " << fileName << endl;
4487 ofl.open(fileName.c_str(), ios_base::out);
4488 for(MInt i = 0; i < count; i++)
4489 ofl << globalTimeStep << " " << i << " " << totalDiss[i] << " " << totalSGSDiss[i] << " " << energy << endl;
4490 ofl.close();
4491 }
4492 }
4493}

◆ rbgk_smagorinsky_collision_step()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::rbgk_smagorinsky_collision_step
override
Property value solverMethod
MAIA_LATTICE_RBGK_SMAGORINSKY

Collision step for the regularized LBGK-Algorithm + Smagorinsky turbulence model

Definition at line 4281 of file lbsolverdxqy.cpp.

4281 {
4282 rbgk_collision_step_base<true>();
4283}

◆ refineCellLb()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::refineCellLb ( const MInt  parentId,
const MInt childIds 
)
virtual

: Call interface function that performs initialization

Parameters
[in]

parentId: Solver id of cell that is refined childIds: Solver ids of new finde cells

Author
: Philipp Brokof, Moritz Waldmann

Definition at line 6560 of file lbsolverdxqy.cpp.

6560 {
6561 m_interface->refineCell(parentId, childIds);
6562}

◆ removeChildsLb()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::removeChildsLb ( const MInt  parentId)
virtual

: Call interface function that performs initialization

Parameters
[in]

parentId: Solver cell id of parent that will be coarsen

Author
: Philipp Brokof, Moritz Waldmann

Definition at line 6548 of file lbsolverdxqy.cpp.

6548 {
6549 m_interface->removeChildren(parentId);
6550}

◆ restartBndCnd()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::restartBndCnd
virtual
Author
: Philipp Brokof, Moritz Waldmann

Definition at line 7123 of file lbsolverdxqy.cpp.

7123 {
7124 if(m_isRefined || this->m_adaptation) {
7125 delete m_interface;
7126 }
7127
7128 if(m_isRefined || this->m_adaptation) m_interface = new LbInterfaceDxQy<nDim, nDist, SysEqn>(this);
7129
7130 delete m_bndCnd;
7131 m_bndCnd = new LbBndCnd(this);
7134}
void initializeBcData()
Initialize BC data variables.
Definition: lbbndcnd.cpp:3390

◆ restartInitLb()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::restartInitLb
virtual

Definition at line 4993 of file lbsolverdxqy.cpp.

4993 {
4994 TRACE();
4996
4997 if(m_isThermal) {
4999 }
5000 if(m_isTransport) {
5002 }
5003}

◆ restriction()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::restriction
private

Definition at line 6536 of file lbsolverdxqy.cpp.

6536 {
6537 TRACE();
6538 m_interface->restriction();
6539}

◆ sensorDivergence()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::sensorDivergence ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
override

Definition at line 6843 of file lbsolverdxqy.cpp.

6846 {
6847 m_log << " - Sensor preparation for the divergence sensor" << endl;
6848 cerr0 << " - Sensor preparation for the divergence sensor" << endl;
6849
6850 MFloat dx = 0.0;
6851
6852 std::array<MFloat, nDim> u{};
6853 std::array<std::array<MFloat, nDim>, nDim> u_p{};
6854 std::array<std::array<MFloat, nDim>, nDim> u_m{};
6855
6856 MFloat rho = 0.0;
6857 MFloat rho_p[nDim] = {0.0};
6858 MFloat rho_m[nDim] = {0.0};
6859
6860 MFloat dudx = 0.0;
6861 MFloat dvdy = 0.0;
6862
6863 MFloat phi_m = 0.0; // Sensor value mass conservation
6864
6865 // Set sensor weights for refinement (K_f)
6866 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
6867
6868 // Set cell seize weihts
6869 // TODO labels:LB Make available by property?
6870 MFloat cellSizeWeight_m = 1.0;
6871
6872 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
6873 ASSERT(!a_isHalo(cellId), "");
6874 const MInt gridId = this->grid().tree().solver2grid(cellId);
6875
6876 // Mesh adaptation is only performed on active cells
6877 // --> untag inactive cells
6878 if(!a_isActive(cellId)) {
6879 sensorCellFlag[gridId][sensorOffset + sen] = 0;
6880 continue;
6881 }
6882
6883 // Get cell size for cell size weighting
6884 dx = grid().cellLengthAtLevel(c_level(cellId));
6885
6886 // Compute macroscopic variables for sensor evaluation
6887 // All cells performed propagation step before. Thus, in-coming distributions
6888 // of all cells are in the same time step and comparable
6889 // --> Compute macroscopic variables from in-coming distributions.
6890 //
6891 // Depending on the neighbors of the cell, variables for
6892 // central, backwards or forwards differentials are computed
6893 calculateMacroscopicVariables(cellId, rho, u.data());
6894 if(a_hasNeighbor(cellId, 0) && a_isActive(c_neighborId(cellId, 0))) {
6895 MInt nghbrId = c_neighborId(cellId, 0);
6896 calculateMacroscopicVariables(nghbrId, rho_m[0], u_m[0].data());
6897 }
6898 if(a_hasNeighbor(cellId, 1) && a_isActive(c_neighborId(cellId, 1))) {
6899 MInt nghbrId = c_neighborId(cellId, 1);
6900 calculateMacroscopicVariables(nghbrId, rho_p[0], u_p[0].data());
6901 }
6902 if(a_hasNeighbor(cellId, 2) && a_isActive(c_neighborId(cellId, 2))) {
6903 MInt nghbrId = c_neighborId(cellId, 2);
6904 calculateMacroscopicVariables(nghbrId, rho_m[1], u_m[1].data());
6905 }
6906 if(a_hasNeighbor(cellId, 3) && a_isActive(c_neighborId(cellId, 3))) {
6907 MInt nghbrId = c_neighborId(cellId, 3);
6908 calculateMacroscopicVariables(nghbrId, rho_p[1], u_p[1].data());
6909 }
6910 if constexpr(nDim == 3) {
6911 if(a_hasNeighbor(cellId, 4) && a_isActive(c_neighborId(cellId, 4))) {
6912 MInt nghbrId = c_neighborId(cellId, 4);
6913 calculateMacroscopicVariables(nghbrId, rho_m[2], u_m[2].data());
6914 }
6915 if(a_hasNeighbor(cellId, 5) && a_isActive(c_neighborId(cellId, 5))) {
6916 MInt nghbrId = c_neighborId(cellId, 5);
6917 calculateMacroscopicVariables(nghbrId, rho_p[2], u_p[2].data());
6918 }
6919 }
6920
6921 // Central difference in x-direction
6922 if((a_hasNeighbor(cellId, 0) && a_isActive(c_neighborId(cellId, 0)))
6923 && (a_hasNeighbor(cellId, 1) && a_isActive(c_neighborId(cellId, 1)))) {
6924 dudx = (rho_p[0] * u_p[0][0] - rho_m[0] * u_m[0][0]) / (2.0 * dx);
6925 }
6926 // Forwards differnce in x-direction
6927 else if((!a_hasNeighbor(cellId, 0) || !a_isActive(c_neighborId(cellId, 0)))
6928 && (a_hasNeighbor(cellId, 1) && a_isActive(c_neighborId(cellId, 1)))) {
6929 dudx = (rho_p[0] * u_p[0][0] - rho * u[0]) / dx;
6930 }
6931 // Backwards difference in x-direction
6932 else if((a_hasNeighbor(cellId, 0) && a_isActive(c_neighborId(cellId, 0)))
6933 && (!a_hasNeighbor(cellId, 1) || !a_isActive(c_neighborId(cellId, 1)))) {
6934 dudx = (rho * u[0] - rho_m[0] * u_m[0][0]) / dx;
6935 }
6936 // Central differences in y-direction
6937 if((a_hasNeighbor(cellId, 2) && a_isActive(c_neighborId(cellId, 2)))
6938 && (a_hasNeighbor(cellId, 3) && a_isActive(c_neighborId(cellId, 3)))) {
6939 dvdy = (rho_p[1] * u_p[1][1] - rho_m[1] * u_m[1][1]) / (2.0 * dx);
6940 }
6941 // Forwards differences in y-direction
6942 else if((!a_hasNeighbor(cellId, 2) || !a_isActive(c_neighborId(cellId, 2)))
6943 && (a_hasNeighbor(cellId, 3) && a_isActive(c_neighborId(cellId, 3)))) {
6944 dvdy = (rho_m[1] * u_p[1][1] - rho * u[1]) / dx;
6945 }
6946 // Backwars differences in y-direction
6947 else if((a_hasNeighbor(cellId, 2) && a_isActive(c_neighborId(cellId, 2)))
6948 && (!a_hasNeighbor(cellId, 3) || !a_isActive(c_neighborId(cellId, 3)))) {
6949 dvdy = (rho * u[1] - rho_m[1] * u_m[1][1]) / dx;
6950 }
6951 if constexpr(nDim == 3) {
6952 MFloat dwdz = 0.0;
6953 // Central differences in z-direction
6954 if((a_hasNeighbor(cellId, 4) && a_isActive(c_neighborId(cellId, 4)))
6955 && (a_hasNeighbor(cellId, 5) && a_isActive(c_neighborId(cellId, 5)))) {
6956 dwdz = (rho_p[2] * u_p[2][2] - rho_m[2] * u_m[2][2]) / (2.0 * dx);
6957 }
6958 // Forwards differences in z-direction
6959 else if((!a_hasNeighbor(cellId, 4) || !a_isActive(c_neighborId(cellId, 4)))
6960 && (a_hasNeighbor(cellId, 5) && a_isActive(c_neighborId(cellId, 5)))) {
6961 dwdz = (rho_p[2] * u_p[2][2] - rho * u[2]) / dx;
6962 }
6963 // Backwars differences in z-direction
6964 else if((a_hasNeighbor(cellId, 4) && a_isActive(c_neighborId(cellId, 4)))
6965 && (!a_hasNeighbor(cellId, 5) || !a_isActive(c_neighborId(cellId, 5)))) {
6966 dwdz = (rho * u[2] - rho_m[2] * u_m[2][2]) / dx;
6967 }
6968
6969 phi_m = abs(dudx + dvdy + dwdz) * pow(dx, cellSizeWeight_m);
6970 // Test: Do not use divergence but use gradient of solution!
6971 // phi_m = (abs(dudx)+abs(dvdy)+abs(dwdz))*pow(dx,2.0);
6972 }
6973 if constexpr(nDim == 2) phi_m = abs(dudx + dvdy) * pow(dx, cellSizeWeight_m);
6974
6975 sensors[sensorOffset + sen][gridId] = phi_m;
6976 sensorCellFlag[gridId][sensorOffset + sen] = 1;
6977 }
6978}
void calculateMacroscopicVariables(const MInt cellId, MFloat &rho, MFloat *const u)
Calculate macroscopic variables for a given cell.
Definition: lbsolverdxqy.h:898
std::ostream cerr0

◆ sensorInterface()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::sensorInterface ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
override
Author
: Julian Vorspohl j.vor.nosp@m.spoh.nosp@m.l@aia.nosp@m..rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de

Definition at line 6577 of file lbsolverdxqy.cpp.

6580 {
6581 m_log << " - Sensor preparation for the boundary sensor for " << m_maxNoSets << " starting from " << m_levelSetId
6582 << endl;
6583 cerr0 << " - Sensor preparation for the boundary sensor for " << m_maxNoSets << " starting from " << m_levelSetId
6584 << endl;
6585
6586 // inList > 0: Cells are marked for refinement
6587 // inList = 1: Seeding cells for markSurroundingCells
6588 MIntScratchSpace inList(a_noCells(), AT_, "inList");
6589 inList.fill(0);
6590
6591 // Fill inList with cells wich are to be refined
6592 MInt interfaceCellCounter = 0;
6593 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6594 if(a_isHalo(cellId)) continue;
6595 if(inList[cellId] > 0) continue; // Already marked for refinement
6596
6597 if(this->a_isBndryCell(cellId)) {
6598 if(a_level(cellId) <= this->m_maxSensorRefinementLevel[sen]) {
6599 inList[cellId] = 1;
6600 interfaceCellCounter++;
6601
6602 // Propagate information to lower levels...
6603 MInt currentCellId = cellId;
6604 for(MInt parentLevel = this->a_level(cellId); parentLevel >= minLevel(); parentLevel--) {
6605 const MInt parentCellId = this->c_parentId(currentCellId);
6606 if(parentCellId == -1) {
6607 break;
6608 }
6609 inList[parentCellId] = 1;
6610 interfaceCellCounter++;
6611 currentCellId = parentCellId;
6612 }
6613 }
6614 }
6615 }
6616
6617 std::cout << "Found " << interfaceCellCounter << " static boundary cells..." << std::endl;
6618
6619 // Fill inList with cells wich are to be refined
6620 interfaceCellCounter = 0;
6621 MInt startSet = m_levelSetId;
6622 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6623 if(a_isHalo(cellId)) continue;
6624 for(MInt set = startSet; set < m_maxNoSets; set++) {
6625 if(inList[cellId] > 0) continue; // Already marked for refinement
6626 if(fabs(a_levelSetFunctionMB(cellId, set)) < this->c_cellLengthAtCell(cellId)) {
6627 if(a_level(cellId) < this->m_maxSensorRefinementLevel[sen]) {
6628 inList[cellId] = 1;
6629 interfaceCellCounter++;
6630 }
6631 } else {
6632 for(MInt dir = 0; dir < 2 * nDim; dir++) {
6633 if(a_hasNeighbor(cellId, dir) > 0) {
6634 MInt nghbrId = c_neighborId(cellId, dir);
6635 if((a_levelSetFunctionMB(nghbrId, set) * a_levelSetFunctionMB(cellId, set) < F0)) {
6636 if(a_level(cellId) < this->m_maxSensorRefinementLevel[sen]) {
6637 inList[cellId] = 1;
6638 interfaceCellCounter++;
6639 }
6640 break;
6641 }
6642 }
6643 }
6644 }
6645 }
6646 }
6647
6648 std::cout << "Found " << interfaceCellCounter << " moving boundary cells..." << std::endl;
6649
6650 // Mark surrounding cells according to m_bandWidth
6651 for(MInt level = minLevel(); level < this->m_maxSensorRefinementLevel[sen]; level++) {
6652 this->exchangeData(inList.data());
6653 this->markSurrndCells(inList, m_bandWidth[level], level, this->m_refineDiagonals);
6654 }
6655
6656 // Transfer inList to sensor
6657 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
6658 ASSERT(!a_isHalo(cellId), "");
6659 if(inList(cellId) == 0) {
6660 if(a_level(cellId) == minLevel()) continue;
6661 if(inList(c_parentId(cellId))) continue;
6662 if(c_isLeafCell(cellId)) {
6663 const MInt gridCellId = grid().tree().solver2grid(cellId);
6664 sensors[sensorOffset + sen][gridCellId] = -1.0;
6665 sensorCellFlag[gridCellId][sensorOffset + sen] = true;
6666 }
6667 } else {
6668 if(a_level(cellId) < this->m_maxSensorRefinementLevel[sen]) {
6669 if(c_noChildren(cellId) > 0) continue;
6670 const MInt gridCellId = grid().tree().solver2grid(cellId);
6671 sensors[sensorOffset + sen][gridCellId] = 1.0;
6672 sensorCellFlag[gridCellId][sensorOffset + sen] = true;
6673 }
6674 }
6675 }
6676 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
6677}

◆ sensorMeanStress()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::sensorMeanStress ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
override

Definition at line 7050 of file lbsolverdxqy.cpp.

7053 {
7054 if(nDim == 3) {
7055 TERMM(1, "Not implemented for 3D");
7056 }
7057
7058
7059 m_log << " - Sensor preparation for the mean stress sensor" << endl;
7060 cerr0 << " - Sensor preparation for the mean stress sensor" << endl;
7061
7062 // Set sensor weights for refinement (K_f)
7063 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
7064
7065 // Set cell seize weihts
7066 // TODO: Make available by property?
7067 const MFloat cellSizeWeight = 1.0;
7068
7069 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
7070 ASSERT(!a_isHalo(cellId), "");
7071 const MInt gridId = this->grid().tree().solver2grid(cellId);
7072
7073 // Mesh adaptation is only performed on active cells
7074 // --> untag inactive cells
7075 if(!a_isActive(cellId)) {
7076 sensorCellFlag[gridId][sensorOffset + sen] = 0;
7077 continue;
7078 }
7079
7080 // Calculate mean stress
7081 const MFloat rho = a_variable(cellId, PV->RHO);
7082 std::array<MFloat, 2> u = {a_variable(cellId, PV->U), a_variable(cellId, PV->V)};
7083
7084 std::array<MFloat, nDist> eqDist{};
7085 eqDist = getEqDists(rho, u.data());
7086
7087 // Calculation of non-eq-parts
7088 std::array<MFloat, 9> d{};
7089 for(MInt j = 0; j < 9; j++) {
7090 d[j] = a_oldDistribution(cellId, j) - eqDist[j];
7091 }
7092
7093 // Calculation of momentum flux tensor for non-equilibrium parts
7094 std::array<MFloat, 4> Q{};
7095 Q[0] = (d[0] + d[1] + d[4] + d[5] + d[6] + d[7]);
7096 Q[1] = (d[4] - d[5] + d[6] - d[7]);
7097
7098 Q[2] = Q[1];
7099 Q[3] = (d[2] + d[3] + d[4] + d[5] + d[6] + d[7]);
7100
7101 MFloat Qmean = 0.0;
7102 for(MInt k = 0; k < 4; k++) {
7103 Qmean += Q[k] * Q[k];
7104 }
7105
7106 Qmean = sqrt(2 * Qmean);
7107
7108 // Get cell size for cell size weighting
7109 const MFloat dx = grid().cellLengthAtLevel(c_level(cellId));
7110
7111 const MFloat phi = Qmean * pow(dx, cellSizeWeight);
7112
7113 sensors[sensorOffset + sen][gridId] = phi;
7114 sensorCellFlag[gridId][sensorOffset + sen] = 1;
7115 }
7116}

◆ sensorTotalPressure()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::sensorTotalPressure ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
override

Definition at line 6987 of file lbsolverdxqy.cpp.

6990 {
6991 m_log << " - Sensor preparation for the total pressure sensor" << endl;
6992 cerr0 << " - Sensor preparation for the total pressure sensor" << endl;
6993
6994 // Set sensor weights for refinement (K_f)
6995 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
6996
6997 // Set cell seize weihts
6998 // TODO labels:LB Make available by property?
6999 MFloat cellSizeWeight_p = 1.0;
7000
7001 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
7002 ASSERT(!a_isHalo(cellId), "");
7003 const MInt gridId = this->grid().tree().solver2grid(cellId);
7004
7005 // Mesh adaptation is only performed on active cells
7006 // --> untag inactive cells
7007 if(!a_isActive(cellId)) {
7008 sensorCellFlag[gridId][sensorOffset + sen] = 0;
7009 continue;
7010 }
7011
7012 // Get cell size for cell size weighting
7013 const MFloat dx = grid().cellLengthAtLevel(c_level(cellId));
7014
7015 // Compute macroscopic variables for sensor evaluation
7016 // All cells performed propagation step before. Thus, in-coming distributions
7017 // of all cells are in the same time step and comparable
7018 // --> Compute macroscopic variables from in-coming distributions.
7019 //
7020 // Depending on the neighbors of the cell, variables for
7021 // central, backwards or forwards differentials are computed
7022 MFloat rho{};
7023 std::array<MFloat, nDim> u{};
7024 calculateMacroscopicVariables(cellId, rho, u.data());
7025
7026 // (1) Difference in total pressure
7027 // Incident flow total pressure depends on bc!
7028 // Here so far only for bc10000 --> Assume rho=1 on boundary.
7029 const MFloat rho_0 = 1.0;
7030 const MFloat p_0 = rho_0 / 3.0;
7031 const MFloat p = rho / 3.0;
7032 const MFloat pTotal_0 = 0.5 * rho_0 * (m_Ma * LBCS) * (m_Ma * LBCS) + p_0;
7033 const MFloat squaredVelocity = std::inner_product(u.begin(), u.end(), u.begin(), 0.0);
7034 const MFloat pTotal = 0.5 * rho * squaredVelocity + p;
7035 const MFloat phi_p = abs(pTotal_0 - pTotal) * pow(dx, cellSizeWeight_p);
7036 sensors[sensorOffset + sen][gridId] = phi_p;
7037 sensorCellFlag[gridId][sensorOffset + sen] = 1;
7038 }
7039}

◆ sensorVorticity()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::sensorVorticity ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
override

Definition at line 6686 of file lbsolverdxqy.cpp.

6689 {
6690 m_log << " - Sensor preparation for the vorticity sensor" << endl;
6691 cerr0 << " - Sensor preparation for the vorticity sensor" << endl;
6692
6693 MFloat dx = 0.0;
6694
6695 std::array<MFloat, nDim> u{};
6696 std::array<std::array<MFloat, nDim>, nDim> u_p{};
6697 std::array<std::array<MFloat, nDim>, nDim> u_m{};
6698
6699 MFloat rho = 0.0;
6700 MFloat rho_p[nDim] = {0.0};
6701 MFloat rho_m[nDim] = {0.0};
6702
6703 MFloat dudy = 0.0;
6704 MFloat dvdx = 0.0;
6705
6706 MFloat dwdx = 0.0;
6707 MFloat dwdy = 0.0;
6708
6709 MFloat phi_v = 0.0; // Sensor value vorticity
6710
6711 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
6712
6713 // Set cell seize weihts
6714 // TODO labels:LB Make available by property?
6715 MFloat cellSizeWeight_v = 1.5;
6716
6717 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
6718 ASSERT(!a_isHalo(cellId), "");
6719 const MInt gridId = this->grid().tree().solver2grid(cellId);
6720
6721 // Mesh adaptation is only performed on active cells
6722 // --> untag inactive cells
6723 if(!a_isActive(cellId)) {
6724 sensorCellFlag[gridId][sensorOffset + sen] = 0;
6725 continue;
6726 }
6727
6728 // Get cell size for cell size weighting
6729 dx = grid().cellLengthAtLevel(c_level(cellId));
6730
6731 // Compute macroscopic variables for sensor evaluation
6732 // All cells performed propagation step before. Thus, in-coming distributions
6733 // of all cells are in the same time step and comparable
6734 // --> Compute macroscopic variables from in-coming distributions.
6735 //
6736 // Depending on the neighbors of the cell, variables for
6737 // central, backwards or forwards differentials are computed
6738 calculateMacroscopicVariables(cellId, rho, u.data());
6739 if(a_hasNeighbor(cellId, 0) && a_isActive(c_neighborId(cellId, 0))) {
6740 MInt nghbrId = c_neighborId(cellId, 0);
6741 calculateMacroscopicVariables(nghbrId, rho_m[0], u_m[0].data());
6742 }
6743 if(a_hasNeighbor(cellId, 1) && a_isActive(c_neighborId(cellId, 1))) {
6744 MInt nghbrId = c_neighborId(cellId, 1);
6745 calculateMacroscopicVariables(nghbrId, rho_p[0], u_p[0].data());
6746 }
6747 if(a_hasNeighbor(cellId, 2) && a_isActive(c_neighborId(cellId, 2))) {
6748 MInt nghbrId = c_neighborId(cellId, 2);
6749 calculateMacroscopicVariables(nghbrId, rho_m[1], u_m[1].data());
6750 }
6751 if(a_hasNeighbor(cellId, 3) && a_isActive(c_neighborId(cellId, 3))) {
6752 MInt nghbrId = c_neighborId(cellId, 3);
6753 calculateMacroscopicVariables(nghbrId, rho_p[1], u_p[1].data());
6754 }
6755 if constexpr(nDim == 3) {
6756 if(a_hasNeighbor(cellId, 4) && a_isActive(c_neighborId(cellId, 4))) {
6757 MInt nghbrId = c_neighborId(cellId, 4);
6758 calculateMacroscopicVariables(nghbrId, rho_m[2], u_m[2].data());
6759 }
6760 if(a_hasNeighbor(cellId, 5) && a_isActive(c_neighborId(cellId, 5))) {
6761 MInt nghbrId = c_neighborId(cellId, 5);
6762 calculateMacroscopicVariables(nghbrId, rho_p[2], u_p[2].data());
6763 }
6764 }
6765
6766 // (1) Difference in total pressure
6767 // Incident flow total pressure depends on bc!
6768 // Here so far only for bc10000 --> Assume rho=1 on boundary.
6769 // Central differences in x-direction
6770 if((a_hasNeighbor(cellId, 0) && a_isActive(c_neighborId(cellId, 0)))
6771 && (a_hasNeighbor(cellId, 1) && a_isActive(c_neighborId(cellId, 1)))) {
6772 dvdx = (u_p[0][1] - u_m[0][1]) / (2.0 * dx);
6773 if constexpr(nDim == 3) dwdx = (u_p[0][2] - u_m[0][2]) / (2.0 * dx);
6774 }
6775 // Forwards difference in x-direction
6776 else if((!a_hasNeighbor(cellId, 0) || !a_isActive(c_neighborId(cellId, 0)))
6777 && (a_hasNeighbor(cellId, 1) && a_isActive(c_neighborId(cellId, 1)))) {
6778 dvdx = (u_p[0][1] - u[1]) / dx;
6779 if constexpr(nDim == 3) dwdx = (u_p[0][2] - u[2]) / dx;
6780 }
6781 // Backwards differences in x-direction
6782 else if((a_hasNeighbor(cellId, 0) && a_isActive(c_neighborId(cellId, 0)))
6783 && (!a_hasNeighbor(cellId, 1) || !a_isActive(c_neighborId(cellId, 1)))) {
6784 dvdx = (u[1] - u_m[0][1]) / dx;
6785 if constexpr(nDim == 3) dwdx = (u[2] - u_m[0][2]) / dx;
6786 }
6787 // Central differences in y-direction
6788 if((a_hasNeighbor(cellId, 2) && a_isActive(c_neighborId(cellId, 2)))
6789 && (a_hasNeighbor(cellId, 3) && a_isActive(c_neighborId(cellId, 3)))) {
6790 dudy = (u_p[1][0] - u_m[1][0]) / (2.0 * dx);
6791 if constexpr(nDim == 3) dwdy = (u_p[1][2] - u_m[1][2]) / (2.0 * dx);
6792 }
6793 // Forwards differences in y-direction
6794 else if((!a_hasNeighbor(cellId, 2) || !a_isActive(c_neighborId(cellId, 2)))
6795 && (a_hasNeighbor(cellId, 3) && a_isActive(c_neighborId(cellId, 3)))) {
6796 dudy = (u_p[1][0] - u[0]) / dx;
6797 if constexpr(nDim == 3) dwdy = (u_p[1][2] - u[2]) / dx;
6798 }
6799 // Backwards differences in y-direction
6800 else if((a_hasNeighbor(cellId, 2) && a_isActive(c_neighborId(cellId, 2)))
6801 && (!a_hasNeighbor(cellId, 3) || !a_isActive(c_neighborId(cellId, 3)))) {
6802 dudy = (u[0] - u_m[1][0]) / dx;
6803 if constexpr(nDim == 3) dwdy = (u[2] - u_m[1][2]) / dx;
6804 }
6805 if constexpr(nDim == 3) {
6806 MFloat dudz = 0.0;
6807 MFloat dvdz = 0.0;
6808 // Central differences in z-direction
6809 if((a_hasNeighbor(cellId, 4) && a_isActive(c_neighborId(cellId, 4)))
6810 && (a_hasNeighbor(cellId, 5) && a_isActive(c_neighborId(cellId, 5)))) {
6811 dudz = (u_p[2][0] - u_m[2][0]) / (2.0 * dx);
6812 dvdz = (u_p[2][1] - u_m[2][1]) / (2.0 * dx);
6813 }
6814 // Forwards difference in z-direction
6815 else if((!a_hasNeighbor(cellId, 4) || !a_isActive(c_neighborId(cellId, 4)))
6816 && (a_hasNeighbor(cellId, 5) && a_isActive(c_neighborId(cellId, 5)))) {
6817 dudz = (u_p[2][0] - u[0]) / dx;
6818 dvdz = (u_p[2][1] - u[1]) / dx;
6819 }
6820 // Backwards differences in z-direction
6821 else if((a_hasNeighbor(cellId, 4) && a_isActive(c_neighborId(cellId, 4)))
6822 && (!a_hasNeighbor(cellId, 5) || !a_isActive(c_neighborId(cellId, 5)))) {
6823 dudz = (u[0] - u_m[2][0]) / dx;
6824 dvdz = (u[1] - u_m[2][1]) / dx;
6825 }
6826
6827 phi_v = sqrt(pow((dwdy - dvdz), 2) + pow((dudz - dwdx), 2) + pow((dvdx - dudy), 2)) * pow(dx, cellSizeWeight_v);
6828 }
6829 if constexpr(nDim == 2) phi_v = abs(dvdx - dudy) * pow(dx, cellSizeWeight_v);
6830
6831 sensors[sensorOffset + sen][gridId] = phi_v;
6832 sensorCellFlag[gridId][sensorOffset + sen] = 1;
6833 }
6834}

◆ setEqDists() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDists ( const MInt  cellId,
const MFloat  rho,
const MFloat *const  velocity 
)
inline
Author
Julian Vorspohl j.vor.nosp@m.spoh.nosp@m.l@aia.nosp@m..rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de
Template Parameters
compressibleDetermines which equilibrium formulation is used
Parameters
[in]cellIdCell id in which the equilibrium is set
[in]rhoMacroscropic density
[in]velocityMacroscopic velocity

Definition at line 401 of file lbsolverdxqy.h.

402 {
403 std::array<MFloat, nDist> eqDist;
404#ifdef WAR_NVHPC_PSTL
405 sysEqn().calcEqDists(rho, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(), m_distFld.data());
406 for(MInt dist = 0; dist < nDist; dist++) {
407 a_distribution(cellId, dist) = eqDist[dist];
408 a_oldDistribution(cellId, dist) = eqDist[dist];
409 }
410#else
411 sysEqn().calcEqDists(rho, velocity, eqDist.data());
412
413 std::copy_n(eqDist.begin(), nDist, &a_distribution(cellId, 0));
414 std::copy_n(eqDist.begin(), nDist, &a_oldDistribution(cellId, 0));
415#endif
416}

◆ setEqDists() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDists ( const MInt  cellId,
const MFloat  rho,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)
inline
Author
Julian Vorspohl j.vor.nosp@m.spoh.nosp@m.l@aia.nosp@m..rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de
Template Parameters
compressibleDetermines which equilibrium formulation is used
Parameters
[in]cellIdCell id in which the equilibrium is set
[in]rhoMacroscropic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 431 of file lbsolverdxqy.h.

432 {
433 std::array<MFloat, nDist> eqDist;
434#ifdef WAR_NVHPC_PSTL
435 sysEqn().calcEqDists(rho, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(),
436 m_distFld.data());
437 for(MInt dist = 0; dist < nDist; dist++) {
438 a_distribution(cellId, dist) = eqDist[dist];
439 a_oldDistribution(cellId, dist) = eqDist[dist];
440 }
441#else
442 sysEqn().calcEqDists(rho, squaredVelocity, velocity, eqDist.data());
443
444 std::copy_n(eqDist.begin(), nDist, &a_distribution(cellId, 0));
445 std::copy_n(eqDist.begin(), nDist, &a_oldDistribution(cellId, 0));
446#endif
447}

◆ setEqDistsThermal() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDistsThermal ( const MInt  cellId,
const MFloat  T,
const MFloat  rho,
const MFloat *const  velocity 
)
inline

Use this version if the squaredVelocity is not already precomputed

Author
Julian Vorspohl, Moritz Waldmann
Parameters
[in]cellIdCell id in which the equilibrium is set
[in]TMacroscopic temperature
[in]rhoMacroscopic density
[in]velocityMacroscopic velocity

Definition at line 462 of file lbsolverdxqy.h.

463 {
464 if(m_innerEnergy) {
465 setEqDistsThermal_<1>(cellId, T, rho, velocity);
466 } else if(m_totalEnergy) {
467 setEqDistsThermal_<2>(cellId, T, rho, velocity);
468 } else {
469 setEqDistsThermal_<0>(cellId, T, rho, velocity);
470 }
471}

◆ setEqDistsThermal() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDistsThermal ( const MInt  cellId,
const MFloat  T,
const MFloat  rho,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)
inline

Use this version if the squaredVelocity is already precomputed

Author
Julian Vorspohl, Moritz Waldmann
Parameters
[in]cellIdCell id in which the equilibrium is set
[in]TMacroscopic temperature
[in]rhoMacroscopic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 532 of file lbsolverdxqy.h.

534 {
535 if(m_innerEnergy) {
536 setEqDistsThermal_<1>(cellId, T, rho, squaredVelocity, velocity);
537 } else if(m_totalEnergy) {
538 setEqDistsThermal_<2>(cellId, T, rho, squaredVelocity, velocity);
539 } else {
540 setEqDistsThermal_<0>(cellId, T, rho, squaredVelocity, velocity);
541 }
542}

◆ setEqDistsThermal_() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt thermalMode>
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDistsThermal_ ( const MInt  cellId,
const MFloat  T,
const MFloat  rho,
const MFloat *const  velocity 
)
inline

Use this version if the squaredVelocity is not already precomputed

Author
Julian Vorspohl, Moritz Waldmann
Template Parameters
thermalModeDetermines which equilibrium formulation is used
Parameters
[in]cellIdCell id in which the equilibrium is set
[in]TMacroscopic temperature
[in]rhoMacroscopic density
[in]velocityMacroscopic velocity

Definition at line 489 of file lbsolverdxqy.h.

490 {
491 std::array<MFloat, nDist> eqDist;
492#ifdef WAR_NVHPC_PSTL
493 IF_CONSTEXPR(thermalMode == 0) {
494 lbfunc::calcEqDistsThermal<nDim, nDist>(T, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(),
495 m_distFld.data());
496 }
497 IF_CONSTEXPR(thermalMode == 1) {
498 lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(T, rho, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
499 m_tp.data(), m_distFld.data());
500 }
501 IF_CONSTEXPR(thermalMode == 2) {
502 lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(T, rho, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
503 m_tp.data(), m_distFld.data());
504 }
505 for(MInt dist = 0; dist < nDist; dist++) {
506 a_distributionThermal(cellId, dist) = eqDist[dist];
507 a_oldDistributionThermal(cellId, dist) = eqDist[dist];
508 }
509#else
510 IF_CONSTEXPR(thermalMode == 0) { lbfunc::calcEqDistsThermal<nDim, nDist>(T, velocity, eqDist.data()); }
511 IF_CONSTEXPR(thermalMode == 1) { lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(T, rho, velocity, eqDist.data()); }
512 IF_CONSTEXPR(thermalMode == 2) { lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(T, rho, velocity, eqDist.data()); }
513 std::copy_n(eqDist.begin(), nDist, &a_distributionThermal(cellId, 0));
514 std::copy_n(eqDist.begin(), nDist, &a_oldDistributionThermal(cellId, 0));
515#endif
516}

◆ setEqDistsThermal_() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt thermalMode>
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDistsThermal_ ( const MInt  cellId,
const MFloat  T,
const MFloat  rho,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)
inline

Use this version if the squaredVelocity is already precomputed

Author
Julian Vorspohl, Moritz Waldmann
Template Parameters
thermalModeDetermines which equilibrium formulation is used
Parameters
[in]cellIdCell id in which the equilibrium is set
[in]TMacroscopic temperature
[in]rhoMacroscopic density
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 561 of file lbsolverdxqy.h.

563 {
564 std::array<MFloat, nDist> eqDist;
565#ifdef WAR_NVHPC_PSTL
566 IF_CONSTEXPR(thermalMode == 0) {
567 lbfunc::calcEqDistsThermal<nDim, nDist>(T, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
568 m_tp.data(), m_distFld.data());
569 }
570 IF_CONSTEXPR(thermalMode == 1) {
571 lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(T, rho, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(),
572 m_mFld2.data(), m_tp.data(), m_distFld.data());
573 }
574 IF_CONSTEXPR(thermalMode == 2) {
575 lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(T, rho, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(),
576 m_mFld2.data(), m_tp.data(), m_distFld.data());
577 }
578 for(MInt dist = 0; dist < nDist; dist++) {
579 a_distributionThermal(cellId, dist) = eqDist[dist];
580 a_oldDistributionThermal(cellId, dist) = eqDist[dist];
581 }
582#else
583 IF_CONSTEXPR(thermalMode == 0) {
584 lbfunc::calcEqDistsThermal<nDim, nDist>(T, squaredVelocity, velocity, eqDist.data());
585 }
586 IF_CONSTEXPR(thermalMode == 1) {
587 lbfunc::calcEqDistsInnerEnergy<nDim, nDist>(T, rho, squaredVelocity, velocity, eqDist.data());
588 }
589 IF_CONSTEXPR(thermalMode == 2) {
590 lbfunc::calcEqDistsTotalEnergy<nDim, nDist>(T, rho, squaredVelocity, velocity, eqDist.data());
591 }
592 std::copy_n(eqDist.begin(), nDist, &a_distributionThermal(cellId, 0));
593 std::copy_n(eqDist.begin(), nDist, &a_oldDistributionThermal(cellId, 0));
594#endif
595}

◆ setEqDistsTransport() [1/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDistsTransport ( const MInt  cellId,
const MFloat  C,
const MFloat *const  velocity 
)
inline

This uses the basic transport equilibrium model

Parameters
[in]cellIdCell id in which the equilibrium is set
[in]CMacroscopic concentration
[in]velocityMacroscopic velocity

Definition at line 607 of file lbsolverdxqy.h.

608 {
609 std::array<MFloat, nDist> eqDist;
610#ifdef WAR_NVHPC_PSTL
611 lbfunc::calcEqDistsTransport<nDim, nDist>(C, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(), m_tp.data(),
612 m_distFld.data());
613 for(MInt dist = 0; dist < nDist; dist++) {
614 a_distributionTransport(cellId, dist) = eqDist[dist];
615 a_oldDistributionTransport(cellId, dist) = eqDist[dist];
616 }
617#else
618 lbfunc::calcEqDistsTransport<nDim, nDist>(C, velocity, eqDist.data());
619
620 std::copy_n(eqDist.begin(), nDist, &a_distributionTransport(cellId, 0));
621 std::copy_n(eqDist.begin(), nDist, &a_oldDistributionTransport(cellId, 0));
622#endif
623}

◆ setEqDistsTransport() [2/2]

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::setEqDistsTransport ( const MInt  cellId,
const MFloat  C,
const MFloat  squaredVelocity,
const MFloat *const  velocity 
)
inline

This uses the basic transport equilibrium model

Use this version if the squaredVelocity is already precomputed

Parameters
[in]cellIdCell id in which the equilibrium is set
[in]CMacroscopic concentration
[in]squaredVelocityMacroscopic velocity squared
[in]velocityMacroscopic velocity

Definition at line 638 of file lbsolverdxqy.h.

640 {
641 std::array<MFloat, nDist> eqDist;
642#ifdef WAR_NVHPC_PSTL
643 lbfunc::calcEqDistsTransport<nDim, nDist>(C, squaredVelocity, velocity, eqDist.data(), m_mFld1.data(), m_mFld2.data(),
644 m_tp.data(), m_distFld.data());
645 for(MInt dist = 0; dist < nDist; dist++) {
646 a_distributionTransport(cellId, dist) = eqDist[dist];
647 a_oldDistributionTransport(cellId, dist) = eqDist[dist];
648 }
649#else
650 lbfunc::calcEqDistsTransport<nDim, nDist>(C, squaredVelocity, velocity, eqDist.data());
651
652 std::copy_n(eqDist.begin(), nDist, &a_distributionTransport(cellId, 0));
653 std::copy_n(eqDist.begin(), nDist, &a_oldDistributionTransport(cellId, 0));
654#endif
655}

◆ sysEqn()

template<MInt nDim, MInt nDist, class SysEqn >
constexpr SysEqn LbSolverDxQy< nDim, nDist, SysEqn >::sysEqn ( ) const
inlineconstexpr

Definition at line 194 of file lbsolverdxqy.h.

194{ return m_sysEqn; }
const SysEqn m_sysEqn
Definition: lbsolverdxqy.h:31

◆ updateMacroscopicVariables()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::updateMacroscopicVariables

Definition at line 4730 of file lbsolverdxqy.cpp.

4730 {
4731 TRACE();
4732
4733 for(MInt i = 0; i < m_currentMaxNoCells; i++) {
4734 const MInt pCellId = m_activeCellList[i];
4735 swap_variables(pCellId);
4736
4737 // Update macroscopic variables
4738 a_variable(pCellId, PV->RHO) = 0.0;
4739 for(MInt j = 0; j < nDist; j++) {
4740 a_variable(pCellId, PV->RHO) += a_oldDistribution(pCellId, j);
4741 }
4742 for(MInt d = 0; d < nDim; d++) {
4743 a_variable(pCellId, PV->U + d) = 0.0;
4744 for(MInt j = 0; j < Ld::dxQyFld(); j++) {
4745 a_variable(pCellId, PV->U + d) += a_oldDistribution(pCellId, Ld::pFld(d, j));
4746 a_variable(pCellId, PV->U + d) -= a_oldDistribution(pCellId, Ld::nFld(d, j));
4747 }
4748 }
4749 }
4750}

◆ updateVariablesFromOldDist()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::updateVariablesFromOldDist
overridevirtual

Definition at line 434 of file lbsolverdxqy.cpp.

434 {
435 updateVariablesFromOldDist_<0>();
436}

◆ updateVariablesFromOldDist_()

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt timeStepOffset>
void LbSolverDxQy< nDim, nDist, SysEqn >::updateVariablesFromOldDist_

Definition at line 383 of file lbsolverdxqy.cpp.

383 {
384 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
385 const MInt gTSmOffset = globalTimeStep - timeStepOffset; // Because collision step is performed one TS earlier
386 const MInt maxLevel_ = maxLevel();
387
388 if(this->isCompressible()) {
389 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
390 const MInt pCellId = m_activeCellList[index];
391 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
392 if(gTSmOffset % IPOW2(lvlDiff) != 0) return;
393 swap_variables(pCellId);
394#ifdef WAR_NVHPC_PSTL
395 MFloat u[nDim] = {F0};
396 for(MInt d = 0; d < nDim; d++) {
397 u[d] = a_variable(pCellId, d);
398 }
399 MFloat l_rho = a_variable(pCellId, PV->RHO);
400 calculateMacroscopicVariables<true>(pCellId, l_rho, u);
401 for(MInt d = 0; d < nDim; d++) {
402 a_variable(pCellId, d) = u[d];
403 }
404 a_variable(pCellId, PV->RHO) = l_rho;
405#else
406 calculateMacroscopicVariables<true>(pCellId, a_variable(pCellId, PV->RHO), &a_variable(pCellId, PV->U));
407#endif
408 });
409 } else {
410 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
411 const MInt pCellId = m_activeCellList[index];
412 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
413 if(gTSmOffset % IPOW2(lvlDiff) != 0) return;
414 swap_variables(pCellId);
415#ifdef WAR_NVHPC_PSTL
416 MFloat u[nDim] = {F0};
417 for(MInt d = 0; d < nDim; d++) {
418 u[d] = a_variable(pCellId, d);
419 }
420 MFloat l_rho = a_variable(pCellId, PV->RHO);
421 calculateMacroscopicVariables(pCellId, l_rho, u);
422 for(MInt d = 0; d < nDim; d++) {
423 a_variable(pCellId, d) = u[d];
424 }
425 a_variable(pCellId, PV->RHO) = l_rho;
426#else
427 calculateMacroscopicVariables(pCellId, a_variable(pCellId, PV->RHO), &a_variable(pCellId, PV->U));
428#endif
429 });
430 }
431}

◆ updateVariablesFromOldDist_preCollision()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::updateVariablesFromOldDist_preCollision
overridevirtual

Definition at line 439 of file lbsolverdxqy.cpp.

439 {
440 // TODO labels:LB @johannes/julian: You made this step after propagation. Preference against here?
441 // if(this->m_isInitRun) {
442 // this->initRunCorrection();
443 // } else {
444 updateVariablesFromOldDist_<1>();
445 // }
446}

◆ updateViscosity()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::updateViscosity
override
Author
Miro Gondrum
Date
03.01.2024 Reset viscoisty to m_nu default value or according to tanh ramping

Definition at line 4689 of file lbsolverdxqy.cpp.

4689 {
4690 TRACE();
4691 // Update the global Reynolds number if we use the tanh-adaption
4692 if(m_tanhInit && (globalTimeStep > m_initStartTime)) {
4693 const MFloat scale =
4694 0.5 * (m_tanhScaleFactor * tanh((5.0 * (MFloat)(globalTimeStep - m_initStartTime) / (MFloat)m_initTime) - 2.5))
4695 + 0.5;
4696
4697 m_Re = m_initRe + scale * (m_finalRe - m_initRe);
4698 // final timestep reached
4699 if(globalTimeStep == m_initStartTime + m_initTime) {
4700 m_Re = m_finalRe;
4701 m_tanhInit = false;
4702 }
4703 }
4704 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
4705 const MInt gTS = globalTimeStep;
4706 const MInt maxLevel_ = maxLevel();
4707 // update/reset m_nu and a_nu/a_oldNu
4708 m_nu = m_Ma * LBCS / m_Re * m_referenceLength;
4709 if(m_cells.saveOldNu()) {
4710 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
4711 const MInt pCellId = m_activeCellList[index];
4712 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
4713 if((gTS - 1) % IPOW2(lvlDiff) != 0) return;
4714 this->a_oldNu(pCellId) = a_nu(pCellId);
4715 a_nu(pCellId) = m_nu;
4716 });
4717 } else {
4718 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
4719 const MInt pCellId = m_activeCellList[index];
4720 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
4721 if((gTS - 1) % IPOW2(lvlDiff) != 0) return;
4722 a_nu(pCellId) = m_nu;
4723 });
4724 }
4725}

◆ volumeForces()

template<MInt nDim, MInt nDist, class SysEqn >
void LbSolverDxQy< nDim, nDist, SysEqn >::volumeForces
virtual
Author
Daniel Lauwers
Date
June 2021

apply volumeForces to the oldDistributions. Should be called after propagation.

Definition at line 456 of file lbsolverdxqy.cpp.

456 {
457 if(string2enum(solverMethod()) == MAIA_LATTICE_BGK_TOTALENERGY)
458 return; // in this collision step the forcing is added differently. There seems to be no easy way to unify the
459 // methods.
460 if(m_controlVelocity) controlVelocity();
461
462 // Required for ported functions, since GPUs cannot access the global variable globalTimeStep
463 const MInt gTS = globalTimeStep;
464 const MInt maxLevel_ = maxLevel();
465
466 // TODO labels:LB Move to lb source terms?
467 if(this->m_externalForcing) {
468 // add forcing term
469 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
470 const MInt pCellId = m_activeCellList[index];
471 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
472 if((gTS) % IPOW2(lvlDiff) != 0) return;
473 for(MInt j = 0; j < nDist - 1; j++) {
474 a_oldDistribution(pCellId, j) += FPOW2(maxLevel_ - this->a_level(pCellId)) * m_Fext[j];
475 }
476 });
477 }
478
479 if(m_isEELiquid && m_EELiquid.gravity) {
480 maia::parallelFor<true>(0, m_currentMaxNoCells, [=](MInt index) {
481 const MInt pCellId = m_activeCellList[index];
482 const MInt lvlDiff = maxLevel_ - a_level(pCellId);
483 if((gTS) % IPOW2(lvlDiff) != 0) return;
484 const MFloat alpha = a_alphaGasLim(pCellId);
485
486 for(MInt j = 0; j < nDist - 1; j++) {
487 // gravity included in m_EELiquid.Fg
488 // *3.0 is 1/c_s^2 see Haenel_MolekulareGasdynamik Eq. (9.65)
489 // -= because the effects of gravity are introduced through buoyancy
490 a_oldDistribution(pCellId, j) -= FPOW2(maxLevel_ - this->a_level(pCellId)) * m_EELiquid.Fg[j] * alpha;
491 }
492 });
493 }
494}
virtual void controlVelocity()
control velocity of a periodic channel flow via volume forces
@ MAIA_LATTICE_BGK_TOTALENERGY
Definition: enums.h:86

Friends And Related Function Documentation

◆ CouplingLB

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt nDim_, MInt nDist_, class SysEqn_ >
friend class CouplingLB
friend

Definition at line 192 of file lbsolverdxqy.h.

◆ LbBndCndDxQy

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt nDim_, MInt nDist_, class SysEqn_ >
friend class LbBndCndDxQy
friend

Definition at line 183 of file lbsolverdxqy.h.

◆ LbInterface

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt nDim_>
friend class LbInterface
friend

Definition at line 189 of file lbsolverdxqy.h.

◆ LbInterfaceDxQy

template<MInt nDim, MInt nDist, class SysEqn >
template<MInt nDim_, MInt nDist_, class SysEqn_ >
friend class LbInterfaceDxQy
friend

Definition at line 186 of file lbsolverdxqy.h.

Member Data Documentation

◆ C1

template<MInt nDim, MInt nDist, class SysEqn >
const MFloat LbSolverDxQy< nDim, nDist, SysEqn >::C1
private

Definition at line 354 of file lbsolverdxqy.h.

◆ C2

template<MInt nDim, MInt nDist, class SysEqn >
const MFloat LbSolverDxQy< nDim, nDist, SysEqn >::C2
private

Definition at line 354 of file lbsolverdxqy.h.

◆ C3

template<MInt nDim, MInt nDist, class SysEqn >
const MFloat LbSolverDxQy< nDim, nDist, SysEqn >::C3
private

Definition at line 354 of file lbsolverdxqy.h.

◆ C4

template<MInt nDim, MInt nDist, class SysEqn >
const MFloat LbSolverDxQy< nDim, nDist, SysEqn >::C4
private

Definition at line 354 of file lbsolverdxqy.h.

◆ distrib

template<MInt nDim, MInt nDist, class SysEqn >
std::uniform_real_distribution LbSolverDxQy< nDim, nDist, SysEqn >::distrib {0.0, 1.0}

Definition at line 323 of file lbsolverdxqy.h.

◆ m_bndCnd

template<MInt nDim, MInt nDist, class SysEqn >
LbBndCnd* LbSolverDxQy< nDim, nDist, SysEqn >::m_bndCnd
protected

Definition at line 332 of file lbsolverdxqy.h.

◆ m_initMethodPtr

template<MInt nDim, MInt nDist, class SysEqn >
void(LbSolverDxQy< nDim, nDist, SysEqn >::* LbSolverDxQy< nDim, nDist, SysEqn >::m_initMethodPtr) ()
protected

Definition at line 339 of file lbsolverdxqy.h.

◆ m_interface

template<MInt nDim, MInt nDist, class SysEqn >
LbInterfaceDxQy<nDim, nDist, SysEqn>* LbSolverDxQy< nDim, nDist, SysEqn >::m_interface
protected

Definition at line 334 of file lbsolverdxqy.h.

◆ m_noDistributions

template<MInt nDim, MInt nDist, class SysEqn >
constexpr MInt LbSolverDxQy< nDim, nDist, SysEqn >::m_noDistributions = nDist
staticconstexpr

Definition at line 180 of file lbsolverdxqy.h.

◆ m_smallestCellLength

template<MInt nDim, MInt nDist, class SysEqn >
MFloat LbSolverDxQy< nDim, nDist, SysEqn >::m_smallestCellLength {}
private

Definition at line 351 of file lbsolverdxqy.h.

◆ m_srcTermController

template<MInt nDim, MInt nDist, class SysEqn >
maia::lb::LbSrcTermController<nDim, nDist, SysEqn> LbSolverDxQy< nDim, nDist, SysEqn >::m_srcTermController
protected

Definition at line 333 of file lbsolverdxqy.h.

◆ m_sysEqn

template<MInt nDim, MInt nDist, class SysEqn >
const SysEqn LbSolverDxQy< nDim, nDist, SysEqn >::m_sysEqn {}

Definition at line 31 of file lbsolverdxqy.h.

◆ randNumGen

template<MInt nDim, MInt nDist, class SysEqn >
std::mt19937 LbSolverDxQy< nDim, nDist, SysEqn >::randNumGen

Definition at line 322 of file lbsolverdxqy.h.


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