13template <MInt nDim,
class SysEqn>
25 const MString propNameLpt =
"solverOrder_" + std::to_string(
lpt().solverId());
26 const MString propNameFv =
"solverOrder_" + std::to_string(
fvSolver().solverId());
29 if(Context::getBasicProperty<MInt>(propNameLpt, AT_, step) > 0) {
32 if(Context::getBasicProperty<MInt>(propNameFv, AT_, step) > 0) {
43 lpt().m_noSolutionSteps = 5;
44 if(
lpt().domainId() == 0) {
45 cerr <<
"Interleafed Fv - LPT execution at step " <<
m_lptSolverOrder << endl;
55template <MInt nDim,
class SysEqn>
64 MInt noInactiveFv = 0;
65 MInt noInactiveLPT = 0;
66 if(!fvSolver().isActive()) {
69 if(!lpt().isActive()) {
73 MPI_Allreduce(MPI_IN_PLACE, &noInactiveFv, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD, AT_,
"MPI_IN_PLACE",
"noInactiveFv");
74 MPI_Allreduce(MPI_IN_PLACE, &noInactiveLPT, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD, AT_,
"MPI_IN_PLACE",
76 if(noInactiveFv > 0) {
77 cerr0 <<
"Fv solver has " << noInactiveFv <<
" inactive ranks!" << endl;
79 if(noInactiveLPT > 0) {
80 cerr0 <<
"LPT solver has " << noInactiveLPT <<
" inactive ranks!" << endl;
91template <MInt nDim,
class SysEqn>
103 lengthFactor = Context::getSolverProperty<MFloat>(
"lengthFactor", lpt().solverId(), AT_, &lengthFactor);
105 MFloat velocityFactor = 1;
113 velocityFactor = Context::getSolverProperty<MFloat>(
"velocityFactor", lpt().solverId(), AT_, &velocityFactor);
115 MFloat viscosityFactor = 1.0;
125 viscosityFactor = Context::getSolverProperty<MFloat>(
"viscosityFactor", lpt().solverId(), AT_, &viscosityFactor);
127 const MFloat particleRe = Context::getSolverProperty<MFloat>(
"Re", lpt().solverId(), AT_);
130 const MFloat ReFactor = fvSolver().sysEqn().m_Re0 / particleRe;
131 MFloat densityFactor = ReFactor * lengthFactor / (velocityFactor * viscosityFactor);
132 MFloat pressureFactor =
POW2(velocityFactor) * densityFactor;
133 MFloat temperatureFactor = sqrt(velocityFactor);
138 if(!lpt().m_nonDimensional) {
139 MFloat specificGasConstant = 287.00283051433;
140 static constexpr MFloat defaultAir = 0.02896;
141 MFloat molarMass = Context::getSolverProperty<MFloat>(
"ambientMolarWeight", lpt().solverId(), AT_, &defaultAir);
143 T0 = Context::getSolverProperty<MFloat>(
"ambientTemperature", lpt().solverId(), AT_, &T0);
146 specificGasConstant =
147 Context::getSolverProperty<MFloat>(
"gasConstant", lpt().solverId(), AT_, &specificGasConstant);
148 specificGasConstant = specificGasConstant / molarMass;
152 if(Context::getSolverProperty<MInt>(
"initialCondition", lpt().solverId(), AT_) != 465) {
153 Tinfty = T0 * fvSolver().sysEqn().temperature_IR(fvSolver().m_Ma);
157 density0 = Context::getSolverProperty<MFloat>(
"ambientDensity", lpt().solverId(), AT_, &density0);
158 MFloat dynamicViscosity0 = 0.00001716 * pow(T0 / 273.15, 1.5) * (273.15 + 110.4) / (T0 + 110.4);
160 Context::getSolverProperty<MFloat>(
"ambientDynViscosity", lpt().solverId(), AT_, &dynamicViscosity0);
163 density0 = fvSolver().sysEqn().m_Re0 * dynamicViscosity0
164 / sqrt(fvSolver().sysEqn().gamma_Ref() * specificGasConstant * T0);
167 const MFloat pressure = density0 * specificGasConstant * Tinfty;
169 velocityFactor = sqrt(fvSolver().sysEqn().gamma_Ref() * specificGasConstant * T0);
170 densityFactor = density0;
171 pressureFactor = pressure * fvSolver().sysEqn().gamma_Ref();
172 temperatureFactor = T0;
173 viscosityFactor = dynamicViscosity0;
175 lpt().m_material->m_temperatureFactor = temperatureFactor;
176 lpt().m_material->m_viscosityFactor = viscosityFactor;
181 conversionFvLpt.velocity = velocityFactor;
182 conversionLptFv.velocity = 1.0 / conversionFvLpt.velocity;
183 conversionFvLpt.density = densityFactor;
184 conversionLptFv.density = 1.0 / conversionFvLpt.density;
185 conversionFvLpt.pressure = pressureFactor;
186 conversionLptFv.pressure = 1.0 / conversionFvLpt.pressure;
187 conversionLptFv.length = lengthFactor;
188 conversionFvLpt.length = 1.0 / conversionLptFv.length;
189 conversionFvLpt.temperature = temperatureFactor;
190 conversionLptFv.temperature = 1 / conversionFvLpt.temperature;
191 conversionFvLpt.viscosity = viscosityFactor;
192 conversionLptFv.viscosity = 1 / conversionFvLpt.viscosity;
194 ASSERT(fabs(lpt().m_sutherlandConstant - fvSolver().m_sutherlandConstant) < MFloatEps,
"");
195 ASSERT(fabs(lpt().m_sutherlandPlusOne - fvSolver().m_sutherlandPlusOne) < MFloatEps,
"");
197 if(lpt().domainId() == 0) {
198 cerr <<
"Fv-Lpt conversion factors are: " << endl;
199 cerr <<
"length : " << conversionFvLpt.length << endl;
200 cerr <<
"velocity : " << conversionFvLpt.velocity << endl;
201 cerr <<
"density : " << conversionFvLpt.density << endl;
202 cerr <<
"pressure : " << conversionFvLpt.pressure << endl;
203 cerr <<
"temperature : " << conversionFvLpt.temperature << endl;
204 cerr <<
"viscosity : " << conversionFvLpt.viscosity << endl;
207 conversionFvLpt.mass = conversionFvLpt.velocity * conversionFvLpt.density *
POW2(conversionFvLpt.length);
208 conversionLptFv.mass = 1 / conversionFvLpt.mass;
209 conversionFvLpt.momentum = conversionFvLpt.density *
POW2(conversionFvLpt.velocity) *
POW2(conversionFvLpt.length);
210 conversionLptFv.momentum = 1 / conversionFvLpt.momentum;
211 conversionFvLpt.energy = conversionFvLpt.density * conversionFvLpt.velocity *
POW2(conversionFvLpt.velocity)
212 *
POW2(conversionFvLpt.length);
213 conversionLptFv.energy = 1 / conversionFvLpt.energy;
215 if(lpt().m_ellipsoids) {
216 conversionFvLpt.velocitySlope = conversionFvLpt.velocity / conversionFvLpt.length;
217 conversionLptFv.velocitySlope = 1 / conversionFvLpt.velocitySlope;
226template <MInt nDim,
class SysEqn>
228 if(!lpt().m_restart) {
230 for(
MInt i = 0; i < lpt().a_noParticles(); i++) {
231 lpt().m_partList[i].initVelocityAndDensity();
234 for(
MInt i = 0; i < lpt().a_noEllipsoidalParticles(); i++) {
235 lpt().m_partListEllipsoid[i].initVelocityAndDensity();
243template <MInt nDim,
class SysEqn>
247 m_fvSolverId = fvSolver().m_solverId;
248 m_lptSolverId = lpt().m_solverId;
254template <MInt nDim,
class SysEqn>
259 transferCellStatus();
261 transferVelocitySlopes();
262 if(lpt().isActive()) {
263 lpt().receiveFlowField();
264 lpt().receiveVelocitySlopes();
265 lpt().waitForSendReqs();
268 initParticleVelocity();
270 if(!lpt().m_restartFile && fvSolver().m_restartFile) {
271 if(lpt().domainId() == 0) {
272 cerr <<
"Restart without LPT restartFile -> setting time from Fv-time!" << endl;
274 const MFloat conversionTime = conversionFvLpt.length / conversionFvLpt.velocity;
275 const MFloat fvTime = fvSolver().m_levelSetMb ? fvSolver().m_physicalTime : fvSolver().m_time;
276 lpt().m_time = fvTime * conversionTime;
280 if(m_forceFvTimeStep) {
286 MBool writeParticleStats =
false;
287 if(writeParticleStats) {
288 writeParticleCellStats();
295template <MInt nDim,
class SysEqn>
299 m_lptFvInterpolation =
300 Context::getSolverProperty<MBool>(
"allowLPTFvInterpolation", m_fvSolverId, AT_, &m_lptFvInterpolation);
312 m_fvLPTSpeciesId = 0;
313 m_fvLPTSpeciesId = Context::getSolverProperty<MInt>(
"fvLptSpeciesId", m_lptSolverId, AT_, &m_fvLPTSpeciesId);
327 m_forceFvTimeStep =
true;
328 m_forceFvTimeStep = Context::getSolverProperty<MBool>(
"forceFvTimeStep", m_lptSolverId, AT_, &m_forceFvTimeStep);
329 if(!m_forceFvTimeStep && !m_interLeafed) {
330 mTerm(1, AT_,
"Coupled timesteps only working with interleafed setup!");
337template <MInt nDim,
class SysEqn>
341 ASSERT(fabs(fvSolver().m_sutherlandConstant - lpt().m_sutherlandConstant) < MFloatEps,
"");
342 ASSERT(fabs(lpt().m_sutherlandPlusOne - fvSolver().m_sutherlandPlusOne) < MFloatEps,
"");
343 ASSERT(lpt().a_timeStepComputationInterval() == fvSolver().a_timeStepComputationInterval(),
"");
349template <MInt nDim,
class SysEqn>
354 if(recipeStep == m_lptSolverOrder) {
360 if(!m_interLeafed) fvSolver().computeConservativeVariables();
364 transferCellStatus();
368 const MFloat conversionTime = conversionFvLpt.length / conversionFvLpt.velocity;
369 const MFloat fvTime = fvSolver().m_levelSetMb ? fvSolver().m_physicalTime : fvSolver().m_time;
370 if(lpt().isActive() && fabs(fvTime * conversionTime - lpt().m_time) > MFloatEps) {
371 cerr <<
"LPT-time " << lpt().m_time <<
" Fv-time " << fvTime << endl;
372 mTerm(1, AT_,
"Miss-matching time!");
381template <MInt nDim,
class SysEqn>
385 if(recipeStep == m_fvSolverOrder) {
386 transferVelocitySlopes();
392 if(recipeStep == m_lptSolverOrder) {
394 if(fvSolver().m_hasExternalSource) {
395 fvSolver().applyExternalOldSource();
396 fvSolver().resetExternalSources();
397 transferExternalSources();
402 if(recipeStep == m_fvSolverOrder) {
404 transferVelocitySlopes();
405 if(lpt().isActive()) {
406 lpt().receiveFlowField();
407 lpt().receiveVelocitySlopes();
408 lpt().waitForSendReqs();
417template <MInt nDim,
class SysEqn>
420 if(
id == lpt().solverId()) {
421 if(fvSolver().m_hasExternalSource) {
422 fvSolver().resetExternalSources();
427 transferExternalSources();
428 fvSolver().advanceExternalSource();
431 }
else if(
id == fvSolver().solverId()) {
432 transferCellStatus();
434 transferVelocitySlopes();
435 if(lpt().isActive()) {
436 lpt().receiveFlowField();
437 lpt().receiveVelocitySlopes();
438 lpt().waitForSendReqs();
451template <MInt nDim,
class SysEqn>
456 MBool diverged =
false;
459 for(
MInt lptCellId = 0; lptCellId < lpt().noInternalCells(); lptCellId++) {
460 if(!lpt().c_isLeafCell(lptCellId))
continue;
461 MInt fvCellId = lpt2fvId(lptCellId);
462 if(fvCellId > -1 && fvSolver().c_isLeafCell(fvCellId)) {
464 for(
MInt n = 0; n < nDim; n++) {
465 lpt().a_fluidVelocity(lptCellId, n) =
466 fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->VV[n]) * conversionFvLpt.velocity;
468 lpt().a_fluidDensity(lptCellId) =
469 fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->RHO) * conversionFvLpt.density;
470 lpt().a_fluidPressure(lptCellId) =
471 fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->P) * conversionFvLpt.pressure;
473 if(std::isnan(lpt().a_fluidPressure(lptCellId)) && lpt().a_isValidCell(lptCellId)) {
475 cerr <<
"Nan pressure " << lpt().a_fluidPressure(lptCellId) <<
" " << lpt().a_coordinate(lptCellId, 0) <<
" "
476 << lpt().a_coordinate(lptCellId, 1) <<
" " << lpt().a_coordinate(lptCellId, nDim - 1) << endl;
480 lpt().a_fluidTemperature(lptCellId) =
481 fvSolver().sysEqn().temperature_ES(fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->RHO),
482 fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->P))
483 * conversionFvLpt.temperature;
484 if(lpt().m_evaporation && fvSolver().m_noSpecies > 0) {
485 lpt().a_fluidSpecies(lptCellId) =
486 mMax(0.0,
mMin(1.0, fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->Y[m_fvLPTSpeciesId])));
489 }
else if(fvCellId > -1 && !fvSolver().c_isLeafCell(fvCellId)) {
491 if(lpt().a_isHalo(lptCellId))
continue;
493 vector<MInt> leafChildIds;
494 fvSolver().grid().getAllLeafChilds(fvCellId, leafChildIds);
495 ASSERT(!leafChildIds.empty(),
"");
498 for(
MInt n = 0; n < nDim; n++) {
499 lpt().a_fluidVelocity(lptCellId, n) = 0;
501 lpt().a_fluidDensity(lptCellId) = 0;
502 lpt().a_fluidPressure(lptCellId) = 0;
503 lpt().a_fluidTemperature(lptCellId) = 0;
504 if(lpt().m_evaporation) {
505 lpt().a_fluidSpecies(lptCellId) = 0;
509 for(
MUint i = 0; i < leafChildIds.size(); i++) {
510 const MInt cellId = leafChildIds[i];
511 if(fvSolver().a_isInactive(cellId))
continue;
512 const MFloat cellVolume = fvSolver().a_cellVolume(cellId);
513 ASSERT(fvSolver().c_isLeafCell(cellId),
"");
515 if(cellVolume < 1e-16) {
516 mTerm(1, AT_,
"Invalid cell-volume!");
518 volume += cellVolume;
519 for(
MInt n = 0; n < nDim; n++) {
520 lpt().a_fluidVelocity(lptCellId, n) +=
521 cellVolume * fvSolver().a_pvariable(cellId, fvSolver().m_sysEqn.PV->VV[n]);
523 lpt().a_fluidDensity(lptCellId) += cellVolume * fvSolver().a_pvariable(cellId, fvSolver().m_sysEqn.PV->RHO);
524 lpt().a_fluidPressure(lptCellId) += cellVolume * fvSolver().a_pvariable(cellId, fvSolver().m_sysEqn.PV->P);
525 lpt().a_fluidTemperature(lptCellId) +=
527 * fvSolver().sysEqn().temperature_ES(fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->RHO),
528 fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->P));
529 if(lpt().m_evaporation && fvSolver().m_noSpecies > 0) {
530 lpt().a_fluidSpecies(lptCellId) +=
mMax(
532 mMin(1.0, cellVolume * fvSolver().a_pvariable(fvCellId, fvSolver().m_sysEqn.PV->Y[m_fvLPTSpeciesId])));
538 for(
MInt n = 0; n < nDim; n++) {
539 lpt().a_fluidVelocity(lptCellId, n) *= conversionFvLpt.velocity / volume;
541 lpt().a_fluidDensity(lptCellId) *= conversionFvLpt.density / volume;
542 lpt().a_fluidPressure(lptCellId) *= conversionFvLpt.pressure / volume;
543 lpt().a_fluidTemperature(lptCellId) *= conversionFvLpt.temperature / volume;
544 if(lpt().m_evaporation && fvSolver().m_noSpecies > 0) {
545 lpt().a_fluidSpecies(lptCellId) *= 1 / volume;
549 for(
MInt n = 0; n < nDim; n++) {
550 lpt().a_fluidVelocity(lptCellId, n) = conversionFvLpt.velocity;
552 lpt().a_fluidDensity(lptCellId) = conversionFvLpt.density;
553 lpt().a_fluidPressure(lptCellId) = conversionFvLpt.pressure;
554 lpt().a_fluidTemperature(lptCellId) = conversionFvLpt.temperature;
555 if(lpt().m_evaporation && fvSolver().m_noSpecies > 0) {
556 lpt().a_fluidSpecies(lptCellId) = 1;
559 }
else if(fvCellId < 0) {
560 if(lpt().a_isHalo(lptCellId))
continue;
562 fvCellId = lpt2fvIdParent(lptCellId);
565 cerr <<
"LPT-cell is missing fv-cell parent" << lptCellId <<
" " << fvCellId <<
" " << lpt().a_level(lptCellId)
568 interpolateFVLPT(fvCellId, lptCellId);
574 if(!lpt().m_nonBlockingComm) {
575 lpt().exchangeData(&lpt().a_fluidVariable(0, 0), lpt().PV.noVars());
576 if(lpt().m_evaporation) {
577 lpt().exchangeData(&lpt().a_fluidSpecies(0), 1);
580 if(lpt().isActive()) {
581 MPI_Allreduce(MPI_IN_PLACE, &diverged, 1, MPI_C_BOOL, MPI_LOR, lpt().mpiComm(), AT_,
"MPI_IN_PLACE",
"divCheck");
583 lpt().saveDebugRestartFile();
586 if(fvSolver().isActive()) {
587 MPI_Allreduce(MPI_IN_PLACE, &diverged, 1, MPI_C_BOOL, MPI_LOR, fvSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
590 fvSolver().writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
595 if(lpt().isActive()) {
596 lpt().sendFlowField();
606template <MInt nDim,
class SysEqn>
610 if(!lpt().m_wallCollisions)
return;
612 if(!lpt().isActive())
return;
615 for(
MInt lptCell = 0; lptCell < lpt().a_noCells(); lptCell++) {
616 if(lpt().a_bndryCellId(lptCell) >= lpt().m_noOuterBndryCells) {
617 lpt().a_bndryCellId(lptCell) = -1;
622 lpt().m_bndryCells->resetSize(lpt().m_noOuterBndryCells);
630 for(
MInt bndryId = fvSolver().m_noOuterBndryCells; bndryId < fvSolver().m_fvBndryCnd->m_bndryCells->size();
632 const MInt fvCellId = fvSolver().m_bndryCells->a[bndryId].m_cellId;
634 if(fvCellId < 0 || fvCellId >= fvSolver().c_noCells())
continue;
635 if(!fvSolver().c_isLeafCell(fvCellId))
continue;
636 MInt lptCellId = fv2lptId(fvCellId);
638 lptCellId = fv2lptIdParent(fvCellId);
639 if(lptCellId < 0)
continue;
640 if(lpt().c_level(lptCellId) < lpt().maxRefinementLevel())
continue;
641 ASSERT(m_lptFvInterpolation,
"");
644 if(!lpt().c_isLeafCell(lptCellId)) {
645 ASSERT(m_lptFvInterpolation,
"");
648 MInt noSurf = fvSolver().m_bndryCells->a[bndryId].m_noSrfcs;
654 if(noSurf > 1) noSurf = 1;
656 bndryData[0] = fvSolver().m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
657 for(
MInt i = 0; i < nDim; i++) {
658 bndryData[1 + i] = fvSolver().m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[i];
661 for(
MInt s = 0; s < noSurf; s++) {
662 MInt bodyId = fvSolver().m_levelSetMb ? fvSolver().m_bndryCells->a[bndryId].m_srfcs[s]->m_bodyId[0] : -1;
663 for(
MInt n = 0; n < nDim; n++) {
664 surfaceC(noSurf * s + n, 0) = fvSolver().m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[s]->m_coordinates[n];
665 for(
MInt i = 0; i < nDim; i++) {
666 surfaceC(noSurf * s + n, i + 1) =
667 fvSolver().m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[s]->m_cutCoordinates[i][n];
674 surfaceV[noSurf * s + n] = fvSolver().m_bodyVelocity[bodyId * nDim + n];
676 surfaceV[noSurf * s + n] = 0.0;
678 surfaceN[noSurf * s + n] = fvSolver().m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[s]->m_normalVector[n];
683 lpt().addBndryCell(lptCellId, &bndryData[0], &surfaceN[0], surfaceC, &surfaceV[0]);
691template <MInt nDim,
class SysEqn>
695 if(!fvSolver().m_sensorParticle)
return;
698 for(
MInt fvCell = 0; fvCell < fvSolver().c_noCells(); fvCell++) {
699 fvSolver().a_noPart(fvCell) = 0;
701 for(
MInt fvCell = fvSolver().c_noCells(); fvCell < fvSolver().a_noCells(); fvCell++) {
703 if(fvSolver().a_noPart(fvCell) > 0) {
704 cerr <<
" Particles in " << fvCell <<
" " << fvSolver().a_noCells() <<
" " << fvSolver().a_isHalo(fvCell)
705 << fvSolver().a_isBndryGhostCell(fvCell) << endl;
708 fvSolver().a_noPart(fvCell) = 0;
712 for(
MInt lptCell = 0; lptCell < lpt().noInternalCells(); lptCell++) {
713 if(lpt().a_noParticlesInCell(lptCell) < 1 && lpt().a_noEllipsoidsInCell(lptCell) < 1)
continue;
714 MInt fvCellId = lpt2fvId(lptCell);
716 ASSERT(m_lptFvInterpolation,
"");
717 fvCellId = lpt2fvIdParent(lptCell);
718 if(fvCellId < 0)
continue;
721 if(!fvSolver().c_isLeafCell(fvCellId)) {
722 ASSERT(m_lptFvInterpolation,
"");
725 fvSolver().a_noPart(fvCellId) = lpt().a_noParticlesInCell(lptCell) + lpt().a_noEllipsoidsInCell(lptCell);
728 fvSolver().exchangeData(&fvSolver().a_noPart(0));
735template <MInt nDim,
class SysEqn>
739 if(!fvSolver().isActive())
return;
741 if(!lpt().m_momentumCoupling && !lpt().m_heatCoupling && !lpt().m_massCoupling)
return;
743 if(lpt().isActive()) lpt().exchangeSourceTerms();
747 for(
MInt cellId = 0; cellId < fvSolver().a_noCells(); cellId++) {
748 for(
MInt var = 0; var < fvSolver().CV->noVariables; var++) {
751 if(abs(fvSolver().a_externalSource(cellId, var)) > MFloatEps) {
752 mTerm(1, AT_,
"External Source not reset correctly!!");
758 for(
MInt lptCell = 0; lptCell < lpt().noInternalCells(); lptCell++) {
760 if(!lpt().c_isLeafCell(lptCell))
continue;
761 MInt fvCellId = lpt2fvId(lptCell);
762 if(fvCellId > -1 && fvSolver().c_isLeafCell(fvCellId)) {
764 setExternalSourceInCell(fvCellId, lptCell, -1);
766 }
else if(fvCellId > -1 && !fvSolver().c_isLeafCell(fvCellId)) {
769 vector<MInt> leafChildIds;
770 fvSolver().grid().getAllLeafChilds(fvCellId, leafChildIds);
772 for(
MUint i = 0; i < leafChildIds.size(); i++) {
773 const MInt cellId = leafChildIds[i];
774 totalVol += fvSolver().a_cellVolume(cellId);
776 for(
MUint i = 0; i < leafChildIds.size(); i++) {
777 const MInt cellId = leafChildIds[i];
778 const MFloat vFrac = fvSolver().a_cellVolume(cellId) / totalVol;
779 setExternalSourceInCell(cellId, lptCell, vFrac);
783 fvCellId = lpt2fvIdParent(lptCell);
784 if(fvCellId < 0)
continue;
785 setExternalSourceInCell(fvCellId, lptCell, -1);
790 MInt numVars = 2 + nDim;
792 conservativeSums.
fill(0.0);
793 const MFloat dt = fvSolver().timeStep();
794 for(
MInt cellId = 0; cellId < fvSolver().noInternalCells(); cellId++) {
795 if(!fvSolver().c_isLeafCell(cellId))
continue;
796 if(fvSolver().a_isInactive(cellId))
continue;
798 if(fvSolver().m_noSpecies > 0) {
799 conservativeSums[0] -= dt * fvSolver().a_externalSource(cellId, fvSolver().CV->RHO_Y[m_fvLPTSpeciesId]);
801 conservativeSums[1] -= dt * fvSolver().a_externalSource(cellId, fvSolver().CV->RHO_E);
802 for(
MInt i = 0; i < nDim; i++) {
803 conservativeSums[2 + i] -= dt * fvSolver().a_externalSource(cellId, fvSolver().CV->RHO_VV[i]);
807 if(fvSolver().m_vapourData.size() > 0) {
809 if(it != fvSolver().m_vapourData.end()) {
810 for(
MInt i = 0; i < numVars; i++) {
811 MFloat lastSource = (it->second)[i];
812 conservativeSums[i] += lastSource;
817 vector<MFloat> tmp(numVars);
818 for(
MInt j = 0; j < numVars; j++) {
819 tmp[j] = conservativeSums[j];
829template <MInt nDim,
class SysEqn>
833 ASSERT(m_forceFvTimeStep,
"");
836 const MFloat conversionTime = conversionFvLpt.length / conversionFvLpt.velocity;
837 lpt().forceTimeStep(fvSolver().timeStep(
true) * conversionTime);
838 const MFloat fvTime = fvSolver().m_levelSetMb ? fvSolver().m_physicalTime : fvSolver().m_time;
839 if(lpt().isActive()) {
840 if(fabs(fvTime * conversionTime - lpt().m_time) > MFloatEps) {
841 cerr <<
"LPT-time " << lpt().m_time <<
" Fv-time " << fvTime <<
" " << conversionTime <<
" " <<
globalTimeStep
842 <<
" " << lpt().isActive() << endl;
843 mTerm(1, AT_,
"Miss-matching time!");
846 lpt().forceTimeStep(fvSolver().timeStep(
true) * fvSolver().m_timeRef);
848 cerr0 <<
"Fv-LPT time step set as " << fvSolver().timeStep(
true) * fvSolver().m_timeRef << endl;
852 if(lpt().m_sprayModel !=
nullptr && lpt().m_sprayModel->m_injectionCrankAngle > 0) {
853 const MFloat cad = fvSolver().crankAngle(fvTime, 0);
855 injDuration = Context::getSolverProperty<MFloat>(
"injectorInjectionTime", lpt().solverId(), AT_, &injDuration);
857 if(injDuration > 15) {
860 if(cad > lpt().m_sprayModel->m_injectionCrankAngle + injCAD && fvSolver().m_cfl < 0.7) {
861 cerr0 <<
"Increasing FV CFL for next computation from " << fvSolver().m_cfl <<
" to 0.95!" << endl;
862 fvSolver().m_cfl = 0.95;
870template <MInt nDim,
class SysEqn>
875 transferNoParticlesInCell();
881template <MInt nDim,
class SysEqn>
888 if(lpt().m_momentumCoupling) {
889 for(
MInt i = 0; i < nDim; i++) {
890 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_VV[i]) +=
891 lpt().a_momentumFlux(lptCell, i) / conversionFvLpt.momentum;
893 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_E) += lpt().a_workFlux(lptCell) / conversionFvLpt.energy;
895 if(lpt().m_heatCoupling) {
896 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_E) += lpt().a_heatFlux(lptCell) / conversionFvLpt.energy;
898 if(lpt().m_massCoupling) {
899 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO) += lpt().a_massFlux(lptCell) / conversionFvLpt.mass;
900 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_Y[m_fvLPTSpeciesId]) +=
901 lpt().a_massFlux(lptCell) / conversionFvLpt.mass;
904 if(lpt().m_momentumCoupling) {
905 for(
MInt i = 0; i < nDim; i++) {
906 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_VV[i]) +=
907 lpt().a_momentumFlux(lptCell, i) * factor / conversionFvLpt.momentum;
909 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_E) +=
910 lpt().a_workFlux(lptCell) * factor / conversionFvLpt.energy;
912 if(lpt().m_heatCoupling) {
913 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_E) +=
914 lpt().a_heatFlux(lptCell) * factor / conversionFvLpt.energy;
916 if(lpt().m_massCoupling) {
917 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO) +=
918 lpt().a_massFlux(lptCell) * factor / conversionFvLpt.mass;
920 fvSolver().a_externalSource(fvCellId, fvSolver().CV->RHO_Y[m_fvLPTSpeciesId]) +=
921 lpt().a_massFlux(lptCell) * factor / conversionFvLpt.mass;
929template <MInt nDim,
class SysEqn>
934 if(solverId == fvSolver().solverId()) {
935 transferCellStatus();
937 transferVelocitySlopes();
938 if(lpt().isActive()) {
939 lpt().receiveFlowField();
940 lpt().receiveVelocitySlopes();
941 lpt().waitForSendReqs();
946 }
else if(solverId == lpt().solverId()) {
949 if(fvSolver().m_hasExternalSource) {
950 fvSolver().resetExternalSources();
951 transferExternalSources();
961template <MInt nDim,
class SysEqn>
965 MInt interpolationCells[8] = {0, 0, 0, 0, 0, 0, 0, 0};
966 MFloat point[3] = {lpt().c_coordinate(to, 0), lpt().c_coordinate(to, 1), lpt().c_coordinate(to, 2)};
969 return static_cast<MBool>(fvSolver().checkNeighborActive(cellId,
id));
972 const MInt position = fvSolver().setUpInterpolationStencil(from, interpolationCells, point, neighborCheck,
true);
975 for(
MInt n = 0; n < nDim; n++) {
976 lpt().a_fluidVelocity(to, n) =
977 fvSolver().a_pvariable(from, fvSolver().m_sysEqn.PV->VV[n]) * conversionFvLpt.velocity;
979 lpt().a_fluidDensity(to) = fvSolver().a_pvariable(from, fvSolver().m_sysEqn.PV->RHO) * conversionFvLpt.density;
980 lpt().a_fluidPressure(to) = fvSolver().a_pvariable(from, fvSolver().m_sysEqn.PV->P) * conversionFvLpt.pressure;
981 lpt().a_fluidTemperature(to) =
982 fvSolver().sysEqn().temperature_ES(fvSolver().a_pvariable(from, fvSolver().m_sysEqn.PV->RHO),
983 fvSolver().a_pvariable(from, fvSolver().m_sysEqn.PV->P))
984 * conversionFvLpt.temperature;
985 if(lpt().m_evaporation && fvSolver().m_noSpecies > 0) {
986 lpt().a_fluidSpecies(to) = fvSolver().a_pvariable(from, fvSolver().m_sysEqn.PV->Y[m_fvLPTSpeciesId]);
990 for(
MInt n = 0; n < nDim; n++) {
991 lpt().a_fluidVelocity(to, n) =
992 interpolateVariable(interpolationCells, point, fvSolver().m_sysEqn.PV->VV[n]) * conversionFvLpt.velocity;
994 const MFloat rho = interpolateVariable(interpolationCells, point, fvSolver().m_sysEqn.PV->RHO);
995 const MFloat p = interpolateVariable(interpolationCells, point, fvSolver().m_sysEqn.PV->P);
996 lpt().a_fluidDensity(to) = rho * conversionFvLpt.density;
997 lpt().a_fluidPressure(to) = p * conversionFvLpt.pressure;
998 lpt().a_fluidTemperature(to) = fvSolver().sysEqn().temperature_ES(rho, p) * conversionFvLpt.temperature;
999 if(lpt().m_evaporation && fvSolver().m_noSpecies > 0) {
1000 lpt().a_fluidSpecies(to) =
1001 interpolateVariable(interpolationCells, point, fvSolver().m_sysEqn.PV->Y[m_fvLPTSpeciesId]);
1011template <MInt nDim,
class SysEqn>
1015 MInt interpolationCells[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1016 MFloat point[3] = {lpt().c_coordinate(to, 0), lpt().c_coordinate(to, 1), lpt().c_coordinate(to, 2)};
1019 return static_cast<MBool>(fvSolver().checkNeighborActive(cellId,
id));
1022 const MInt position = fvSolver().setUpInterpolationStencil(from, interpolationCells, point, neighborCheck,
true);
1025 for(
MInt varId = 0; varId < nDim; varId++) {
1026 for(
MInt dir = 0; dir < nDim; dir++) {
1027 lpt().a_velocitySlope(to, varId, dir) =
1028 fvSolver().a_slope(from, fvSolver().m_sysEqn.PV->VV[varId], dir) * conversionFvLpt.velocitySlope;
1032 for(
MInt varId = 0; varId < nDim; varId++) {
1033 for(
MInt dir = 0; dir < nDim; dir++) {
1034 lpt().a_velocitySlope(to, varId, dir) =
1035 interpolateSlope(interpolationCells, point, fvSolver().m_sysEqn.PV->VV[varId], dir)
1036 * conversionFvLpt.velocitySlope;
1046template <MInt nDim,
class SysEqn>
1051 return static_cast<MFloat>(fvSolver().a_pvariable(cellId, varId));
1055 return static_cast<MFloat>(fvSolver().a_coordinate(cellId,
id));
1058 return fvSolver().template interpolateFieldData<false>(&interpolationCells[0], &point[0], v, scalarField, coordinate);
1066template <MInt nDim,
class SysEqn>
1071 return static_cast<MFloat>(*(&fvSolver().a_slope(cellId, 0, 0) + varId));
1075 return static_cast<MFloat>(fvSolver().a_coordinate(cellId,
id));
1078 MInt valIndex = v * nDim + dir;
1079 return fvSolver().template interpolateFieldData<false>(&interpolationCells[0], &point[0], valIndex, scalarField,
1086template <MInt nDim,
class SysEqn>
1088 for(
MInt lptCellId = 0; lptCellId < lpt().a_noCells(); lptCellId++) {
1089 MInt fvCellId = lpt2fvIdParent(lptCellId);
1090 if(fvCellId < 0 || fvCellId > fvSolver().a_noCells()) {
1091 lpt().a_isValidCell(lptCellId) =
false;
1092 }
else if(fvSolver().a_hasProperty(fvCellId,
FvCell::IsCutOff) && !lpt().grid().isPeriodic(lptCellId)) {
1093 lpt().a_isValidCell(lptCellId) =
false;
1095 lpt().a_isValidCell(lptCellId) =
false;
1096 }
else if(fvSolver().a_isInactive(fvCellId)) {
1097 lpt().a_isValidCell(lptCellId) =
false;
1099 lpt().a_isValidCell(lptCellId) =
true;
1111template <MInt nDim,
class SysEqn>
1113 if(!lpt().m_ellipsoids)
return;
1116 MBool diverged =
false;
1119 for(
MInt lptCellId = 0; lptCellId < lpt().noInternalCells(); lptCellId++) {
1120 if(!lpt().c_isLeafCell(lptCellId))
continue;
1121 MInt fvCellId = lpt2fvId(lptCellId);
1122 if(fvCellId > -1 && fvSolver().c_isLeafCell(fvCellId)) {
1124 for(
MInt varId = 0; varId < nDim; varId++) {
1125 for(
MInt dir = 0; dir < nDim; dir++) {
1126 lpt().a_velocitySlope(lptCellId, varId, dir) =
1127 fvSolver().a_slope(fvCellId, fvSolver().m_sysEqn.PV->VV[varId], dir) * conversionFvLpt.velocitySlope;
1129 if(std::isnan(lpt().a_velocitySlope(lptCellId, varId, dir)) && lpt().a_isValidCell(lptCellId)
1132 cerr <<
"Nan velocity slope: " << lpt().a_velocitySlope(lptCellId, varId, dir) <<
" "
1133 << lpt().a_coordinate(lptCellId, 0) <<
" " << lpt().a_coordinate(lptCellId, 1) <<
" "
1134 << lpt().a_coordinate(lptCellId, nDim - 1) << endl;
1135 mTerm(1, AT_,
"FVParticle: Transfer of slope that is NAN");
1140 }
else if(fvCellId > -1 && !fvSolver().c_isLeafCell(fvCellId)) {
1142 if(lpt().a_isHalo(lptCellId))
continue;
1144 vector<MInt> leafChildIds;
1145 fvSolver().grid().getAllLeafChilds(fvCellId, leafChildIds);
1146 ASSERT(!leafChildIds.empty(),
"");
1149 for(
MInt varId = 0; varId < nDim; varId++) {
1150 for(
MInt dir = 0; dir < nDim; dir++) {
1151 lpt().a_velocitySlope(lptCellId, varId, dir) = F0;
1156 for(
MUint i = 0; i < leafChildIds.size(); i++) {
1157 const MInt cellId = leafChildIds[i];
1158 if(fvSolver().a_isInactive(cellId))
continue;
1159 const MFloat cellVolume = fvSolver().a_cellVolume(cellId);
1160 ASSERT(fvSolver().c_isLeafCell(cellId),
"");
1161 if(cellVolume < 1e-16)
mTerm(1, AT_,
"Invalid cell-volume!");
1162 volume += cellVolume;
1163 for(
MInt varId = 0; varId < nDim; varId++) {
1164 for(
MInt dir = 0; dir < nDim; dir++) {
1165 lpt().a_velocitySlope(lptCellId, varId, dir) +=
1166 cellVolume * fvSolver().a_slope(fvCellId, fvSolver().m_sysEqn.PV->VV[varId], dir);
1170 if(volume > 1e-16) {
1172 for(
MInt varId = 0; varId < nDim; varId++) {
1173 for(
MInt dir = 0; dir < nDim; dir++) {
1174 lpt().a_velocitySlope(lptCellId, varId, dir) *= conversionFvLpt.velocitySlope / volume;
1179 for(
MInt varId = 0; varId < nDim; varId++) {
1180 for(
MInt dir = 0; dir < nDim; dir++) {
1181 lpt().a_velocitySlope(lptCellId, varId, dir) = conversionFvLpt.velocitySlope;
1185 }
else if(fvCellId < 0) {
1186 if(lpt().a_isHalo(lptCellId))
continue;
1188 fvCellId = lpt2fvIdParent(lptCellId);
1189 ASSERT(fvCellId > -1,
"LPT-cell has no matching FV-cell!");
1190 interpolateVelocitySlopesFVLPT(fvCellId, lptCellId);
1196 if(!lpt().m_nonBlockingComm) {
1197 lpt().exchangeData(&lpt().a_velocitySlope(0, 0, 0), nDim * nDim);
1199 if(lpt().isActive()) {
1200 MPI_Allreduce(MPI_IN_PLACE, &diverged, 1, MPI_C_BOOL, MPI_LOR, lpt().mpiComm(), AT_,
"MPI_IN_PLACE",
"divCheck");
1202 lpt().saveDebugRestartFile();
1205 if(fvSolver().isActive()) {
1206 MPI_Allreduce(MPI_IN_PLACE, &diverged, 1, MPI_C_BOOL, MPI_LOR, fvSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
1209 fvSolver().writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
1214 if(lpt().isActive()) {
1215 lpt().sendVelocitySlopes();
1225template <MInt nDim,
class SysEqn>
1229 ASSERT(m_interLeafed,
"");
1231 cerr0 <<
"Unifying time-step LPT: " << lpt().m_timeStep <<
" FV: " << fvSolver().timeStep() << endl;
1233 const MFloat invalidTimeStep = std::numeric_limits<MFloat>::max();
1234 const MFloat conversionTime = conversionFvLpt.length / conversionFvLpt.velocity;
1235 MFloat timeFv = invalidTimeStep;
1236 MFloat timeLpt = invalidTimeStep;
1237 MInt maxLevelFv = -1;
1238 MInt maxLevelLpt = -1;
1239 MFloat newTimeFv = invalidTimeStep;
1240 MFloat newTimeLpt = invalidTimeStep;
1243 if(fvSolver().isActive() && lpt().isActive()) {
1244 timeFv = fvSolver().timeStep(
true);
1245 maxLevelFv = fvSolver().maxLevel();
1246 timeLpt = lpt().timeStep() / conversionTime;
1247 maxLevelLpt = lpt().maxLevel();
1249 MInt levelDiff = maxLevelLpt - maxLevelFv;
1250 if(levelDiff == 0) {
1251 newTimeFv =
mMin(timeFv, timeLpt);
1252 newTimeLpt = newTimeFv * conversionTime;
1254 if(levelDiff == 1) {
1256 newTimeLpt =
mMin(newTimeLpt, newTimeFv / 2.0);
1257 newTimeFv = 2.0 * newTimeLpt;
1258 }
else if(levelDiff == -1) {
1260 newTimeFv =
mMin(newTimeFv, newTimeLpt / 2.0);
1261 newTimeLpt = 2.0 * newTimeFv;
1263 mTerm(1, AT_,
"TimeStepping currently only implemented for 1 level difference!");
1268 if(lpt().isActive()) {
1269 MPI_Allreduce(MPI_IN_PLACE, &newTimeLpt, 1, MPI_DOUBLE, MPI_MIN, lpt().mpiComm(), AT_,
"MPI_IN_PLACE",
1272 if(fvSolver().isActive()) {
1273 MPI_Allreduce(MPI_IN_PLACE, &newTimeFv, 1, MPI_DOUBLE, MPI_MIN, fvSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
1277 if(fvSolver().domainId() == 0) {
1278 cerr <<
"Fv timestep was " << timeFv <<
" combined TS is " << newTimeFv << endl;
1281 if(lpt().domainId() == 0) {
1282 cerr <<
"LPT timestep was " << timeLpt <<
" combined TS is " << newTimeLpt << endl;
1286 if(fvSolver().isActive()) {
1287 fvSolver().forceTimeStep(newTimeFv);
1289 if(lpt().isActive()) {
1290 lpt().forceTimeStep(newTimeLpt);
1297template <MInt nDim,
class SysEqn>
1299 std::vector<MBool>& ) {
1300 if(!m_interLeafed)
return;
1302 if(fvSolver().isActive() && lpt().isActive()) {
1304 && fabs(lpt().m_timeStep - fvSolver().timeStep()) > MFloatEps) {
1310 if(recipeStep == m_lptSolverOrder && (solverId == m_fvSolverId || solverId == m_lptSolverId)) {
1314 if(m_solutionStep == 2 * m_noSolutionSteps - 3) {
1315 if(solverId == m_lptSolverId) {
1319 if(fvSolver().m_hasExternalSource && !lpt().m_skipLPT) {
1320 fvSolver().resetExternalSources();
1321 transferExternalSources();
1322 }
else if(lpt().m_skipLPT) {
1323 vector<MFloat> tmp(2 + nDim);
1324 for(
MInt j = 0; j < (2 + nDim); j++) {
1332 if(m_solutionStep == 2 * m_noSolutionSteps - 2 && !lpt().m_skipLPT) {
1333 if(fvSolver().m_hasExternalSource) {
1334 fvSolver().applyExternalOldSource();
1339 if(m_solutionStep == 2 * m_noSolutionSteps) {
1340 if(solverId == m_fvSolverId && !lpt().m_skipLPT) {
1342 transferFlowField();
1346 if(m_solutionStep == 2 * m_noSolutionSteps && (fvSolver().m_timeStepUpdated || lpt().m_timeStepUpdated)) {
1347 if(!m_forceFvTimeStep) {
1359template <MInt nDim,
class SysEqn>
1364 lpt().countParticlesInCells();
1366 if(!fvSolver().isActive()) {
1371 transferNoParticlesInCell();
1374 MInt maxNoParticles = 0;
1375 MInt maxParticlesSum = 0;
1376 for(
MInt cellId = 0; cellId < fvSolver().noInternalCells(); cellId++) {
1377 if(fvSolver().a_noPart(cellId) > maxNoParticles) {
1378 maxNoParticles = fvSolver().a_noPart(cellId);
1380 maxParticlesSum += fvSolver().a_noPart(cellId);
1383 MPI_Allreduce(MPI_IN_PLACE, &maxNoParticles, 1, MPI_INT, MPI_MAX, fvSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
1386 MPI_Allreduce(MPI_IN_PLACE, &maxParticlesSum, 1, MPI_INT, MPI_MAX, fvSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
1394 for(
MInt cellId = 0; cellId < fvSolver().noInternalCells(); cellId++) {
1395 if(!fvSolver().c_isLeafCell(cellId)) {
1398 if(!fvSolver().a_isActive(cellId)) {
1402 const MInt pos = fvSolver().a_noPart(cellId);
1407 MPI_Allreduce(MPI_IN_PLACE, &noCells(0), maxNoParticles + 1, MPI_DOUBLE, MPI_SUM, fvSolver().mpiComm(), AT_,
1408 "MPI_IN_PLACE",
"noCells");
1411 if(fvSolver().domainId() == 0) {
1412 struct stat buffer {};
1413 MString name =
"noParticlesInCells_" + to_string(fvSolver().solverId()) +
"_" + to_string(
globalTimeStep);
1414 const char* cstr = name.c_str();
1415 if(stat(cstr, &buffer) == 0) {
1416 rename(cstr,
"noParticlesInCells_BAK");
1419 ofl.open(name, ios_base::out | ios_base::app);
1420 ofl <<
"# 1:noParticles 2:noCells " << endl;
1421 for(
MInt i = 0; i < maxNoParticles + 1; i++) {
1422 ofl << i <<
" " << noCells(i) << endl;
1433 for(
MInt cellId = fvSolver().noInternalCells(); cellId < fvSolver().a_noCells(); cellId++) {
1434 fvSolver().a_noPart(cellId) = 0;
1437 MFloat minCellVolume = -1;
1438 for(
MInt id = 0;
id < fvSolver().grid().noMinCells();
id++) {
1439 const MInt cellId = fvSolver().grid().minCell(
id);
1443 minCellVolume = fvSolver().c_cellVolumeAtLevel(fvSolver().a_level(cellId));
1446 MInt curCount = childLoop(cellId);
1448 if(curCount > maxParticlesSum || curCount < 0) {
1449 cerr <<
"Strange particle count!" << curCount << endl;
1452 noMinCells(curCount)++;
1456 MPI_Allreduce(MPI_IN_PLACE, &noMinCells(0), maxParticlesSum + 1, MPI_INT, MPI_SUM, fvSolver().mpiComm(), AT_,
1457 "MPI_IN_PLACE",
"noMinCells");
1460 if(fvSolver().domainId() == 0) {
1461 struct stat buffer {};
1462 MString name =
"noParticlesInMinCells_" + to_string(fvSolver().solverId()) +
"_" + to_string(
globalTimeStep);
1463 const char* cstr = name.c_str();
1464 if(stat(cstr, &buffer) == 0) {
1465 rename(cstr,
"noParticlesInMinCells_BAK");
1468 MString header =
"# Min-cell volume : " + to_string(minCellVolume) +
" \n";
1470 ofl.open(name, ios_base::out | ios_base::trunc);
1471 ofl << header << endl;
1473 for(
MInt i = 0; i < maxParticlesSum + 1; i++) {
1474 ofl << i <<
" " << noMinCells(i) << endl;
1483template <MInt nDim,
class SysEqn>
1486 if(fvSolver().c_noChildren(cellId) > 0) {
1487 for(
MInt child = 0; child < fvSolver().c_noChildren(cellId); child++) {
1488 MInt childId = fvSolver().c_childId(cellId, child);
1492 sum += childLoop(childId);
1495 sum += fvSolver().a_noPart(cellId);
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
FvCartesianSolverXD< nDim, SysEqn > & fvSolver() const
void finalizeAdaptation(const MInt) override
prepate adaptation
LPT< nDim > & lpt() const override
void initConversion()
Calculates the conversion factor for different non-dimensionalisations in the FV and LPT solvers.
void finalizeBalance(const MInt unused) override
postCouple: exchange source terms after the LPT timeStep
void transferVelocitySlopes()
transfer the FV velocity slopes to the LPT solver
MInt childLoop(MInt cellId)
compute particle-cell binning and write to file
void initParticleVelocity()
Sets the initial particle velocity based on the flow field velocity in that cell. NOTE: This can not ...
MFloat interpolateVariable(MInt *, MFloat *, MInt)
interpolates the fv-variable /
void transferCellStatus()
set the isValid status for LPT cells based on the FV-solver cell properties
void transferNoParticlesInCell()
set a_noPart in Fv based on a_noParticlesInCell and a_noEllipsoidsInCell in LPT solver NOTE: this is ...
void unifyTimeStep()
Find combinded maximum timeStep for Fv and LPT solvers only possible for interleafed execution assumi...
void updateLPTBndry()
transfer all relevant bndryCell-data from FV to LPT solver before the LPT timeStep!
void interpolateFVLPT(const MInt from, const MInt to)
interpolate flow variables from the fv-grid to the LPT-cell position
FvCartesianSolverXD< nDim, SysEqn > * m_fvSolver
void writeParticleCellStats()
compute particle-cell binning and write to file
void transferFlowField()
transfer flow data from FV to LPT
void preCouple(MInt) override
preCoupler: reset external source terms before the LPT timestep
void checkProperties() override
Checks property-data which is read in by both lpt-and Fv-Solver.
MFloat interpolateSlope(MInt *, MFloat *, MInt, MInt)
interpolate fv slope
void initData()
Initialize coupling-class-specific Data.
void transferTimeStep()
transfer/enforce Fv timeStep onto LPT solver
void subCouple(MInt, MInt, std::vector< MBool > &) override
transfer the FV velocity slopes to the LPT solver
void postCouple(MInt) override
postCouple: exchange source terms after the LPT timeStep
void transferExternalSources()
set external sources in Fv solver based on values in the LPT solver
void prepareAdaptation() override
prepate adaptation
void interpolateVelocitySlopesFVLPT(const MInt from, const MInt to)
Interpolates the velocity slopes from the fv-grid to the LPT-cell.
void init() override
performs the coupling after solver initialization
void setExternalSourceInCell(const MInt, const MInt, const MFloat)
set external source in FV-solver from LPT fluxes
void finalizeCouplerInit() override
CouplerFvParticle(const MInt couplingId, LPT< nDim > *particle, FvCartesianSolver *fv)
This class is a ScratchSpace.
void fill(T val)
fill the scratch with a given value
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr Real POW2(const Real x)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
std::basic_string< char > MString
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