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

#include <lpt.h>

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

Classes

struct  PrimitiveVariables
 Static indices for accessing primitive variables in nDim spatial dimensions. More...
 

Public Types

using CartesianSolver = typename maia::CartesianSolver< nDim, LPT >
 
using Cell = typename maia::grid::tree::Tree< nDim >::Cell
 
using Geom = Geometry< nDim >
 
using Grid = typename CartesianSolver::Grid
 
using GridProxy = typename CartesianSolver::GridProxy
 
using LptCellCollector = maia::lpt::collector::LptCells< nDim >
 
- Public Types inherited from maia::CartesianSolver< nDim, LPT< nDim > >
using Grid = CartesianGrid< nDim >
 
using GridProxy = typename maia::grid::Proxy< nDim >
 
using Geom = Geometry< nDim >
 
using TreeProxy = maia::grid::tree::TreeProxy< nDim >
 
using Cell = maia::grid::tree::Cell
 

Public Member Functions

Geomgeometry () const
 Access the solver's geometry. More...
 
 LPT (const MInt solverId, GridProxy &gridProxy_, Geom &geometry_, const MPI_Comm comm)
 Solver constructor. More...
 
virtual ~LPT ()
 
 LPT (const LPT &)=delete
 
LPToperator= (const LPT &)=delete
 
void preTimeStep () override
 prepare the LPT timeStep More...
 
MBool solutionStep () override
 Time stepping of particles NOTE: the solutionStep is split into sub-steps, to allow for an interleafed computation when coupled with a different solver! More...
 
void postTimeStep () override
 after the LPT time-Step! More...
 
void initSolver () override
 
void finalizeInitSolver () override
 
void saveSolverSolution (const MBool, const MBool) override
 
void cleanUp () override
 
void prepareAdaptation () override
 prepare solver adaptation More...
 
void setSensors (std::vector< std::vector< MFloat > > &, std::vector< MFloat > &, std::vector< std::bitset< 64 > > &, std::vector< MInt > &) override
 set the sensors for a single adaptation step More...
 
void swapProxy (MInt, MInt) override
 
void resizeGridMap () override
 Swap the given cells. More...
 
void postAdaptation () override
 post adaptation for split adaptation within the adaptation loop More...
 
void finalizeAdaptation () override
 reinit the solver after the full adaptation loop! More...
 
void removeChilds (const MInt) override
 coarseining a cartesian cell More...
 
void removeCell (const MInt) override
 Remove the given cell. More...
 
void refineCell (const MInt) override
 refining a cartesian cell More...
 
void swapCells (const MInt, const MInt) override
 swap Cell information when the grid collector is restructured during adaptation cleanup More...
 
MInt cellOutside (const MFloat *, const MInt, const MInt) override
 checks if a child lies outSide of the domain! necessary for refinement at the bndry! More...
 
void sensorParticle (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 set the sensors around the particle positions to get the markedCells More...
 
void sensorInterface (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen) override
 set the sensors around the boundary positions to get the markedCells More...
 
MBool forceAdaptation () override
 Returns the LPT adaptation forcing. More...
 
MBool prepareRestart (MBool force, MBool &) override
 before writing a restart file More...
 
void writeRestartFile (const MBool, const MBool, const MString, MInt *) override
 writing a restart File as regularly called from the grid-controller! More...
 
void writeParticleRestartFile ()
 Write particle restart file. More...
 
void writeCellSolutionFile (const MString &, MInt *)
 Write lpt cell based solution file currently ony used for debugging! More...
 
void reIntAfterRestart (MBool) override
 
void saveDebugRestartFile ()
 writing a restart File NOTE: for debugging purposes only! More...
 
void writeRestartFile (MBool) override
 
void setCellWeights (MFloat *) override
 set cell weight for partitioning More...
 
void getSolverTimings (std::vector< std::pair< std::string, MFloat > > &, const MBool allTimings) override
 Get solver timings. More...
 
void getDefaultWeights (MFloat *weights, std::vector< MString > &names) const override
 Return the default weights for all load quantities. More...
 
void getLoadQuantities (MInt *const loadQuantities) const override
 Return the cumulative load quantities on this domain. More...
 
MFloat getCellLoad (const MInt cellId, const MFloat *const weights) const override
 Return the load of a single cell (given computational weights). More...
 
void limitWeights (MFloat *) override
 Limit weight of base cell. More...
 
void getDomainDecompositionInformation (std::vector< std::pair< MString, MInt > > &domainInfo) override
 Return decomposition information, i.e. number of local elements,... More...
 
MInt noSolverTimers (const MBool allTimings) override
 
MInt noLoadTypes () const override
 
void resetSolverFull ()
 reset the solver during balancing More...
 
void resetSolver () override
 actually doing some pre-balance-stuff More...
 
void balancePre () override
 reset the solver during balancing More...
 
void balancePost () override
 Reinitialize solver after setting solution data in DLB. More...
 
void finalizeBalance () override
 re-inits the solver after the balance More...
 
void cancelMpiRequests () override
 actually doing same pre-partitioneing stuff during balcne More...
 
MInt noCellDataDlb () const override
 Methods to inquire solver data information. More...
 
MInt cellDataTypeDlb (const MInt dataId) const override
 
MInt cellDataSizeDlb (const MInt dataId, const MInt cellId) override
 Return data size to be communicated during DLB for a grid cell and given data id. More...
 
void getCellDataDlb (const MInt dataId, const MInt oldNoCells, const MInt *const bufferIdToCellId, MInt *const data) override
 Return solver data for DLB. More...
 
void getCellDataDlb (const MInt dataId, const MInt oldNoCells, const MInt *const bufferIdToCellId, MFloat *const data) override
 Store the solver data for a given data id ordered in the given buffer for DLB. More...
 
void setCellDataDlb (const MInt dataId, const MInt *const data) override
 Set solver data for DLB. More...
 
void setCellDataDlb (const MInt dataId, const MFloat *const data) override
 Set the solver cell data after DLB. More...
 
void getGlobalSolverVars (std::vector< MFloat > &globalFloatVars, std::vector< MInt > &globalIdVars) override
 Get/set global solver variables during DLB. More...
 
void setGlobalSolverVars (std::vector< MFloat > &globalFloatVars, std::vector< MInt > &globalIdVars) override
 Set global solver variables for DLB (same on each domain) More...
 
MBool hasSplitBalancing () const override
 Return if load balancing for solver is split into multiple methods or implemented in balance() More...
 
MFloat computeTimeStep ()
 computes the non-dimensional LPT time-step on the assumption that a particle may only travel for a complete cell length with cfl = 1 at current velocity! More...
 
MFloat timeStep ()
 
void forceTimeStep (const MFloat timeStep)
 
MInt a_timeStepComputationInterval ()
 
MInt a_hasNeighbor (const MInt cellId, const MInt dir) const
 
MInt mpiTag (const MString exchangeType)
 
MFloat reduceData (const MInt cellId, MFloat *data, const MInt dataBlockSize=1, const MBool average=true)
 reduce data to lower level More...
 
template<class LPTParticle = LPTSpherical<nDim>>
MInt a_noParticles ()
 
MInt a_noSphericalParticles () const
 
MInt a_noEllipsoidalParticles () const
 
MInt a_noCells () const
 
template<class LPTParticle >
std::vector< LPTParticle > & a_particleList ()
 
MFloata_volumeFraction (const MInt cellId)
 
MFloat a_volumeFraction (const MInt cellId) const
 
MInta_noParticlesInCell (const MInt cellId)
 
MInt a_noParticlesInCell (const MInt cellId) const
 
MInta_noEllipsoidsInCell (const MInt cellId)
 
MInt a_noEllipsoidsInCell (const MInt cellId) const
 
MInta_bndryCellId (const MInt cellId)
 
MInt a_bndryCellId (const MInt cellId) const
 
MFloata_fluidVariable (const MInt cellId, const MInt var)
 
MFloat a_fluidVariable (const MInt cellId, const MInt var) const
 
MFloata_fluidVelocity (const MInt cellId, const MInt dim)
 
MFloat a_fluidVelocity (const MInt cellId, const MInt dim) const
 
MFloata_fluidDensity (const MInt cellId)
 
MFloat a_fluidDensity (const MInt cellId) const
 
MFloata_fluidPressure (const MInt cellId)
 
MFloat a_fluidPressure (const MInt cellId) const
 
MFloata_fluidTemperature (const MInt cellId)
 
MFloat a_fluidTemperature (const MInt cellId) const
 
MFloata_fluidSpecies (const MInt cellId)
 
MFloat a_fluidSpecies (const MInt cellId) const
 
MFloata_heatFlux (const MInt cellId)
 
MFloat a_heatFlux (const MInt cellId) const
 
MFloata_massFlux (const MInt cellId)
 
MFloat a_massFlux (const MInt cellId) const
 
MFloata_momentumFlux (const MInt cellId, const MInt dim)
 
MFloat a_momentumFlux (const MInt cellId, const MInt dim) const
 
MFloata_workFlux (const MInt cellId)
 
MFloat a_workFlux (const MInt cellId) const
 
MFloata_velocitySlope (const MInt cellId, const MInt varId, const MInt dir)
 
MFloat a_velocitySlope (const MInt cellId, const MInt varId, const MInt dir) const
 
void a_resetPropertiesSolver (const MInt cellId)
 
MBool a_isHalo (const MInt cellId) const
 
maia::lpt::cell::BitsetType::reference a_isHalo (const MInt cellId)
 
MBool a_isWindow (const MInt cellId) const
 
maia::lpt::cell::BitsetType::reference a_isWindow (const MInt cellId)
 
MBool a_isValidCell (const MInt cellId) const
 
maia::lpt::cell::BitsetType::reference a_isValidCell (const MInt cellId)
 
MBool a_regridTrigger (const MInt cellId) const
 
maia::lpt::cell::BitsetType::reference a_regridTrigger (const MInt cellId)
 
MBool a_isBndryCell (const MInt cellId) const override
 
const MFloata_coordinate (const MInt cellId, const MInt dim) const
 
template<class P , MInt a, MInt b>
void interpolateAndCalcWeights (P &particle, const MInt cellId, const MFloat *position, const MFloat *interpolatedVar, std::vector< MFloat > &weight)
 
template<MInt a, MInt b, MBool interpolateVelocitySlopes>
void interpolateVariablesLS (const MInt cellId, const MFloat *const position, MFloat *const interpolatedVar)
 calculates interpolated variables (in the range a, b) for a given position in a given cell More...
 
template<MInt a, MInt b>
void interpolateVariablesLS (const MInt cellId, const MFloat *const position, MFloat *const interpolatedVar)
 
void updateFluidFraction ()
 
MFloat injectionDuration () const
 
MFloat timeSinceSOI () const
 
MInt injectorCellId () const
 
MInt globalNoParticles ()
 
MInt globalNoEllipsoids ()
 
template<class LPTParticle >
MBool pushToQueue (std::vector< std::map< MInt, MInt > > &pointsTo, const MInt partPos)
 
MFloat time () const override
 Return the time. More...
 
MInt noVariables () const override
 Return the number of variables. More...
 
MInt c_noCells () const
 
MInt c_childId (const MInt cellId, const MInt pos) const
 
MInt c_noChildren (const MInt cellId) const
 
MInt c_parentId (const MInt cellId) const
 
MFloat c_cellLengthAtLevel (const MInt level) const
 
MFloat c_cellLengthAtCell (const MInt cellId) const
 
MInt c_level (const MInt cellId) const
 
MInt a_level (const MInt cellId) const
 
MFloat c_cellVolume (const MInt cellId) const
 
MFloat c_coordinate (const MInt cellId, const MInt dir) const
 
MBool c_isLeafCell (const MInt cellId) const
 
MLong c_globalId (const MInt cellId) const
 
MInt noInternalCells () const override
 Return the number of internal cells within this solver. More...
 
MInt domainId () const override
 Return the domainId (rank) More...
 
MInt noDomains () const override
 
MInt c_hasNeighbor (const MInt cellId, const MInt dir) const
 
MInt c_neighborId (const MInt cellId, const MInt dir) const
 
MBool a_validCell (const MInt cellId)
 
void loadSampleVariables (MInt timeStep)
 
void getSampleVariables (MInt cellId, const MFloat *&vars)
 
void getSampleVariables (const MInt cellId, std::vector< MFloat > &)
 
void calculateHeatRelease ()
 
void getHeatRelease (MFloat *&heatRelease)
 
- Public Member Functions inherited from maia::CartesianSolver< nDim, LPT< nDim > >
 CartesianSolver (const MInt solverId, GridProxy &gridProxy_, const MPI_Comm comm, const MBool checkActive=false)
 
MInt minLevel () const
 Read-only accessors for grid data. More...
 
MInt maxLevel () const
 
MInt maxNoGridCells () const
 
MInt maxRefinementLevel () const
 
MInt maxUniformRefinementLevel () const
 
MInt noNeighborDomains () const
 
MInt neighborDomain (const MInt id) const
 
MLong domainOffset (const MInt id) const
 
MInt noHaloLayers () const
 
MInt noHaloCells (const MInt domainId) const
 
MInt haloCellId (const MInt domainId, const MInt cellId) const
 
MInt noWindowCells (const MInt domainId) const
 
MInt windowCellId (const MInt domainId, const MInt cellId) const
 
MString gridInputFileName () const
 
MFloat reductionFactor () const
 
MFloat centerOfGravity (const MInt dir) const
 
MInt neighborList (const MInt cellId, const MInt dir) const
 
const MLonglocalPartitionCellGlobalIds (const MInt cellId) const
 
MLong localPartitionCellOffsets (const MInt index) const
 
MInt noMinCells () const
 
MInt minCell (const MInt id) const
 
const MInthaloCell (const MInt domainId, const MInt cellId) const
 
const MIntwindowCell (const MInt domainId, const MInt cellId) const
 
MBool isActive () const override
 
constexpr GridProxygrid () const
 
GridProxygrid ()
 
virtual void sensorDerivative (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorDivergence (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorTotalPressure (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorEntropyGrad (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorEntropyQuot (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorVorticity (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorInterface (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
void sensorLimit (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt, std::function< MFloat(MInt)>, const MFloat, const MInt *, const MBool, const MBool allowCoarsening=true)
 simple sensor to apply a limit for a value More...
 
void sensorSmooth (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 sensor to smooth level jumps NOTE: only refines additional cells to ensure a smooth level transition this requires that all other sensors are frozen i.e. no refine/coarse sensors set! More...
 
void sensorBand (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 This sensor generates a max refinement band around the cells with max refinement level. In order for it to work, the property addedAdaptationSteps has to be equal to /maxRefinementLevel() - minLevel()/. This sensor also ensures a smooth transition between levels. Do not use together with sensorSmooth. More...
 
virtual void sensorMeanStress (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorParticle (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorSpecies (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
virtual void sensorPatch (std::vector< std::vector< MFloat > > &sensor, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen)
 
virtual void sensorCutOff (std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 
void saveSensorData (const std::vector< std::vector< MFloat > > &sensors, const MInt &level, const MString &gridFileName, const MInt *const recalcIds) override
 Saves all sensor values for debug/tunig purposes. More...
 
void assertValidGridCellId (const MInt) const
 
MLong c_parentId (const MInt cellId) const
 Returns the grid parent id of the cell cellId. More...
 
MLong c_neighborId (const MInt cellId, const MInt dir) const
 Returns the grid neighbor id of the grid cell cellId dir. More...
 
MInt c_noCells () const
 
MInt c_level (const MInt cellId) const
 
MLong c_globalGridId (const MInt cellId)
 
void exchangeData (T *data, const MInt dataBlockSize=1)
 Exchange memory in 'data' assuming a solver size of 'dataBlockSize' per cell. More...
 
void exchangeLeafData (std::function< T &(MInt, MInt)> data, const MInt noDat=1)
 Blocking exchange memory in 'data' assuming a solver size of 'dataBlockSize' per cell NOTE: exchange is only performed on leaf-cells and leaf-NeighborDomains Assumes, that updateLeafCellExchange has been called in the proxy previously! More...
 
void exchangeSparseLeafValues (G getData, S setData, const MInt dataSize, M cellMapping)
 Exchange of sparse data structures on max Level. More...
 
void exchangeAzimuthalPer (T *data, MInt dataBlockSize=1, MInt firstBlock=0)
 Exchange of sparse data structures on max Level. More...
 
void collectVariables (T *variablesIn, ScratchSpace< T > &variablesOut, const std::vector< MString > &variablesNameIn, std::vector< MString > &variablesNameOut, const MInt noVars, const MInt noCells, const MBool reverseOrder=false)
 generalised helper function for writing restart files! This is necessary for example if the minLevel shall be raised at the new restart! More...
 
void collectVariables (T **variablesIn, ScratchSpace< T > &variablesOut, const std::vector< MString > &variablesNameIn, std::vector< MString > &variablesNameOut, const MInt noVars, const MInt noCells)
 generalised helper function for writing restart files! This is necessary for example if the minLevel shall be raised at the new restart! More...
 
void saveGridFlowVars (const MChar *fileName, const MChar *gridFileName, const MInt noTotalCells, const MInt noInternal, MFloatScratchSpace &dbVariables, std::vector< MString > &dbVariablesName, MInt noDbVars, MIntScratchSpace &idVariables, std::vector< MString > &idVariablesName, MInt noIdVars, MFloatScratchSpace &dbParameters, std::vector< MString > &dbParametersName, MIntScratchSpace &idParameters, std::vector< MString > &idParametersName, MInt *recalcIds, MFloat time)
 This function writes the parallel Netcdf cartesian grid cell based solution/restart file currently used in PostData, LPT and LS solvers! More...
 
void collectParameters (T, ScratchSpace< T > &, const MChar *, std::vector< MString > &)
 This function collects a single parameters for the massivley parallel IO functions. More...
 
void calcRecalcCellIdsSolver (const MInt *const recalcIdsTree, MInt &noCells, MInt &noInternalCellIds, std::vector< MInt > &recalcCellIdsSolver, std::vector< MInt > &reorderedCellIds)
 Derive recalc cell ids of the solver and reordered cell ids. More...
 
- Public Member Functions inherited from Solver
MString getIdentifier (const MBool useSolverId=false, const MString preString="", const MString postString="_")
 
virtual ~Solver ()=default
 
virtual MInt noInternalCells () const =0
 Return the number of internal cells within this solver. More...
 
virtual MFloat time () const =0
 Return the time. More...
 
virtual MInt noVariables () const
 Return the number of variables. More...
 
virtual void getDimensionalizationParams (std::vector< std::pair< MFloat, MString > > &) const
 Return the dimensionalization parameters of this solver. More...
 
void updateDomainInfo (const MInt domainId, const MInt noDomains, const MPI_Comm mpiComm, const MString &loc)
 Set new domain information. More...
 
virtual MFloata_slope (const MInt, MInt const, const MInt)
 
virtual MBool a_isBndryCell (const MInt) const
 
virtual MFloata_FcellVolume (MInt)
 
virtual MInt getCurrentTimeStep () const
 
virtual void accessSampleVariables (MInt, MFloat *&)
 
virtual void getSampleVariableNames (std::vector< MString > &NotUsed(varNames))
 
virtual MBool a_isBndryGhostCell (MInt) const
 
virtual void saveCoarseSolution ()
 
virtual void getSolverSamplingProperties (std::vector< MInt > &NotUsed(samplingVarIds), std::vector< MInt > &NotUsed(noSamplingVars), std::vector< std::vector< MString > > &NotUsed(samplingVarNames), const MString NotUsed(featureName)="")
 
virtual void initSolverSamplingVariables (const std::vector< MInt > &NotUsed(varIds), const std::vector< MInt > &NotUsed(noSamplingVars))
 
virtual void calcSamplingVariables (const std::vector< MInt > &NotUsed(varIds), const MBool NotUsed(exchange))
 
virtual void calcSamplingVarAtPoint (const MFloat *NotUsed(point), const MInt NotUsed(id), const MInt NotUsed(sampleVarId), MFloat *NotUsed(state), const MBool NotUsed(interpolate)=false)
 
virtual void balance (const MInt *const NotUsed(noCellsToReceiveByDomain), const MInt *const NotUsed(noCellsToSendByDomain), const MInt *const NotUsed(targetDomainsByCell), const MInt NotUsed(oldNoCells))
 Perform load balancing. More...
 
virtual MBool hasSplitBalancing () const
 Return if load balancing for solver is split into multiple methods or implemented in balance() More...
 
virtual void balancePre ()
 
virtual void balancePost ()
 
virtual void finalizeBalance ()
 
virtual void resetSolver ()
 Reset the solver/solver for load balancing. More...
 
virtual void cancelMpiRequests ()
 Cancel open mpi (receive) requests in the solver (e.g. due to interleaved execution) More...
 
virtual void setCellWeights (MFloat *)
 Set cell weights. More...
 
virtual MInt noLoadTypes () const
 
virtual void getDefaultWeights (MFloat *NotUsed(weights), std::vector< MString > &NotUsed(names)) const
 
virtual void getLoadQuantities (MInt *const NotUsed(loadQuantities)) const
 
virtual MFloat getCellLoad (const MInt NotUsed(cellId), const MFloat *const NotUsed(weights)) const
 
virtual void limitWeights (MFloat *NotUsed(weights))
 
virtual void localToGlobalIds ()
 
virtual void globalToLocalIds ()
 
virtual MInt noCellDataDlb () const
 Methods to inquire solver data information. More...
 
virtual MInt cellDataTypeDlb (const MInt NotUsed(dataId)) const
 
virtual MInt cellDataSizeDlb (const MInt NotUsed(dataId), const MInt NotUsed(cellId))
 
virtual void getCellDataDlb (const MInt NotUsed(dataId), const MInt NotUsed(oldNoCells), const MInt *const NotUsed(bufferIdToCellId), MInt *const NotUsed(data))
 
virtual void getCellDataDlb (const MInt NotUsed(dataId), const MInt NotUsed(oldNoCells), const MInt *const NotUsed(bufferIdToCellId), MLong *const NotUsed(data))
 
virtual void getCellDataDlb (const MInt NotUsed(dataId), const MInt NotUsed(oldNoCells), const MInt *const NotUsed(bufferIdToCellId), MFloat *const NotUsed(data))
 
virtual void setCellDataDlb (const MInt NotUsed(dataId), const MInt *const NotUsed(data))
 
virtual void setCellDataDlb (const MInt NotUsed(dataId), const MLong *const NotUsed(data))
 
virtual void setCellDataDlb (const MInt NotUsed(dataId), const MFloat *const NotUsed(data))
 
virtual void getGlobalSolverVars (std::vector< MFloat > &NotUsed(globalFloatVars), std::vector< MInt > &NotUsed(globalIntVars))
 
virtual void setGlobalSolverVars (std::vector< MFloat > &NotUsed(globalFloatVars), std::vector< MInt > &NotUsed(globalIdVars))
 
void enableDlbTimers ()
 
void reEnableDlbTimers ()
 
void disableDlbTimers ()
 
MBool dlbTimersEnabled ()
 
void startLoadTimer (const MString name)
 
void stopLoadTimer (const MString &name)
 
void stopIdleTimer (const MString &name)
 
void startIdleTimer (const MString &name)
 
MBool isLoadTimerRunning ()
 
virtual MInt noSolverTimers (const MBool NotUsed(allTimings))
 
virtual void getSolverTimings (std::vector< std::pair< MString, MFloat > > &NotUsed(solverTimings), const MBool NotUsed(allTimings))
 
virtual void getDomainDecompositionInformation (std::vector< std::pair< MString, MInt > > &NotUsed(domainInfo))
 
void setDlbTimer (const MInt timerId)
 
virtual void prepareAdaptation (std::vector< std::vector< MFloat > > &, std::vector< MFloat > &, std::vector< std::bitset< 64 > > &, std::vector< MInt > &)
 
virtual void reinitAfterAdaptation ()
 
virtual void prepareAdaptation ()
 prepare adaptation for split adaptation before the adaptation loop More...
 
virtual void setSensors (std::vector< std::vector< MFloat > > &, std::vector< MFloat > &, std::vector< std::bitset< 64 > > &, std::vector< MInt > &)
 set solver sensors for split adaptation within the adaptation loop More...
 
virtual void saveSensorData (const std::vector< std::vector< MFloat > > &, const MInt &, const MString &, const MInt *const)
 
virtual void postAdaptation ()
 post adaptation for split adaptation within the adaptation loop More...
 
virtual void finalizeAdaptation ()
 finalize adaptation for split sadptation after the adaptation loop More...
 
virtual void refineCell (const MInt)
 Refine the given cell. More...
 
virtual void removeChilds (const MInt)
 Coarsen the given cell. More...
 
virtual void removeCell (const MInt)
 Remove the given cell. More...
 
virtual void swapCells (const MInt, const MInt)
 Swap the given cells. More...
 
virtual void swapProxy (const MInt, const MInt)
 Swap the given cells. More...
 
virtual MInt cellOutside (const MFloat *, const MInt, const MInt)
 Check whether cell is outside the fluid domain. More...
 
virtual void resizeGridMap ()
 Swap the given cells. More...
 
virtual MBool prepareRestart (MBool, MBool &)
 Prepare the solvers for a grid-restart. More...
 
virtual void reIntAfterRestart (MBool)
 
MPI_Comm mpiComm () const
 Return the MPI communicator used by this solver. More...
 
virtual MInt domainId () const
 Return the domainId (rank) More...
 
virtual MInt noDomains () const
 
virtual MBool isActive () const
 
void setSolverStatus (const MBool status)
 
MBool getSolverStatus ()
 Get the solver status indicating if the solver is currently active in the execution recipe. More...
 
MString testcaseDir () const
 Return the testcase directory. More...
 
MString outputDir () const
 Return the directory for output files. More...
 
MString restartDir () const
 Return the directory for restart files. More...
 
MString solverMethod () const
 Return the solverMethod of this solver. More...
 
MString solverType () const
 Return the solverType of this solver. More...
 
MInt restartInterval () const
 Return the restart interval of this solver. More...
 
MInt restartTimeStep () const
 Return the restart interval of this solver. More...
 
MInt solverId () const
 Return the solverId. More...
 
MBool restartFile ()
 
MInt readSolverSamplingVarNames (std::vector< MString > &varNames, const MString featureName="") const
 Read sampling variables names, store in vector and return the number of sampling variables. More...
 
virtual MBool hasRestartTimeStep () const
 
virtual MBool forceAdaptation ()
 
virtual void preTimeStep ()=0
 
virtual void postTimeStep ()=0
 
virtual void initSolver ()=0
 
virtual void finalizeInitSolver ()=0
 
virtual void saveSolverSolution (const MBool NotUsed(forceOutput)=false, const MBool NotUsed(finalTimeStep)=false)=0
 
virtual void cleanUp ()=0
 
virtual MBool solutionStep ()
 
virtual void preSolutionStep (MInt)
 
virtual MBool postSolutionStep ()
 
virtual MBool solverConverged ()
 
virtual void getInterpolatedVariables (MInt, const MFloat *, MFloat *)
 
virtual void loadRestartFile ()
 
virtual MInt determineRestartTimeStep () const
 
virtual void writeRestartFile (MBool)
 
virtual void writeRestartFile (const MBool, const MBool, const MString, MInt *)
 
virtual void setTimeStep ()
 
virtual void implicitTimeStep ()
 
virtual void prepareNextTimeStep ()
 

Public Attributes

Geomm_geometry
 
LptCellCollector m_cells
 
PrimitiveVariables PV
 
Collector< LPTBndryCell< nDim > > * m_bndryCells = nullptr
 
std::unique_ptr< ParticleCollision< nDim > > m_collisionModel
 
std::map< MInt, std::vector< MFloat > > m_injData
 
MFloat m_sutherlandConstant = -1
 
MFloat m_sutherlandPlusOne = -1
 
MBool m_nonDimensional = false
 
MInt m_noSolutionSteps = 1
 
MInt m_solutionStep = 0
 
MInt m_restartTimeStep {}
 
- Public Attributes inherited from Solver
std::set< MIntm_freeIndices
 
MBool m_singleAdaptation = false
 
MBool m_splitAdaptation = true
 
MBool m_saveSensorData = false
 

Protected Types

using Timers = maia::lpt::Timers_
 
- Protected Types inherited from maia::CartesianSolver< nDim, LPT< nDim > >
using fun = void(CartesianSolver< nDim, LPT< nDim > >::*)(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt)
 

Protected Member Functions

void calculateTerminalVelocities ()
 calculates the terminal velocity of particles used for initialization More...
 
MFloat calculateAverageRep ()
 
MFloat calculateVRMS ()
 
MFloat calculateTotalKineticEnergy ()
 
void particleRespawn ()
 respawn of Particles More...
 
void spawnParticles ()
 Spawn new particles (used for testing) More...
 
MInt addParticle (const MInt cellId, const MFloat diameter, const MFloat particleDensityRatio, const MInt random=1, const MInt addMode=0, const MFloat *velocity=nullptr, const MFloat *position=nullptr, const MInt parcelSize=1)
 Add new particle. More...
 
MInt addEllipsoid (const MInt cellId, const MFloat semiMinorAxis, const MFloat aspectRatio, const MFloat particleDensityRatio, const MInt random=1, const MInt addMode=0, const MFloat *velocity=nullptr, const MFloat *position=nullptr)
 Add new ellipsoidal particle. More...
 
MInt loadParticleRestartFile ()
 Read particle restart file and create new particle instances accordingly. More...
 
void writePartData ()
 write particle snapshot to Netcdf file (using parallel output) More...
 
void crankAngleSolutionOutput ()
 save a full solutionOutput at timeSteps closesed to a specified crankAngle Interval save a solution slice at timeSteps closesed to a specified slice Interval More...
 
template<class LPTParticle >
MInt elemPerP ()
 
template<class LPTParticle >
MInt intElemPerP ()
 
template<class LPTParticle >
MInt bufSize ()
 
template<class LPTParticle >
MInt intBufSize ()
 
void exchangeParticles (const MBool collOnly, const MInt offset, const MBool allowNonLeaf=false)
 Calls exchange for the different particle types. More...
 
template<class LPTParticle >
void exchangeParticles_ (const MBool collOnly, const MInt offset, const MBool allowNonLeaf=false)
 exchange particles to neighboring domains, can be either non-blocking or blocking communication! More...
 
template<class LPTParticle >
void sendAndReceiveParticles (const MBool allowNonLeaf)
 Particle transfer between solvers The particles to be sent are in the queueToSend array MBool mayExist is true for particle transfer after collisions, since in that case the particle may already be found on this rank. More...
 
template<MBool allNeighbors, class LPTParticle >
void sendParticles ()
 send particles non-blocking More...
 
template<MBool allNeighbors>
void receiveParticles ()
 Calls particle receive function for different particle types. More...
 
template<MBool allNeighbors, class LPTParticle >
void receiveParticles_ ()
 receive particles that have been sent non-blocking before More...
 
void exchangeOffset (MInt noParticles)
 In case of multisolver, communicate particle id offset to ensure consistent particle ids across the solvers. More...
 
void exchangeSourceTerms ()
 exchanges the source terms on the LPT grid, this is necessary a) before writing the cell solution file for consistent/rank-independant data b) before the adaptation, so that all relevant data is stored on window-cells c) before transferring the source terms to the coupled solver, so that all relevant data is stored on window cells More...
 
void sendSourceTerms ()
 exchanges the source terms on the LPT grid, non-Blocking version from above More...
 
void receiveSourceTerms ()
 exchanges the source terms on the LPT grid, non-Blocking version from above More...
 
void sendFlowField ()
 exchanges the flow Field data on the LPT grid, non-Blocking version More...
 
void receiveFlowField ()
 exchanges the flow Field data on the LPT grid, non-Blocking version More...
 
void waitForSendReqs ()
 wait on all mpi send calls, prior to balance, adaptation or IO More...
 
void sendVelocitySlopes ()
 exchanges the velocity slopes on the LPT grid, non-Blocking version More...
 
void receiveVelocitySlopes ()
 exchanges the velocity slopes on the LPT grid, non-Blocking version More...
 
void checkParticles ()
 some debug check for partcles More...
 
void checkCells ()
 some debug check for cells More...
 
void resetSourceTerms (const MInt)
 reset all source terms with cellId larger than the offset More...
 
template<class T , class Pred >
void own_sort (T &c, Pred &p)
 
template<class T , class Pred >
void sort_impl_ (T &c, Pred &p, std::random_access_iterator_tag)
 
template<class T , class Pred >
void own_remove_if (T &c, Pred &p)
 
template<class T , class Pred >
void remove_if_impl_ (T &c, Pred &p, std::random_access_iterator_tag)
 
MBool smallParticle (const LPTSpherical< nDim > &particle)
 
std::mt19937_64 & randomSpawn (const MInt calls)
 
std::mt19937_64 & randomRespawn ()
 
std::mt19937_64 & randomInit ()
 
- Protected Member Functions inherited from maia::CartesianSolver< nDim, LPT< nDim > >
void identifyBoundaryCells (MBool *const isInterface, const std::vector< MInt > &bndCndIds=std::vector< MInt >())
 
void identifyBoundaryCells ()
 
MBool cellIsOnGeometry (MInt cellId, Geometry< nDim > *geom)
 checks whether a cell lies on a certain geometry copied the essential part from identifyBoundaryCells More...
 
void setBoundaryDistance (const MBool *const interfaceCell, const MFloat *const outerBandWidth, MFloatScratchSpace &distance)
 transverses over all neighboring cells for a specified length More...
 
void markSurrndCells (MIntScratchSpace &inList, const MInt bandWidth, const MInt level, const MBool refineDiagonals=true)
 
void receiveWindowTriangles ()
 Receives triangles from neighbors contained in their window cells and inserts them locally. More...
 
void compactCells ()
 Removes all holes in the cell collector and moves halo cells to the back of the collector. More...
 
MInt createCellId (const MInt gridCellId)
 
void removeCellId (const MInt cellId)
 
MInt inCell (const MInt cellId, MFloat *point, MFloat fac=F1)
 
MInt setUpInterpolationStencil (const MInt cellId, MInt *, const MFloat *, std::function< MBool(MInt, MInt)>, MBool allowIncompleteStencil)
 
MFloat interpolateFieldData (MInt *, MFloat *, MInt varId, std::function< MFloat(MInt, MInt)> scalarField, std::function< MFloat(MInt, MInt)> coordinate)
 
MFloat leastSquaresInterpolation (MInt *, MFloat *, MInt varId, std::function< MFloat(MInt, MInt)> scalarField, std::function< MFloat(MInt, MInt)> coordinate)
 
void checkNoHaloLayers ()
 check that each solver has the required number of haloLayers for leaf cells!!! TODO labels:toenhance under production, needs to be cleaned up! More...
 
void mapInterpolationCells (std::map< MInt, MInt > &cellMap)
 
void setHaloCellsOnInactiveRanks ()
 
void patchRefinement (std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen)
 
void reOrderCellIds (std::vector< MInt > &reOrderedCells)
 reOrder cellIds before writing the restart file! This is necessary for example if the minLevel shall be raised at the new restart! More...
 
void recomputeGlobalIds (std::vector< MInt > &, std::vector< MLong > &)
 reOrder cellIds before writing the restart file! This is necessary for example if the minLevel shall be raised at the new restart! More...
 
void extractPointIdsFromGrid (Collector< PointBasedCell< nDim > > *&, Collector< CartesianGridPoint< nDim > > *&, const MBool, const std::map< MInt, MInt > &, MInt levelThreshold=999999, MFloat *bBox=nullptr, MBool levelSetMb=false) const
 Creates a list of unique corner points for all cells using a hash map levelThreshold optionally specifies the maximum cell level to be extracted bBox optionally specifies a bounding to box to which the extracted domain shall be truncated. More...
 
- Protected Member Functions inherited from Solver
 Solver (const MInt solverId, const MPI_Comm comm, const MBool isActive=true)
 
MFloat returnLoadRecord () const
 
MFloat returnIdleRecord () const
 

Protected Attributes

std::vector< LPTSpherical< nDim > > m_partList
 
std::vector< LPTEllipsoidal< nDim > > m_partListEllipsoid
 
std::map< MInt, std::vector< MInt > > m_cellToNghbrHood
 
std::map< MInt, std::vector< MInt > > m_cellToNghbrHoodInterpolation
 
MInt m_timerGroup = -1
 
std::array< MInt, Timers::_countm_timers {}
 
MInt m_sleepLPT = -1
 
MBool m_skipLPT = false
 
MBool m_domainIdOutput = false
 
MFloat m_weightBaseCell = 0.0
 
MFloat m_weightLeafCell = 0.05
 
MFloat m_weightParticleCell = 0.1
 
MFloat m_weightParticle = 0.1
 
MFloat m_weightSpawnCell = 5.0
 
MFloat m_weightMulitSolverFactor = 1
 
MBool m_limitWeights = false
 
MBool m_weightSourceCells = false
 
MFloat m_time = 0.0
 
std::mt19937_64 m_PRNGSpawn
 
MInt m_PRNGSpawnCount = 0
 
std::mt19937_64 m_PRNGRespawn
 
std::mt19937_64 m_PRNGInit
 
particleSendQueue< nDim > m_queueToSend
 
std::vector< std::map< MInt, MInt > > m_pointsToHalo
 
std::vector< std::map< MInt, MInt > > m_pointsToWindow
 
std::map< MFloat, MFloatm_terminalVelocity
 
MFloat m_timeStep {}
 
MFloat m_timeStepOld {}
 
MInt m_timeStepComputationInterval {}
 
MBool m_timeStepUpdated = true
 
MBool m_primaryExchange = false
 
MInt m_noSourceTerms = 0
 
MPI_Request * m_sourceSendRequest = nullptr
 
MPI_Request * m_sourceRecvRequest = nullptr
 
std::vector< std::unique_ptr< MFloat[]> > m_sourceRecv {}
 
std::vector< std::unique_ptr< MFloat[]> > m_sourceSend {}
 
MPI_Request * m_checkAdaptationRecvRequest = nullptr
 
MPI_Request * m_checkAdaptationSendRequest = nullptr
 
std::vector< MIntm_checkAdaptationRecv {}
 
std::vector< MIntm_checkAdaptationSend {}
 
MPI_Request * m_flowSendRequest = nullptr
 
MPI_Request * m_flowRecvRequest = nullptr
 
MFloat ** m_flowRecv = nullptr
 
MFloat ** m_flowSend = nullptr
 
MPI_Request * m_slopesSendRequest = nullptr
 
MPI_Request * m_slopesRecvRequest = nullptr
 
MFloat ** m_slopesRecv = nullptr
 
MFloat ** m_slopesSend = nullptr
 
std::vector< MIntm_sendSize {}
 
std::vector< MIntm_recvSize {}
 
std::vector< MPI_Request > m_mpi_reqSendFloat {}
 
std::vector< MPI_Request > m_mpi_reqSendInt {}
 
std::vector< MPI_Request > m_mpi_reqSendSize {}
 
std::vector< MPI_Request > m_mpi_reqRecvFloat {}
 
std::vector< MPI_Request > m_mpi_reqRecvInt {}
 
std::vector< MPI_Status > m_mpi_statusProbe {}
 
std::vector< std::unique_ptr< MFloat[]> > m_sendBuffer {}
 
std::vector< std::unique_ptr< MFloat[]> > m_recvBuffer {}
 
std::vector< std::unique_ptr< MInt[]> > m_intSendBuffer {}
 
std::vector< std::unique_ptr< MInt[]> > m_intRecvBuffer {}
 
MBool m_nonBlockingComm = false
 
MInt m_nonBlockingStage = -1
 
MBool m_receiveFlowField = false
 
MBool m_receiveVelocitySlopes = false
 
MInt m_noSendParticles = 0
 
MPI_Status m_mpi_statusInt {}
 
MPI_Status m_mpi_statusFloat {}
 
MBool m_openParticleInjSend = false
 
MBool m_openParticleSend = false
 
MBool m_openSourceSend = false
 
MBool m_openFlowSend = false
 
MBool m_openRegridSend = false
 
MBool m_openSlopesSend = false
 
MBool m_couplingRedist = false
 
MInt m_noRedistLayer = 1
 
MBool m_momentumCoupling = false
 
MBool m_heatCoupling = false
 
MBool m_massCoupling = false
 
MBool m_evaporation = false
 
MFloat m_sumEvapMass = 0
 
MFloat m_particleResiduum = 0.0
 
- Protected Attributes inherited from maia::CartesianSolver< nDim, LPT< nDim > >
MIntm_rfnBandWidth
 
MInt m_noSensors
 
MInt m_adaptationInterval
 
MInt m_adaptationStep
 
std::vector< MIntm_maxSensorRefinementLevel
 
std::vector< MFloatm_sensorWeight
 
std::vector< MFloatm_sensorDerivativeVariables
 
MBool m_adaptation
 
MBool m_adapts
 
MInt m_noInitialSensors
 
MBool m_resTriggeredAdapt
 
MInt m_noSmoothingLayers
 
MInt m_sensorBandAdditionalLayers
 
MBool m_sensorInterface
 
MBool m_sensorParticle
 
std::vector< MStringm_sensorType
 
MIntm_recalcIds
 
std::vector< funm_sensorFnPtr
 
MInt m_maxNoSets
 
std::vector< MFloatm_azimuthalCartRecCoord
 
const MInt m_revDir [6]
 
const MInt m_noDirs
 
- Protected Attributes inherited from Solver
MFloat m_Re {}
 the Reynolds number More...
 
MFloat m_Ma {}
 the Mach number More...
 
MInt m_solutionInterval
 The number of timesteps before writing the next solution file. More...
 
MInt m_solutionOffset {}
 
std::set< MIntm_solutionTimeSteps
 
MInt m_restartInterval
 The number of timesteps before writing the next restart file. More...
 
MInt m_restartTimeStep
 
MInt m_restartOffset
 
MString m_solutionOutput
 
MBool m_useNonSpecifiedRestartFile = false
 
MBool m_initFromRestartFile
 
MInt m_residualInterval
 The number of timesteps before writing the next residual. More...
 
const MInt m_solverId
 a unique solver identifier More...
 
MFloatm_outerBandWidth = nullptr
 
MFloatm_innerBandWidth = nullptr
 
MIntm_bandWidth = nullptr
 
MBool m_restart = false
 
MBool m_restartFile = false
 

Private Member Functions

void readModelProps ()
 Read model configuration properties from configuration file. More...
 
void readSpawnProps ()
 Read properties related to creating particles from configuration file. More...
 
void readEllipsoidProps ()
 Read properties specific to ellipsoids. More...
 
void readMomentumCouplingProps ()
 Read properties specific to the momentum coupling. More...
 
void findSpawnCellId ()
 Find spawn cellId. More...
 
MBool fiveStageSolutionStep ()
 Splitting the solutionStep into 5 separate parts to match the 5-stage Runge-Kutta time-stepping for inter-leafed computation! More...
 
MBool oneStageSolutionStep ()
 single solution step for pure LPT computation or without interleafed coupling! More...
 
void initMPI (const MBool=true)
 Init MPI buffers and communication datastructures. More...
 
void initialCondition ()
 Initialize particles. More...
 
void initSummary ()
 Print information at the start of simulation. More...
 
void initCollector ()
 init LPT cell collector More...
 
void initBndryCells ()
 init LPT boundary-cells used for the wall-collision More...
 
void initParticleVector ()
 init LPT spherical and ellipsoids particle vectors (i.e. set length and read non-dimensionalisation Parameters!) More...
 
void initGridProperties ()
 calculate Grid Properties for periodic boundaries, adapted from rigedbodies More...
 
void initParticleLog ()
 
void writeParticleLog ()
 
void computeBoundingBox (MFloat *globalBbox)
 
void addBndryCell (const MInt, MFloat *, MFloat *, MFloatScratchSpace &, MFloat *)
 add an LPT bndryCell to the collector and fill the data More...
 
void packParticles (std::vector< LPTSpherical< nDim > * > &particlesToSend, MInt *intBuffer, MFloat *floatBuffer, std::vector< MInt >)
 Pack particles for sending. More...
 
void packParticles (std::vector< LPTEllipsoidal< nDim > * > &particlesToSend, MInt *intBuffer, MFloat *floatBuffer, std::vector< MInt >)
 Pack ellipsoids to be sent. More...
 
template<class LPTParticle , MBool t_search>
void unpackParticles (const MInt num, const MInt *intBuffer, const MFloat *floatBuffer, const MInt domainId=-1, const MBool allowNonLeaf=false)
 Unpack particles. More...
 
void unpackParticle (LPTSpherical< nDim > &thisParticle, const MInt *intBuffer, MInt &z, const MFloat *floatBuffer, MInt &h, MInt &step, MInt id)
 Unpack spherical particle from buffers. More...
 
void unpackParticle (LPTEllipsoidal< nDim > &thisParticle, const MInt *intBuffer, MInt &z, const MFloat *floatBuffer, MInt &h, MInt &step, MInt id)
 Unpack ellipsoidal particle and fill buffers. More...
 
void broadcastInjected (const MUint prevNumPart)
 Send newly created particles. More...
 
void recvInjected ()
 receive particles generated during injection More...
 
void sendInjected (const MUint prevNumPart)
 
void updateExchangeCells ()
 Set exchange properties in LPT cell collector (a_isHalo/a_isWindow) and set m_pointsToHalo and m_pointsToWindow lists. More...
 
void motionEquation (const MInt offset)
 
void motionEquationEllipsoids (const MInt offset)
 
void evaporation (const MInt offset)
 
void coupling (MInt offset)
 
void advanceParticles (const MInt offset)
 
void perCellStats ()
 set cell-particle mapping which is used to merge particle in reduceParticles! More...
 
void countParticlesInCells ()
 set accessor for a_noParticlesInCell which is used for the particle-sensor during adaptation More...
 
void reduceParticles ()
 
void mergeParticles (LPTSpherical< nDim > *partA, LPTSpherical< nDim > *partB)
 
void spawnTimeStep ()
 spawn new particles and compute their timeStep NOTE: this is an older functionality which is only used in testcases... More...
 
void sprayInjection ()
 
void removeInvalidParticles (const MBool)
 
void wallCollision ()
 collision step with LPT wall More...
 
void particleWallCollisionStep (const MInt)
 
void writeCollData ()
 
void setRegridTrigger ()
 set a_regridTriggerG around all particles to allow for an adaptation check More...
 
void checkRegridTrigger ()
 check if any of the cells with the regrid Trigger also have particles inside More...
 
void recvRegridTrigger ()
 
void initializeTimers ()
 Initializes the communication timers. More...
 

Private Attributes

MInt m_skewnessTimeStep = -1
 
MBool m_periodicBC = false
 
MBool m_engineSetup = false
 
std::array< MFloat, nDim > m_globDomainLength {}
 
std::array< MFloat, nDim *2 > m_globBbox {0}
 
MFloat m_sizeLimit {}
 
MLong m_spawnSeed {}
 
MBool m_activePrimaryBUp {}
 
MBool m_activeSecondaryBUp {}
 
MInt m_maxNoParticles {}
 
MFloat m_xCutOff = -1000.0
 
MBool m_restart = false
 
MBool m_ellipsoids = false
 
MInt m_ellipsoidRandomOrientation = 1
 
MLong m_ellipsoidRandomOrientationSeed {}
 
MInt m_initializationMethod = 0
 
MFloat m_FrMag = 0.0
 
MInt m_dragModelType = 1
 
MInt m_liftModelType = 0
 
MInt m_torqueModelType = 0
 
MInt m_motionEquationType = 0
 
MBool m_respawn = false
 
MFloat m_respawnPlane {}
 
MInt m_respawnDomain {}
 
MInt m_noRespawnDomains {}
 
MIntm_respawnDomainRanks {}
 
MIntm_respawnGlobalDomainOffsets {}
 
std::vector< MIntm_respawnCells
 
MBool m_wallCollisions = true
 
MInt m_maxNoBndryCells = 0
 
MInt m_collisions = 0
 
MInt m_noOuterBndryCells = 0
 
MInt m_exchangeBufferSize = 1000
 
MFloat m_cfl = 1.0
 
std::unique_ptr< SprayModel< nDim > > m_sprayModel
 
MBool m_spawnParticles = false
 
MInt m_spawnCellId = -1
 
MInt m_spawnDomainId = -1
 
MFloat m_spawnParticlesConeAngle = 0.0
 
MFloat m_spawnDir [nDim] {}
 
MFloat m_spawnDiameter = 0.00001
 
MInt m_spawnParticlesCount = 1
 
MFloat m_spawnCoord [nDim] {}
 
MFloat m_spawnVelocity = 0.0
 
MInt m_spawnEmittDist = string2enum("PART_EMITT_DIST_UNIFORM")
 
MFloat m_spawnDistSigmaCoeff = 1.0
 
MInt m_sprayAngleModel = 0
 
std::unique_ptr< MaterialState< nDim > > m_material
 
MLong m_addedParticle = 0
 
std::multimap< MInt, LPTSpherical< nDim > * > m_cellToPartMap
 
std::multimap< MInt, LPTEllipsoidal< nDim > * > m_cellToEllipsMap
 
MInt m_adaptationLevel = 0
 
MInt m_loadBalancingReinitStage = -1
 
MInt m_shadowWidth {}
 
MInt m_innerBound = 2
 
MBool m_forceAdaptation = false
 

Static Private Attributes

static constexpr MInt m_addInjDataCnt = 4
 

Friends

template<MInt nDim_>
class LPTBase
 
template<MInt nDim_>
class LPTSpherical
 
template<MInt nDim_>
class LPTEllipsoidal
 
template<MInt nDim_>
class SprayModel
 
template<MInt nDim_>
class CouplingParticle
 
template<MInt nDim_, class SysEqn >
class CouplerFvParticle
 
template<MInt nDim_, MInt nDist, class SysEqn >
class LbLpt
 
template<MInt nDim_, class SysEqn >
class PostProcessingFvLPT
 
template<MInt nDim_>
class PostProcessingLbLPT
 
template<MInt nDim_>
class PostProcessingLPT
 
template<MInt nDim_>
class ParticleCollision
 
template<MInt nDim_>
class MaterialState
 

Detailed Description

template<MInt nDim>
class LPT< nDim >

Definition at line 82 of file lpt.h.

Member Typedef Documentation

◆ CartesianSolver

template<MInt nDim>
using LPT< nDim >::CartesianSolver = typename maia::CartesianSolver<nDim, LPT>

Definition at line 120 of file lpt.h.

◆ Cell

template<MInt nDim>
using LPT< nDim >::Cell = typename maia::grid::tree::Tree<nDim>::Cell

Definition at line 121 of file lpt.h.

◆ Geom

template<MInt nDim>
using LPT< nDim >::Geom = Geometry<nDim>

Definition at line 123 of file lpt.h.

◆ Grid

template<MInt nDim>
using LPT< nDim >::Grid = typename CartesianSolver::Grid

Definition at line 124 of file lpt.h.

◆ GridProxy

template<MInt nDim>
using LPT< nDim >::GridProxy = typename CartesianSolver::GridProxy

Definition at line 125 of file lpt.h.

◆ LptCellCollector

template<MInt nDim>
using LPT< nDim >::LptCellCollector = maia::lpt::collector::LptCells<nDim>

Definition at line 126 of file lpt.h.

◆ Timers

template<MInt nDim>
using LPT< nDim >::Timers = maia::lpt::Timers_
protected

Definition at line 533 of file lpt.h.

Constructor & Destructor Documentation

◆ LPT() [1/2]

template<MInt nDim>
LPT< nDim >::LPT ( const MInt  solverId,
GridProxy gridProxy_,
Geom geometry_,
const MPI_Comm  comm 
)

◆ ~LPT()

template<MInt nDim>
virtual LPT< nDim >::~LPT ( )
inlinevirtual

Definition at line 188 of file lpt.h.

188 {
189 };

◆ LPT() [2/2]

template<MInt nDim>
LPT< nDim >::LPT ( const LPT< nDim > &  )
delete

Member Function Documentation

◆ a_bndryCellId() [1/2]

template<MInt nDim>
MInt & LPT< nDim >::a_bndryCellId ( const MInt  cellId)
inline

Definition at line 391 of file lpt.h.

391{ return m_cells.bndryCellId(cellId); }
LptCellCollector m_cells
Definition: lpt.h:175
MInt bndryCellId(const MInt id) const

◆ a_bndryCellId() [2/2]

template<MInt nDim>
MInt LPT< nDim >::a_bndryCellId ( const MInt  cellId) const
inline

Definition at line 392 of file lpt.h.

392{ return m_cells.bndryCellId(cellId); }

◆ a_coordinate()

template<MInt nDim>
const MFloat & LPT< nDim >::a_coordinate ( const MInt  cellId,
const MInt  dim 
) const
inline

Definition at line 455 of file lpt.h.

455 {
456 if(a_isBndryCell(cellId)) {
457 return m_bndryCells->a[a_bndryCellId(cellId)].m_coordinates[dim];
458 }
459 return grid().tree().coordinate(cellId, dim);
460 }
MBool a_isBndryCell(const MInt cellId) const override
Definition: lpt.h:453
Collector< LPTBndryCell< nDim > > * m_bndryCells
Definition: lpt.h:180
MInt & a_bndryCellId(const MInt cellId)
Definition: lpt.h:391
constexpr GridProxy & grid() const

◆ a_fluidDensity() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_fluidDensity ( const MInt  cellId)
inline

Definition at line 400 of file lpt.h.

400{ return m_cells.fluidVariable(cellId, PV.RHO); }
PrimitiveVariables PV
Definition: lpt.h:178
MFloat fluidVariable(const MInt id, const MInt var) const
static constexpr MInt RHO
Definition: lpt.h:1022

◆ a_fluidDensity() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_fluidDensity ( const MInt  cellId) const
inline

Definition at line 401 of file lpt.h.

401{ return m_cells.fluidVariable(cellId, PV.RHO); }

◆ a_fluidPressure() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_fluidPressure ( const MInt  cellId)
inline

Definition at line 403 of file lpt.h.

403{ return m_cells.fluidVariable(cellId, PV.P); }
static constexpr MInt P
Definition: lpt.h:1023

◆ a_fluidPressure() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_fluidPressure ( const MInt  cellId) const
inline

Definition at line 404 of file lpt.h.

404{ return m_cells.fluidVariable(cellId, PV.P); }

◆ a_fluidSpecies() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_fluidSpecies ( const MInt  cellId)
inline

Definition at line 409 of file lpt.h.

409{ return m_cells.fluidSpecies(cellId); }
MFloat fluidSpecies(const MInt id) const

◆ a_fluidSpecies() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_fluidSpecies ( const MInt  cellId) const
inline

Definition at line 410 of file lpt.h.

410{ return m_cells.fluidSpecies(cellId); }

◆ a_fluidTemperature() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_fluidTemperature ( const MInt  cellId)
inline

Definition at line 406 of file lpt.h.

406{ return m_cells.fluidVariable(cellId, PV.T); }
static constexpr MInt T
Definition: lpt.h:1024

◆ a_fluidTemperature() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_fluidTemperature ( const MInt  cellId) const
inline

Definition at line 407 of file lpt.h.

407{ return m_cells.fluidVariable(cellId, PV.T); }

◆ a_fluidVariable() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_fluidVariable ( const MInt  cellId,
const MInt  var 
)
inline

Definition at line 394 of file lpt.h.

394{ return m_cells.fluidVariable(cellId, var); }

◆ a_fluidVariable() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_fluidVariable ( const MInt  cellId,
const MInt  var 
) const
inline

Definition at line 395 of file lpt.h.

395{ return m_cells.fluidVariable(cellId, var); }

◆ a_fluidVelocity() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_fluidVelocity ( const MInt  cellId,
const MInt  dim 
)
inline

Definition at line 397 of file lpt.h.

397{ return m_cells.fluidVariable(cellId, PV.VV[dim]); }
static constexpr std::array< MInt, 3 > VV
Definition: lpt.h:1021

◆ a_fluidVelocity() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_fluidVelocity ( const MInt  cellId,
const MInt  dim 
) const
inline

Definition at line 398 of file lpt.h.

398{ return m_cells.fluidVariable(cellId, PV.VV[dim]); }

◆ a_hasNeighbor()

template<MInt nDim>
MInt LPT< nDim >::a_hasNeighbor ( const MInt  cellId,
const MInt  dir 
) const
inline

Definition at line 321 of file lpt.h.

321{ return grid().tree().hasNeighbor(cellId, dir); }

◆ a_heatFlux() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_heatFlux ( const MInt  cellId)
inline

Definition at line 412 of file lpt.h.

412{ return m_cells.heatFlux(cellId); }
MFloat & heatFlux(const MInt id)
Accessor for heatFlux.

◆ a_heatFlux() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_heatFlux ( const MInt  cellId) const
inline

Definition at line 413 of file lpt.h.

413{ return m_cells.heatFlux(cellId); }

◆ a_isBndryCell()

template<MInt nDim>
MBool LPT< nDim >::a_isBndryCell ( const MInt  cellId) const
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 453 of file lpt.h.

453{ return a_bndryCellId(cellId) > -1; }

◆ a_isHalo() [1/2]

template<MInt nDim>
maia::lpt::cell::BitsetType::reference LPT< nDim >::a_isHalo ( const MInt  cellId)
inline

Definition at line 434 of file lpt.h.

434 {
435 return m_cells.hasProperty(cellId, LptCell::IsHalo);
436 }
BitsetType::reference hasProperty(const MInt id, const LptCell p)
Accessor for properties.

◆ a_isHalo() [2/2]

template<MInt nDim>
MBool LPT< nDim >::a_isHalo ( const MInt  cellId) const
inline

Definition at line 433 of file lpt.h.

433{ return m_cells.hasProperty(cellId, LptCell::IsHalo); }

◆ a_isValidCell() [1/2]

template<MInt nDim>
maia::lpt::cell::BitsetType::reference LPT< nDim >::a_isValidCell ( const MInt  cellId)
inline

Definition at line 444 of file lpt.h.

444 {
445 return m_cells.hasProperty(cellId, LptCell::IsValid);
446 }

◆ a_isValidCell() [2/2]

template<MInt nDim>
MBool LPT< nDim >::a_isValidCell ( const MInt  cellId) const
inline

Definition at line 443 of file lpt.h.

443{ return m_cells.hasProperty(cellId, LptCell::IsValid); }

◆ a_isWindow() [1/2]

template<MInt nDim>
maia::lpt::cell::BitsetType::reference LPT< nDim >::a_isWindow ( const MInt  cellId)
inline

Definition at line 439 of file lpt.h.

439 {
440 return m_cells.hasProperty(cellId, LptCell::IsWindow);
441 }

◆ a_isWindow() [2/2]

template<MInt nDim>
MBool LPT< nDim >::a_isWindow ( const MInt  cellId) const
inline

Definition at line 438 of file lpt.h.

438{ return m_cells.hasProperty(cellId, LptCell::IsWindow); }

◆ a_level()

template<MInt nDim>
MInt LPT< nDim >::a_level ( const MInt  cellId) const
inline

Definition at line 968 of file lpt.h.

968{ return c_level(cellId); }
MInt c_level(const MInt cellId) const
Definition: lpt.h:966

◆ a_massFlux() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_massFlux ( const MInt  cellId)
inline

Definition at line 415 of file lpt.h.

415{ return m_cells.massFlux(cellId); }
MFloat & massFlux(const MInt id)
Accessor for massFlux.

◆ a_massFlux() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_massFlux ( const MInt  cellId) const
inline

Definition at line 416 of file lpt.h.

416{ return m_cells.massFlux(cellId); }

◆ a_momentumFlux() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_momentumFlux ( const MInt  cellId,
const MInt  dim 
)
inline

Definition at line 418 of file lpt.h.

418{ return m_cells.momentumFlux(cellId, dim); }
MFloat & momentumFlux(const MInt id, const MInt dim)
Accessor for momentumFlux.

◆ a_momentumFlux() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_momentumFlux ( const MInt  cellId,
const MInt  dim 
) const
inline

Definition at line 419 of file lpt.h.

419{ return m_cells.momentumFlux(cellId, dim); }

◆ a_noCells()

template<MInt nDim>
MInt LPT< nDim >::a_noCells ( ) const
inline

Definition at line 373 of file lpt.h.

373{ return m_cells.size(); }
constexpr MInt size() const
Return size (i.e., currently used number of nodes)
Definition: container.h:89

◆ a_noEllipsoidalParticles()

template<MInt nDim>
MInt LPT< nDim >::a_noEllipsoidalParticles ( ) const
inline

Definition at line 372 of file lpt.h.

372{ return m_partListEllipsoid.size(); }
std::vector< LPTEllipsoidal< nDim > > m_partListEllipsoid
Definition: lpt.h:528

◆ a_noEllipsoidsInCell() [1/2]

template<MInt nDim>
MInt & LPT< nDim >::a_noEllipsoidsInCell ( const MInt  cellId)
inline

Definition at line 388 of file lpt.h.

388{ return m_cells.noEllipsoids(cellId); }
MInt noEllipsoids(const MInt id) const

◆ a_noEllipsoidsInCell() [2/2]

template<MInt nDim>
MInt LPT< nDim >::a_noEllipsoidsInCell ( const MInt  cellId) const
inline

Definition at line 389 of file lpt.h.

389{ return m_cells.noEllipsoids(cellId); }

◆ a_noParticles()

template<MInt nDim>
template<class LPTParticle = LPTSpherical<nDim>>
MInt LPT< nDim >::a_noParticles ( )
inline

Definition at line 366 of file lpt.h.

366 {
367 IF_CONSTEXPR(std::is_same_v<LPTParticle, LPTSpherical<nDim>>) { return m_partList.size(); }
368 IF_CONSTEXPR(std::is_same_v<LPTParticle, LPTEllipsoidal<nDim>>) { return m_partListEllipsoid.size(); }
369 mTerm(-1, AT_, "Unknown particle type");
370 }
std::vector< LPTSpherical< nDim > > m_partList
Definition: lpt.h:527
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29

◆ a_noParticlesInCell() [1/2]

template<MInt nDim>
MInt & LPT< nDim >::a_noParticlesInCell ( const MInt  cellId)
inline

Definition at line 385 of file lpt.h.

385{ return m_cells.noParticles(cellId); }
MInt noParticles(const MInt id) const

◆ a_noParticlesInCell() [2/2]

template<MInt nDim>
MInt LPT< nDim >::a_noParticlesInCell ( const MInt  cellId) const
inline

Definition at line 386 of file lpt.h.

386{ return m_cells.noParticles(cellId); }

◆ a_noSphericalParticles()

template<MInt nDim>
MInt LPT< nDim >::a_noSphericalParticles ( ) const
inline

Definition at line 371 of file lpt.h.

371{ return m_partList.size(); }

◆ a_particleList()

template<MInt nDim>
template<class LPTParticle >
std::vector< LPTParticle > & LPT< nDim >::a_particleList ( )
inline

Definition at line 376 of file lpt.h.

376 {
377 IF_CONSTEXPR(std::is_same_v<LPTParticle, LPTSpherical<nDim>>) { return m_partList; }
378 IF_CONSTEXPR(std::is_same_v<LPTParticle, LPTEllipsoidal<nDim>>) { return m_partListEllipsoid; }
379 mTerm(-1, AT_, "Unknown particle type");
380 }

◆ a_regridTrigger() [1/2]

template<MInt nDim>
maia::lpt::cell::BitsetType::reference LPT< nDim >::a_regridTrigger ( const MInt  cellId)
inline

Definition at line 449 of file lpt.h.

449 {
450 return m_cells.hasProperty(cellId, LptCell::RegridTrigger);
451 }

◆ a_regridTrigger() [2/2]

template<MInt nDim>
MBool LPT< nDim >::a_regridTrigger ( const MInt  cellId) const
inline

Definition at line 448 of file lpt.h.

448{ return m_cells.hasProperty(cellId, LptCell::RegridTrigger); }

◆ a_resetPropertiesSolver()

template<MInt nDim>
void LPT< nDim >::a_resetPropertiesSolver ( const MInt  cellId)
inline

Definition at line 431 of file lpt.h.

431{ m_cells.resetProperties(cellId); }
void resetProperties(const MInt id)
Reset all properties.

◆ a_timeStepComputationInterval()

template<MInt nDim>
MInt LPT< nDim >::a_timeStepComputationInterval ( )
inline

Definition at line 319 of file lpt.h.

MInt m_timeStepComputationInterval
Definition: lpt.h:575

◆ a_validCell()

template<MInt nDim>
MBool LPT< nDim >::a_validCell ( const MInt  cellId)
inline

Definition at line 987 of file lpt.h.

987 {
988 if(cellId < 0 || cellId > a_noCells()) {
989 return false;
990 }
991 return true;
992 }
MInt a_noCells() const
Definition: lpt.h:373

◆ a_velocitySlope() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_velocitySlope ( const MInt  cellId,
const MInt  varId,
const MInt  dir 
)
inline

Definition at line 424 of file lpt.h.

424 {
425 return m_cells.velocitySlope(cellId, varId, dir);
426 }
MFloat & velocitySlope(const MInt id, const MInt varId, const MInt dim)

◆ a_velocitySlope() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_velocitySlope ( const MInt  cellId,
const MInt  varId,
const MInt  dir 
) const
inline

Definition at line 427 of file lpt.h.

427 {
428 return m_cells.velocitySlope(cellId, varId, dir);
429 }

◆ a_volumeFraction() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_volumeFraction ( const MInt  cellId)
inline

Definition at line 382 of file lpt.h.

382{ return m_cells.volumeFraction(cellId); }
MFloat volumeFraction(const MInt id) const

◆ a_volumeFraction() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_volumeFraction ( const MInt  cellId) const
inline

Definition at line 383 of file lpt.h.

383{ return m_cells.volumeFraction(cellId); }

◆ a_workFlux() [1/2]

template<MInt nDim>
MFloat & LPT< nDim >::a_workFlux ( const MInt  cellId)
inline

Definition at line 421 of file lpt.h.

421{ return m_cells.workFlux(cellId); }
MFloat & workFlux(const MInt id)
Accessor for workFlux.

◆ a_workFlux() [2/2]

template<MInt nDim>
MFloat LPT< nDim >::a_workFlux ( const MInt  cellId) const
inline

Definition at line 422 of file lpt.h.

422{ return m_cells.workFlux(cellId); }

◆ addBndryCell()

template<MInt nDim>
void LPT< nDim >::addBndryCell ( const MInt  cellId,
MFloat bndryData,
MFloat surfaceN,
MFloatScratchSpace surfaceC,
MFloat surfaceV 
)
private
Author
Tim Wegmann
Date
November 2020

Definition at line 6391 of file lpt.cpp.

6392 {
6393 TRACE();
6394
6395 ASSERT(a_bndryCellId(cellId) < 0, "ERROR, cell already has a bndryCell!");
6396
6397 // currently the LPT-bndryCell consist of the following data-structure:
6398 //- matching cellId
6399 //- coordinate of the cut-Cell
6400 // (note, that in the FV-solver, the coordinate is only the shift from the un-cut center!)
6401 //- volume of the cut-Cell
6402 //- a single bndry-Surface with the following data:
6403 // - surface normal
6404 // - surface velocity (only unqual zero for moving bndries!)
6405 // - surface centroid coordinate
6406 // - coordinate of 3 points on the cell-edges of the surface
6407
6408 const MInt bndryCellId = m_bndryCells->size();
6410 a_bndryCellId(cellId) = bndryCellId;
6411
6412 m_bndryCells->a[bndryCellId].m_cellId = cellId;
6413 m_bndryCells->a[bndryCellId].m_volume = bndryData[0];
6414 for(MInt n = 0; n < nDim; n++) {
6415 m_bndryCells->a[bndryCellId].m_coordinates[n] = c_coordinate(cellId, n) + bndryData[1 + n];
6416 }
6417 const MInt noSurf = 1;
6418 m_bndryCells->a[bndryCellId].m_noSrfcs = noSurf;
6419 for(MInt s = 0; s < noSurf; s++) {
6420 for(MInt n = 0; n < nDim; n++) {
6421 m_bndryCells->a[bndryCellId].m_srfcs[s]->m_normal[n] = surfaceN[noSurf * s + n];
6422 m_bndryCells->a[bndryCellId].m_srfcs[s]->m_velocity[n] = surfaceV[noSurf * s + n];
6423 m_bndryCells->a[bndryCellId].m_srfcs[s]->m_coordinates[n] = surfaceC(noSurf * s + n, 0);
6424 for(MInt i = 0; i < nDim; i++) {
6425 m_bndryCells->a[bndryCellId].m_srfcs[s]->m_planeCoordinates[i][n] = surfaceC(noSurf * s + n, i + 1);
6426 }
6427 }
6428 }
6429}
void append()
Definition: collector.h:153
MInt size()
Definition: collector.h:29
MFloat c_coordinate(const MInt cellId, const MInt dir) const
Definition: lpt.h:972
int32_t MInt
Definition: maiatypes.h:62
void const MInt cellId
Definition: collector.h:239

◆ addEllipsoid()

template<MInt nDim>
MInt LPT< nDim >::addEllipsoid ( const MInt  cellId,
const MFloat  semiMinorAxis,
const MFloat  aspectRatio,
const MFloat  particleDensityRatio,
const MInt  random = 1,
const MInt  addMode = 0,
const MFloat velocity = nullptr,
const MFloat position = nullptr 
)
protected
Author
Laurent Andre
Date
September 2022
Parameters
cellId
semiMinorAxis
aspectRatio
particleDensityRatio
random
Returns

Definition at line 5607 of file lpt.cpp.

5609 {
5610 LPTEllipsoidal<nDim> thisParticle;
5611 const MFloat epsilon = MFloatEps;
5612 const MFloat cellLength = 0.5 * c_cellLengthAtCell(cellId) - epsilon;
5613
5614 thisParticle.m_cellId = cellId;
5615 thisParticle.m_oldCellId = cellId;
5616 thisParticle.m_temperature = m_material->T();
5617 thisParticle.m_semiMinorAxis = semiMinorAxis;
5618 thisParticle.m_aspectRatio = aspectRatio;
5619 thisParticle.initEllipsoialProperties();
5620
5621 if(addMode == 0) {
5622 for(MInt j = 0; j < nDim; j++) {
5623 // add particle around the cell-coordinate
5624 // include a small offset w.r.t.(with respect to) the cell coordinates, so that the
5625 // interpolation stencil is unambiguously defined later on
5626 thisParticle.m_position[j] = thisParticle.m_oldPos[j] =
5627 c_coordinate(cellId, j) + epsilon - random * (-cellLength + 2 * cellLength * rand() / (RAND_MAX + 1.0));
5628 thisParticle.m_velocity[j] = thisParticle.m_oldVel[j] = a_fluidVelocity(cellId, j);
5629 thisParticle.m_angularVel[j] = F0;
5630 thisParticle.m_accel[j] = F0;
5631 thisParticle.m_angularAccel[j] = F0;
5632 }
5633 } else if(addMode == 1 || addMode == 2) {
5634 // for spray-injection the position and velocity of new particles is specified
5635 for(MInt j = 0; j < nDim; j++) {
5636 thisParticle.m_position[j] = position[j];
5637 thisParticle.m_oldPos[j] = c_coordinate(cellId, j);
5638 thisParticle.m_velocity[j] = velocity[j];
5639 thisParticle.m_oldVel[j] = velocity[j];
5640 thisParticle.m_angularVel[j] = F0;
5641 thisParticle.m_accel[j] = F0;
5642 thisParticle.m_angularAccel[j] = F0;
5643 }
5644 } else if(addMode == 3) {
5645 for(MInt j = 0; j < nDim; j++) {
5646 thisParticle.m_position[j] = position[j] + MFloatEps;
5647 thisParticle.m_oldPos[j] = c_coordinate(cellId, j);
5648 thisParticle.m_velocity[j] = velocity[j];
5649 thisParticle.m_oldVel[j] = velocity[j];
5650 thisParticle.m_angularVel[j] = F0;
5651 thisParticle.m_accel[j] = F0;
5652 thisParticle.m_angularAccel[j] = F0;
5653 }
5654 } else {
5655 mTerm(1, AT_, "Unknown particle add-Mode!");
5656 }
5657
5659 mt19937_64 randomOrientationGen(m_ellipsoidRandomOrientationSeed);
5660 uniform_real_distribution<MFloat> dist(F0, F1);
5661 MFloat alpha = dist(randomOrientationGen);
5662 MFloat beta = dist(randomOrientationGen);
5663 MFloat gamma = dist(randomOrientationGen);
5664 thisParticle.m_quaternion[0] = sqrt(1 - alpha) * sin(2 * PI * beta);
5665 thisParticle.m_quaternion[1] = sqrt(1 - alpha) * cos(2 * PI * beta);
5666 thisParticle.m_quaternion[2] = sqrt(alpha) * sin(2 * PI * gamma);
5667 thisParticle.m_quaternion[3] = sqrt(alpha) * cos(2 * PI * gamma);
5668 MFloat normFactor = F0;
5669 for(MFloat k : thisParticle.m_quaternion) {
5670 normFactor += k * k;
5671 }
5672 normFactor = sqrt(normFactor);
5673 for(MInt i = 0; i < 4; i++) {
5674 thisParticle.m_quaternion[i] /= normFactor;
5675 thisParticle.m_oldQuaternion[i] = thisParticle.m_quaternion[i];
5676 }
5677 }
5678
5679 thisParticle.m_oldFluidDensity = a_fluidDensity(thisParticle.m_cellId);
5680 for(MInt i = 0; i < nDim; i++) {
5681 thisParticle.m_oldFluidVel[i] = a_fluidVelocity(thisParticle.m_cellId, i);
5682 }
5683 thisParticle.m_densityRatio = particleDensityRatio;
5684
5685 thisParticle.updateProperties();
5686 thisParticle.firstStep() = true;
5687
5688 // update the cellId and compute createTime!
5689 MFloat time = 0;
5690 if(addMode == 1) {
5691 thisParticle.checkCellChange(m_spawnCoord);
5692 } else if(addMode == 2) {
5693 ASSERT(m_activePrimaryBUp, "");
5694 thisParticle.checkCellChange(m_spawnCoord, !m_sprayModel->m_broadcastInjected);
5695 uniform_real_distribution<MFloat> randMov(0, m_timeStep); // - MFloatEps);
5696 time = randMov(m_sprayModel->randomPrimBreakUp(1));
5697 if(time > m_timeStep) {
5698 time = m_timeStep;
5699 }
5700 } else if(addMode == 3) {
5701 ASSERT(m_activeSecondaryBUp, "");
5702
5703 thisParticle.m_fluidDensity = a_fluidDensity(thisParticle.m_cellId);
5704 for(MInt i = 0; i < nDim; i++) {
5705 thisParticle.m_fluidVel[i] = a_fluidVelocity(thisParticle.m_cellId, i);
5706 }
5707 }
5708
5709 thisParticle.m_creationTime = time;
5710
5711 if(thisParticle.m_creationTime < 0 || thisParticle.m_creationTime > m_timeStep) {
5712 mTerm(1, AT_, "Invalid creation Time");
5713 }
5714
5715#ifdef _OPENMP
5716#pragma omp critical
5717#endif
5718 {
5719 // create a unique particle id
5720 thisParticle.m_partId = static_cast<MLong>(domainId() * 1E9 + m_addedParticle);
5722 m_partListEllipsoid.push_back(thisParticle);
5723 }
5724
5725 return a_noParticles() + a_noEllipsoidalParticles() - 1;
5726}
MFloat m_creationTime
creation time modifier
Definition: lptbase.h:50
std::array< MFloat, nDim > m_position
Definition: lptbase.h:34
MLong m_partId
Definition: lptbase.h:45
std::array< MFloat, nDim > m_velocity
Definition: lptbase.h:35
BitsetType::reference firstStep()
Definition: lptbase.h:179
std::array< MFloat, nDim > m_oldPos
particle position of the last time step
Definition: lptbase.h:39
void updateProperties(const MBool init=true)
Update particle properties.
Definition: lptbase.cpp:299
MInt m_oldCellId
Definition: lptbase.h:47
std::array< MFloat, nDim > m_oldVel
particle velocity of the last time step
Definition: lptbase.h:41
MFloat m_densityRatio
Definition: lptbase.h:44
MInt m_cellId
Definition: lptbase.h:46
void checkCellChange(const MFloat *oldPosition, const MBool allowHaloNonLeaf=false)
Checks whether position is within cell with number cellId if not, cellId is updated.
Definition: lptbase.cpp:233
std::array< MFloat, nDim > m_accel
Definition: lptbase.h:36
std::array< MFloat, 4 > m_oldQuaternion
MFloat m_oldFluidDensity
old fluid density
std::array< MFloat, nDim > m_fluidVel
fluid velocity
std::array< MFloat, nDim > m_angularAccel
particle angular acceleration
MFloat m_temperature
temperature
std::array< MFloat, nDim > m_oldFluidVel
fluid velocity of the last time step
MFloat m_aspectRatio
aspect ratio a/c of ellipsoidal: 0 < oblate < 1, =1 spherical, >1 prolate
std::array< MFloat, nDim > m_angularVel
particle angular velocity
std::array< MFloat, 4 > m_quaternion
void initEllipsoialProperties()
MFloat m_fluidDensity
fluid density
MFloat m_semiMinorAxis
semi minor axis a
MLong m_addedParticle
Definition: lpt.h:817
MInt domainId() const override
Return the domainId (rank)
Definition: lpt.h:980
MFloat & a_fluidDensity(const MInt cellId)
Definition: lpt.h:400
MBool m_activeSecondaryBUp
Definition: lpt.h:761
MFloat m_spawnCoord[nDim]
Definition: lpt.h:809
std::unique_ptr< MaterialState< nDim > > m_material
Definition: lpt.h:815
MFloat & a_fluidVelocity(const MInt cellId, const MInt dim)
Definition: lpt.h:397
MInt a_noParticles()
Definition: lpt.h:366
MFloat m_timeStep
Definition: lpt.h:573
MFloat c_cellLengthAtCell(const MInt cellId) const
Definition: lpt.h:964
MFloat time() const override
Return the time.
Definition: lpt.h:940
std::unique_ptr< SprayModel< nDim > > m_sprayModel
Definition: lpt.h:798
MLong m_ellipsoidRandomOrientationSeed
Definition: lpt.h:771
MInt a_noEllipsoidalParticles() const
Definition: lpt.h:372
MInt m_ellipsoidRandomOrientation
Definition: lpt.h:770
MBool m_activePrimaryBUp
Definition: lpt.h:760
double MFloat
Definition: maiatypes.h:52
int64_t MLong
Definition: maiatypes.h:64
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54

◆ addParticle()

template<MInt nDim>
MInt LPT< nDim >::addParticle ( const MInt  cellId,
const MFloat  diameter,
const MFloat  particleDensityRatio,
const MInt  random = 1,
const MInt  addMode = 0,
const MFloat velocity = nullptr,
const MFloat position = nullptr,
const MInt  parcelSize = 1 
)
protected
Author
Sven Berger
Date
June 2015
Parameters
[in]cellIdCellId of the cell in which the particle is to be created.
[in]diameterDiameter of the added particle.
[in]particleDensityRatioThe density ratio of the added particle.
[in]randomAdd random displacement to particle position.
[in]addMode0: as initial-condition 1: as particle spawn 2: as spray primaryBreakUp 3: as spray secondaryBreakUp

Definition at line 5495 of file lpt.cpp.

5497 {
5498 LPTSpherical<nDim> thisParticle;
5499 const MFloat epsilon = MFloatEps;
5500 const MFloat cellLength = 0.5 * c_cellLengthAtCell(cellId) - epsilon;
5501
5502 thisParticle.m_cellId = cellId;
5503 thisParticle.m_oldCellId = cellId;
5504 thisParticle.m_diameter = diameter;
5505 thisParticle.m_shedDiam = diameter;
5506 thisParticle.m_temperature = m_material->T();
5507 thisParticle.m_noParticles = parcelSize;
5508 thisParticle.m_dM = 0;
5509
5510 if(addMode == 0) {
5511 for(MInt j = 0; j < nDim; j++) {
5512 // add particle around the cell-coordinate
5513 // include a small offset w.r.t.(with respect to) the cell coordinates, so that the
5514 // interpolation stencil is unambiguously defined later on
5515 thisParticle.m_position[j] = thisParticle.m_oldPos[j] =
5516 c_coordinate(cellId, j) + epsilon - random * (-cellLength + 2 * cellLength * rand() / (RAND_MAX + 1.0));
5517 thisParticle.m_velocity[j] = thisParticle.m_oldVel[j] = a_fluidVelocity(cellId, j);
5518
5519 thisParticle.m_accel[j] = 0.0;
5520 }
5521 } else if(addMode == 1 || addMode == 2) {
5522 // for spray-injection the position and velocity of new particles is specified
5523 for(MInt j = 0; j < nDim; j++) {
5524 thisParticle.m_position[j] = position[j];
5525 thisParticle.m_oldPos[j] = c_coordinate(cellId, j);
5526 thisParticle.m_velocity[j] = velocity[j];
5527 thisParticle.m_oldVel[j] = velocity[j];
5528 thisParticle.m_accel[j] = 0.0;
5529 }
5530 } else if(addMode == 3) {
5531 for(MInt j = 0; j < nDim; j++) {
5532 thisParticle.m_position[j] = position[j] + MFloatEps;
5533 thisParticle.m_oldPos[j] = c_coordinate(cellId, j);
5534 thisParticle.m_velocity[j] = velocity[j];
5535 thisParticle.m_oldVel[j] = velocity[j];
5536 thisParticle.m_accel[j] = 0.0;
5537 }
5538 } else {
5539 mTerm(1, AT_, "Unknown particle add-Mode!");
5540 }
5541
5542 thisParticle.m_oldFluidDensity = a_fluidDensity(thisParticle.m_cellId);
5543 for(MInt i = 0; i < nDim; i++) {
5544 thisParticle.m_oldFluidVel[i] = a_fluidVelocity(thisParticle.m_cellId, i);
5545 }
5546 thisParticle.m_densityRatio = particleDensityRatio;
5547
5548 thisParticle.updateProperties();
5549 thisParticle.firstStep() = true;
5550
5551 // update the cellId and compute createTime!
5552 MFloat time = 0;
5553 if(addMode == 1) {
5554 thisParticle.checkCellChange(m_spawnCoord);
5555 } else if(addMode == 2) {
5556 ASSERT(m_activePrimaryBUp, "");
5557 thisParticle.checkCellChange(m_spawnCoord, !m_sprayModel->m_broadcastInjected);
5558 uniform_real_distribution<MFloat> randMov(0, m_timeStep); // - MFloatEps);
5559 time = randMov(m_sprayModel->randomPrimBreakUp(1));
5560 if(time > m_timeStep) {
5561 time = m_timeStep;
5562 }
5563 } else if(addMode == 3) {
5564 ASSERT(m_activeSecondaryBUp, "");
5565
5566 thisParticle.m_fluidDensity = a_fluidDensity(thisParticle.m_cellId);
5567 for(MInt i = 0; i < nDim; i++) {
5568 thisParticle.m_fluidVel[i] = a_fluidVelocity(thisParticle.m_cellId, i);
5569 }
5570 }
5571
5572
5573 thisParticle.m_creationTime = time;
5574 thisParticle.m_breakUpTime = -time;
5575
5576 if(thisParticle.m_creationTime < 0 || thisParticle.m_creationTime > m_timeStep) {
5577 mTerm(1, AT_, "Invalid creation Time");
5578 }
5579
5580#ifdef _OPENMP
5581#pragma omp critical
5582#endif
5583 {
5584 // create a unique particle id
5585 thisParticle.m_partId = static_cast<MLong>(domainId() * 1E9 + m_addedParticle);
5587 m_partList.push_back(thisParticle);
5588 }
5589
5590 return a_noParticles() - 1;
5591}
MFloat m_shedDiam
shedding diameter
Definition: lptspherical.h:82
std::array< MFloat, nDim > m_oldFluidVel
fluid velocity of the last time step
Definition: lptspherical.h:70
MFloat m_temperature
temperature
Definition: lptspherical.h:78
MFloat m_oldFluidDensity
old fluid density
Definition: lptspherical.h:73
MFloat m_dM
mass evaporation rate
Definition: lptspherical.h:86
MInt m_noParticles
parceled particles
Definition: lptspherical.h:84
MFloat m_diameter
particle diameter
Definition: lptspherical.h:76
MFloat m_breakUpTime
time since last breakUp
Definition: lptspherical.h:80
MFloat m_fluidDensity
fluid density
Definition: lptspherical.h:65
std::array< MFloat, nDim > m_fluidVel
fluid velocity
Definition: lptspherical.h:63

◆ advanceParticles()

template<MInt nDim>
void LPT< nDim >::advanceParticles ( const MInt  offset)
private

Definition at line 3041 of file lpt.cpp.

3041 {
3042 ASSERT(grid().checkNghbrIds(), "");
3043#ifdef _OPENMP
3044#pragma omp parallel default(none) shared(offset)
3045#endif
3046 {
3047#ifdef _OPENMP
3048#pragma omp for nowait
3049#endif
3050 for(MInt i = offset; i < a_noParticles(); i++) {
3051 if(!m_partList[i].isInvalid()) {
3052 m_partList[i].advanceParticle();
3053 }
3054 }
3055#ifdef _OPENMP
3056#pragma omp for nowait
3057#endif
3058 for(MInt i = offset; i < a_noEllipsoidalParticles(); i++) {
3059 if(!m_partListEllipsoid[i].isInvalid()) {
3060 m_partListEllipsoid[i].advanceParticle();
3061 }
3062 }
3063 }
3064}

◆ balancePost()

template<MInt nDim>
void LPT< nDim >::balancePost
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 6920 of file lpt.cpp.

6920 {
6921 TRACE();
6922
6924
6925 ASSERT(m_cells.size() == c_noCells() && c_noCells() == a_noCells(), "");
6926}
MInt c_noCells() const
Definition: lpt.h:954
MInt m_loadBalancingReinitStage
Definition: lpt.h:825

◆ balancePre()

template<MInt nDim>
void LPT< nDim >::balancePre
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 6867 of file lpt.cpp.

6867 {
6868 // Set reinitialization stage
6870
6871 // Update the grid proxy for this solver
6872 grid().update();
6873
6874 if(!grid().isActive()) {
6875 // Reset parallelization information if solver is not active
6876 updateDomainInfo(-1, -1, MPI_COMM_NULL, AT_);
6877 } else {
6878 // Set new domain info for solver
6880 }
6881
6882 // Reset cell, boundary cell data and deallocate halo/window cell arrays
6884
6885 // check for empry cell and particle collector
6886 ASSERT(m_cells.size() == 0, "");
6887 ASSERT(a_noParticles() == 0, "");
6888 ASSERT(a_noEllipsoidalParticles() == 0, "");
6889
6890 // Return if solver is not active
6891 if(!grid().isActive()) {
6894 return;
6895 }
6896
6897 initCollector();
6898
6899 // Check that global ids are sorted
6900 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
6901 if(grid().domainOffset(domainId()) + (MLong)cellId != c_globalId(cellId)) {
6902 TERMM(1, "Global id mismatch.");
6903 }
6904 }
6905
6907 grid().updateLeafCellExchange();
6908 initMPI();
6909
6910
6911 // this can only be done, after the halo property has been set above
6912 this->checkNoHaloLayers();
6913}
MLong c_globalId(const MInt cellId) const
Definition: lpt.h:976
void initCollector()
init LPT cell collector
Definition: lpt.cpp:153
void resetSolverFull()
reset the solver during balancing
Definition: lpt.cpp:6822
void initMPI(const MBool=true)
Init MPI buffers and communication datastructures.
Definition: lpt.cpp:374
MInt noDomains() const override
Definition: lpt.h:981
void updateExchangeCells()
Set exchange properties in LPT cell collector (a_isHalo/a_isWindow) and set m_pointsToHalo and m_poin...
Definition: lpt.cpp:6339
MPI_Comm mpiComm() const
Return the MPI communicator used by this solver.
Definition: solver.h:380
void updateDomainInfo(const MInt domainId, const MInt noDomains, const MPI_Comm mpiComm, const MString &loc)
Set new domain information.
Definition: solver.h:135
void checkNoHaloLayers()
check that each solver has the required number of haloLayers for leaf cells!!! TODO labels:toenhance ...
void reset()
Reset tree, re-create data structures with given capacity, and set size to zero.
void const MInt const MInt const MInt const MInt maxNoCells
Definition: collector.h:240

◆ broadcastInjected()

template<MInt nDim>
void LPT< nDim >::broadcastInjected ( const MUint  prevNumPart)
private
Author
Sven Berger
Date
October 2018
Parameters
[in]prevNumPartPrevious number of particles.

Definition at line 6221 of file lpt.cpp.

6221 {
6222 TRACE();
6223
6224 if(noDomains() > 1) {
6225 vector<LPTSpherical<nDim>*> particlesToSend;
6226 vector<MInt> cellIds;
6227 vector<LPTSpherical<nDim>>& partList = a_particleList<LPTSpherical<nDim>>();
6228 // collect particles which are marked as inactive
6229 for(MInt i = prevNumPart; i < a_noParticles(); i++) {
6230 if(partList[i].toBeDeleted() || partList[i].toBeRespawn()) {
6231 particlesToSend.push_back(&partList[i]);
6232 cellIds.push_back(-1);
6233#ifdef LPT_DEBUG
6234 cerr << domainId() << ": " << partList[i].m_partId << " is to be send to all domains during injection." << endl;
6235 << endl;
6236#endif
6237 }
6238 }
6239
6240 MInt numPartSend = static_cast<MInt>(particlesToSend.size());
6241
6242 // send number of particles
6243 MPI_Bcast(&numPartSend, 1, MPI_INT, m_spawnDomainId, mpiComm(), AT_, "intSendBuffer");
6244
6245#ifdef LPT_DEBUG
6246 cerr << domainId() << ": "
6247 << " is sending " << numPartSend << " particles" << endl;
6248#endif
6249
6251 > max(numPartSend * intElemPerP<LPTSpherical<nDim>>(), numPartSend * elemPerP<LPTSpherical<nDim>>()),
6252 "ERROR: Exchange buffer to small");
6253
6254 if(numPartSend > 0) {
6255 // pack particles
6256 packParticles(particlesToSend, m_intSendBuffer[0].get(), m_sendBuffer[0].get(), cellIds);
6257
6258 // send particles
6260 m_spawnDomainId, mpiComm(), AT_, "intSendBuffer");
6261
6263 m_spawnDomainId, mpiComm(), AT_, "intSendBuffer");
6264 }
6265
6266 for(auto part : particlesToSend) {
6267 part->wasSend() = true;
6268 part->reqSend() = false;
6269 part->isInvalid() = true;
6270 }
6271
6272
6273#ifndef NDEBUG
6274 MInt particlesReceived = 0;
6275 MPI_Allreduce(MPI_IN_PLACE, &particlesReceived, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE",
6276 "particlesReceived");
6277 if(particlesReceived != numPartSend) {
6278 cerr << "total particles received: " << particlesReceived << endl;
6279 TERMM(-1, "ERROR: Inconsistent number of particles");
6280 }
6281#endif
6282 }
6283}
MInt intElemPerP()
Definition: lpt.h:675
std::vector< std::unique_ptr< MFloat[]> > m_sendBuffer
Definition: lpt.h:610
MInt m_spawnDomainId
Definition: lpt.h:804
MInt m_exchangeBufferSize
Definition: lpt.h:794
void packParticles(std::vector< LPTSpherical< nDim > * > &particlesToSend, MInt *intBuffer, MFloat *floatBuffer, std::vector< MInt >)
Pack particles for sending.
Definition: lpt.cpp:5850
std::vector< std::unique_ptr< MInt[]> > m_intSendBuffer
Definition: lpt.h:612
MInt elemPerP()
Definition: lpt.h:671
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
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

◆ bufSize()

template<MInt nDim>
template<class LPTParticle >
MInt LPT< nDim >::bufSize ( )
inlineprotected

Definition at line 679 of file lpt.h.

679 {
680 return m_exchangeBufferSize * elemPerP<LPTParticle>() + 1;
681 }

◆ c_cellLengthAtCell()

template<MInt nDim>
MFloat LPT< nDim >::c_cellLengthAtCell ( const MInt  cellId) const
inline

Definition at line 964 of file lpt.h.

964{ return c_cellLengthAtLevel(c_level(cellId)); }
MFloat c_cellLengthAtLevel(const MInt level) const
Definition: lpt.h:962

◆ c_cellLengthAtLevel()

template<MInt nDim>
MFloat LPT< nDim >::c_cellLengthAtLevel ( const MInt  level) const
inline

Definition at line 962 of file lpt.h.

962{ return grid().cellLengthAtLevel(level); }

◆ c_cellVolume()

template<MInt nDim>
MFloat LPT< nDim >::c_cellVolume ( const MInt  cellId) const
inline

Definition at line 970 of file lpt.h.

970{ return grid().cellVolumeAtLevel(grid().tree().level(cellId)); }

◆ c_childId()

template<MInt nDim>
MInt LPT< nDim >::c_childId ( const MInt  cellId,
const MInt  pos 
) const
inline

Definition at line 956 of file lpt.h.

956{ return grid().tree().child(cellId, pos); }

◆ c_coordinate()

template<MInt nDim>
MFloat LPT< nDim >::c_coordinate ( const MInt  cellId,
const MInt  dir 
) const
inline

Definition at line 972 of file lpt.h.

972{ return grid().tree().coordinate(cellId, dir); }

◆ c_globalId()

template<MInt nDim>
MLong LPT< nDim >::c_globalId ( const MInt  cellId) const
inline

Definition at line 976 of file lpt.h.

976{ return grid().tree().globalId(cellId); }

◆ c_hasNeighbor()

template<MInt nDim>
MInt LPT< nDim >::c_hasNeighbor ( const MInt  cellId,
const MInt  dir 
) const
inline

Definition at line 983 of file lpt.h.

983{ return grid().tree().hasNeighbor(cellId, dir); }

◆ c_isLeafCell()

template<MInt nDim>
MBool LPT< nDim >::c_isLeafCell ( const MInt  cellId) const
inline

Definition at line 974 of file lpt.h.

974{ return grid().tree().isLeafCell(cellId); }

◆ c_level()

template<MInt nDim>
MInt LPT< nDim >::c_level ( const MInt  cellId) const
inline

Definition at line 966 of file lpt.h.

966{ return grid().tree().level(cellId); }

◆ c_neighborId()

template<MInt nDim>
MInt LPT< nDim >::c_neighborId ( const MInt  cellId,
const MInt  dir 
) const
inline

Definition at line 985 of file lpt.h.

985{ return grid().tree().neighbor(cellId, dir); }

◆ c_noCells()

template<MInt nDim>
MInt LPT< nDim >::c_noCells ( ) const
inline

Definition at line 954 of file lpt.h.

954{ return grid().tree().size(); }

◆ c_noChildren()

template<MInt nDim>
MInt LPT< nDim >::c_noChildren ( const MInt  cellId) const
inline

Definition at line 958 of file lpt.h.

958{ return grid().tree().noChildren(cellId); }

◆ c_parentId()

template<MInt nDim>
MInt LPT< nDim >::c_parentId ( const MInt  cellId) const
inline

Definition at line 960 of file lpt.h.

960{ return grid().tree().parent(cellId); }

◆ calculateAverageRep()

template<MInt nDim>
MFloat LPT< nDim >::calculateAverageRep ( )
protected

◆ calculateHeatRelease()

template<MInt nDim>
void LPT< nDim >::calculateHeatRelease ( )
inline

Definition at line 1006 of file lpt.h.

1006{ std::cerr << "calculateHeatRelease DgCartesianSolver " << std::endl; }

◆ calculateTerminalVelocities()

template<MInt nDim>
void LPT< nDim >::calculateTerminalVelocities ( )
protected

version: Dez-2013

Author
Christoph Siewert

◆ calculateTotalKineticEnergy()

template<MInt nDim>
MFloat LPT< nDim >::calculateTotalKineticEnergy ( )
protected

◆ calculateVRMS()

template<MInt nDim>
MFloat LPT< nDim >::calculateVRMS ( )
protected

◆ cancelMpiRequests()

template<MInt nDim>
void LPT< nDim >::cancelMpiRequests
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 6855 of file lpt.cpp.

6855 {
6856 if(isActive()) {
6858 }
6859}
void countParticlesInCells()
set accessor for a_noParticlesInCell which is used for the particle-sensor during adaptation
Definition: lpt.cpp:2741

◆ cellDataSizeDlb()

template<MInt nDim>
MInt LPT< nDim >::cellDataSizeDlb ( const MInt  dataId,
const MInt  gridCellId 
)
override
Author
Tim Wegmann

Definition at line 6933 of file lpt.cpp.

6933 {
6934 // Inactive ranks do not have any data to communicate
6935 if(!isActive()) {
6936 return 0;
6937 }
6938
6939 // Convert to solver cell id and check
6940 const MInt cellId = grid().tree().grid2solver(gridCellId);
6941 if(cellId < 0 || cellId >= noInternalCells()) {
6942 return 0;
6943 }
6944
6945 // only noParticlesInCell and particle information is balanced
6946 if(dataId == 0) return 2; // 2 because we spherical and elllipsoidal particles
6947
6948 if(a_noParticlesInCell(cellId) == 0 && a_noEllipsoidsInCell(cellId) == 0) return 0;
6949
6950 MInt dataSize = 0;
6951
6952 switch(dataId) {
6953 case 1:
6954 dataSize = (elemPerP<LPTSpherical<nDim>>() + 3) * a_noParticlesInCell(cellId)
6955 + (elemPerP<LPTEllipsoidal<nDim>>() + 2) * a_noEllipsoidsInCell(cellId);
6956 break;
6957 case 2: // spheres particleId(2) and noParcels, ellipsoids only particleId(2)
6958 dataSize = 3 * a_noParticlesInCell(cellId) + 2 * a_noEllipsoidsInCell(cellId);
6959 break;
6960 default:
6961 TERMM(1, "Unknown data id.");
6962 break;
6963 }
6964
6965 return dataSize;
6966}
MInt & a_noParticlesInCell(const MInt cellId)
Definition: lpt.h:385
MInt & a_noEllipsoidsInCell(const MInt cellId)
Definition: lpt.h:388
MInt noInternalCells() const override
Return the number of internal cells within this solver.
Definition: lpt.h:979

◆ cellDataTypeDlb()

template<MInt nDim>
MInt LPT< nDim >::cellDataTypeDlb ( const MInt  dataId) const
inlineoverride

Definition at line 290 of file lpt.h.

290 {
291 if(dataId == 1) {
292 return MFLOAT;
293 } else if(dataId == 0 || dataId == 2) {
294 return MINT;
295 } else {
296 TERMM(1, "solverCelldataType: invalid data id");
297 }
298 };
@ MINT
Definition: enums.h:269
@ MFLOAT
Definition: enums.h:269

◆ cellOutside()

template<MInt nDim>
MInt LPT< nDim >::cellOutside ( const MFloat coords,
const MInt  level,
const MInt  gridCellId 
)
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1740 of file lpt.cpp.

1740 {
1741 // currently all cells with the refineFlag are keep during adaptation!
1742 return -1;
1743
1744 std::ignore = gridCellId;
1745 std::ignore = coords[0];
1746 std::ignore = level;
1747
1748 /*
1749 static constexpr MInt cornerIndices[8][3] = {{-1, -1, -1}, {1, -1, -1}, {-1, 1, -1}, {1, 1, -1},
1750 {-1, -1, 1}, {1, -1, 1}, {-1, 1, 1}, {1, 1, 1}};
1751 static constexpr const MInt noCorners = (nDim == 2) ? 4 : 8;
1752
1753 MFloat corner[3] = {0, 0, 0};
1754 MBool outside = true;
1755 MFloat cellHalfLength = F1B2 * c_cellLengthAtLevel(level);
1756
1757
1758 for(MInt i = 0; i < noCorners; i++) {
1759 for(MInt dim = 0; dim < nDim; dim++) {
1760 corner[dim] = coords[dim] + cornerIndices[i][dim] * cellHalfLength;
1761 }
1762 IF_CONSTEXPR(nDim == 2) {
1763 if(!m_geometry->pointIsInside(corner)) outside = false;
1764 // pointIsInside == true if Point is outside fluid domain
1765 } else {
1766 if(!m_geometry->pointIsInside2(corner)) outside = false;
1767 // pointIsInside == true if Point is outside fluid domain
1768 }
1769 }
1770
1771 return outside;
1772 */
1773}

◆ checkCells()

template<MInt nDim>
void LPT< nDim >::checkCells
protected
Author
Tim Wegmann
Date
Aug 2021

Definition at line 6631 of file lpt.cpp.

6631 {
6632 TRACE();
6633
6634// check that particle starts on a valid location
6635#ifdef LPT_DEBUG
6636 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6637 if(!c_isLeafCell(cellId)) continue;
6638 if(a_fluidDensity(cellId) < MFloatEps) {
6639 mTerm(1, AT_, "Invalid density in cell!");
6640 }
6641
6642 if(isnan(a_massFlux(cellId))) {
6643 mTerm(1, AT_, "Invalid mass-flux in cell!");
6644 }
6645 }
6646
6647#endif
6648}
MFloat & a_massFlux(const MInt cellId)
Definition: lpt.h:415
MBool c_isLeafCell(const MInt cellId) const
Definition: lpt.h:974

◆ checkParticles()

template<MInt nDim>
void LPT< nDim >::checkParticles
protected
Author
Tim Wegmann
Date
Aug 2021

Definition at line 6441 of file lpt.cpp.

6441 {
6442 TRACE();
6443
6444 if(globalTimeStep < 0) return;
6445
6446 // check that particle starts on a valid location
6447#if defined LPT_DEBUG || !defined NDEBUG
6448
6449 // calculate weights of the redistribution
6450 static const MInt noOfRedistLayers = m_couplingRedist ? ((m_noRedistLayer > 0) ? m_noRedistLayer : 2) : 0;
6451
6452 if(!((noOfRedistLayers == 0 && !m_couplingRedist) || m_couplingRedist)) {
6453 mTerm(1, AT_, "Invalid configuration noOfRedistLayers > 0, but coupling redistribution is not active!");
6454 }
6455
6456 for(MInt part = 0; part < a_noParticles(); part++) {
6457 if(m_partList[part].isInvalid()) {
6458 if(!m_partList[part].fullyEvaporated()) continue;
6459 if(m_partList[part].m_noParticles < 1) {
6460 cerr << "Fully evap. has neg. parcel count! " << m_partList[part].m_noParticles << " " << m_partList[part].m_dM
6461 << endl;
6462 }
6463 if(m_partList[part].m_dM > 0.000001) {
6464 cerr << "Fully evap. has large mass-transfer " << m_partList[part].m_dM << " " << m_partList[part].m_partId
6465 << endl;
6466 }
6467 continue;
6468 }
6469 const MInt cellId = m_partList[part].m_cellId;
6470 if(cellId < 0 || cellId > noInternalCells()) {
6471 cerr << "Invalid cellId " << cellId << " " << m_partList[part].hasCollided() << " " << a_isHalo(cellId) << " "
6472 << c_isLeafCell(cellId) << " " << m_partList[part].isWindow() << " " << m_partList[part].reqSend() << " "
6473 << m_partList[part].wasSend() << " " << m_partList[part].hadWallColl() << " " << part << " "
6474 << m_partList[part].m_partId << endl;
6475 mTerm(1, AT_, "Invalid cellId!");
6476 }
6477 if(m_partList[part].isInvalid()) {
6478 mTerm(1, AT_, "Invalid particle at TS beginning!");
6479 }
6480 if(a_isHalo(cellId) || !c_isLeafCell(cellId) || c_noChildren(cellId) > 0) {
6481 mTerm(1, AT_, "Particle in halo or non-leaf cell!");
6482 }
6483 // check particle coordinate:
6484 const MFloat halfCellLength = c_cellLengthAtLevel(c_level(cellId) + 1);
6485 std::array<MFloat, 3> origCellC = {};
6486 for(MInt i = 0; i < nDim; i++) {
6487 origCellC[i] = c_coordinate(cellId, i);
6488 }
6489 // before particle motion, the particle should be located in the correct cell
6490 if(fabs(origCellC[0] - m_partList[part].m_position[0]) > halfCellLength
6491 || fabs(origCellC[1] - m_partList[part].m_position[1]) > halfCellLength
6492 || fabs(origCellC[2] - m_partList[part].m_position[2]) > halfCellLength) {
6493 cerr << "ERROR: particle " << m_partList[part].m_partId << " is in on incorrect cell "
6494 << sqrt(POW2(origCellC[0] - m_partList[part].m_position[0])
6495 + POW2(origCellC[1] - m_partList[part].m_position[1])
6496 + POW2(origCellC[2] - m_partList[part].m_position[2]))
6497 << " > " << halfCellLength << " and particle location: " << m_partList[part].m_position[0] << " "
6498 << m_partList[part].m_position[1] << " " << m_partList[part].m_position[2] << " "
6499 << m_partList[part].hadWallColl() << " " << a_level(cellId) << " " << origCellC[0] << " " << origCellC[1]
6500 << " " << origCellC[2] << endl;
6501 // mTerm(1, AT_, "Invalid cell for particle position!" );
6502 m_partList[part].isInvalid() = true;
6503 continue;
6504 }
6505
6506 if(m_partList[part].m_diameter < m_sizeLimit || isnan(m_partList[part].m_diameter)) {
6507 cerr << "Invalid particle diameter : " << m_partList[part].m_diameter << " " << m_sizeLimit << " "
6508 << m_partList[part].firstStep() << " " << m_partList[part].hadWallColl() << " "
6509 << m_partList[part].m_breakUpTime << " " << m_partList[part].m_partId << endl;
6510 // mTerm(1, AT_, "Invalid particle diameter!");
6511 }
6512
6513 if(m_partList[part].m_noParticles < 0) {
6514 cerr << m_partList[part].m_noParticles << endl;
6515 mTerm(1, AT_, "Invalid parcel count!");
6516 }
6517
6518 if(m_partList[part].m_oldCellId < 0 && !m_periodicBC) {
6519 mTerm(1, AT_, "Invalid old CellId!");
6520 }
6521
6522 if(m_partList[part].m_oldFluidDensity < MFloatEps) {
6523 cerr << a_fluidDensity(cellId) << " " << a_isHalo(cellId) << " " << a_level(cellId) << " " << part << " "
6524 << a_noParticles() << " " << m_partList[part].m_oldFluidDensity << endl;
6525 mTerm(1, AT_, "Invalid old fluid density!");
6526 }
6527
6528 for(MInt i = 0; i < nDim; i++) {
6529 if(isnan(m_partList[part].m_oldFluidVel[i])) {
6530 mTerm(1, AT_, "Invalid old fluid velocity!");
6531 }
6532 }
6533
6534 if(m_partList[part].m_temperature < 0) {
6535 mTerm(1, AT_, "Invalid particle temperature!");
6536 }
6537
6538 if(m_partList[part].m_shedDiam < 0) {
6539 cerr << "Negative shed-diameter " << m_partList[part].m_partId << endl;
6540 }
6541 if(m_partList[part].m_noParticles < 1) {
6542 cerr << "Negative parcel-count " << m_partList[part].m_partId << endl;
6543 }
6544 if(m_partList[part].m_dM > 0.000001) {
6545 cerr << "Large mass-transfer " << m_partList[part].m_dM << " " << m_partList[part].m_partId << endl;
6546 }
6547 }
6548
6549 // ellipsoids
6550 for(MInt part = 0; part < a_noEllipsoidalParticles(); part++) {
6551 const MInt cellId = m_partListEllipsoid[part].m_cellId;
6552
6553 if(cellId < 0 || cellId > noInternalCells()) {
6554 cerr << "Invalid cellId " << cellId << " " << m_partListEllipsoid[part].hasCollided() << " " << a_isHalo(cellId)
6555 << " " << c_isLeafCell(cellId) << " " << m_partListEllipsoid[part].isWindow() << " "
6556 << m_partListEllipsoid[part].reqSend() << " " << m_partListEllipsoid[part].wasSend() << " "
6557 << m_partListEllipsoid[part].hadWallColl() << " " << part << " " << m_partListEllipsoid[part].m_partId
6558 << endl;
6559 mTerm(1, AT_, "Invalid cellId!");
6560 }
6561 if(m_partListEllipsoid[part].isInvalid()) {
6562 mTerm(1, AT_, "Invalid ellipsoid at TS beginning!");
6563 }
6564
6565
6566 if(a_isHalo(cellId) || !c_isLeafCell(cellId) || c_noChildren(cellId) > 0) {
6567 mTerm(1, AT_, "Ellipsoid in halo or non-leaf cell!");
6568 }
6569
6570 // check particle coordinate:
6571 const MFloat halfCellLength = c_cellLengthAtLevel(c_level(cellId) + 1);
6572
6573 std::array<MFloat, 3> origCellC = {};
6574 for(MInt i = 0; i < nDim; i++) {
6575 origCellC[i] = c_coordinate(cellId, i);
6576 }
6577
6578 // before particle motion, the particle should be located in the correct cell
6579 if(fabs(origCellC[0] - m_partListEllipsoid[part].m_position[0]) > halfCellLength
6580 || fabs(origCellC[1] - m_partListEllipsoid[part].m_position[1]) > halfCellLength
6581 || fabs(origCellC[2] - m_partListEllipsoid[part].m_position[2]) > halfCellLength) {
6582 cerr << "ERROR: ellipsoid " << m_partListEllipsoid[part].m_partId << " is in on incorrect cell "
6583 << sqrt(POW2(origCellC[0] - m_partListEllipsoid[part].m_position[0])
6584 + POW2(origCellC[1] - m_partListEllipsoid[part].m_position[1])
6585 + POW2(origCellC[2] - m_partListEllipsoid[part].m_position[2]))
6586 << " > " << halfCellLength << " and ellipsoid location: " << m_partListEllipsoid[part].m_position[0] << " "
6587 << m_partListEllipsoid[part].m_position[1] << " " << m_partListEllipsoid[part].m_position[2] << " "
6588 << m_partListEllipsoid[part].hadWallColl() << " " << a_level(cellId) << " " << origCellC[0] << " "
6589 << origCellC[1] << " " << origCellC[2] << endl;
6590 // mTerm(1, AT_, "Invalid cell for particle position!" );
6591 m_partListEllipsoid[part].isInvalid() = true;
6592 continue;
6593 }
6594
6595 if(m_partListEllipsoid[part].equivalentDiameter() < m_sizeLimit
6596 || isnan(m_partListEllipsoid[part].equivalentDiameter())) {
6597 cerr << "Invalid ellipsoid diameter : " << m_partListEllipsoid[part].equivalentDiameter() << " " << m_sizeLimit
6598 << " " << m_partListEllipsoid[part].firstStep() << " " << m_partListEllipsoid[part].hadWallColl() << " "
6599 << m_partListEllipsoid[part].m_partId << endl;
6600 // mTerm(1, AT_, "Invalid particle diameter!");
6601 }
6602
6603 if(m_partListEllipsoid[part].m_oldCellId < 0 && !m_periodicBC) {
6604 mTerm(1, AT_, "Invalid old CellId!");
6605 }
6606
6607 if(m_partListEllipsoid[part].m_oldFluidDensity < 0) {
6608 cerr << a_fluidDensity(cellId) << " " << a_isHalo(cellId) << " " << a_level(cellId) << "" << part << " "
6609 << a_noEllipsoidalParticles() << endl;
6610 mTerm(1, AT_, "Invalid old fluid density!");
6611 }
6612
6613 for(MInt i = 0; i < nDim; i++) {
6614 if(isnan(m_partListEllipsoid[part].m_oldFluidVel[i])) {
6615 mTerm(1, AT_, "Invalid old fluid velocity!");
6616 }
6617 }
6618
6619 if(m_partListEllipsoid[part].m_temperature < 0) {
6620 mTerm(1, AT_, "Invalid particle temperature!");
6621 }
6622 }
6623#endif
6624}
MInt c_noChildren(const MInt cellId) const
Definition: lpt.h:958
MInt a_level(const MInt cellId) const
Definition: lpt.h:968
MBool m_periodicBC
Definition: lpt.h:753
MBool a_isHalo(const MInt cellId) const
Definition: lpt.h:433
MInt m_noRedistLayer
Definition: lpt.h:633
MFloat m_sizeLimit
Definition: lpt.h:758
MBool m_couplingRedist
Definition: lpt.h:632
constexpr Real POW2(const Real x)
Definition: functions.h:119
MInt globalTimeStep

◆ checkRegridTrigger()

template<MInt nDim>
void LPT< nDim >::checkRegridTrigger
private
Author
Tim Wegmann

Definition at line 7470 of file lpt.cpp.

7470 {
7471 if(!this->m_adaptation || this->m_noSensors < 1) return;
7472
7473 for(MInt id = 0; id < a_noParticles(); id++) {
7474 if(m_partList[id].isInvalid()) continue;
7475 const MInt cellId = m_partList[id].m_cellId;
7476 if(a_isHalo(cellId)) continue;
7477 if(a_regridTrigger(cellId)) {
7478 m_forceAdaptation = true;
7479 break;
7480 }
7481 }
7482 for(MInt id = 0; id < a_noEllipsoidalParticles(); id++) {
7483 if(m_partListEllipsoid[id].isInvalid()) continue;
7484 const MInt cellId = m_partListEllipsoid[id].m_cellId;
7485 if(a_isHalo(cellId)) continue;
7486 if(a_regridTrigger(cellId)) {
7487 m_forceAdaptation = true;
7488 break;
7489 }
7490 }
7491
7492 if(!m_nonBlockingComm) {
7493 // moved exchange for forceAdaptation() call!
7494 MPI_Allreduce(MPI_IN_PLACE, &m_forceAdaptation, 1, MPI_C_BOOL, MPI_LOR, mpiComm(), AT_, "MPI_IN_PLACE", "status");
7495
7496 if(domainId() == 0 && m_forceAdaptation) {
7497 cerr << "LPT-Solver is forcing a mesh-adaptation at time step " << globalTimeStep << endl;
7498 }
7499 } else {
7500 MPI_Iallreduce(MPI_IN_PLACE, &m_forceAdaptation, 1, MPI_C_BOOL, MPI_LOR, mpiComm(),
7501 &m_checkAdaptationRecvRequest[0], AT_, "MPI_IN_PLACE", "status");
7502 m_openRegridSend = true;
7503 }
7504}
MBool m_openRegridSend
Definition: lpt.h:629
MBool m_nonBlockingComm
Definition: lpt.h:614
MPI_Request * m_checkAdaptationRecvRequest
Definition: lpt.h:586
MBool m_forceAdaptation
Definition: lpt.h:829
MBool a_regridTrigger(const MInt cellId) const
Definition: lpt.h:448
MInt id
Definition: maiatypes.h:71
int MPI_Iallreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Iallreduce

◆ cleanUp()

template<MInt nDim>
void LPT< nDim >::cleanUp ( )
inlineoverridevirtual

Implements Solver.

Definition at line 206 of file lpt.h.

206{};

◆ computeBoundingBox()

template<MInt nDim>
void LPT< nDim >::computeBoundingBox ( MFloat globalBbox)
inlineprivate

Definition at line 852 of file lpt.h.

852 {
853 // if has cutoff, find solver specific bouding box, else use bounding box of raw grid
854 if(Context::propertyExists("cutOffCoordinates", m_solverId)
855 || Context::propertyExists("cutOffDirections", m_solverId)) {
856 MFloat bboxLocal[nDim * 2];
857 for(MInt i = 0; i < nDim; i++) {
858 bboxLocal[i] = std::numeric_limits<MFloat>::max();
859 bboxLocal[nDim + i] = std::numeric_limits<MFloat>::lowest();
860 }
861 // Find local max and min values
862 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
863 for(MInt i = 0; i < nDim; i++) {
864 bboxLocal[i] =
865 mMin(bboxLocal[i],
866 grid().tree().coordinate(cellId, i) - F1B2 * grid().cellLengthAtLevel(grid().tree().level(cellId)));
867 bboxLocal[nDim + i] =
868 mMax(bboxLocal[nDim + i],
869 grid().tree().coordinate(cellId, i) + F1B2 * grid().cellLengthAtLevel(grid().tree().level(cellId)));
870 }
871 }
872 for(MInt i = 0; i < 2 * nDim; i++)
873 globalBbox[i] = bboxLocal[i];
874 // reduce over all domains to find the global min and max values
875 MPI_Allreduce(MPI_IN_PLACE, &globalBbox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE",
876 "m_bbox[0]");
877 MPI_Allreduce(MPI_IN_PLACE, &globalBbox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
878 "m_bbox[nDim]");
879 } else {
880 for(MInt i = 0; i < 2 * nDim; i++) {
881 globalBbox[i] = grid().raw().globalBoundingBox()[i];
882 }
883 }
884 }
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
const MInt m_solverId
a unique solver identifier
Definition: solver.h:90
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

◆ computeTimeStep()

template<MInt nDim>
MFloat LPT< nDim >::computeTimeStep
Author
Tim Wegmann

Definition at line 7533 of file lpt.cpp.

7533 {
7534 TRACE();
7535
7536 m_timeStepUpdated = true;
7537
7538 MFloat timeStep = std::numeric_limits<MFloat>::max();
7539
7540 for(MInt id = 0; id < a_noParticles(); id++) {
7541 if(m_partList[id].isInvalid()) continue;
7542 const MFloat dx = c_cellLengthAtCell(m_partList[id].m_cellId) / m_partList[id].s_lengthFactor;
7543 for(MInt d = 0; d < nDim; ++d) {
7544 const MFloat u_d = fabs(m_partList[id].m_velocity[d]);
7545 MFloat dt_dir = 0;
7546 if(abs(m_cfl + 1.0) < MFloatEps && abs(m_Ma + 1.0) > MFloatEps) {
7547 dt_dir = m_Ma / SQRT3 * dx / u_d;
7548 } else if(abs(m_cfl + 1.0) > MFloatEps)
7549 dt_dir = m_cfl * dx / u_d;
7550 timeStep = mMin(timeStep, dt_dir);
7551 }
7552 }
7553
7554 // Ellipsoids
7555 for(MInt id = 0; id < a_noEllipsoidalParticles(); id++) {
7556 if(m_partListEllipsoid[id].isInvalid()) continue;
7557 const MFloat dx = c_cellLengthAtCell(m_partListEllipsoid[id].m_cellId) / m_partListEllipsoid[id].s_lengthFactor;
7558 for(MInt d = 0; d < nDim; ++d) {
7559 const MFloat u_d = fabs(m_partListEllipsoid[id].m_velocity[d]);
7560 MFloat dt_dir = 0;
7561 if(abs(m_cfl + 1.0) < MFloatEps && abs(m_Ma + 1.0) > MFloatEps) {
7562 dt_dir = m_Ma / SQRT3 * dx / u_d;
7563 } else if(abs(m_cfl + 1.0) > MFloatEps)
7564 dt_dir = m_cfl * dx / u_d;
7565 timeStep = mMin(timeStep, dt_dir);
7566 }
7567 }
7568
7569 // consider injection speed
7570 if(m_activePrimaryBUp && m_spawnCellId > -1) {
7571 const MFloat dx = c_cellLengthAtCell(maxRefinementLevel()) / m_partList[0].s_lengthFactor;
7572 const MFloat u_d = fabs(m_sprayModel->injectionSpeed());
7573 MFloat dt_dir = m_cfl * dx / u_d;
7574 timeStep = mMin(timeStep, dt_dir);
7575 }
7576
7577 // consider spawn velocity
7578 if(m_spawnParticles && m_spawnCellId > -1) {
7579 const MFloat dx = c_cellLengthAtCell(m_spawnCellId) / m_partList[0].s_lengthFactor;
7580 const MFloat u_d = fabs(m_spawnVelocity);
7581 MFloat dt_dir = m_cfl * dx / u_d;
7582 timeStep = mMin(timeStep, dt_dir);
7583 }
7584
7585 // read timeStep from property file
7586 // i.e. used to resolve evaporation time-span
7587 MBool useFixed = false;
7588 if(a_noParticles() > 0) useFixed = true;
7589 if(a_noEllipsoidalParticles() > 0) useFixed = true;
7590 if(m_spawnCellId > -1 && m_sprayModel != nullptr && m_sprayModel->soonInjection(m_time + timeStep * 100)) {
7591 // check if injection will occure in the next time-steps
7592 useFixed = true;
7593 }
7594
7595 if(useFixed && Context::propertyExists("fixedTimeStep", solverId())) {
7596 timeStep = Context::getSolverProperty<MFloat>("fixedTimeStep", m_solverId, AT_);
7597 if(domainId() == m_spawnDomainId) {
7598 cerr << "Applying LPT fixed timeStep of " << timeStep << endl;
7599 }
7600 }
7601
7602 MPI_Allreduce(MPI_IN_PLACE, &timeStep, 1, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE", "timeStep");
7603
7604 if(domainId() == 0) {
7605 cerr << "LPT-timestep could be " << timeStep << " is " << m_timeStep << endl;
7606 }
7607
7608 return timeStep;
7609}
MFloat m_spawnVelocity
Definition: lpt.h:810
MBool m_timeStepUpdated
Definition: lpt.h:576
MFloat m_cfl
Definition: lpt.h:796
MFloat timeStep()
Definition: lpt.h:317
MFloat m_time
Definition: lpt.h:555
MInt m_spawnCellId
Definition: lpt.h:803
MBool m_spawnParticles
Definition: lpt.h:802
MInt solverId() const
Return the solverId.
Definition: solver.h:425
MFloat m_Ma
the Mach number
Definition: solver.h:71
bool MBool
Definition: maiatypes.h:58

◆ countParticlesInCells()

template<MInt nDim>
void LPT< nDim >::countParticlesInCells
private
Date
Aug. 2021
Author
Tim Wegmann

Definition at line 2741 of file lpt.cpp.

2741 {
2742 TRACE();
2743
2744 // reset
2745 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
2746 a_noParticlesInCell(cellId) = 0;
2747 a_noEllipsoidsInCell(cellId) = 0;
2748 }
2749
2750 // fast, local count
2751 for(MInt i = 0; i < a_noParticles(); i++) {
2752 const MInt cellId = m_partList[i].m_cellId;
2753 if(m_partList[i].isInvalid()) {
2754 mTerm(1, AT_, "Counting invalid particle!");
2755 }
2756 ASSERT(cellId > -1, "");
2757 ASSERT(!a_isHalo(cellId), "Particle in halo-cell!");
2758 ASSERT(c_isLeafCell(cellId), "Particle in non-leaf cell!");
2759 a_noParticlesInCell(cellId)++;
2760 }
2761 // Ellipsoidal particles
2762 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
2763 const MInt cellId = m_partListEllipsoid[i].m_cellId;
2764 if(m_partListEllipsoid[i].isInvalid()) {
2765 mTerm(1, AT_, "Counting invalid ellipsoid!");
2766 }
2767 ASSERT(cellId > -1, "");
2768 ASSERT(!a_isHalo(cellId), "Ellipsoid in halo-cell!");
2769 if(globalTimeStep > 0) ASSERT(c_isLeafCell(cellId), "Ellipsoid in non-leaf cell!");
2770 a_noEllipsoidsInCell(cellId)++;
2771 }
2772}

◆ coupling()

template<MInt nDim>
void LPT< nDim >::coupling ( MInt  offset)
private

Definition at line 3014 of file lpt.cpp.

3014 {
3015 MBool afterBalance = false;
3016 if(offset > 0) {
3017 RECORD_TIMER_START(m_timers[Timers::SourceTerms]);
3018 } else {
3019 offset = 0;
3020 afterBalance = true;
3021 }
3022
3023 ASSERT(grid().checkNghbrIds(), "");
3024
3025 for(MInt i = offset; i < a_noParticles(); i++) {
3026 if(!m_partList[i].isInvalid() || m_partList[i].fullyEvaporated()) {
3027 m_partList[i].coupling();
3028 }
3029 }
3030 for(MInt i = offset; i < a_noEllipsoidalParticles(); i++) {
3031 if(!m_partListEllipsoid[i].isInvalid()) {
3032 m_partListEllipsoid[i].coupling();
3033 }
3034 }
3035 if(!afterBalance) {
3036 RECORD_TIMER_STOP(m_timers[Timers::SourceTerms]);
3037 }
3038}
std::array< MInt, Timers::_count > m_timers
Definition: lpt.h:538

◆ crankAngleSolutionOutput()

template<MInt nDim>
void LPT< nDim >::crankAngleSolutionOutput
protected
Author
Tim Wegmann

Definition at line 7935 of file lpt.cpp.

7935 {
7936 TRACE();
7937
7938 if(m_sprayModel == nullptr) return;
7939
7940 static const MInt cadStart = m_sprayModel->m_injectionCrankAngle;
7941 static const MInt cadEnd = m_sprayModel->m_injectionCrankAngle + 90;
7942 static const MInt cadInterval = 1;
7943 const MInt cadMaxIter = (cadEnd - cadStart) / cadInterval;
7944
7945 const MFloat cad = maia::math::crankAngle(m_time, m_sprayModel->m_Strouhal, m_sprayModel->m_initialCad, 0);
7946 const MFloat cad_prev =
7947 maia::math::crankAngle(m_time - m_timeStep, m_sprayModel->m_Strouhal, m_sprayModel->m_initialCad, 0);
7948 const MFloat cad_next =
7949 maia::math::crankAngle(m_time + m_timeStep, m_sprayModel->m_Strouhal, m_sprayModel->m_initialCad, 0);
7950
7951 if(cad > cadEnd) return;
7952 if(cad < (cadStart - cadInterval)) return;
7953
7954 // iterate for full solution output
7955 for(MInt i = 0; i < cadMaxIter; i++) {
7956 const MFloat cadTarget = cadStart + i * cadInterval;
7957
7958 if(cad < cadTarget && cad_next > cadTarget) {
7959 if(fabs(cad - cadTarget) <= fabs(cad_next - cadTarget)) {
7960 if(domainId() == 0) {
7961 cerr << "Saving particle output at crankAngle " << cad << endl;
7962 }
7963 writePartData();
7964 break;
7965 }
7966 } else if(cad > cadTarget && cad_prev < cadTarget) {
7967 if(abs(cad - cadTarget) < fabs(cad_prev - cadTarget)) {
7968 if(domainId() == 0) {
7969 cerr << "Saving particle output at crankAngle " << cad << endl;
7970 }
7971 writePartData();
7972 break;
7973 }
7974 }
7975 }
7976}
void writePartData()
write particle snapshot to Netcdf file (using parallel output)
Definition: lpt.cpp:3997
MFloat crankAngle(const MFloat time, const MFloat Strouhal, const MFloat offset, const MInt mode)
help-function for engine calculations which returns the crank-angle for a given time,...
Definition: maiamath.h:506

◆ domainId()

template<MInt nDim>
MInt LPT< nDim >::domainId ( ) const
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 980 of file lpt.h.

980{ return grid().domainId(); }

◆ elemPerP()

template<MInt nDim>
template<class LPTParticle >
MInt LPT< nDim >::elemPerP ( )
inlineprotected

Definition at line 671 of file lpt.h.

671 {
672 return LPTParticle::s_floatElements + LPTBase<nDim>::s_floatElements;
673 }

◆ evaporation()

template<MInt nDim>
void LPT< nDim >::evaporation ( const MInt  offset)
private

Definition at line 2991 of file lpt.cpp.

2991 {
2992 if(!m_heatCoupling && !m_evaporation) return;
2993
2994 RECORD_TIMER_START(m_timers[Timers::Energy]);
2995 ASSERT(grid().checkNghbrIds(), "");
2996
2997#ifdef _OPENMP
2998#pragma omp parallel default(none) shared(offset)
2999#endif
3000 {
3001#ifdef _OPENMP
3002#pragma omp for nowait
3003#endif
3004 for(MInt i = offset; i < a_noParticles(); i++) {
3005 if(!m_partList[i].isInvalid()) {
3006 m_partList[i].energyEquation();
3007 }
3008 }
3009 }
3010 RECORD_TIMER_STOP(m_timers[Timers::Energy]);
3011}
MBool m_heatCoupling
Definition: lpt.h:636
MBool m_evaporation
Definition: lpt.h:638

◆ exchangeOffset()

template<MInt nDim>
void LPT< nDim >::exchangeOffset ( MInt  noParticles)
protected
Author
Sven Berger
Date
July 2015
Parameters
[in]noParticlesNumber of particles created in this domain.

Definition at line 3963 of file lpt.cpp.

3963 {
3964 if(noDomains() > 1) {
3965 MIntScratchSpace offsets(noDomains() + 1, AT_, "offsets");
3966 MPI_Allgather(&noParticles, 1, MPI_INT, &offsets[0], 1, MPI_INT, mpiComm(), AT_, "noParticles", "offsets");
3967
3968 // determine the particle offset for this solver
3969 const MInt totalOffset = accumulate(&offsets[0], &offsets[domainId()], 0);
3970
3971 // determine the maximal partId
3972 MLong maxPartId = accumulate(&offsets[0], &offsets[noDomains()], 0);
3973
3974 // output maxPartId
3975 if(domainId() == 0) {
3976 m_log << "Domain 0 has " << noParticles << " particles initialized, out of globally " << maxPartId << " particles"
3977 << endl;
3978 }
3979
3980 // now the particles can be consistently numbered throughout the
3981 // entire domain
3982 for(auto& part : m_partList) {
3983 part.m_partId += totalOffset;
3984 }
3985 for(auto& ellip : m_partListEllipsoid) {
3986 ellip.m_partId += totalOffset;
3987 }
3988 }
3989}
This class is a ScratchSpace.
Definition: scratch.h:758
InfoOutFile m_log
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

◆ exchangeParticles()

template<MInt nDim>
void LPT< nDim >::exchangeParticles ( const MBool  collOnly,
const MInt  offset,
const MBool  allowNonLeaf = false 
)
protected
Author
Laurent Andre

Definition at line 3463 of file lpt.cpp.

3463 {
3464 if(m_ellipsoids) {
3465 exchangeParticles_<LPTEllipsoidal<nDim>>(collOnly, offset, allowNonLeaf);
3466 } else {
3467 exchangeParticles_<LPTSpherical<nDim>>(collOnly, offset, allowNonLeaf);
3468 }
3469}
MBool m_ellipsoids
Definition: lpt.h:769

◆ exchangeParticles_()

template<MInt nDim>
template<class LPTParticle >
void LPT< nDim >::exchangeParticles_ ( const MBool  collOnly,
const MInt  offset,
const MBool  allowNonLeaf = false 
)
protected
Author
Rudie Kunnen, Sven Berger, Tim Wegmann, Johannes Grafen

Definition at line 3478 of file lpt.cpp.

3478 {
3479 TRACE();
3480
3481 if(noDomains() == 1) return;
3482
3483 MBool foundCell = false;
3484 RECORD_TIMER_START(m_timers[Timers::Exchange]);
3485
3486 vector<LPTParticle>& partList = a_particleList<LPTParticle>();
3487 MInt noParticles = a_noParticles<LPTParticle>();
3488
3489 // check for transfer
3490 for(MInt id = offset; id < noParticles; id++) {
3491 auto& part = partList[id];
3492 if((collOnly && !part.hasCollided()) || // if coll only skip all non collided particles
3493 (part.wasSend())) { // exclude ghost particles
3494 continue;
3495 }
3496
3497 foundCell = true;
3498 if(!collOnly && m_collisions > 0 && part.isWindow()) {
3499 // particle must be copied to the halo cell(s) of neighboring solver(s)
3500 // this is only necessary when collisions are activated otherwise this just leads to
3501 // overhead...
3502 foundCell = pushToQueue<LPTParticle>(m_pointsToHalo, id);
3503 } else if(!m_periodicBC && part.reqSend()) {
3504 // particle must be copied to a window cell of a neighboring solver
3505 // reduce the search to only halo-cells!
3506
3507 if(a_isHalo(part.m_cellId)) {
3508 foundCell = pushToQueue<LPTParticle>(m_pointsToWindow, id);
3509 if(allowNonLeaf && !foundCell) {
3510 // if allowing for non-leaf cell transfer, check for all halo cells
3511 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3512 for(MInt i = 0; i < noHaloCells(d); i++) {
3513 if(part.m_cellId == grid().haloCell(d, i)) {
3514 sendQueueType<nDim> thisSend{};
3515 thisSend.partPos = id;
3516 thisSend.toCellId = i;
3517 m_queueToSend[d].push(thisSend);
3518 foundCell = true;
3519 }
3520 }
3521 }
3522 }
3523 }
3524 } else if(m_periodicBC && part.reqSend()) {
3525 std::array<MFloat, nDim> tmpShift{F0};
3526 if(grid().isPeriodic(part.m_cellId)) {
3527 for(MInt n = 0; n < nDim; n++) {
3528 if(grid().raw().periodicCartesianDir(n)) {
3529 MFloat cellCoordinate = c_coordinate(part.m_cellId, n);
3530 MInt sign1 = maia::math::sgn(m_globBbox[n] - cellCoordinate);
3531 MInt sign2 = maia::math::sgn(m_globBbox[n + nDim] - cellCoordinate);
3532 MFloat sign = F0;
3533 if(sign1 == 1 && sign2 == 1) {
3534 sign = F1;
3535 } else if(sign1 == -1 && sign2 == -1) {
3536 sign = -F1;
3537 } else {
3538 sign = F0;
3539 }
3540 tmpShift[n] = m_globDomainLength[n] * sign;
3541 }
3542 }
3543 // new position of particle
3544 for(MInt n = 0; n < nDim; n++) {
3545 partList[id].m_position[n] += tmpShift[n];
3546 }
3547 }
3548 // find cell where particle is supposed to be send to
3549 if(a_isHalo(part.m_cellId)) {
3550 foundCell = pushToQueue<LPTParticle>(m_pointsToWindow, id);
3551 if(allowNonLeaf && !foundCell) {
3552 // if allowing for non-leaf cell transfer, check for all halo cells
3553 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3554 for(MInt i = 0; i < noHaloCells(d); i++) {
3555 if(part.m_cellId == grid().haloCell(d, i)) {
3556 sendQueueType<nDim> thisSend{};
3557 thisSend.partPos = id;
3558 thisSend.toCellId = i;
3559 m_queueToSend[d].push(thisSend);
3560 foundCell = true;
3561 }
3562 }
3563 }
3564 }
3565 }
3566 }
3567
3568 if(!foundCell) {
3569 cerr << " globalTimeStep " << globalTimeStep << endl;
3570 cerr << part.m_cellId << endl;
3571 cerr << a_isHalo(part.m_cellId) << endl;
3572 m_log << "TRANSFER status &1 or &4: no corresponding cell found! Original cell " << part.m_cellId
3573 << " properties " << endl;
3574 TERMM(-1, "????");
3575 }
3576 }
3577
3578 // copy particles to the neighboring domains
3579 // blocking comminucation version
3580 if(!m_nonBlockingComm || collOnly) {
3581 sendAndReceiveParticles<LPTParticle>(allowNonLeaf);
3582 } else {
3583 if(allowNonLeaf) {
3584 sendParticles<true, LPTParticle>();
3586 } else {
3587 sendParticles<false, LPTParticle>();
3589 }
3590 }
3591 RECORD_TIMER_STOP(m_timers[Timers::Exchange]);
3592}
MInt m_collisions
Definition: lpt.h:791
std::vector< std::map< MInt, MInt > > m_pointsToHalo
Definition: lpt.h:568
std::vector< std::map< MInt, MInt > > m_pointsToWindow
Definition: lpt.h:569
particleSendQueue< nDim > m_queueToSend
Definition: lpt.h:566
MInt m_nonBlockingStage
Definition: lpt.h:615
std::array< MFloat, nDim > m_globDomainLength
Definition: lpt.h:755
std::array< MFloat, nDim *2 > m_globBbox
Definition: lpt.h:756
MInt noHaloCells(const MInt domainId) const
MInt sgn(T val)
Definition: maiamath.h:495

◆ exchangeSourceTerms()

template<MInt nDim>
void LPT< nDim >::exchangeSourceTerms
protected
Author
Tim Wegmann

Definition at line 7620 of file lpt.cpp.

7620 {
7621 if(m_nonBlockingComm) return;
7622 if(noDomains() > 1) {
7623 if(m_massCoupling) {
7624 maia::mpi::reverseExchangeAddData(grid().neighborDomains(), grid().haloCells(), grid().windowCells(), mpiComm(),
7625 &a_massFlux(0), 1);
7626 }
7627 if(m_momentumCoupling) {
7628 maia::mpi::reverseExchangeAddData(grid().neighborDomains(), grid().haloCells(), grid().windowCells(), mpiComm(),
7629 &a_momentumFlux(0, 0), nDim);
7630 maia::mpi::reverseExchangeAddData(grid().neighborDomains(), grid().haloCells(), grid().windowCells(), mpiComm(),
7631 &a_workFlux(0), 1);
7632 }
7633 if(m_heatCoupling) {
7634 maia::mpi::reverseExchangeAddData(grid().neighborDomains(), grid().haloCells(), grid().windowCells(), mpiComm(),
7635 &a_heatFlux(0), 1);
7636 }
7637 }
7638 // after the values on halo-cells have been added to the matching window cells, the halo-cell values
7639 // must be resettet
7641}
void resetSourceTerms(const MInt)
reset all source terms with cellId larger than the offset
Definition: lpt.cpp:2112
MBool m_momentumCoupling
Definition: lpt.h:635
MFloat & a_momentumFlux(const MInt cellId, const MInt dim)
Definition: lpt.h:418
MBool m_massCoupling
Definition: lpt.h:637
MFloat & a_workFlux(const MInt cellId)
Definition: lpt.h:421
MFloat & a_heatFlux(const MInt cellId)
Definition: lpt.h:412
void reverseExchangeAddData(const std::vector< MInt > &nghbrDomains, const std::vector< std::vector< MInt > > &haloCellVec, const std::vector< std::vector< MInt > > &windowCellVec, const MPI_Comm comm, U **const data, const MInt noDat=1)
Generic exchange from halo to window cells, however in this case the value in the halo-cell is added ...
Definition: mpiexchange.h:1205

◆ finalizeAdaptation()

template<MInt nDim>
void LPT< nDim >::finalizeAdaptation
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1434 of file lpt.cpp.

1434 {
1435 TRACE();
1436
1437 if(!isActive()) return;
1438
1439 if(domainId() == 0) {
1440 cerr << "Finding cartesian neighbors for LPT-solver!" << endl;
1441 }
1442 grid().findCartesianNghbIds();
1443
1445
1447
1448 m_cellToNghbrHood.clear();
1450
1451 // update particle cellIds
1452 // this is probably still faster than having to swap all particle-cellIds during
1453 // multiple adaptation steps!
1454 for(MInt i = 0; i < a_noParticles(); i++) {
1455 m_partList[i].m_neighborList.clear();
1456 const MInt cellId = grid().findContainingLeafCell(&m_partList[i].m_position[0]);
1457 ASSERT(cellId > -1, "");
1458 m_partList[i].m_cellId = cellId;
1459 m_partList[i].m_oldCellId = cellId;
1460 ASSERT(m_partList[i].m_cellId > 0, "ERROR: Illegal cellId after adaptation!");
1461 ASSERT(c_isLeafCell(cellId) && c_level(cellId) == maxRefinementLevel(), "");
1462 }
1463 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
1464 m_partListEllipsoid[i].m_neighborList.clear();
1465 const MInt cellId = grid().findContainingLeafCell(&m_partListEllipsoid[i].m_position[0]);
1466 ASSERT(cellId > -1, "");
1467 m_partListEllipsoid[i].m_cellId = cellId;
1468 m_partListEllipsoid[i].m_oldCellId = cellId;
1469 ASSERT(m_partListEllipsoid[i].m_cellId > 0, "ERROR: Illegal cellId after adaptation!");
1470 ASSERT(c_isLeafCell(cellId) && c_level(cellId) == maxRefinementLevel(), "");
1471 }
1472
1475
1477
1479 checkCells();
1480
1481 // unset bndry-Cell id after adaptation
1482 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
1483 a_bndryCellId(cellId) = -1;
1484 }
1485
1486 // LPT-statistics
1487 MInt noCells = a_noCells();
1488 MInt minCells = noCells;
1489 MInt maxCells = noCells;
1490 MInt noPart = a_noParticles();
1491 MInt minParts = noPart;
1492 MInt maxParts = noPart;
1493 MInt noEllips = a_noEllipsoidalParticles();
1494 MInt minEllips = noEllips;
1495 MInt maxEllips = noEllips;
1496
1497 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noCells");
1498 MPI_Allreduce(MPI_IN_PLACE, &noPart, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noPart");
1499 MPI_Allreduce(MPI_IN_PLACE, &maxCells, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxCells");
1500 MPI_Allreduce(MPI_IN_PLACE, &minCells, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minCells");
1501 MPI_Allreduce(MPI_IN_PLACE, &maxParts, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxParts");
1502 MPI_Allreduce(MPI_IN_PLACE, &minParts, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minParts");
1503 if(m_ellipsoids) {
1504 MPI_Allreduce(MPI_IN_PLACE, &noEllips, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noEllips");
1505 MPI_Allreduce(MPI_IN_PLACE, &maxEllips, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxEllips");
1506 MPI_Allreduce(MPI_IN_PLACE, &minEllips, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minEllips");
1507 }
1508
1509 if(domainId() == 0) {
1510 cerr << "LPT cell-statistics : " << minCells << " - " << maxCells << " avg " << noCells / noDomains() << endl;
1511 cerr << "LPT particle-statistics : " << minParts << " - " << maxParts << " avg " << noPart / noDomains() << endl;
1512 if(m_ellipsoids)
1513 cerr << "LPT ellipsoid-statistics : " << minEllips << " - " << maxEllips << " avg " << noEllips / noDomains()
1514 << endl;
1515 }
1516}
void checkCells()
some debug check for cells
Definition: lpt.cpp:6631
std::map< MInt, std::vector< MInt > > m_cellToNghbrHoodInterpolation
Definition: lpt.h:531
void checkParticles()
some debug check for partcles
Definition: lpt.cpp:6441
std::map< MInt, std::vector< MInt > > m_cellToNghbrHood
Definition: lpt.h:530
void updateFluidFraction()
Definition: lpt.cpp:6286
void findSpawnCellId()
Find spawn cellId.
void setRegridTrigger()
set a_regridTriggerG around all particles to allow for an adaptation check
Definition: lpt.cpp:7373

◆ finalizeBalance()

template<MInt nDim>
void LPT< nDim >::finalizeBalance
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 7243 of file lpt.cpp.

7243 {
7244 TRACE();
7245
7246 if(!isActive()) return;
7247
7248 grid().findCartesianNghbIds();
7249
7251
7252 // reset random-number generator
7254 m_sprayModel->m_PRNGPrimBreakUp.seed(m_sprayModel->m_spraySeed);
7255 }
7256
7257 if(domainId() != m_spawnDomainId) {
7260 m_sprayModel->m_PRNGPrimBreakUpCount = 0;
7261 }
7262 } else {
7263 m_sprayModel->m_PRNGPrimBreakUp.discard(m_sprayModel->m_PRNGPrimBreakUpCount);
7264 }
7265
7266 m_cellToNghbrHood.clear();
7268
7269 // removeInvalidParticles(true);
7270
7272 checkCells();
7273
7275
7277
7278 // reset injection data on all ranks which do not have the injection-cell
7279 if(m_spawnCellId == -1 && m_sprayModel != nullptr) {
7280 const MInt vectorSize = m_injData.size();
7281 m_injData.clear();
7282 const MInt count = m_sprayModel->m_injDataSize + m_addInjDataCnt;
7283 vector<MFloat> tmp(count);
7284 for(MInt i = 0; i < count; i++) {
7285 tmp[i] = 0.0;
7286 }
7287 for(MInt i = 0; i < vectorSize; i++) {
7288 MInt stepId = globalTimeStep - vectorSize + i + 1;
7289 m_injData.insert(make_pair(stepId, tmp));
7290 }
7291 }
7292
7293#ifdef LPT_DEBUG
7294 MInt noParticles = a_noParticles();
7295
7296 MPI_Allreduce(MPI_IN_PLACE, &noParticles, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noParticles");
7297
7298 if(domainId() == 0) {
7299 cerr << noParticles << " #particles after balancing!" << endl;
7300 }
7301
7302 if(m_ellipsoids) {
7303 MInt noEllipsoids = a_noEllipsoidalParticles();
7304 MPI_Allreduce(MPI_IN_PLACE, &noEllipsoids, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noEllipsoids");
7305 cerr0 << noEllipsoids << " #ellipsoids after balancing!" << endl;
7306 }
7307#endif
7308
7309 /*
7310 MInt backup = globalTimeStep;
7311 globalTimeStep = -2;
7312 saveDebugRestartFile();
7313 globalTimeStep = backup;
7314 */
7315
7316 if(globalTimeStep < 0) {
7317 // add refinement around spawnCellId!
7318 // NOTE: a_noParticlesInCell will be corrected after the adaptation!
7319 if(m_spawnCellId > -1) {
7322 }
7323 } else {
7324 // get new neighbor list and distribution weights
7325 for(MInt i = 0; i < a_noParticles(); i++) {
7326 m_partList[i].resetWeights();
7327 }
7328 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
7329 m_partListEllipsoid[i].resetWeights();
7330 }
7331 // re-compute source terms
7333 m_sumEvapMass = 0;
7334 if(!m_skipLPT) {
7335 coupling(-1);
7336 m_sumEvapMass = 0;
7337 if(m_nonBlockingComm) {
7341 } else {
7343 }
7344 }
7345 }
7346
7347 // LPT-statistics
7348 MInt noCells = a_noCells();
7349 MInt minCells = noCells;
7350 MInt maxCells = noCells;
7351 MInt noPart = a_noParticles();
7352 MInt minParts = noPart;
7353 MInt maxParts = noPart;
7354
7355 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noCells");
7356 MPI_Allreduce(MPI_IN_PLACE, &noPart, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noPart");
7357 MPI_Allreduce(MPI_IN_PLACE, &maxCells, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxCells");
7358 MPI_Allreduce(MPI_IN_PLACE, &minCells, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minCells");
7359 MPI_Allreduce(MPI_IN_PLACE, &maxParts, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxParts");
7360 MPI_Allreduce(MPI_IN_PLACE, &minParts, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minParts");
7361
7362 if(domainId() == 0) {
7363 cerr << "LPT cell-statistics : " << minCells << " - " << maxCells << " avg " << noCells / noDomains() << endl;
7364 cerr << "LPT particle-statistics : " << minParts << " - " << maxParts << " avg " << noPart / noDomains() << endl;
7365 }
7366}
void sendSourceTerms()
exchanges the source terms on the LPT grid, non-Blocking version from above
Definition: lpt.cpp:7648
MFloat m_sumEvapMass
Definition: lpt.h:640
static constexpr MInt m_addInjDataCnt
Definition: lpt.h:799
void receiveSourceTerms()
exchanges the source terms on the LPT grid, non-Blocking version from above
Definition: lpt.cpp:7699
void coupling(MInt offset)
Definition: lpt.cpp:3014
MFloat m_particleResiduum
Definition: lpt.h:642
void exchangeSourceTerms()
exchanges the source terms on the LPT grid, this is necessary a) before writing the cell solution fil...
Definition: lpt.cpp:7620
void waitForSendReqs()
wait on all mpi send calls, prior to balance, adaptation or IO
Definition: lpt.cpp:7818
std::map< MInt, std::vector< MFloat > > m_injData
Definition: lpt.h:491
MBool m_skipLPT
Definition: lpt.h:541
std::ostream cerr0

◆ finalizeInitSolver()

template<MInt nDim>
void LPT< nDim >::finalizeInitSolver
overridevirtual

Implements Solver.

Definition at line 1179 of file lpt.cpp.

1179 {
1180 TRACE();
1181
1182 if(m_spawnParticles && !m_restart) {
1183 m_particleResiduum = 1.0;
1184 }
1185
1186 if(!isActive()) return;
1187
1188 if(domainId() == 0) {
1189 cerr << "Finding cartesian neighbors for LPT-solver!" << endl;
1190 }
1191 grid().findCartesianNghbIds();
1192
1193
1194 if(domainId() == 0) {
1195 initSummary();
1196 }
1197
1198 if(!m_restart) {
1199 if(domainId() == 0) {
1200 cerr << "Writing initial particle file" << endl;
1201 }
1202 writePartData();
1203 }
1204
1206}
MBool m_restart
Definition: lpt.h:767
void initSummary()
Print information at the start of simulation.
Definition: lpt.cpp:5778

◆ findSpawnCellId()

template<MInt nDim>
void LPT< nDim >::findSpawnCellId ( )
private
Author
Sven Berger
Date
December 2019

◆ fiveStageSolutionStep()

template<MInt nDim>
MBool LPT< nDim >::fiveStageSolutionStep
private
Date
August 21
Author
Tim Wegmann

Definition at line 2194 of file lpt.cpp.

2194 {
2195 NEW_TIMER_GROUP_STATIC(t_part, "particle timestep");
2196 NEW_TIMER_STATIC(partTS, "particle timestep", t_part);
2197 NEW_SUB_TIMER_STATIC(spawn, "spawn", partTS);
2198 NEW_SUB_TIMER_STATIC(motion, "motion", partTS);
2199 NEW_SUB_TIMER_STATIC(transfer, "transfer", partTS);
2200 NEW_SUB_TIMER_STATIC(evap, "evaporation", partTS);
2201 NEW_SUB_TIMER_STATIC(couplingTerms, "couplingTerms", partTS);
2202 NEW_SUB_TIMER_STATIC(collision1, "wall-collision", partTS);
2203 NEW_SUB_TIMER_STATIC(primBU, "primaryBreakUp", partTS);
2204 NEW_SUB_TIMER_STATIC(secBU, "secondaryBreakUp", partTS);
2205 NEW_SUB_TIMER_STATIC(respawn, "particle-respawn", partTS);
2206 NEW_SUB_TIMER_STATIC(deleteP, "Remove-particles", partTS);
2207
2208 RECORD_TIMER_START(partTS);
2209
2211
2212 switch(m_solutionStep) {
2213 case 1: {
2214 // blocking injection step
2215 RECORD_TIMER_START(primBU);
2216 // some debug checks
2218 checkCells();
2219
2220 if(m_activePrimaryBUp) {
2222 }
2223 RECORD_TIMER_STOP(primBU);
2224
2225 RECORD_TIMER_STOP(partTS);
2226 return false;
2227 break;
2228 }
2229 case 2: {
2230 // receive flow field data from previous TS
2232 // if ellipsoids are activated also receive velocity slopes from previous TS
2234
2236 RECORD_TIMER_START(transfer);
2237 receiveParticles<true>();
2238 m_primaryExchange = false;
2239 RECORD_TIMER_STOP(transfer);
2240 }
2241
2242 // fully non-blocking movement of particles
2243 RECORD_TIMER_START(motion);
2244 motionEquation(0);
2245 RECORD_TIMER_STOP(motion);
2246
2247 RECORD_TIMER_START(collision1);
2248 wallCollision();
2249 RECORD_TIMER_STOP(collision1);
2250
2251 if(m_nonBlockingComm) {
2252 RECORD_TIMER_START(transfer);
2253 exchangeParticles(false, 0);
2254 RECORD_TIMER_STOP(transfer);
2255 }
2256
2257 RECORD_TIMER_STOP(partTS);
2258 return false;
2259 break;
2260 }
2261 case 3: {
2262 if(!m_nonBlockingComm) {
2263 // blocking exchange step
2264 RECORD_TIMER_START(transfer);
2265 exchangeParticles(false, 0);
2266 RECORD_TIMER_STOP(transfer);
2267 } else {
2268 // non-blocking receive
2269 RECORD_TIMER_START(transfer);
2270 receiveParticles<false>();
2271 RECORD_TIMER_STOP(transfer);
2272 }
2273
2274 // non-blocking eveporation
2275 RECORD_TIMER_START(evap);
2276 evaporation(0);
2277 RECORD_TIMER_STOP(evap);
2278
2279 if(m_nonBlockingComm) {
2280 RECORD_TIMER_START(couplingTerms);
2281 coupling(0);
2282 RECORD_TIMER_STOP(couplingTerms);
2284
2285 if(this->m_adaptation && this->m_noSensors > 0) {
2287 }
2288 }
2289
2290 RECORD_TIMER_STOP(partTS);
2291
2292 return false;
2293 break;
2294 }
2295 case 4: {
2296 if(!m_nonBlockingComm) {
2297 // non-blocking computation of source-terms
2298 RECORD_TIMER_START(couplingTerms);
2299 coupling(0);
2300 RECORD_TIMER_STOP(couplingTerms);
2301 } else {
2302 // wait and receive source terms
2303 RECORD_TIMER_START(transfer);
2305 RECORD_TIMER_STOP(transfer);
2306 }
2307
2308 RECORD_TIMER_STOP(partTS);
2309 return false;
2310 break;
2311 }
2312 case 5: {
2313 // non-blocking step unless using outdated particle spawn/respawn or particle-collision
2314 // only particle data-structure related
2315 RECORD_TIMER_START(secBU);
2316 RECORD_TIMER_START(m_timers[Timers::Breakup]);
2318 m_sprayModel->secondaryBreakUp(m_timeStep);
2319 }
2320 RECORD_TIMER_STOP(m_timers[Timers::Breakup]);
2321 RECORD_TIMER_STOP(secBU);
2322
2323 // check for collided particles to be copied to other ranks
2324 RECORD_TIMER_START(transfer);
2325 if(m_collisions < 5 && m_collisions > 0) {
2326 exchangeParticles(true, 0);
2327 }
2328 RECORD_TIMER_STOP(transfer);
2329
2330 RECORD_TIMER_START(spawn);
2331 if(m_spawnParticles) {
2332 spawnTimeStep();
2333 }
2334 RECORD_TIMER_STOP(spawn);
2335
2336 RECORD_TIMER_START(deleteP);
2338 RECORD_TIMER_STOP(deleteP);
2339
2340 RECORD_TIMER_START(respawn);
2341 if(m_respawn) {
2343 }
2344 RECORD_TIMER_STOP(respawn);
2345
2346 RECORD_TIMER_START(deleteP);
2348
2351 }
2352
2353 // gather post-processing data
2354 if(m_sprayModel != nullptr) {
2355 const MInt count = m_sprayModel->m_injDataSize;
2356 vector<MFloat> tmp(count + m_addInjDataCnt);
2357 for(MInt i = 0; i < count; i++) {
2358 tmp[i] = m_sprayModel->m_injData[i];
2359 }
2360 tmp[count] = m_sumEvapMass;
2361 tmp[count + 1] = m_sprayModel->m_noRTsecBreakUp;
2362 tmp[count + 2] = m_sprayModel->m_noKHsecBreakUp;
2363 tmp[count + 3] = m_noSendParticles;
2364
2365 m_injData.insert(make_pair(globalTimeStep, tmp));
2366 }
2367
2368 RECORD_TIMER_STOP(deleteP);
2369 RECORD_TIMER_STOP(partTS);
2370
2371 return true;
2372 break;
2373 }
2374 default: {
2375 mTerm(1, AT_, "Invalid solution Step!");
2376 break;
2377 }
2378 }
2379}
void motionEquation(const MInt offset)
Definition: lpt.cpp:2962
void checkRegridTrigger()
check if any of the cells with the regrid Trigger also have particles inside
Definition: lpt.cpp:7470
MBool m_respawn
Definition: lpt.h:781
MInt m_solutionStep
Definition: lpt.h:949
void exchangeParticles(const MBool collOnly, const MInt offset, const MBool allowNonLeaf=false)
Calls exchange for the different particle types.
Definition: lpt.cpp:3463
MBool m_primaryExchange
Definition: lpt.h:579
void evaporation(const MInt offset)
Definition: lpt.cpp:2991
void particleRespawn()
respawn of Particles
Definition: lpt.cpp:3114
void wallCollision()
collision step with LPT wall
Definition: lpt.cpp:3070
void removeInvalidParticles(const MBool)
Definition: lpt.cpp:2667
void forceTimeStep(const MFloat timeStep)
Definition: lpt.h:318
MInt a_timeStepComputationInterval()
Definition: lpt.h:319
void spawnTimeStep()
spawn new particles and compute their timeStep NOTE: this is an older functionality which is only use...
Definition: lpt.cpp:2624
void receiveVelocitySlopes()
exchanges the velocity slopes on the LPT grid, non-Blocking version
Definition: lpt.cpp:7901
MInt m_noSendParticles
Definition: lpt.h:619
void receiveFlowField()
exchanges the flow Field data on the LPT grid, non-Blocking version
Definition: lpt.cpp:7784
MFloat computeTimeStep()
computes the non-dimensional LPT time-step on the assumption that a particle may only travel for a co...
Definition: lpt.cpp:7533
void sprayInjection()
Definition: lpt.cpp:2644

◆ forceAdaptation()

template<MInt nDim>
MBool LPT< nDim >::forceAdaptation ( )
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 228 of file lpt.h.

228 {
229 this->startLoadTimer(AT_);
230
232
233 // If LPTSolver is inactive on one of the ranks we need this allreduce!
234 if(grid().hasInactiveRanks()) {
235 MPI_Allreduce(MPI_IN_PLACE, &m_forceAdaptation, 1, MPI_C_BOOL, MPI_LOR, grid().raw().mpiComm(), AT_,
236 "MPI_IN_PLACE", "m_forceAdaptation");
237 }
238
239 this->stopLoadTimer(AT_);
240
241 return m_forceAdaptation;
242 }
void recvRegridTrigger()
Definition: lpt.cpp:7507
void startLoadTimer(const MString name)
Definition: solver.h:293
void stopLoadTimer(const MString &name)
Definition: solver.h:295

◆ forceTimeStep()

template<MInt nDim>
void LPT< nDim >::forceTimeStep ( const MFloat  timeStep)
inline

Definition at line 318 of file lpt.h.

318{ m_timeStep = timeStep; }

◆ geometry()

template<MInt nDim>
Geom & LPT< nDim >::geometry ( ) const
inline

Definition at line 183 of file lpt.h.

183{ return *m_geometry; }
Geom * m_geometry
Definition: lpt.h:173

◆ getCellDataDlb() [1/2]

template<MInt nDim>
void LPT< nDim >::getCellDataDlb ( const MInt  dataId,
const MInt  oldNoCells,
const MInt *const  bufferIdToCellId,
MFloat *const  data 
)
override
Author
Tim Wegmann

Definition at line 6973 of file lpt.cpp.

6974 {
6975 TRACE();
6976
6977 if(dataId != 1) mTerm(1, AT_, "Only Type 1 should be FLOAT");
6978
6979 MInt localBufferId = 0;
6980 for(MInt i = 0; i < oldNoCells; i++) {
6981 const MInt gridCellId = bufferIdToCellId[i];
6982
6983 if(gridCellId < 0) continue;
6984
6985 const MInt cellId = grid().tree().grid2solver(gridCellId);
6986 if(cellId < 0 || cellId >= noInternalCells()) {
6987 continue;
6988 }
6989
6990 if(a_noParticlesInCell(cellId) > 0) {
6991 auto particlesInCell = m_cellToPartMap.equal_range(cellId);
6992 // loop over all particles in the cell
6993 vector<LPTSpherical<nDim>*> particlesToSend;
6994 vector<MInt> cellIds;
6995 for(auto it = particlesInCell.first; it != particlesInCell.second; it++) {
6996 auto& particle = it->second;
6997 particlesToSend.push_back(particle);
6998 }
6999 if((MInt)particlesToSend.size() != a_noParticlesInCell(cellId)) {
7000 cerr << particlesToSend.size() << " " << a_noParticlesInCell(cellId) << " miss-count!" << endl;
7001 mTerm(1, AT_, "Particle count not matching!");
7002 }
7003 packParticles(particlesToSend, nullptr, &data[localBufferId], cellIds);
7004 localBufferId += ((elemPerP<LPTSpherical<nDim>>() + 3) * particlesToSend.size());
7005 }
7006
7007 if(a_noEllipsoidsInCell(cellId) > 0) {
7008 auto ellipsoidsInCell = m_cellToEllipsMap.equal_range(cellId);
7009 vector<LPTEllipsoidal<nDim>*> ellipsoidsToSend;
7010 vector<MInt> cellIds;
7011 for(auto it = ellipsoidsInCell.first; it != ellipsoidsInCell.second; it++) {
7012 auto& particle = it->second;
7013 ellipsoidsToSend.push_back(particle);
7014 }
7015 if((MInt)ellipsoidsToSend.size() != a_noEllipsoidsInCell(cellId)) {
7016 cerr << ellipsoidsToSend.size() << " " << a_noEllipsoidsInCell(cellId) << " miss-count!" << endl;
7017 mTerm(1, AT_, "Ellipsoids count not matching!");
7018 }
7019 packParticles(ellipsoidsToSend, nullptr, &data[localBufferId], cellIds);
7020 localBufferId += ((elemPerP<LPTEllipsoidal<nDim>>() + 2) * ellipsoidsToSend.size());
7021 }
7022 }
7023}
std::multimap< MInt, LPTSpherical< nDim > * > m_cellToPartMap
Definition: lpt.h:819
std::multimap< MInt, LPTEllipsoidal< nDim > * > m_cellToEllipsMap
Definition: lpt.h:820

◆ getCellDataDlb() [2/2]

template<MInt nDim>
void LPT< nDim >::getCellDataDlb ( const MInt  dataId,
const MInt  oldNoCells,
const MInt *const  bufferIdToCellId,
MInt *const  data 
)
override

Definition at line 7026 of file lpt.cpp.

7027 {
7028 TRACE();
7029
7030 if(dataId != 2 && dataId != 0) mTerm(1, AT_, "Type 0 or 2 should be INT");
7031
7032 MInt localBufferId = 0;
7033 for(MInt i = 0; i < oldNoCells; i++) {
7034 const MInt gridCellId = bufferIdToCellId[i];
7035
7036 if(gridCellId < 0) continue;
7037
7038 const MInt cellId = grid().tree().grid2solver(gridCellId);
7039 if(cellId < 0 || cellId >= noInternalCells()) {
7040 continue;
7041 }
7042
7043 if(dataId == 0) {
7044 data[localBufferId++] = a_noParticlesInCell(cellId);
7045 data[localBufferId++] = a_noEllipsoidsInCell(cellId);
7046 continue;
7047 }
7048
7049 if(a_noParticlesInCell(cellId) > 0) {
7050 auto particlesInCell = m_cellToPartMap.equal_range(cellId);
7051 // loop over all particles in the cell
7052 vector<LPTSpherical<nDim>*> particlesToSend;
7053 for(auto it = particlesInCell.first; it != particlesInCell.second; it++) {
7054 auto& particle = it->second;
7055 data[localBufferId] = (MInt)(particle->m_partId >> 32);
7056 data[localBufferId + 1] = MInt(particle->m_partId);
7057 data[localBufferId + 2] = particle->m_noParticles;
7058 // ASSERT(data[localBufferId + 2] > 0 , "");
7059 if(data[localBufferId + 2] < 0) {
7060 cerr << "Setting strange exchange buffer!" << endl;
7061 }
7062 localBufferId += 3;
7063 }
7064 }
7065
7066 if(a_noEllipsoidsInCell(cellId) > 0) {
7067 auto ellipsoidsInCell = m_cellToEllipsMap.equal_range(cellId);
7068 vector<LPTEllipsoidal<nDim>*> ellipsoidsToSend;
7069 for(auto it = ellipsoidsInCell.first; it != ellipsoidsInCell.second; it++) {
7070 auto& particle = it->second;
7071 data[localBufferId] = (MInt)(particle->m_partId >> 32);
7072 data[localBufferId + 1] = MInt(particle->m_partId);
7073 localBufferId += 2;
7074 }
7075 }
7076 }
7077}

◆ getCellLoad()

template<MInt nDim>
MFloat LPT< nDim >::getCellLoad ( const MInt  gridCellId,
const MFloat *const  weights 
) const
override
Parameters
[in]cellIdRequested grid cell id.
[in]weightsComputational weights for different simulation components.
Returns
Cell load.
Author
Tim Wegmann

Definition at line 1988 of file lpt.cpp.

1988 {
1989 TRACE();
1990 ASSERT(isActive(), "solver is not active");
1991
1992 // Convert to solver cell id and check
1993 const MInt cellId = grid().tree().grid2solver(gridCellId);
1994 if(cellId < 0) {
1995 return 0;
1996 }
1997
1998 if(cellId < 0 || cellId >= grid().noInternalCells()) {
1999 TERMM(1, "The given cell id is invalid.");
2000 }
2001
2002 // Default cell load
2003 MFloat cellLoad = 0.0;
2004 if(c_isLeafCell(cellId) && a_isValidCell(cellId)) {
2005 cellLoad = weights[0];
2006 }
2007
2008 if(a_noParticlesInCell(cellId) > 0 || a_noEllipsoidsInCell(cellId) > 0) {
2009 cellLoad = weights[1];
2010 cellLoad += a_noParticlesInCell(cellId) * weights[2];
2011 } else if(m_weightSourceCells) {
2012 if(m_massCoupling && a_massFlux(cellId) < 0.0) {
2013 cellLoad = weights[3];
2014 }
2015 }
2016
2017 if(m_sprayModel != nullptr && cellId == m_spawnCellId) {
2018 cellLoad += 5 * weights[1];
2019 }
2020
2021
2022 return cellLoad;
2023}
MBool m_weightSourceCells
Definition: lpt.h:553
MBool a_isValidCell(const MInt cellId) const
Definition: lpt.h:443

◆ getDefaultWeights()

template<MInt nDim>
void LPT< nDim >::getDefaultWeights ( MFloat weights,
std::vector< MString > &  names 
) const
override

Definition at line 1888 of file lpt.cpp.

1888 {
1889 TRACE();
1890
1891 weights[0] = 0.1;
1892 names[0] = "lpt_cell";
1893 MInt count = 1;
1894
1895 weights[1] = 0.9;
1896 names[1] = "lpt_particleCell";
1897 count++;
1898
1899 weights[2] = 0.1;
1900 names[2] = "lpt_particle";
1901 count++;
1902
1904 weights[3] = 0.01;
1905 names[3] = "lpt_source";
1906 count++;
1907 }
1908
1909 if(noLoadTypes() != count) {
1910 TERMM(1, "Count does not match noLoadTypes.");
1911 }
1912}
MInt noLoadTypes() const override
Definition: lpt.h:270

◆ getDomainDecompositionInformation()

template<MInt nDim>
void LPT< nDim >::getDomainDecompositionInformation ( std::vector< std::pair< MString, MInt > > &  domainInfo)
override
Author
Tim Wegmann

Definition at line 2031 of file lpt.cpp.

2031 {
2032 TRACE();
2033
2034 const MString namePrefix = "b" + std::to_string(solverId()) + "_";
2035
2036 const MInt noInternalCells = isActive() ? grid().noInternalCells() : 0;
2037
2038 domainInfo.emplace_back(namePrefix + "noLptCells", noInternalCells);
2039
2040 // Number of Ls-Band-Cells
2041 MInt noCellsWithParticles = 0;
2042 MInt noLeafCells = 0;
2043 MInt noParticles = 0;
2044
2045 if(isActive()) {
2046 noParticles = a_noParticles();
2047 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
2048 if(a_noParticlesInCell(cellId) > 0 || a_noEllipsoidsInCell(cellId) > 0) {
2049 noCellsWithParticles++;
2050 }
2051 if(c_isLeafCell(cellId) && a_isValidCell(cellId)) {
2052 noLeafCells++;
2053 }
2054 }
2055 }
2056
2057 domainInfo.emplace_back(namePrefix + "noLptLeafCells", noLeafCells);
2058 domainInfo.emplace_back(namePrefix + "noLptParticleCells", noCellsWithParticles);
2059 domainInfo.emplace_back(namePrefix + "noLptParticles", noParticles);
2060}
std::basic_string< char > MString
Definition: maiatypes.h:55

◆ getGlobalSolverVars()

template<MInt nDim>
void LPT< nDim >::getGlobalSolverVars ( std::vector< MFloat > &  globalFloatVars,
std::vector< MInt > &  globalIdVars 
)
override

Get global solver variables that need to be communicated for DLB (same on each domain)

Author
Tim Wegmann

Definition at line 7167 of file lpt.cpp.

7167 {
7168 TRACE();
7169
7170 globalIntVars.push_back(m_PRNGSpawnCount);
7171
7173 globalIntVars.push_back(m_sprayModel->m_PRNGPrimBreakUpCount);
7174 }
7175
7176 globalFloatVars.push_back(m_particleResiduum);
7177 globalFloatVars.push_back(m_time);
7178 globalFloatVars.push_back(m_timeStep);
7179
7180 if(m_activePrimaryBUp) {
7181 globalFloatVars.push_back(m_sprayModel->timeSinceSOI());
7182 }
7183
7184 if(m_activePrimaryBUp && !m_injData.empty()) {
7185 for(auto it = m_injData.begin(); it != m_injData.end(); it++) {
7186 const MFloat timeStep = (MFloat)it->first;
7187 globalFloatVars.push_back(timeStep);
7188 for(MInt i = 0; i < m_sprayModel->m_injDataSize + m_addInjDataCnt; i++) {
7189 const MFloat data = (it->second)[i];
7190 globalFloatVars.push_back(data);
7191 }
7192 }
7193 globalIntVars.push_back(m_injData.size());
7194 } else if(m_activePrimaryBUp) {
7195 globalIntVars.push_back(0);
7196 }
7197}
MInt m_PRNGSpawnCount
Definition: lpt.h:559

◆ getHeatRelease()

template<MInt nDim>
void LPT< nDim >::getHeatRelease ( MFloat *&  heatRelease)
inline

Definition at line 1007 of file lpt.h.

1007 {
1008 std::cerr << "getHeatRelease DgCartesianSolver " << heatRelease << std::endl;
1009 }

◆ getLoadQuantities()

template<MInt nDim>
void LPT< nDim >::getLoadQuantities ( MInt *const  loadQuantities) const
override
Parameters
[out]loadQuantitiesStorage for load quantities.
Author
Tim Wegmann

Definition at line 1934 of file lpt.cpp.

1934 {
1935 TRACE();
1936
1937 // Nothing to do if solver is not active
1938 if(!isActive()) {
1939 return;
1940 }
1941
1942 // reset
1943 for(MInt type = 0; type < noLoadTypes(); type++) {
1944 loadQuantities[type] = 0;
1945 }
1946
1947 MInt noLeafCells = 0;
1948 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
1949 if(c_isLeafCell(cellId) && a_isValidCell(cellId)) {
1950 noLeafCells++;
1951 }
1952 }
1953
1954 loadQuantities[0] = noLeafCells;
1955
1956 MInt noCellsWithParticles = 0;
1957 MInt noCellsWithSources = 0;
1958
1959 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
1960 if(a_noParticlesInCell(cellId) == 0 && a_noEllipsoidsInCell(cellId) == 0) {
1961 if(m_massCoupling && a_massFlux(cellId) < 0.0) {
1962 noCellsWithSources++;
1963 }
1964 continue;
1965 }
1966 noCellsWithParticles++;
1967 }
1968 loadQuantities[1] = noCellsWithParticles;
1969 loadQuantities[2] = a_noSphericalParticles() + a_noEllipsoidalParticles();
1970
1971
1973 loadQuantities[3] = noCellsWithSources;
1974 }
1975}
MInt a_noSphericalParticles() const
Definition: lpt.h:371

◆ getSampleVariables() [1/2]

template<MInt nDim>
void LPT< nDim >::getSampleVariables ( const MInt  cellId,
std::vector< MFloat > &   
)
inline

Definition at line 1003 of file lpt.h.

1003 {
1004 std::cerr << "getSampleVariables LPT " << cellId << std::endl;
1005 };

◆ getSampleVariables() [2/2]

template<MInt nDim>
void LPT< nDim >::getSampleVariables ( MInt  cellId,
const MFloat *&  vars 
)
inline

Definition at line 1000 of file lpt.h.

1000 {
1001 std::cerr << "getSampleVariables LPT " << cellId << " " << vars << std::endl;
1002 };

◆ getSolverTimings()

template<MInt nDim>
void LPT< nDim >::getSolverTimings ( std::vector< std::pair< std::string, MFloat > > &  ,
const MBool  allTimings 
)
override
Author
Tim Wegmann

Definition at line 1861 of file lpt.cpp.

1862 {
1863 TRACE();
1864
1865 const MString namePrefix = "b" + std::to_string(solverId()) + "_";
1866
1867 const MFloat load = returnLoadRecord();
1868 const MFloat idle = returnIdleRecord();
1869
1870 solverTimings.emplace_back(namePrefix + "loadLptSolver", load);
1871 solverTimings.emplace_back(namePrefix + "idleLptSolver", idle);
1872
1873#ifdef MAIA_TIMER_FUNCTION
1874 solverTimings.emplace_back(namePrefix + "timeIntegration", RETURN_TIMER_TIME(m_timers[Timers::TimeInt]));
1875 solverTimings.emplace_back(namePrefix + "motion", RETURN_TIMER_TIME(m_timers[Timers::Motion]));
1876 solverTimings.emplace_back(namePrefix + "energy", RETURN_TIMER_TIME(m_timers[Timers::Energy]));
1877 solverTimings.emplace_back(namePrefix + "injection", RETURN_TIMER_TIME(m_timers[Timers::Injection]));
1878 solverTimings.emplace_back(namePrefix + "secBreakUp", RETURN_TIMER_TIME(m_timers[Timers::Breakup]));
1879 solverTimings.emplace_back(namePrefix + "wall", RETURN_TIMER_TIME(m_timers[Timers::Wall]));
1880 solverTimings.emplace_back(namePrefix + "source", RETURN_TIMER_TIME(m_timers[Timers::SourceTerms]));
1881 solverTimings.emplace_back(namePrefix + "regridExc", RETURN_TIMER_TIME(m_timers[Timers::Exchange2]));
1882 solverTimings.emplace_back(namePrefix + "exchange", RETURN_TIMER_TIME(m_timers[Timers::Exchange]));
1883#endif
1884}
MFloat returnIdleRecord() const
Definition: solver.h:486
MFloat returnLoadRecord() const
Definition: solver.h:485

◆ globalNoEllipsoids()

template<MInt nDim>
MInt LPT< nDim >::globalNoEllipsoids ( )
inline

Definition at line 501 of file lpt.h.

501 {
502 MInt sumPart = 0;
503 MInt noPart = m_partListEllipsoid.size();
504 MPI_Allreduce(&noPart, &sumPart, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "sumpart");
505 return sumPart;
506 }

◆ globalNoParticles()

template<MInt nDim>
MInt LPT< nDim >::globalNoParticles ( )
inline

Definition at line 494 of file lpt.h.

494 {
495 MInt sumPart = 0;
496 MInt noPart = m_partList.size();
497 MPI_Allreduce(&noPart, &sumPart, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "sumpart");
498 return sumPart;
499 }

◆ hasSplitBalancing()

template<MInt nDim>
MBool LPT< nDim >::hasSplitBalancing ( ) const
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 314 of file lpt.h.

314{ return true; }

◆ initBndryCells()

template<MInt nDim>
void LPT< nDim >::initBndryCells
private
Author
Tim Wegmann
Date
October 2020

Definition at line 352 of file lpt.cpp.

352 {
353 TRACE();
354
355 // if(!m_wallCollisions) return;
356
357 // init data structure
358 constexpr MInt maxNoSurfaces = 1;
359 mAlloc(m_bndryCells, m_maxNoBndryCells, nDim, 0, 0, maxNoSurfaces, 0, "m_bndryCells", AT_);
360
361 // fill on own data
364}
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
MInt resetSize(MInt inputSize)
Definition: collector.h:45
MInt m_noOuterBndryCells
Definition: lpt.h:792
MInt m_maxNoBndryCells
Definition: lpt.h:790

◆ initCollector()

template<MInt nDim>
void LPT< nDim >::initCollector
private
Author
Tim Wegmann
Date
October 2020

Definition at line 153 of file lpt.cpp.

153 {
154 TRACE();
155
156 m_cells.clear();
158 ASSERT(grid().tree().size() < grid().maxNoCells(), "Increase collector size!");
159 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
160 m_cells.append();
161 a_isHalo(cellId) = false;
162 a_isValidCell(cellId) = true;
163 a_isWindow(cellId) = false;
164 a_regridTrigger(cellId) = false;
165 a_noParticlesInCell(cellId) = 0;
166 a_noEllipsoidsInCell(cellId) = 0;
167 a_bndryCellId(cellId) = -1;
168 for(MInt n = 0; n < nDim; n++) {
169 a_fluidVelocity(cellId, n) = 0.0;
170 }
171 a_fluidDensity(cellId) = 0.0;
172 a_fluidPressure(cellId) = 0.0;
173 a_fluidTemperature(cellId) = 0.0;
174 if(m_evaporation) {
175 a_fluidSpecies(cellId) = 0.0;
176 }
177
179 for(MInt i = 0; i < nDim; i++) {
180 a_momentumFlux(cellId, i) = 0;
181 }
182 a_workFlux(cellId) = 0;
183 }
184 if(m_heatCoupling) {
185 a_heatFlux(cellId) = 0;
186 }
187 if(m_massCoupling) {
188 a_massFlux(cellId) = 0;
189 }
190 if(m_ellipsoids) {
191 for(MInt varId = 0; varId < nDim; varId++) {
192 for(MInt dir = 0; dir < nDim; dir++) {
193 a_velocitySlope(cellId, varId, dir) = F0;
194 }
195 }
196 }
197 }
198 for(MInt cellId = grid().noInternalCells(); cellId < grid().tree().size(); cellId++) {
199 m_cells.append();
200 a_isHalo(cellId) = true;
201 a_isWindow(cellId) = false;
202 a_isValidCell(cellId) = true;
203 a_regridTrigger(cellId) = false;
204 a_noParticlesInCell(cellId) = 0;
205 a_noEllipsoidsInCell(cellId) = 0;
206 a_bndryCellId(cellId) = -1;
207 for(MInt n = 0; n < nDim; n++) {
208 a_fluidVelocity(cellId, n) = 0.0;
209 }
210 a_fluidDensity(cellId) = 0.0;
211 a_fluidPressure(cellId) = 0.0;
212 a_fluidTemperature(cellId) = 0.0;
213 if(m_evaporation) {
214 a_fluidSpecies(cellId) = 0.0;
215 }
217 for(MInt i = 0; i < nDim; i++) {
218 a_momentumFlux(cellId, i) = 0;
219 }
220 a_workFlux(cellId) = 0;
221 }
222 if(m_heatCoupling) {
223 a_heatFlux(cellId) = 0;
224 }
225 if(m_massCoupling) {
226 a_massFlux(cellId) = 0;
227 }
228 if(m_ellipsoids) {
229 for(MInt varId = 0; varId < nDim; varId++) {
230 for(MInt dir = 0; dir < nDim; dir++) {
231 a_velocitySlope(cellId, varId, dir) = F0;
232 }
233 }
234 }
235 }
236}
MBool a_isWindow(const MInt cellId) const
Definition: lpt.h:438
MFloat & a_fluidTemperature(const MInt cellId)
Definition: lpt.h:406
MFloat & a_velocitySlope(const MInt cellId, const MInt varId, const MInt dir)
Definition: lpt.h:424
MFloat & a_fluidPressure(const MInt cellId)
Definition: lpt.h:403
MFloat & a_fluidSpecies(const MInt cellId)
Definition: lpt.h:409
void clear()
Clear tree by invalidating all nodes and setting size to zero.
Definition: container.h:395
void append(const MInt count)
Append nodes to end of tree.
Definition: container.h:223

◆ initGridProperties()

template<MInt nDim>
void LPT< nDim >::initGridProperties
private
Author
Oliver Groll, Johannes Grafen
Date
March 2022

Definition at line 603 of file lpt.cpp.

603 {
605 MInt periodic = 0;
606 for(MInt n = 0; n < nDim; n++) {
607 m_globDomainLength[n] = m_globBbox[n + nDim] - m_globBbox[n];
608 periodic += grid().raw().periodicCartesianDir(n);
609 }
610
611 if(periodic) {
612 m_periodicBC = true;
613 }
614}
void computeBoundingBox(MFloat *globalBbox)
Definition: lpt.h:852

◆ initialCondition()

template<MInt nDim>
void LPT< nDim >::initialCondition ( )
private
Author
Christoph Siewert, Sven Berger, Tim Wegmann
Date
June 2015

◆ initializeTimers()

template<MInt nDim>
void LPT< nDim >::initializeTimers
private
Author
Tim Wegmann

Definition at line 7984 of file lpt.cpp.

7984 {
7985 TRACE();
7986
7987 std::fill(m_timers.begin(), m_timers.end(), -1);
7988
7989 // Create timer group & timer for solver, and start the timer
7990 NEW_TIMER_GROUP_NOCREATE(m_timerGroup, "LPT (solverId = " + to_string(m_solverId) + ")");
7991 NEW_TIMER_NOCREATE(m_timers[Timers::SolverType], "total object lifetime", m_timerGroup);
7992 RECORD_TIMER_START(m_timers[Timers::SolverType]);
7993
7994 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::TimeInt], "Time-integration", m_timers[Timers::SolverType]);
7995 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::PreTime], "PreTimeStep", m_timers[Timers::SolverType]);
7996
7997 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Motion], "Motion", m_timers[Timers::TimeInt]);
7998 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Energy], "Energy", m_timers[Timers::TimeInt]);
7999 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Wall], "Wall", m_timers[Timers::TimeInt]);
8000 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SourceTerms], "Sources", m_timers[Timers::TimeInt]);
8001
8002 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Injection], "injection", m_timers[Timers::TimeInt]);
8003 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Breakup], "breakup", m_timers[Timers::TimeInt]);
8004
8005 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Exchange], "exchange", m_timers[Timers::SolverType]);
8006
8007 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Exchange1], "mpi", m_timers[Timers::Exchange]);
8008 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Exchange2], "prepare", m_timers[Timers::Exchange]);
8009 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Exchange3], "pack", m_timers[Timers::Exchange]);
8010 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Exchange4], "receive", m_timers[Timers::Exchange]);
8011 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Exchange5], "unpack", m_timers[Timers::Exchange]);
8012}
MInt m_timerGroup
Definition: lpt.h:536

◆ initMPI()

template<MInt nDim>
void LPT< nDim >::initMPI ( const MBool  fullReinit = true)
private
Author
Sven Berger, Tim Wegmann
Date
August 2015

Definition at line 374 of file lpt.cpp.

374 {
375 TRACE();
376
377 if(noDomains() < 1) {
378 return;
379 }
380
381 const MInt noNghbrDomains = grid().noNeighborDomains();
382
383 if(fullReinit) {
384 m_queueToSend.resize(noNghbrDomains);
385 m_sendSize.resize(noNghbrDomains);
386 m_recvSize.resize(noNghbrDomains);
387 m_sendBuffer.resize(noNghbrDomains);
388 m_recvBuffer.resize(noNghbrDomains);
389 m_intSendBuffer.resize(noNghbrDomains);
390 m_intRecvBuffer.resize(noNghbrDomains);
391 m_mpi_reqSendFloat.resize(noNghbrDomains);
392 m_mpi_reqRecvFloat.resize(noNghbrDomains);
393 m_mpi_reqSendSize.resize(noNghbrDomains);
394 m_mpi_reqSendInt.resize(noNghbrDomains);
395 m_mpi_reqRecvInt.resize(noNghbrDomains);
396 m_mpi_statusProbe.resize(noNghbrDomains);
397
398 // if particles and ellipsoids can be present, the larger buffer size is chosen
399 const MInt bufferSize = !m_ellipsoids ? bufSize<LPTSpherical<nDim>>()
400 : mMax(bufSize<LPTSpherical<nDim>>(), bufSize<LPTEllipsoidal<nDim>>());
401 const MInt intBufferSize = !m_ellipsoids
402 ? intBufSize<LPTSpherical<nDim>>()
403 : mMax(intBufSize<LPTSpherical<nDim>>(), intBufSize<LPTEllipsoidal<nDim>>());
404
405 for(MInt i = 0; i < noNghbrDomains; i++) {
406 m_sendSize[i] = 0;
407 m_recvSize[i] = 0;
408 m_sendBuffer[i] = make_unique<MFloat[]>(bufferSize);
409 m_recvBuffer[i] = make_unique<MFloat[]>(bufferSize);
410 m_intSendBuffer[i] = make_unique<MInt[]>(intBufferSize);
411 m_intRecvBuffer[i] = make_unique<MInt[]>(intBufferSize);
412 }
413
414 // initialize the buffer
415 for(MInt i = 0; i < noNghbrDomains; i++) {
416 for(MInt j = 0; j < bufferSize; j++) {
417 m_sendBuffer[i][j] = 0.0;
418 m_recvBuffer[i][j] = 0.0;
419 }
420 for(MInt j = 0; j < intBufferSize; j++) {
421 m_intSendBuffer[i][j] = 0;
422 m_intRecvBuffer[i][j] = 0;
423 }
424 }
425
426
428 m_noSourceTerms = 0;
432
433 m_sourceSend.resize(noNghbrDomains);
434 m_sourceRecv.resize(noNghbrDomains);
435
437 mAlloc(m_sourceSendRequest, noNghbrDomains, "sourceSendReq", AT_);
439 mAlloc(m_sourceRecvRequest, noNghbrDomains, "sourceRecvReq", AT_);
440
441 if(m_flowSendRequest != nullptr) {
443 }
444 mAlloc(m_flowSendRequest, noNghbrDomains, "flowSendReq", AT_);
445 if(m_flowRecvRequest != nullptr) {
447 }
448 mAlloc(m_flowRecvRequest, noNghbrDomains, "flowRecvReq", AT_);
449
450 if(m_checkAdaptationSendRequest != nullptr) {
452 }
453 mAlloc(m_checkAdaptationSendRequest, noDomains(), "checkAdapSendReq", AT_);
454 if(m_checkAdaptationRecvRequest != nullptr) {
456 }
457 mAlloc(m_checkAdaptationRecvRequest, noDomains(), "checkAdapRecvReq", AT_);
458
461
462 if(m_ellipsoids) {
463 if(m_slopesSendRequest != nullptr) {
465 }
466 mAlloc(m_slopesSendRequest, noNghbrDomains, "slopesSendReq", AT_);
467 if(m_slopesRecvRequest != nullptr) {
469 }
470 mAlloc(m_slopesRecvRequest, noNghbrDomains, "slopesRecvReq", AT_);
471 }
472 }
473 }
474
476 MInt maxNoHaloCells = 0;
477 MInt maxNoWindowCells = 0;
478
479 ScratchSpace<MInt> windowCellsCnt(noNeighborDomains(), AT_, "noWindowCells");
480 ScratchSpace<MInt> haloCellsCnt(noNeighborDomains(), AT_, "noHaloCells");
481
482 for(MInt i = 0; i < noNghbrDomains; i++) {
483 maxNoHaloCells = mMax(maxNoHaloCells, grid().noLeafHaloCells(i));
484 maxNoWindowCells = mMax(maxNoWindowCells, grid().noLeafWindowCells(i));
485 m_sourceSendRequest[i] = MPI_REQUEST_NULL;
486 m_sourceRecvRequest[i] = MPI_REQUEST_NULL;
487 m_flowSendRequest[i] = MPI_REQUEST_NULL;
488 m_flowRecvRequest[i] = MPI_REQUEST_NULL;
489 if(m_ellipsoids) {
490 m_slopesSendRequest[i] = MPI_REQUEST_NULL;
491 m_slopesRecvRequest[i] = MPI_REQUEST_NULL;
492 }
493 windowCellsCnt[i] = grid().noLeafWindowCells(i);
494 haloCellsCnt[i] = grid().noLeafHaloCells(i);
495 }
496
497 for(MInt d = 0; d < noDomains(); d++) {
498 m_checkAdaptationRecvRequest[d] = MPI_REQUEST_NULL;
499 m_checkAdaptationSendRequest[d] = MPI_REQUEST_NULL;
500 }
501
502 if(m_flowRecv != nullptr) {
504 }
505 mAlloc(m_flowRecv, noNeighborDomains(), &haloCellsCnt[0], PV.noVars() + m_evaporation, "m_flowRecv", AT_);
506 if(m_flowSend != nullptr) {
508 }
509 mAlloc(m_flowSend, noNeighborDomains(), &windowCellsCnt[0], PV.noVars() + m_evaporation, "m_flowSend", AT_);
510
511
512 for(MInt i = 0; i < noNghbrDomains; i++) {
513 m_sourceSend[i] = make_unique<MFloat[]>(maxNoHaloCells * m_noSourceTerms);
514 m_sourceRecv[i] = make_unique<MFloat[]>(maxNoWindowCells * m_noSourceTerms);
515 }
516
517
518 for(MInt i = 0; i < noNghbrDomains; i++) {
519 for(MInt j = 0; j < grid().noLeafHaloCells(i) * m_noSourceTerms; j++) {
520 m_sourceSend[i][j] = 0.0;
521 }
522 for(MInt j = 0; j < grid().noLeafWindowCells(i) * m_noSourceTerms; j++) {
523 m_sourceRecv[i][j] = 0.0;
524 }
525 }
526 for(MInt i = 0; i < noDomains(); i++) {
529 }
530
531 if(m_ellipsoids) {
532 if(m_slopesRecv != nullptr) {
534 }
535 mAlloc(m_slopesRecv, noNeighborDomains(), &haloCellsCnt[0], nDim * nDim, "m_slopesRecv", AT_);
536 if(m_slopesSend != nullptr) {
538 }
539 mAlloc(m_slopesSend, noNeighborDomains(), &windowCellsCnt[0], nDim * nDim, "m_slopesSend", AT_);
540 }
541 }
542
543 if(m_respawn && fullReinit) {
544 struct {
545 MInt val;
546 MInt rank;
547 } local{}, global{};
548 local.val = (MInt)m_respawnCells.size();
549 local.rank = domainId();
550 global.val = 0;
551 global.rank = -1;
552 MPI_Allreduce(&local, &global, 1, MPI_2INT, MPI_MAXLOC, mpiComm(), AT_, "local", "global");
553 m_respawnDomain = global.rank;
554 MInt* particleRespawnCellsPerDomain = nullptr;
555 if(domainId() == m_respawnDomain) {
556 particleRespawnCellsPerDomain = new MInt[noDomains()];
557 }
558 MPI_Gather(&local.val, 1, MPI_INT, particleRespawnCellsPerDomain, 1, MPI_INT, m_respawnDomain, mpiComm(), AT_,
559 "local.val", "particleRespawnCellsPerDomain");
560
561
562 if(domainId() == m_respawnDomain) {
563 MInt globalNoRespawnCells = 0;
565 for(MInt i = 0; i < noDomains(); ++i) {
566 globalNoRespawnCells += particleRespawnCellsPerDomain[i];
567 if(particleRespawnCellsPerDomain[i] > 0) {
569 }
570 }
571 if(globalNoRespawnCells == 0) {
572 stringstream errorMessage;
573 errorMessage << "globally no RespawnCells found despite the set properties particleRespawn " << m_respawn
574 << " and general Respawn (particleRespawnType==0) or massiveParallel ";
575 mTerm(1, AT_, errorMessage.str());
576 }
580 MInt counter = 0;
581 for(MInt i = 0; i < noDomains(); ++i) {
582 if(particleRespawnCellsPerDomain[i] > 0) {
583 m_respawnDomainRanks[counter] = i;
584 m_respawnGlobalDomainOffsets[counter + 1] =
585 m_respawnGlobalDomainOffsets[counter] + particleRespawnCellsPerDomain[i];
586 ++counter;
587 }
588 }
589
590 delete[] particleRespawnCellsPerDomain;
591 } else {
593 }
594 }
595}
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
Definition: alloc.h:544
MInt m_noRespawnDomains
Definition: lpt.h:784
MInt intBufSize()
Definition: lpt.h:683
MPI_Request * m_checkAdaptationSendRequest
Definition: lpt.h:587
std::vector< MPI_Request > m_mpi_reqSendFloat
Definition: lpt.h:604
std::vector< MPI_Request > m_mpi_reqRecvInt
Definition: lpt.h:608
std::vector< MInt > m_checkAdaptationSend
Definition: lpt.h:589
std::vector< std::unique_ptr< MFloat[]> > m_recvBuffer
Definition: lpt.h:611
std::vector< std::unique_ptr< MFloat[]> > m_sourceSend
Definition: lpt.h:584
MFloat ** m_slopesRecv
Definition: lpt.h:598
std::vector< MInt > m_checkAdaptationRecv
Definition: lpt.h:588
MPI_Request * m_flowSendRequest
Definition: lpt.h:591
MFloat ** m_flowRecv
Definition: lpt.h:593
std::vector< std::unique_ptr< MFloat[]> > m_sourceRecv
Definition: lpt.h:583
MFloat ** m_slopesSend
Definition: lpt.h:599
std::vector< std::unique_ptr< MInt[]> > m_intRecvBuffer
Definition: lpt.h:613
std::vector< MPI_Status > m_mpi_statusProbe
Definition: lpt.h:609
MInt * m_respawnGlobalDomainOffsets
Definition: lpt.h:786
MInt bufSize()
Definition: lpt.h:679
MPI_Request * m_slopesRecvRequest
Definition: lpt.h:597
MPI_Request * m_slopesSendRequest
Definition: lpt.h:596
std::vector< MInt > m_respawnCells
Definition: lpt.h:787
std::vector< MPI_Request > m_mpi_reqRecvFloat
Definition: lpt.h:607
MPI_Request * m_sourceRecvRequest
Definition: lpt.h:582
std::vector< MPI_Request > m_mpi_reqSendSize
Definition: lpt.h:606
MPI_Request * m_sourceSendRequest
Definition: lpt.h:581
MInt m_respawnDomain
Definition: lpt.h:783
MPI_Request * m_flowRecvRequest
Definition: lpt.h:592
std::vector< MPI_Request > m_mpi_reqSendInt
Definition: lpt.h:605
MFloat ** m_flowSend
Definition: lpt.h:594
MInt * m_respawnDomainRanks
Definition: lpt.h:785
std::vector< MInt > m_sendSize
Definition: lpt.h:601
MInt m_noSourceTerms
Definition: lpt.h:580
std::vector< MInt > m_recvSize
Definition: lpt.h:602
int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gather
constexpr MInt noVars() const
Definition: lpt.h:1027

◆ initParticleLog()

template<MInt nDim>
void LPT< nDim >::initParticleLog ( )
private

◆ initParticleVector()

template<MInt nDim>
void LPT< nDim >::initParticleVector ( )
private
Author
Tim Wegmann
Date
August 2021

◆ initSolver()

template<MInt nDim>
void LPT< nDim >::initSolver
overridevirtual

Implements Solver.

Definition at line 53 of file lpt.cpp.

53 {
54
55 m_time = 0.0;
56
57 // 1) read all properties
59
60 // deleted in new version
61 // readAdditionalProperties();
62
64
65 if(m_evaporation) {
67 }
68
69 if(m_ellipsoids) {
71 }
72
73 // load properties related to intial generation of particles
76 }
77
80 }
81 if(m_ellipsoids) {
83 }
84
86
88 m_sprayModel = std::unique_ptr<SprayModel<nDim>>(new SprayModel<nDim>());
89 m_sprayModel->init(this);
90 m_log << "Spray model has been activated." << std::endl;
91 }
92
93 // If solver inactive only add dummy cells and mark all cells as halo cells
94 // Inactive solvers can not have internal cells
95 if(!isActive()) {
96 m_cells.clear();
97 m_cells.reset(grid().maxNoCells());
100 return;
101 }
102
104
106
108
110
112 grid().updateLeafCellExchange();
113 initMPI();
114
115 grid().findEqualLevelNeighborsParDiagonal(false);
116
118
121 }
122
124
125 // LPT-statistics
126 MInt noCells = a_noCells();
127 MInt minCells = noCells;
128 MInt maxCells = noCells;
129 MInt noPart = a_noParticles();
130 MInt minParts = noPart;
131 MInt maxParts = noPart;
132
133 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noCells");
134 MPI_Allreduce(MPI_IN_PLACE, &noPart, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noPart");
135 MPI_Allreduce(MPI_IN_PLACE, &maxCells, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxCells");
136 MPI_Allreduce(MPI_IN_PLACE, &minCells, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minCells");
137 MPI_Allreduce(MPI_IN_PLACE, &maxParts, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "maxParts");
138 MPI_Allreduce(MPI_IN_PLACE, &minParts, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "INPLACE", "minParts");
139
140 if(domainId() == 0) {
141 cerr << "LPT cell-statistics : " << minCells << " - " << maxCells << " avg " << noCells / noDomains() << endl;
142 cerr << "LPT particle-statistics : " << minParts << " - " << maxParts << " avg " << noPart / noDomains() << endl;
143 }
144}
void readSpawnProps()
Read properties related to creating particles from configuration file.
void initGridProperties()
calculate Grid Properties for periodic boundaries, adapted from rigedbodies
Definition: lpt.cpp:603
void readMomentumCouplingProps()
Read properties specific to the momentum coupling.
void readEllipsoidProps()
Read properties specific to ellipsoids.
void initialCondition()
Initialize particles.
void initBndryCells()
init LPT boundary-cells used for the wall-collision
Definition: lpt.cpp:352
void initParticleVector()
init LPT spherical and ellipsoids particle vectors (i.e. set length and read non-dimensionalisation P...
void readModelProps()
Read model configuration properties from configuration file.
void setLptCollectorCoupling(const MBool mass, const MBool momentum, const MBool heat)
Set the lpt-collector type.
void setLptCollectorNoSpecies(const MInt noSpecies)

◆ initSummary()

template<MInt nDim>
void LPT< nDim >::initSummary
private
Author
Sven Berger
Date
January 2018

Definition at line 5778 of file lpt.cpp.

5778 {
5779 cerr << "//////////////////////////////////////////////////////////////////////////////////////////////////" << endl;
5780 cerr << "/// Particle INITIALISATION INFORMATION ///" << endl;
5781 cerr << "///--------------------------------------------------------------------------------------------///" << endl;
5782 cerr << "spawning is active : " << boolalpha << m_spawnParticles << endl;
5783 cerr << "spray model is active : " << boolalpha << (MBool)(m_activePrimaryBUp || m_activeSecondaryBUp)
5784 << endl;
5785 cerr << "momentum coupling is active : " << boolalpha << m_momentumCoupling << endl;
5787 cerr << " * redistribution is active : " << boolalpha << m_couplingRedist << endl;
5788 cerr << " - redistribution area is set to : " << m_noRedistLayer << endl;
5789 }
5790 cerr << "drag modelling is active : " << boolalpha << (m_dragModelType > 0) << endl;
5791 if(m_dragModelType > 0) {
5792 cerr << " * drag model used is : " << m_dragModelType << endl;
5793 }
5794 if(m_ellipsoids) {
5795 cerr << "lift modelling is active : " << boolalpha << (m_liftModelType > 0) << endl;
5796 if(m_liftModelType > 0) {
5797 cerr << " * lift model used is : " << m_liftModelType << endl;
5798 }
5799 cerr << "torque modelling is active : " << boolalpha << (m_torqueModelType > 0) << endl;
5800 if(m_torqueModelType > 0) {
5801 cerr << " * torque model used is : " << m_torqueModelType << endl;
5802 }
5803 }
5804 cerr << "//////////////////////////////////////////////////////////////////////////////////////////////////" << endl;
5805}
MInt m_liftModelType
Definition: lpt.h:776
MInt m_dragModelType
Definition: lpt.h:775
MInt m_torqueModelType
Definition: lpt.h:777

◆ injectionDuration()

template<MInt nDim>
MFloat LPT< nDim >::injectionDuration ( ) const
inline

Definition at line 477 of file lpt.h.

477{ return m_sprayModel != nullptr ? m_sprayModel->injectionDuration() : m_time; }

◆ injectorCellId()

template<MInt nDim>
MInt LPT< nDim >::injectorCellId ( ) const
inline

Definition at line 481 of file lpt.h.

481 {
482 if(m_sprayModel != nullptr) return m_spawnCellId;
483 if(domainId() == 0) {
484 return 1;
485 } else {
486 return -1;
487 }
488 }

◆ intBufSize()

template<MInt nDim>
template<class LPTParticle >
MInt LPT< nDim >::intBufSize ( )
inlineprotected

Definition at line 683 of file lpt.h.

683 {
684 return m_exchangeBufferSize * intElemPerP<LPTParticle>() + 1;
685 }

◆ intElemPerP()

template<MInt nDim>
template<class LPTParticle >
MInt LPT< nDim >::intElemPerP ( )
inlineprotected

Definition at line 675 of file lpt.h.

675 {
676 return LPTParticle::s_intElements + LPTBase<nDim>::s_intElements;
677 }

◆ interpolateAndCalcWeights()

template<MInt nDim>
template<class P , MInt a, MInt b>
void LPT< nDim >::interpolateAndCalcWeights ( P &  particle,
const MInt  cellId,
const MFloat position,
const MFloat interpolatedVar,
std::vector< MFloat > &  weight 
)

◆ interpolateVariablesLS() [1/2]

template<MInt nDim>
template<MInt a, MInt b, MBool interpolateVelocitySlopes>
void LPT< nDim >::interpolateVariablesLS ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  interpolatedVar 
)
Author
Sven Berger, update Laurent Andre
Date
January 2016, August 2022
Parameters
[in]cellIdid of the cell used for interpolation
[in]positioninterpolation point
[out]interpolatedVararray containing the interpolated variables
  1. Find all direct neighboring cells

2a. if only a low number of neighbors is found use distance weighted averaging

2b. build the least square matrix LSMatrix...

  1. Build rhs and solve the LS problem
  2. determine solution

Definition at line 8063 of file lpt.cpp.

8063 {
8064 ASSERT((b - a) > 0, "ERROR: Difference between b and a needs to be positive!");
8065 ASSERT(cellId >= 0, "ERROR: Invalid cellId!");
8066
8067 const MFloat originX = c_coordinate(cellId, 0);
8068 const MFloat originY = c_coordinate(cellId, 1);
8069 const MFloat originZ = c_coordinate(cellId, 2);
8070
8074 std::vector<MInt> nghbrList;
8075#ifdef _OPENMP
8076#pragma omp critical
8077#endif
8078 {
8079 if(m_cellToNghbrHoodInterpolation.count(cellId) > 0) {
8081 // std::cout << "New use existing hood with " << nghbrList.size() << " for " << cellId << std::endl;
8082 } else {
8083 grid().findDirectNghbrs(cellId, nghbrList);
8084 // std::cout << "New find hood with " << nghbrList.size() << std::endl;
8085 if(nghbrList.size() < 12) {
8086 // std::cout << "New find better hood with " << nghbrList.size() << std::endl;
8087 grid().findNeighborHood(cellId, 2, nghbrList);
8088#ifndef NDEBUG
8089 if(nghbrList.size() < 14) {
8090 std::cout << "WARNING: Only found " << nghbrList.size() << " neighbors during interpolation!" << std::endl;
8091 }
8092#endif
8093 }
8094 m_cellToNghbrHoodInterpolation.emplace(make_pair(cellId, nghbrList));
8095 }
8096 }
8097
8098 const MInt pseudoVarCount = (interpolateVelocitySlopes ? nDim * nDim + b - a : b - a);
8099 std::vector<std::array<MFloat, pseudoVarCount>> pseudoCellVar{};
8100 std::vector<std::array<MFloat, nDim>> pseudoCellPos{};
8101
8102 auto nghbrIt = nghbrList.begin();
8103 while(nghbrIt != nghbrList.end()) {
8104 const MInt nghbrId = *nghbrIt;
8105 const MInt bndryCellId = a_bndryCellId(nghbrId);
8106 if(bndryCellId > -1) {
8107 const auto& bndryCell = m_bndryCells->a[bndryCellId];
8108 for(MInt srfcId = 0; srfcId < bndryCell.m_noSrfcs; srfcId++) {
8109 auto& srfc = *bndryCell.m_srfcs[srfcId];
8110 pseudoCellPos.emplace_back();
8111 auto& pos = pseudoCellPos.back();
8112 for(MInt n = 0; n < nDim; n++) {
8113 pos[n] = srfc.m_coordinates[n];
8114 }
8115 // TODO labels:LPT Distinguish between different boundary condtions
8116 pseudoCellVar.emplace_back();
8117 auto& vars = pseudoCellVar.back();
8118 for(MInt i = a; i < b; i++) {
8119 vars[i] = a_fluidVariable(nghbrId, i);
8120 }
8121 if(interpolateVelocitySlopes) {
8122 for(MInt i = 0; i < nDim; i++) {
8123 for(MInt j = 0; j < nDim; j++) {
8124 vars[b + nDim * i + j] = a_velocitySlope(nghbrId, i, j);
8125 }
8126 }
8127 }
8128 }
8129 nghbrIt = nghbrList.erase(nghbrIt);
8130 } else {
8131 ++nghbrIt;
8132 }
8133 }
8134
8135 const MUint noInterpolationPoints = nghbrList.size() + pseudoCellPos.size();
8136
8140 if(noInterpolationPoints < 10) {
8141 std::vector<MFloat> dist(noInterpolationPoints, 0);
8142 // Internal cells
8143 for(MUint nId = 0; nId < nghbrList.size(); nId++) {
8144 const MInt nghbrId = nghbrList[nId];
8145 dist[nId] = 0;
8146 for(MInt i = 0; i < nDim; i++) {
8147 dist[nId] += POW2(c_coordinate(nghbrId, i) - position[i]);
8148 }
8149 }
8150 // Boundary surfaces
8151 for(MUint pId = 0; pId < pseudoCellPos.size(); pId++) {
8152 IF_CONSTEXPR(nDim == 2) {
8153 dist[pId + nghbrList.size()] =
8154 POW2(pseudoCellPos[pId][0] - position[0]) + POW2(pseudoCellPos[pId][1] - position[1]);
8155 }
8156 else {
8157 dist[pId + nghbrList.size()] = POW2(pseudoCellPos[pId][0] - position[0])
8158 + POW2(pseudoCellPos[pId][1] - position[1])
8159 + POW2(pseudoCellPos[pId][2] - position[2]);
8160 }
8161 }
8162
8163 MFloat sum = std::accumulate(dist.begin(), dist.end(), 0.0);
8164
8165 for(MInt k = a; k < b; k++) {
8166 MFloat var = 0;
8167 interpolatedVar[k] = 0.0;
8168
8169 // Internal cells
8170 for(MUint nId = 0; nId < nghbrList.size(); nId++) {
8171 const MInt nghbrId = nghbrList[nId];
8172 var = a_fluidVariable(nghbrId, k);
8173 interpolatedVar[k] += dist[nId] / sum * var;
8174 }
8175 // Boundary surfaces
8176 for(MUint pId = 0; pId < pseudoCellPos.size(); pId++) {
8177 var = pseudoCellVar[pId][k - a];
8178 interpolatedVar[k] += dist[pId + nghbrList.size()] / sum * var;
8179 }
8180 }
8181
8182 // interpolate velocity slopes
8183 if(interpolateVelocitySlopes) {
8184 for(MInt i = 0; i < nDim; i++) {
8185 for(MInt j = 0; j < nDim; j++) {
8186 MFloat var = 0;
8187 interpolatedVar[b + nDim * i + j - a] = 0.0;
8188 // Internal cells
8189 for(MUint nId = 0; nId < nghbrList.size(); nId++) {
8190 const MInt nghbrId = nghbrList[nId];
8191 var = a_velocitySlope(nghbrId, i, j);
8192 interpolatedVar[b + nDim * i + j - a] += dist[nId] / sum * var;
8193 }
8194 // Boundary surfaces
8195 for(MUint pId = 0; pId < pseudoCellPos.size(); pId++) {
8196 var = pseudoCellVar[pId][nDim * i + j + b];
8197 interpolatedVar[b + nDim * i + j - a] += dist[pId + nghbrList.size()] / sum * var;
8198 }
8199 }
8200 }
8201 }
8202
8203#ifndef NDEBUG
8204 // cout << "WARNING: Not enough neighbors found to use LS using weighted averaging instead!" << endl;
8205 m_log << "WARNING: Not enough neighbors found to use LS using weighted averaging instead!" << std::endl;
8206#endif
8207 } else {
8211 MFloatTensor LSMatrix(2 * nDim + pow(2, nDim - 1), 2 * nDim + pow(2, nDim - 1));
8212 MFloatTensor rhs(2 * nDim + pow(2, nDim - 1));
8213 // MFloatTensor weights(2 * nDim + pow(2, nDim - 1));
8214 MFloatTensor matInv(2 * nDim + pow(2, nDim - 1), 2 * nDim + pow(2, nDim - 1));
8215
8216 LSMatrix.set(0.0);
8217 // weights.set(1.0);
8218 matInv.set(0.0);
8219
8220 MFloat sumX = 0;
8221 MFloat sumY = 0;
8222 MFloat sumZ = 0;
8223 MFloat sumXY = 0;
8224 MFloat sumXZ = 0;
8225 MFloat sumYZ = 0;
8226 MFloat sumX2 = 0;
8227 MFloat sumY2 = 0;
8228 MFloat sumZ2 = 0;
8229 MFloat sumXYZ = 0;
8230 MFloat sumX2Y = 0;
8231 MFloat sumX2Z = 0;
8232 MFloat sumXY2 = 0;
8233 MFloat sumY2Z = 0;
8234 MFloat sumXZ2 = 0;
8235 MFloat sumYZ2 = 0;
8236 MFloat sumX3 = 0;
8237 MFloat sumY3 = 0;
8238 MFloat sumZ3 = 0;
8239 MFloat sumX3Y = 0;
8240 MFloat sumX3Z = 0;
8241 MFloat sumXY3 = 0;
8242 MFloat sumY3Z = 0;
8243 MFloat sumXZ3 = 0;
8244 MFloat sumYZ3 = 0;
8245 MFloat sumX2Y2 = 0;
8246 MFloat sumX2Z2 = 0;
8247 MFloat sumX2YZ = 0;
8248 MFloat sumY2Z2 = 0;
8249 MFloat sumXY2Z = 0;
8250 MFloat sumXYZ2 = 0;
8251 MFloat sumX4 = 0;
8252 MFloat sumY4 = 0;
8253 MFloat sumZ4 = 0;
8254
8255
8256 // 2.1 Calculate intermediate variables
8257 for(MUint nId = 1; nId < noInterpolationPoints; nId++) {
8258 MFloat x = 0;
8259 MFloat y = 0;
8260 MFloat z = 0;
8261 if(nId >= nghbrList.size()) {
8262 const MUint pId = nId - nghbrList.size();
8263 x = pseudoCellPos[pId][0] - originX;
8264 y = pseudoCellPos[pId][1] - originY;
8265 IF_CONSTEXPR(nDim == 3) { z = pseudoCellPos[pId][2] - originZ; }
8266 } else {
8267 const MInt nghbrId = nghbrList[nId];
8268 x = c_coordinate(nghbrId, 0) - originX;
8269 y = c_coordinate(nghbrId, 1) - originY;
8270 IF_CONSTEXPR(nDim == 3) { z = c_coordinate(nghbrId, 2) - originZ; }
8271 }
8272
8273 sumX += x;
8274 sumY += y;
8275 sumZ += z;
8276 sumXY += x * y;
8277 sumXZ += x * z;
8278 sumYZ += y * z;
8279 sumX2 += x * x;
8280 sumY2 += y * y;
8281 sumZ2 += z * z;
8282 sumXYZ += x * y * z;
8283 sumX2Y += x * x * y;
8284 sumX2Z += x * x * z;
8285 sumXY2 += x * y * y;
8286 sumY2Z += y * y * z;
8287 sumXZ2 += z * z * x;
8288 sumYZ2 += z * z * y;
8289 sumX3 += x * x * x;
8290 sumY3 += y * y * y;
8291 sumZ3 += z * z * z;
8292 sumX3Y += x * x * x * y;
8293 sumX3Z += x * x * x * z;
8294 sumXY3 += y * y * y * x;
8295 sumY3Z += y * y * y * z;
8296 sumXZ3 += z * z * z * x;
8297 sumYZ3 += z * z * z * y;
8298 sumX2Y2 += x * x * y * y;
8299 sumX2Z2 += x * x * z * z;
8300 sumX2YZ += x * x * y * z;
8301 sumY2Z2 += y * y * z * z;
8302 sumXY2Z += x * y * y * z;
8303 sumXYZ2 += x * y * z * z;
8304 sumX4 += x * x * x * x;
8305 sumY4 += y * y * y * y;
8306 sumZ4 += z * z * z * z;
8307 }
8308
8309 // 2.2 Use intermediate variables to build LSMatrix
8310 IF_CONSTEXPR(nDim == 2) {
8311 // diagonal
8312 LSMatrix(0, 0) = sumX4;
8313 LSMatrix(1, 1) = sumY4;
8314 LSMatrix(2, 2) = sumX2Y2;
8315 LSMatrix(3, 3) = sumX2;
8316 LSMatrix(4, 4) = sumY2;
8317 LSMatrix(5, 5) = noInterpolationPoints;
8318
8319 // first column/row
8320 LSMatrix(0, 1) = LSMatrix(1, 0) = sumX2Y2;
8321 LSMatrix(0, 2) = LSMatrix(2, 0) = sumX3Y;
8322 LSMatrix(0, 3) = LSMatrix(3, 0) = sumX3;
8323 LSMatrix(0, 4) = LSMatrix(4, 0) = sumX2Y;
8324 LSMatrix(0, 5) = LSMatrix(5, 0) = sumX2;
8325
8326 // second column/row
8327 LSMatrix(1, 2) = LSMatrix(2, 1) = sumXY3;
8328 LSMatrix(1, 3) = LSMatrix(3, 1) = sumXY2;
8329 LSMatrix(1, 4) = LSMatrix(4, 1) = sumY3;
8330 LSMatrix(1, 5) = LSMatrix(5, 1) = sumY2;
8331
8332 // third column/row
8333 LSMatrix(2, 3) = LSMatrix(3, 2) = sumX2Y;
8334 LSMatrix(2, 4) = LSMatrix(4, 2) = sumXY2;
8335 LSMatrix(2, 5) = LSMatrix(5, 2) = sumXY;
8336
8337 // fourth column/row
8338 LSMatrix(3, 4) = LSMatrix(4, 3) = sumXY;
8339 LSMatrix(3, 5) = LSMatrix(5, 3) = sumX;
8340
8341 // fifth coulmn/row
8342 LSMatrix(4, 5) = LSMatrix(5, 4) = sumY;
8343 }
8344 else {
8345 // diagonal
8346 LSMatrix(0, 0) = sumX4;
8347 LSMatrix(1, 1) = sumY4;
8348 LSMatrix(2, 2) = sumZ4;
8349 LSMatrix(3, 3) = sumX2Y2;
8350 LSMatrix(4, 4) = sumX2Z2;
8351 LSMatrix(5, 5) = sumY2Z2;
8352 LSMatrix(6, 6) = sumX2;
8353 LSMatrix(7, 7) = sumY2;
8354 LSMatrix(8, 8) = sumZ2;
8355 LSMatrix(9, 9) = noInterpolationPoints;
8356
8357 // first column/row
8358 LSMatrix(0, 1) = LSMatrix(1, 0) = sumX2Y2;
8359 LSMatrix(0, 2) = LSMatrix(2, 0) = sumX2Z2;
8360 LSMatrix(0, 3) = LSMatrix(3, 0) = sumX3Y;
8361 LSMatrix(0, 4) = LSMatrix(4, 0) = sumX3Z;
8362 LSMatrix(0, 5) = LSMatrix(5, 0) = sumX2YZ;
8363 LSMatrix(0, 6) = LSMatrix(6, 0) = sumX3;
8364 LSMatrix(0, 7) = LSMatrix(7, 0) = sumX2Y;
8365 LSMatrix(0, 8) = LSMatrix(8, 0) = sumX2Z;
8366 LSMatrix(0, 9) = LSMatrix(9, 0) = sumX2;
8367
8368 // second column/row
8369 LSMatrix(1, 2) = LSMatrix(2, 1) = sumY2Z2;
8370 LSMatrix(1, 3) = LSMatrix(3, 1) = sumXY3;
8371 LSMatrix(1, 4) = LSMatrix(4, 1) = sumXY2Z;
8372 LSMatrix(1, 5) = LSMatrix(5, 1) = sumY3Z;
8373 LSMatrix(1, 6) = LSMatrix(6, 1) = sumXY2;
8374 LSMatrix(1, 7) = LSMatrix(7, 1) = sumY3;
8375 LSMatrix(1, 8) = LSMatrix(8, 1) = sumY2Z;
8376 LSMatrix(1, 9) = LSMatrix(9, 1) = sumY2;
8377
8378 // third column/row
8379 LSMatrix(2, 3) = LSMatrix(3, 2) = sumXYZ2;
8380 LSMatrix(2, 4) = LSMatrix(4, 2) = sumXZ3;
8381 LSMatrix(2, 5) = LSMatrix(5, 2) = sumYZ3;
8382 LSMatrix(2, 6) = LSMatrix(6, 2) = sumXZ2;
8383 LSMatrix(2, 7) = LSMatrix(7, 2) = sumYZ2;
8384 LSMatrix(2, 8) = LSMatrix(8, 2) = sumZ3;
8385 LSMatrix(2, 9) = LSMatrix(9, 2) = sumZ2;
8386
8387 // fourth column, fourth line
8388 LSMatrix(3, 4) = LSMatrix(4, 3) = sumX2YZ;
8389 LSMatrix(3, 5) = LSMatrix(5, 3) = sumXY2Z;
8390 LSMatrix(3, 6) = LSMatrix(6, 3) = sumX2Y;
8391 LSMatrix(3, 7) = LSMatrix(7, 3) = sumXY2;
8392 LSMatrix(3, 8) = LSMatrix(8, 3) = sumXYZ;
8393 LSMatrix(3, 9) = LSMatrix(9, 3) = sumXY;
8394
8395 // fifth coulmn, fifth line
8396 LSMatrix(4, 5) = LSMatrix(5, 4) = sumXYZ2;
8397 LSMatrix(4, 6) = LSMatrix(6, 4) = sumX2Z;
8398 LSMatrix(4, 7) = LSMatrix(7, 4) = sumXYZ;
8399 LSMatrix(4, 8) = LSMatrix(8, 4) = sumXZ2;
8400 LSMatrix(4, 9) = LSMatrix(9, 4) = sumXZ;
8401
8402 // sixth column, sixth line
8403 LSMatrix(5, 6) = LSMatrix(6, 5) = sumXYZ;
8404 LSMatrix(5, 7) = LSMatrix(7, 5) = sumY2Z;
8405 LSMatrix(5, 8) = LSMatrix(8, 5) = sumYZ2;
8406 LSMatrix(5, 9) = LSMatrix(9, 5) = sumYZ;
8407
8408 // seventh column, seventh line
8409 LSMatrix(6, 7) = LSMatrix(7, 6) = sumXY;
8410 LSMatrix(6, 8) = LSMatrix(8, 6) = sumXZ;
8411 LSMatrix(6, 9) = LSMatrix(9, 6) = sumX;
8412
8413 // eigth column, eigth line
8414 LSMatrix(7, 8) = LSMatrix(8, 7) = sumYZ;
8415 LSMatrix(7, 9) = LSMatrix(9, 7) = sumY;
8416
8417 // nineth column, nineth line
8418 LSMatrix(8, 9) = LSMatrix(9, 8) = sumZ;
8419 }
8420
8421 // 2.3 scale solution since the condition number gets really bad for large discrepancies in cell size
8422 const MFloat normalizationFactor = FPOW2(2 * c_level(cellId)) / c_cellLengthAtLevel(0);
8423 for(MInt i = 0; i < 2 * nDim + pow(2, nDim - 1); i++) {
8424 for(MInt j = 0; j < 2 * nDim + pow(2, nDim - 1); j++) {
8425 LSMatrix(i, j) *= normalizationFactor;
8426 }
8427 }
8428
8429 // 2.4 determine the pseudoinverse using SVD
8430 maia::math::invert(LSMatrix, matInv, 2 * nDim + pow(2, nDim - 1), 2 * nDim + pow(2, nDim - 1));
8431
8435 const MInt totalNumberOfVars = interpolateVelocitySlopes ? b + nDim * nDim : b;
8436 for(MInt k = a; k < totalNumberOfVars; k++) {
8437 MFloat sumVar = 0;
8438 if(k < b) {
8439 sumVar = a_fluidVariable(cellId, k);
8440 } else {
8441 sumVar = a_velocitySlope(cellId, std::floor((k - b) / 3), (k - b) % 3);
8442 }
8443 MFloat sumVarX = 0;
8444 MFloat sumVarY = 0;
8445 MFloat sumVarZ = 0;
8446 MFloat sumVarXY = 0;
8447 MFloat sumVarXZ = 0;
8448 MFloat sumVarYZ = 0;
8449 MFloat sumVarX2 = 0;
8450 MFloat sumVarY2 = 0;
8451 MFloat sumVarZ2 = 0;
8452
8453 rhs.set(0.0);
8454
8455 // 3.1 Calculate intermediate variables
8456 for(MUint nId = 1; nId < noInterpolationPoints; nId++) {
8457 MFloat x = 0;
8458 MFloat y = 0;
8459 MFloat z = 0;
8460 MFloat var = 0;
8461 if(nId >= nghbrList.size()) {
8462 const MUint pId = nId - nghbrList.size();
8463 x = pseudoCellPos[pId][0] - originX;
8464 y = pseudoCellPos[pId][1] - originY;
8465 var = pseudoCellVar[pId][k - a];
8466 IF_CONSTEXPR(nDim == 3) { z = pseudoCellPos[pId][2] - originZ; }
8467 } else {
8468 const MInt nghbrId = nghbrList[nId];
8469 x = c_coordinate(nghbrId, 0) - originX;
8470 y = c_coordinate(nghbrId, 1) - originY;
8471 if(k < b) {
8472 var = a_fluidVariable(nghbrId, k);
8473 } else {
8474 var = a_velocitySlope(nghbrId, std::floor((k - b) / 3), (k - b) % 3);
8475 }
8476 IF_CONSTEXPR(nDim == 3) { z = c_coordinate(nghbrId, 2) - originZ; }
8477 }
8478
8479 sumVar += var;
8480 sumVarX += var * x;
8481 sumVarY += var * y;
8482 sumVarZ += var * z;
8483 sumVarXY += var * x * y;
8484 sumVarXZ += var * x * z;
8485 sumVarYZ += var * y * z;
8486 sumVarX2 += var * x * x;
8487 sumVarY2 += var * y * y;
8488 sumVarZ2 += var * z * z;
8489 }
8490
8491 // 3.2 assign intermediate variables to rhs
8492 IF_CONSTEXPR(nDim == 2) {
8493 rhs[0] = sumVarX2;
8494 rhs[1] = sumVarY2;
8495 rhs[2] = sumVarXY;
8496 rhs[3] = sumVarX;
8497 rhs[4] = sumVarY;
8498 rhs[5] = sumVar;
8499 }
8500 else {
8501 rhs(0) = sumVarX2;
8502 rhs(1) = sumVarY2;
8503 rhs(2) = sumVarZ2;
8504 rhs(3) = sumVarXY;
8505 rhs(4) = sumVarXZ;
8506 rhs(5) = sumVarYZ;
8507 rhs(6) = sumVarX;
8508 rhs(7) = sumVarY;
8509 rhs(8) = sumVarZ;
8510 rhs(9) = sumVar;
8511 }
8512
8513 // 3.3 scale rhs
8514 for(MInt i = 0; i < 2 * nDim + pow(2, nDim - 1); i++) {
8515 rhs(i) *= normalizationFactor;
8516 }
8517
8518 MFloatTensor coeff(2 * nDim + pow(2, nDim - 1));
8519 coeff.set(F0);
8520
8521 // 3.4 determine coefficients of the aim function polynomial
8522 for(MInt i = 0; i < 2 * nDim + pow(2, nDim - 1); i++) {
8523 for(MInt j = 0; j < 2 * nDim + pow(2, nDim - 1); j++) {
8524 coeff(i) += matInv(i, j) * rhs(j);
8525 }
8526 }
8527
8531 MFloat positionX = position[0] - originX;
8532 MFloat positionY = position[1] - originY;
8533 MFloat positionZ = 0;
8534 IF_CONSTEXPR(nDim == 3) { positionZ = position[2] - originZ; }
8535 MFloat result = coeff((MInt)(2 * nDim + pow(2, nDim - 1) - 1));
8536 IF_CONSTEXPR(nDim == 2) {
8537 result += coeff(0) * positionX * positionX;
8538 result += coeff(1) * positionY * positionY;
8539 result += coeff(2) * positionX * positionY;
8540 result += coeff(3) * positionX;
8541 result += coeff(4) * positionY;
8542 }
8543 else {
8544 result += coeff(0) * positionX * positionX;
8545 result += coeff(1) * positionY * positionY;
8546 result += coeff(2) * positionZ * positionZ;
8547 result += coeff(3) * positionX * positionY;
8548 result += coeff(4) * positionX * positionZ;
8549 result += coeff(5) * positionY * positionZ;
8550 result += coeff(6) * positionX;
8551 result += coeff(7) * positionY;
8552 result += coeff(8) * positionZ;
8553 }
8554
8555 interpolatedVar[k - a] = result;
8556 }
8557 }
8558
8559 // TRACE_OUT();
8560}
MFloat & a_fluidVariable(const MInt cellId, const MInt var)
Definition: lpt.h:394
constexpr MFloat FPOW2(MInt x)
uint32_t MUint
Definition: maiatypes.h:63
void invert(MFloat *A, const MInt m, const MInt n)
Definition: maiamath.cpp:171
Definition: contexttypes.h:19
define array structures

◆ interpolateVariablesLS() [2/2]

template<MInt nDim>
template<MInt a, MInt b>
void LPT< nDim >::interpolateVariablesLS ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  interpolatedVar 
)
inline

Definition at line 472 of file lpt.h.

472 {
473 interpolateVariablesLS<a, b, false>(cellId, position, interpolatedVar);
474 }

◆ limitWeights()

template<MInt nDim>
void LPT< nDim >::limitWeights ( MFloat weights)
override
Author
Tim Wegmann

Definition at line 1919 of file lpt.cpp.

1919 {
1920 if(m_limitWeights) {
1921 weights[0] = mMax(weights[0], 0.01 * weights[1]);
1922 }
1923}
MBool m_limitWeights
Definition: lpt.h:552

◆ loadParticleRestartFile()

template<MInt nDim>
MInt LPT< nDim >::loadParticleRestartFile
protected
Author
Jerry Grimmen, Apr-10

Definition at line 4822 of file lpt.cpp.

4822 {
4823 TRACE();
4824
4825 // if(grid().hasInactiveRanks()) {
4826 grid().updatePartitionCellOffsets();
4827 //}
4828
4829 using namespace maia::parallel_io;
4830
4831 // Open collective Netcdf file.
4832 MString particleRestartFilename =
4833 restartDir() + "restartPart_" + getIdentifier() + to_string(globalTimeStep) + ParallelIo::fileExt();
4834
4835 // 1. Loading spherical particles
4836 {
4837 // check if file exists
4838 struct stat buffer {};
4839 if(stat(particleRestartFilename.c_str(), &buffer) != 0) {
4840 if(domainId() == 0) {
4841 cerr << "WARNING: starting with restart but no particle file present!" << endl;
4842 m_log << "WARNING: starting with restart but no particle file present!" << endl;
4843 }
4844 m_restartFile = false;
4845 return 0;
4846 }
4847
4848 // check that the timeStep in the restart-file matches the current globalTimeStep!
4849 MFloat loadedTimeStep = 0;
4850 ParallelIo parallelIo(particleRestartFilename, PIO_READ, mpiComm());
4851
4852 parallelIo.getAttribute(&loadedTimeStep, "timestep");
4853 if(MInt(loadedTimeStep) != globalTimeStep) {
4854 stringstream errorMessage;
4855 errorMessage << "Error! restartTimeStep = " << globalTimeStep << " differs from timestep in restartPart"
4856 << ParallelIo::fileExt() << ", which is " << loadedTimeStep << endl;
4857 mTerm(1, AT_, errorMessage.str());
4858 }
4859
4860 parallelIo.getAttribute(&m_time, "time");
4861
4863 parallelIo.getAttribute(&m_sprayModel->m_injStep, "injStep");
4864 parallelIo.getAttribute(&m_sprayModel->timeSinceSOI(), "timeSinceSOI");
4865 }
4866
4867
4868 // Get the number of particle each domain has.
4869 const MInt noGlobalPartitionCells = grid().localPartitionCellOffsetsRestart(2);
4870 const MInt localPartitionCellBeginning = grid().localPartitionCellOffsetsRestart(0);
4871 const MInt localPartitionCellEnd = grid().localPartitionCellOffsetsRestart(1);
4872
4873 MIntScratchSpace noParticlesPerPartitionCell(noGlobalPartitionCells, AT_, "noParticlesPerPartitionCell");
4874
4875 if(domainId() == 0) {
4876 cerr << "noGlobalPartitionCells " << noGlobalPartitionCells << endl;
4877 }
4878
4879 // load number of particle in partition cell for all partition cells!
4880 parallelIo.setOffset(noGlobalPartitionCells, 0);
4881 parallelIo.readArray(&noParticlesPerPartitionCell[0], "partCount");
4882
4883 // total number of particles
4884 MInt numberOfParts = 0;
4885#ifdef _OPENMP
4886#pragma omp parallel for reduction(+ : numberOfParts)
4887#endif
4888 for(MInt i = 0; i < noGlobalPartitionCells; ++i) {
4889 numberOfParts += noParticlesPerPartitionCell[i];
4890 }
4891 if(domainId() == 0) {
4892 cerr << "Global number of particles loaded from restart file " << numberOfParts << endl;
4893 }
4894 m_log << "Global number of particles loaded from restart file " << numberOfParts << endl;
4895
4896
4899 if(domainId() == m_spawnDomainId) {
4900 parallelIo.getAttribute(&m_PRNGSpawnCount, "spawnCount");
4902
4903 m_log << "PRNG state after restart " << randomSpawn(0) << endl;
4904
4905 parallelIo.getAttribute(&m_particleResiduum, "particleResiduum");
4906 }
4907
4908 ParallelIo::size_type beginPartId = 0;
4909 beginPartId = 0;
4910 for(MInt i = 0; i < localPartitionCellBeginning; ++i) {
4911 beginPartId += noParticlesPerPartitionCell[i];
4912 }
4913
4914 MInt localNoPart = noParticlesPerPartitionCell[localPartitionCellBeginning];
4915 for(MInt i = (localPartitionCellBeginning + 1); i < localPartitionCellEnd; ++i) {
4916 localNoPart += noParticlesPerPartitionCell[i];
4917 }
4918
4919 MInt checkPartCount = 0;
4920 MPI_Allreduce(&localNoPart, &checkPartCount, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "localNoPart");
4921
4922 if(domainId() == 0 && checkPartCount != numberOfParts) {
4923 // numberOfParts is only set on the root-rank!
4924 TERM(-1);
4925 }
4926
4927 ASSERT(localNoPart >= 0, "ERROR: Invalid number of particles to be loaded during restart");
4928
4929 if(localNoPart == 0) {
4930 beginPartId = 0;
4931 }
4932 // if the last domain has nothing to load, beginPartId is
4933 // one index after the dimension of the array
4934
4935 // Preparing arrays and getting particle datas.
4936 if(numberOfParts > 0) {
4937 MLongScratchSpace ncmpiPartId(localNoPart, AT_, "ncmpiPartId");
4938 MFloatScratchSpace ncmpiDiameter(localNoPart, AT_, "ncmpiDiameter");
4939 MFloatScratchSpace ncmpiDensityRatio(localNoPart, AT_, "ncmpiDensityRatio");
4940 MIntScratchSpace ncmpiPartStatus(localNoPart, AT_, "ncmpiPartStatus");
4941 MFloatScratchSpace ncmpiPartCoords(3 * localNoPart, AT_, "PartCoords");
4942 MFloatScratchSpace ncmpiPartVel(3 * localNoPart, AT_, "ncmpiPartVel");
4943 MFloatScratchSpace ncmpiPartAccel(3 * localNoPart, AT_, "ncmpiPartAccel");
4944 MFloatScratchSpace ncmpiOldCoords(3 * localNoPart, AT_, "ncmpiOldCoords");
4945 MFloatScratchSpace ncmpiOldVel(3 * localNoPart, AT_, "ncmpiOldVel");
4946 MFloatScratchSpace ncmpiOldAccel(3 * localNoPart, AT_, "ncmpiOldAccel");
4947 MIntScratchSpace ncmpiPartParceledNo(localNoPart, AT_, "ncmpiPartParceledNo");
4948 MFloatScratchSpace ncmpiTemp(localNoPart, AT_, "ncmpiTemp");
4949 MFloatScratchSpace ncmpiDM(localNoPart, AT_, "ncmpiDM");
4950 MFloatScratchSpace ncmpiCT(localNoPart, AT_, "ncmpiCT");
4951 MFloatScratchSpace ncmpiBT(localNoPart, AT_, "ncmpiBT");
4952 MFloatScratchSpace ncmpiOldFluidDensity(localNoPart, AT_, "ncmpiOldFluidDensity");
4953 MFloatScratchSpace ncmpiOldFluidVelocity(3 * localNoPart, AT_, "ncmpiOldFluidVelocity");
4954 MFloatScratchSpace ncmpiShedD(localNoPart, AT_, "ncmpiShedD");
4955
4956 parallelIo.setOffset(localNoPart, beginPartId);
4957 parallelIo.readArray(ncmpiPartId.begin(), "partId");
4958 parallelIo.readArray(ncmpiDiameter.begin(), "partDia");
4959 // parallelIo.readArray(ncmpiDensityRatio.begin(), "partPpPf");
4960 parallelIo.readArray(ncmpiPartStatus.begin(), "partStatus");
4961 parallelIo.readArray(ncmpiPartParceledNo.begin(), "partParceledNo");
4962 parallelIo.readArray(ncmpiCT.begin(), "creationTime");
4963
4965 parallelIo.readArray(ncmpiBT.begin(), "breakUpTime");
4966 }
4967
4968
4970 parallelIo.readArray(ncmpiShedD.begin(), "shedD");
4971 }
4972
4974 parallelIo.readArray(ncmpiTemp.begin(), "partTemp");
4975 parallelIo.readArray(ncmpiDM.begin(), "partDM");
4976 }
4977 parallelIo.readArray(ncmpiOldFluidDensity.begin(), "oldFluidDensity");
4978
4979 ParallelIo::size_type ncmpi3Start = 3 * beginPartId;
4980 ParallelIo::size_type ncmpi3Count = 3 * localNoPart;
4981 parallelIo.setOffset(ncmpi3Count, ncmpi3Start);
4982 parallelIo.readArray(ncmpiPartCoords.begin(), "partPos");
4983 parallelIo.readArray(ncmpiPartVel.begin(), "partVel");
4984 parallelIo.readArray(ncmpiPartAccel.begin(), "partAccel");
4985 parallelIo.readArray(ncmpiOldFluidVelocity.begin(), "oldFluidVelocity");
4986
4987 LPTSpherical<nDim> thisParticle;
4988
4989 for(MLong i = 0; i < localNoPart; ++i) {
4990 thisParticle.m_position[0] = ncmpiPartCoords[(3 * i)];
4991 thisParticle.m_position[1] = ncmpiPartCoords[(3 * i) + 1];
4992 thisParticle.m_position[2] = ncmpiPartCoords[(3 * i) + 2];
4993 // find matching cellId
4994 const MInt cellId = grid().findContainingLeafCell(&thisParticle.m_position[0]);
4995 if(cellId == -1) continue;
4996 if(a_isHalo(cellId)) {
4997 cerr << "Particle in halo-cell!" << endl;
4998 continue;
4999 }
5000
5001 thisParticle.m_cellId = cellId;
5002 ASSERT(thisParticle.m_cellId >= 0, "Invalid cellId! " + to_string(thisParticle.m_cellId));
5003 ASSERT(c_isLeafCell(thisParticle.m_cellId), "No leaf cell... " + std::to_string(thisParticle.m_cellId));
5004
5005 thisParticle.m_partId = ncmpiPartId[i];
5006 thisParticle.m_noParticles = ncmpiPartParceledNo[i];
5007 thisParticle.m_temperature = ncmpiTemp[i];
5008 thisParticle.m_dM = ncmpiDM[i];
5009 thisParticle.m_creationTime = ncmpiCT[i];
5010 thisParticle.m_breakUpTime = ncmpiBT[i];
5011 thisParticle.m_diameter = ncmpiDiameter[i];
5012 thisParticle.m_densityRatio = ncmpiDensityRatio[i];
5013 thisParticle.firstStep() = (ncmpiPartStatus[i] > 0);
5014 thisParticle.m_velocity[0] = ncmpiPartVel[(3 * i)];
5015 thisParticle.m_velocity[1] = ncmpiPartVel[(3 * i) + 1];
5016 thisParticle.m_velocity[2] = ncmpiPartVel[(3 * i) + 2];
5017 thisParticle.m_accel[0] = ncmpiPartAccel[(3 * i)];
5018 thisParticle.m_accel[1] = ncmpiPartAccel[(3 * i) + 1];
5019 thisParticle.m_accel[2] = ncmpiPartAccel[(3 * i) + 2];
5020
5021 thisParticle.m_oldCellId = cellId;
5022 for(MInt j = 0; j < nDim; j++) {
5023 thisParticle.m_oldPos[j] = thisParticle.m_position[j];
5024 thisParticle.m_oldVel[j] = thisParticle.m_velocity[j];
5025 thisParticle.m_oldAccel[j] = thisParticle.m_accel[j];
5026 }
5027
5028 thisParticle.m_oldFluidDensity = ncmpiOldFluidDensity[i];
5029 for(MInt j = 0; j < nDim; j++) {
5030 thisParticle.m_oldFluidVel[j] = ncmpiOldFluidVelocity[(3 * i) + j];
5031 }
5032
5033 thisParticle.updateProperties();
5035 thisParticle.m_shedDiam = ncmpiShedD[i];
5036 } else {
5037 thisParticle.m_shedDiam = thisParticle.m_diameter;
5038 }
5039
5040 m_partList.push_back(thisParticle);
5041 }
5042
5043 MLong sumPart = 0;
5044 MLong noPart = a_noParticles();
5045 MPI_Allreduce(&noPart, &sumPart, 1, type_traits<MLong>::mpiType(), MPI_SUM, mpiComm(), AT_, "INPLACE", "sumpart");
5046
5047 // check if everything is loaded
5048 if(domainId() == 0) {
5049 cerr << "Loaded " << numberOfParts << " particles of " << sumPart << endl;
5050
5051 if(numberOfParts != sumPart) {
5052 TERMM(-1, "invalid number of particles loaded");
5053 }
5054 }
5055 }
5056 }
5057
5058 if(m_ellipsoids) {
5059 particleRestartFilename =
5060 restartDir() + "restartPartEllipsoid_" + getIdentifier() + to_string(globalTimeStep) + ParallelIo::fileExt();
5061
5062 ParallelIo parallelIo2(particleRestartFilename, PIO_READ, mpiComm());
5063
5064 MInt loadedTimeStep2 = 0;
5065 parallelIo2.getAttribute(&loadedTimeStep2, "timestep");
5066 if(loadedTimeStep2 != globalTimeStep) {
5067 stringstream errorMessage;
5068 errorMessage << endl
5069 << "Error! restartTimeStep = " << globalTimeStep
5070 << " differs from timestep in "
5071 "restartPartEllipsoid"
5072 << ParallelIo::fileExt() << ", which is " << loadedTimeStep2 << endl;
5073 mTerm(1, AT_, errorMessage.str());
5074 }
5075
5076 // Get the number of particle each domain has.
5077 const MInt noGlobalPartitionCells = grid().localPartitionCellOffsetsRestart(2);
5078 const MInt localPartitionCellBeginning = grid().localPartitionCellOffsetsRestart(0);
5079 const MInt localPartitionCellEnd = grid().localPartitionCellOffsetsRestart(1);
5080
5081 MIntScratchSpace noEllipsoidsPerPartitionCell(noGlobalPartitionCells, AT_, "noParticlesPerPartitionCell");
5082
5083 if(domainId() == 0) {
5084 cerr << "noGlobalPartitionCells " << noGlobalPartitionCells << endl;
5085 }
5086
5087 // load number of particle in partition cell for all partition cells!
5088 parallelIo2.setOffset(noGlobalPartitionCells, 0);
5089 parallelIo2.readArray(&noEllipsoidsPerPartitionCell[0], "partCount");
5090
5091 // total number of ellipsoids
5092 MInt numberOfEllips = 0;
5093#ifdef _OPENMP
5094#pragma omp parallel for reduction(+ : numberOfEllips)
5095#endif
5096 for(MInt i = 0; i < noGlobalPartitionCells; ++i) {
5097 numberOfEllips += noEllipsoidsPerPartitionCell[i];
5098 }
5099
5100 if(domainId() == 0) {
5101 cerr << "Global number of ellipsoids loaded from restart file " << numberOfEllips << endl;
5102 }
5103 m_log << "Global number of ellipsoids loaded from restart file " << numberOfEllips << endl;
5104
5105 ParallelIo::size_type beginPartId = 0;
5106 beginPartId = 0;
5107 for(MInt i = 0; i < localPartitionCellBeginning; ++i) {
5108 beginPartId += noEllipsoidsPerPartitionCell[i];
5109 }
5110
5111 MInt localNoPart = noEllipsoidsPerPartitionCell[localPartitionCellBeginning];
5112 for(MInt i = (localPartitionCellBeginning + 1); i < localPartitionCellEnd; ++i) {
5113 localNoPart += noEllipsoidsPerPartitionCell[i];
5114 }
5115
5116 MInt checkPartCount = 0;
5117 MPI_Allreduce(&localNoPart, &checkPartCount, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "localNoPart");
5118
5119 if(domainId() == 0 && checkPartCount != numberOfEllips) {
5120 // numberOfEllps is only set on the root-rank!
5121 TERM(-1);
5122 }
5123
5124 ASSERT(localNoPart >= 0, "ERROR: Invalid number of ellipsoids to be loaded during restart");
5125
5126 if(localNoPart == 0) {
5127 beginPartId = 0;
5128 }
5129
5130 // Preparing arrays and getting particle datas.
5131 if(numberOfEllips > 0) {
5132 MLongScratchSpace ncmpiPartId(localNoPart, AT_, "ncmpiPartId");
5133 MFloatScratchSpace ncmpiSemiMinorAxis(localNoPart, AT_, "ncmpiSemiMinorAxis");
5134 MFloatScratchSpace ncmpiAspectRatio(localNoPart, AT_, "ncmpiAspectRatio");
5135 MFloatScratchSpace ncmpiDensityRatio(localNoPart, AT_, "ncmpiDensityRatio");
5136 MIntScratchSpace ncmpiPartStatus(localNoPart, AT_, "ncmpiPartStatus");
5137 MFloatScratchSpace ncmpiPartCoords(3 * localNoPart, AT_, "ncmpiPartCoords");
5138 MFloatScratchSpace ncmpiPartVel(3 * localNoPart, AT_, "ncmpiPartVel");
5139 MFloatScratchSpace ncmpiPartAccel(3 * localNoPart, AT_, "ncmpiPartAccel");
5140 MFloatScratchSpace ncmpiPartAngVel(3 * localNoPart, AT_, "ncmpiPartVel");
5141 MFloatScratchSpace ncmpiPartAngAccel(3 * localNoPart, AT_, "ncmpiPartAngAccel");
5142 MFloatScratchSpace ncmpiPartOldCoords(3 * localNoPart, AT_, "ncmpiPartOldCoords");
5143 MFloatScratchSpace ncmpiPartOldVel(3 * localNoPart, AT_, "ncmpiPartOldVel");
5144 MFloatScratchSpace ncmpiPartOldAccel(3 * localNoPart, AT_, "ncmpiPartOldAccel");
5145 MFloatScratchSpace ncmpiPartOldAngVel(3 * localNoPart, AT_, "ncmpiPartOldAngVel");
5146 MFloatScratchSpace ncmpiPartOldAngAccel(3 * localNoPart, AT_, "ncmpiPartOldAngAccel");
5147 MFloatScratchSpace ncmpiPartQuat(4 * localNoPart, AT_, "ncmpiPartQuaternions");
5148 MFloatScratchSpace ncmpiPartOldQuat(4 * localNoPart, AT_, "ncmpiPartOldQuaternions");
5149 MFloatScratchSpace ncmpiTemp(localNoPart, AT_, "ncmpiTemp");
5150 MFloatScratchSpace ncmpiCT(localNoPart, AT_, "ncmpiCT");
5151 MFloatScratchSpace ncmpiOldFluidDensity(localNoPart, AT_, "ncmpiOldFluidDensity");
5152 MFloatScratchSpace ncmpiOldFluidVelocity(3 * localNoPart, AT_, "ncmpiOldFluidVelocity");
5153
5154 parallelIo2.setOffset(localNoPart, beginPartId);
5155 parallelIo2.readArray(ncmpiPartId.begin(), "partId");
5156 parallelIo2.readArray(ncmpiSemiMinorAxis.begin(), "partSemiMinorAxis");
5157 parallelIo2.readArray(ncmpiAspectRatio.begin(), "partAspectRatio");
5158 parallelIo2.readArray(ncmpiDensityRatio.begin(), "partDensityRatio");
5159 parallelIo2.readArray(ncmpiPartStatus.begin(), "partStatus");
5160 parallelIo2.readArray(ncmpiCT.begin(), "creationTime");
5161 if(m_heatCoupling) parallelIo2.readArray(ncmpiTemp.begin(), "partTemp");
5162 parallelIo2.readArray(ncmpiOldFluidDensity.begin(), "oldFluidDensity");
5163
5164 ParallelIo::size_type localNoPart3 = 3 * localNoPart;
5165 ParallelIo::size_type beginPartId3 = 3 * beginPartId;
5166 parallelIo2.setOffset(localNoPart3, beginPartId3);
5167 parallelIo2.readArray(ncmpiPartCoords.begin(), "partPos");
5168 parallelIo2.readArray(ncmpiPartVel.begin(), "partVel");
5169 parallelIo2.readArray(ncmpiPartAccel.begin(), "partAccel");
5170 parallelIo2.readArray(ncmpiPartAngVel.begin(), "partAngVel");
5171 parallelIo2.readArray(ncmpiPartAngAccel.begin(), "partAngAccel");
5172 parallelIo2.readArray(ncmpiPartOldCoords.begin(), "partOldPos");
5173 parallelIo2.readArray(ncmpiPartOldVel.begin(), "partOldVel");
5174 parallelIo2.readArray(ncmpiPartOldAccel.begin(), "partOldAccel");
5175 parallelIo2.readArray(ncmpiPartOldAngVel.begin(), "partOldAngVel");
5176 parallelIo2.readArray(ncmpiPartOldAngAccel.begin(), "partOldAngAccel");
5177
5178 ParallelIo::size_type localNoPart4 = 4 * localNoPart;
5179 ParallelIo::size_type beginPartId4 = 4 * beginPartId;
5180 parallelIo2.setOffset(localNoPart4, beginPartId4);
5181 parallelIo2.readArray(ncmpiPartQuat.begin(), "partQuat");
5182 parallelIo2.readArray(ncmpiPartOldQuat.begin(), "partOldQuat");
5183
5184 LPTEllipsoidal<nDim> thisParticleEllipsoid;
5185
5186 // If any particle, write particle to the particle list m_partList.
5187 for(MLong i = 0; i < localNoPart; ++i) {
5188 for(MInt n = 0; n < nDim; n++)
5189 thisParticleEllipsoid.m_position[n] = ncmpiPartCoords[(3 * i) + n];
5190 // find matching cellId
5191 const MInt cellId = grid().findContainingLeafCell(&thisParticleEllipsoid.m_position[0]);
5192 if(cellId == -1) continue;
5193 if(a_isHalo(cellId)) {
5194 cerr << "Particle in halo-cell!" << endl;
5195 continue;
5196 }
5197
5198 thisParticleEllipsoid.m_cellId = cellId;
5199 ASSERT(thisParticleEllipsoid.m_cellId >= 0, "Invalid cellId! " + to_string(thisParticleEllipsoid.m_cellId));
5200 ASSERT(c_isLeafCell(thisParticleEllipsoid.m_cellId),
5201 "No leaf cell... " + std::to_string(thisParticleEllipsoid.m_cellId));
5202 thisParticleEllipsoid.m_partId = ncmpiPartId[i];
5203 thisParticleEllipsoid.m_semiMinorAxis = ncmpiSemiMinorAxis[i];
5204 thisParticleEllipsoid.m_aspectRatio = ncmpiAspectRatio[i];
5205 thisParticleEllipsoid.initEllipsoialProperties();
5206 thisParticleEllipsoid.m_densityRatio = ncmpiDensityRatio[i];
5207 thisParticleEllipsoid.m_temperature = ncmpiTemp[i];
5208 thisParticleEllipsoid.m_creationTime = ncmpiCT[i];
5209 thisParticleEllipsoid.firstStep() = (ncmpiPartStatus[i] > 0);
5210 thisParticleEllipsoid.m_oldCellId = cellId;
5211 thisParticleEllipsoid.m_oldFluidDensity = ncmpiOldFluidDensity[i];
5212
5213 for(MInt n = 0; n < nDim; n++) {
5214 // velocites and accelerations
5215 thisParticleEllipsoid.m_velocity[n] = ncmpiPartVel[(3 * i) + n];
5216 thisParticleEllipsoid.m_accel[n] = ncmpiPartAccel[(3 * i) + n];
5217 thisParticleEllipsoid.m_angularVel[n] = ncmpiPartAngVel[(3 * i) + n];
5218 thisParticleEllipsoid.m_angularAccel[n] = ncmpiPartAngAccel[(3 * i) + n];
5219 // old position, velocities and accelerations
5220 thisParticleEllipsoid.m_oldPos[n] = ncmpiPartOldCoords[(3 * i) + n];
5221 thisParticleEllipsoid.m_oldVel[n] = ncmpiPartOldVel[(3 * i) + n];
5222 thisParticleEllipsoid.m_oldAccel[n] = ncmpiPartOldAccel[(3 * i) + n];
5223 thisParticleEllipsoid.m_oldAngularVel[n] = ncmpiPartOldAngVel[(3 * i) + n];
5224 thisParticleEllipsoid.m_oldAngularAccel[n] = ncmpiPartOldAngAccel[(3 * i) + n];
5225 // copy fluid velocity
5226 thisParticleEllipsoid.m_oldFluidVel[n] = ncmpiOldFluidVelocity[(3 * i) + n];
5227 }
5228 // store current and old quaternions
5229 for(MInt n = 0; n < 4; n++) {
5230 thisParticleEllipsoid.m_quaternion[n] = ncmpiPartQuat[(4 * i) + n];
5231 thisParticleEllipsoid.m_oldQuaternion[n] = ncmpiPartOldQuat[(4 * i) + n];
5232 }
5233 thisParticleEllipsoid.updateProperties();
5234
5235 m_partListEllipsoid.push_back(thisParticleEllipsoid);
5236 }
5237 MLong sumEllips = 0;
5238 MLong noEllips = a_noEllipsoidalParticles();
5239 MPI_Allreduce(&noEllips, &sumEllips, 1, type_traits<MLong>::mpiType(), MPI_SUM, mpiComm(), AT_, "INPLACE",
5240 "sumpart");
5241
5242 // check if everything is loaded
5243 if(domainId() == 0) {
5244 cerr << "Loaded " << numberOfEllips << " particles of " << sumEllips << endl;
5245
5246 if(numberOfEllips != sumEllips) {
5247 TERMM(-1, "invalid number of ellipsoids loaded");
5248 }
5249 }
5250 }
5251 }
5252
5253 MInt theSize = a_noParticles();
5255 if(m_ellipsoids) {
5256 theSize += a_noEllipsoidalParticles();
5258 }
5259
5260 m_addedParticle = 0;
5261 MLong noPart = a_noParticles();
5262 MPI_Allreduce(MPI_IN_PLACE, &noPart, 1, type_traits<MLong>::mpiType(), MPI_SUM, mpiComm(), AT_, "INPLACE", "noPart");
5263
5264 if(m_ellipsoids) {
5265 MLong noEllipsoids = a_noEllipsoidalParticles();
5266 MPI_Allreduce(MPI_IN_PLACE, &noEllipsoids, 1, type_traits<MLong>::mpiType(), MPI_SUM, mpiComm(), AT_, "INPLACE",
5267 "noPart");
5268 noPart += noEllipsoids;
5269 }
5270
5271 if(domainId() == m_spawnDomainId) {
5272 m_addedParticle = noPart;
5273 }
5274
5275 return theSize;
5276}
std::array< MFloat, nDim > m_oldAccel
particle acceleration of the last time step
std::array< MFloat, nDim > m_oldAngularAccel
particle angular acceleration of the last time step
std::array< MFloat, nDim > m_oldAngularVel
particle angular velocity of the last time step
std::mt19937_64 m_PRNGSpawn
Definition: lpt.h:558
std::mt19937_64 & randomSpawn(const MInt calls)
Definition: lpt.h:736
MLong m_spawnSeed
Definition: lpt.h:759
void own_sort(T &c, Pred &p)
Definition: lpt.h:713
std::array< MFloat, nDim > m_oldAccel
particle acceleration of the last time step
Definition: lptspherical.h:68
MString getIdentifier(const MBool useSolverId=false, const MString preString="", const MString postString="_")
Definition: solver.cpp:188
MBool m_restartFile
Definition: solver.h:98
MString restartDir() const
Return the directory for restart files.
Definition: solver.h:410
PARALLELIO_DEFAULT_BACKEND ParallelIo
Definition: parallelio.h:292

◆ loadSampleVariables()

template<MInt nDim>
void LPT< nDim >::loadSampleVariables ( MInt  timeStep)
inline

Definition at line 997 of file lpt.h.

997 {
998 std::cerr << "loadSampleVariables DgCartesianSolver " << timeStep << std::endl;
999 };

◆ mergeParticles()

template<MInt nDim>
void LPT< nDim >::mergeParticles ( LPTSpherical< nDim > *  partA,
LPTSpherical< nDim > *  partB 
)
private

Merge both particles to A

Template Parameters
nDim
Parameters
partA
partB

Definition at line 2890 of file lpt.cpp.

2890 {
2891 if(smallParticle(*partA) || smallParticle(*partB)) {
2892 TERM(-1);
2893 }
2894
2895 // mass average value
2896 auto massAvg = [](const MFloat massA, MFloat* const valueA, const MFloat massB, const MFloat* const valueB) {
2897 for(MInt dim = 0; dim < nDim; dim++) {
2898 valueA[dim] = (massA * valueA[dim] + massB * valueB[dim]) / (massA + massB);
2899 }
2900 };
2901 // calculate new direction of parcel while keeping kinetic energy constant
2902 auto massAvg2 = [](const MFloat massA, MFloat* const valueA, const MFloat massB, const MFloat* const valueB) {
2903 // calculate unit direction vector
2904 array<MFloat, nDim> dir{};
2905 MFloat resultingV =
2906 pow((massA * POW2(math::norm(valueA, nDim)) + massB * POW2(math::norm(valueB, nDim))) / (massA + massB), 0.5);
2907 for(MInt dim = 0; dim < nDim; ++dim) {
2908 dir.at(dim) = massA * valueA[dim] + massB * valueB[dim];
2909 }
2910 math::normalize(dir);
2911
2912 for(MInt dim = 0; dim < nDim; dim++) {
2913 valueA[dim] = dir.at(dim) * resultingV;
2914 }
2915 };
2916
2917 const MInt noA = partA->m_noParticles;
2918 const MInt noB = partB->m_noParticles;
2919
2920 const MFloat massA = partA->sphericalMass() * noA;
2921 const MFloat massB = partB->sphericalMass() * noB;
2922
2923 massAvg(massA, &partA->m_oldPos[0], massB, &partB->m_oldPos[0]);
2924 massAvg(massA, &partA->m_position[0], massB, &partB->m_position[0]);
2925 massAvg(massA, &partA->m_accel[0], massB, &partB->m_accel[0]);
2926 massAvg(massA, &partA->m_oldAccel[0], massB, &partB->m_oldAccel[0]);
2927 massAvg2(massA, &partA->m_oldVel[0], massB, &partB->m_oldVel[0]);
2928
2929 // cerr << "EKIN before " << massA * POW2(math::norm(&partA->m_velocity[0], 3)) + massB * POW2(math::norm
2930 // (&partB->m_velocity[0], 3)) << endl;
2931
2932 // auto temp = partA->m_velocity;
2933 // cerr << "asddas " << temp[0] << endl;
2934 // massAvg(massA, &temp[0], massB, &partB->m_velocity[0]);
2935 // cerr << "before " << temp[0] << endl;
2936 massAvg2(massA, &partA->m_velocity[0], massB, &partB->m_velocity[0]);
2937 // cerr << "after " << partA->m_velocity[0] << endl;
2938 // cerr << "EKIN after " << (massA+massB) * POW2(math::norm(&partA->m_velocity[0], 3)) << endl;
2939 // cerr << "EKIN after2 " << (massA+massB) * POW2(math::norm(&temp[0], 3)) << endl;
2940 // TERM(-1);
2941 partA->m_creationTime = (massA * partA->m_creationTime + massB * partB->m_creationTime) / (massA + massB);
2942 partA->m_temperature = (massA * partA->m_temperature + massB * partB->m_temperature) / (massA + massB);
2943 partA->m_breakUpTime = (massA * partA->m_breakUpTime + massB * partB->m_breakUpTime) / (massA + massB);
2944 partA->m_shedDiam = (massA * partA->m_shedDiam + massB * partB->m_shedDiam) / (massA + massB);
2945 partA->m_dM = (massA * partA->m_dM + massB * partB->m_dM) / (massA + massB);
2946
2947 // calculate new diameter based on mass -> which does not keep SMD constant....
2948 // partA->m_diameter = pow((partA->m_noParticles * POW3(partA->m_diameter) + partB->m_noParticles * POW3
2949 // (partB->m_diameter))/(partA->m_noParticles + partB->m_noParticles), 1.0/3.0);
2950
2951 // to keep SMD constant merge to SMD value diameter
2952 partA->m_diameter = (noA * POW3(partA->m_diameter) + noB * POW3(partB->m_diameter))
2953 / (noA * POW2(partA->m_diameter) + noB * POW2(partB->m_diameter));
2954 partB->m_diameter = 0; // mark for deletion
2955
2956 const MFloat newMassPerDrop = partA->sphericalMass();
2957 partA->m_noParticles = (massA + massB) / newMassPerDrop;
2958}
MBool smallParticle(const LPTSpherical< nDim > &particle)
Definition: lpt.h:734
MFloat sphericalMass() const
Calculate the current mass.
Definition: lptspherical.h:126
constexpr Real POW3(const Real x)
Definition: functions.h:123
void normalize(std::array< T, N > &u)
Definition: maiamath.h:191
MFloat norm(const std::array< T, N > &u)
Definition: maiamath.h:148

◆ motionEquation()

template<MInt nDim>
void LPT< nDim >::motionEquation ( const MInt  offset)
private

Definition at line 2962 of file lpt.cpp.

2962 {
2963 RECORD_TIMER_START(m_timers[Timers::Motion]);
2964 ASSERT(grid().checkNghbrIds(), "");
2965
2966#ifdef _OPENMP
2967#pragma omp parallel default(none) shared(offset)
2968#endif
2969 {
2970#ifdef _OPENMP
2971#pragma omp for nowait
2972#endif
2973 for(MInt i = offset; i < a_noParticles(); i++) {
2974 if(!m_partList[i].isInvalid()) {
2975 m_partList[i].motionEquation();
2976 }
2977 }
2978#ifdef _OPENMP
2979#pragma omp for nowait
2980#endif
2981 for(MInt i = offset; i < a_noEllipsoidalParticles(); i++) {
2982 if(!m_partListEllipsoid[i].isInvalid()) {
2983 m_partListEllipsoid[i].motionEquation();
2984 }
2985 }
2986 }
2987 RECORD_TIMER_STOP(m_timers[Timers::Motion]);
2988}

◆ motionEquationEllipsoids()

template<MInt nDim>
void LPT< nDim >::motionEquationEllipsoids ( const MInt  offset)
private

◆ mpiTag()

template<MInt nDim>
MInt LPT< nDim >::mpiTag ( const MString  exchangeType)
inline

Definition at line 323 of file lpt.h.

323 {
324 switch((LPTmpiTag)string2enum(exchangeType)) {
325 case PARTICLE_COUNT: {
326 return 0;
327 }
328 case PARTICLE_FLOAT: {
329 if(!m_primaryExchange) {
330 return 1;
331 } else {
332 return 5;
333 }
334 }
335 case PARTICLE_INT: {
336 if(!m_primaryExchange) {
337 return 2;
338 } else {
339 return 6;
340 }
341 }
342 case SOURCE_TERMS: {
343 return 3;
344 }
345 case FLOW_FIELD: {
346 return 7;
347 }
348 case CHECK_ADAP: {
349 return 8;
350 }
351 case VELOCITY_SLOPES: {
352 return 14;
353 }
354 default: {
355 mTerm(1, AT_, "Unknown mpiTag");
356 return -1;
357 }
358 }
359 }
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
LPTmpiTag
Definition: enums.h:426
@ FLOW_FIELD
Definition: enums.h:426
@ PARTICLE_INT
Definition: enums.h:426
@ CHECK_ADAP
Definition: enums.h:426
@ VELOCITY_SLOPES
Definition: enums.h:426
@ PARTICLE_COUNT
Definition: enums.h:426
@ PARTICLE_FLOAT
Definition: enums.h:426
@ SOURCE_TERMS
Definition: enums.h:426

◆ noCellDataDlb()

template<MInt nDim>
MInt LPT< nDim >::noCellDataDlb ( ) const
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 280 of file lpt.h.

280 {
281 if(grid().isActive()) {
282 return 3;
283 // 0: cell int data
284 // 1: particle float data
285 // 2: particle int data
286 } else {
287 return 0;
288 }
289 }

◆ noDomains()

template<MInt nDim>
MInt LPT< nDim >::noDomains ( ) const
inlineoverridevirtual

Return the total number of domains (total number of ranks in current MPI communicator)

Reimplemented from Solver.

Definition at line 981 of file lpt.h.

981{ return grid().noDomains(); }

◆ noInternalCells()

template<MInt nDim>
MInt LPT< nDim >::noInternalCells ( ) const
inlineoverridevirtual

Implements Solver.

Definition at line 979 of file lpt.h.

979{ return grid().noInternalCells(); }

◆ noLoadTypes()

template<MInt nDim>
MInt LPT< nDim >::noLoadTypes ( ) const
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 270 of file lpt.h.

270{ return 3 + m_weightSourceCells; };

◆ noSolverTimers()

template<MInt nDim>
MInt LPT< nDim >::noSolverTimers ( const MBool  allTimings)
inlineoverride

Definition at line 261 of file lpt.h.

261 {
262#ifdef MAIA_TIMER_FUNCTION
263 TERMM_IF_COND(!allTimings, "FIXME: reduced timings mode not yet supported by LPT.");
264 static const MInt noAdditionTimers = 9;
265 return 2 + noAdditionTimers;
266#else
267 return 2;
268#endif
269 }

◆ noVariables()

template<MInt nDim>
MInt LPT< nDim >::noVariables ( ) const
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 941 of file lpt.h.

941 {
942 // noParticlesInCell
943 return 1;
944 }

◆ oneStageSolutionStep()

template<MInt nDim>
MBool LPT< nDim >::oneStageSolutionStep
private
Date
August 21
Author
Tim Wegmann

Definition at line 2387 of file lpt.cpp.

2387 {
2388 NEW_TIMER_GROUP_STATIC(t_part, "particle timestep");
2389 NEW_TIMER_STATIC(partTS, "particle timestep", t_part);
2390 NEW_SUB_TIMER_STATIC(spawn, "spawn", partTS);
2391 NEW_SUB_TIMER_STATIC(motion, "motion", partTS);
2392 NEW_SUB_TIMER_STATIC(transfer, "transfer", partTS);
2393 NEW_SUB_TIMER_STATIC(evap, "evaporation", partTS);
2394 NEW_SUB_TIMER_STATIC(couplingTerms, "couplingTerms", partTS);
2395 NEW_SUB_TIMER_STATIC(collision1, "wall-collision", partTS);
2396 NEW_SUB_TIMER_STATIC(primBU, "primaryBreakUp", partTS);
2397 NEW_SUB_TIMER_STATIC(secBU, "secondaryBreakUp", partTS);
2398 NEW_SUB_TIMER_STATIC(respawn, "particle-respawn", partTS);
2399 NEW_SUB_TIMER_STATIC(deleteP, "Remove-particles", partTS);
2400
2401 RECORD_TIMER_START(partTS);
2402
2403 ASSERT(!m_nonBlockingComm, "");
2404
2405 // some debug checks
2407 checkCells();
2408
2409 RECORD_TIMER_START(primBU);
2410 if(m_activePrimaryBUp) {
2412 }
2413 RECORD_TIMER_STOP(primBU);
2414
2415 // receive flow field data from previous TS
2417 // if ellipsoids are activated also receive velocity slopes from previous TS
2419
2420 // move particles
2421 RECORD_TIMER_START(motion);
2422 motionEquation(0);
2423 RECORD_TIMER_STOP(motion);
2424
2425 RECORD_TIMER_START(collision1);
2426 wallCollision();
2427 RECORD_TIMER_STOP(collision1);
2428
2429 RECORD_TIMER_START(transfer);
2430 exchangeParticles(false, 0);
2431 RECORD_TIMER_STOP(transfer);
2432
2433 RECORD_TIMER_START(evap);
2434 evaporation(0);
2435 RECORD_TIMER_STOP(evap);
2436
2437 RECORD_TIMER_START(couplingTerms);
2438 coupling(0);
2439 RECORD_TIMER_STOP(couplingTerms);
2440
2441 RECORD_TIMER_START(secBU);
2442 RECORD_TIMER_START(m_timers[Timers::Breakup]);
2444 m_sprayModel->secondaryBreakUp(m_timeStep);
2445 }
2446 RECORD_TIMER_STOP(m_timers[Timers::Breakup]);
2447 RECORD_TIMER_STOP(secBU);
2448
2449 // check for collided particles to be copied to other ranks
2450 RECORD_TIMER_START(transfer);
2451 if(m_collisions < 5 && m_collisions > 0) {
2452 exchangeParticles(true, 0);
2453 }
2454 RECORD_TIMER_STOP(transfer);
2455
2456 RECORD_TIMER_START(spawn);
2457 if(m_spawnParticles) {
2458 spawnTimeStep();
2459 }
2460 RECORD_TIMER_STOP(spawn);
2461
2462 RECORD_TIMER_START(deleteP);
2464 RECORD_TIMER_STOP(deleteP);
2465
2466 // reduceParticles(); // TODO labels:LPT activate and make settable
2467
2468 // advanceParticles(0);
2469
2470 RECORD_TIMER_START(respawn);
2471 if(m_respawn) {
2473 }
2474 RECORD_TIMER_STOP(respawn);
2475
2477
2478 if(this->m_adaptation && this->m_noSensors > 0) {
2480 }
2481
2484 }
2485
2486 // gather post-processing data
2487 if(m_sprayModel != nullptr) {
2488 const MInt count = m_sprayModel->m_injDataSize;
2489 vector<MFloat> tmp(count + m_addInjDataCnt);
2490 for(MInt i = 0; i < count; i++) {
2491 tmp[i] = m_sprayModel->m_injData[i];
2492 }
2493 tmp[count] = m_sumEvapMass;
2494 tmp[count + 1] = m_sprayModel->m_noRTsecBreakUp;
2495 tmp[count + 2] = m_sprayModel->m_noKHsecBreakUp;
2496 tmp[count + 3] = m_noSendParticles;
2497
2498 m_injData.insert(make_pair(globalTimeStep, tmp));
2499 }
2500
2501 RECORD_TIMER_STOP(partTS);
2502 return true;
2503}

◆ operator=()

template<MInt nDim>
LPT & LPT< nDim >::operator= ( const LPT< nDim > &  )
delete

◆ own_remove_if()

template<MInt nDim>
template<class T , class Pred >
void LPT< nDim >::own_remove_if ( T &  c,
Pred &  p 
)
inlineprotected

Definition at line 724 of file lpt.h.

724 {
725 using tag = typename std::iterator_traits<typename T::iterator>::iterator_category;
726 remove_if_impl_(c, p, tag());
727 }
void remove_if_impl_(T &c, Pred &p, std::random_access_iterator_tag)
Definition: lpt.h:730

◆ own_sort()

template<MInt nDim>
template<class T , class Pred >
void LPT< nDim >::own_sort ( T &  c,
Pred &  p 
)
inlineprotected

Definition at line 713 of file lpt.h.

713 {
714 using tag = typename std::iterator_traits<typename T::iterator>::iterator_category;
715 sort_impl_(c, p, tag());
716 }
void sort_impl_(T &c, Pred &p, std::random_access_iterator_tag)
Definition: lpt.h:719

◆ packParticles() [1/2]

template<MInt nDim>
void LPT< nDim >::packParticles ( std::vector< LPTEllipsoidal< nDim > * > &  particlesToSend,
MInt intBuffer,
MFloat floatBuffer,
std::vector< MInt cellIds 
)
private
Author
Laurent Andre
Date
September 2022

Definition at line 5928 of file lpt.cpp.

5929 {
5930 if(!m_ellipsoids) {
5931 mTerm(1, AT_, "Only allowed for ellipsoids!");
5932 }
5933
5934 MInt z = 0;
5935 if(intBuffer != nullptr) {
5936 for(MInt id = 0; id < (MInt)particlesToSend.size(); id++) {
5937 // splitting long into two ints
5938 intBuffer[z++] = (MInt)(particlesToSend[id]->m_partId >> 32);
5939 intBuffer[z++] = MInt(particlesToSend[id]->m_partId);
5940 intBuffer[z++] = cellIds[id];
5941 intBuffer[z++] = ((particlesToSend[id]->firstStep() ? 1 : 0) + (particlesToSend[id]->reqSend() ? 2 : 0));
5942 intBuffer[z++] = (MInt)(particlesToSend[id]->hadWallColl());
5943 if(id == 0 && z != intElemPerP<LPTEllipsoidal<nDim>>()) {
5944 mTerm(1, AT_, "Buffersize missmatching!");
5945 }
5946 }
5947 }
5948
5949 if(floatBuffer != nullptr) {
5950 z = 0;
5951 for(MInt id = 0; id < (MInt)particlesToSend.size(); id++) {
5952 floatBuffer[z++] = particlesToSend[id]->m_semiMinorAxis;
5953 floatBuffer[z++] = particlesToSend[id]->m_aspectRatio;
5954 floatBuffer[z++] = particlesToSend[id]->m_densityRatio;
5955 for(MInt j = 0; j < nDim; j++)
5956 floatBuffer[z++] = particlesToSend[id]->m_position.at(j);
5957 for(MInt j = 0; j < nDim; j++)
5958 floatBuffer[z++] = particlesToSend[id]->m_velocity.at(j);
5959 for(MInt j = 0; j < nDim; j++)
5960 floatBuffer[z++] = particlesToSend[id]->m_accel.at(j);
5961 for(MInt j = 0; j < nDim; j++)
5962 floatBuffer[z++] = particlesToSend[id]->m_angularVel.at(j);
5963 for(MInt j = 0; j < nDim; j++)
5964 floatBuffer[z++] = particlesToSend[id]->m_angularAccel.at(j);
5965 for(MInt j = 0; j < 4; j++)
5966 floatBuffer[z++] = particlesToSend[id]->m_quaternion.at(j);
5967 for(MInt j = 0; j < nDim; j++)
5968 floatBuffer[z++] = particlesToSend[id]->m_oldPos.at(j);
5969 for(MInt j = 0; j < nDim; j++)
5970 floatBuffer[z++] = particlesToSend[id]->m_oldVel.at(j);
5971 for(MInt j = 0; j < nDim; j++)
5972 floatBuffer[z++] = particlesToSend[id]->m_oldAccel.at(j);
5973 for(MInt j = 0; j < nDim; j++)
5974 floatBuffer[z++] = particlesToSend[id]->m_oldAngularVel.at(j);
5975 for(MInt j = 0; j < nDim; j++)
5976 floatBuffer[z++] = particlesToSend[id]->m_oldAngularAccel.at(j);
5977 for(MInt j = 0; j < 4; j++)
5978 floatBuffer[z++] = particlesToSend[id]->m_oldQuaternion.at(j);
5979 floatBuffer[z++] = particlesToSend[id]->m_creationTime;
5980 floatBuffer[z++] = particlesToSend[id]->m_temperature;
5981 floatBuffer[z++] = particlesToSend[id]->m_heatFlux;
5982 floatBuffer[z++] = particlesToSend[id]->m_fluidVelMag;
5983 floatBuffer[z++] = particlesToSend[id]->m_oldFluidDensity;
5984 for(MInt j = 0; j < nDim; j++)
5985 floatBuffer[z++] = particlesToSend[id]->m_oldFluidVel[j];
5986
5987 if(id == 0 && z != elemPerP<LPTEllipsoidal<nDim>>()) {
5988 mTerm(1, AT_, "Buffersize missmatching!");
5989 }
5990 if(intBuffer == nullptr) {
5991 MInt partId1 = (MInt)(particlesToSend[id]->m_partId >> 32);
5992 MInt partId2 = MInt(particlesToSend[id]->m_partId);
5993 floatBuffer[z++] = (MFloat)partId1;
5994 floatBuffer[z++] = (MFloat)partId2;
5995 }
5996 }
5997 }
5998}

◆ packParticles() [2/2]

template<MInt nDim>
void LPT< nDim >::packParticles ( std::vector< LPTSpherical< nDim > * > &  particlesToSend,
MInt intBuffer,
MFloat floatBuffer,
std::vector< MInt cellIds 
)
private
Author
Sven Berger
Date
September 2018
Parameters
particlesToSendparticles that need to be send
intBufferinteger buffer to use
floatBufferfloat buffer to use

Definition at line 5850 of file lpt.cpp.

5851 {
5852 MInt z = 0;
5853 if(intBuffer != nullptr) {
5854 for(MInt id = 0; id < (MInt)particlesToSend.size(); id++) {
5855 // splitting long into two ints
5856 intBuffer[z++] = (MInt)(particlesToSend[id]->m_partId >> 32);
5857 intBuffer[z++] = MInt(particlesToSend[id]->m_partId);
5858 intBuffer[z++] = cellIds[id];
5859 intBuffer[z++] = particlesToSend[id]->m_noParticles;
5860 intBuffer[z++] = ((particlesToSend[id]->firstStep() ? 1 : 0) + (particlesToSend[id]->reqSend() ? 2 : 0));
5861 intBuffer[z++] = (MInt)(particlesToSend[id]->hadWallColl());
5862 if(id == 0 && z != intElemPerP<LPTSpherical<nDim>>()) {
5863 mTerm(1, AT_, "Buffersize missmatching!");
5864 }
5865 }
5866 }
5867
5868 if(floatBuffer != nullptr) {
5869 z = 0;
5870 for(MInt id = 0; id < (MInt)particlesToSend.size(); id++) {
5871 floatBuffer[z++] = particlesToSend[id]->m_diameter;
5872 floatBuffer[z++] = particlesToSend[id]->m_densityRatio;
5873 for(MInt j = 0; j < nDim; j++) {
5874 floatBuffer[z++] = particlesToSend[id]->m_position.at(j);
5875 }
5876 for(MInt j = 0; j < nDim; j++) {
5877 floatBuffer[z++] = particlesToSend[id]->m_velocity.at(j);
5878 }
5879 for(MInt j = 0; j < nDim; j++) {
5880 floatBuffer[z++] = particlesToSend[id]->m_accel.at(j);
5881 }
5882 for(MInt j = 0; j < nDim; j++) {
5883 floatBuffer[z++] = particlesToSend[id]->m_oldPos.at(j);
5884 }
5885 for(MInt j = 0; j < nDim; j++) {
5886 floatBuffer[z++] = particlesToSend[id]->m_oldVel.at(j);
5887 }
5888 for(MInt j = 0; j < nDim; j++) {
5889 floatBuffer[z++] = particlesToSend[id]->m_oldAccel.at(j);
5890 }
5891 floatBuffer[z++] = particlesToSend[id]->m_creationTime;
5892 floatBuffer[z++] = particlesToSend[id]->m_breakUpTime;
5893 floatBuffer[z++] = particlesToSend[id]->m_shedDiam;
5894 floatBuffer[z++] = particlesToSend[id]->m_temperature;
5895 floatBuffer[z++] = particlesToSend[id]->m_dM;
5896 floatBuffer[z++] = particlesToSend[id]->m_heatFlux;
5897 floatBuffer[z++] = particlesToSend[id]->m_fluidVelMag;
5898
5899 floatBuffer[z++] = particlesToSend[id]->m_oldFluidDensity;
5900 for(MInt j = 0; j < nDim; j++) {
5901 floatBuffer[z++] = particlesToSend[id]->m_oldFluidVel[j];
5902 }
5903 if(id == 0 && z != elemPerP<LPTSpherical<nDim>>()) {
5904 mTerm(1, AT_, "Buffersize missmatching!");
5905 }
5906 if(intBuffer == nullptr) {
5907 MInt partId1 = (MInt)(particlesToSend[id]->m_partId >> 32);
5908 MInt partId2 = MInt(particlesToSend[id]->m_partId);
5909 floatBuffer[z++] = (MFloat)partId1;
5910 floatBuffer[z++] = (MFloat)partId2;
5911 floatBuffer[z++] = particlesToSend[id]->m_noParticles;
5912 }
5913 }
5914 }
5915
5916 if(intBuffer != nullptr && floatBuffer != nullptr) {
5918 }
5919}

◆ particleRespawn()

template<MInt nDim>
void LPT< nDim >::particleRespawn
protected

void LPT::particleRespawn()

version: December-09, split into seperate function from timestep() Dez-2013

Author
Rudie Kunnen, Christoph Siewert

Definition at line 3114 of file lpt.cpp.

3114 {
3115 partType thisPart{};
3116 list<partType> partRespawnList; // queue<partType> partQueue;
3117
3118 {
3119 auto deleteOffset = partition(m_partList.begin(), m_partList.end(), activeParticle<nDim>);
3120 auto offset = deleteOffset;
3121 while(offset != m_partList.end()) {
3122 if(offset->toBeRespawn()) {
3123 thisPart.partId = offset->m_partId;
3124 thisPart.cellId = offset->m_cellId;
3125 thisPart.diam = offset->m_diameter;
3126 thisPart.densRatio = offset->m_densityRatio;
3127 partRespawnList.push_back(thisPart); // partQueue.push(thisPart);
3128 }
3129 ++offset;
3130 }
3131 m_partList.erase(deleteOffset, m_partList.end());
3132 }
3133
3134 if(noDomains() > 1) {
3135 MInt const respawnSize = 3;
3136 MInt const respawnSendSize = respawnSize + 3;
3137 if(domainId() == m_respawnDomain) {
3138 MIntScratchSpace arrayNoOfParts(noDomains(), AT_, "arrayNoOfParts");
3139 arrayNoOfParts.p[m_respawnDomain] = (MInt)partRespawnList.size();
3140 MPI_Gather(MPI_IN_PLACE, 1, MPI_INT, &arrayNoOfParts.p[0], 1, MPI_INT, m_respawnDomain, mpiComm(), AT_, "INPLACE",
3141 "arrayNoOfParts");
3142
3144
3145 MInt globalNoRespawnPart = 0;
3146 for(MInt i = 0; i < noDomains(); ++i) {
3147 globalNoRespawnPart += arrayNoOfParts.p[i];
3148 arrayNoOfParts.p[i] *= respawnSize;
3149 }
3150 MIntScratchSpace displs((noDomains() + 1), AT_, "displs");
3151 displs.p[0] = 0;
3152 for(MInt i = 1; i <= noDomains(); ++i) {
3153 displs.p[i] = displs.p[i - 1] + arrayNoOfParts.p[i - 1];
3154 }
3155
3156 MFloatScratchSpace recvbuf(max(displs.p[noDomains()], 1), AT_, "recvbuf");
3157 MInt counter = displs.p[m_respawnDomain];
3158 while(!partRespawnList.empty()) {
3159 thisPart = partRespawnList.front();
3160 recvbuf.p[counter++] = MFloat(thisPart.partId);
3161 recvbuf.p[counter++] = thisPart.diam;
3162 recvbuf.p[counter++] = thisPart.densRatio;
3163 partRespawnList.pop_front(); // partQueue.pop();
3164 }
3165 MPI_Gatherv(MPI_IN_PLACE, arrayNoOfParts.p[m_respawnDomain], MPI_DOUBLE, &recvbuf.p[0], &arrayNoOfParts.p[0],
3166 &displs.p[0], MPI_DOUBLE, m_respawnDomain, mpiComm(), AT_, "INPLACE", "m_respawnDomain");
3167
3168 // generate random things on top of the id, dia, densRation. 1 which cell, 2 random values for
3169 // coordinates
3170 MIntScratchSpace bufferSizes(m_noRespawnDomains, AT_, "bufferSizes");
3171 for(MInt domain = 0; domain < m_noRespawnDomains; ++domain) {
3172 bufferSizes.p[domain] = 0;
3173 }
3174 MIntScratchSpace cellIds(globalNoRespawnPart, AT_, "cellIds");
3175 MFloatScratchSpace randCoord1(globalNoRespawnPart, AT_, "randCoord1");
3176 MFloatScratchSpace randCoord2(globalNoRespawnPart, AT_, "randCoord2");
3177 uniform_int_distribution<MInt> dist_cells(0, m_respawnGlobalDomainOffsets[m_noRespawnDomains] - 1);
3178 uniform_real_distribution<MFloat> dist_coord(0, 1);
3179 for(MInt i = 0; i < globalNoRespawnPart; ++i) {
3180 cellIds.p[i] = dist_cells(randomRespawn());
3181 randCoord1.p[i] = dist_coord(randomRespawn()) - 0.5;
3182 randCoord2.p[i] = dist_coord(randomRespawn()) - 0.5;
3183
3184 for(MInt domain = 1; domain <= m_noRespawnDomains; ++domain) {
3185 if(cellIds.p[i] < m_respawnGlobalDomainOffsets[domain]) {
3186 bufferSizes.p[domain - 1] += 1;
3187 break;
3188 }
3189 }
3190 }
3191 MInt ownRankInRespawnDomains = -1;
3192 ScratchSpace<MPI_Request> receiveRequest(m_noRespawnDomains, AT_, "receiveRequest");
3193 for(MInt i = 0; i < m_noRespawnDomains; ++i) {
3194 receiveRequest[i] = MPI_REQUEST_NULL;
3195 if(m_respawnDomainRanks[i] == domainId()) {
3196 ownRankInRespawnDomains = i;
3197 continue;
3198 }
3199
3200 MPI_Isend(&bufferSizes.p[i], 1, MPI_INT, m_respawnDomainRanks[i], LPT_MPI_PARTICLE_RESPAWN_TAG, mpiComm(),
3201 &receiveRequest[i], AT_, "bufferSizes");
3202 }
3203 MIntScratchSpace countsPerDomain(m_noRespawnDomains, AT_, "countsPerDomain");
3204 countsPerDomain.p[0] = 0;
3205 for(MInt domain = 1; domain < m_noRespawnDomains; ++domain) {
3206 countsPerDomain.p[domain] = countsPerDomain.p[domain - 1];
3207 if((domain - 1) != ownRankInRespawnDomains) {
3208 countsPerDomain.p[domain] += bufferSizes.p[domain - 1] * respawnSendSize;
3209 }
3210 }
3211 MFloatScratchSpace sendbuf(respawnSendSize * (globalNoRespawnPart - bufferSizes.p[ownRankInRespawnDomains]), AT_,
3212 "sendbuf");
3213 for(MInt i = 0; i < globalNoRespawnPart; ++i) {
3214 MInt thisDomain = -1;
3215 for(MInt domain = 1; domain <= m_noRespawnDomains; ++domain) {
3216 if(cellIds.p[i] < m_respawnGlobalDomainOffsets[domain]) {
3217 thisDomain = domain - 1;
3218 break;
3219 }
3220 }
3221 if(thisDomain == ownRankInRespawnDomains) {
3222 continue;
3223 }
3224 MInt address = countsPerDomain.p[thisDomain];
3225 for(MInt inner = 0; inner < respawnSize; ++inner) {
3226 sendbuf.p[address + inner] = recvbuf.p[i * respawnSize + inner];
3227 }
3228 sendbuf.p[address + respawnSize + 0] = MFloat(cellIds.p[i] - m_respawnGlobalDomainOffsets[thisDomain]);
3229 sendbuf.p[address + respawnSize + 1] = randCoord1.p[i];
3230 sendbuf.p[address + respawnSize + 2] = randCoord2.p[i];
3231
3232 countsPerDomain.p[thisDomain] += respawnSendSize;
3233 }
3234 // reset countsPerDomain
3235 countsPerDomain.p[0] = 0;
3236 for(MInt domain = 1; domain < m_noRespawnDomains; ++domain) {
3237 countsPerDomain.p[domain] = countsPerDomain.p[domain - 1];
3238 if((domain - 1) != ownRankInRespawnDomains) {
3239 countsPerDomain.p[domain] += bufferSizes.p[domain - 1] * respawnSendSize;
3240 }
3241 }
3242 MPI_Waitall(m_noRespawnDomains, &receiveRequest[0], MPI_STATUSES_IGNORE, AT_);
3243 for(MInt domain = 0; domain < m_noRespawnDomains; ++domain) {
3244 if((domain == ownRankInRespawnDomains) || (bufferSizes.p[domain] == 0)) {
3245 receiveRequest[domain] = MPI_REQUEST_NULL;
3246 } else {
3247 MInt address = countsPerDomain.p[domain];
3248 MPI_Isend(&sendbuf.p[address], bufferSizes.p[domain] * respawnSendSize, MPI_DOUBLE,
3249 m_respawnDomainRanks[domain], LPT_MPI_PARTICLE_RESPAWN_TAG, mpiComm(), &receiveRequest[domain], AT_,
3250 "sendbuf");
3251 }
3252 }
3253
3254 // auspacken
3255 if(bufferSizes.p[ownRankInRespawnDomains] != 0) {
3256 for(MInt i = 0; i < globalNoRespawnPart; ++i) {
3257 if((cellIds.p[i] < m_respawnGlobalDomainOffsets[ownRankInRespawnDomains + 1])
3258 && (cellIds.p[i] >= m_respawnGlobalDomainOffsets[ownRankInRespawnDomains])) {
3259 LPTSpherical<nDim> thisParticle;
3260 MFloat x[3];
3261 MFloat v[3];
3262
3263 counter = i * respawnSize;
3264 MInt id = cellIds.p[i] - m_respawnGlobalDomainOffsets[ownRankInRespawnDomains];
3265 // obtain random positions within this cell
3266 MFloat cellLength = c_cellLengthAtCell(m_respawnCells.at((MUlong)id));
3267
3268 x[m_respawn - 1] = m_respawnPlane;
3269
3270 x[m_respawn % 3] =
3271 cellLength * randCoord1.p[i] + c_coordinate(m_respawnCells.at((MUlong)id), m_respawn % 3);
3272 x[(m_respawn + 1) % 3] =
3273 cellLength * randCoord2.p[i] + c_coordinate(m_respawnCells.at((MUlong)id), (m_respawn + 1) % 3);
3274
3275 thisParticle.m_cellId = m_respawnCells.at((MUlong)id);
3276 thisParticle.m_partId = MInt(recvbuf.p[counter++]);
3277 thisParticle.m_diameter = recvbuf.p[counter++];
3278 thisParticle.m_densityRatio = recvbuf.p[counter];
3279 thisParticle.updateProperties();
3280 thisParticle.firstStep() = true;
3281 interpolateVariablesLS<0, nDim>(m_respawnCells[id], x, v);
3282 for(MInt j = 0; j < nDim; j++) {
3283 thisParticle.m_position[j] = x[j];
3284 thisParticle.m_oldPos[j] = x[j];
3285 thisParticle.m_velocity[j] =
3286 v[j] + m_terminalVelocity[thisParticle.m_diameter] * m_partList[0].s_Frm[j] / m_FrMag;
3287 thisParticle.m_oldVel[j] =
3288 v[j] + m_terminalVelocity[thisParticle.m_diameter] * m_partList[0].s_Frm[j] / m_FrMag;
3289 thisParticle.m_accel[j] = F0;
3290 thisParticle.m_oldFluidVel[j] = a_fluidVelocity(thisParticle.m_cellId, j);
3291 }
3292
3293 thisParticle.m_oldFluidDensity = a_fluidDensity(thisParticle.m_cellId);
3294
3295 m_partList.push_back(thisParticle);
3296 }
3297 }
3298 }
3299
3300 MPI_Waitall(m_noRespawnDomains, &receiveRequest[0], MPI_STATUSES_IGNORE, AT_);
3301 } else {
3302 MInt noPartsToRespawn = 0;
3303 MPI_Request receiveRequest = MPI_REQUEST_NULL;
3304 if(!m_respawnCells.empty()) {
3305 MPI_Irecv(&noPartsToRespawn, 1, MPI_INT, m_respawnDomain, LPT_MPI_PARTICLE_RESPAWN_TAG, mpiComm(),
3306 &receiveRequest, AT_, "noPartsToRespawn");
3307 }
3308
3309 auto localNoOfParts = (MInt)partRespawnList.size();
3310 MPI_Gather(&localNoOfParts, 1, MPI_INT, nullptr, 1, MPI_INT, m_respawnDomain, mpiComm(), AT_, "localNoOfParts",
3311 "nullptr");
3312 MFloatScratchSpace sendbuf(max(localNoOfParts, 1) * respawnSize, AT_, "sendbuf");
3313 MInt counter = 0;
3314 while(!partRespawnList.empty()) {
3315 thisPart = partRespawnList.front();
3316 sendbuf.p[counter++] = MFloat(thisPart.partId);
3317 sendbuf.p[counter++] = thisPart.diam;
3318 sendbuf.p[counter++] = thisPart.densRatio;
3319 partRespawnList.pop_front(); // partQueue.pop();
3320 }
3321
3322 MPI_Gatherv(&sendbuf.p[0], localNoOfParts * respawnSize, MPI_DOUBLE, nullptr, nullptr, nullptr, MPI_DOUBLE,
3323 m_respawnDomain, mpiComm(), AT_, "sendbuf", "nullptr");
3324
3325 if(!m_respawnCells.empty()) {
3326 MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE, AT_);
3327
3328 if(noPartsToRespawn != 0) {
3329 MFloatScratchSpace recvbuf(noPartsToRespawn * respawnSendSize, AT_, "recvbuf");
3330 MPI_Recv(&recvbuf.p[0], noPartsToRespawn * respawnSendSize, MPI_DOUBLE, m_respawnDomain,
3331 LPT_MPI_PARTICLE_RESPAWN_TAG, mpiComm(), MPI_STATUS_IGNORE, AT_, "recvbuf");
3332
3333 for(MInt part = 0; part < noPartsToRespawn; ++part) {
3334 LPTSpherical<nDim> thisParticle;
3335 MInt id;
3336 MInt address;
3337 MFloat x[3];
3338 MFloat v[3];
3339
3340 address = part * respawnSendSize;
3341 id = MInt(recvbuf.p[address + respawnSize + 0]);
3342 MFloat cellLength = c_cellLengthAtCell(m_respawnCells.at((MUlong)id));
3343
3344 x[m_respawn - 1] = m_respawnPlane;
3345
3346 x[m_respawn % 3] = cellLength * recvbuf.p[address + respawnSize + 1]
3348 x[(m_respawn + 1) % 3] = cellLength * recvbuf.p[address + respawnSize + 2]
3349 + c_coordinate(m_respawnCells.at((MUlong)id), (m_respawn + 1) % 3);
3350 thisParticle.m_cellId = m_respawnCells.at((MUlong)id);
3351 thisParticle.m_partId = MInt(recvbuf.p[address + 0]);
3352 thisParticle.m_diameter = recvbuf.p[address + 1];
3353 thisParticle.m_densityRatio = recvbuf.p[address + 2];
3354 thisParticle.updateProperties();
3355 thisParticle.firstStep() = true;
3356 interpolateVariablesLS<0, nDim>(m_respawnCells[id], x, v);
3357 for(MInt j = 0; j < nDim; j++) {
3358 thisParticle.m_position[j] = x[j];
3359 thisParticle.m_oldPos[j] = x[j];
3360 thisParticle.m_velocity[j] =
3361 v[j] + m_terminalVelocity[thisParticle.m_diameter] * m_partList[0].s_Frm[j] / m_FrMag;
3362 thisParticle.m_oldVel[j] =
3363 v[j] + m_terminalVelocity[thisParticle.m_diameter] * m_partList[0].s_Frm[j] / m_FrMag;
3364 thisParticle.m_accel[j] = F0;
3365 thisParticle.m_oldFluidVel[j] = a_fluidVelocity(thisParticle.m_cellId, j);
3366 }
3367 thisParticle.m_oldFluidDensity = a_fluidDensity(thisParticle.m_cellId);
3368 m_partList.push_back(thisParticle);
3369 }
3370 }
3371 }
3372 }
3373 }
3374 if(m_ellipsoids) {
3375 mTerm(-1, AT_, "particleRespawn not implemented for ellipsoidal particle");
3376 }
3377}
std::mt19937_64 & randomRespawn()
Definition: lpt.h:741
MFloat m_respawnPlane
Definition: lpt.h:782
MFloat m_FrMag
Definition: lpt.h:774
std::map< MFloat, MFloat > m_terminalVelocity
Definition: lpt.h:571
@ LPT_MPI_PARTICLE_RESPAWN_TAG
Definition: enums.h:20
uint64_t MUlong
Definition: maiatypes.h:65
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_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
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
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall

◆ particleWallCollisionStep()

template<MInt nDim>
void LPT< nDim >::particleWallCollisionStep ( const  MInt)
private

◆ perCellStats()

template<MInt nDim>
void LPT< nDim >::perCellStats
private
Author
Sven Berger

Definition at line 2780 of file lpt.cpp.

2780 {
2781 TRACE();
2782
2783 // sort particles after id to make results consistent and faster searching!
2784 // own_sort(m_partList, sort_particleAfterPartIds<LPTSpherical<nDim>>::compare);
2785
2786 // update mapping from cellId to particles
2787 m_cellToPartMap.clear();
2788 // generate mapping cell to particles
2789 for(MInt i = 0; i < a_noParticles(); i++) {
2790 m_cellToPartMap.insert({m_partList[i].m_cellId, &m_partList[i]});
2791 ASSERT(!a_isHalo(m_partList[i].m_cellId), "Particle in halo-cell!");
2792 }
2793 if(m_ellipsoids) {
2794 m_cellToEllipsMap.clear();
2795 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
2797 ASSERT(!a_isHalo(m_partListEllipsoid[i].m_cellId), "Ellipsoid in halo-cell!");
2798 }
2799 }
2800}

◆ postAdaptation()

template<MInt nDim>
void LPT< nDim >::postAdaptation
overridevirtual

Reimplemented from Solver.

Definition at line 1394 of file lpt.cpp.

1394 {
1395 TRACE();
1396
1397 this->compactCells();
1398
1399 m_freeIndices.clear();
1400
1401 grid().updateOther();
1402
1404 this->checkNoHaloLayers();
1405
1406 if(!isActive()) return;
1407
1408 grid().updateLeafCellExchange();
1409 initMPI(true);
1410
1411 if(globalTimeStep < 0) {
1413 if(m_spawnCellId > -1) {
1416 }
1417 }
1418
1419 this->exchangeData(&a_noParticlesInCell(0), 1);
1420 this->exchangeData(&a_bndryCellId(0), 1);
1422
1424
1426}
MInt m_adaptationLevel
Definition: lpt.h:822
std::set< MInt > m_freeIndices
Definition: solver.h:101
void compactCells()
Removes all holes in the cell collector and moves halo cells to the back of the collector.
void exchangeData(T *data, const MInt dataBlockSize=1)
Exchange memory in 'data' assuming a solver size of 'dataBlockSize' per cell.

◆ postTimeStep()

template<MInt nDim>
void LPT< nDim >::postTimeStep
overridevirtual
Date
November-20
Author
Tim Wegmann

Implements Solver.

Definition at line 2512 of file lpt.cpp.

2512 {
2513 TRACE();
2514
2515 NEW_TIMER_GROUP_STATIC(t_post, "LPT postTimeStep");
2516 NEW_TIMER_STATIC(postTS, "postTimeStep", t_post);
2517
2518 RECORD_TIMER_START(postTS);
2519
2520 if(m_skipLPT) {
2521 return;
2522 }
2523 if(m_sleepLPT > 0.0) {
2524 std::this_thread::sleep_for(std::chrono::milliseconds(m_sleepLPT));
2525 }
2526
2527 // some debug checks
2529 checkCells();
2530
2531 m_solutionStep = 0;
2532
2533
2536
2537 RECORD_TIMER_STOP(postTS);
2538}
MInt m_sleepLPT
Definition: lpt.h:540
void advanceParticles(const MInt offset)
Definition: lpt.cpp:3041

◆ prepareAdaptation()

template<MInt nDim>
void LPT< nDim >::prepareAdaptation
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1214 of file lpt.cpp.

1214 {
1215 TRACE();
1216
1217 ASSERT(m_freeIndices.empty(), "");
1219 m_forceAdaptation = false;
1220
1221 if(!isActive()) {
1222 return;
1223 }
1224
1228
1229 if(globalTimeStep > 0) {
1231 }
1232
1233 // add refinement around spawnCellId!
1234 // NOTE: a_noParticlesInCell will be corrected after the adaptation!
1235 if(m_spawnCellId > -1) {
1238 }
1239
1240 this->exchangeData(&a_noParticlesInCell(0), 1);
1242
1243
1244 // add fluxes to window-cells
1245 if(!m_nonBlockingComm) {
1247 } else {
1251 }
1252 // reset fluxes on halo-cells
1254
1255 // set bndry-Cell Id for adaptation on leaf-cells and all parants
1256 // and exchange information, to set this on halo-cells and
1257 // partition level-shift ancestors in a different rank
1258 // as required for interface sensor!!
1259 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
1260 a_bndryCellId(cellId) = -1;
1261 }
1262 for(MInt id = 0; id < m_bndryCells->size(); id++) {
1263 const MInt cellId = m_bndryCells->a[id].m_cellId;
1264 a_bndryCellId(cellId) = 1;
1265 MInt parentId = c_parentId(cellId);
1266 while(parentId > -1 && parentId < a_noCells()) {
1267 a_bndryCellId(parentId) = 1;
1268 parentId = c_parentId(parentId);
1269 }
1270 }
1271 this->exchangeData(&a_bndryCellId(0), 1);
1272
1273 // remove all bndryCells
1274 if(m_wallCollisions) {
1277 }
1278}
MBool m_wallCollisions
Definition: lpt.h:789
MInt c_parentId(const MInt cellId) const
Definition: lpt.h:960

◆ prepareRestart()

template<MInt nDim>
MBool LPT< nDim >::prepareRestart ( MBool  force,
MBool writeGridRestart 
)
overridevirtual
Date
November-20
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 2547 of file lpt.cpp.

2547 {
2548 MBool writeRestart = false;
2549
2550 if((((globalTimeStep % this->m_restartInterval) == 0 && (globalTimeStep > m_restartTimeStep)) || force)) {
2551 if(isActive()) {
2553 if(!m_nonBlockingComm) {
2555 } else {
2561 }
2562 }
2563 writeRestart = true;
2564 }
2565
2566 if(m_restart && !m_restartFile) writeGridRestart = true;
2567
2568 return (force || writeRestart);
2569}
MInt m_restartTimeStep
Definition: lpt.h:950
MInt m_restartInterval
The number of timesteps before writing the next restart file.
Definition: solver.h:79

◆ preTimeStep()

template<MInt nDim>
void LPT< nDim >::preTimeStep
overridevirtual
Date
November-20
Author
Tim Wegmann

Implements Solver.

Definition at line 2069 of file lpt.cpp.

2069 {
2070 TRACE();
2071
2072 RECORD_TIMER_START(m_timers[Timers::PreTime]);
2073
2074 // Exchange flow field wich has been set by one or more flow solver via the coupler(s)
2075 // exchangeData(&a_fluidVariable(0, 0), nDim+2);
2076
2077 // m_partCellMapCurrent = false;
2078
2079 // advanceTimeStep
2080 m_time += m_timeStep;
2081 ASSERT(m_timeStep > MFloatEps, "TS not set!");
2082
2083
2085 m_timeStepUpdated = false;
2086 m_sumEvapMass = 0;
2088
2089 if(m_skipLPT) {
2090 return;
2091 }
2092
2094
2095 // reset creation time of all particles
2096 for(MInt i = 0; i < a_noParticles(); i++) {
2097 m_partList[i].m_creationTime = 0.0;
2098 }
2099 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
2100 m_partListEllipsoid[i].m_creationTime = 0.0;
2101 }
2102
2103 RECORD_TIMER_STOP(m_timers[Timers::PreTime]);
2104}
MFloat m_timeStepOld
Definition: lpt.h:574

◆ pushToQueue()

template<MInt nDim>
template<class LPTParticle >
MBool LPT< nDim >::pushToQueue ( std::vector< std::map< MInt, MInt > > &  pointsTo,
const MInt  partPos 
)
inline

Definition at line 509 of file lpt.h.

509 {
510 std::vector<LPTParticle>& partList = a_particleList<LPTParticle>();
512 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
513 auto pos = pointsTo[d].find(partList[partPos].m_cellId);
514 // particle is inside a halo cell so send it...
515 if(pos != pointsTo[d].end()) {
516 thisSend.partPos = partPos;
517 thisSend.toCellId = pos->second;
518 m_queueToSend[d].push(thisSend);
519 return true;
520 }
521 }
522 return false;
523 }

◆ randomInit()

template<MInt nDim>
std::mt19937_64 & LPT< nDim >::randomInit ( )
inlineprotected

Definition at line 745 of file lpt.h.

745 {
746 ASSERT(!m_restart, "");
747 return m_PRNGInit;
748 }
std::mt19937_64 m_PRNGInit
Definition: lpt.h:564

◆ randomRespawn()

template<MInt nDim>
std::mt19937_64 & LPT< nDim >::randomRespawn ( )
inlineprotected

Definition at line 741 of file lpt.h.

741 {
742 ASSERT(domainId() == m_respawnDomain, "");
743 return m_PRNGRespawn;
744 }
std::mt19937_64 m_PRNGRespawn
Definition: lpt.h:561

◆ randomSpawn()

template<MInt nDim>
std::mt19937_64 & LPT< nDim >::randomSpawn ( const MInt  calls)
inlineprotected

Definition at line 736 of file lpt.h.

736 {
737 ASSERT(domainId() == m_spawnDomainId, "");
738 m_PRNGSpawnCount += calls;
739 return m_PRNGSpawn;
740 }

◆ readEllipsoidProps()

template<MInt nDim>
void LPT< nDim >::readEllipsoidProps ( )
private
Author
Sven Berger
Date
September 2016

◆ readModelProps()

template<MInt nDim>
void LPT< nDim >::readModelProps ( )
private
Author
Sven Berger, Tim Wegmann
Date
August 2015

◆ readMomentumCouplingProps()

template<MInt nDim>
void LPT< nDim >::readMomentumCouplingProps ( )
private
Author
Sven Berger
Date
September 2016

◆ readSpawnProps()

template<MInt nDim>
void LPT< nDim >::readSpawnProps ( )
private
Author
Sven Berger
Date
March 2016

◆ receiveFlowField()

template<MInt nDim>
void LPT< nDim >::receiveFlowField
protected
Author
Tim Wegmann

Definition at line 7784 of file lpt.cpp.

7784 {
7785 if(!m_nonBlockingComm) return;
7786 if(!m_receiveFlowField) return;
7787
7788 RECORD_TIMER_START(m_timers[Timers::Exchange]);
7789
7790 MPI_Waitall(grid().noLeafRecvNeighborDomains(), &m_flowRecvRequest[0], MPI_STATUSES_IGNORE, AT_);
7791
7792 // set data on halo-cells
7793 RECORD_TIMER_START(m_timers[Timers::Exchange5]);
7794 for(MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
7795 const MInt d = grid().leafRecvNeighborDomain(n);
7796 MInt buffId = 0;
7797 for(MInt j = 0; j < grid().noLeafHaloCells(d); j++) {
7798 const MInt cellId = grid().leafHaloCell(d, j);
7799 std::copy_n(&m_flowRecv[d][buffId], PV.noVars(), &a_fluidVariable(cellId, 0));
7800 buffId += PV.noVars();
7801 if(m_evaporation) {
7802 std::copy_n(&m_flowRecv[d][buffId], 1, &a_fluidSpecies(cellId));
7803 buffId++;
7804 }
7805 }
7806 }
7807
7808 RECORD_TIMER_STOP(m_timers[Timers::Exchange5]);
7809 RECORD_TIMER_STOP(m_timers[Timers::Exchange]);
7810 m_receiveFlowField = false;
7811}
MBool m_receiveFlowField
Definition: lpt.h:616

◆ receiveParticles()

template<MInt nDim>
template<MBool allNeighbors>
void LPT< nDim >::receiveParticles
protected
Author
Laurent Andre

Definition at line 3836 of file lpt.cpp.

3836 {
3837 if(m_ellipsoids) {
3838 receiveParticles_<allNeighbors, LPTEllipsoidal<nDim>>();
3839 } else {
3840 receiveParticles_<allNeighbors, LPTSpherical<nDim>>();
3841 }
3842}

◆ receiveParticles_()

template<MInt nDim>
template<MBool allNeighbors, class LPTParticle >
void LPT< nDim >::receiveParticles_
protected
Author
Tim Wegmann

Definition at line 3851 of file lpt.cpp.

3851 {
3852 TRACE();
3853
3854 if(m_nonBlockingStage < 1) {
3855 mTerm(1, AT_, "Incorrect non-blocking stage!");
3856 }
3857 RECORD_TIMER_START(m_timers[Timers::Exchange]);
3858 RECORD_TIMER_START(m_timers[Timers::Exchange1]);
3859
3860 RECORD_TIMER_START(m_timers[Timers::Exchange4]);
3861
3862 // 1) Probe and get count of the receiving int-buffer
3863 // to find the number received particles for each rank
3864 // from all ranks, which could not be received at the send-stage
3865
3866 const MBool loadWasRunning = this->isLoadTimerRunning();
3867 if(loadWasRunning) {
3868 this->stopLoadTimer(AT_);
3869 this->startIdleTimer(AT_);
3870 this->disableDlbTimers();
3871 }
3872
3873 const MInt noNeighborsRecv = allNeighbors ? grid().noNeighborDomains() : grid().noLeafRecvNeighborDomains();
3874
3875 MBool allReceived = false;
3876 while(!allReceived) {
3877 // check if all have been received
3878 allReceived = true;
3879 for(MInt n = 0; n < noNeighborsRecv; n++) {
3880 MInt d = n;
3881 if(!allNeighbors) {
3882 d = grid().leafRecvNeighborDomain(n);
3883 }
3884 if(m_recvSize[d] == -99) {
3885 allReceived = false;
3886 break;
3887 }
3888 }
3889
3890 // loop aver all domains and check for receive again
3891 for(MInt n = 0; n < noNeighborsRecv; n++) {
3892 MInt d = n;
3893 if(!allNeighbors) {
3894 d = grid().leafRecvNeighborDomain(n);
3895 }
3896 MInt flag{};
3897 MPI_Iprobe(grid().neighborDomain(d), mpiTag("PARTICLE_INT"), mpiComm(), &flag, &m_mpi_statusProbe[n],
3898 "statusProbe");
3899 if(flag) {
3900 MPI_Get_count(&m_mpi_statusProbe[n], MPI_INT, &m_recvSize[d], "m_intRecvBuffer");
3901 m_recvSize[d] = m_recvSize[d] / intElemPerP<LPTParticle>();
3902 MPI_Irecv(&m_intRecvBuffer[d][0], m_recvSize[d] * intElemPerP<LPTParticle>(), MPI_INT, grid().neighborDomain(d),
3903 mpiTag("PARTICLE_INT"), mpiComm(), &m_mpi_reqRecvInt[n], AT_, "m_intRecvBuffer");
3904
3905 if(m_recvSize[d] > 0) {
3906 MPI_Irecv(&m_recvBuffer[d][0], m_recvSize[d] * elemPerP<LPTParticle>(), MPI_DOUBLE, grid().neighborDomain(d),
3907 mpiTag("PARTICLE_FLOAT"), mpiComm(), &m_mpi_reqRecvFloat[n], AT_, "m_recvBuffer");
3908 } else {
3909 m_mpi_reqRecvFloat[n] = MPI_REQUEST_NULL;
3910 }
3911 }
3912 }
3913 }
3914
3915 if(loadWasRunning) {
3916 this->reEnableDlbTimers();
3917 this->stopIdleTimer(AT_);
3918 this->startLoadTimer(AT_);
3919 }
3920
3921 RECORD_TIMER_STOP(m_timers[Timers::Exchange4]);
3922
3923 // 1) wait until I have received all
3924 MPI_Waitall(noNeighborsRecv, &m_mpi_reqRecvFloat[0], MPI_STATUSES_IGNORE, AT_);
3925 MPI_Waitall(noNeighborsRecv, &m_mpi_reqRecvInt[0], MPI_STATUSES_IGNORE, AT_);
3926
3927
3928 RECORD_TIMER_START(m_timers[Timers::Exchange5]);
3929
3930 MBool allowNonLeaf = false;
3931 if(m_nonBlockingStage == 2) allowNonLeaf = true;
3932
3933 // 2) interpret the receive buffers and add incomming particles
3934 for(MInt n = 0; n < noNeighborsRecv; n++) {
3935 MInt d = n;
3936 if(!allNeighbors) {
3937 d = grid().leafRecvNeighborDomain(n);
3938 }
3939 // nothing to receive skip
3940 if(m_recvSize[d] == 0) continue;
3941 if(!m_periodicBC) {
3942 unpackParticles<LPTParticle, false>(m_recvSize[d], &m_intRecvBuffer[d][0], &m_recvBuffer[d][0], d, allowNonLeaf);
3943 } else {
3944 unpackParticles<LPTParticle, true>(m_recvSize[d], &m_intRecvBuffer[d][0], &m_recvBuffer[d][0], d, allowNonLeaf);
3945 }
3946 }
3947
3948 RECORD_TIMER_STOP(m_timers[Timers::Exchange5]);
3949
3950 RECORD_TIMER_STOP(m_timers[Timers::Exchange1]);
3952 RECORD_TIMER_STOP(m_timers[Timers::Exchange]);
3953}
MInt mpiTag(const MString exchangeType)
Definition: lpt.h:323
MBool isLoadTimerRunning()
Definition: solver.h:303
void stopIdleTimer(const MString &name)
Definition: solver.h:297
void startIdleTimer(const MString &name)
Definition: solver.h:299
void reEnableDlbTimers()
Definition: solver.h:286
void disableDlbTimers()
Definition: solver.h:289
MInt neighborDomain(const MInt id) const
int MPI_Get_count(const MPI_Status *status, MPI_Datatype datatype, int *count, const MString &name)
same as MPI_Get_count
int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *flag, MPI_Status *status, const MString &name)
Iprobe MPI to get status without actually receiving the message.

◆ receiveSourceTerms()

template<MInt nDim>
void LPT< nDim >::receiveSourceTerms
protected
Author
Tim Wegmann

Definition at line 7699 of file lpt.cpp.

7699 {
7700 if(!m_nonBlockingComm) return;
7701
7702 RECORD_TIMER_START(m_timers[Timers::Exchange]);
7703
7704 // wait for all receives before using buffers
7705 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_sourceRecvRequest[0], MPI_STATUSES_IGNORE, AT_);
7706
7707 // add received source terms
7708 RECORD_TIMER_START(m_timers[Timers::Exchange5]);
7709
7710 for(MInt n = 0; n < grid().noLeafSendNeighborDomains(); n++) {
7711 const MInt d = grid().leafSendNeighborDomain(n);
7712 MInt buffId = 0;
7713 for(MInt j = 0; j < grid().noLeafWindowCells(d); j++) {
7714 const MInt cellId = grid().leafWindowCell(d, j);
7715 if(m_massCoupling) {
7716 a_massFlux(cellId) += m_sourceRecv[d][buffId++];
7717 }
7718 if(m_momentumCoupling) {
7719 for(MInt i = 0; i < nDim; i++) {
7720 a_momentumFlux(cellId, i) += m_sourceRecv[d][buffId++];
7721 }
7722 a_workFlux(cellId) += m_sourceRecv[d][buffId++];
7723 }
7724 if(m_heatCoupling) {
7725 a_heatFlux(cellId) += m_sourceRecv[d][buffId++];
7726 }
7727 }
7728 }
7729
7730 RECORD_TIMER_STOP(m_timers[Timers::Exchange5]);
7731 RECORD_TIMER_STOP(m_timers[Timers::Exchange]);
7732}

◆ receiveVelocitySlopes()

template<MInt nDim>
void LPT< nDim >::receiveVelocitySlopes
protected
Author
Laurent Andre

Definition at line 7901 of file lpt.cpp.

7901 {
7902 if(!m_ellipsoids) return; // only if ellipsoids are activated
7903 if(!m_nonBlockingComm) return;
7904 if(!m_receiveVelocitySlopes) return;
7905
7906 RECORD_TIMER_START(m_timers[Timers::Exchange]);
7907
7908 MPI_Waitall(grid().noLeafRecvNeighborDomains(), &m_slopesRecvRequest[0], MPI_STATUSES_IGNORE, AT_);
7909
7910 // set data on halo-cells
7911 RECORD_TIMER_START(m_timers[Timers::Exchange5]);
7912 for(MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
7913 const MInt d = grid().leafRecvNeighborDomain(n);
7914 MInt buffId = 0;
7915 for(MInt j = 0; j < grid().noLeafHaloCells(d); j++) {
7916 const MInt cellId = grid().leafHaloCell(d, j);
7917 std::copy_n(&m_slopesRecv[d][buffId], nDim * nDim, &a_velocitySlope(cellId, 0, 0));
7918 buffId += nDim * nDim;
7919 }
7920 }
7921
7922 RECORD_TIMER_STOP(m_timers[Timers::Exchange5]);
7923 RECORD_TIMER_STOP(m_timers[Timers::Exchange]);
7924
7926}
MBool m_receiveVelocitySlopes
Definition: lpt.h:617

◆ recvInjected()

template<MInt nDim>
void LPT< nDim >::recvInjected
private
Author
Sven Berger
Date
September 2018

Definition at line 5812 of file lpt.cpp.

5812 {
5813 TRACE();
5814
5815 MInt partReceive = 0;
5816
5817 // wait for number
5818 MPI_Bcast(&partReceive, 1, MPI_INT, m_spawnDomainId, mpiComm(), AT_, "part");
5819
5820#ifndef NDEBUG
5821 MInt noParticlesB = -static_cast<MInt>(m_partList.size());
5822 // Note: cast to signed type first to prevent overflow
5823#endif
5824
5825 if(partReceive > 0) {
5826 // receive
5827 MPI_Bcast(&m_intRecvBuffer[0][0], partReceive * intElemPerP<LPTSpherical<nDim>>(), MPI_INT, m_spawnDomainId,
5828 mpiComm(), AT_, "buffer");
5829 MPI_Bcast(&m_recvBuffer[0][0], partReceive * elemPerP<LPTSpherical<nDim>>(), MPI_DOUBLE, m_spawnDomainId, mpiComm(),
5830 AT_, "buffer");
5831
5832 // unpack and check whether they are on this domain
5833 unpackParticles<LPTSpherical<nDim>, true>(partReceive, m_intRecvBuffer[0].get(), m_recvBuffer[0].get());
5834 }
5835
5836#ifndef NDEBUG
5837 noParticlesB += m_partList.size();
5838 MPI_Allreduce(MPI_IN_PLACE, &noParticlesB, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noParticlesB");
5839#endif
5840}

◆ recvRegridTrigger()

template<MInt nDim>
void LPT< nDim >::recvRegridTrigger
private

Definition at line 7507 of file lpt.cpp.

7507 {
7508 if(!m_nonBlockingComm) {
7509 return;
7510 }
7511 if(!isActive()) {
7512 return;
7513 }
7514
7515 // wait for all send and receive
7516 if(m_openRegridSend) {
7517 RECORD_TIMER_START(m_timers[Timers::Exchange]);
7518 RECORD_TIMER_START(m_timers[Timers::Exchange2]);
7519 MPI_Wait(&m_checkAdaptationRecvRequest[0], MPI_STATUS_IGNORE, AT_);
7520 m_openRegridSend = false;
7521 RECORD_TIMER_STOP(m_timers[Timers::Exchange2]);
7522 RECORD_TIMER_STOP(m_timers[Timers::Exchange]);
7523 }
7524}

◆ reduceData()

template<MInt nDim>
MFloat LPT< nDim >::reduceData ( const MInt  cellId,
MFloat data,
const MInt  dataBlockSize = 1,
const MBool  average = true 
)
Author
Tim Wegmann

Definition at line 8020 of file lpt.cpp.

8020 {
8021 MFloat vol = a_bndryCellId(cellId) < 0 ? c_cellVolume(cellId) : m_bndryCells->a[a_bndryCellId(cellId)].m_volume;
8022
8023 if(c_noChildren(cellId) > 0) {
8024 vol = F0;
8025 for(MInt d = 0; d < dataBlockSize; d++) {
8026 data[dataBlockSize * cellId + d] = F0;
8027 }
8028 for(MInt child = 0; child < c_noChildren(cellId); child++) {
8029 MInt childId = c_childId(cellId, child);
8030 if(childId < 0) {
8031 continue;
8032 }
8033 if(c_noChildren(childId) == 0 && !a_isValidCell(childId)) {
8034 continue;
8035 }
8036 MFloat volc = reduceData(childId, data, dataBlockSize);
8037 for(MInt d = 0; d < dataBlockSize; d++) {
8038 data[dataBlockSize * cellId + d] += volc * data[dataBlockSize * childId + d];
8039 }
8040 vol += volc;
8041 }
8042 if(average) {
8043 for(MInt d = 0; d < dataBlockSize; d++) {
8044 data[dataBlockSize * cellId + d] /= mMax(1e-14, vol);
8045 }
8046 }
8047 }
8048 return vol;
8049}
MFloat c_cellVolume(const MInt cellId) const
Definition: lpt.h:970
MInt c_childId(const MInt cellId, const MInt pos) const
Definition: lpt.h:956
MFloat reduceData(const MInt cellId, MFloat *data, const MInt dataBlockSize=1, const MBool average=true)
reduce data to lower level
Definition: lpt.cpp:8020

◆ reduceParticles()

template<MInt nDim>
void LPT< nDim >::reduceParticles
private

Reduce the number of active particles by using some artificial cell-based criterias

Template Parameters
nDim

Definition at line 2805 of file lpt.cpp.

2805 {
2807 perCellStats();
2808
2809 vector<MInt> cellIds;
2810
2811 // determine critical cells by checking conditions
2812 static constexpr MInt cellPartLimit = 150;
2813 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
2814 if(a_noParticlesInCell(cellId) < cellPartLimit) {
2815 continue;
2816 }
2817 cellIds.emplace_back(cellId);
2818 }
2819
2820 // TODO labels:LPT make settable
2821 MInt totalMerged = 0;
2822 // 1. remove all particles with low relative velocity
2823 const MFloat dvLimit = 0.5;
2824 // 2. remove all particles with a small diameter
2825 const MFloat diamLimit = 1E-5;
2826 // 3. combine the rest by merging with the next valid parcel
2827 for(auto const& cellId : cellIds) {
2828 // iterator over all particles in this cell
2829 auto particlesInCell = m_cellToPartMap.equal_range(cellId);
2830 LPTSpherical<nDim>* validPartToMerge = nullptr;
2831
2832 MInt filterCount = 0;
2833 MInt mergedParticles = 0;
2834 for(auto i = particlesInCell.first; i != particlesInCell.second; i++) {
2835 auto& particle = i->second;
2836 const MFloat magDv =
2837 sqrt(POW2(particle->m_accel.at(0)) + POW2(particle->m_accel.at(1)) + POW2(particle->m_accel.at(2)))
2838 * m_timeStep;
2839 const MFloat partD = particle->m_diameter;
2840 if(magDv < dvLimit && partD < diamLimit) {
2841 if(validPartToMerge == nullptr) {
2842 validPartToMerge = particle;
2843 } else {
2844 mergeParticles(validPartToMerge, particle);
2845
2846 mergedParticles++;
2847 validPartToMerge = nullptr;
2848 }
2849 filterCount++;
2850 }
2851 }
2852
2853
2854 if(filterCount > 0) {
2855 totalMerged += mergedParticles;
2856 }
2857 }
2858
2859 // sort by diameter smallest last (otherwise deletion takes forever)
2861
2862 // erase particles with 0 mass
2863 MInt noDeleted = 0;
2864 for(MInt i = (MInt)m_partList.size() - 1; i >= 0; i--) {
2865 if(smallParticle(m_partList[i])) {
2866#ifdef LPT_DEBUG
2867 cerr << "deleted small particle " << i << " at timestep " << m_timeStep << endl;
2868#endif
2869 ++noDeleted;
2870 m_partList.erase(m_partList.begin() + i);
2871 }
2872 // else {
2873 // break;
2874 // }
2875 }
2876
2877 // recover original sort
2879
2880 if(noDeleted > 0) {
2881 cerr << domainId() << ": total particles merged " << totalMerged << " deleted " << noDeleted << endl;
2882 }
2883}
void perCellStats()
set cell-particle mapping which is used to merge particle in reduceParticles!
Definition: lpt.cpp:2780
void mergeParticles(LPTSpherical< nDim > *partA, LPTSpherical< nDim > *partB)
Definition: lpt.cpp:2890

◆ refineCell()

template<MInt nDim>
void LPT< nDim >::refineCell ( const MInt  gridCellId)
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1538 of file lpt.cpp.

1538 {
1539 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
1540
1541 ASSERT(solverCellId > -1 && solverCellId < m_cells.size(), "solverCellId is: " << solverCellId);
1542
1543 MInt noNewChildren = 0;
1544
1545 for(MInt child = 0; child < grid().m_maxNoChilds; child++) {
1546 const MInt gridChildId = grid().raw().treeb().child(gridCellId, child);
1547 if(gridChildId == -1) continue;
1548
1549 // Skip if cell is a partition level ancestor and its child was not newly created
1550 if(!grid().raw().a_hasProperty(gridChildId, Cell::WasNewlyCreated)
1551 && grid().raw().a_hasProperty(gridCellId, Cell::IsPartLvlAncestor)) {
1552 continue;
1553 }
1554
1555 // If solver is inactive all cells musst be halo cells!
1556 if(!isActive()) ASSERT(grid().raw().a_isHalo(gridChildId), "");
1557 // If child exists in grid but is not located inside solver geometry
1558 if(!grid().solverFlag(gridChildId, solverId())) continue;
1559
1560 const MInt solverChildId = this->createCellId(gridChildId);
1561 noNewChildren++;
1562
1563 for(MInt n = 0; n < nDim; n++) {
1564 a_fluidVelocity(solverChildId, n) = 0.0;
1565 }
1566 a_fluidDensity(solverChildId) = 0.0;
1567 a_fluidPressure(solverChildId) = 0.0;
1568 a_fluidTemperature(solverChildId) = 0.0;
1569
1570 if(m_evaporation) {
1571 a_fluidSpecies(solverChildId) = 0.0;
1572 }
1573 a_isValidCell(solverChildId) = true;
1574
1575 a_bndryCellId(solverChildId) = a_bndryCellId(solverCellId);
1576 if(m_ellipsoids) {
1577 for(MInt varId = 0; varId < nDim; varId++) {
1578 for(MInt dir = 0; dir < nDim; dir++) {
1579 a_velocitySlope(solverChildId, varId, dir) = F0;
1580 }
1581 }
1582 }
1583 }
1584
1585 if(noNewChildren == 0) return;
1586
1587 const MInt noParticles = a_noParticlesInCell(solverCellId);
1588 const MInt noEllipsoids = a_noEllipsoidsInCell(solverCellId);
1589
1590 //NOTE: setting an estimate of the number particles in the cell
1591 // is necessary as this is used to set the sensors for further refinement!
1592 // the true value will be updated in finalizeAdaptation!
1593 const MInt noParticlesEach = noParticles / noNewChildren;
1594 const MInt noEllipsoidsEach = noEllipsoids / noNewChildren;
1595
1596 for(MInt child = 0; child < c_noChildren(solverCellId) -1; child++) {
1597 const MInt childId = c_childId(solverCellId,child);
1598 if(childId < 0) continue;
1599 a_noParticlesInCell(childId) = noParticles > 0 ? noParticlesEach : 0;
1600 a_noEllipsoidsInCell(childId) = noEllipsoids > 0 ? noEllipsoidsEach : 0;
1601
1602 // average of solver parent
1603 if(m_momentumCoupling) {
1604 for(MInt i = 0; i < nDim; i++) {
1605 a_momentumFlux(childId, i) = a_momentumFlux(solverCellId, i) / noNewChildren;
1606 }
1607 a_workFlux(childId) = a_workFlux(solverCellId) / noNewChildren;
1608 }
1609 if(m_heatCoupling) {
1610 a_heatFlux(childId) = a_heatFlux(solverCellId) / noNewChildren;
1611 }
1612 if(m_massCoupling) {
1613 a_massFlux(childId) = a_massFlux(solverCellId) / noNewChildren;
1614 }
1615 }
1616 const MInt remainingParticles = noParticles - ((c_noChildren(solverCellId) - 1) * noParticlesEach);
1617 const MInt remainingEllipsoids = noEllipsoids - ((c_noChildren(solverCellId) - 1) * noEllipsoidsEach);
1618
1619 const MInt remainingChild = c_childId(solverCellId, c_noChildren(solverCellId) - 1);
1620 if(remainingChild > 0) {
1621 a_noParticlesInCell(remainingChild) = noParticles > 0 ? remainingParticles : 0;
1622 a_noEllipsoidsInCell(remainingChild) = noEllipsoids > 0 ? remainingEllipsoids : 0;
1623
1624 if(m_momentumCoupling) {
1625 for(MInt i = 0; i < nDim; i++) {
1626 a_momentumFlux(remainingChild, i) = a_momentumFlux(solverCellId, i) / noNewChildren;
1627 }
1628 a_workFlux(remainingChild) = a_workFlux(solverCellId) / noNewChildren;
1629 }
1630 if(m_heatCoupling) {
1631 a_heatFlux(remainingChild) = a_heatFlux(solverCellId) / noNewChildren;
1632 }
1633 if(m_massCoupling) {
1634 a_massFlux(remainingChild) = a_massFlux(solverCellId) / noNewChildren;
1635 }
1636 }
1637
1638 // reset values on new non-leaf cell
1639 if(noNewChildren > 0 ){
1640 a_noParticlesInCell(solverCellId) = 0;
1641 a_noEllipsoidsInCell(solverCellId) = 0;
1642
1643 if(m_momentumCoupling) {
1644 for(MInt i = 0; i < nDim; i++) {
1645 a_momentumFlux(solverCellId, i) = 0;
1646 }
1647 a_workFlux(solverCellId) = 0;
1648 }
1649 if(m_heatCoupling) {
1650 a_heatFlux(solverCellId) = 0;
1651 }
1652 if(m_massCoupling) {
1653 a_massFlux(solverCellId) = 0;
1654 }
1655 }
1656}
MInt createCellId(const MInt gridCellId)

◆ reIntAfterRestart()

template<MInt nDim>
void LPT< nDim >::reIntAfterRestart ( MBool  )
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 249 of file lpt.h.

249{};

◆ remove_if_impl_()

template<MInt nDim>
template<class T , class Pred >
void LPT< nDim >::remove_if_impl_ ( T &  c,
Pred &  p,
std::random_access_iterator_tag   
)
inlineprotected

Definition at line 730 of file lpt.h.

730 {
731 c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
732 }

◆ removeCell()

template<MInt nDim>
void LPT< nDim >::removeCell ( const MInt  MInt)
overridevirtual

Reimplemented from Solver.

Definition at line 1717 of file lpt.cpp.

1717 {
1718 // If solver is inactive cell musst never be a internal cell
1719 if(!isActive()) {
1720 ASSERT(grid().raw().a_isHalo(gridCellId), "");
1721 }
1722
1723 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
1724
1725 ASSERT(gridCellId > -1 && gridCellId < grid().raw().treeb().size() && solverCellId > -1
1726 && solverCellId < m_cells.size() && grid().tree().solver2grid(solverCellId) == gridCellId,
1727 "");
1728 ASSERT(c_noChildren(solverCellId) == 0, "");
1729 this->removeCellId(solverCellId);
1730}

◆ removeChilds()

template<MInt nDim>
void LPT< nDim >::removeChilds ( const MInt  gridCellId)
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1663 of file lpt.cpp.

1663 {
1664 // If solver is inactive cell musst never be a internal cell
1665 if(!isActive()) {
1666 ASSERT(grid().raw().a_isHalo(gridCellId), "");
1667 }
1668
1669 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
1670
1671 ASSERT(solverCellId > -1 && solverCellId < m_cells.size(), "solverCellId is: " << solverCellId);
1672
1673 // reset values of new leaf cell
1674 a_noParticlesInCell(solverCellId) = 0;
1675 a_noEllipsoidsInCell(solverCellId) = 0;
1676 if(m_momentumCoupling) {
1677 for(MInt i = 0; i < nDim; i++) {
1678 a_momentumFlux(solverCellId, i) = 0;
1679 }
1680 a_workFlux(solverCellId) = 0;
1681 }
1682 if(m_heatCoupling) {
1683 a_heatFlux(solverCellId) = 0;
1684 }
1685 if(m_massCoupling) {
1686 a_massFlux(solverCellId) = 0;
1687 }
1688
1689 for(MInt c = 0; c < grid().m_maxNoChilds; c++) {
1690 const MInt childId = c_childId(solverCellId, c);
1691 if(childId < 0) continue;
1692
1693 // sum values of childs which will be removed
1694 a_noParticlesInCell(solverCellId) += a_noParticlesInCell(childId);
1695 a_noEllipsoidsInCell(solverCellId) += a_noEllipsoidsInCell(childId);
1696 if(m_momentumCoupling) {
1697 for(MInt i = 0; i < nDim; i++) {
1698 a_momentumFlux(solverCellId, i) += a_momentumFlux(childId, i);
1699 }
1700 a_workFlux(solverCellId) += a_workFlux(childId);
1701 }
1702 if(m_heatCoupling) {
1703 a_heatFlux(solverCellId) += a_heatFlux(childId);
1704 }
1705 if(m_massCoupling) {
1706 a_massFlux(solverCellId) += a_massFlux(childId);
1707 }
1708
1709 this->removeCellId(childId);
1710 }
1711}

◆ removeInvalidParticles()

template<MInt nDim>
void LPT< nDim >::removeInvalidParticles ( const MBool  alsoFullyEvaporated)
private

Definition at line 2667 of file lpt.cpp.

2667 {
2668 // check list for inactive particles and remove these
2669 // inactive particles are generally particles which:
2670 // a) have been communicated to a different rank
2671 // b) have been fully evaporated
2672
2673 if(!m_respawn) {
2674 for(MInt i = a_noParticles() - 1; i >= 0; i--) {
2675 if(!alsoFullyEvaporated && m_partList[i].fullyEvaporated()) continue;
2676 if(m_partList[i].isInvalid()) {
2677 if(!m_partList[i].fullyEvaporated() && !m_partList[i].wasSend()) {
2678 if(m_partList[i].m_cellId < 0 || m_partList[i].m_cellId >= a_noCells() || !a_isHalo(m_partList[i].m_cellId)) {
2679 cerr << "Removing at " << m_partList[i].m_position[0] << " " << m_partList[i].m_position[1] << " "
2680 << m_partList[i].m_position[nDim - 1] << " " << m_partList[i].m_cellId << " "
2681 << m_partList[i].m_oldCellId << " " << m_partList[i].hadWallColl() << " " << m_partList[i].m_oldPos[0]
2682 << " " << m_partList[i].m_oldPos[1] << " " << m_partList[i].m_oldPos[nDim - 1] << " "
2683 << m_partList[i].m_partId << endl;
2684 if(m_partList[i].m_cellId > -1 && m_partList[i].m_cellId < a_noCells()) {
2685 cerr << "Cell-stats " << a_isHalo(m_partList[i].m_cellId) << " " << a_isBndryCell(m_partList[i].m_cellId)
2686 << " " << a_isValidCell(m_partList[i].m_cellId) << endl;
2687 if(m_partList[i].m_oldCellId > -1 && m_partList[i].m_oldCellId < a_noCells()) {
2688 cerr << "Old-cell-stats " << a_isBndryCell(m_partList[i].m_oldCellId) << " "
2689 << a_isValidCell(m_partList[i].m_oldCellId) << endl;
2690 }
2691 m_partList[i].checkCellChange(nullptr, false);
2692 cerr << "After-update: " << m_partList[i].m_cellId << " " << m_partList[i].isInvalid() << " "
2693 << a_isValidCell(m_partList[i].m_cellId) << endl;
2694 }
2695 }
2696 }
2697 m_partList.erase(m_partList.begin() + i);
2698 }
2699 }
2700 if(m_ellipsoids) {
2701 for(MInt i = a_noEllipsoidalParticles() - 1; i >= 0; i--) {
2702 if(m_partListEllipsoid[i].isInvalid()) {
2703 if(!m_partListEllipsoid[i].fullyEvaporated() && !m_partListEllipsoid[i].wasSend()) {
2704 if(m_partListEllipsoid[i].m_cellId < 0 || m_partListEllipsoid[i].m_cellId >= a_noCells()
2705 || !a_isHalo(m_partListEllipsoid[i].m_cellId)) {
2706 cerr << "Removing at " << m_partListEllipsoid[i].m_position[0] << " "
2707 << m_partListEllipsoid[i].m_position[1] << " " << m_partListEllipsoid[i].m_position[nDim - 1] << " "
2708 << m_partListEllipsoid[i].m_cellId << " " << m_partListEllipsoid[i].m_oldCellId << " "
2709 << m_partListEllipsoid[i].hadWallColl() << " " << m_partListEllipsoid[i].m_oldPos[0] << " "
2710 << m_partListEllipsoid[i].m_oldPos[1] << " " << m_partListEllipsoid[i].m_oldPos[nDim - 1] << " "
2711 << m_partListEllipsoid[i].m_partId << endl;
2712 if(m_partListEllipsoid[i].m_cellId > -1 && m_partListEllipsoid[i].m_cellId < a_noCells()) {
2713 cerr << "Cell-stats " << a_isHalo(m_partListEllipsoid[i].m_cellId) << " "
2714 << a_isBndryCell(m_partListEllipsoid[i].m_cellId) << " "
2715 << a_isValidCell(m_partListEllipsoid[i].m_cellId) << endl;
2716 if(m_partListEllipsoid[i].m_oldCellId > -1 && m_partListEllipsoid[i].m_oldCellId < a_noCells()) {
2717 cerr << "Old-cell-stats " << a_isBndryCell(m_partListEllipsoid[i].m_oldCellId) << " "
2718 << a_isValidCell(m_partListEllipsoid[i].m_oldCellId) << endl;
2719 }
2720 m_partListEllipsoid[i].checkCellChange(nullptr, false);
2721 cerr << "After-update: " << m_partListEllipsoid[i].m_cellId << " " << m_partListEllipsoid[i].isInvalid()
2722 << " " << a_isValidCell(m_partListEllipsoid[i].m_cellId) << endl;
2723 }
2724 }
2725 }
2726 m_partListEllipsoid.erase(m_partListEllipsoid.begin() + i);
2727 }
2728 }
2729 }
2730 }
2731}

◆ resetSolver()

template<MInt nDim>
void LPT< nDim >::resetSolver
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 6655 of file lpt.cpp.

6655 {
6656 TRACE();
6657
6658 if(!isActive()) {
6659 m_injData.clear();
6660 } else {
6664 }
6665
6666 // set correct size of m_injData on inactive ranks!
6667 MInt vectorSize = 0;
6668 if(m_activePrimaryBUp && grid().hasInactiveRanks()) {
6669 if(!m_injData.empty()) {
6670 vectorSize = m_injData.size();
6671 }
6672 MPI_Allreduce(MPI_IN_PLACE, &vectorSize, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD, AT_, "INPLACE", "vectorSize");
6673
6674 if(vectorSize > 0 && !isActive()) {
6675 m_injData.clear();
6676 const MInt count = m_sprayModel->m_injDataSize + m_addInjDataCnt;
6677 MInt dummyTimeStep = -1;
6678 for(MInt i = 0; i < vectorSize; i++) {
6679 vector<MFloat> tmp(count);
6680 for(MInt j = 0; j < count; j++) {
6681 tmp[j] = 0.0;
6682 }
6683 m_injData.insert(make_pair(dummyTimeStep, tmp));
6684 dummyTimeStep--;
6685 }
6686 } else if(isActive() && domainId() == m_spawnDomainId) {
6687 if(vectorSize != (signed)m_injData.size()) {
6688 cerr << "Injector size differs! " << vectorSize << " " << m_injData.size() << endl;
6689 }
6690 }
6691 }
6692
6693 if(!isActive()) {
6694 return;
6695 }
6696
6697 cerr0 << "LPT-time step is : " << m_timeStep << endl;
6698
6700
6701 checkParticles(); // check particles before balance!
6702
6703 countParticlesInCells(); // used to determine the data size necessary for sending
6704
6705 // remove all bndryCells
6706 if(m_wallCollisions) {
6709 }
6710
6711 // NOTE:latest point to write a debug file before the balance:
6712 /*
6713 MInt backup = globalTimeStep;
6714 globalTimeStep = -1;
6715 saveDebugRestartFile();
6716 globalTimeStep = backup;
6717 */
6718
6719 perCellStats(); // cell-particle mapping necessary to pack particles for a given cell
6720
6721 MPI_Allreduce(MPI_IN_PLACE, &m_particleResiduum, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "INPLACE",
6722 "m_particleResiduum");
6723
6724 MPI_Allreduce(MPI_IN_PLACE, &m_PRNGSpawnCount, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "m_PRNGSpawnCount");
6725
6726 MPI_Allreduce(MPI_IN_PLACE, &m_spawnDomainId, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "m_spawnDomainId");
6727
6729 MInt count = m_sprayModel->m_PRNGPrimBreakUpCount;
6730 MPI_Allreduce(MPI_IN_PLACE, &count, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "m_PRNGPrimBreakUpCount");
6731 m_sprayModel->m_PRNGPrimBreakUpCount = count;
6732
6733 MFloat timeSinceSOI = 0;
6734 if(m_spawnCellId > -1) {
6735 timeSinceSOI = m_sprayModel->timeSinceSOI();
6736 }
6737 MPI_Allreduce(MPI_IN_PLACE, &timeSinceSOI, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "INPLACE", "timeSinceSOI");
6738 m_sprayModel->timeSinceSOI() = timeSinceSOI;
6739 }
6740
6741 // exchange the injection-data
6742 if(m_activePrimaryBUp) {
6743 MInt vectorSizeBU = vectorSize;
6744 vectorSize = m_injData.size();
6745 const MInt count = m_sprayModel->m_injDataSize + m_addInjDataCnt;
6746
6747 MPI_Allreduce(MPI_IN_PLACE, &vectorSize, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "vectorSize");
6748 const MInt totalSize = vectorSize * (count + 1);
6749
6750 if(vectorSize > 0) {
6751 MFloatScratchSpace injData(vectorSize * (count + 1), AT_, "injData");
6752 injData.fill(0.0);
6753 if(vectorSize != vectorSizeBU && grid().hasInactiveRanks()) {
6754 cerr << domainId() << "Vector size differs " << vectorSizeBU << " " << vectorSize << endl;
6755 }
6756
6757 if(domainId() == m_spawnDomainId) {
6758 ASSERT((signed)m_injData.size() == vectorSize, "");
6759 MInt i = 0;
6760 for(auto it = m_injData.begin(); it != m_injData.end(); it++) {
6761 const MFloat timeStep = (MFloat)it->first;
6762 injData(i++) = timeStep;
6763 for(MInt j = 0; j < count; j++) {
6764 const MFloat data = (it->second)[j];
6765 injData(i++) = data;
6766 }
6767 }
6768 } else {
6769 MInt i = 0;
6770 for(auto it = m_injData.begin(); it != m_injData.end(); it++) {
6771 i = i + m_sprayModel->m_injDataSize + 1;
6772 const MFloat sumEvap = (it->second)[m_sprayModel->m_injDataSize];
6773 const MInt numRT = (it->second)[m_sprayModel->m_injDataSize + 1];
6774 const MInt numKH = (it->second)[m_sprayModel->m_injDataSize + 2];
6775 const MInt numSend = (it->second)[m_sprayModel->m_injDataSize + 3];
6776 injData(i++) = sumEvap;
6777 injData(i++) = numRT;
6778 injData(i++) = numKH;
6779 injData(i++) = numSend;
6780 }
6781 }
6782
6783 MPI_Allreduce(MPI_IN_PLACE, &injData[0], totalSize, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "INPLACE", "injData");
6784
6785 // reset injection data with summed data
6786 m_injData.clear();
6787
6788 for(MInt i = 0; i < totalSize; i = i + (count + 1)) {
6789 const MInt timeStep = (MInt)injData(i);
6790 vector<MFloat> tmp(count);
6791 for(MInt j = 0; j < count; j++) {
6792 tmp[j] = injData[i + j + 1];
6793 }
6794 m_injData.insert(make_pair(timeStep, tmp));
6795 }
6796 }
6797 }
6798
6799#ifdef LPT_DEBUG
6800 MInt noParticles = a_noParticles();
6801
6802 MPI_Allreduce(MPI_IN_PLACE, &noParticles, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noParticles");
6803
6804 if(domainId() == 0) {
6805 cerr << noParticles << " #particles before balancing!" << endl;
6806 }
6807
6808 if(m_ellipsoids) {
6809 MInt noEllipsoids = a_noEllipsoidalParticles();
6810 MPI_Allreduce(MPI_IN_PLACE, &noEllipsoids, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "INPLACE", "noEllipsoids");
6811 cerr0 << noEllipsoids << " #ellipsoids before balancing!" << endl;
6812 }
6813
6814#endif
6815}
MFloat timeSinceSOI() const
Definition: lpt.h:479

◆ resetSolverFull()

template<MInt nDim>
void LPT< nDim >::resetSolverFull
Author
Tim Wegmann

Definition at line 6822 of file lpt.cpp.

6822 {
6823 m_queueToSend.clear();
6824 m_sendBuffer.clear();
6825 m_recvBuffer.clear();
6826 m_intSendBuffer.clear();
6827 m_intRecvBuffer.clear();
6828 m_mpi_reqSendFloat.clear();
6829 m_mpi_reqSendInt.clear();
6830 m_mpi_reqSendSize.clear();
6831 m_mpi_statusProbe.clear();
6832
6833 m_partList.clear();
6834 m_partListEllipsoid.clear();
6835 m_cells.clear();
6836 if(m_wallCollisions) {
6838 }
6839
6840 m_cellToNghbrHood.clear();
6842
6843 m_pointsToHalo.clear();
6844 m_pointsToWindow.clear();
6845
6846 m_cellToPartMap.clear();
6847 m_cellToEllipsMap.clear();
6848}

◆ resetSourceTerms()

template<MInt nDim>
void LPT< nDim >::resetSourceTerms ( const MInt  offset)
protected
Date
November-20
Author
Tim Wegmann

Definition at line 2112 of file lpt.cpp.

2112 {
2113 TRACE();
2114
2115 for(MInt cellId = offset; cellId < a_noCells(); cellId++) {
2116 if(m_momentumCoupling) {
2117 for(MInt i = 0; i < nDim; i++) {
2118 a_momentumFlux(cellId, i) = 0;
2119 }
2120 a_workFlux(cellId) = 0;
2121 }
2122 if(m_heatCoupling) {
2123 a_heatFlux(cellId) = 0;
2124 }
2125 if(m_massCoupling) {
2126 a_massFlux(cellId) = 0;
2127 }
2128 }
2129}

◆ resizeGridMap()

template<MInt nDim>
void LPT< nDim >::resizeGridMap
overridevirtual

Reimplemented from Solver.

Definition at line 1519 of file lpt.cpp.

1519 {
1520 grid().resizeGridMap(m_cells.size());
1521}

◆ saveDebugRestartFile()

template<MInt nDim>
void LPT< nDim >::saveDebugRestartFile
Date
January-2021
Author
Tim Wegmann

Definition at line 2597 of file lpt.cpp.

2597 {
2599
2600 MBool writeCellFile = true;
2601 if(grid().hasInactiveRanks()) writeCellFile = false;
2602
2603 // write an additional cell based solution file (useful for debuging!)
2604 if(writeCellFile) {
2605 stringstream gridFile;
2606 stringstream gridFilePath;
2607 gridFile << "grid_LPTDebug_" << globalTimeStep << ".Netcdf";
2608 gridFilePath << outputDir() << "grid_LPTDebug_" << globalTimeStep << ".Netcdf";
2609 MIntScratchSpace recalcIds(grid().raw().treeb().size(), AT_, "recalcIds");
2610
2611 grid().raw().saveGrid((gridFilePath.str()).c_str(), recalcIds.begin());
2612
2613 writeCellSolutionFile((gridFile.str()).c_str(), &recalcIds[0]);
2614 }
2615}
void writeParticleRestartFile()
Write particle restart file.
Definition: lpt.cpp:4304
void writeCellSolutionFile(const MString &, MInt *)
Write lpt cell based solution file currently ony used for debugging!
Definition: lpt.cpp:5285
MString outputDir() const
Return the directory for output files.
Definition: solver.h:407

◆ saveSolverSolution()

template<MInt nDim>
void LPT< nDim >::saveSolverSolution ( const  MBool,
const  MBool 
)
inlineoverride

Definition at line 205 of file lpt.h.

205{};

◆ sendAndReceiveParticles()

template<MInt nDim>
template<class LPTParticle >
void LPT< nDim >::sendAndReceiveParticles ( const MBool  allowNonLeaf)
protected
Author
Rudie Kunnen, Sven Berger, Tim Wegmann

Definition at line 3603 of file lpt.cpp.

3603 {
3604 TRACE();
3605
3606 MPI_Status status{};
3607
3608 // 1) exchange the number of particles to be sent:
3609 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3610 m_sendSize[d] = m_queueToSend[d].size();
3612 mTerm(1, AT_, "Increase particle exchange buffer size!");
3613 }
3614 MPI_Isend(&m_sendSize[d], 1, MPI_INT, grid().neighborDomain(d), mpiTag("PARTICLE_COUNT"), mpiComm(),
3615 &m_mpi_reqSendSize[d], AT_, "noToSend");
3616 }
3617
3618 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3619 MPI_Recv(&m_recvSize[d], 1, MPI_INT, grid().neighborDomain(d), mpiTag("PARTICLE_COUNT"), mpiComm(), &status, AT_,
3620 "m_recvSize");
3621 }
3622
3623 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3624 MPI_Wait(&m_mpi_reqSendSize[d], &status, AT_);
3625 }
3626
3627 // 2) prepare/write the two send buffers (MInt, MFloat)
3628 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3629 if(m_queueToSend[d].empty()) {
3630 // skip nothing to send
3631 m_mpi_reqSendFloat[d] = MPI_REQUEST_NULL;
3632 m_mpi_reqSendInt[d] = MPI_REQUEST_NULL;
3633 continue;
3634 }
3635
3636 vector<LPTParticle*> particlesToSend;
3637 vector<MInt> cellIds;
3638 vector<LPTParticle>& partList = a_particleList<LPTParticle>();
3639
3640 while(!m_queueToSend[d].empty()) {
3641 sendQueueType<nDim> thisSend = m_queueToSend[d].front();
3642 m_queueToSend[d].pop();
3643 MInt partPos = thisSend.partPos;
3644
3645 particlesToSend.push_back(&partList[partPos]);
3646 cellIds.push_back(thisSend.toCellId);
3647 }
3648
3649 MInt noParticles = particlesToSend.size();
3650
3651 packParticles(particlesToSend, m_intSendBuffer[d].get(), m_sendBuffer[d].get(), cellIds);
3652
3653 for(auto* part : particlesToSend) {
3654 if(part->reqSend()) {
3655 part->wasSend() = true;
3656 part->reqSend() = false;
3657 part->isInvalid() = true;
3658 }
3659 }
3660
3661 // 3) send the buffers
3662 MPI_Isend(&m_sendBuffer[d][0], noParticles * elemPerP<LPTParticle>(), MPI_DOUBLE, grid().neighborDomain(d),
3663 mpiTag("PARTICLE_FLOAT"), mpiComm(), &m_mpi_reqSendFloat[d], AT_, "m_sendBuffer");
3664
3665 MPI_Isend(&m_intSendBuffer[d][0], noParticles * intElemPerP<LPTParticle>(), MPI_INT, grid().neighborDomain(d),
3666 mpiTag("PARTICLE_INT"), mpiComm(), &m_mpi_reqSendInt[d], AT_, "m_intSendBuffer");
3667 }
3668
3669 // 4) receive the buffers
3670 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3671 if(m_recvSize[d] > 0) {
3672 MPI_Recv(&m_recvBuffer[d][0], mMin(bufSize<LPTParticle>(), m_recvSize[d] * elemPerP<LPTParticle>()), MPI_DOUBLE,
3673 grid().neighborDomain(d), mpiTag("PARTICLE_FLOAT"), mpiComm(), &status, AT_, "m_recvBuffer");
3674 MPI_Recv(&m_intRecvBuffer[d][0], mMin(intBufSize<LPTParticle>(), m_recvSize[d] * intElemPerP<LPTParticle>()),
3675 MPI_INT, grid().neighborDomain(d), mpiTag("PARTICLE_INT"), mpiComm(), &status, AT_, "m_intRecvBuffer");
3676 }
3677 }
3678
3679 // 5) wait for completion of communication
3680 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3681 MPI_Wait(&m_mpi_reqSendFloat[d], &status, AT_);
3682 MPI_Wait(&m_mpi_reqSendInt[d], &status, AT_);
3683 }
3684
3685 // 6) interpret the receive buffers and add incomming particles
3686 for(MInt d = 0; d < grid().noNeighborDomains(); d++) {
3687 // nothing to receive skip
3688 if(m_recvSize[d] == 0) continue;
3689
3690 if(!m_periodicBC) {
3691 unpackParticles<LPTParticle, false>(m_recvSize[d], &m_intRecvBuffer[d][0], &m_recvBuffer[d][0], d, allowNonLeaf);
3692 } else {
3693 unpackParticles<LPTParticle, true>(m_recvSize[d], &m_intRecvBuffer[d][0], &m_recvBuffer[d][0], d, allowNonLeaf);
3694 }
3695 }
3696}

◆ sendFlowField()

template<MInt nDim>
void LPT< nDim >::sendFlowField
protected
Author
Tim Wegmann

Definition at line 7739 of file lpt.cpp.

7739 {
7740 if(!m_nonBlockingComm) {
7741 return;
7742 }
7743 m_receiveFlowField = true;
7744
7745 // start receiving flow field data
7746 for(MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
7747 const MInt d = grid().leafRecvNeighborDomain(n);
7748 MPI_Irecv(&m_flowRecv[d][0], (PV.noVars() + m_evaporation) * grid().noLeafHaloCells(d), MPI_DOUBLE,
7749 grid().neighborDomain(d), mpiTag("FLOW_FIELD"), mpiComm(), &m_flowRecvRequest[n], AT_, "m_flowRecv");
7750 }
7751
7752 // wait until all sends have been processed before sending new
7753 if(m_openFlowSend) {
7754 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_flowSendRequest[0], MPI_STATUSES_IGNORE, AT_);
7755 m_openFlowSend = false;
7756 }
7757
7758
7759 // send flow field data
7760 for(MInt n = 0; n < grid().noLeafSendNeighborDomains(); n++) {
7761 const MInt d = grid().leafSendNeighborDomain(n);
7762 MInt buffId = 0;
7763 for(MInt j = 0; j < grid().noLeafWindowCells(d); j++) {
7764 const MInt cellId = grid().leafWindowCell(d, j);
7765 std::copy_n(&a_fluidVariable(cellId, 0), PV.noVars(), &m_flowSend[d][buffId]);
7766 buffId += PV.noVars();
7767 if(m_evaporation) {
7768 std::copy_n(&a_fluidSpecies(cellId), 1, &m_flowSend[d][buffId]);
7769 buffId++;
7770 }
7771 }
7772 MPI_Isend(&m_flowSend[d][0], (PV.noVars() + m_evaporation) * grid().noLeafWindowCells(d), MPI_DOUBLE,
7773 grid().neighborDomain(d), mpiTag("FLOW_FIELD"), mpiComm(), &m_flowSendRequest[n], AT_, "m_flowSend");
7774 }
7775
7776 m_openFlowSend = true;
7777}
MBool m_openFlowSend
Definition: lpt.h:628

◆ sendInjected()

template<MInt nDim>
void LPT< nDim >::sendInjected ( const MUint  prevNumPart)
private

◆ sendParticles()

template<MInt nDim>
template<MBool allNeighbors, class LPTParticle >
void LPT< nDim >::sendParticles
protected
Author
Tim Wegmann

Definition at line 3705 of file lpt.cpp.

3705 {
3706 TRACE();
3707
3708 if(m_nonBlockingStage != 0) {
3709 mTerm(1, AT_, "Incorrect non-blocking stage!");
3710 }
3711
3712 RECORD_TIMER_START(m_timers[Timers::Exchange1]);
3713
3714 // wait on all previously send before send new
3716 MPI_Waitall(noNeighborDomains(), &m_mpi_reqSendFloat[0], MPI_STATUSES_IGNORE, AT_);
3717 MPI_Waitall(noNeighborDomains(), &m_mpi_reqSendInt[0], MPI_STATUSES_IGNORE, AT_);
3718 m_openParticleInjSend = false;
3719 }
3720
3721 if(m_openParticleSend) {
3722 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_mpi_reqSendFloat[0], MPI_STATUSES_IGNORE, AT_);
3723 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_mpi_reqSendInt[0], MPI_STATUSES_IGNORE, AT_);
3724 m_openParticleSend = false;
3725 }
3726
3727 const MInt noNeighborsSend = allNeighbors ? grid().noNeighborDomains() : grid().noLeafSendNeighborDomains();
3728 const MInt noNeighborsRecv = allNeighbors ? grid().noNeighborDomains() : grid().noLeafRecvNeighborDomains();
3729
3730 // 3) prepare/write the two send buffers (MInt, MFloat)
3731 for(MInt n = 0; n < noNeighborsSend; n++) {
3732 MInt d = n;
3733 if(!allNeighbors) {
3734 d = grid().leafSendNeighborDomain(n);
3735 }
3736 if(m_queueToSend[d].empty()) {
3737 // skip nothing to send
3738 m_mpi_reqSendFloat[n] = MPI_REQUEST_NULL;
3739 m_intSendBuffer[d][0] = -intElemPerP<LPTParticle>();
3740 MPI_Isend(&m_intSendBuffer[d][0], 0, MPI_INT, grid().neighborDomain(d), mpiTag("PARTICLE_INT"), mpiComm(),
3741 &m_mpi_reqSendInt[n], AT_, "m_intSendBuffer");
3742 continue;
3743 }
3744
3745 vector<LPTParticle*> particlesToSend;
3746 RECORD_TIMER_START(m_timers[Timers::Exchange3]);
3747 vector<MInt> cellIds;
3748 vector<LPTParticle>& partList = a_particleList<LPTParticle>();
3749
3750 while(!m_queueToSend[d].empty()) {
3751 sendQueueType<nDim> thisSend = m_queueToSend[d].front();
3752 m_queueToSend[d].pop();
3753 MInt partPos = thisSend.partPos;
3754
3755 particlesToSend.push_back(&partList[partPos]);
3756 cellIds.push_back(thisSend.toCellId);
3757 }
3758
3759 MInt noParticles = particlesToSend.size();
3760 packParticles(particlesToSend, &m_intSendBuffer[d][0], &m_sendBuffer[d][0], cellIds);
3761
3762 for(auto& part : particlesToSend) {
3763 if(part->reqSend()) {
3764 part->wasSend() = true;
3765 part->reqSend() = false;
3766 part->isInvalid() = true;
3767 }
3768 }
3769 RECORD_TIMER_STOP(m_timers[Timers::Exchange3]);
3770
3771 // 3) send the buffers
3772 MPI_Isend(&m_sendBuffer[d][0], noParticles * elemPerP<LPTParticle>(), MPI_DOUBLE, grid().neighborDomain(d),
3773 mpiTag("PARTICLE_FLOAT"), mpiComm(), &m_mpi_reqSendFloat[n], AT_, "m_sendBuffer");
3774
3775 MPI_Isend(&m_intSendBuffer[d][0], noParticles * intElemPerP<LPTParticle>(), MPI_INT, grid().neighborDomain(d),
3776 mpiTag("PARTICLE_INT"), mpiComm(), &m_mpi_reqSendInt[n], AT_, "m_intSendBuffer");
3777 }
3778
3779 if(allNeighbors) {
3780 m_openParticleInjSend = true;
3781 } else {
3782 m_openParticleSend = true;
3783 }
3784
3785 // 1) Probe and get count of the receiving int-buffer
3786 // to find the number received particles for each rank
3787 // from all ranks which have already called the send and receive those buffers
3788 const MBool loadWasRunning = this->isLoadTimerRunning();
3789 if(loadWasRunning) {
3790 this->stopLoadTimer(AT_);
3791 this->startIdleTimer(AT_);
3792 this->disableDlbTimers();
3793 }
3794
3795 for(MInt n = 0; n < noNeighborsRecv; n++) {
3796 MInt d = n;
3797 if(!allNeighbors) {
3798 d = grid().leafRecvNeighborDomain(n);
3799 }
3800 m_recvSize[d] = -99;
3801 MInt flag{};
3802 MPI_Iprobe(grid().neighborDomain(d), mpiTag("PARTICLE_INT"), mpiComm(), &flag, &m_mpi_statusProbe[n],
3803 "statusProbe");
3804 if(flag) {
3805 MPI_Get_count(&m_mpi_statusProbe[n], MPI_INT, &m_recvSize[d], "m_intRecvBuffer");
3806
3807 m_recvSize[d] = m_recvSize[d] / intElemPerP<LPTParticle>();
3808
3809 MPI_Irecv(&m_intRecvBuffer[d][0], m_recvSize[d] * intElemPerP<LPTParticle>(), MPI_INT, grid().neighborDomain(d),
3810 mpiTag("PARTICLE_INT"), mpiComm(), &m_mpi_reqRecvInt[n], AT_, "m_intRecvBuffer");
3811
3812 if(m_recvSize[d] > 0) {
3813 MPI_Irecv(&m_recvBuffer[d][0], m_recvSize[d] * elemPerP<LPTParticle>(), MPI_DOUBLE, grid().neighborDomain(d),
3814 mpiTag("PARTICLE_FLOAT"), mpiComm(), &m_mpi_reqRecvFloat[n], AT_, "m_recvBuffer");
3815 } else {
3816 m_mpi_reqRecvFloat[n] = MPI_REQUEST_NULL;
3817 }
3818 }
3819 }
3820
3821 if(loadWasRunning) {
3822 this->reEnableDlbTimers();
3823 this->stopIdleTimer(AT_);
3824 this->startLoadTimer(AT_);
3825 }
3826 RECORD_TIMER_STOP(m_timers[Timers::Exchange1]);
3827}
MBool m_openParticleSend
Definition: lpt.h:625
MBool m_openParticleInjSend
Definition: lpt.h:624

◆ sendSourceTerms()

template<MInt nDim>
void LPT< nDim >::sendSourceTerms
protected
Author
Tim Wegmann

Definition at line 7648 of file lpt.cpp.

7648 {
7649 if(!m_nonBlockingComm) {
7650 mTerm(1, AT_, "Calling non-Blocking exchange for blocking setup!");
7651 }
7652
7653 // start receiving source terms
7654 for(MInt n = 0; n < grid().noLeafSendNeighborDomains(); n++) {
7655 const MInt d = grid().leafSendNeighborDomain(n);
7656 MPI_Irecv(&m_sourceRecv[d][0], m_noSourceTerms * grid().noLeafWindowCells(d), MPI_DOUBLE, grid().neighborDomain(d),
7657 mpiTag("SOURCE_TERMS"), mpiComm(), &m_sourceRecvRequest[n], AT_, "m_sourceRecv");
7658 }
7659
7660 // wait until all sends have been received before sending new
7661 if(m_openSourceSend) {
7662 MPI_Waitall(grid().noLeafRecvNeighborDomains(), &m_sourceSendRequest[0], MPI_STATUSES_IGNORE, AT_);
7663 m_openSourceSend = false;
7664 }
7665
7666 // send source terms
7667 for(MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
7668 const MInt d = grid().leafRecvNeighborDomain(n);
7669 MInt buffId = 0;
7670 for(MInt j = 0; j < grid().noLeafHaloCells(d); j++) {
7671 const MInt cellId = grid().leafHaloCell(d, j);
7672 if(m_massCoupling) {
7673 m_sourceSend[d][buffId++] = a_massFlux(cellId);
7674 }
7675 if(m_momentumCoupling) {
7676 for(MInt i = 0; i < nDim; i++) {
7677 m_sourceSend[d][buffId++] = a_momentumFlux(cellId, i);
7678 }
7679 m_sourceSend[d][buffId++] = a_workFlux(cellId);
7680 }
7681 if(m_heatCoupling) {
7682 m_sourceSend[d][buffId++] = a_heatFlux(cellId);
7683 }
7684 }
7685 MPI_Isend(&m_sourceSend[d][0], m_noSourceTerms * grid().noLeafHaloCells(d), MPI_DOUBLE, grid().neighborDomain(d),
7686 mpiTag("SOURCE_TERMS"), mpiComm(), &m_sourceSendRequest[n], AT_, "m_sourceSend");
7687 }
7688 m_openSourceSend = true;
7689
7690 // reset sources on halo cells to zero after send
7692}
MBool m_openSourceSend
Definition: lpt.h:627

◆ sendVelocitySlopes()

template<MInt nDim>
void LPT< nDim >::sendVelocitySlopes
protected
Author
Laurent Andre

Definition at line 7861 of file lpt.cpp.

7861 {
7862 if(!m_ellipsoids) return;
7863 if(!m_nonBlockingComm) return;
7864
7866
7867 // start receiving velocity slopes
7868 for(MInt n = 0; n < grid().noLeafRecvNeighborDomains(); n++) {
7869 const MInt d = grid().leafRecvNeighborDomain(n);
7870 MPI_Irecv(&m_slopesRecv[d][0], (nDim * nDim) * grid().noLeafHaloCells(d), MPI_DOUBLE, grid().neighborDomain(d),
7871 mpiTag("VELOCITY_SLOPES"), mpiComm(), &m_slopesRecvRequest[n], AT_, "m_slopesRecv");
7872 }
7873
7874 // wait until all sends have been processed before sending new
7875 if(m_openSlopesSend) {
7876 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_slopesSendRequest[0], MPI_STATUSES_IGNORE, AT_);
7877 m_openSlopesSend = false;
7878 }
7879
7880 // send velocity slopes
7881 for(MInt n = 0; n < grid().noLeafSendNeighborDomains(); n++) {
7882 const MInt d = grid().leafSendNeighborDomain(n);
7883 MInt buffId = 0;
7884 for(MInt j = 0; j < grid().noLeafWindowCells(d); j++) {
7885 const MInt cellId = grid().leafWindowCell(d, j);
7886 std::copy_n(&a_velocitySlope(cellId, 0, 0), nDim * nDim, &m_slopesSend[d][buffId]);
7887 buffId += nDim * nDim;
7888 }
7889 MPI_Isend(&m_slopesSend[d][0], (nDim * nDim) * grid().noLeafWindowCells(d), MPI_DOUBLE, grid().neighborDomain(d),
7890 mpiTag("VELOCITY_SLOPES"), mpiComm(), &m_slopesSendRequest[n], AT_, "m_slopesSend");
7891 }
7892
7893 m_openSlopesSend = true;
7894}
MBool m_openSlopesSend
Definition: lpt.h:630

◆ sensorInterface()

template<MInt nDim>
void LPT< nDim >::sensorInterface ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
overridevirtual
Author
Tim Wegmann

Reimplemented from maia::CartesianSolver< nDim, LPT< nDim > >.

Definition at line 1368 of file lpt.cpp.

1369 {
1370 MIntScratchSpace bandWidth(maxRefinementLevel() + 1, AT_, "bandWidth");
1371 MInt range1 = 2;
1372 MInt range2 = 1;
1373 bandWidth[maxRefinementLevel() - 1] = range1;
1374 for(MInt i = maxRefinementLevel() - 2; i >= 0; i--) {
1375 bandWidth[i] = (bandWidth[i + 1] / 2) + 1 + range2;
1376 }
1377
1378 static constexpr MFloat limit = 1;
1379 std::function<MFloat(const MInt)> isBndry = [&](const MInt cellId) {
1380 return static_cast<MFloat>(a_bndryCellId(cellId));
1381 };
1382
1383 this->sensorLimit(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen, isBndry, limit, &bandWidth[0], true,
1384 false);
1385}
void sensorLimit(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt, std::function< MFloat(MInt)>, const MFloat, const MInt *, const MBool, const MBool allowCoarsening=true)
simple sensor to apply a limit for a value

◆ sensorParticle()

template<MInt nDim>
void LPT< nDim >::sensorParticle ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MFloat > &  sensorWeight,
MInt  sensorOffset,
MInt  sen 
)
overridevirtual
Author
Tim Wegmann, Sven Berger

Reimplemented from maia::CartesianSolver< nDim, LPT< nDim > >.

Definition at line 1349 of file lpt.cpp.

1350 {
1351 static constexpr MFloat particleLimit = 1;
1352
1353 std::function<MFloat(const MInt)> noPart = [&](const MInt cellId) {
1354 return static_cast<MFloat>(a_noParticlesInCell(cellId)) + static_cast<MFloat>(a_noEllipsoidsInCell(cellId));
1355 };
1356
1357 this->sensorLimit(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen, noPart, particleLimit, &m_bandWidth[0],
1358 true);
1359}
MInt * m_bandWidth
Definition: solver.h:94

◆ setCellDataDlb() [1/2]

template<MInt nDim>
void LPT< nDim >::setCellDataDlb ( const MInt  dataId,
const MFloat *const  data 
)
override
Author
Tim Wegmann

Definition at line 7084 of file lpt.cpp.

7084 {
7085 TRACE();
7086
7087 // Nothing to do if solver is not active
7088 if(!isActive()) {
7089 return;
7090 }
7091
7092 if(dataId != 1) mTerm(1, AT_, "Only Type 1 should be FLOAT");
7093
7094 // Set the no-particles in cell if this is the correct reinitialization stage
7096 // gather the number of particles this rank will have after the balance
7097 MInt noParticlesOnRank = 0;
7098 MInt noEllipsoidsOnRank = 0;
7099 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
7100 noParticlesOnRank += a_noParticlesInCell(cellId);
7101 noEllipsoidsOnRank += a_noEllipsoidsInCell(cellId);
7102 }
7103
7104 unpackParticles<LPTSpherical<nDim>, true>(noParticlesOnRank, nullptr, &data[0]);
7105 if(a_noParticles() != noParticlesOnRank) {
7106 cerr << domainId() << " has incorrect count " << a_noSphericalParticles() << " " << noParticlesOnRank << endl;
7107 mTerm(1, AT_, "Particle gone missing!");
7108 }
7109
7110 if(m_ellipsoids) {
7111 unpackParticles<LPTEllipsoidal<nDim>, true>(noEllipsoidsOnRank, nullptr,
7112 &data[(elemPerP<LPTSpherical<nDim>>() + 3) * noParticlesOnRank]);
7113 if(a_noEllipsoidalParticles() != noEllipsoidsOnRank) {
7114 cerr << domainId() << " has incorrect count " << a_noParticles<LPTEllipsoidal<nDim>>() << " "
7115 << noEllipsoidsOnRank << endl;
7116 mTerm(1, AT_, "Ellipsoid gone missing!");
7117 }
7118 }
7119 }
7120}

◆ setCellDataDlb() [2/2]

template<MInt nDim>
void LPT< nDim >::setCellDataDlb ( const MInt  dataId,
const MInt *const  data 
)
override

Definition at line 7123 of file lpt.cpp.

7123 {
7124 TRACE();
7125
7126 // Nothing to do if solver is not active
7127 if(!isActive()) {
7128 return;
7129 }
7130
7131 if(dataId != 2 && dataId != 0) mTerm(1, AT_, "Type 0 or 2 should be INT");
7132
7134 if(dataId == 0) {
7135 MInt counter = 0;
7136 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
7137 a_noParticlesInCell(cellId) = data[counter++];
7138 a_noEllipsoidsInCell(cellId) = data[counter++];
7139 }
7140 } else if(dataId == 2) {
7141 /*
7142 MInt i = 0;
7143 for(MInt part = 0; part < a_noParticles(); part++){
7144 MInt a = data[i];
7145 MInt b = data[i + 1 ];
7146 MLong partId = ((MLong)a << 32 | ((MLong)b & 0xFFFFFFFFL));
7147 //m_partList[part].m_partId = partId;
7148 //m_partList[part].m_noParticles = data[i + 2];
7149 //ASSERT(m_partList[part].m_noParticles > 0 , "");
7150 if(data[i + 2] < 0 || data[i + 2] > 10000) {
7151 cerr << "Strange parcel-count!" << data[i + 2] << " " << partId << endl;
7152 }
7153 i = i + 3;
7154 }
7155 */
7156 }
7157 }
7158}

◆ setCellWeights()

template<MInt nDim>
void LPT< nDim >::setCellWeights ( MFloat solverCellWeight)
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1827 of file lpt.cpp.

1827 {
1828 TRACE();
1829 ASSERT(isActive(), "solver is not active");
1830
1832
1833 const MInt noCellsGrid = grid().raw().treeb().size();
1834 const MInt offset = noCellsGrid * solverId();
1835
1836 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
1837 const MInt gridCellId = grid().tree().solver2grid(cellId);
1838 const MInt id = gridCellId + offset;
1839 solverCellWeight[id] = m_weightBaseCell * m_weightMulitSolverFactor;
1840 if(!c_isLeafCell(cellId)) continue;
1841 solverCellWeight[id] = m_weightLeafCell * m_weightMulitSolverFactor;
1842 if(a_noParticlesInCell(cellId) == 0 && a_noEllipsoidsInCell(cellId) == 0) continue;
1843 solverCellWeight[id] =
1846 }
1847
1848 // additionally increase weight at spawncellId
1849 if(m_engineSetup && m_sprayModel != nullptr && m_spawnCellId > -1) {
1850 const MInt gridCellId = grid().tree().solver2grid(m_spawnCellId);
1851 const MInt id = gridCellId + offset;
1852 solverCellWeight[id] += m_weightSpawnCell * m_weightMulitSolverFactor;
1853 }
1854}
MFloat m_weightParticleCell
Definition: lpt.h:547
MFloat m_weightBaseCell
Definition: lpt.h:545
MFloat m_weightParticle
Definition: lpt.h:548
MFloat m_weightSpawnCell
Definition: lpt.h:549
MBool m_engineSetup
Definition: lpt.h:754
MFloat m_weightLeafCell
Definition: lpt.h:546
MFloat m_weightMulitSolverFactor
Definition: lpt.h:550

◆ setGlobalSolverVars()

template<MInt nDim>
void LPT< nDim >::setGlobalSolverVars ( std::vector< MFloat > &  globalFloatVars,
std::vector< MInt > &  globalIdVars 
)
override
Author
Tim Wegmann

Definition at line 7204 of file lpt.cpp.

7204 {
7205 TRACE();
7206
7207 m_PRNGSpawnCount = globalIntVars[0];
7208
7209 m_particleResiduum = globalFloatVars[0];
7210 m_time = globalFloatVars[1];
7211 m_timeStep = globalFloatVars[2];
7212
7214 m_sprayModel->m_PRNGPrimBreakUpCount = globalIntVars[1];
7215 }
7216 if(m_activePrimaryBUp) {
7217 m_sprayModel->timeSinceSOI() = globalFloatVars[3];
7218 }
7219
7220
7221 if(m_activePrimaryBUp) {
7222 const MInt vectorSize = globalIntVars[2];
7223 m_injData.clear();
7224
7225 const MInt count = m_sprayModel->m_injDataSize + m_addInjDataCnt;
7226 for(MInt i = 0; i < vectorSize * (count + 1); i = i + 1 + count) {
7227 const MInt timeStep = (MInt)globalFloatVars[i + m_addInjDataCnt];
7228 vector<MFloat> tmp(count);
7229 for(MInt j = 0; j < count; j++) {
7230 tmp[j] = globalFloatVars[i + j + 1 + m_addInjDataCnt];
7231 }
7232 m_injData.insert(make_pair(timeStep, tmp));
7233 }
7234 }
7235}

◆ setRegridTrigger()

template<MInt nDim>
void LPT< nDim >::setRegridTrigger
private
Author
Tim Wegmann

Definition at line 7373 of file lpt.cpp.

7373 {
7374 TRACE();
7375
7376 if(!this->m_adaptation || this->m_noSensors == 0) return;
7377
7378 m_log << "Reset LPT-regrid trigger at timestep: " << globalTimeStep << endl;
7379
7380 MBoolScratchSpace inShadowLayer(a_noCells(), AT_, "inShadowLayer");
7381 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
7382
7383 vector<MInt> lastLayer;
7384 vector<MInt> tmp;
7385
7386 // reset property and mark cells with particles as first layer
7387 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
7388 a_regridTrigger(cellId) = false;
7389 if(a_noParticlesInCell(cellId) > 0 || a_noEllipsoidsInCell(cellId) > 0 || cellId == m_spawnCellId) {
7390 inShadowLayer(cellId) = true;
7391 lastLayer.emplace_back(cellId);
7392 }
7393 }
7394
7395 // 4. cover shadow band locally in the domain
7396 MInt layerCount = 0;
7397 while(layerCount < m_bandWidth[maxRefinementLevel() - 1]) {
7398 // ii. build the next layer
7399 tmp.clear();
7400 for(MInt c = 0; c < (signed)lastLayer.size(); c++) {
7401 const MInt cellId = lastLayer[c];
7402 for(MInt d = 0; d < m_noDirs; d++) {
7403 if(c_hasNeighbor(cellId, d) == 0) {
7404 // additionally check for regrid when rebuilding
7405 if(c_parentId(cellId) > -1 && c_hasNeighbor(c_parentId(cellId), d) && !a_isHalo(cellId)) {
7406 if(a_isValidCell(cellId)) {
7407 m_forceAdaptation = true;
7408 }
7409 }
7410 continue;
7411 }
7412 const MInt nghbrId = c_neighborId(cellId, d);
7413 if(!inShadowLayer[nghbrId]) {
7414 tmp.emplace_back(nghbrId);
7415 if(layerCount > m_bandWidth[maxRefinementLevel() - 1] - m_innerBound) {
7416 a_regridTrigger(nghbrId) = true;
7417 }
7418 }
7419 inShadowLayer[nghbrId] = true;
7420 }
7421 }
7422
7423 // exchange next layer with neighboring domains
7424 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
7425 for(MInt j = 0; j < noWindowCells(i); j++) {
7426 tmp_data(windowCellId(i, j)) = inShadowLayer(windowCellId(i, j));
7427 }
7428 }
7429
7430 this->exchangeData(&tmp_data(0), 1);
7431
7432 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
7433 for(MInt j = 0; j < noHaloCells(i); j++) {
7434 const MInt haloCell = haloCellId(i, j);
7435 if(!inShadowLayer[haloCell]) {
7436 inShadowLayer[haloCell] = tmp_data(haloCell);
7437 if(inShadowLayer[haloCell]) {
7438 tmp.emplace_back(haloCell);
7439 if(layerCount > m_bandWidth[maxRefinementLevel() - 1] - m_innerBound) {
7440 a_regridTrigger(haloCell) = true;
7441 }
7442 }
7443 }
7444 }
7445 }
7446
7447 // iii. swap data
7448 // continue to the next layer
7449 lastLayer.clear();
7450 for(MInt c = 0; c < (signed)tmp.size(); c++) {
7451 lastLayer.emplace_back(tmp[c]);
7452 }
7453 layerCount++;
7454 }
7455
7456
7457 MPI_Allreduce(MPI_IN_PLACE, &m_forceAdaptation, 1, MPI_C_BOOL, MPI_LOR, mpiComm(), AT_, "MPI_IN_PLACE", "status");
7458
7459 if(domainId() == 0 && m_forceAdaptation) {
7460 cerr << "LPT-Solver is forcing a mesh-adaptation at time step " << globalTimeStep << endl;
7461 }
7462}
MInt c_neighborId(const MInt cellId, const MInt dir) const
Definition: lpt.h:985
MInt m_innerBound
Definition: lpt.h:828
MInt c_hasNeighbor(const MInt cellId, const MInt dir) const
Definition: lpt.h:983
MInt noWindowCells(const MInt domainId) const
MInt windowCellId(const MInt domainId, const MInt cellId) const
const MInt & haloCell(const MInt domainId, const MInt cellId) const
MInt haloCellId(const MInt domainId, const MInt cellId) const

◆ setSensors()

template<MInt nDim>
void LPT< nDim >::setSensors ( std::vector< std::vector< MFloat > > &  sensors,
std::vector< MFloat > &  sensorWeight,
std::vector< std::bitset< 64 > > &  sensorCellFlag,
std::vector< MInt > &  sensorSolverId 
)
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1285 of file lpt.cpp.

1288 {
1289 TRACE();
1290
1291 MInt noSensors = this->m_noInitialSensors;
1292 if(globalTimeStep > 0) noSensors = this->m_noSensors;
1293
1294 // If solver is inactive the sensor arrays still need to be set to optain the
1295 // correct offsets
1296 const MInt sensorOffset = (signed)sensors.size();
1297 ASSERT(sensorOffset == 0 || grid().raw().treeb().noSolvers() > 1, "");
1298 sensors.resize(sensorOffset + noSensors, vector<MFloat>(grid().raw().m_noInternalCells, F0));
1299 sensorWeight.resize(sensorOffset + noSensors, -1);
1300 sensorCellFlag.resize(grid().raw().m_noInternalCells, sensorOffset + noSensors);
1301 sensorSolverId.resize(sensorOffset + noSensors, solverId());
1302 ASSERT(sensorOffset + noSensors < CartesianGrid<nDim>::m_maxNoSensors, "Increase bitset size!");
1303
1304 if(domainId() == 0) {
1305 cerr << "Setting " << noSensors << " sensors for LPT-Solver adaptation." << endl;
1306 }
1307
1308 for(MInt sen = 0; sen < noSensors; sen++) {
1309 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
1310 }
1311
1312 ASSERT(m_freeIndices.empty(), "");
1313 m_freeIndices.clear();
1314
1315 if(!isActive()) return;
1316
1317 for(MInt sen = 0; sen < noSensors; sen++) {
1318 (this->*(this->m_sensorFnPtr[sen]))(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen);
1319 }
1320
1321 /*
1322 if(m_spawnCellId > -1) {
1323 const MInt gridCellId = grid().tree().solver2grid(m_spawnCellId);
1324 const MInt partent = c_parentId(m_spawnCellId);
1325 const MInt parentGridCellId = partent > -1 ? grid().tree().solver2grid(partent) : -1;
1326 if(parentGridCellId > -1 && sensors[sensorOffset][parentGridCellId] < 1) {
1327 if(sensors[sensorOffset][gridCellId] < 1) {
1328 cerr << "Injector is not refined!" << endl;
1329 }
1330 }
1331 }
1332 */
1333}
MInt noSolvers
Definition: maiatypes.h:73

◆ smallParticle()

template<MInt nDim>
MBool LPT< nDim >::smallParticle ( const LPTSpherical< nDim > &  particle)
inlineprotected

Definition at line 734 of file lpt.h.

734{ return (particle.m_diameter < m_sizeLimit); }

◆ solutionStep()

template<MInt nDim>
MBool LPT< nDim >::solutionStep
overridevirtual
Date
December-09
Author
Rudie Kunnen, Sven Berger, Tim Wegmann

Reimplemented from Solver.

Definition at line 2139 of file lpt.cpp.

2139 {
2140 TRACE();
2141
2143 && globalTimeStep == 0 && noDomains() == 1) {
2144 return true;
2145 }
2146
2147 // To set particle release Time for particles in isoTropic Turbulence
2148 // Release Timestep is determined by a Skewness of 0.44 of fluid velocity
2149 if(m_skewnessTimeStep != 0 && globalTimeStep < m_skewnessTimeStep) return true;
2150
2151 RECORD_TIMER_START(m_timers[Timers::TimeInt]);
2152
2153 // apply arbitrary LPT load to test&validate interleaved coupling
2154 // remaining for documentation and testing purposes
2155 if(m_sleepLPT > 0.0) {
2156 cerr0 << "Sleeping LPT-solver for " << m_sleepLPT << " milli-seconds!" << endl;
2157 std::this_thread::sleep_for(std::chrono::milliseconds(m_sleepLPT));
2158 }
2159
2160 if(m_skipLPT) {
2161 cerr0 << "Skipping LPT execution!" << endl;
2162 return true;
2163 }
2164
2165
2166 MBool completed = false;
2167 switch(m_noSolutionSteps) {
2168 case 1: {
2169 completed = oneStageSolutionStep();
2170 break;
2171 }
2172 case 5: {
2173 completed = fiveStageSolutionStep();
2174 break;
2175 }
2176 default: {
2177 mTerm(1, AT_, "SolutionStep method not implemented in LPT!");
2178 break;
2179 }
2180 }
2181
2182 RECORD_TIMER_STOP(m_timers[Timers::TimeInt]);
2183 return completed;
2184}
MBool fiveStageSolutionStep()
Splitting the solutionStep into 5 separate parts to match the 5-stage Runge-Kutta time-stepping for i...
Definition: lpt.cpp:2194
MInt m_noSolutionSteps
Definition: lpt.h:948
MInt m_skewnessTimeStep
Definition: lpt.h:751
MBool oneStageSolutionStep()
single solution step for pure LPT computation or without interleafed coupling!
Definition: lpt.cpp:2387

◆ sort_impl_()

template<MInt nDim>
template<class T , class Pred >
void LPT< nDim >::sort_impl_ ( T &  c,
Pred &  p,
std::random_access_iterator_tag   
)
inlineprotected

Definition at line 719 of file lpt.h.

719 {
720 std::sort(c.begin(), c.end(), p);
721 }

◆ spawnParticles()

template<MInt nDim>
void LPT< nDim >::spawnParticles
protected
Author
Sven Berger
Date
June 2015

Definition at line 5734 of file lpt.cpp.

5734 {
5735 // particles are spawned on another domain
5736 if(m_spawnCellId < 0) {
5737 if(noDomains() > 1) {
5738 // receive injected particles instead
5739 recvInjected();
5740 }
5741 m_particleResiduum = 0.0;
5742 return;
5743 }
5744 ASSERT(domainId() == m_spawnDomainId, "");
5745
5746 const MInt prevNo = m_partList.empty() ? 0 : m_partList.size() - 1;
5747 const auto noNewParticles = (MInt)(m_spawnParticlesCount * m_timeStep + m_particleResiduum);
5749
5750 if(noNewParticles >= 1) {
5751 MFloatScratchSpace spawnParticlesInitVelo(nDim, AT_, "spawnParticlesInitVelo");
5752
5753 for(MInt i = 0; i < noNewParticles; i++) {
5757
5758 addParticle(m_spawnCellId, m_spawnDiameter, m_material->densityRatio(), 0, 1, &spawnParticlesInitVelo[0],
5759 &m_spawnCoord[0], 1);
5760 }
5761
5762
5763 broadcastInjected(prevNo);
5764
5765#ifdef LPT_DEBUG
5766 cerr << "added " << noNewParticles << " new particles with diameter " << m_spawnDiameter << " to cell "
5767 << m_spawnCellId << endl;
5768#endif
5769 }
5770}
void broadcastInjected(const MUint prevNumPart)
Send newly created particles.
Definition: lpt.cpp:6221
MInt m_spawnParticlesCount
Definition: lpt.h:808
MFloat m_spawnParticlesConeAngle
Definition: lpt.h:805
MFloat m_spawnDir[nDim]
Definition: lpt.h:806
MInt m_spawnEmittDist
Definition: lpt.h:811
MFloat m_spawnDiameter
Definition: lpt.h:807
MFloat m_spawnDistSigmaCoeff
Definition: lpt.h:812
void recvInjected()
receive particles generated during injection
Definition: lpt.cpp:5812
MInt addParticle(const MInt cellId, const MFloat diameter, const MFloat particleDensityRatio, const MInt random=1, const MInt addMode=0, const MFloat *velocity=nullptr, const MFloat *position=nullptr, const MInt parcelSize=1)
Add new particle.
Definition: lpt.cpp:5495
MInt randomVectorInCone(MFloat *vec, const MFloat *coneAxis, const MFloat length, const MFloat openingAngle, const MInt dist, std::mt19937_64 &PRNG, const MFloat distCoeff=0.0, const MFloat nozzleAngle=0.0)
Generate a random vector in a cone defined by its opening angle.
Definition: lptlib.h:252

◆ spawnTimeStep()

template<MInt nDim>
void LPT< nDim >::spawnTimeStep
private
Date
August-2021
Author
???, update Tim Wegmann

Definition at line 2624 of file lpt.cpp.

2624 {
2625 // current number of particles
2626 const MInt oldNum = a_noParticles();
2627
2628 ASSERT(!m_nonBlockingComm, "");
2629
2631
2632 exchangeParticles(false, oldNum, false);
2633
2634 motionEquation(oldNum);
2635
2636 exchangeParticles(false, oldNum);
2637
2638 evaporation(oldNum);
2639
2640 coupling(oldNum);
2641}
void spawnParticles()
Spawn new particles (used for testing)
Definition: lpt.cpp:5734

◆ sprayInjection()

template<MInt nDim>
void LPT< nDim >::sprayInjection
private

Definition at line 2644 of file lpt.cpp.

2644 {
2645 RECORD_TIMER_START(m_timers[Timers::Injection]);
2646 const MInt oldNum = a_noParticles();
2647
2648 m_sprayModel->injection(m_timeStep);
2649
2650 // check for particles to be copied to other solvers
2651 // this is necessary for particles during injection
2652 // for which a leaf-halo cell could be found
2653 // where the injector dimension lies within a 2 minLevel cells
2654 // meaning that at least lower level halo cells can be found and an exchange is possible
2655 // instead of a broadcast!
2656 MBool allowNonLeaf = !m_sprayModel->m_broadcastInjected;
2657 m_primaryExchange = true;
2658 exchangeParticles(false, oldNum, allowNonLeaf);
2659 if(!m_nonBlockingComm) {
2660 m_primaryExchange = false;
2661 }
2662 RECORD_TIMER_STOP(m_timers[Timers::Injection]);
2663}

◆ swapCells()

template<MInt nDim>
void LPT< nDim >::swapCells ( const MInt  cellId0,
const MInt  cellId1 
)
overridevirtual
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 1782 of file lpt.cpp.

1782 {
1783 std::swap(m_cells.properties(cellId1), m_cells.properties(cellId0));
1784
1785 std::swap(m_cells.volumeFraction(cellId1), m_cells.volumeFraction(cellId0));
1786 std::swap(m_cells.noParticles(cellId1), m_cells.noParticles(cellId0));
1787 std::swap(m_cells.noEllipsoids(cellId1), m_cells.noEllipsoids(cellId0));
1788
1789 for(MInt n = 0; n < PV.noVars(); n++) {
1790 std::swap(m_cells.fluidVariable(cellId1, n), m_cells.fluidVariable(cellId0, n));
1791 }
1792
1793 if(m_evaporation) {
1794 std::swap(m_cells.fluidSpecies(cellId1), m_cells.fluidSpecies(cellId0));
1795 }
1796
1797 if(m_massCoupling) {
1798 std::swap(m_cells.massFlux(cellId1), m_cells.massFlux(cellId0));
1799 }
1800 if(m_heatCoupling) {
1801 std::swap(m_cells.heatFlux(cellId1), m_cells.heatFlux(cellId0));
1802 }
1803 if(m_momentumCoupling) {
1804 for(MInt i = 0; i < nDim; i++) {
1805 std::swap(m_cells.momentumFlux(cellId1, i), m_cells.momentumFlux(cellId0, i));
1806 }
1807 std::swap(m_cells.workFlux(cellId1), m_cells.workFlux(cellId0));
1808 }
1809 std::swap(m_cells.bndryCellId(cellId1), m_cells.bndryCellId(cellId0));
1810
1811 // only ellipsoids require velocity slopes
1812 if(m_ellipsoids) {
1813 for(MInt varId = 0; varId < nDim; varId++) {
1814 for(MInt dim = 0; dim < nDim; dim++) {
1815 std::swap(m_cells.velocitySlope(cellId1, varId, dim), m_cells.velocitySlope(cellId0, varId, dim));
1816 }
1817 }
1818 }
1819}
BitsetType & properties(const MInt id)
Accessor for properties.

◆ swapProxy()

template<MInt nDim>
void LPT< nDim >::swapProxy ( MInt  cellId0,
MInt  cellId1 
)
overridevirtual
Author
Lennart Schneiders

Reimplemented from Solver.

Definition at line 1528 of file lpt.cpp.

1528 {
1529 grid().swapGridIds(cellId0, cellId1);
1530}

◆ time()

template<MInt nDim>
MFloat LPT< nDim >::time ( ) const
inlineoverridevirtual

Implements Solver.

Definition at line 940 of file lpt.h.

940{ return m_time; }

◆ timeSinceSOI()

template<MInt nDim>
MFloat LPT< nDim >::timeSinceSOI ( ) const
inline

Definition at line 479 of file lpt.h.

479{ return m_sprayModel != nullptr ? m_sprayModel->timeSinceSOI() : m_time; }

◆ timeStep()

template<MInt nDim>
MFloat LPT< nDim >::timeStep ( )
inline

Definition at line 317 of file lpt.h.

317{ return m_timeStep; }

◆ unpackParticle() [1/2]

template<MInt nDim>
void LPT< nDim >::unpackParticle ( LPTEllipsoidal< nDim > &  thisParticle,
const MInt intBuffer,
MInt z,
const MFloat floatBuffer,
MInt h,
MInt step,
MInt  id 
)
private
Author
Laurent Andre
Date
Februar 2022

Definition at line 6152 of file lpt.cpp.

6153 {
6154 if(intBuffer != nullptr) {
6155 MInt a = intBuffer[z++];
6156 MInt b = intBuffer[z++];
6157 MLong partId = ((MLong)a << 32 | ((MLong)b & 0xFFFFFFFFL));
6158 thisParticle.m_partId = partId;
6159 thisParticle.m_cellId = intBuffer[z++];
6160 step = intBuffer[z++];
6161 thisParticle.hadWallColl() = (MBool)intBuffer[z++];
6162 if(id == 0 && z != intElemPerP<LPTEllipsoidal<nDim>>()) {
6163 mTerm(1, AT_, "Buffersize missmatching!");
6164 }
6165 }
6166 thisParticle.m_semiMinorAxis = floatBuffer[h++];
6167 thisParticle.m_aspectRatio = floatBuffer[h++];
6168 thisParticle.initEllipsoialProperties();
6169 thisParticle.m_densityRatio = floatBuffer[h++];
6170 for(MInt l = 0; l < nDim; l++)
6171 thisParticle.m_position.at(l) = floatBuffer[h++];
6172 for(MInt l = 0; l < nDim; l++)
6173 thisParticle.m_velocity.at(l) = floatBuffer[h++];
6174 for(MInt l = 0; l < nDim; l++)
6175 thisParticle.m_accel.at(l) = floatBuffer[h++];
6176 for(MInt l = 0; l < nDim; l++)
6177 thisParticle.m_angularVel.at(l) = floatBuffer[h++];
6178 for(MInt l = 0; l < nDim; l++)
6179 thisParticle.m_angularAccel.at(l) = floatBuffer[h++];
6180 for(MInt l = 0; l < 4; l++)
6181 thisParticle.m_quaternion.at(l) = floatBuffer[h++];
6182 for(MInt l = 0; l < nDim; l++)
6183 thisParticle.m_oldPos.at(l) = floatBuffer[h++];
6184 for(MInt l = 0; l < nDim; l++)
6185 thisParticle.m_oldVel.at(l) = floatBuffer[h++];
6186 for(MInt l = 0; l < nDim; l++)
6187 thisParticle.m_oldAccel.at(l) = floatBuffer[h++];
6188 for(MInt l = 0; l < nDim; l++)
6189 thisParticle.m_oldAngularVel.at(l) = floatBuffer[h++];
6190 for(MInt l = 0; l < nDim; l++)
6191 thisParticle.m_oldAngularAccel.at(l) = floatBuffer[h++];
6192 for(MInt l = 0; l < 4; l++)
6193 thisParticle.m_oldQuaternion.at(l) = floatBuffer[h++];
6194 thisParticle.m_creationTime = floatBuffer[h++];
6195 thisParticle.m_temperature = floatBuffer[h++];
6196 thisParticle.m_heatFlux = floatBuffer[h++];
6197 thisParticle.m_fluidVelMag = floatBuffer[h++];
6198 thisParticle.m_oldFluidDensity = floatBuffer[h++];
6199 for(MInt l = 0; l < nDim; l++)
6200 thisParticle.m_oldFluidVel[l] = floatBuffer[h++];
6201
6202 if(id == 0 && h != elemPerP<LPTEllipsoidal<nDim>>()) {
6203 mTerm(1, AT_, "Buffersize missmatching!");
6204 }
6205
6206 if(intBuffer == nullptr) {
6207 MInt a = (MInt)floatBuffer[h++];
6208 MInt b = (MInt)floatBuffer[h++];
6209 MLong partId = ((MLong)a << 32 | ((MLong)b & 0xFFFFFFFFL));
6210 thisParticle.m_partId = partId;
6211 }
6212}
BitsetType::reference hadWallColl()
Definition: lptbase.h:169
MFloat m_fluidVelMag
fluid velocity magnitude
MFloat m_heatFlux
heat flux to cell

◆ unpackParticle() [2/2]

template<MInt nDim>
void LPT< nDim >::unpackParticle ( LPTSpherical< nDim > &  thisParticle,
const MInt intBuffer,
MInt z,
const MFloat floatBuffer,
MInt h,
MInt step,
MInt  id 
)
private

Definition at line 6084 of file lpt.cpp.

6085 {
6086 if(intBuffer != nullptr) {
6087 MInt a = intBuffer[z++];
6088 MInt b = intBuffer[z++];
6089 MLong partId = ((MLong)a << 32 | ((MLong)b & 0xFFFFFFFFL));
6090 thisParticle.m_partId = partId;
6091 thisParticle.m_cellId = intBuffer[z++];
6092 thisParticle.m_noParticles = intBuffer[z++];
6093 step = intBuffer[z++];
6094 thisParticle.hadWallColl() = (MBool)intBuffer[z++];
6095 if(id == 0 && z != intElemPerP<LPTSpherical<nDim>>()) {
6096 mTerm(1, AT_, "Buffersize missmatching!");
6097 }
6098 }
6099
6100 thisParticle.m_diameter = floatBuffer[h++];
6101 thisParticle.m_densityRatio = floatBuffer[h++];
6102 for(MInt l = 0; l < nDim; l++) {
6103 thisParticle.m_position.at(l) = floatBuffer[h++];
6104 }
6105 for(MInt l = 0; l < nDim; l++) {
6106 thisParticle.m_velocity.at(l) = floatBuffer[h++];
6107 }
6108 for(MInt l = 0; l < nDim; l++) {
6109 thisParticle.m_accel.at(l) = floatBuffer[h++];
6110 }
6111 for(MInt l = 0; l < nDim; l++) {
6112 thisParticle.m_oldPos.at(l) = floatBuffer[h++];
6113 }
6114 for(MInt l = 0; l < nDim; l++) {
6115 thisParticle.m_oldVel.at(l) = floatBuffer[h++];
6116 }
6117 for(MInt l = 0; l < nDim; l++) {
6118 thisParticle.m_oldAccel.at(l) = floatBuffer[h++];
6119 }
6120 thisParticle.m_creationTime = floatBuffer[h++];
6121 thisParticle.m_breakUpTime = floatBuffer[h++];
6122 thisParticle.m_shedDiam = floatBuffer[h++];
6123 thisParticle.m_temperature = floatBuffer[h++];
6124 thisParticle.m_dM = floatBuffer[h++];
6125 thisParticle.m_heatFlux = floatBuffer[h++];
6126 thisParticle.m_fluidVelMag = floatBuffer[h++];
6127
6128 thisParticle.m_oldFluidDensity = floatBuffer[h++];
6129 for(MInt l = 0; l < nDim; l++) {
6130 thisParticle.m_oldFluidVel[l] = floatBuffer[h++];
6131 }
6132 if(id == 0 && h != elemPerP<LPTSpherical<nDim>>()) {
6133 mTerm(1, AT_, "Buffersize missmatching!");
6134 }
6135
6136 if(intBuffer == nullptr) {
6137 MInt a = (MInt)floatBuffer[h++];
6138 MInt b = (MInt)floatBuffer[h++];
6139 MLong partId = ((MLong)a << 32 | ((MLong)b & 0xFFFFFFFFL));
6140 thisParticle.m_partId = partId;
6141 thisParticle.m_noParticles = (MInt)floatBuffer[h++];
6142 }
6143}
MFloat m_heatFlux
heat flux to cell
Definition: lptspherical.h:90
MFloat m_fluidVelMag
fluid velocity magnitude
Definition: lptspherical.h:88

◆ unpackParticles()

template<MInt nDim>
template<class LPTParticle , MBool t_search>
void LPT< nDim >::unpackParticles ( const MInt  num,
const MInt intBuffer,
const MFloat floatBuffer,
const MInt  domain = -1,
const MBool  allowNonLeaf = false 
)
private
Author
Sven Berger
Date
September 2018
Template Parameters
t_searchsearch for valid cellId, otherwise use known cellId

Definition at line 6008 of file lpt.cpp.

6009 {
6010 MInt z = 0;
6011 MInt h = 0;
6012 MInt i = -1;
6013 for(MInt id = 0; id < num; id++) {
6014 LPTParticle thisParticle;
6015 unpackParticle(thisParticle, intBuffer, z, floatBuffer, h, i, id);
6016
6017 thisParticle.initProperties();
6018 thisParticle.firstStep() = ((i % 2) > 0);
6019
6020 // search for new cellId
6021 if(t_search) {
6022 const MInt cellId = grid().findContainingLeafCell(&thisParticle.m_position[0]);
6023
6024 if(cellId >= 0 && !a_isHalo(cellId)) {
6025 thisParticle.m_cellId = cellId;
6026 } else {
6027 continue;
6028 }
6029 } else { // use cellId from halo/window cell collector
6030 if(i < 2) {
6031 // before the particle-particle collision step,
6032 // when window particles are communicated back to the halo part for collision
6033 thisParticle.m_cellId = haloCellId(domain, thisParticle.m_cellId);
6034 thisParticle.wasSend() = true;
6035 thisParticle.toBeDeleted() = false;
6036 thisParticle.isInvalid() = true;
6037 ASSERT(m_collisions > 0, "");
6038 } else {
6039 // NOTE: at this point the cellId represents the entry to the matching
6040 // halo/windowcellId in the corresponding containers!
6041 if(thisParticle.m_cellId < 0) {
6042 mTerm(1, AT_, "ERROR: Particle has no valid cell!");
6043 }
6044 // regular exchange from halo to window => thus already knowing the matching cellId
6045 // and avoiding the search for the matching cellId!
6046 thisParticle.m_cellId = windowCellId(domain, thisParticle.m_cellId);
6047 // update window/halo cell properties only
6048 thisParticle.updateProperties(false);
6049
6050 // loop down and find leaf-windowcell for particles
6051 // which where on a non-leaf halo-cell
6052 if(allowNonLeaf && !c_isLeafCell(thisParticle.m_cellId)) {
6053 thisParticle.m_cellId = grid().findContainingLeafCell(&thisParticle.m_position[0], thisParticle.m_cellId);
6054 thisParticle.m_oldCellId = thisParticle.m_cellId;
6055
6056 if(!thisParticle.firstStep()) {
6057 mTerm(1, AT_, "Non-leaf comm. of not injected cell requested!");
6058 }
6059 }
6060 if(!c_isLeafCell(thisParticle.m_cellId)) {
6061 mTerm(1, AT_, "ERROR: Particle has no valid leaf-cell!");
6062 }
6063 }
6064 }
6065
6066 if(thisParticle.m_cellId < 0) {
6067 mTerm(1, AT_, "ERROR: Particle has no valid cell!");
6068 }
6069
6070 if(thisParticle.m_oldCellId < 0) {
6071 thisParticle.m_oldCellId = grid().findContainingLeafCell(&thisParticle.m_oldPos[0], thisParticle.m_cellId);
6072 }
6073
6074 std::vector<LPTParticle>& particleList = a_particleList<LPTParticle>();
6075 particleList.push_back(thisParticle);
6076 }
6077}
void unpackParticle(LPTSpherical< nDim > &thisParticle, const MInt *intBuffer, MInt &z, const MFloat *floatBuffer, MInt &h, MInt &step, MInt id)
Unpack spherical particle from buffers.
Definition: lpt.cpp:6084

◆ updateExchangeCells()

template<MInt nDim>
void LPT< nDim >::updateExchangeCells
private
Author
Tim Wegmann
Date
November 2020

Definition at line 6339 of file lpt.cpp.

6339 {
6340 TRACE();
6341
6342 const MInt noNghbrDomains = grid().noNeighborDomains();
6343
6344 // set lpt cell collector property
6345 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6346 a_isHalo(cellId) = false;
6347 a_isWindow(cellId) = false;
6348 }
6349
6350 m_pointsToHalo.clear();
6351 m_pointsToHalo.resize(noNghbrDomains);
6352
6353 for(MInt i = 0; i < noNghbrDomains; i++) {
6354 for(MInt j = 0; j < noWindowCells(i); j++) {
6355 const MInt windowCell = windowCellId(i, j);
6356 a_isWindow(windowCell) = true;
6357 if(!c_isLeafCell(windowCell)) continue;
6358 // set pointsToHalo for leaf-Cell window-Cells.
6359 // this is used in the pushToQueue-function in particleTransfer!
6360 // Meaning that the particle is only transferred if the corresponding cellId
6361 // is found in this list!
6362 const MInt windowCellOffset = j;
6363 m_pointsToHalo[i].insert(make_pair(windowCell, windowCellOffset));
6364 }
6365 }
6366
6367 m_pointsToWindow.clear();
6368 m_pointsToWindow.resize(noNghbrDomains);
6369
6370 for(MInt i = 0; i < noNghbrDomains; i++) {
6371 for(MInt j = 0; j < noHaloCells(i); j++) {
6372 const MInt haloCell = haloCellId(i, j);
6373 a_isHalo(haloCell) = true;
6374 if(!c_isLeafCell(haloCell)) continue;
6375 const MInt HaloCellOffset = j;
6376 // set pointsToHalo for leaf-Cell halo-Cells.
6377 // this is used in the pushToQueue-function in particleTransfer!
6378 // Meaning that the particle is only transferred if the corresponding cellId
6379 // is found in this list!
6380 // NOTE: the search is now only done for matching cells(in this case halo-cells!)
6381 m_pointsToWindow[i].insert(make_pair(haloCell, HaloCellOffset));
6382 }
6383 }
6384}
const MInt & windowCell(const MInt domainId, const MInt cellId) const

◆ updateFluidFraction()

template<MInt nDim>
void LPT< nDim >::updateFluidFraction

Definition at line 6286 of file lpt.cpp.

6286 {
6287
6288#ifdef _OPENMP
6289#pragma omp single
6290#endif
6291 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6292 a_volumeFraction(cellId) = 0.0;
6293 }
6294
6295#ifdef _OPENMP
6296#pragma omp single
6297#endif
6298 for(MInt i = 0; i < a_noParticles(); i++) {
6299 const MInt cellId = m_partList[i].m_cellId;
6300 // particle Volume Fraction = particleVolume * parcelSize / volume of the cartesian cell!
6301 a_volumeFraction(cellId) +=
6302 4.0 / 3.0 * PI * POW3(0.5 * m_partList[i].m_diameter) * m_partList[i].m_noParticles / c_cellVolume(cellId);
6303 }
6304 if(m_ellipsoids) {
6305#ifdef _OPENMP
6306#pragma omp single
6307#endif
6308 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
6309 const MInt cellId = m_partListEllipsoid[i].m_cellId;
6310 // particle Volume Fraction = particleVolume / volume of the cartesian cell!
6311 a_volumeFraction(cellId) += m_partListEllipsoid[i].particleVolume() / c_cellVolume(cellId);
6312 }
6313 }
6314
6315 // correct cell-volume for bndrycells
6316 for(MInt bndryCellId = 0; bndryCellId < m_bndryCells->size(); bndryCellId++) {
6317 const MInt lptCellId = m_bndryCells->a[bndryCellId].m_cellId;
6318 a_volumeFraction(lptCellId) *= c_cellVolume(lptCellId) / m_bndryCells->a[bndryCellId].m_volume;
6319 }
6320
6321#if !defined NDEBUG
6322 /*
6323 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6324 if(a_volumeFraction(cellId) > 0.9) {
6325 cerr << "Particle volume in cell is almost larger than the cartesian cell! " << a_volumeFraction(cellId)
6326 << " This is not possible, particles should have left the cell before! " << endl;
6327 }
6328 }
6329 */
6330#endif
6331}
MFloat & a_volumeFraction(const MInt cellId)
Definition: lpt.h:382

◆ waitForSendReqs()

template<MInt nDim>
void LPT< nDim >::waitForSendReqs
protected
Author
Tim Wegmann

Definition at line 7818 of file lpt.cpp.

7818 {
7819 if(!m_nonBlockingComm) {
7820 return;
7821 }
7822
7824 MPI_Waitall(noNeighborDomains(), &m_mpi_reqSendFloat[0], MPI_STATUSES_IGNORE, AT_);
7825 MPI_Waitall(noNeighborDomains(), &m_mpi_reqSendInt[0], MPI_STATUSES_IGNORE, AT_);
7826 m_openParticleInjSend = false;
7827 }
7828
7829 if(m_openParticleSend) {
7830 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_mpi_reqSendFloat[0], MPI_STATUSES_IGNORE, AT_);
7831 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_mpi_reqSendInt[0], MPI_STATUSES_IGNORE, AT_);
7832 m_openParticleSend = false;
7833 }
7834
7835 if(m_openSourceSend) {
7836 MPI_Waitall(grid().noLeafRecvNeighborDomains(), &m_sourceSendRequest[0], MPI_STATUSES_IGNORE, AT_);
7837 m_openSourceSend = false;
7838 }
7839
7840 if(m_openFlowSend) {
7841 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_flowSendRequest[0], MPI_STATUSES_IGNORE, AT_);
7842 m_openFlowSend = false;
7843 }
7844
7845 if(m_openRegridSend) {
7846 MPI_Wait(&m_checkAdaptationRecvRequest[0], MPI_STATUS_IGNORE, AT_);
7847 m_openRegridSend = false;
7848 }
7849
7850 if(m_openSlopesSend) {
7851 MPI_Waitall(grid().noLeafSendNeighborDomains(), &m_slopesSendRequest[0], MPI_STATUSES_IGNORE, AT_);
7852 m_openSlopesSend = false;
7853 }
7854}

◆ wallCollision()

template<MInt nDim>
void LPT< nDim >::wallCollision
private
Author
Tim Wegmann

Definition at line 3070 of file lpt.cpp.

3070 {
3071 if(!m_wallCollisions) return;
3072
3073 RECORD_TIMER_START(m_timers[Timers::Wall]);
3074
3075 // loop over all particles and call particleCollision step if necessary
3076 for(MInt i = 0; i < a_noParticles(); i++) {
3077 const MInt cellId = m_partList[i].m_cellId;
3078 const MInt oldCellId = m_partList[i].m_oldCellId;
3079
3080 if(cellId < 0) continue;
3081
3082 // if is or was in a boundary cell
3083 // if the cell leaves the cartesin grid the current cellId may be -1,
3084 // but in this case the oldCellId should be a bndryCell!
3085 if(a_isBndryCell(cellId) || a_isBndryCell(oldCellId)) {
3086 m_partList[i].particleWallCollision();
3087 m_partList[i].wallParticleCollision();
3088 }
3089 }
3090
3091 // for ellipsoids
3092 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
3093 const MInt cellId = m_partListEllipsoid[i].m_cellId;
3094 const MInt oldCellId = m_partListEllipsoid[i].m_oldCellId;
3095 if(cellId < 0) continue;
3096 if(a_isBndryCell(cellId) || a_isBndryCell(oldCellId)) {
3097 m_partListEllipsoid[i].particleWallCollision();
3098 m_partListEllipsoid[i].wallParticleCollision();
3099 }
3100 }
3101
3102 RECORD_TIMER_STOP(m_timers[Timers::Wall]);
3103}

◆ writeCellSolutionFile()

template<MInt nDim>
void LPT< nDim >::writeCellSolutionFile ( const MString gridFileName,
MInt recalcIds 
)
Author
Tim Wegmann

Definition at line 5285 of file lpt.cpp.

5285 {
5286 TRACE();
5287
5288 MInt noCells;
5289 MInt noInternalCellIds;
5290 std::vector<MInt> recalcIdsSolver(0);
5291 std::vector<MInt> reOrderedCells(0);
5292 this->calcRecalcCellIdsSolver(recalcIds, noCells, noInternalCellIds, recalcIdsSolver, reOrderedCells);
5293 MInt* pointerRecalcIds = (recalcIds == nullptr) ? nullptr : recalcIdsSolver.data();
5294
5295 if(grid().newMinLevel() > 0) {
5296 cerr0 << "Skipping LPT solution file when min-level changes are applied!" << endl;
5297 return;
5298 }
5299
5300 MBool debugOutput = false;
5301#ifdef LPT_DEBUG
5302 debugOutput = true;
5303#endif
5304
5305 const MInt noIdParams = 0;
5306 const MInt noDbParams = 0;
5307 const MInt noIdVars = 1 + m_ellipsoids;
5308 // VolumeFraction + flowVariables + noSpecies + massCoupling + heatCoupling + momentumCoupling
5309 MInt noDbVars = 1 + PV.noVars() + m_evaporation + m_massCoupling + m_heatCoupling + (nDim + 1) * m_momentumCoupling;
5310 if(m_ellipsoids) {
5311 noDbVars += (nDim * nDim); // if ellipsoids are used also write out the velocity slopes
5312 }
5313 if(debugOutput) {
5314 if(this->m_adaptation && this->m_noSensors > 0) {
5315 noDbVars = noDbVars + 1;
5316 }
5317 if(m_wallCollisions) {
5318 noDbVars = noDbVars + 1;
5319 }
5320 }
5321
5322 MIntScratchSpace idVariables(noCells * noIdVars, AT_, "idVariables");
5323 MFloatScratchSpace dbVariables(noCells * noDbVars, AT_, "dbVariables");
5324 MIntScratchSpace idParameters(noIdParams, AT_, "idParameters");
5325 MFloatScratchSpace dbParameters(noDbParams, AT_, "dbParameters");
5326 vector<MString> dbVariablesName;
5327 vector<MString> idVariablesName;
5328 vector<MString> dbParametersName;
5329 vector<MString> idParametersName;
5330 vector<MString> name;
5331
5332 // TODO labels:LPT,IO @Julian, avoid using buffer
5333 MIntScratchSpace tmp(noCells, AT_, "tmp");
5334 MFloatScratchSpace tmpW(noCells, AT_, "tmpw");
5335
5336 // gather solver data:
5337 name.clear();
5338 name.push_back("noParticlesInCell");
5339 for(MInt cell = 0; cell < noCells; cell++) {
5340 tmp[cell] = a_noParticlesInCell(cell);
5341 }
5342 this->collectVariables(tmp.begin(), idVariables, name, idVariablesName, 1, noCells);
5343
5344 if(m_ellipsoids) {
5345 name.clear();
5346 name.push_back("noEllipsoidsInCell");
5347 for(MInt cell = 0; cell < noCells; cell++) {
5348 tmp[cell] = a_noEllipsoidsInCell(cell);
5349 }
5350 this->collectVariables(tmp.begin(), idVariables, name, idVariablesName, 1, noCells);
5351 }
5352
5353 if(m_massCoupling) {
5354 name.clear();
5355 name.push_back("massFlux");
5356 for(MInt cell = 0; cell < noCells; cell++) {
5357 tmpW[cell] = a_massFlux(cell);
5358 }
5359 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5360 }
5361
5362 if(m_momentumCoupling) {
5363 for(MInt i = 0; i < nDim; i++) {
5364 name.clear();
5365 string tmps = "momentumFlux" + to_string(i);
5366 name.push_back(tmps);
5367 for(MInt cell = 0; cell < noCells; cell++) {
5368 tmpW[cell] = a_momentumFlux(cell, i);
5369 }
5370 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5371 }
5372 name.clear();
5373 name.push_back("workFlux");
5374 for(MInt cell = 0; cell < noCells; cell++) {
5375 tmpW[cell] = a_workFlux(cell);
5376 }
5377 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5378 }
5379
5380 if(m_heatCoupling) {
5381 name.clear();
5382 name.push_back("heatFlux");
5383 for(MInt cell = 0; cell < noCells; cell++) {
5384 tmpW[cell] = a_heatFlux(cell);
5385 }
5386 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5387 }
5388
5389 name.clear();
5390 name.push_back("volumeFraction");
5391 for(MInt cell = 0; cell < noCells; cell++) {
5392 tmpW[cell] = a_volumeFraction(cell);
5393 }
5394 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5395
5396 for(MInt i = 0; i < nDim; i++) {
5397 name.clear();
5398 string tmps = "fluidVelocity_" + to_string(i);
5399 name.push_back(tmps);
5400 for(MInt cell = 0; cell < noCells; cell++) {
5401 tmpW[cell] = a_fluidVelocity(cell, i);
5402 }
5403 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5404 }
5405
5406 name.clear();
5407 name.push_back("fluidDensity");
5408 for(MInt cell = 0; cell < noCells; cell++) {
5409 tmpW[cell] = a_fluidDensity(cell);
5410 }
5411 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5412
5413 name.clear();
5414 name.push_back("fluidPressure");
5415 for(MInt cell = 0; cell < noCells; cell++) {
5416 tmpW[cell] = a_fluidPressure(cell);
5417 }
5418 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5419
5420 name.clear();
5421 name.push_back("fluidTemperture");
5422 for(MInt cell = 0; cell < noCells; cell++) {
5423 tmpW[cell] = a_fluidTemperature(cell);
5424 }
5425 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5426
5427 if(m_evaporation) {
5428 name.clear();
5429 name.push_back("fluidSpecies");
5430 for(MInt cell = 0; cell < noCells; cell++) {
5431 tmpW[cell] = a_fluidSpecies(cell);
5432 }
5433 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5434 }
5435
5436 if(m_ellipsoids) {
5437 for(MInt i = 0; i < nDim; i++) {
5438 for(MInt j = 0; j < nDim; j++) {
5439 name.clear();
5440 string tmps = "fluidVelocitySlopes_" + to_string(i) + "_" + to_string(j);
5441 name.push_back(tmps);
5442 for(MInt cell = 0; cell < noCells; cell++) {
5443 tmpW[cell] = a_velocitySlope(cell, i, j);
5444 }
5445 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5446 }
5447 }
5448 }
5449
5450 if(debugOutput && this->m_adaptation && this->m_noSensors > 0) {
5451 name.clear();
5452 name.push_back("regridTrigger");
5453 for(MInt cell = 0; cell < noCells; cell++) {
5454 tmpW[cell] = a_regridTrigger(cell);
5455 }
5456 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5457 }
5458
5459 if(debugOutput && m_wallCollisions) {
5460 name.clear();
5461 name.push_back("boundaryCellId");
5462 for(MInt cell = 0; cell < noCells; cell++) {
5463 tmpW[cell] = a_bndryCellId(cell);
5464 if(!a_isValidCell(cell)) {
5465 tmpW[cell] = -2;
5466 }
5467 }
5468 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
5469 }
5470
5471 // build file name
5472 stringstream fileName;
5473 fileName.clear();
5474 fileName.str("");
5475 fileName << outputDir() << "solutionLPT_" << getIdentifier(true) << globalTimeStep << ParallelIo::fileExt();
5476
5477 this->saveGridFlowVars((fileName.str()).c_str(), gridFileName.c_str(), noCells, noInternalCellIds, dbVariables,
5478 dbVariablesName, 0, idVariables, idVariablesName, 0, dbParameters, dbParametersName,
5479 idParameters, idParametersName, pointerRecalcIds, -1);
5480}
void saveGridFlowVars(const MChar *fileName, const MChar *gridFileName, const MInt noTotalCells, const MInt noInternal, MFloatScratchSpace &dbVariables, std::vector< MString > &dbVariablesName, MInt noDbVars, MIntScratchSpace &idVariables, std::vector< MString > &idVariablesName, MInt noIdVars, MFloatScratchSpace &dbParameters, std::vector< MString > &dbParametersName, MIntScratchSpace &idParameters, std::vector< MString > &idParametersName, MInt *recalcIds, MFloat time)
This function writes the parallel Netcdf cartesian grid cell based solution/restart file currently us...
void collectVariables(T *variablesIn, ScratchSpace< T > &variablesOut, const std::vector< MString > &variablesNameIn, std::vector< MString > &variablesNameOut, const MInt noVars, const MInt noCells, const MBool reverseOrder=false)
generalised helper function for writing restart files! This is necessary for example if the minLevel ...
void calcRecalcCellIdsSolver(const MInt *const recalcIdsTree, MInt &noCells, MInt &noInternalCellIds, std::vector< MInt > &recalcCellIdsSolver, std::vector< MInt > &reorderedCellIds)
Derive recalc cell ids of the solver and reordered cell ids.

◆ writeCollData()

template<MInt nDim>
void LPT< nDim >::writeCollData
private

Definition at line 6433 of file lpt.cpp.

6433 {
6434 m_collisionModel->writeCollData();
6435}
std::unique_ptr< ParticleCollision< nDim > > m_collisionModel
Definition: lpt.h:195

◆ writePartData()

template<MInt nDim>
void LPT< nDim >::writePartData
protected
Author
Jerry Grimmen, Apr-10

Definition at line 3997 of file lpt.cpp.

3997 {
3998 TRACE();
3999
4000 // sort particles after paricle-id!
4002
4003 queue<partListIteratorConst<nDim>> ncmpiPartQueue;
4004 MInt ncmpiPartQueueSize = 0;
4005
4006 auto i1 = m_partList.begin();
4007 while(i1 != m_partList.end()) {
4008 if(!(*i1).isInvalid() && ((*i1).m_position[0] > m_xCutOff)) {
4009 ++ncmpiPartQueueSize;
4010 ncmpiPartQueue.push(i1);
4011 }
4012 i1++;
4013 }
4014
4015 // Get Variable partCount[noDomains()]
4016 MIntScratchSpace ncmpiPartCount(noDomains(), AT_, "ncmpiPartCount");
4017 MPI_Allgather(&ncmpiPartQueueSize, 1, MPI_INT, &ncmpiPartCount[0], 1, MPI_INT, mpiComm(), AT_, "ncmpiPartQueueSize",
4018 "ncmpiPartCount");
4019
4020 // Calculate ncmpiPartCountMax
4021 ParallelIo::size_type ncmpiPartCountMax = 0;
4022 for(MInt i = 0; i < noDomains(); ++i) {
4023 ncmpiPartCountMax += ncmpiPartCount[i];
4024 }
4025
4026 // If there are 0 particle in the whole domain, don't write particle data.
4027 if(ncmpiPartCountMax != 0) {
4028 // stringstream ncmpistream;
4029 const MString ncmpiFileName =
4030 outputDir() + "partData_" + getIdentifier() + to_string(globalTimeStep) + ParallelIo::fileExt();
4031
4032 using namespace maia::parallel_io;
4033 ParallelIo parallelIo(ncmpiFileName, PIO_REPLACE, mpiComm());
4034
4035 // Define Attribute timestep (double).
4036 parallelIo.setAttribute(globalTimeStep, "globalTimestep");
4037 parallelIo.setAttribute(globalTimeStep, "particleTimestep");
4038 if(globalTimeStep == 0) {
4039 parallelIo.setAttribute(0.0, "time");
4040 } else {
4041 parallelIo.setAttribute(m_time, "time");
4042 }
4043 // Define Dimension partCount [noDomains()] & Define Variable partCount
4044 // (int) [partCount].
4045 parallelIo.defineArray(PIO_INT, "partCount", noDomains());
4046
4047 // Define Dimension partId [ncmpiPartCountMax] & Define Variable partId
4048 // (int) [partId].
4049 parallelIo.defineArray(PIO_LONG, "partId", ncmpiPartCountMax);
4050
4051 // Define Dimension partPos [3 * ncmpiPartCountMax] & Define Variable
4052 // partPos (double) [partPos].
4053 parallelIo.defineArray(PIO_FLOAT, "partPos", 3 * ncmpiPartCountMax);
4054
4055 // Define Dimension partVel [3 * ncmpiPartCountMax] & Define Variable
4056 // partVel (double) [partVel].
4057 parallelIo.defineArray(PIO_FLOAT, "partVel", 3 * ncmpiPartCountMax);
4058
4059 // Define Dimension partDia [ncmpiPartCountMax] & Define Variable partDia
4060 // (double) [partDia].
4061 parallelIo.defineArray(PIO_FLOAT, "partDia", ncmpiPartCountMax);
4062
4064 parallelIo.defineArray(PIO_INT, "partParceledNo", ncmpiPartCountMax);
4065 }
4066
4068 parallelIo.defineArray(PIO_FLOAT, "partTemp", ncmpiPartCountMax);
4069 }
4070
4071 if(m_domainIdOutput) {
4072 parallelIo.defineArray(PIO_INT, "domainId", ncmpiPartCountMax);
4073 }
4074
4075 parallelIo.setOffset(1, domainId());
4076 parallelIo.writeArray(&ncmpiPartQueueSize, "partCount");
4077
4078 // Create arrays to hold the particle datas.
4079 ParallelIo::size_type ncmpiStart = 0;
4080 ParallelIo::size_type ncmpiCount = ncmpiPartCount[domainId()];
4081
4082 if(ncmpiPartCount[domainId()] > 0) {
4083 for(MInt i = 0; i < domainId(); i++) {
4084 ncmpiStart += ncmpiPartCount[i];
4085 }
4086 }
4087
4088 ASSERT(ncmpiStart + ncmpiPartCount[domainId()] <= ncmpiPartCountMax,
4089 "ERROR: Invalid number of particles " + to_string(ncmpiStart + ncmpiPartCount[domainId()]) + " > "
4090 + to_string(ncmpiPartCountMax));
4091
4092 ASSERT(ncmpiStart + ncmpiPartCount[domainId()] <= ncmpiPartCountMax,
4093 "ERROR: Invalid number of particles " + to_string(ncmpiStart + ncmpiPartCount[domainId()]) + " > "
4094 + to_string(ncmpiPartCountMax));
4095
4096 MLongScratchSpace ncmpiPartId(ncmpiPartCount[domainId()], AT_, "ncmpiPartId");
4097 MIntScratchSpace ncmpiPartParceledNo(ncmpiPartCount[domainId()], AT_, "ncmpiPartParceledNo");
4098 MFloatScratchSpace ncmpiDiameter(ncmpiPartCount[domainId()], AT_, "ncmpiDiameter");
4099 MFloatScratchSpace ncmpiTemp(ncmpiPartCount[domainId()], AT_, "ncmpiTemp");
4100 MFloatScratchSpace ncmpiPartCoords(3 * ncmpiPartCount[domainId()], AT_, "ncmpiPartCoords");
4101 // MFloatScratchSpace ncmpiPartCoordsM(3 * ncmpiPartCount[domainId()], AT_,
4102 // "ncmpiPartCoordsM");
4103 MFloatScratchSpace ncmpiPartVel(3 * ncmpiPartCount[domainId()], AT_, "ncmpiPartVel");
4104 MInt ncmpiCountId = 0;
4105
4106 // Put all particle data in arrays.
4107 while(!ncmpiPartQueue.empty()) {
4108 ncmpiPartId[ncmpiCountId] = (*(ncmpiPartQueue.front())).m_partId;
4109 ncmpiPartParceledNo[ncmpiCountId] = (*(ncmpiPartQueue.front())).m_noParticles;
4110 ncmpiDiameter[ncmpiCountId] = (*(ncmpiPartQueue.front())).m_diameter;
4111 ncmpiTemp[ncmpiCountId] = (*(ncmpiPartQueue.front())).m_temperature;
4112 ncmpiPartCoords[(3 * ncmpiCountId)] = (*(ncmpiPartQueue.front())).m_position[0];
4113 ncmpiPartCoords[(3 * ncmpiCountId) + 1] = (*(ncmpiPartQueue.front())).m_position[1];
4114 ncmpiPartCoords[(3 * ncmpiCountId) + 2] = (*(ncmpiPartQueue.front())).m_position[2];
4115 ncmpiPartVel[(3 * ncmpiCountId)] = (*(ncmpiPartQueue.front())).m_velocity[0];
4116 ncmpiPartVel[(3 * ncmpiCountId) + 1] = (*(ncmpiPartQueue.front())).m_velocity[1];
4117 ncmpiPartVel[(3 * ncmpiCountId) + 2] = (*(ncmpiPartQueue.front())).m_velocity[2];
4118
4119 ncmpiPartQueue.pop();
4120 ++ncmpiCountId;
4121 }
4122
4123 // Put the arrays in the Netcdf file.
4124 parallelIo.setOffset(ncmpiCount, ncmpiStart);
4125 parallelIo.writeArray(ncmpiPartId.begin(), "partId");
4126 parallelIo.writeArray(ncmpiDiameter.begin(), "partDia");
4127
4129 parallelIo.writeArray(ncmpiPartParceledNo.begin(), "partParceledNo");
4130 }
4131
4133 parallelIo.writeArray(ncmpiTemp.begin(), "partTemp");
4134 }
4135 if(m_domainIdOutput) {
4136 MFloatScratchSpace ncmpiDomain(ncmpiPartCount[domainId()], AT_, "ncmpiDomain");
4137 ncmpiDomain.fill(domainId());
4138 parallelIo.writeArray(ncmpiDomain.begin(), "domainId");
4139 }
4140
4141 ncmpiCount *= 3;
4142 ParallelIo::size_type ncmpi3Start = 3 * ncmpiStart;
4143 parallelIo.setOffset(ncmpiCount, ncmpi3Start);
4144 parallelIo.writeArray(ncmpiPartCoords.begin(), "partPos");
4145 parallelIo.writeArray(ncmpiPartVel.begin(), "partVel");
4146
4147 if(domainId() == 0) {
4148 cerr << "Writing particle solution file at time step " << globalTimeStep << endl;
4149 }
4150
4151 } else {
4152 if(domainId() == 0) {
4153 m_log << "WARNING: Write called but no particles present!" << endl;
4154 cerr << "WARNING: Write called but no particles present!" << endl;
4155 }
4156 }
4157 if(m_ellipsoids) {
4158 // Make ncmpiPartQueue, Queue of "Real" Particle and ncmpiPartQueueSize (MInt),
4159 // size of the queue.
4160 queue<ellipsListIterator<nDim>> ncmpiEllipsoidQueue;
4161 ncmpiPartQueueSize = 0;
4162
4163 auto i2 = m_partListEllipsoid.begin();
4164 while(i2 != m_partListEllipsoid.end()) {
4165 if(!(*i2).isInvalid() && ((*i2).m_position[0] > m_xCutOff)) {
4166 ++ncmpiPartQueueSize;
4167 ncmpiEllipsoidQueue.push(i2);
4168 }
4169 i2++;
4170 }
4171
4172 // Get Variable partCount[noDomains()]
4173 MIntScratchSpace ncmpiEllipsoidCount(noDomains(), AT_, "ncmpiEllipsoidCount");
4174 MPI_Allgather(&ncmpiPartQueueSize, 1, MPI_INT, &ncmpiEllipsoidCount[0], 1, MPI_INT, mpiComm(), AT_,
4175 "ncmpiPartQueueSize", "ncmpiEllipsoidCount");
4176
4177 // Calculate ncmpiPartCountMax
4178 ncmpiPartCountMax = 0;
4179 for(MInt i = 0; i < noDomains(); ++i) {
4180 ncmpiPartCountMax += ncmpiEllipsoidCount[i];
4181 }
4182
4183 // If there are 0 particle in the whole domain, don't write particle data.
4184 if(ncmpiPartCountMax != 0) {
4185 const MString ncmpiFileName =
4186 outputDir() + "partEllipsoid_" + getIdentifier() + to_string(globalTimeStep) + ParallelIo::fileExt();
4187
4188 using namespace maia::parallel_io;
4189 ParallelIo parallelIo(ncmpiFileName, PIO_REPLACE, mpiComm());
4190
4191 // Define Attribute timestep (double).
4192 parallelIo.setAttribute(globalTimeStep + 1, "globalTimestep");
4193 parallelIo.setAttribute(globalTimeStep, "particleTimestep");
4194 parallelIo.setAttribute(m_time, "time");
4195
4196 parallelIo.defineArray(PIO_INT, "partCount", noDomains());
4197 parallelIo.defineArray(PIO_LONG, "partId", ncmpiPartCountMax);
4198 parallelIo.defineArray(PIO_FLOAT, "partSemiMinorAxis", ncmpiPartCountMax);
4199 parallelIo.defineArray(PIO_FLOAT, "partAspectRatio", ncmpiPartCountMax);
4200 parallelIo.defineArray(PIO_FLOAT, "partDia", ncmpiPartCountMax);
4201 parallelIo.defineArray(PIO_FLOAT, "partDensityRatio", ncmpiPartCountMax);
4202 parallelIo.defineArray(PIO_FLOAT, "partPos", 3 * ncmpiPartCountMax);
4203 parallelIo.defineArray(PIO_FLOAT, "partVel", 3 * ncmpiPartCountMax);
4204 parallelIo.defineArray(PIO_FLOAT, "partAngVel", 3 * ncmpiPartCountMax);
4205 parallelIo.defineArray(PIO_FLOAT, "partMajorAxis", 3 * ncmpiPartCountMax);
4206 parallelIo.defineArray(PIO_FLOAT, "partQuat", 4 * ncmpiPartCountMax);
4207 // EndDef (Go into data mode).
4208
4209 ParallelIo::size_type ncmpiStart = domainId();
4210 ParallelIo::size_type ncmpiCount = 1;
4211
4212 parallelIo.setOffset(ncmpiCount, ncmpiStart);
4213
4214 // Put Variable partCount = ncmpiPartQueueSize at Position MPI_Rank
4215 parallelIo.writeArray(&ncmpiPartQueueSize, "partCount");
4216
4217 // Create arrays to hold the particle data.
4218 ncmpiStart = 0;
4219
4220 for(MInt i = 0; i < domainId(); ++i) {
4221 ncmpiStart += ncmpiEllipsoidCount[i];
4222 }
4223 ncmpiCount = ncmpiEllipsoidCount[domainId()];
4224 if(ncmpiStart >= ncmpiPartCountMax) {
4225 if(ncmpiCount == 0) {
4226 ncmpiStart = 0;
4227 } else {
4228 mTerm(1, AT_, "Error in m_ellipsoids ncmpiStart >= ncmpiPartCountMax but ncmpiCount != 0");
4229 }
4230 }
4231
4232 MLongScratchSpace ncmpiPartId(ncmpiPartCountMax, AT_, "ncmpiEllipsId");
4233 MFloatScratchSpace ncmpiSemiMinorAxis(ncmpiPartCountMax, AT_, "ncmpiSemiMinorAxis");
4234 MFloatScratchSpace ncmpiAspectRatio(ncmpiPartCountMax, AT_, "ncmpiAspectRatio");
4235 MFloatScratchSpace ncmpiEqDia(ncmpiPartCountMax, AT_, "ncmpiEquivalentDiameter");
4236 MFloatScratchSpace ncmpiDensityRatio(ncmpiPartCountMax, AT_, "ncmpiDensityRatio");
4237 MFloatScratchSpace ncmpiPartCoords(3 * ncmpiPartCountMax, AT_, "ncmpiCoords");
4238 MFloatScratchSpace ncmpiPartVel(3 * ncmpiPartCountMax, AT_, "ncmpiEllipsVel");
4239 MFloatScratchSpace ncmpiPartAngVel(3 * ncmpiPartCountMax, AT_, "ncmpiEllipsAngVel");
4240 MFloatScratchSpace ncmpiPartMajorAxis(3 * ncmpiPartCountMax, AT_, "ncmpiEllipsMajorAxis");
4241 MFloatScratchSpace ncmpiPartQuat(4 * ncmpiPartCountMax, AT_, "ncmpiEllipsQuat");
4242 MInt ncmpiCountId = 0;
4243
4244 // Put all particle data in arrays.
4245 while(!ncmpiEllipsoidQueue.empty()) {
4246 LPTEllipsoidal<nDim>& particle = *ncmpiEllipsoidQueue.front();
4247 ncmpiPartId[ncmpiCountId] = particle.m_partId;
4248 ncmpiSemiMinorAxis[ncmpiCountId] = particle.m_semiMinorAxis;
4249 ncmpiAspectRatio[ncmpiCountId] = particle.m_aspectRatio;
4250 ncmpiEqDia[ncmpiCountId] = particle.equivalentDiameter();
4251 ncmpiDensityRatio[ncmpiCountId] = particle.m_densityRatio;
4252 std::array<MFloat, nDim> majorAxis{};
4253 particle.calculateMajorAxisOrientation(majorAxis.begin());
4254 for(MInt n = 0; n < nDim; n++) {
4255 ncmpiPartCoords[(3 * ncmpiCountId) + n] = particle.m_position[n];
4256 ncmpiPartVel[(3 * ncmpiCountId) + n] = particle.m_velocity[n];
4257 ncmpiPartAngVel[(3 * ncmpiCountId) + n] = particle.m_angularVel[n];
4258 ncmpiPartMajorAxis[(3 * ncmpiCountId) + n] = majorAxis[n];
4259 }
4260 for(MInt n = 0; n < 4; n++) {
4261 ncmpiPartQuat[(4 * ncmpiCountId) + n] = particle.m_quaternion[n];
4262 }
4263
4264 ncmpiEllipsoidQueue.pop();
4265 ++ncmpiCountId;
4266 }
4267
4268 // Put the arrays in the Netcdf file.
4269 parallelIo.setOffset(ncmpiCount, ncmpiStart);
4270 parallelIo.writeArray(&ncmpiPartId[0], "partId");
4271 parallelIo.writeArray(&ncmpiSemiMinorAxis[0], "partSemiMinorAxis");
4272 parallelIo.writeArray(&ncmpiAspectRatio[0], "partAspectRatio");
4273 parallelIo.writeArray(&ncmpiEqDia[0], "partDia");
4274 parallelIo.writeArray(&ncmpiDensityRatio[0], "partDensityRatio");
4275
4276 ncmpiCount *= 3;
4277 ParallelIo::size_type ncmpi3Start = 3 * ncmpiStart;
4278 parallelIo.setOffset(ncmpiCount, ncmpi3Start);
4279 parallelIo.writeArray(&ncmpiPartCoords[0], "partPos");
4280 parallelIo.writeArray(&ncmpiPartVel[0], "partVel");
4281 parallelIo.writeArray(&ncmpiPartAngVel[0], "partAngVel");
4282 parallelIo.writeArray(&ncmpiPartMajorAxis[0], "partMajorAxis");
4283
4284 ParallelIo::size_type ncmpi4Start = 4 * ncmpiStart;
4285 ncmpiCount /= 3;
4286 ncmpiCount *= 4;
4287 parallelIo.setOffset(ncmpiCount, ncmpi4Start);
4288 parallelIo.writeArray(&ncmpiPartQuat[0], "partQuat");
4289
4290 // Free Memory
4291 while(!ncmpiEllipsoidQueue.empty()) {
4292 ncmpiEllipsoidQueue.pop();
4293 }
4294 }
4295 }
4296}
void calculateMajorAxisOrientation(MFloat *majorAxis)
Calculate the orientation of the major axis in the world coordinate system.
MFloat equivalentDiameter() const
Returns the equivalent diameter.
MFloat m_xCutOff
Definition: lpt.h:765
MBool m_domainIdOutput
Definition: lpt.h:543

◆ writeParticleLog()

template<MInt nDim>
void LPT< nDim >::writeParticleLog ( )
private

◆ writeParticleRestartFile()

template<MInt nDim>
void LPT< nDim >::writeParticleRestartFile
Author
Jerry Grimmen, Sven Berger

Definition at line 4304 of file lpt.cpp.

4304 {
4305 TRACE();
4306
4307 // if(grid().hasInactiveRanks()) {
4308 grid().updatePartitionCellOffsets();
4309 //}
4310
4311 m_log << "Writing LPT restart file..." << endl;
4312
4313 // Write a collective Netcdf restart file.
4314 // First, create a new collective Netcdf file. (Leaves file open and in define mode).
4315 MInt noParticles = 0;
4316 for(MInt id = 0; id < a_noParticles(); id++) {
4317 if(m_partList[id].isInvalid()) {
4318 cerr << "Invalid particle when writing restart-file!" << endl;
4319 continue;
4320 }
4321 noParticles++;
4322 }
4323 MIntScratchSpace ncmpiPartCount(noDomains(), AT_, "ncmpiPartCount");
4324 const MInt noLocalPartitionCells =
4325 grid().localPartitionCellOffsetsRestart(1) - grid().localPartitionCellOffsetsRestart(0);
4326 const MInt noGlobalPartitionCells = grid().localPartitionCellOffsetsRestart(2);
4327
4328 MIntScratchSpace noParticlesPerLocalPartitionCell(noLocalPartitionCells, AT_, "noParticlesPerLocalPartitionCell");
4329 noParticlesPerLocalPartitionCell.fill(0);
4330
4331 MPI_Allgather(&noParticles, 1, MPI_INT, &ncmpiPartCount[0], 1, MPI_INT, mpiComm(), AT_, "noParticles",
4332 "ncmpiPartCount");
4333
4334 // Calculate global number of particles
4335 ParallelIo::size_type globalNoParticles = 0;
4336 for(MInt i = 0; i < noDomains(); ++i) {
4337 globalNoParticles += ncmpiPartCount[i];
4338 }
4339
4340 if(domainId() == 0) {
4341 cerr << "Write Particle Restart at Time step " << globalTimeStep << endl;
4342 cerr << "for number of particles: " << globalNoParticles << " and " << noGlobalPartitionCells << " partition cells!"
4343 << endl;
4344 }
4345
4346 m_log << "Time step " << globalTimeStep << " -- this proc. has " << noParticles << " particles of "
4347 << globalNoParticles << endl;
4348
4349
4350 ParallelIo::size_type ncmpiStart = grid().localPartitionCellOffsetsRestart(0);
4351 ParallelIo::size_type ncmpiCount = noLocalPartitionCells;
4352
4353 auto sortByGId = [&](const LPTBase<nDim>& i, const LPTBase<nDim>& j) {
4354 const MLong globalId1 = c_globalId(i.m_cellId);
4355 const MLong globalId2 = c_globalId(j.m_cellId);
4356 if(globalId1 != globalId2) {
4357 return (c_globalId(i.m_cellId) < c_globalId(j.m_cellId));
4358 } else {
4359 return (i.m_partId < j.m_partId);
4360 }
4361 };
4362
4363 if(a_noParticles() > 0) {
4364 own_sort(m_partList, sortByGId);
4365
4366 MInt localPartitionCellCounter = 0;
4367 for(auto i1 = m_partList.begin(); i1 != m_partList.end(); i1++) {
4368 MLong particleGlobalCellId = c_globalId(i1->m_cellId);
4369 if(i1->isInvalid()) continue;
4370 if(a_isHalo(i1->m_cellId)) {
4371 cerr << "Particle in halo-cell!" << endl;
4372 cerr << i1->hadWallColl() << " " << i1->isInvalid() << " " << i1->reqSend() << " " << i1->m_partId << endl;
4373 MInt cellId2 = grid().findContainingLeafCell(&i1->m_position[0]);
4374 MInt cellId3 = grid().findContainingLeafCell(&i1->m_position[0], i1->m_cellId, true);
4375 cerr << i1->m_cellId << " " << cellId2 << " " << cellId3 << endl;
4376 }
4377 if((localPartitionCellCounter + 1 < noLocalPartitionCells)) {
4378 ASSERT(grid().localPartitionCellGlobalIdsRestart(localPartitionCellCounter + 1) > -1, "");
4379 while(particleGlobalCellId >= grid().localPartitionCellGlobalIdsRestart(localPartitionCellCounter + 1)) {
4380 localPartitionCellCounter++;
4381 if(localPartitionCellCounter + 1 >= noLocalPartitionCells) {
4382 break;
4383 }
4384 }
4385 }
4386 noParticlesPerLocalPartitionCell[localPartitionCellCounter] += 1;
4387 }
4388 }
4389
4390 MString ncmpiFileName =
4391 outputDir() + "restartPart_" + getIdentifier() + to_string(globalTimeStep) + ParallelIo::fileExt();
4392
4393 using namespace maia::parallel_io;
4394 ParallelIo parallelIo(ncmpiFileName, PIO_REPLACE, mpiComm());
4395
4396 parallelIo.setAttribute(globalTimeStep, "timestep");
4397 parallelIo.setAttribute(globalTimeStep, "particleTimestep");
4399 MInt globalInjStep = m_sprayModel->m_injStep;
4400 MPI_Allreduce(MPI_IN_PLACE, &globalInjStep, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "globalInjStep");
4401 parallelIo.setAttribute(globalInjStep, "injStep");
4402
4403 MFloat globalTimeSOI = m_sprayModel->timeSinceSOI();
4404 MPI_Allreduce(MPI_IN_PLACE, &globalTimeSOI, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "INPLACE", "globalTimeSOI");
4405 parallelIo.setAttribute(globalTimeSOI, "timeSinceSOI");
4406 }
4407 parallelIo.setAttribute(m_time, "time");
4408
4409 // count the number of times random numbers were drawn for predictable restart
4410 MInt count = m_PRNGSpawnCount;
4411 MFloat particleResiduum = 0;
4412
4414 count = m_sprayModel->m_PRNGPrimBreakUpCount;
4415 particleResiduum = std::numeric_limits<MFloat>::max();
4416 }
4417
4418 if(m_spawnParticles) {
4419 particleResiduum = std::numeric_limits<MFloat>::max();
4420 }
4421
4422 if(domainId() != m_spawnDomainId) {
4423 ASSERT(count == 0, "");
4424 } else {
4425#ifndef NDEBUG
4426 // re-compute the number of times the PRNG has been used!
4427 mt19937_64 PRNG;
4428 MInt j = 0;
4429 if(m_spawnParticles) {
4430 PRNG.seed(m_spawnSeed);
4431 } else if(m_sprayModel) {
4432 PRNG.seed(m_sprayModel->m_spraySeed);
4433 }
4434 const MInt maxCount = 1000000000;
4435 for(MInt i = 0; i < maxCount; i++) {
4437 break;
4438 } else if((m_activePrimaryBUp || m_activeSecondaryBUp) && PRNG == m_sprayModel->m_PRNGPrimBreakUp) {
4439 break;
4440 }
4441 j++;
4442 PRNG();
4443 }
4444 if(j < maxCount) {
4445 ASSERT(m_PRNGSpawnCount == j
4446 || ((m_activePrimaryBUp || m_activeSecondaryBUp) && j == m_sprayModel->m_PRNGPrimBreakUpCount),
4447 "");
4448 } else {
4449 cerr << "PRNG-state could not be checked" << endl;
4450 }
4451#endif
4452 }
4453 if(m_spawnCellId > -1) {
4454 particleResiduum = m_particleResiduum;
4455 }
4456
4457 MPI_Allreduce(MPI_IN_PLACE, &count, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "INPLACE", "count");
4458 MPI_Allreduce(MPI_IN_PLACE, &particleResiduum, 1, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "INPLACE", "particleResiduum");
4459
4460 parallelIo.setAttribute(count, "spawnCount");
4461 parallelIo.setAttribute(particleResiduum, "particleResiduum");
4462
4463 parallelIo.defineArray(PIO_INT, "partCount", noGlobalPartitionCells);
4464
4465 if(globalNoParticles > 0) {
4466 parallelIo.defineArray(PIO_LONG, "partId", globalNoParticles);
4467 parallelIo.defineArray(PIO_FLOAT, "partDia", globalNoParticles);
4468 parallelIo.defineArray(PIO_INT, "partStatus", globalNoParticles);
4469 parallelIo.defineArray(PIO_FLOAT, "partPos", 3 * globalNoParticles);
4470 parallelIo.defineArray(PIO_FLOAT, "partVel", 3 * globalNoParticles);
4471 parallelIo.defineArray(PIO_FLOAT, "partAccel", 3 * globalNoParticles);
4472 parallelIo.defineArray(PIO_FLOAT, "oldPos", 3 * globalNoParticles);
4473 parallelIo.defineArray(PIO_FLOAT, "oldVel", 3 * globalNoParticles);
4474 parallelIo.defineArray(PIO_FLOAT, "oldAccel", 3 * globalNoParticles);
4475 parallelIo.defineArray(PIO_INT, "partParceledNo", globalNoParticles);
4476 parallelIo.defineArray(PIO_FLOAT, "creationTime", globalNoParticles);
4477 parallelIo.defineArray(PIO_FLOAT, "oldFluidVelocity", 3 * globalNoParticles);
4478 parallelIo.defineArray(PIO_FLOAT, "oldFluidDensity", globalNoParticles);
4480 parallelIo.defineArray(PIO_FLOAT, "breakUpTime", globalNoParticles);
4481 }
4483 parallelIo.defineArray(PIO_FLOAT, "partTemp", globalNoParticles);
4484 parallelIo.defineArray(PIO_FLOAT, "partDM", globalNoParticles);
4485 }
4487 parallelIo.defineArray(PIO_FLOAT, "shedD", globalNoParticles);
4488 }
4489 }
4490
4491 // Put Variable partCount = ncmpiPartQueueSize at Position MPI_Rank
4492 parallelIo.setOffset(ncmpiCount, ncmpiStart);
4493 parallelIo.writeArray(&noParticlesPerLocalPartitionCell[0], "partCount");
4494
4495 // Write particle data.
4496 ncmpiStart = 0;
4497 for(MInt i = 0; i < domainId(); ++i) {
4498 ncmpiStart += ncmpiPartCount[i];
4499 }
4500 ncmpiCount = ncmpiPartCount[domainId()];
4501 if(ncmpiStart >= globalNoParticles) {
4502 if(ncmpiCount == 0) {
4503 ncmpiStart = 0;
4504 } else {
4505 mTerm(1, AT_, "Error ncmpiStart >= globalNoParticles but ncmpiCount != 0");
4506 }
4507 }
4508 ASSERT(ncmpiCount == a_noParticles(), "");
4509
4510 if(globalNoParticles > 0) {
4511 MLongScratchSpace ncmpiPartId(ncmpiCount, AT_, "ncmpiPartId");
4512 MFloatScratchSpace ncmpiDiameter(ncmpiCount, AT_, "ncmpiDiameter");
4513 MFloatScratchSpace ncmpiDensityRatio(ncmpiCount, AT_, "ncmpiDensityRatio");
4514 MIntScratchSpace ncmpiPartStatus(ncmpiCount, AT_, "ncmpiPartStatus");
4515 MFloatScratchSpace ncmpiPartCoords(3 * ncmpiCount, AT_, "PartCoords");
4516 MFloatScratchSpace ncmpiPartVel(3 * ncmpiCount, AT_, "ncmpiPartVel");
4517 MFloatScratchSpace ncmpiPartAccel(3 * ncmpiCount, AT_, "ncmpiPartAccel");
4518 MFloatScratchSpace ncmpiOldCoords(3 * ncmpiCount, AT_, "ncmpiOldCoords");
4519 MFloatScratchSpace ncmpiOldVel(3 * ncmpiCount, AT_, "ncmpiOldVel");
4520 MFloatScratchSpace ncmpiOldAccel(3 * ncmpiCount, AT_, "ncmpiOldAccel");
4521 MIntScratchSpace ncmpiPartParceledNo(ncmpiCount, AT_, "ncmpiPartParceledNo");
4522 MFloatScratchSpace ncmpiTemp(ncmpiCount, AT_, "ncmpiTemp");
4523 MFloatScratchSpace ncmpiDM(ncmpiCount, AT_, "ncmpiDM");
4524 MFloatScratchSpace ncmpiCT(ncmpiCount, AT_, "ncmpiCT");
4525 MFloatScratchSpace ncmpiBT(ncmpiCount, AT_, "ncmpiBT");
4526 MFloatScratchSpace ncmpiOldFluidDensity(ncmpiCount, AT_, "ncmpiOldFluidDensity");
4527 MFloatScratchSpace ncmpiOldFluidVelocity(3 * ncmpiCount, AT_, "ncmpiOldFluidVelocity");
4528 MFloatScratchSpace ncmpishedD(ncmpiCount, AT_, "ncmpishedD");
4529
4530 MInt id = 0;
4531
4532 for(MInt i = 0; i < a_noParticles(); i++) {
4533 if(m_partList[i].isInvalid()) continue;
4534 ncmpiPartId[id] = m_partList[i].m_partId;
4535 ncmpiDiameter[id] = m_partList[i].m_diameter;
4536 ncmpiDensityRatio[id] = m_partList[i].m_densityRatio;
4537 ncmpiPartStatus[id] = (m_partList[i].firstStep() ? 1 : 0);
4538 ncmpiPartCoords[(3 * id)] = m_partList[i].m_position[0];
4539 ncmpiPartCoords[(3 * id) + 1] = m_partList[i].m_position[1];
4540 ncmpiPartCoords[(3 * id) + 2] = m_partList[i].m_position[2];
4541 ncmpiPartVel[(3 * id)] = m_partList[i].m_velocity[0];
4542 ncmpiPartVel[(3 * id) + 1] = m_partList[i].m_velocity[1];
4543 ncmpiPartVel[(3 * id) + 2] = m_partList[i].m_velocity[2];
4544 ncmpiPartAccel[(3 * id)] = m_partList[i].m_accel[0];
4545 ncmpiPartAccel[(3 * id) + 1] = m_partList[i].m_accel[1];
4546 ncmpiPartAccel[(3 * id) + 2] = m_partList[i].m_accel[2];
4547 ncmpiOldCoords[(3 * id)] = m_partList[i].m_oldPos[0];
4548 ncmpiOldCoords[(3 * id) + 1] = m_partList[i].m_oldPos[1];
4549 ncmpiOldCoords[(3 * id) + 2] = m_partList[i].m_oldPos[2];
4550 ncmpiOldVel[(3 * id)] = m_partList[i].m_oldVel[0];
4551 ncmpiOldVel[(3 * id) + 1] = m_partList[i].m_oldVel[1];
4552 ncmpiOldVel[(3 * id) + 2] = m_partList[i].m_oldVel[2];
4553 ncmpiOldAccel[(3 * id)] = m_partList[i].m_oldAccel[0];
4554 ncmpiOldAccel[(3 * id) + 1] = m_partList[i].m_oldAccel[1];
4555 ncmpiOldAccel[(3 * id) + 2] = m_partList[i].m_oldAccel[2];
4556 ncmpiPartParceledNo[id] = m_partList[i].m_noParticles;
4557 ncmpiTemp[id] = m_partList[i].m_temperature;
4558 ncmpiDM[id] = m_partList[i].m_dM;
4559 ncmpiCT[id] = 0.0; // m_partList[i].m_creationTime;
4560 ncmpiBT[id] = m_partList[i].m_breakUpTime;
4562 ncmpishedD[id] = m_partList[i].m_shedDiam;
4563 }
4564
4565 ncmpiOldFluidDensity[id] = m_partList[i].m_oldFluidDensity;
4566 ncmpiOldFluidVelocity[(3 * id)] = m_partList[i].m_oldFluidVel[0];
4567 ncmpiOldFluidVelocity[(3 * id) + 1] = m_partList[i].m_oldFluidVel[1];
4568 ncmpiOldFluidVelocity[(3 * id) + 2] = m_partList[i].m_oldFluidVel[2];
4569
4570 id = id + 1;
4571 }
4572
4573 parallelIo.setOffset(ncmpiCount, ncmpiStart);
4574
4575 parallelIo.writeArray(ncmpiPartId.begin(), "partId");
4576 parallelIo.writeArray(ncmpiDiameter.begin(), "partDia");
4577 parallelIo.writeArray(ncmpiPartStatus.begin(), "partStatus");
4578 parallelIo.writeArray(ncmpiPartParceledNo.begin(), "partParceledNo");
4579 parallelIo.writeArray(ncmpiCT.begin(), "creationTime");
4580
4582 parallelIo.writeArray(ncmpiBT.begin(), "breakUpTime");
4583 }
4584
4586 parallelIo.writeArray(ncmpiTemp.begin(), "partTemp");
4587 parallelIo.writeArray(ncmpiDM.begin(), "partDM");
4588 }
4589
4591 parallelIo.writeArray(ncmpishedD.begin(), "shedD");
4592 }
4593
4594 parallelIo.writeArray(ncmpiOldFluidDensity.begin(), "oldFluidDensity");
4595
4596 ncmpiCount *= 3;
4597 ParallelIo::size_type ncmpi3Start = 3 * ncmpiStart;
4598 parallelIo.setOffset(ncmpiCount, ncmpi3Start);
4599 parallelIo.writeArray(ncmpiPartCoords.begin(), "partPos");
4600 parallelIo.writeArray(ncmpiPartVel.begin(), "partVel");
4601 parallelIo.writeArray(ncmpiPartAccel.begin(), "partAccel");
4602 parallelIo.writeArray(ncmpiOldCoords.begin(), "oldPos");
4603 parallelIo.writeArray(ncmpiOldVel.begin(), "oldVel");
4604 parallelIo.writeArray(ncmpiOldAccel.begin(), "oldAccel");
4605 parallelIo.writeArray(ncmpiOldFluidVelocity.begin(), "oldFluidVelocity");
4606 }
4607 // recover original sorting
4609
4610 if(m_ellipsoids) {
4611 MInt noEllipsoids = 0;
4612 for(MInt id = 0; id < a_noEllipsoidalParticles(); id++) {
4613 if(m_partListEllipsoid[id].isInvalid()) {
4614 cerr << "Invalid particle when writing restart-file!" << endl;
4615 continue;
4616 }
4617 noEllipsoids++;
4618 }
4619
4620 MIntScratchSpace noEllipsoidsPerLocalPartitionCell(noLocalPartitionCells, AT_, "noEllipsoidsPerLocalPartitionCell");
4621 noEllipsoidsPerLocalPartitionCell.fill(0);
4622 MIntScratchSpace ncmpiEllipsoidCount(noDomains(), AT_, "ncmpiEllipsoidCount");
4623 MPI_Allgather(&noEllipsoids, 1, MPI_INT, &ncmpiEllipsoidCount[0], 1, MPI_INT, mpiComm(), AT_, "noEllipsoids",
4624 "ncmpiEllipsoidCount");
4625
4626 // Calculate global no ellipsoids
4627 ParallelIo::size_type globalNoEllipsoids = 0;
4628 for(MInt i = 0; i < noDomains(); ++i) {
4629 globalNoEllipsoids += ncmpiEllipsoidCount[i];
4630 }
4631
4632 m_log << "Time step " << globalTimeStep << " -- this proc. has " << noEllipsoids << " ellipsoids of "
4633 << globalNoEllipsoids << endl;
4634 if(domainId() == 0) {
4635 cerr << "Write Ellipsoid Restart at Time step " << globalTimeStep << endl;
4636 cerr << "for number of ellipsoids: " << globalNoEllipsoids << " and " << noGlobalPartitionCells
4637 << " partition cells!" << endl;
4638 }
4639
4640 ncmpiStart = grid().localPartitionCellOffsetsRestart(0);
4641 ncmpiCount = noLocalPartitionCells;
4642
4643 // If there are 0 particle in the whole domain, don't write particle data.
4644 if(a_noEllipsoidalParticles() > 0) {
4645 own_sort(m_partListEllipsoid, sortByGId);
4646
4647 MInt localPartitionCellCounter = 0;
4648 for(auto i1 = m_partListEllipsoid.begin(); i1 != m_partListEllipsoid.end(); i1++) {
4649 MLong particleGlobalCellId = c_globalId(i1->m_cellId);
4650 if(i1->isInvalid()) continue;
4651 if(a_isHalo(i1->m_cellId)) {
4652 cerr << "Particle in halo-cell!" << endl;
4653 cerr << i1->hadWallColl() << " " << i1->isInvalid() << " " << i1->reqSend() << " " << i1->m_partId << endl;
4654 MInt cellId2 = grid().findContainingLeafCell(&i1->m_position[0]);
4655 MInt cellId3 = grid().findContainingLeafCell(&i1->m_position[0], i1->m_cellId, true);
4656 cerr << i1->m_cellId << " " << cellId2 << " " << cellId3 << endl;
4657 }
4658 if((localPartitionCellCounter + 1 < noLocalPartitionCells)) {
4659 ASSERT(grid().localPartitionCellGlobalIdsRestart(localPartitionCellCounter + 1) > -1, "");
4660 while(particleGlobalCellId >= grid().localPartitionCellGlobalIdsRestart(localPartitionCellCounter + 1)) {
4661 localPartitionCellCounter++;
4662 if(localPartitionCellCounter + 1 >= noLocalPartitionCells) {
4663 break;
4664 }
4665 }
4666 }
4667 noEllipsoidsPerLocalPartitionCell[localPartitionCellCounter] += 1;
4668 }
4669 }
4670
4671 ncmpiFileName =
4672 outputDir() + "restartPartEllipsoid_" + getIdentifier() + to_string(globalTimeStep) + ParallelIo::fileExt();
4673
4674 ParallelIo parallelIoE(ncmpiFileName, PIO_REPLACE, mpiComm());
4675
4676 // Define Attribute timestep (double).
4677 parallelIoE.setAttribute(globalTimeStep, "timestep");
4678 parallelIoE.setAttribute(globalTimeStep, "particleTimestep");
4679 parallelIoE.defineArray(PIO_INT, "partCount", noGlobalPartitionCells);
4680
4681
4682 if(globalNoEllipsoids > 0) {
4683 parallelIoE.defineArray(PIO_LONG, "partId", globalNoEllipsoids);
4684 parallelIoE.defineArray(PIO_FLOAT, "partSemiMinorAxis", globalNoEllipsoids);
4685 parallelIoE.defineArray(PIO_FLOAT, "partDia", globalNoEllipsoids);
4686 parallelIoE.defineArray(PIO_FLOAT, "partAspectRatio", globalNoEllipsoids);
4687 parallelIoE.defineArray(PIO_FLOAT, "partDensityRatio", globalNoEllipsoids);
4688 parallelIoE.defineArray(PIO_INT, "partStatus", globalNoEllipsoids);
4689 parallelIoE.defineArray(PIO_FLOAT, "partPos", 3 * globalNoEllipsoids);
4690 parallelIoE.defineArray(PIO_FLOAT, "partVel", 3 * globalNoEllipsoids);
4691 parallelIoE.defineArray(PIO_FLOAT, "partAccel", 3 * globalNoEllipsoids);
4692 parallelIoE.defineArray(PIO_FLOAT, "partAngVel", 3 * globalNoEllipsoids);
4693 parallelIoE.defineArray(PIO_FLOAT, "partAngAccel", 3 * globalNoEllipsoids);
4694 parallelIoE.defineArray(PIO_FLOAT, "partOldPos", 3 * globalNoEllipsoids);
4695 parallelIoE.defineArray(PIO_FLOAT, "partOldVel", 3 * globalNoEllipsoids);
4696 parallelIoE.defineArray(PIO_FLOAT, "partOldAccel", 3 * globalNoEllipsoids);
4697 parallelIoE.defineArray(PIO_FLOAT, "partOldAngVel", 3 * globalNoEllipsoids);
4698 parallelIoE.defineArray(PIO_FLOAT, "partOldAngAccel", 3 * globalNoEllipsoids);
4699 parallelIoE.defineArray(PIO_FLOAT, "partQuat", 4 * globalNoEllipsoids);
4700 parallelIoE.defineArray(PIO_FLOAT, "partOldQuat", 4 * globalNoEllipsoids);
4701 parallelIoE.defineArray(PIO_FLOAT, "creationTime", globalNoEllipsoids);
4702 parallelIoE.defineArray(PIO_FLOAT, "oldFluidVelocity", 3 * globalNoEllipsoids);
4703 parallelIoE.defineArray(PIO_FLOAT, "oldFluidDensity", globalNoEllipsoids);
4704 if(m_heatCoupling) parallelIoE.defineArray(PIO_FLOAT, "partTemp", globalNoEllipsoids);
4705 // EndDef (Go into data mode).
4706
4707 // Put Variable partCount = ncmpiPartQueueSize at Position MPI_Rank
4708 parallelIoE.setOffset(ncmpiCount, ncmpiStart);
4709 parallelIoE.writeArray(&noEllipsoidsPerLocalPartitionCell[0], "partCount");
4710
4711 // Write particle data.
4712 ncmpiStart = 0;
4713 for(MInt i = 0; i < domainId(); ++i) {
4714 ncmpiStart += ncmpiEllipsoidCount[i];
4715 }
4716 ncmpiCount = ncmpiEllipsoidCount[domainId()];
4717 if(ncmpiStart >= globalNoEllipsoids) {
4718 if(ncmpiCount == 0) {
4719 ncmpiStart = 0;
4720 } else {
4721 mTerm(1, AT_, "m_ellipsoids ncmpiStart >= globalNoEllipsoids but ncmpiCount != 0");
4722 }
4723 }
4724 ASSERT(ncmpiCount == a_noEllipsoidalParticles(), "");
4725
4726 MLongScratchSpace ncmpiPartId(ncmpiCount, AT_, "ncmpiPartIdE");
4727 MFloatScratchSpace ncmpiSemiMinorAxis(ncmpiCount, AT_, "ncmpiSemiMinorAxis");
4728 MFloatScratchSpace ncmpiEquivalentDia(ncmpiCount, AT_, "ncmpiEquivalentDia");
4729 MFloatScratchSpace ncmpiAspectRatio(ncmpiCount, AT_, "ncmpiAspectRatio");
4730 MFloatScratchSpace ncmpiDensityRatio(ncmpiCount, AT_, "ncmpiDensityRatio");
4731 MIntScratchSpace ncmpiPartStatus(ncmpiCount, AT_, "ncmpiPartStatus");
4732 MFloatScratchSpace ncmpiPartCoords(3 * ncmpiCount, AT_, "ncmpiPartCoords");
4733 MFloatScratchSpace ncmpiPartVel(3 * ncmpiCount, AT_, "ncmpiPartVel");
4734 MFloatScratchSpace ncmpiPartAccel(3 * ncmpiCount, AT_, "ncmpiPartAccel");
4735 MFloatScratchSpace ncmpiPartAngVel(3 * ncmpiCount, AT_, "ncmpiPartAngVel");
4736 MFloatScratchSpace ncmpiPartAngAccel(3 * ncmpiCount, AT_, "ncmpiPartAngAccel");
4737 MFloatScratchSpace ncmpiPartOldCoords(3 * ncmpiCount, AT_, "ncmpiPartOldCoords");
4738 MFloatScratchSpace ncmpiPartOldVel(3 * ncmpiCount, AT_, "ncmpiPartOldVel");
4739 MFloatScratchSpace ncmpiPartOldAccel(3 * ncmpiCount, AT_, "ncmpiPartOldAccel");
4740 MFloatScratchSpace ncmpiPartOldAngVel(3 * ncmpiCount, AT_, "ncmpiPartOldAngVel");
4741 MFloatScratchSpace ncmpiPartOldAngAccel(3 * ncmpiCount, AT_, "ncmpiPartOldAngAccel");
4742 MFloatScratchSpace ncmpiPartQuat(4 * ncmpiCount, AT_, "ncmpiPartQuaternion");
4743 MFloatScratchSpace ncmpiPartOldQuat(4 * ncmpiCount, AT_, "ncmpiPartOldQuaternion");
4744 MFloatScratchSpace ncmpiTemp(ncmpiCount, AT_, "ncmpiTemp");
4745 MFloatScratchSpace ncmpiCT(ncmpiCount, AT_, "ncmpiCT");
4746 MFloatScratchSpace ncmpiOldFluidDensity(ncmpiCount, AT_, "ncmpiOldFluidDensity");
4747 MFloatScratchSpace ncmpiOldFluidVelocity(3 * ncmpiCount, AT_, "ncmpiOldFluidVelocity");
4748
4749 for(MInt i = 0; i < a_noEllipsoidalParticles(); i++) {
4750 if(m_partListEllipsoid[i].isInvalid()) continue;
4751 ncmpiPartId[i] = m_partListEllipsoid[i].m_partId;
4752 ncmpiSemiMinorAxis[i] = m_partListEllipsoid[i].m_semiMinorAxis;
4753 ncmpiEquivalentDia[i] = m_partListEllipsoid[i].equivalentDiameter();
4754 ncmpiAspectRatio[i] = m_partListEllipsoid[i].m_aspectRatio;
4755 ncmpiDensityRatio[i] = m_partListEllipsoid[i].m_densityRatio;
4756 ncmpiPartStatus[i] = (m_partListEllipsoid[i].firstStep() ? 1 : 0);
4757 for(MInt n = 0; n < nDim; n++) {
4758 ncmpiPartCoords[(3 * i) + n] = m_partListEllipsoid[i].m_position[n];
4759 ncmpiPartVel[(3 * i) + n] = m_partListEllipsoid[i].m_velocity[n];
4760 ncmpiPartAccel[(3 * i) + n] = m_partListEllipsoid[i].m_accel[n];
4761 ncmpiPartAngVel[(3 * i) + n] = m_partListEllipsoid[i].m_angularVel[n];
4762 ncmpiPartAngAccel[(3 * i) + n] = m_partListEllipsoid[i].m_angularAccel[n];
4763 ncmpiPartOldCoords[(3 * i) + n] = m_partListEllipsoid[i].m_oldPos[n];
4764 ncmpiPartOldVel[(3 * i) + n] = m_partListEllipsoid[i].m_oldVel[n];
4765 ncmpiPartOldAccel[(3 * i) + n] = m_partListEllipsoid[i].m_oldAccel[n];
4766 ncmpiPartOldAngVel[(3 * i) + n] = m_partListEllipsoid[i].m_oldAngularVel[n];
4767 ncmpiPartOldAngAccel[(3 * i) + n] = m_partListEllipsoid[i].m_oldAngularAccel[n];
4768 ncmpiOldFluidVelocity[(3 * i) + n] = m_partListEllipsoid[i].m_oldFluidVel[n];
4769 }
4770 for(MInt n = 0; n < 4; n++) {
4771 ncmpiPartQuat[(4 * i) + n] = m_partListEllipsoid[i].m_quaternion[n];
4772 ncmpiPartOldQuat[(4 * i) + n] = m_partListEllipsoid[i].m_oldQuaternion[n];
4773 }
4774 ncmpiOldFluidDensity[i] = m_partListEllipsoid[i].m_oldFluidDensity;
4775 ncmpiTemp[i] = m_partListEllipsoid[i].m_temperature;
4776 ncmpiCT[i] = m_partListEllipsoid[i].m_creationTime;
4777 }
4778
4779 parallelIoE.setOffset(ncmpiCount, ncmpiStart);
4780 parallelIoE.writeArray(ncmpiPartId.begin(), "partId");
4781 parallelIoE.writeArray(ncmpiSemiMinorAxis.begin(), "partSemiMinorAxis");
4782 parallelIoE.writeArray(ncmpiEquivalentDia.begin(), "partDia");
4783 parallelIoE.writeArray(ncmpiAspectRatio.begin(), "partAspectRatio");
4784 parallelIoE.writeArray(ncmpiDensityRatio.begin(), "partDensityRatio");
4785 parallelIoE.writeArray(ncmpiPartStatus.begin(), "partStatus");
4786 parallelIoE.writeArray(ncmpiCT.begin(), "creationTime");
4787 parallelIoE.writeArray(ncmpiOldFluidDensity.begin(), "oldFluidDensity");
4788 if(m_heatCoupling) parallelIoE.writeArray(ncmpiTemp.begin(), "partTemp");
4789
4790 ncmpiCount *= 3;
4791 ParallelIo::size_type ncmpi3Start = 3 * ncmpiStart;
4792 parallelIoE.setOffset(ncmpiCount, ncmpi3Start);
4793 parallelIoE.writeArray(ncmpiPartCoords.begin(), "partPos");
4794 parallelIoE.writeArray(ncmpiPartVel.begin(), "partVel");
4795 parallelIoE.writeArray(ncmpiPartAccel.begin(), "partAccel");
4796 parallelIoE.writeArray(ncmpiPartAngVel.begin(), "partAngVel");
4797 parallelIoE.writeArray(ncmpiPartAngAccel.begin(), "partAngAccel");
4798 parallelIoE.writeArray(ncmpiPartOldCoords.begin(), "partOldPos");
4799 parallelIoE.writeArray(ncmpiPartOldVel.begin(), "partOldVel");
4800 parallelIoE.writeArray(ncmpiPartOldAccel.begin(), "partOldAccel");
4801 parallelIoE.writeArray(ncmpiPartOldAngVel.begin(), "partOldAngVel");
4802 parallelIoE.writeArray(ncmpiPartOldAngAccel.begin(), "partOldAngAccel");
4803
4804 ParallelIo::size_type ncmpi4Start = 4 * ncmpiStart;
4805 ncmpiCount /= 3;
4806 ncmpiCount *= 4;
4807 parallelIoE.setOffset(ncmpiCount, ncmpi4Start);
4808 parallelIoE.writeArray(ncmpiPartQuat.begin(), "partQuat");
4809 parallelIoE.writeArray(ncmpiPartOldQuat.begin(), "partOldQuat");
4810 }
4812 }
4813}
MInt globalNoParticles()
Definition: lpt.h:494
MInt globalNoEllipsoids()
Definition: lpt.h:501

◆ writeRestartFile() [1/2]

template<MInt nDim>
void LPT< nDim >::writeRestartFile ( const MBool  writeRestart,
const  MBool,
const MString  gridFileName,
MInt recalcIdTree 
)
overridevirtual
Date
January-2021
Author
Tim Wegmann

Reimplemented from Solver.

Definition at line 2578 of file lpt.cpp.

2579 {
2580 if(writeRestart) {
2582
2583 writeCellSolutionFile(gridFileName, &recalcIdTree[0]);
2584
2585 // write the particle based restart-file
2587 }
2588}

◆ writeRestartFile() [2/2]

template<MInt nDim>
void LPT< nDim >::writeRestartFile ( MBool  )
inlineoverridevirtual

Reimplemented from Solver.

Definition at line 251 of file lpt.h.

251{};

Friends And Related Function Documentation

◆ CouplerFvParticle

template<MInt nDim>
template<MInt nDim_, class SysEqn >
friend class CouplerFvParticle
friend

Definition at line 99 of file lpt.h.

◆ CouplingParticle

template<MInt nDim>
template<MInt nDim_>
friend class CouplingParticle
friend

Definition at line 96 of file lpt.h.

◆ LbLpt

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

Definition at line 102 of file lpt.h.

◆ LPTBase

template<MInt nDim>
template<MInt nDim_>
friend class LPTBase
friend

Definition at line 84 of file lpt.h.

◆ LPTEllipsoidal

template<MInt nDim>
template<MInt nDim_>
friend class LPTEllipsoidal
friend

Definition at line 90 of file lpt.h.

◆ LPTSpherical

template<MInt nDim>
template<MInt nDim_>
friend class LPTSpherical
friend

Definition at line 87 of file lpt.h.

◆ MaterialState

template<MInt nDim>
template<MInt nDim_>
friend class MaterialState
friend

Definition at line 117 of file lpt.h.

◆ ParticleCollision

template<MInt nDim>
template<MInt nDim_>
friend class ParticleCollision
friend

Definition at line 114 of file lpt.h.

◆ PostProcessingFvLPT

template<MInt nDim>
template<MInt nDim_, class SysEqn >
friend class PostProcessingFvLPT
friend

Definition at line 105 of file lpt.h.

◆ PostProcessingLbLPT

template<MInt nDim>
template<MInt nDim_>
friend class PostProcessingLbLPT
friend

Definition at line 108 of file lpt.h.

◆ PostProcessingLPT

template<MInt nDim>
template<MInt nDim_>
friend class PostProcessingLPT
friend

Definition at line 111 of file lpt.h.

◆ SprayModel

template<MInt nDim>
template<MInt nDim_>
friend class SprayModel
friend

Definition at line 93 of file lpt.h.

Member Data Documentation

◆ m_activePrimaryBUp

template<MInt nDim>
MBool LPT< nDim >::m_activePrimaryBUp {}
private

Definition at line 760 of file lpt.h.

◆ m_activeSecondaryBUp

template<MInt nDim>
MBool LPT< nDim >::m_activeSecondaryBUp {}
private

Definition at line 761 of file lpt.h.

◆ m_adaptationLevel

template<MInt nDim>
MInt LPT< nDim >::m_adaptationLevel = 0
private

Definition at line 822 of file lpt.h.

◆ m_addedParticle

template<MInt nDim>
MLong LPT< nDim >::m_addedParticle = 0
private

Definition at line 817 of file lpt.h.

◆ m_addInjDataCnt

template<MInt nDim>
constexpr MInt LPT< nDim >::m_addInjDataCnt = 4
staticconstexprprivate

Definition at line 799 of file lpt.h.

◆ m_bndryCells

template<MInt nDim>
Collector<LPTBndryCell<nDim> >* LPT< nDim >::m_bndryCells = nullptr

Definition at line 180 of file lpt.h.

◆ m_cells

template<MInt nDim>
LptCellCollector LPT< nDim >::m_cells

Definition at line 175 of file lpt.h.

◆ m_cellToEllipsMap

template<MInt nDim>
std::multimap<MInt, LPTEllipsoidal<nDim>*> LPT< nDim >::m_cellToEllipsMap
private

Definition at line 820 of file lpt.h.

◆ m_cellToNghbrHood

template<MInt nDim>
std::map<MInt, std::vector<MInt> > LPT< nDim >::m_cellToNghbrHood
protected

Definition at line 530 of file lpt.h.

◆ m_cellToNghbrHoodInterpolation

template<MInt nDim>
std::map<MInt, std::vector<MInt> > LPT< nDim >::m_cellToNghbrHoodInterpolation
protected

Definition at line 531 of file lpt.h.

◆ m_cellToPartMap

template<MInt nDim>
std::multimap<MInt, LPTSpherical<nDim>*> LPT< nDim >::m_cellToPartMap
private

Definition at line 819 of file lpt.h.

◆ m_cfl

template<MInt nDim>
MFloat LPT< nDim >::m_cfl = 1.0
private

Definition at line 796 of file lpt.h.

◆ m_checkAdaptationRecv

template<MInt nDim>
std::vector<MInt> LPT< nDim >::m_checkAdaptationRecv {}
protected

Definition at line 588 of file lpt.h.

◆ m_checkAdaptationRecvRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_checkAdaptationRecvRequest = nullptr
protected

Definition at line 586 of file lpt.h.

◆ m_checkAdaptationSend

template<MInt nDim>
std::vector<MInt> LPT< nDim >::m_checkAdaptationSend {}
protected

Definition at line 589 of file lpt.h.

◆ m_checkAdaptationSendRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_checkAdaptationSendRequest = nullptr
protected

Definition at line 587 of file lpt.h.

◆ m_collisionModel

template<MInt nDim>
std::unique_ptr<ParticleCollision<nDim> > LPT< nDim >::m_collisionModel

Definition at line 195 of file lpt.h.

◆ m_collisions

template<MInt nDim>
MInt LPT< nDim >::m_collisions = 0
private

Definition at line 791 of file lpt.h.

◆ m_couplingRedist

template<MInt nDim>
MBool LPT< nDim >::m_couplingRedist = false
protected

Definition at line 632 of file lpt.h.

◆ m_domainIdOutput

template<MInt nDim>
MBool LPT< nDim >::m_domainIdOutput = false
protected

Definition at line 543 of file lpt.h.

◆ m_dragModelType

template<MInt nDim>
MInt LPT< nDim >::m_dragModelType = 1
private

Definition at line 775 of file lpt.h.

◆ m_ellipsoidRandomOrientation

template<MInt nDim>
MInt LPT< nDim >::m_ellipsoidRandomOrientation = 1
private

Definition at line 770 of file lpt.h.

◆ m_ellipsoidRandomOrientationSeed

template<MInt nDim>
MLong LPT< nDim >::m_ellipsoidRandomOrientationSeed {}
private

Definition at line 771 of file lpt.h.

◆ m_ellipsoids

template<MInt nDim>
MBool LPT< nDim >::m_ellipsoids = false
private

Definition at line 769 of file lpt.h.

◆ m_engineSetup

template<MInt nDim>
MBool LPT< nDim >::m_engineSetup = false
private

Definition at line 754 of file lpt.h.

◆ m_evaporation

template<MInt nDim>
MBool LPT< nDim >::m_evaporation = false
protected

Definition at line 638 of file lpt.h.

◆ m_exchangeBufferSize

template<MInt nDim>
MInt LPT< nDim >::m_exchangeBufferSize = 1000
private

Definition at line 794 of file lpt.h.

◆ m_flowRecv

template<MInt nDim>
MFloat** LPT< nDim >::m_flowRecv = nullptr
protected

Definition at line 593 of file lpt.h.

◆ m_flowRecvRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_flowRecvRequest = nullptr
protected

Definition at line 592 of file lpt.h.

◆ m_flowSend

template<MInt nDim>
MFloat** LPT< nDim >::m_flowSend = nullptr
protected

Definition at line 594 of file lpt.h.

◆ m_flowSendRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_flowSendRequest = nullptr
protected

Definition at line 591 of file lpt.h.

◆ m_forceAdaptation

template<MInt nDim>
MBool LPT< nDim >::m_forceAdaptation = false
private

Definition at line 829 of file lpt.h.

◆ m_FrMag

template<MInt nDim>
MFloat LPT< nDim >::m_FrMag = 0.0
private

Definition at line 774 of file lpt.h.

◆ m_geometry

template<MInt nDim>
Geom* LPT< nDim >::m_geometry

Definition at line 173 of file lpt.h.

◆ m_globBbox

template<MInt nDim>
std::array<MFloat, nDim * 2> LPT< nDim >::m_globBbox {0}
private

Definition at line 756 of file lpt.h.

◆ m_globDomainLength

template<MInt nDim>
std::array<MFloat, nDim> LPT< nDim >::m_globDomainLength {}
private

Definition at line 755 of file lpt.h.

◆ m_heatCoupling

template<MInt nDim>
MBool LPT< nDim >::m_heatCoupling = false
protected

Definition at line 636 of file lpt.h.

◆ m_initializationMethod

template<MInt nDim>
MInt LPT< nDim >::m_initializationMethod = 0
private

Definition at line 773 of file lpt.h.

◆ m_injData

template<MInt nDim>
std::map<MInt, std::vector<MFloat> > LPT< nDim >::m_injData

Definition at line 491 of file lpt.h.

◆ m_innerBound

template<MInt nDim>
MInt LPT< nDim >::m_innerBound = 2
private

Definition at line 828 of file lpt.h.

◆ m_intRecvBuffer

template<MInt nDim>
std::vector<std::unique_ptr<MInt[]> > LPT< nDim >::m_intRecvBuffer {}
protected

Definition at line 613 of file lpt.h.

◆ m_intSendBuffer

template<MInt nDim>
std::vector<std::unique_ptr<MInt[]> > LPT< nDim >::m_intSendBuffer {}
protected

Definition at line 612 of file lpt.h.

◆ m_liftModelType

template<MInt nDim>
MInt LPT< nDim >::m_liftModelType = 0
private

Definition at line 776 of file lpt.h.

◆ m_limitWeights

template<MInt nDim>
MBool LPT< nDim >::m_limitWeights = false
protected

Definition at line 552 of file lpt.h.

◆ m_loadBalancingReinitStage

template<MInt nDim>
MInt LPT< nDim >::m_loadBalancingReinitStage = -1
private

Definition at line 825 of file lpt.h.

◆ m_massCoupling

template<MInt nDim>
MBool LPT< nDim >::m_massCoupling = false
protected

Definition at line 637 of file lpt.h.

◆ m_material

template<MInt nDim>
std::unique_ptr<MaterialState<nDim> > LPT< nDim >::m_material
private

Definition at line 815 of file lpt.h.

◆ m_maxNoBndryCells

template<MInt nDim>
MInt LPT< nDim >::m_maxNoBndryCells = 0
private

Definition at line 790 of file lpt.h.

◆ m_maxNoParticles

template<MInt nDim>
MInt LPT< nDim >::m_maxNoParticles {}
private

Definition at line 763 of file lpt.h.

◆ m_momentumCoupling

template<MInt nDim>
MBool LPT< nDim >::m_momentumCoupling = false
protected

Definition at line 635 of file lpt.h.

◆ m_motionEquationType

template<MInt nDim>
MInt LPT< nDim >::m_motionEquationType = 0
private

Definition at line 778 of file lpt.h.

◆ m_mpi_reqRecvFloat

template<MInt nDim>
std::vector<MPI_Request> LPT< nDim >::m_mpi_reqRecvFloat {}
protected

Definition at line 607 of file lpt.h.

◆ m_mpi_reqRecvInt

template<MInt nDim>
std::vector<MPI_Request> LPT< nDim >::m_mpi_reqRecvInt {}
protected

Definition at line 608 of file lpt.h.

◆ m_mpi_reqSendFloat

template<MInt nDim>
std::vector<MPI_Request> LPT< nDim >::m_mpi_reqSendFloat {}
protected

Definition at line 604 of file lpt.h.

◆ m_mpi_reqSendInt

template<MInt nDim>
std::vector<MPI_Request> LPT< nDim >::m_mpi_reqSendInt {}
protected

Definition at line 605 of file lpt.h.

◆ m_mpi_reqSendSize

template<MInt nDim>
std::vector<MPI_Request> LPT< nDim >::m_mpi_reqSendSize {}
protected

Definition at line 606 of file lpt.h.

◆ m_mpi_statusFloat

template<MInt nDim>
MPI_Status LPT< nDim >::m_mpi_statusFloat {}
protected

Definition at line 622 of file lpt.h.

◆ m_mpi_statusInt

template<MInt nDim>
MPI_Status LPT< nDim >::m_mpi_statusInt {}
protected

Definition at line 621 of file lpt.h.

◆ m_mpi_statusProbe

template<MInt nDim>
std::vector<MPI_Status> LPT< nDim >::m_mpi_statusProbe {}
protected

Definition at line 609 of file lpt.h.

◆ m_nonBlockingComm

template<MInt nDim>
MBool LPT< nDim >::m_nonBlockingComm = false
protected

Definition at line 614 of file lpt.h.

◆ m_nonBlockingStage

template<MInt nDim>
MInt LPT< nDim >::m_nonBlockingStage = -1
protected

Definition at line 615 of file lpt.h.

◆ m_nonDimensional

template<MInt nDim>
MBool LPT< nDim >::m_nonDimensional = false

Definition at line 946 of file lpt.h.

◆ m_noOuterBndryCells

template<MInt nDim>
MInt LPT< nDim >::m_noOuterBndryCells = 0
private

Definition at line 792 of file lpt.h.

◆ m_noRedistLayer

template<MInt nDim>
MInt LPT< nDim >::m_noRedistLayer = 1
protected

Definition at line 633 of file lpt.h.

◆ m_noRespawnDomains

template<MInt nDim>
MInt LPT< nDim >::m_noRespawnDomains {}
private

Definition at line 784 of file lpt.h.

◆ m_noSendParticles

template<MInt nDim>
MInt LPT< nDim >::m_noSendParticles = 0
protected

Definition at line 619 of file lpt.h.

◆ m_noSolutionSteps

template<MInt nDim>
MInt LPT< nDim >::m_noSolutionSteps = 1

Definition at line 948 of file lpt.h.

◆ m_noSourceTerms

template<MInt nDim>
MInt LPT< nDim >::m_noSourceTerms = 0
protected

Definition at line 580 of file lpt.h.

◆ m_openFlowSend

template<MInt nDim>
MBool LPT< nDim >::m_openFlowSend = false
protected

Definition at line 628 of file lpt.h.

◆ m_openParticleInjSend

template<MInt nDim>
MBool LPT< nDim >::m_openParticleInjSend = false
protected

Definition at line 624 of file lpt.h.

◆ m_openParticleSend

template<MInt nDim>
MBool LPT< nDim >::m_openParticleSend = false
protected

Definition at line 625 of file lpt.h.

◆ m_openRegridSend

template<MInt nDim>
MBool LPT< nDim >::m_openRegridSend = false
protected

Definition at line 629 of file lpt.h.

◆ m_openSlopesSend

template<MInt nDim>
MBool LPT< nDim >::m_openSlopesSend = false
protected

Definition at line 630 of file lpt.h.

◆ m_openSourceSend

template<MInt nDim>
MBool LPT< nDim >::m_openSourceSend = false
protected

Definition at line 627 of file lpt.h.

◆ m_particleResiduum

template<MInt nDim>
MFloat LPT< nDim >::m_particleResiduum = 0.0
protected

Definition at line 642 of file lpt.h.

◆ m_partList

template<MInt nDim>
std::vector<LPTSpherical<nDim> > LPT< nDim >::m_partList
protected

Definition at line 527 of file lpt.h.

◆ m_partListEllipsoid

template<MInt nDim>
std::vector<LPTEllipsoidal<nDim> > LPT< nDim >::m_partListEllipsoid
protected

Definition at line 528 of file lpt.h.

◆ m_periodicBC

template<MInt nDim>
MBool LPT< nDim >::m_periodicBC = false
private

Definition at line 753 of file lpt.h.

◆ m_pointsToHalo

template<MInt nDim>
std::vector<std::map<MInt, MInt> > LPT< nDim >::m_pointsToHalo
protected

Definition at line 568 of file lpt.h.

◆ m_pointsToWindow

template<MInt nDim>
std::vector<std::map<MInt, MInt> > LPT< nDim >::m_pointsToWindow
protected

Definition at line 569 of file lpt.h.

◆ m_primaryExchange

template<MInt nDim>
MBool LPT< nDim >::m_primaryExchange = false
protected

Definition at line 579 of file lpt.h.

◆ m_PRNGInit

template<MInt nDim>
std::mt19937_64 LPT< nDim >::m_PRNGInit
protected

Definition at line 564 of file lpt.h.

◆ m_PRNGRespawn

template<MInt nDim>
std::mt19937_64 LPT< nDim >::m_PRNGRespawn
protected

Definition at line 561 of file lpt.h.

◆ m_PRNGSpawn

template<MInt nDim>
std::mt19937_64 LPT< nDim >::m_PRNGSpawn
protected

Definition at line 558 of file lpt.h.

◆ m_PRNGSpawnCount

template<MInt nDim>
MInt LPT< nDim >::m_PRNGSpawnCount = 0
protected

Definition at line 559 of file lpt.h.

◆ m_queueToSend

template<MInt nDim>
particleSendQueue<nDim> LPT< nDim >::m_queueToSend
protected

Definition at line 566 of file lpt.h.

◆ m_receiveFlowField

template<MInt nDim>
MBool LPT< nDim >::m_receiveFlowField = false
protected

Definition at line 616 of file lpt.h.

◆ m_receiveVelocitySlopes

template<MInt nDim>
MBool LPT< nDim >::m_receiveVelocitySlopes = false
protected

Definition at line 617 of file lpt.h.

◆ m_recvBuffer

template<MInt nDim>
std::vector<std::unique_ptr<MFloat[]> > LPT< nDim >::m_recvBuffer {}
protected

Definition at line 611 of file lpt.h.

◆ m_recvSize

template<MInt nDim>
std::vector<MInt> LPT< nDim >::m_recvSize {}
protected

Definition at line 602 of file lpt.h.

◆ m_respawn

template<MInt nDim>
MBool LPT< nDim >::m_respawn = false
private

Definition at line 781 of file lpt.h.

◆ m_respawnCells

template<MInt nDim>
std::vector<MInt> LPT< nDim >::m_respawnCells
private

Definition at line 787 of file lpt.h.

◆ m_respawnDomain

template<MInt nDim>
MInt LPT< nDim >::m_respawnDomain {}
private

Definition at line 783 of file lpt.h.

◆ m_respawnDomainRanks

template<MInt nDim>
MInt* LPT< nDim >::m_respawnDomainRanks {}
private

Definition at line 785 of file lpt.h.

◆ m_respawnGlobalDomainOffsets

template<MInt nDim>
MInt* LPT< nDim >::m_respawnGlobalDomainOffsets {}
private

Definition at line 786 of file lpt.h.

◆ m_respawnPlane

template<MInt nDim>
MFloat LPT< nDim >::m_respawnPlane {}
private

Definition at line 782 of file lpt.h.

◆ m_restart

template<MInt nDim>
MBool LPT< nDim >::m_restart = false
private

Definition at line 767 of file lpt.h.

◆ m_restartTimeStep

template<MInt nDim>
MInt LPT< nDim >::m_restartTimeStep {}

Definition at line 950 of file lpt.h.

◆ m_sendBuffer

template<MInt nDim>
std::vector<std::unique_ptr<MFloat[]> > LPT< nDim >::m_sendBuffer {}
protected

Definition at line 610 of file lpt.h.

◆ m_sendSize

template<MInt nDim>
std::vector<MInt> LPT< nDim >::m_sendSize {}
protected

Definition at line 601 of file lpt.h.

◆ m_shadowWidth

template<MInt nDim>
MInt LPT< nDim >::m_shadowWidth {}
private

Definition at line 827 of file lpt.h.

◆ m_sizeLimit

template<MInt nDim>
MFloat LPT< nDim >::m_sizeLimit {}
private

Definition at line 758 of file lpt.h.

◆ m_skewnessTimeStep

template<MInt nDim>
MInt LPT< nDim >::m_skewnessTimeStep = -1
private

Definition at line 751 of file lpt.h.

◆ m_skipLPT

template<MInt nDim>
MBool LPT< nDim >::m_skipLPT = false
protected

Definition at line 541 of file lpt.h.

◆ m_sleepLPT

template<MInt nDim>
MInt LPT< nDim >::m_sleepLPT = -1
protected

Definition at line 540 of file lpt.h.

◆ m_slopesRecv

template<MInt nDim>
MFloat** LPT< nDim >::m_slopesRecv = nullptr
protected

Definition at line 598 of file lpt.h.

◆ m_slopesRecvRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_slopesRecvRequest = nullptr
protected

Definition at line 597 of file lpt.h.

◆ m_slopesSend

template<MInt nDim>
MFloat** LPT< nDim >::m_slopesSend = nullptr
protected

Definition at line 599 of file lpt.h.

◆ m_slopesSendRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_slopesSendRequest = nullptr
protected

Definition at line 596 of file lpt.h.

◆ m_solutionStep

template<MInt nDim>
MInt LPT< nDim >::m_solutionStep = 0

Definition at line 949 of file lpt.h.

◆ m_sourceRecv

template<MInt nDim>
std::vector<std::unique_ptr<MFloat[]> > LPT< nDim >::m_sourceRecv {}
protected

Definition at line 583 of file lpt.h.

◆ m_sourceRecvRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_sourceRecvRequest = nullptr
protected

Definition at line 582 of file lpt.h.

◆ m_sourceSend

template<MInt nDim>
std::vector<std::unique_ptr<MFloat[]> > LPT< nDim >::m_sourceSend {}
protected

Definition at line 584 of file lpt.h.

◆ m_sourceSendRequest

template<MInt nDim>
MPI_Request* LPT< nDim >::m_sourceSendRequest = nullptr
protected

Definition at line 581 of file lpt.h.

◆ m_spawnCellId

template<MInt nDim>
MInt LPT< nDim >::m_spawnCellId = -1
private

Definition at line 803 of file lpt.h.

◆ m_spawnCoord

template<MInt nDim>
MFloat LPT< nDim >::m_spawnCoord[nDim] {}
private

Definition at line 809 of file lpt.h.

◆ m_spawnDiameter

template<MInt nDim>
MFloat LPT< nDim >::m_spawnDiameter = 0.00001
private

Definition at line 807 of file lpt.h.

◆ m_spawnDir

template<MInt nDim>
MFloat LPT< nDim >::m_spawnDir[nDim] {}
private

Definition at line 806 of file lpt.h.

◆ m_spawnDistSigmaCoeff

template<MInt nDim>
MFloat LPT< nDim >::m_spawnDistSigmaCoeff = 1.0
private

Definition at line 812 of file lpt.h.

◆ m_spawnDomainId

template<MInt nDim>
MInt LPT< nDim >::m_spawnDomainId = -1
private

Definition at line 804 of file lpt.h.

◆ m_spawnEmittDist

template<MInt nDim>
MInt LPT< nDim >::m_spawnEmittDist = string2enum("PART_EMITT_DIST_UNIFORM")
private

Definition at line 811 of file lpt.h.

◆ m_spawnParticles

template<MInt nDim>
MBool LPT< nDim >::m_spawnParticles = false
private

Definition at line 802 of file lpt.h.

◆ m_spawnParticlesConeAngle

template<MInt nDim>
MFloat LPT< nDim >::m_spawnParticlesConeAngle = 0.0
private

Definition at line 805 of file lpt.h.

◆ m_spawnParticlesCount

template<MInt nDim>
MInt LPT< nDim >::m_spawnParticlesCount = 1
private

Definition at line 808 of file lpt.h.

◆ m_spawnSeed

template<MInt nDim>
MLong LPT< nDim >::m_spawnSeed {}
private

Definition at line 759 of file lpt.h.

◆ m_spawnVelocity

template<MInt nDim>
MFloat LPT< nDim >::m_spawnVelocity = 0.0
private

Definition at line 810 of file lpt.h.

◆ m_sprayAngleModel

template<MInt nDim>
MInt LPT< nDim >::m_sprayAngleModel = 0
private

Definition at line 813 of file lpt.h.

◆ m_sprayModel

template<MInt nDim>
std::unique_ptr<SprayModel<nDim> > LPT< nDim >::m_sprayModel
private

Definition at line 798 of file lpt.h.

◆ m_sumEvapMass

template<MInt nDim>
MFloat LPT< nDim >::m_sumEvapMass = 0
protected

Definition at line 640 of file lpt.h.

◆ m_sutherlandConstant

template<MInt nDim>
MFloat LPT< nDim >::m_sutherlandConstant = -1

Definition at line 937 of file lpt.h.

◆ m_sutherlandPlusOne

template<MInt nDim>
MFloat LPT< nDim >::m_sutherlandPlusOne = -1

Definition at line 938 of file lpt.h.

◆ m_terminalVelocity

template<MInt nDim>
std::map<MFloat, MFloat> LPT< nDim >::m_terminalVelocity
protected

Definition at line 571 of file lpt.h.

◆ m_time

template<MInt nDim>
MFloat LPT< nDim >::m_time = 0.0
protected

Definition at line 555 of file lpt.h.

◆ m_timerGroup

template<MInt nDim>
MInt LPT< nDim >::m_timerGroup = -1
protected

Definition at line 536 of file lpt.h.

◆ m_timers

template<MInt nDim>
std::array<MInt, Timers::_count> LPT< nDim >::m_timers {}
protected

Definition at line 538 of file lpt.h.

◆ m_timeStep

template<MInt nDim>
MFloat LPT< nDim >::m_timeStep {}
protected

Definition at line 573 of file lpt.h.

◆ m_timeStepComputationInterval

template<MInt nDim>
MInt LPT< nDim >::m_timeStepComputationInterval {}
protected

Definition at line 575 of file lpt.h.

◆ m_timeStepOld

template<MInt nDim>
MFloat LPT< nDim >::m_timeStepOld {}
protected

Definition at line 574 of file lpt.h.

◆ m_timeStepUpdated

template<MInt nDim>
MBool LPT< nDim >::m_timeStepUpdated = true
protected

Definition at line 576 of file lpt.h.

◆ m_torqueModelType

template<MInt nDim>
MInt LPT< nDim >::m_torqueModelType = 0
private

Definition at line 777 of file lpt.h.

◆ m_wallCollisions

template<MInt nDim>
MBool LPT< nDim >::m_wallCollisions = true
private

Definition at line 789 of file lpt.h.

◆ m_weightBaseCell

template<MInt nDim>
MFloat LPT< nDim >::m_weightBaseCell = 0.0
protected

Definition at line 545 of file lpt.h.

◆ m_weightLeafCell

template<MInt nDim>
MFloat LPT< nDim >::m_weightLeafCell = 0.05
protected

Definition at line 546 of file lpt.h.

◆ m_weightMulitSolverFactor

template<MInt nDim>
MFloat LPT< nDim >::m_weightMulitSolverFactor = 1
protected

Definition at line 550 of file lpt.h.

◆ m_weightParticle

template<MInt nDim>
MFloat LPT< nDim >::m_weightParticle = 0.1
protected

Definition at line 548 of file lpt.h.

◆ m_weightParticleCell

template<MInt nDim>
MFloat LPT< nDim >::m_weightParticleCell = 0.1
protected

Definition at line 547 of file lpt.h.

◆ m_weightSourceCells

template<MInt nDim>
MBool LPT< nDim >::m_weightSourceCells = false
protected

Definition at line 553 of file lpt.h.

◆ m_weightSpawnCell

template<MInt nDim>
MFloat LPT< nDim >::m_weightSpawnCell = 5.0
protected

Definition at line 549 of file lpt.h.

◆ m_xCutOff

template<MInt nDim>
MFloat LPT< nDim >::m_xCutOff = -1000.0
private

Definition at line 765 of file lpt.h.

◆ PV

template<MInt nDim>
PrimitiveVariables LPT< nDim >::PV

Definition at line 178 of file lpt.h.


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