32template <MInt nDim,
class SysEqn>
39template <MInt nDim,
class SysEqn>
41 const MBool* propertiesGroups,
44 :
FvCartesianSolverXD<nDim, SysEqn>(solverId_, noSpecies, propertiesGroups, gridProxy_, geometry_, comm),
46 m_noCVars(CV->noVariables),
47 m_noFVars(FV->noVariables),
48 m_noPVars(PV->noVariables),
49 m_noSlopes(nDim * m_noPVars),
50 m_gammaMinusOne(m_gamma - F1) {
54 if(this->
m_fvBndryCnd ==
nullptr)
mTerm(1, AT_,
"something went wrong with the boundary condition in MB...");
67template <MInt nDim,
class SysEqn>
71 const clock_t t1 = clock();
72 const MFloat t =
static_cast<MFloat>(t1 - m_t0) / CLOCKS_PER_SEC;
73 m_log <<
"========================================" << endl;
74 m_log <<
"Total execution time FvMbSolver3D: " << printTime(t) <<
" (" << setprecision(8) << t <<
")" << endl;
75 m_log <<
"========================================" << endl;
87template <MInt nDim,
class SysEqn>
95 memset(execname, 0,
sizeof(execname));
96 readlink(
"/proc/self/exe", execname,
sizeof(execname) - 1);
97 gethostname(hostname,
sizeof(hostname));
98 cerr << endl << domainId() <<
": PID " << getpid() <<
" on " << hostname <<
" ready for attach." << endl;
99 cerr << domainId() <<
": ssh " << hostname <<
" \"gdb " << execname <<
" " << getpid()
100 <<
" -ex 'tbreak initializeMb()'\"" << endl;
104#ifdef _LOCAL_TIME_STEPPING
105 if(domainId() == 0) {
106 cerr << endl <<
"Local time stepping active!" << endl << endl;
112#if defined _MB_DEBUG_ || !defined NDEBUG
113 cerr0 <<
"DEBUG macro enabled." << endl;
114 m_log <<
"DEBUG macro enabled." << endl;
117 m_log <<
"Geometric conservation law enabled." << endl;
121 m_constructGField =
true;
122 m_constructGField = Context::getSolverProperty<MBool>(
"constructGField", m_solverId, AT_, &m_constructGField);
140 m_motionEquation = 0;
141 m_motionEquation = Context::getSolverProperty<MInt>(
"motionEquation", m_solverId, AT_, &m_motionEquation);
142 m_log <<
"motion equation: " << m_motionEquation << endl;
153 m_euler = Context::getSolverProperty<MBool>(
"euler", m_solverId, AT_, &m_euler);
155 m_solverType = (
SolverType)
string2enum(Context::getSolverProperty<MString>(
"solvertype", m_solverId, AT_));
156 execRungeKuttaStep =
nullptr;
165 m_generateOuterBndryCells = 1;
166 m_generateOuterBndryCells =
167 Context::getSolverProperty<MBool>(
"generateOuterBndryCells", m_solverId, AT_, &m_generateOuterBndryCells);
184 m_centralizeSurfaceVariables = 0;
185 m_centralizeSurfaceVariables =
186 Context::getSolverProperty<MInt>(
"centralizeSurfaceVariables", m_solverId, AT_, &m_centralizeSurfaceVariables);
187 m_log <<
"centralize surface vars: " << m_centralizeSurfaceVariables << endl;
199 m_levelSetAdaptationScheme = 0;
200 m_levelSetAdaptationScheme =
201 Context::getSolverProperty<MInt>(
"adaptLevelSetExtensionScheme", m_solverId, AT_, &m_levelSetAdaptationScheme);
204 if(!m_constructGField && m_levelSetAdaptationScheme != 2) m_singleAdaptation =
true;
213 m_haloCellOutput =
false;
214 m_haloCellOutput = Context::getSolverProperty<MBool>(
"haloCellOutput", m_solverId, AT_, &m_haloCellOutput);
216 m_solutionDiverged =
false;
218 m_movingBndryCndId = m_euler ? 3007 : 3006;
219 m_movingBndryCndId = Context::getSolverProperty<MInt>(
"movingBndryCndId", m_solverId, AT_, &m_movingBndryCndId);
221 m_loggingInterval = 100;
222 m_loggingInterval = Context::getSolverProperty<MInt>(
"loggingInterval", m_solverId, AT_, &m_loggingInterval);
235 m_bodySamplingInterval = 0;
236 m_bodySamplingInterval =
237 Context::getSolverProperty<MInt>(
"bodySamplingInterval", m_solverId, AT_, &m_bodySamplingInterval);
250 m_particleSamplingInterval = 0;
251 m_particleSamplingInterval =
252 Context::getSolverProperty<MInt>(
"particleSamplingInterval", m_solverId, AT_, &m_particleSamplingInterval);
264 m_conservationCheck =
false;
265 m_conservationCheck = Context::getSolverProperty<MBool>(
"conservationCheck", m_solverId, AT_, &m_conservationCheck);
278 m_writeCenterLineData =
false;
279 m_writeCenterLineData =
280 Context::getSolverProperty<MBool>(
"writeCenterLineData", m_solverId, AT_, &m_writeCenterLineData);
295 m_trackMovingBndry =
true;
296 m_trackMovingBndry = Context::getSolverProperty<MBool>(
"trackMovingBndry", m_solverId, AT_, &m_trackMovingBndry);
299 m_maxStructureSteps = 1;
300 m_maxStructureSteps = Context::getSolverProperty<MInt>(
"maxIterations", m_solverId, AT_, &m_maxStructureSteps);
302 m_gclIntermediate = m_levelSetMb;
304 if((m_motionEquation > 0) && !m_constructGField) {
305 mTerm(1, AT_,
"Please turn on 'constructGField'-property to start fluid structure interaction!");
321 m_trackMbStart = Context::getSolverProperty<MInt>(
"trackMbStart", m_solverId, AT_, &m_trackMbStart);
335 m_FSIStart = m_trackMbStart;
336 m_FSIStart = Context::getSolverProperty<MInt>(
"FSIStart", m_solverId, AT_, &m_FSIStart);
338 m_FSIToleranceU = 1e-6;
339 m_FSIToleranceU = Context::getSolverProperty<MFloat>(
"FSIToleranceU", m_solverId, AT_, &m_FSIToleranceU);
340 m_FSIToleranceX = 1e-6;
341 m_FSIToleranceX = Context::getSolverProperty<MFloat>(
"FSIToleranceX", m_solverId, AT_, &m_FSIToleranceX);
342 m_FSIToleranceW = 1e-5;
343 m_FSIToleranceW = Context::getSolverProperty<MFloat>(
"FSIToleranceW", m_solverId, AT_, &m_FSIToleranceW);
344 m_FSIToleranceR = 1e-5;
345 m_FSIToleranceR = Context::getSolverProperty<MFloat>(
"FSIToleranceR", m_solverId, AT_, &m_FSIToleranceR);
359 m_trackMbEnd = numeric_limits<MInt>::max();
360 m_trackMbEnd = Context::getSolverProperty<MInt>(
"trackMbEnd", m_solverId, AT_, &m_trackMbEnd);
362 m_noLevelSetsUsedForMb = 1;
363 m_noLevelSetsUsedForMb = Context::getSolverProperty<MInt>(
"maxNoLevelSets", m_solverId, AT_, &m_noLevelSetsUsedForMb);
365 m_lsCutCellBaseLevel = -1;
366 m_lsCutCellMinLevel = 99;
367 mAlloc(m_lsCutCellLevel, m_noLevelSetsUsedForMb,
"m_lsCutCellLevel", maxRefinementLevel(), AT_);
370 m_lsCutCellBaseLevel = maxRefinementLevel();
371 m_lsCutCellMinLevel = maxRefinementLevel();
374 m_lsCutCellBaseLevel = Context::getSolverProperty<MInt>(
"cutCellLevel", m_solverId, AT_, 0);
376 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
377 m_lsCutCellLevel[set] = Context::getSolverProperty<MInt>(
"cutCellLevel", m_solverId, AT_, set);
378 m_lsCutCellMinLevel =
mMin(m_lsCutCellMinLevel, m_lsCutCellLevel[set]);
382 ASSERT(m_lsCutCellBaseLevel <= maxRefinementLevel() && m_lsCutCellBaseLevel >= maxUniformRefinementLevel()
383 && m_lsCutCellMinLevel <= maxRefinementLevel() && m_lsCutCellMinLevel >= maxUniformRefinementLevel(),
386 MInt maxSensorLevel = 0;
387 for(
MInt s = 0; s < this->m_noSensors; s++) {
388 maxSensorLevel =
mMax(maxSensorLevel, this->m_maxSensorRefinementLevel[s]);
392 m_bndryLevelJumps =
false;
393 if(maxRefinementLevel() != m_lsCutCellBaseLevel || maxRefinementLevel() != m_lsCutCellMinLevel) {
395 m_bndryLevelJumps =
true;
396 cerr0 <<
"Warning: Using different levels for levelset bndryd: cutCellBaseLevel ( " << m_lsCutCellBaseLevel
397 <<
") , maxRefinementLevel (" << maxRefinementLevel() <<
") and cutCellMinLevel ( " << m_lsCutCellMinLevel
400 cerr0 <<
"Solver " << m_solverId <<
" is multi-level secondary with maxLevel " << maxLevel()
401 <<
", maxRefinementLevel " << maxRefinementLevel() <<
", maxSensorLevel " << maxSensorLevel
402 <<
" and cutCellLevel " << m_lsCutCellBaseLevel << endl;
406 MFloat distFac[2] = {18.0, 9.0};
407 for(
MInt i = 0; i < 2; i++) {
408 distFac[i] = Context::getSolverProperty<MFloat>(
"mbBandWidth", m_solverId, AT_, &distFac[i], i);
410 m_bandWidth[m_lsCutCellBaseLevel - 1] = distFac[0];
411 for(
MInt i = maxRefinementLevel() - 2; i >= 0; i--) {
412 m_bandWidth[i] = (m_bandWidth[i + 1] / 2) + 1 + distFac[1];
416 m_maxLevelChange =
false;
417 if(
globalTimeStep > 0 && isActive() && m_restartFile && maxLevel() != maxRefinementLevel() && !m_bndryLevelJumps
419 cerr0 <<
"MaxLevel is " << maxLevel() <<
" and maxRefinementLevel is " << maxRefinementLevel()
420 <<
" => temporarily reduction of lsCutCellMinLevel to MaxLevel! " << endl;
421 m_maxLevelChange =
true;
422 m_lsCutCellMinLevel = maxLevel();
423 m_bndryLevelJumps =
true;
427 m_maxLevelDecrease =
false;
428 if(
globalTimeStep > 0 && m_restartFile && isActive() && this->m_adaptation && maxLevel() > maxSensorLevel) {
429 m_maxLevelDecrease =
true;
430 cerr0 <<
"MaxLevel will be reduced from " << maxLevel() <<
" to " << maxSensorLevel << endl;
431 ASSERT(m_lsCutCellMinLevel <= maxSensorLevel,
"");
453 m_bodyTypeMb = Context::getSolverProperty<MInt>(
"bodyTypeMb", m_solverId, AT_, &m_bodyTypeMb);
454 if(m_bodyTypeMb < 0 || m_bodyTypeMb > 7) {
455 mTerm(1, AT_,
"Unknown body type!");
469 m_logBoundaryData =
false;
470 m_logBoundaryData = Context::getSolverProperty<MBool>(
"logBoundaryData", m_solverId, AT_, &m_logBoundaryData);
472 m_recordBodyData =
true;
474 m_trackBodySurfaceData =
true;
475 m_trackBodySurfaceData =
476 Context::getSolverProperty<MBool>(
"trackBodySurfaceData", m_solverId, AT_, &m_trackBodySurfaceData);
478 if(m_outputOffset > 0) m_solutionOffset = m_outputOffset;
481 m_onlineRestart =
false;
482 m_onlineRestartInterval = 0;
483 m_onlineRestartInterval =
484 Context::getSolverProperty<MInt>(
"onlineRestartInterval", m_solverId, AT_, &m_onlineRestartInterval);
495 m_complexBoundary =
false;
496 m_complexBoundary = Context::getSolverProperty<MBool>(
"complexBoundaryForMb", m_solverId, AT_, &m_complexBoundary);
499 m_physicalTimeDt1 = F0;
507 m_noOuterBndryCells = 0;
508 m_noLsMbBndryCells = 0;
509 m_deleteNeighbour =
false;
510 m_noNearBndryCells = 0;
511 m_noEmergedCells = 0;
512 m_noEmergedWindowCells = 0;
513 m_reconstructionDataSize = 0;
514 m_bndryCellSurfacesOffset = 0;
515 m_bndrySurfacesOffset = 0;
516 m_totalnosplitchilds = 0;
518 mAlloc(m_gridCellArea, maxRefinementLevel() + 1,
"m_gridCellArea", -F1, AT_);
520 for(
MInt level = 0; level < maxRefinementLevel() + 1; level++) {
521 m_gridCellArea[level] = F1;
522 for(
MInt spaceId = 1; spaceId < nDim; spaceId++) {
523 m_gridCellArea[level] *= c_cellLengthAtLevel(level);
527 mAlloc(m_gravity, 3,
"m_gravity", F0, AT_);
529 cerr0 <<
"min/max cell length is " << setprecision(15) << c_cellLengthAtLevel(maxRefinementLevel()) <<
"/"
530 << c_cellLengthAtLevel(maxUniformRefinementLevel()) << setprecision(6) << endl;
533 MInt maxPointsXD = 12;
534 IF_CONSTEXPR(nDim == 3) maxPointsXD = 12;
535 m_noSurfacePointSamples = 0;
547 m_maxNoSurfacePointSamples = m_fvBndryCnd->m_maxNoBndryCells;
548 m_maxNoSurfacePointSamples =
549 Context::getSolverProperty<
MInt>("maxNoSurfacePointSamples", m_solverId, AT_, &m_maxNoSurfacePointSamples);
551 m_maxNoSampleNghbrs = 6;
552 m_stableVolumeFraction = m_fvBndryCnd->m_volumeLimitWall;
565 m_timeStepAdaptationStart = -1;
566 m_timeStepAdaptationStart =
567 Context::getSolverProperty<
MInt>("timeStepAdaptationStart", m_solverId, AT_, &m_timeStepAdaptationStart);
580 m_timeStepAdaptationEnd = -1;
581 m_timeStepAdaptationEnd =
582 Context::getSolverProperty<
MInt>("timeStepAdaptationEnd", m_solverId, AT_, &m_timeStepAdaptationEnd);
595 m_cflInitial =
Context::getSolverProperty<
MFloat>("cflInitial", m_solverId, AT_, &m_cfl);
612 if(
Context::propertyExists("Froude", m_solverId)) {
613 m_Fr = Context::getSolverProperty<MFloat>(
"Froude", m_solverId, AT_, &m_Fr);
614 m_g =
POW2(m_Ma / m_Fr);
627 m_g = Context::getSolverProperty<MFloat>(
"gravitationalAcceleration", m_solverId, AT_, &m_g);
628 m_Fr = m_Ma / sqrt(m_g);
639 for(
MInt i = 0; i < nDim; i++)
640 m_gravity[i] = Context::getSolverProperty<MFloat>(
"gravity", m_solverId, AT_, i);
641 m_g =
mMax(
mMax(m_gravity[0], m_gravity[1]), m_gravity[2]);
642 m_log <<
"gravity: " << m_gravity[0] <<
" " << m_gravity[1] <<
" " << m_gravity[2] <<
", Froude: " << F1 / sqrt(m_g)
647 m_log <<
"gravity: " << m_g <<
", Froude: " << m_Fr << endl;
649 MInt noPeriodicDirs = 0;
650 for(
MInt dir = 0; dir < nDim; dir++) {
651 if(grid().periodicCartesianDir(dir)) noPeriodicDirs++;
654 m_maxBndryLayerLevel = maxRefinementLevel();
655 m_maxBndryLayerWidth = 6;
656 m_outsideFactor = F2;
661 m_noEmbeddedBodies = 1;
663 m_noEmbeddedBodies = Context::getSolverProperty<MInt>(
"noEmbeddedBodies", m_solverId, AT_, &m_noEmbeddedBodies);
667 m_log <<
"noEmbeddedBodies " << m_noEmbeddedBodies << endl;
668 m_noPeriodicGhostBodies = 0;
670 m_maxNoEmbeddedBodiesPeriodic = (noPeriodicDirs > 0)
671 ? ((m_noEmbeddedBodies < 100) ? 12 * m_noEmbeddedBodies : 4 * m_noEmbeddedBodies)
672 : m_noEmbeddedBodies;
673 if(m_noEmbeddedBodies > 9999 && noPeriodicDirs > 0) {
674 m_maxNoEmbeddedBodiesPeriodic =
675 m_noEmbeddedBodies + m_noEmbeddedBodies / 2;
677 m_log <<
"m_maxNoEmbeddedBodiesPeriodic"
678 <<
" " << m_maxNoEmbeddedBodiesPeriodic << endl;
681 allocateBodyMemory(0);
683 mAlloc(m_levelSetValuesMb, m_noLevelSetsUsedForMb * maxNoCells,
"m_levelSetValuesMb", F0, AT_);
685 m_bndryCandidateIds.reserve(maxNoCells);
687 m_maxNearestBodies = 20;
688 m_maxNearestBodies = Context::getSolverProperty<MInt>(
"maxNearestBodies", m_solverId, AT_, &m_maxNearestBodies);
689 MInt noParticles = 0;
691 if(isActive() && m_noEmbeddedBodies > 0) {
692 m_particleOffsets.push_back(0);
693 for(
MLong dom = 0; dom < noDomains(); dom++) {
694 MLong tmpv = (((
MLong)m_noEmbeddedBodies) * (dom + 1)) / ((
MLong)noDomains());
695 if(tmpv > numeric_limits<MInt>::max())
mTerm(1,
"int overflow");
696 m_particleOffsets.push_back((
MInt)tmpv);
698 noParticles = m_particleOffsets[domainId() + 1] - m_particleOffsets[domainId()];
701 ? Context::getSolverProperty<MInt>(
"slipInterval", m_solverId, AT_, &m_slipInterval)
703 m_saveSlipInterval = 0;
704 if(m_noEmbeddedBodies > 0 && m_slipInterval > 0) {
706 MInt noSetups = m_noAngleSetups * m_noDistSetups;
713 m_noSlipDataOutputs = m_saveSlipInterval / m_slipInterval;
714 if(m_noSlipDataOutputs < 1) {
715 mTerm(0,
"Properties saveSlipInterval and slipInterval inconsistent.");
717 mAlloc(m_slipDataParticleCollision,
mMax(1, noParticles) * m_noSlipDataOutputs * 1,
"m_slipDataParticleCollision",
719 mAlloc(m_slipDataParticleQuaternion,
mMax(1, noParticles) * m_noSlipDataOutputs * 4,
"m_slipDataParticleQuaternion",
721 mAlloc(m_slipDataParticleVel,
mMax(1, noParticles) * m_noSlipDataOutputs * nDim,
"m_slipDataParticleVel", -F1, AT_);
722 mAlloc(m_slipDataParticleAngularVel,
mMax(1, noParticles) * m_noSlipDataOutputs * 3,
"m_slipDataParticleAngularVel",
724 mAlloc(m_slipDataParticleForce,
mMax(1, noParticles) * m_noSlipDataOutputs * nDim,
"m_slipDataParticleForce", -F1,
726 mAlloc(m_slipDataParticleTorque,
mMax(1, noParticles) * m_noSlipDataOutputs * 3,
"m_slipDataParticleTorque", -F1,
728 mAlloc(m_slipDataParticleFluidVel,
mMax(1, noParticles) * m_noSlipDataOutputs * noSetups * nDim,
729 "m_slipDataParticleFluidVel", -F1, AT_);
730 mAlloc(m_slipDataParticleFluidVelGrad,
mMax(1, noParticles) * m_noSlipDataOutputs * noSetups *
POW2(nDim),
731 "m_slipDataParticleFluidVelGrad", -F1, AT_);
732 mAlloc(m_slipDataParticleFluidVelRot,
mMax(1, noParticles) * m_noSlipDataOutputs * noSetups * 3,
733 "m_slipDataParticleFluidVelRot", -F1, AT_);
734 mAlloc(m_slipDataParticlePosition,
mMax(1, noParticles) * m_noSlipDataOutputs * nDim,
"m_slipDataParticlePosition",
738 m_bndryLayerCells.reserve(m_fvBndryCnd->m_maxNoBndryCells);
739 mAlloc(m_volumeFraction, m_fvBndryCnd->m_maxNoBndryCells,
"m_volumeFraction", -F1, AT_);
740 mAlloc(m_maxBndryLayerDistances, m_maxBndryLayerLevel + 1, 2,
"m_maxBndryLayerDistances", F0, AT_);
741 mAlloc(m_associatedBodyIds, m_noLevelSetsUsedForMb * maxNoCells,
"m_associatedBodyIds", -1, AT_);
742 mAlloc(m_stableCellVolume, m_maxBndryLayerLevel + 1,
"m_stableCellVolume", F0, AT_);
743 mAlloc(m_cellVolumesDt1, maxNoCells,
"m_cellVolumesDt1", F0, AT_);
744 if(m_dualTimeStepping) {
745 mAlloc(m_cellVolumesDt2, maxNoCells,
"m_cellVolumesDt2", F0, AT_);
747 mAlloc(m_sweptVolume, m_fvBndryCnd->m_maxNoBndryCells,
"m_sweptVolume", F0, AT_);
748 mAlloc(m_sweptVolumeDt1, m_fvBndryCnd->m_maxNoBndryCells,
"m_sweptVolumeDt1", F0, AT_);
749 mAlloc(m_rhs0, maxNoCells, m_noFVars,
"m_rhs0", F0, AT_);
751#ifdef VISCOUS_FLUX_FREEZING
752 mAlloc(m_rhsViscous, maxNoCells, m_noFVars,
"m_rhsViscous", F0, AT_);
754 m_rhsViscous =
nullptr;
757 mAlloc(m_noCutCellFaces, m_fvBndryCnd->m_maxNoBndryCells,
"m_noCutCellFaces", 0, AT_);
758 mAlloc(m_cutFacePointIds, m_fvBndryCnd->m_maxNoBndryCells, maxFacesXD * maxPointsXD,
"m_cutFacePointIds", -1, AT_);
759 mAlloc(m_noCutFacePoints, m_fvBndryCnd->m_maxNoBndryCells, maxFacesXD,
"m_noCutFacePoints", 0, AT_);
760 mAlloc(m_cutFaceArea, m_fvBndryCnd->m_maxNoBndryCells, m_noDirs,
"m_cutFaceArea", F0, AT_);
761 mAlloc(m_pointIsInside, m_fvBndryCnd->m_maxNoBndryCells, m_noLevelSetsUsedForMb * m_noCellNodes,
"m_pointIsInside",
763 mAlloc(m_bbox, 2 * nDim,
"m_bbox", F0, AT_);
764 mAlloc(m_bboxLocal, 2 * nDim,
"m_bboxLocal", F0, AT_);
765 mAlloc(m_nghbrList, 27 * m_noCellNodes,
"m_nghbrList", -1, AT_);
766 mAlloc(m_sendBufferSize,
mMax(1, noNeighborDomains()),
"m_sendBufferSize", 0, AT_);
767 mAlloc(m_receiveBufferSize,
mMax(1, noNeighborDomains()),
"m_receiveBufferSize", 0, AT_);
768 mAlloc(g_mpiRequestMb,
mMax(1, noNeighborDomains()),
"g_mpiRequestMb", MPI_REQ_NULL, AT_);
769 mAlloc(m_cellSurfaceMapping, maxNoCells, m_noDirs,
"m_cellSurfaceMapping", -1, AT_);
782 m_noPointParticles = 0;
783 m_noPointParticles = Context::getSolverProperty<MInt>(
"noPointParticles", m_solverId, AT_, &m_noPointParticles);
784 m_noPointParticlesLocal = 0;
800 m_pointParticleType = 1;
801 m_pointParticleType = Context::getSolverProperty<MInt>(
"pointParticleType", m_solverId, AT_, &m_pointParticleType);
815 m_pointParticleTwoWayCoupling = 0;
816 m_pointParticleTwoWayCoupling =
817 Context::getSolverProperty<MInt>(
"pointParticleTwoWayCoupling", m_solverId, AT_, &m_pointParticleTwoWayCoupling);
830 mAlloc(m_particleTerminalVelocity, nDim,
"m_particleTerminalVelocity", F0, AT_);
832 for(
MInt dir = 0; dir < nDim; dir++) {
833 m_particleTerminalVelocity[dir] = Context::getSolverProperty<MFloat>(
"particleTerminalVelocity", m_solverId, AT_,
834 &m_particleTerminalVelocity[dir], dir);
837 if(m_pointParticleTwoWayCoupling == 1 && m_noPointParticles > 0) {
838 mAlloc(m_coupling, maxNoGridCells(), nDim,
"m_coupling", F0, AT_);
842 m_particleCoords.clear();
843 m_particleCoordsDt1.clear();
844 m_particleVelocity.clear();
845 m_particleTemperature.clear();
846 m_particleTemperatureDt1.clear();
847 m_particleHeatFlux.clear();
848 m_particleVelocityDt1.clear();
849 m_particleVelocityFluid.clear();
850 m_particleFluidTemperature.clear();
851 m_particleAcceleration.clear();
852 m_particleAccelerationDt1.clear();
853 m_particleQuaternions.clear();
854 m_particleQuaternionsDt1.clear();
855 m_particleAngularVelocity.clear();
856 m_particleAngularVelocityDt1.clear();
857 m_particleVelocityGradientFluid.clear();
858 m_particleAngularAcceleration.clear();
859 m_particleAngularAccelerationDt1.clear();
860 m_particleShapeParams.clear();
861 m_particleRadii.clear();
862 m_particleCellLink.clear();
864 m_linkedWindowCells =
nullptr;
865 m_linkedHaloCells =
nullptr;
867 mAlloc(m_linkedWindowCells,
mMax(1, noNeighborDomains()),
"m_linkedWindowCells", AT_);
868 mAlloc(m_linkedHaloCells,
mMax(1, noNeighborDomains()),
"m_linkedHaloCells", AT_);
870 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
871 m_internalBodyId[
b] =
b;
874 std::vector<MInt>().swap(m_bndryLayerCells);
876 for(
MInt i = 0; i <= m_maxBndryLayerLevel; i++) {
877 m_maxBndryLayerDistances[i][0] = -c_cellLengthAtLevel(i) * F3;
878 m_maxBndryLayerDistances[i][1] = c_cellLengthAtLevel(i) * (
MFloat)m_maxBndryLayerWidth;
879 m_log <<
"bndry layer width level " << i <<
": " << m_maxBndryLayerDistances[i][0] <<
" "
880 << m_maxBndryLayerDistances[i][1] << endl;
884 m_bodyDistThreshold = 1.1
885 * (
mMax(m_outerBandWidth[
mMin(maxUniformRefinementLevel(), maxRefinementLevel() - 1)],
886 m_maxBndryLayerDistances[maxRefinementLevel()][1])
887 + c_cellLengthAtLevel(minLevel()));
888 m_periodicGhostBodyDist = 1.1
889 * (m_outerBandWidth[
mMin(maxUniformRefinementLevel(), maxRefinementLevel() - 1)]
890 + ((
MFloat)noHaloLayers()) * c_cellLengthAtLevel(minLevel()));
892 m_bodyDistThreshold = 1.1 * m_maxBndryLayerDistances[maxRefinementLevel()][1] + c_cellLengthAtLevel(minLevel());
893 m_periodicGhostBodyDist = 1.1 * ((
MFloat)noHaloLayers()) * c_cellLengthAtLevel(minLevel());
895 m_log <<
"body dist threshold " << m_bodyDistThreshold <<
" " << m_periodicGhostBodyDist << endl;
897 for(
MInt i = 0; i <= m_maxBndryLayerLevel; i++) {
898 m_stableCellVolume[i] = grid().gridCellVolume(i) * m_stableVolumeFraction;
902 m_applyCollisionModel = (m_initialCondition == 15 || m_initialCondition == 16);
903 m_applyCollisionModel =
904 Context::getSolverProperty<MBool>(
"applyCollisionModel", m_solverId, AT_, &m_applyCollisionModel);
906 m_massRedistributionIds.clear();
907 m_massRedistributionVariables.clear();
908 m_massRedistributionRhs.clear();
909 m_massRedistributionVolume.clear();
910 m_massRedistributionSweptVol.clear();
911 m_temporarilyLinkedCells.clear();
913 m_splitCells.clear();
914 m_splitChilds.clear();
915 m_splitChildToSplitCell.clear();
919 m_fvBndryCnd->m_noBoundarySurfaces = 0;
921 if(domainId() == 0) {
927 computeLocalBoundingBox();
928 for(
MInt i = 0; i < 2 * nDim; i++) {
929 m_bbox[i] = m_bboxLocal[i];
933 MPI_Allreduce(MPI_IN_PLACE, &m_bbox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"m_bbox[0]");
934 MPI_Allreduce(MPI_IN_PLACE, &m_bbox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
938 if(domainId() == 0) {
939 cerr <<
"bounding box: " << setprecision(15);
940 for(
MInt i = 0; i < nDim; i++)
941 cerr << m_bbox[i] <<
":" << m_bbox[nDim + i] <<
" ";
942 cerr << setprecision(6) << endl;
943 m_log <<
"bounding box: ";
944 for(
MInt i = 0; i < nDim; i++)
945 m_log << m_bbox[i] <<
":" << m_bbox[nDim + i] <<
" ";
949 stringstream solver_data;
951 solver_data << m_solutionOutput;
952 solver_data <<
"/solver_data";
954 if(stat((solver_data.str()).c_str(), &s0) < 0) {
955#if defined(MAIA_MS_COMPILER)
956#pragma message("WARNING: Not compatible")
957 mTerm(0,
"ERROR: Not implemented!");
959 mkdir((solver_data.str()).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
963 m_log <<
"eps is " << m_eps << endl;
967 m_closeGaps = Context::getSolverProperty<MBool>(
"closeGaps", m_solverId, AT_, &m_closeGaps);
985 m_gapInitMethod = Context::getSolverProperty<MInt>(
"gapInitMethod", 0, AT_, &m_gapInitMethod);
986 m_noGapRegions = Context::getSolverProperty<MInt>(
"noGapRegions", 0, AT_, &m_noGapRegions);
988 mAlloc(m_gapState, m_noGapRegions,
"m_gapState", 0, AT_);
992 m_gapWindowCells =
nullptr;
993 m_gapHaloCells =
nullptr;
994 mAlloc(m_gapWindowCells, noNeighborDomains(),
"m_gapWindowCells", AT_);
995 mAlloc(m_gapHaloCells, noNeighborDomains(),
"m_gapHaloCells", AT_);
998 m_LsMovement =
false;
999 m_LsMovement = Context::getSolverProperty<MBool>(
"LsMovement", m_solverId, AT_, &m_LsMovement);
1008 m_LsRotate = Context::getSolverProperty<MBool>(
"LsRotate", m_solverId, AT_, &m_LsRotate);
1010 m_refineDiagonals =
false;
1013 m_alwaysResetCutOff =
false;
1014 m_alwaysResetCutOff = Context::getSolverProperty<MBool>(
"resetCutOff", m_solverId, AT_, &m_alwaysResetCutOff);
1016 m_maxIterations = 1;
1017 m_maxIterations = Context::getSolverProperty<MInt>(
"maxIterations", m_solverId, AT_, &m_maxIterations);
1020 m_bodyIdOutput = m_bodyIdOutput || !m_constructGField;
1023 m_levelSetOutput = m_levelSetOutput || !m_constructGField;
1026 if(m_constructGField) initAnalyticalLevelSet();
1028 m_reConstSVDWeightMode = 1;
1029 if(m_bndryLevelJumps) m_reConstSVDWeightMode = 0;
1045 m_reConstSVDWeightMode =
1046 Context::getSolverProperty<MInt>(
"reConstSVDWeightMode", m_solverId, AT_, &m_reConstSVDWeightMode);
1048 if(m_bndryLevelJumps) {
1049 ASSERT(m_reConstSVDWeightMode != 1,
"Mode not working for bndry-level-jumps!");
1059 m_engineSetup = Context::getSolverProperty<MBool>(
"engineSetup", m_solverId, AT_, &m_engineSetup);
1068 m_linerLvlJump = Context::getSolverProperty<MBool>(
"linerLevelJump", m_solverId, AT_, &m_linerLvlJump);
1070 if(domainId() == 0 && m_engineSetup) {
1071 cerr <<
"Applying engine setup with " << m_linerLvlJump <<
"liner level Jumps!" << endl;
1074 if(m_linerLvlJump) ASSERT(m_engineSetup,
"");
1090 m_forceNoGaps = Context::getSolverProperty<MInt>(
"forceNoGaps", m_solverId, AT_, &m_forceNoGaps);
1092 MInt noGapRegions = 0;
1093 noGapRegions = Context::getSolverProperty<MInt>(
"noGapRegions", m_solverId, AT_, &noGapRegions);
1095 if(m_forceNoGaps == 1) {
1097 mAlloc(m_gapAngleClose, noGapRegions,
"m_gapAngleClose", F0, AT_);
1098 mAlloc(m_gapAngleOpen, noGapRegions,
"m_gapAngleOpen", F0, AT_);
1099 mAlloc(m_gapSign, noGapRegions,
"m_gapSign", F1, AT_);
1101 for(
MInt i = 0; i < noGapRegions; i++) {
1102 m_gapAngleClose[i] =
1103 Context::getSolverProperty<MFloat>(
"gapAngleClose", m_solverId, AT_, &m_gapAngleClose[i], i);
1104 m_gapAngleOpen[i] = Context::getSolverProperty<MFloat>(
"gapAngleOpen", m_solverId, AT_, &m_gapAngleClose[i], i);
1105 if(m_gapAngleClose[i] < 0.0) {
1106 m_gapAngleClose[i] = 720 + m_gapAngleClose[i];
1108 if(m_gapAngleOpen[i] < 0.0) {
1109 m_gapAngleOpen[i] = 720 + m_gapAngleOpen[i];
1111 if(m_gapAngleOpen[i] > m_gapAngleClose[i]) {
1115 }
else if(m_forceNoGaps == 2) {
1117 ASSERT(noGapRegions == 1,
"Mode only intended for 1 gap-region!");
1119 mAlloc(m_gapAngleClose, noGapRegions + 1,
"m_gapAngleClose", F0, AT_);
1120 mAlloc(m_gapAngleOpen, noGapRegions + 1,
"m_gapAngleOpen", F0, AT_);
1121 mAlloc(m_gapSign, noGapRegions + 1,
"m_gapSign", F1, AT_);
1125 for(
MInt i = 0; i < noGapRegions + 1; i++) {
1126 m_gapAngleClose[i] =
1127 Context::getSolverProperty<MFloat>(
"gapAngleClose", m_solverId, AT_, &m_gapAngleClose[i], i);
1128 m_gapAngleOpen[i] = Context::getSolverProperty<MFloat>(
"gapAngleOpen", m_solverId, AT_, &m_gapAngleClose[i], i);
1129 if(m_gapAngleClose[i] < 0.0) {
1130 m_gapAngleClose[i] = 720 + m_gapAngleClose[i];
1132 if(m_gapAngleOpen[i] < 0.0) {
1133 m_gapAngleOpen[i] = 720 + m_gapAngleOpen[i];
1135 if(m_gapAngleOpen[i] > m_gapAngleClose[i]) {
1143 mAlloc(m_geometryChange, m_noLevelSetsUsedForMb,
"geometryChange",
false, AT_);
1145 MBool anychange =
false;
1146 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
1147 m_geometryChange[set] =
1148 Context::getSolverProperty<MBool>(
"LsGeometryChange", m_solverId, AT_, &m_geometryChange[set], set);
1149 if(m_geometryChange[set]) anychange =
true;
1154 ASSERT(m_geometryChange ==
nullptr,
"");
1158 m_dynamicStencil =
false;
1159 m_dynamicStencil = Context::getSolverProperty<MBool>(
"dynamicStencil", m_solverId, AT_, &m_dynamicStencil);
1161 m_reComputedBndry =
true;
1165 if(m_hasExternalSource ) {
1166 mAlloc(m_externalSourceDt1, maxNoGridCells(), CV->noVariables,
"m_externalForces", 0.0, AT_);
1167 m_log <<
"Allocated memory for old external sources." << endl;
1170 if(grid().azimuthalPeriodicity()) {
1171 m_noFloatDataBalance = 3 + CV->noVariables;
1172 m_noFloatDataAdaptation = 3;
1174 m_noLongDataBalance = 3;
1177 if(calcSlopesAfterStep())
mTerm(1, AT_,
"calcSlopesAfterStep not implemented for FvMb");
1185template <MInt nDim,
class SysEqn>
1210 if(m_motionEquation > 1) {
1241 mAlloc(m_bodyTerminalVelocity, nDim,
"m_bodyTerminalVelocity", F0, AT_);
1243 mAlloc(m_bodyCenter, nDim * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyCenter", F0, AT_);
1244 mAlloc(m_bodyVolume, m_noEmbeddedBodies,
"m_bodyVolume", F0, AT_);
1245 mAlloc(m_bodyMass, m_noEmbeddedBodies,
"m_bodyMass", F0, AT_);
1246 mAlloc(m_projectedArea, m_noEmbeddedBodies,
"m_projectedArea", F0, AT_);
1247 mAlloc(m_bodyRadii, 3 * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyRadii", F0, AT_);
1248 mAlloc(m_bodyRadius, m_maxNoEmbeddedBodiesPeriodic,
"m_bodyRadius", F0, AT_);
1249 mAlloc(m_bodyDiameter, m_maxNoEmbeddedBodiesPeriodic,
"m_bodyDiameter", F0, AT_);
1250 mAlloc(m_bodyVelocity, nDim * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyVelocity", F0, AT_);
1251 mAlloc(m_bodyAcceleration, nDim * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyAcceleration", F0, AT_);
1252 mAlloc(m_bodyAngularVelocity, 3 * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyAngularVelocity", F0, AT_);
1253 mAlloc(m_bodyAngularVelocityDt1, 3 * m_noEmbeddedBodies,
"m_bodyAngularVelocityDt1", F0, AT_);
1254 mAlloc(m_bodyTorque, 3 * m_noEmbeddedBodies,
" m_bodyTorque", F0, AT_);
1255 mAlloc(m_bodyTorqueDt1, 3 * m_noEmbeddedBodies,
"m_bodyTorqueDt1", F0, AT_);
1256 mAlloc(m_bodyQuaternion, 4 * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyQuaternion", F0, AT_);
1257 mAlloc(m_bodyQuaternionDt1, 4 * m_noEmbeddedBodies,
"m_bodyQuaternionDt1", F0, AT_);
1258 mAlloc(m_bodyAngularAcceleration, 3 * m_maxNoEmbeddedBodiesPeriodic,
"m_bodyAngularAcceleration", F0, AT_);
1259 mAlloc(m_bodyAngularAccelerationDt1, 3 * m_noEmbeddedBodies,
"m_bodyAngularAccelerationDt1", F0, AT_);
1260 mAlloc(m_bodyDensity, m_noEmbeddedBodies,
"m_bodyDensity", F0, AT_);
1261 mAlloc(m_bodyMomentOfInertia, 3 * m_noEmbeddedBodies,
"m_bodyMomentOfInertia", F0, AT_);
1262 mAlloc(m_bodyAccelerationDt1, nDim * m_noEmbeddedBodies,
"m_bodyAccelerationDt1", F0, AT_);
1263 mAlloc(m_bodyVelocityDt1, nDim * m_noEmbeddedBodies,
"m_bodyVelocityDt1", F0, AT_);
1264 mAlloc(m_bodyCenterDt1, nDim * m_noEmbeddedBodies,
"m_bodyCenterDt1", F0, AT_);
1266 if(m_motionEquation > 1) {
1267 mAlloc(m_bodyAccelerationDt2, nDim * m_noEmbeddedBodies,
"m_bodyAccelerationDt2", F0, AT_);
1268 mAlloc(m_bodyAccelerationDt3, nDim * m_noEmbeddedBodies,
"m_bodyAccelerationDt3", F0, AT_);
1269 mAlloc(m_bodyVelocityDt2, nDim * m_noEmbeddedBodies,
"m_bodyVelocityDt2", F0, AT_);
1270 mAlloc(m_bodyCenterDt2, nDim * m_noEmbeddedBodies,
"m_bodyCenterDt2", F0, AT_);
1271 mAlloc(m_bodyReducedVelocity, m_noEmbeddedBodies,
"m_bodyReducedVelocity", F0, AT_);
1272 mAlloc(m_bodyReducedFrequency, m_noEmbeddedBodies,
"m_bodyReducedFrequency", F0, AT_);
1273 mAlloc(m_bodyReducedMass, m_noEmbeddedBodies,
"m_bodyReducedMass", F0, AT_);
1274 mAlloc(m_bodyDampingCoefficient, m_noEmbeddedBodies,
"m_bodyDampingCoefficient", F0, AT_);
1275 mAlloc(m_bodyNeutralCenter, nDim * m_noEmbeddedBodies,
"m_bodyNeutralCenter", F0, AT_);
1278 mAlloc(m_bodyTemperature, m_noEmbeddedBodies,
"m_bodyTemperature", F1, AT_);
1279 mAlloc(m_bodyTemperatureDt1, m_noEmbeddedBodies,
"m_bodyTemperatureDt1", F1, AT_);
1280 mAlloc(m_bodyEquation, m_noEmbeddedBodies,
"m_bodyEquation", -1, AT_);
1281 mAlloc(m_bodyInCollision, m_noEmbeddedBodies,
"m_bodyInCollision", 0, AT_);
1282 mAlloc(m_periodicGhostBodies, m_noEmbeddedBodies,
"m_periodicGhostBodies", AT_);
1283 mAlloc(m_internalBodyId, m_maxNoEmbeddedBodiesPeriodic,
"m_internalBodyId", -1, AT_);
1284 mAlloc(m_bodyNearDomain, m_maxNoEmbeddedBodiesPeriodic,
"m_bodyNearDomain",
true, AT_);
1285 mAlloc(m_fixedBodyComponents, nDim,
"m_fixedBodyComponents", 0, AT_);
1286 mAlloc(m_fixedBodyComponentsRotation, 3,
"m_fixedBodyComponentsRotation", 0, AT_);
1288 mAlloc(m_bodyForce, nDim * m_noEmbeddedBodies,
"m_bodyForce", F0, AT_);
1289 mAlloc(m_bodyForceDt1, nDim * m_noEmbeddedBodies,
"m_bodyForceDt1", F0, AT_);
1290 mAlloc(m_bodyHeatFlux, m_noEmbeddedBodies,
"m_bodyHeatFlux", F0, AT_);
1291 mAlloc(m_hydroForce, nDim * m_noEmbeddedBodies,
"m_hydroForce", F0, AT_);
1299template <MInt nDim,
class SysEqn>
1303 constructGField(
false);
1305 std::vector<MInt>().swap(m_bndryLayerCells);
1306 set<MInt> rebuildCells;
1307 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
1308 if(a_bndryId(cellId) < -1)
continue;
1310 ASSERT(!a_isBndryGhostCell(cellId),
"");
1312 if(c_noChildren(cellId) > 0) {
1313 ASSERT(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel),
"Non leaf cell is on current mg level!");
1314 a_hasProperty(cellId, SolverCell::NearWall) =
false;
1317 MBool oldStatus = a_hasProperty(cellId, SolverCell::NearWall);
1319 ASSERT(a_level(cellId) > -1 && a_level(cellId) <= maxRefinementLevel(),
1320 "unexpected cell level " << a_level(cellId) <<
" for cell " << cellId << endl);
1322 if((a_level(cellId) >= m_lsCutCellMinLevel)
1323 && a_levelSetValuesMb(cellId, 0) > m_maxBndryLayerDistances[a_level(cellId)][0]
1324 && a_levelSetValuesMb(cellId, 0) < m_maxBndryLayerDistances[a_level(cellId)][1] && c_isLeafCell(cellId)) {
1325 m_bndryLayerCells.push_back(cellId);
1326 a_hasProperty(cellId, SolverCell::NearWall) =
true;
1328 a_hasProperty(cellId, SolverCell::NearWall) =
false;
1330 if(a_levelSetValuesMb(cellId, 0) < F0) {
1331 a_hasProperty(cellId, SolverCell::IsInactive) =
true;
1332 a_hasProperty(cellId, SolverCell::IsActive) =
false;
1333 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
false;
1335 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
1336 if(c_isLeafCell(cellId)) {
1337 a_hasProperty(cellId, SolverCell::IsActive) =
true;
1338 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
1340 if(oldStatus && (!a_hasProperty(cellId, SolverCell::NearWall))
1341 && !a_hasProperty(cellId, SolverCell::IsNotGradient)) {
1342 a_hasProperty(cellId, SolverCell::IsFlux) =
true;
1343 rebuildCells.insert(cellId);
1349 m_fvBndryCnd->correctCellCoordinates();
1350 for(
auto it = rebuildCells.begin(); it != rebuildCells.end(); ++it) {
1351 rebuildReconstructionConstants(*it);
1353 rebuildCells.clear();
1354 m_fvBndryCnd->recorrectCellCoordinates();
1368template <MInt nDim,
class SysEqn>
1370 const MInt bodyCnt) {
1371 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
1372 a_associatedBodyIds(cellId, set) = -1;
1373 a_levelSetValuesMb(cellId, set) = m_bodyDistThreshold + 1e-14;
1376 for(
MInt b = 0;
b < bodyCnt;
b++) {
1377 const MInt k = bodyIds[
b];
1378 const MInt set = m_bodyToSetTable[k];
1381 if(fabs(
dist) < fabs(a_levelSetValuesMb(cellId, set)) || (
dist < F0)) {
1382 a_levelSetValuesMb(cellId, set) =
dist;
1383 a_associatedBodyIds(cellId, set) = k;
1387 if(m_startSet > 0) {
1388 a_levelSetValuesMb(cellId, 0) = a_levelSetValuesMb(cellId, m_startSet);
1389 a_associatedBodyIds(cellId, 0) = a_associatedBodyIds(cellId, m_startSet);
1390 for(
MInt i = (m_startSet + 1); i < m_noSets; i++) {
1391 if(a_levelSetValuesMb(cellId, i) < a_levelSetValuesMb(
1393 a_levelSetValuesMb(cellId, 0) = a_levelSetValuesMb(cellId, i);
1394 a_associatedBodyIds(cellId, 0) = a_associatedBodyIds(cellId, i);
1399 for(
MInt child = 0; child < m_noCellNodes; child++) {
1400 if(c_childId(cellId, child) < 0)
continue;
1401 descendLevelSetValue(c_childId(cellId, child), bodyIds, bodyCnt);
1410template <MInt nDim,
class SysEqn>
1414 MInt*
const nearBodies = &nearestBodies[cellId * m_maxNearestBodies];
1415 MFloat*
const nearDist = &nearestDist[cellId * m_maxNearestBodies];
1417 for(
MInt b = 0;
b < bodyCnt;
b++) {
1418 const MInt k = bodyIds[
b];
1421 for(
MInt n = 0; n < m_maxNearestBodies; n++) {
1422 if(fabs(
dist) < fabs(nearDist[n])) {
1423 if(n < m_maxNearestBodies - 1) {
1424 std::rotate(nearBodies + n, nearBodies + m_maxNearestBodies - 1, nearBodies + m_maxNearestBodies);
1425 std::rotate(nearDist + n, nearDist + m_maxNearestBodies - 1, nearDist + m_maxNearestBodies);
1434 for(
MInt child = 0; child < m_noCellNodes; child++) {
1435 if(c_childId(cellId, child) < 0)
continue;
1436 descendDistance(c_childId(cellId, child), bodyIds, bodyCnt, nearestBodies, nearestDist);
1445template <MInt nDim,
class SysEqn>
1450 m_noFlowCells = a_noCells();
1451 m_noSurfaces = a_noSurfaces();
1452 m_noBndryCells = m_fvBndryCnd->m_bndryCells->size();
1455 const MInt noAllCells = a_noCells();
1457 m_noActiveCells = 0;
1458 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
1459 if(a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
1460 m_activeCellIds[m_noActiveCells] = cellId;
1465 m_noActiveHaloCellOffset = m_noActiveCells;
1466 for(
MInt cellId = noInternalCells(); cellId < noAllCells; cellId++) {
1467 if(a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
1468 m_activeCellIds[m_noActiveCells] = cellId;
1482template <MInt nDim,
class SysEqn>
1486 MInt noCells_solver = m_cells.size();
1487 MInt noCells_grid = c_noCells();
1488 MInt nosplitchilds = m_totalnosplitchilds;
1489 MInt nosurfaces = m_noSurfaces;
1490 MInt noboundarycells = m_noBndryCells;
1491 MInt nolsmbcells = m_noLsMbBndryCells;
1494 MPI_Allreduce(MPI_IN_PLACE, &noCells_solver, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE ",
1496 MPI_Allreduce(MPI_IN_PLACE, &noCells_grid, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE ",
"noCells_grid");
1497 MPI_Allreduce(MPI_IN_PLACE, &nosplitchilds, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE ",
"nosplitchilds");
1498 MPI_Allreduce(MPI_IN_PLACE, &nosurfaces, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE ",
"nosurfaces");
1499 MPI_Allreduce(MPI_IN_PLACE, &noboundarycells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE ",
1501 MPI_Allreduce(MPI_IN_PLACE, &nolsmbcells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE ",
"nolsmbcells");
1503 m_log <<
"======================================================" << endl << endl;
1505 m_log << setfill(
' ');
1506 m_log <<
"number of grid-cells " << setw(7) << noCells_grid << endl;
1507 m_log <<
"number of fv-cells " << setw(7) << noCells_solver << endl;
1508 m_log <<
"number of splitchilds " << setw(7) << nosplitchilds << endl;
1509 m_log <<
"number of surfaces " << setw(7) << nosurfaces << endl;
1510 m_log <<
"number of boundary cells " << setw(7) << noboundarycells << endl;
1511 m_log <<
"number of moving boundary cells " << setw(7) << nolsmbcells << endl;
1512 m_log <<
"======================================================" << endl << endl;
1521template <MInt nDim,
class SysEqn>
1525 if(m_initialCondition == 465 && m_constructGField) setInfinityState();
1527 updateInfinityVariables();
1535template <MInt nDim,
class SysEqn>
1539 ASSERT(m_constructGField,
"");
1541 if(m_constructGField && m_bodyTypeMb > 0) {
1542 initBodyProperties();
1544 }
else if(m_bodyTypeMb != 0) {
1545 mTerm(1, AT_,
"Unknown body type.");
1554template <MInt nDim,
class SysEqn>
1558 std::vector<MInt>().swap(m_bndryLayerCells);
1559 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
1560 a_hasProperty(cellId, SolverCell::NearWall) =
false;
1562 if(a_bndryId(cellId) < -1)
continue;
1564 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
1565 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
1567 if(c_noChildren(cellId) > 0) {
1568 a_hasProperty(cellId, SolverCell::IsInactive) =
true;
1569 a_hasProperty(cellId, SolverCell::WasInactive) =
true;
1573 if(a_levelSetValuesMb(cellId, 0) > m_maxBndryLayerDistances[a_level(cellId)][0]
1574 && a_levelSetValuesMb(cellId, 0) < m_maxBndryLayerDistances[a_level(cellId)][1] && c_isLeafCell(cellId)) {
1575 m_bndryLayerCells.push_back(cellId);
1576 a_hasProperty(cellId, SolverCell::NearWall) =
true;
1579 if(a_levelSetValuesMb(cellId, 0) < F0 || !c_isLeafCell(cellId)) {
1580 a_hasProperty(cellId, SolverCell::IsInactive) =
true;
1581 a_hasProperty(cellId, SolverCell::WasInactive) =
true;
1582 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
false;
1596template <MInt nDim,
class SysEqn>
1600 if((mode < 0) && (!m_trackMovingBndry || globalTimeStep < m_trackMbStart || globalTimeStep > m_trackMbEnd)) {
1604 NEW_TIMER_GROUP_STATIC(t_initTimer,
"reInitSolutionStep");
1605 NEW_TIMER_STATIC(t_timertotal,
"reInitSolutionStep", t_initTimer);
1606 NEW_SUB_TIMER_STATIC(t_resetSolverMb,
"resetSolverMb", t_timertotal);
1607 NEW_SUB_TIMER_STATIC(t_trackBoundaryLayer,
"trackBoundaryLayer", t_timertotal);
1608 NEW_SUB_TIMER_STATIC(t_generateBndryCellsMb,
"generateBndryCellsMb", t_timertotal);
1609 NEW_SUB_TIMER_STATIC(t_imagePointRec,
"imagePointRec", t_timertotal);
1610 NEW_SUB_TIMER_STATIC(t_initBndEx,
"initBndEx", t_timertotal);
1611 NEW_SUB_TIMER_STATIC(t_massRedist,
"massRedist", t_timertotal);
1612 NEW_SUB_TIMER_STATIC(t_initSmallCells,
"initSmallCells", t_timertotal);
1613 NEW_SUB_TIMER_STATIC(t_generateSurfaces,
"generateSurfaces", t_timertotal);
1614 NEW_SUB_TIMER_STATIC(t_buildLeastSquaresStencil,
"buildLeastSquaresStencil", t_timertotal);
1615 NEW_SUB_TIMER_STATIC(t_finalize,
"finalize", t_timertotal);
1616 m_tCutGroupTotal = t_timertotal;
1617 m_tCutGroup = t_generateBndryCellsMb;
1618 RECORD_TIMER_START(t_timertotal);
1620 RECORD_TIMER_START(m_timers[Timers::ReinitSolu]);
1623 if(m_timeStepAdaptationStart > -1 && m_structureStep == 0) {
1627 m_reComputedBndry =
true;
1628 RECORD_TIMER_START(t_resetSolverMb);
1632 RECORD_TIMER_STOP(t_resetSolverMb);
1634 RECORD_TIMER_START(t_trackBoundaryLayer);
1635 setLevelSetMbCellProperties();
1636#if defined _MB_DEBUG_ || !defined NDEBUG
1639 RECORD_TIMER_STOP(t_trackBoundaryLayer);
1641 RECORD_TIMER_START(m_timers[Timers::BndryMb]);
1642 RECORD_TIMER_START(t_generateBndryCellsMb);
1643 generateBndryCellsMb(mode);
1644 RECORD_TIMER_STOP(t_generateBndryCellsMb);
1645 RECORD_TIMER_STOP(m_timers[Timers::BndryMb]);
1648 m_fvBndryCnd->initWMSurfaces();
1649 Base::initWMExchange();
1650 Base::exchangeWMVars();
1653#if defined _MB_DEBUG_ || !defined NDEBUG
1659 m_bndryGhostCellsOffset = a_noCells();
1660 m_initialSurfacesOffset = a_noSurfaces();
1693 m_fvBndryCnd->correctCellCoordinates();
1695 if((!m_levelSetMb || m_gapOpened) && mode < 1 && m_gapInitMethod == 0) {
1696 initializeEmergedCells();
1700 for(
MInt i = 0; i < a_noCells(); i++) {
1701 if((a_levelSetValuesMb(i, 0) > F0 || a_bndryId(i) > -1) && (c_noChildren(i) == 0)
1702 && ((!a_hasProperty(i, SolverCell::IsActive) && !a_isHalo(i))
1703 || ((!a_hasProperty(i, SolverCell::IsOnCurrentMGLevel) || a_hasProperty(i, SolverCell::IsInactive))
1704 && !a_hasProperty(i, SolverCell::IsNotGradient)))) {
1705 cerr << domainId() <<
": " << i <<
" " << c_globalId(i) <<
" /b " << a_bndryId(i) <<
" /l "
1706 << a_levelSetValuesMb(i, 0) <<
" /i " << a_hasProperty(i, SolverCell::IsInactive) <<
" /p15 " << a_isHalo(i)
1707 <<
" /p7 " << a_hasProperty(i, SolverCell::IsNotGradient) <<
" /p10 " << a_hasProperty(i, SolverCell::IsFlux)
1708 <<
" /p11 " << a_hasProperty(i, SolverCell::IsActive) <<
" /p13 "
1709 << a_hasProperty(i, SolverCell::IsOnCurrentMGLevel) << endl;
1710 mTerm(1, AT_,
"Invalid cell flag.");
1715 if(m_fvBndryCnd->m_cellMerging) {
1717 if(m_fvBndryCnd->m_multipleGhostCells) {
1718 m_fvBndryCnd->detectSmallBndryCellsMGC();
1720 m_fvBndryCnd->detectSmallBndryCells();
1722 if(m_fvBndryCnd->m_multipleGhostCells) {
1723 m_fvBndryCnd->mergeCellsMGC();
1725 m_fvBndryCnd->mergeCells();
1729 m_log <<
" found " << m_fvBndryCnd->m_smallBndryCells->size() <<
"small cells." << endl;
1731 RECORD_TIMER_START(m_timers[Timers::NearBndry]);
1732 RECORD_TIMER_START(t_initBndEx);
1733 m_fvBndryCnd->setNearBoundaryRecNghbrs(m_movingBndryCndId);
1734 if(grid().azimuthalPeriodicity()) {
1735 updateAzimuthalMaxLevelRecCoords();
1736 updateAzimuthalNearBoundaryExchange();
1737 buildAdditionalAzimuthalReconstructionStencil(1);
1738 if(mode == 0) initAzimuthalCartesianHaloInterpolation();
1740 initNearBoundaryExchange(1, m_noOuterBndryCells);
1742 RECORD_TIMER_STOP(m_timers[Timers::NearBndry]);
1743 RECORD_TIMER_STOP(t_initBndEx);
1744 RECORD_TIMER_START(t_massRedist);
1747 std::vector<MInt>().swap(m_massRedistributionIds);
1748 std::vector<MFloat>().swap(m_massRedistributionVariables);
1749 std::vector<MFloat>().swap(m_massRedistributionRhs);
1750 std::vector<MFloat>().swap(m_massRedistributionVolume);
1751 std::vector<MFloat>().swap(m_massRedistributionSweptVol);
1752 std::vector<std::tuple<MInt, MInt, MInt>>().swap(m_temporarilyLinkedCells);
1758 RECORD_TIMER_STOP(t_massRedist);
1760 RECORD_TIMER_START(t_imagePointRec);
1761 m_fvBndryCnd->computeImagePointRecConst(m_movingBndryCndId);
1762 RECORD_TIMER_STOP(t_imagePointRec);
1764 RECORD_TIMER_START(m_timers[Timers::InitSmallCorr]);
1765 RECORD_TIMER_START(t_initSmallCells);
1766 if(m_fvBndryCnd->m_smallCellRHSCorrection) {
1767 m_fvBndryCnd->initSmallCellRHSCorrection(m_movingBndryCndId);
1769 m_fvBndryCnd->initSmallCellCorrection(m_movingBndryCndId);
1771 RECORD_TIMER_STOP(t_initSmallCells);
1772 RECORD_TIMER_STOP(m_timers[Timers::InitSmallCorr]);
1776 if(m_levelSet && m_closeGaps) {
1777 for(
MInt region = 0; region < m_noGapRegions; region++) {
1778 if(m_gapState[region] != -2)
continue;
1779 for(
MInt srfcId = 0; srfcId < a_noSurfaces(); srfcId++) {
1780 MInt nghbrId0 = a_surfaceNghbrCellId(srfcId, 0);
1781 MInt nghbrId1 = a_surfaceNghbrCellId(srfcId, 1);
1782 if(nghbrId0 <= 0 || nghbrId1 <= 0)
continue;
1783 if(a_isGapCell(nghbrId0) && a_isGapCell(nghbrId1) && a_hasProperty(nghbrId0, SolverCell::IsInactive)
1784 && a_hasProperty(nghbrId1, SolverCell::IsInactive)) {
1785 ASSERT(!a_hasProperty(nghbrId0, SolverCell::WasInactive) && !a_hasProperty(nghbrId1, SolverCell::WasInactive),
1788 ASSERT(a_levelSetValuesMb(nghbrId0, 0) < 0 && a_levelSetValuesMb(nghbrId1, 0) < 0,
"");
1790 ASSERT(m_gapInitMethod == 0,
"This should have already been done in gapHandling! ");
1791 deleteSurface(srfcId);
1793 cerr <<
"Deleting Gap-shadowed surfaces in region " << region <<
" due to Gap-Closure at timestep "
1795 cerr <<
" Of Cells: " << c_globalId(nghbrId0) <<
" and " << c_globalId(nghbrId1) << endl;
1801 RECORD_TIMER_START(m_timers[Timers::GhostCells]);
1802 RECORD_TIMER_START(t_generateSurfaces);
1806#if defined _MB_DEBUG_ || !defined NDEBUG
1807 for(
MInt srfcId = 0; srfcId < a_noSurfaces(); srfcId++) {
1808 MInt nghbrId0 = a_surfaceNghbrCellId(srfcId, 0);
1809 MInt nghbrId1 = a_surfaceNghbrCellId(srfcId, 1);
1810 ASSERT(nghbrId0 > -1 && nghbrId1 > -1,
"");
1811 if(a_hasProperty(nghbrId0, SolverCell::IsInactive) || a_hasProperty(nghbrId1, SolverCell::IsInactive)) {
1812 cerr <<
"p15/p7: " << a_isHalo(nghbrId0) <<
" " << a_isHalo(nghbrId1) <<
" / " << nghbrId0 <<
" " << nghbrId1
1813 <<
" / " << c_globalId(nghbrId0) <<
" " << c_globalId(nghbrId1) <<
" / "
1814 << a_hasProperty(nghbrId0, SolverCell::IsNotGradient) <<
" "
1815 << a_hasProperty(nghbrId1, SolverCell::IsNotGradient) <<
" / " << a_isGapCell(nghbrId0) <<
" "
1816 << a_isGapCell(nghbrId1) <<
" / " << a_hasProperty(nghbrId0, SolverCell::IsInactive) <<
" "
1817 << a_hasProperty(nghbrId1, SolverCell::IsInactive) << endl;
1818 cerr <<
"ls: " << a_levelSetValuesMb(nghbrId0, 0) <<
" " << a_levelSetValuesMb(nghbrId1, 0) << endl;
1819 cerr <<
"coord " << a_coordinate(nghbrId0, 0) <<
" " << a_coordinate(nghbrId0, 1) <<
" "
1820 << a_coordinate(nghbrId0, 2) << endl;
1822 ASSERT(!a_hasProperty(nghbrId0, SolverCell::IsInactive) && !a_hasProperty(nghbrId1, SolverCell::IsInactive),
1823 to_string(srfcId) <<
" " << to_string(nghbrId0) <<
" " << to_string(nghbrId1) <<
" "
1824 << to_string(a_noCells()) <<
" " << to_string(c_globalId(nghbrId0)) <<
" "
1825 << to_string(c_globalId(nghbrId1)));
1831 const MInt noBnd = m_fvBndryCnd->m_bndryCells->size();
1832 m_fvBndryCnd->m_bndryCells->resetSize(m_noOuterBndryCells);
1833 m_initialSurfacesOffset = a_noSurfaces();
1834 setOuterBoundaryGhostCells();
1835 setOuterBoundarySurfaces();
1836 m_fvBndryCnd->m_bndryCells->resetSize(noBnd);
1839 computeGhostCellsMb();
1840 addBoundarySurfacesMb();
1841 RECORD_TIMER_STOP(t_generateSurfaces);
1842 RECORD_TIMER_STOP(m_timers[Timers::GhostCells]);
1844 RECORD_TIMER_START(t_buildLeastSquaresStencil);
1845 buildAdditionalReconstructionStencil();
1846 RECORD_TIMER_STOP(t_buildLeastSquaresStencil);
1848 if(grid().azimuthalPeriodicity()) {
1849 buildAdditionalAzimuthalReconstructionStencil(0);
1850 initAzimuthalLinkedHaloExc();
1851 if(mode == 0 || m_wasBalanced) {
1852 m_wasBalanced =
false;
1888 RECORD_TIMER_START(t_finalize);
1889 if(m_fvBndryCnd->m_cellMerging) {
1890 m_fvBndryCnd->computePlaneVectors();
1895 const MInt xdim = a_noCells();
1897 MInt errorFlag =
false;
1898 for(
MInt cellId = xdim; cellId--;) {
1899 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
1900 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
1901 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
1902 if(a_isPeriodic(cellId))
continue;
1903 if(a_isBndryGhostCell(cellId))
continue;
1904 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
1905 if(a_isHalo(cellId) && a_level(cellId) < maxRefinementLevel())
continue;
1906 if(a_isHalo(cellId))
continue;
1907 if(a_isHalo(cellId) && a_bndryId(cellId) > -1 && a_bndryId(cellId) < m_noOuterBndryCells)
continue;
1909 if(a_isHalo(cellId) && a_level(cellId) == maxRefinementLevel()) {
1910 for(
MInt dir = 0; dir < m_noDirs; dir++) {
1911 if(a_hasNeighbor(cellId, dir) > 0) {
1912 MInt nghbrId = c_neighborId(cellId, dir);
1913 if(a_hasProperty(nghbrId, SolverCell::IsNotGradient)) skip =
true;
1922 const MFloat sign[2] = {-F1, F1};
1923 for(
MInt k = 0; k < nDim; k++)
1925 MBool hasBndrySurface =
false;
1926 for(
MInt dir = 0; dir < m_noDirs; dir++) {
1928 if(m_cellSurfaceMapping[cellId][dir] > -1) {
1929 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
1933 if(a_surfaceNghbrCellId(srfcId, 0) == cellId)
1935 else if(a_surfaceNghbrCellId(srfcId, 1) == cellId)
1937 if(
id < 0)
continue;
1938 test[a_surfaceOrientation(srfcId)] += sign[
id] * a_surfaceArea(srfcId);
1939 area[dir] = a_surfaceArea(srfcId);
1941 }
else if(a_hasNeighbor(cellId, dir) > 0) {
1942 MInt nghbrId = c_neighborId(cellId, dir);
1943 if(c_noChildren(nghbrId) > 0) {
1944 for(
MInt child = 0; child < m_noCellNodes; child++) {
1945 if(!childCode[dir][child])
continue;
1946 MInt childId = c_childId(nghbrId, child);
1947 if(childId < 0)
continue;
1948 if(m_cellSurfaceMapping[childId][
m_revDir[dir]] > -1) {
1949 if(a_surfaceNghbrCellId(m_cellSurfaceMapping[childId][
m_revDir[dir]], m_nghbrCellIds[
m_revDir[dir] % 2) == cellId) {
1950 MInt srfcId = m_cellSurfaceMapping[childId][
m_revDir[dir]];
1954 if(a_surfaceNghbrCellId(srfcId, 0) == cellId)
1956 else if(a_surfaceNghbrCellId(srfcId, 1) == cellId)
1958 if(
id < 0)
continue;
1959 test[a_surfaceOrientation(srfcId)] += sign[
id] * a_surfaceArea(srfcId);
1960 area[dir] = a_surfaceArea(srfcId);
1965 }
else if(a_hasProperty(cellId, SolverCell::HasSplitFace)) {
1966 for(
MInt srfcId = a_noSurfaces(); srfcId--;) {
1968 if(a_surfaceBndryCndId(srfcId) > -1)
continue;
1970 if(a_surfaceNghbrCellId(srfcId, 0) == cellId && dir == 2 * a_surfaceOrientation(srfcId) + 1)
1972 else if(a_surfaceNghbrCellId(srfcId, 1) == cellId && dir == 2 * a_surfaceOrientation(srfcId))
1975 test[a_surfaceOrientation(srfcId)] += sign[
id] * a_surfaceArea(srfcId);
1976 area[dir] = a_surfaceArea(srfcId);
1982 if(a_bndryId(cellId) > -1) {
1983 for(
MInt bs = 0; bs < m_fvBndryCnd->m_noBoundarySurfaces; bs++) {
1984 MInt srfcId = m_fvBndryCnd->m_boundarySurfaces[bs];
1988 if(a_surfaceNghbrCellId(srfcId, 0) == cellId)
1990 else if(a_surfaceNghbrCellId(srfcId, 1) == cellId)
1992 if(
id < 0)
continue;
1993 hasBndrySurface =
true;
1994 test[a_surfaceOrientation(srfcId)] += sign[
id] * a_surfaceArea(srfcId);
1998 MBool testPassed =
true;
1999 for(
MInt k = 0; k < nDim; k++) {
2000 if(fabs(test[k]) > EPS * m_gridCellArea[a_level(cellId)]) {
2006 for(
MInt k = 0; k < nDim; k++) {
2007 cerr << domainId() <<
" " << nDim <<
": cell " << cellId <<
" " << a_bndryId(cellId) <<
" "
2008 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << (a_bndryId(cellId) < m_noOuterBndryCells)
2009 <<
" / " << hasBndrySurface <<
" " << a_isHalo(cellId) <<
" "
2010 << a_hasProperty(cellId, SolverCell::IsNotGradient) <<
" / " << k <<
" " << fabs(test[k]) << endl;
2012 cerr <<
"Cell surface is not closed. Check the surfaces! " << domainId() <<
" " << cellId <<
" "
2013 << a_bndryId(cellId) <<
" " << a_isHalo(cellId) <<
" " << a_level(cellId) <<
" "
2014 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << a_hasProperty(cellId, SolverCell::IsSplitCell)
2015 <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild) <<
" "
2016 << a_hasProperty(cellId, SolverCell::HasSplitFace) << endl;
2017 m_log <<
"Cell surface is not closed. Check the surfaces! " << domainId() <<
" " << cellId <<
" "
2018 << a_bndryId(cellId) <<
" " << a_isHalo(cellId) <<
" " << a_level(cellId) << endl;
2019 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
2020 cerr << m_cellSurfaceMapping[cellId][dir2] <<
"(";
2021 MInt nghbrId = (a_hasNeighbor(cellId, dir2) > 0) ? c_neighborId(cellId, dir2) : -1;
2022 MInt state = (nghbrId > -1) ? a_hasProperty(nghbrId, SolverCell::IsInactive) : -1;
2023 cerr << nghbrId <<
"/" << state <<
") ";
2030 const MInt xdim0 = a_noCells();
2031 for(
MInt i = xdim0; i--;) {
2032 if(a_hasProperty(i, SolverCell::IsCutOff))
continue;
2033 if(a_hasProperty(i, SolverCell::IsNotGradient))
continue;
2034 if(a_isBndryGhostCell(i))
continue;
2035 if(a_hasProperty(i, SolverCell::IsInactive))
continue;
2036 ASSERT((a_noReconstructionNeighbors(i) == 0 || c_noChildren(i) == 0),
"No reconstruction nghbrs expected");
2037 if(c_noChildren(i) > 0)
continue;
2038 MBool localError =
false;
2039 for(
MInt n = a_noReconstructionNeighbors(i); n--;) {
2040 if((a_bndryId(a_reconstructionNeighborId(i, n)) > -2)
2041 && (a_isBndryGhostCell(a_reconstructionNeighborId(i, n))
2042 || a_hasProperty(a_reconstructionNeighborId(i, n), SolverCell::IsInactive)
2043 || !a_hasProperty(a_reconstructionNeighborId(i, n), SolverCell::IsOnCurrentMGLevel))) {
2044 cerr << domainId() <<
": Inactive cell used in least squares reconstruction!!!!" << i <<
" " << n <<
"/"
2045 << a_noReconstructionNeighbors(i) <<
" / " << a_reconstructionNeighborId(i, n) <<
" " << a_isHalo(i) <<
" "
2046 << a_isBndryGhostCell(i) <<
" /l " << a_level(i) <<
" " << a_level(a_reconstructionNeighborId(i, n))
2047 <<
" / " << a_hasProperty(i, SolverCell::IsInactive) <<
" " << a_bndryId(i) <<
" /c "
2048 << a_coordinate(a_reconstructionNeighborId(i, n), 0) <<
" "
2049 << a_coordinate(a_reconstructionNeighborId(i, n), 1) <<
" " << a_coordinate(i, 0) <<
" "
2050 << a_coordinate(i, 1) <<
" / "
2051 << a_hasProperty(a_reconstructionNeighborId(i, n), SolverCell::IsOnCurrentMGLevel) <<
" "
2052 << a_isHalo(a_reconstructionNeighborId(i, n)) <<
" "
2053 << a_hasProperty(a_reconstructionNeighborId(i, n), SolverCell::IsNotGradient) <<
" "
2054 << a_isBndryGhostCell(a_reconstructionNeighborId(i, n)) <<
" "
2055 << a_hasProperty(a_reconstructionNeighborId(i, n), SolverCell::IsInactive) <<
" "
2056 << a_bndryId(a_reconstructionNeighborId(i, n)) << endl;
2062 for(
MInt n = 0; n < a_noReconstructionNeighbors(i); n++) {
2063 m_log << a_reconstructionNeighborId(i, n) <<
" ";
2070 cerr << domainId() <<
": Error in reInitSolutionStep" << endl;
2071 m_log <<
"Error in reInitSolutionStep" << endl;
2074 MPI_Allreduce(MPI_IN_PLACE, &errorFlag, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"errorFlag");
2077 cerr <<
"Error in reInitSolutionStep" << endl;
2078 m_log <<
"Error in reInitSolutionStep" << endl;
2079 writeVtkErrorFile();
2086 MFloat* RESTRICT slope = (
MFloat*)(&(a_slope(0, 0, 0)));
2087 const MInt size = a_noCells() * m_slopeMemory *
sizeof(
MFloat);
2088 memset(&(slope[0]), 0, size);
2089 applyBoundaryConditionMb();
2090 leastSquaresReconstruction();
2091 applyBoundaryConditionMb();
2092 if(m_trackBodySurfaceData) computeBodySurfaceData();
2093 if(m_initialCondition == 15 || m_initialCondition == 16) {
2094 if(
globalTimeStep == 0 && mode == 1) computeFlowStatistics(
true);
2098 if(m_restart) m_restart =
false;
2103 for(
MInt srfcId = a_noSurfaces(); srfcId--;) {
2104 rhsTest[a_surfaceNghbrCellId(srfcId, 0)] += a_surfaceArea(srfcId);
2105 rhsTest[a_surfaceNghbrCellId(srfcId, 1)] -= a_surfaceArea(srfcId);
2108 for(
MInt i = a_noCells(); i--;) {
2109 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
2110 if(!a_hasProperty(i, SolverCell::IsOnCurrentMGLevel))
continue;
2111 if(a_isHalo(i))
continue;
2112 if(a_isBndryGhostCell(i))
continue;
2113 if(a_hasProperty(i, SolverCell::IsInactive))
continue;
2114 if(fabs(rhsTest[i]) > 1e-10) {
2115 cerr << domainId() <<
" Warning: cell may not be water tight " << i <<
" " << rhsTest[i] <<
" "
2116 << a_coordinate(i, 0) <<
" " << a_coordinate(i, 1) <<
" " << a_coordinate(i,
mMin(nDim - 1, 2)) << endl;
2142 RECORD_TIMER_STOP(m_timers[Timers::ReinitSolu]);
2143 RECORD_TIMER_STOP(t_finalize);
2144 RECORD_TIMER_STOP(t_timertotal);
2145 DISPLAY_TIMER_OFFSET(t_timertotal, m_restartInterval);
2153template <MInt nDim,
class SysEqn>
2155 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
2156 const MInt cellId = m_splitCells[sc];
2159 for(
MInt v = 0; v < m_noCVars; v++) {
2160 a_variable(cellId, v) = F0;
2163 for(
MInt v = 0; v < m_noFVars; v++) {
2164 a_rightHandSide(cellId, v) = F0;
2165 m_rhs0[cellId][v] = F0;
2168 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
2169 const MInt splitChildId = m_splitChilds[sc][ssc];
2170 for(
MInt v = 0; v < m_noCVars; v++) {
2171 a_variable(cellId, v) += a_cellVolume(splitChildId) * a_variable(splitChildId, v);
2174 for(
MInt v = 0; v < m_noFVars; v++) {
2175 a_rightHandSide(cellId, v) += a_rightHandSide(splitChildId, v);
2176 m_rhs0[cellId][v] += m_rhs0[splitChildId][v];
2178 volCnt += a_cellVolume(splitChildId);
2180 volCnt =
mMax(volCnt, m_eps);
2182 for(
MInt v = 0; v < m_noCVars; v++) {
2183 a_variable(cellId, v) /= volCnt;
2187 if(m_useCentralDifferencingSlopes) {
2188 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
2189 if(a_bndryId(cellId) != -1)
continue;
2190 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
2191 if(c_isLeafCell(cellId))
continue;
2193 if(a_level(cellId) == minLevel()) {
2194 reduceData(cellId, &a_pvariable(0, 0), m_noPVars);
2195 reduceData(cellId, &a_variable(0, 0), m_noCVars);
2206template <MInt nDim,
class SysEqn>
2210 applyBoundaryConditionMb();
2212 RECORD_TIMER_START(m_timers[Timers::MusclReconst]);
2213 leastSquaresReconstruction();
2214 RECORD_TIMER_STOP(m_timers[Timers::MusclReconst]);
2216 RECORD_TIMER_START(m_timers[Timers::MusclCopy]);
2217 m_fvBndryCnd->copySlopesToSmallCells();
2218 RECORD_TIMER_STOP(m_timers[Timers::MusclCopy]);
2220 RECORD_TIMER_START(m_timers[Timers::MusclGhostSlopes]);
2221 updateGhostCellSlopesInviscid();
2222 RECORD_TIMER_STOP(m_timers[Timers::MusclGhostSlopes]);
2224 RECORD_TIMER_START(m_timers[Timers::MusclCutSlopes]);
2225 m_fvBndryCnd->updateCutOffSlopesInviscid();
2226 RECORD_TIMER_STOP(m_timers[Timers::MusclCutSlopes]);
2228 RECORD_TIMER_START(m_timers[Timers::MusclReconstSrfc]);
2229 (this->*m_reconstructSurfaceData)(-1);
2230 RECORD_TIMER_STOP(m_timers[Timers::MusclReconstSrfc]);
2233 m_solutionDiverged =
false;
2234 for(
MInt srfcId = a_noSurfaces(); srfcId--;) {
2236 MInt nghbr0 = a_surfaceNghbrCellId(srfcId, 0);
2237 MInt nghbr1 = a_surfaceNghbrCellId(srfcId, 1);
2239 (a_bndryId(
mMin(nghbr0, nghbr1)) > -1)
2240 ? m_fvBndryCnd->m_bndryCells->a[a_bndryId(
mMin(nghbr0, nghbr1))].m_srfcVariables[0]->m_ghostCellId
2243 for(
MInt v = 0; v < m_noCVars; v++) {
2244 if(std::isnan(a_surfaceVariable(srfcId, 0, v)) || std::isnan(a_surfaceVariable(srfcId, 1, v))) divd =
true;
2246 if(a_surfaceVariable(srfcId, 0, PV->P) < F0 || a_surfaceVariable(srfcId, 1, PV->P) < F0
2247 || a_surfaceVariable(srfcId, 0, PV->RHO) < F0 || a_surfaceVariable(srfcId, 1, PV->RHO) < F0)
2250 cerr << domainId() <<
": surf var " <<
globalTimeStep <<
" " << srfcId <<
" " << c_globalId(nghbr0) <<
" "
2251 << c_globalId(nghbr1) <<
" /g " << ghost <<
" " << a_bndryId(nghbr0) <<
" " << a_bndryId(nghbr1) <<
" /bc "
2252 << a_surfaceBndryCndId(srfcId) <<
" /sp " << a_surfaceVariable(srfcId, 0, PV->P) <<
" "
2253 << a_surfaceVariable(srfcId, 1, PV->P) <<
" /vf "
2254 << a_cellVolume(nghbr0) / grid().gridCellVolume(a_level(nghbr0)) <<
" "
2255 << a_cellVolume(nghbr1) / grid().gridCellVolume(a_level(nghbr1)) <<
" /l " << a_level(nghbr0) <<
" "
2256 << a_level(nghbr1) <<
" /p15 " << a_isHalo(nghbr0) <<
" " << a_isHalo(nghbr1) <<
" /p7 "
2257 << a_hasProperty(nghbr0, SolverCell::IsNotGradient) <<
" "
2258 << a_hasProperty(nghbr1, SolverCell::IsNotGradient) <<
" /c " << a_surfaceCoordinate(srfcId, 0) <<
" "
2259 << a_surfaceCoordinate(srfcId, 1) <<
" " << a_surfaceCoordinate(srfcId,
mMin(nDim - 1, 2)) <<
" /pc "
2260 << a_pvariable(nghbr0, PV->P) <<
" " << a_pvariable(nghbr1, PV->P) <<
" /p "
2261 << a_surfaceVariable(srfcId, 0, PV->P) <<
" " << a_surfaceVariable(srfcId, 1, PV->P) <<
" /rho "
2262 << a_surfaceVariable(srfcId, 0, PV->RHO) <<
" " << a_surfaceVariable(srfcId, 1, PV->RHO) <<
" /sl "
2263 << a_slope(nghbr0, PV->U, a_surfaceOrientation(srfcId)) <<
" "
2264 << a_slope(nghbr1, PV->U, a_surfaceOrientation(srfcId)) <<
" /ls " << a_levelSetValuesMb(nghbr0, 0) <<
" "
2265 << a_levelSetValuesMb(nghbr1, 0) << endl;
2266 m_solutionDiverged =
true;
2270 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
2271 "m_solutionDiverged");
2272 if(m_solutionDiverged) {
2273 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
2276 "Solution diverged after surface value computation @ " + to_string(m_RKStep) +
"/"
2282 RECORD_TIMER_START(m_timers[Timers::MusclGhostSlopes]);
2283 updateGhostCellSlopesViscous();
2284 m_fvBndryCnd->updateCutOffSlopesViscous();
2285 RECORD_TIMER_STOP(m_timers[Timers::MusclGhostSlopes]);
2287 correctBoundarySurfaceVariablesMb();
2295template <MInt nDim,
class SysEqn>
2297 for(
MInt i = 0; i < nDim; i++) {
2298 m_bboxLocal[i] = std::numeric_limits<MFloat>::max();
2299 m_bboxLocal[nDim + i] = std::numeric_limits<MFloat>::lowest();
2302 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
2303 if(a_isPeriodic(cellId))
continue;
2305 for(
MInt i = 0; i < nDim; i++) {
2306 m_bboxLocal[i] =
mMin(m_bboxLocal[i], a_coordinate(cellId, i) - F1B2 * c_cellLengthAtCell(cellId));
2307 m_bboxLocal[nDim + i] =
mMax(m_bboxLocal[nDim + i], a_coordinate(cellId, i) + F1B2 * c_cellLengthAtCell(cellId));
2317template <MInt nDim,
class SysEqn>
2319 IF_CONSTEXPR(nDim == 3) {
2320 if(m_bodyTree !=
nullptr) {
2322 m_bodyTree =
nullptr;
2324 m_bodyCenters.clear();
2326 for(
MInt k = 0; k < (m_noEmbeddedBodies + m_noPeriodicGhostBodies); k++) {
2327 Point<3> a(m_bodyCenter[k * nDim], m_bodyCenter[k * nDim + 1], m_bodyCenter[k * nDim + 2], k);
2328 if(std::isnan(
a.x[0]) || std::isnan(
a.x[1]) || std::isnan(
a.x[2]) || std::isinf(
a.x[0]) || std::isinf(
a.x[1])
2329 || std::isinf(
a.x[2])) {
2330 mTerm(1,
"ERROR body center is NAN " + to_string(k) +
" " + to_string(
a.x[0]) +
" " + to_string(
a.x[1]) +
" "
2331 + to_string(
a.x[2]));
2333 m_bodyCenters.push_back(
a);
2336 if(m_bodyCenters.size() > 0) {
2337 m_bodyTree =
new KDtree<3>(m_bodyCenters);
2347template <MInt nDim,
class SysEqn>
2349 IF_CONSTEXPR(nDim == 3) {
2350 if(m_bodyTreeLocal !=
nullptr) {
2351 delete m_bodyTreeLocal;
2352 m_bodyTreeLocal =
nullptr;
2354 m_bodyCentersLocal.clear();
2356 for(
MInt k = 0; k < (m_noEmbeddedBodies + m_noPeriodicGhostBodies); k++) {
2357 if(!m_bodyNearDomain[k])
continue;
2358 Point<nDim> a(m_bodyCenter[k * nDim + 0], m_bodyCenter[k * nDim + 1], m_bodyCenter[k * nDim + 2], k);
2359 if(std::isnan(
a.x[0]) || std::isnan(
a.x[1]) || std::isnan(
a.x[2]) || std::isinf(
a.x[0]) || std::isinf(
a.x[1])
2360 || std::isinf(
a.x[2])) {
2361 mTerm(1,
"ERROR body center is NAN " + to_string(k) +
" " + to_string(
a.x[0]) +
" " + to_string(
a.x[1]) +
" "
2362 + to_string(
a.x[2]));
2364 m_bodyCentersLocal.push_back(
a);
2366 m_bodyTreeLocal =
new KDtree<nDim>(m_bodyCentersLocal);
2375template <MInt nDim,
class SysEqn>
2379 if(m_noEmbeddedBodies == 0) {
2380 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
2381 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
2382 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
2387 if(m_motionEquation == 0) {
2389 updateBodyProperties();
2391 createPeriodicGhostBodies();
2395 const MInt noBodies = m_noEmbeddedBodies + m_noPeriodicGhostBodies;
2396 if(m_noLevelSetsUsedForMb == 1) {
2397 for(
MInt k = 0; k < noBodies; k++) {
2398 m_bodyNearDomain[k] =
true;
2399 for(
MInt i = 0; i < nDim; i++) {
2400 if(m_bodyCenter[k * nDim + i] < m_bboxLocal[i] - (m_bodyDistThreshold + m_bodyRadius[k])) {
2401 m_bodyNearDomain[k] =
false;
2403 if(m_bodyCenter[k * nDim + i] > m_bboxLocal[nDim + i] + (m_bodyDistThreshold + m_bodyRadius[k])) {
2404 m_bodyNearDomain[k] =
false;
2410 if(!m_constructGField) {
2414 rebuildKDTreeLocal();
2416 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
2417 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
2420 constexpr MFloat safetyFac = 1.1;
2421 const MFloat uncertaintyAngle = sqrt(FD) * c_cellLengthAtLevel(minLevel());
2422 const MFloat uncertaintyRotation = m_maxBodyRadius;
2423 const MFloat minWallDist = F3 * c_cellLengthAtLevel(maxLevel());
2424 const MFloat delta1 = safetyFac * (uncertaintyAngle + uncertaintyRotation);
2425 const MFloat delta0 = delta1 + safetyFac * minWallDist;
2429 MFloat deltaMax = m_bodyDistThreshold + m_maxBodyRadius;
2430 bodyDist.
fill(deltaMax);
2433 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
2434 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
2435 a_associatedBodyIds(cellId, set) = -1;
2436 a_levelSetValuesMb(cellId, set) = m_bodyDistThreshold + 1e-14;
2440 for(
MInt i = 0; i < noMinCells(); i++) {
2441 MInt cellId = minCell(i);
2442 MFloat minDist = c_cellLengthAtLevel(0);
2443 MInt bodyCnt = noBodies;
2445 IF_CONSTEXPR(nDim == 3) {
2446 if(m_bodyTypeMb == 1 || m_bodyTypeMb == 3) {
2447 MBool overflow =
false;
2448 Point<nDim> pt(a_coordinate(cellId, 0), a_coordinate(cellId, 1), a_coordinate(cellId, 2));
2449 bodyCnt = m_bodyTreeLocal->locatenearest(pt, deltaMax, &bodyIds[0], &bodyDist[0], noBodies, overflow);
2451 for(
MInt k = 0; k < noBodies; k++) {
2457 for(
MInt k = 0; k < noBodies; k++) {
2463 for(
MInt k = 0; k < bodyCnt; k++) {
2465 IF_CONSTEXPR(nDim == 2) {
2466 dist = sqrt(
POW2(a_coordinate(cellId, 0) - m_bodyCenter[bodyIds[k] * nDim + 0])
2467 +
POW2(a_coordinate(cellId, 1) - m_bodyCenter[bodyIds[k] * nDim + 1]));
2469 IF_CONSTEXPR(nDim == 3) {
2470 dist = sqrt(
POW2(a_coordinate(cellId, 0) - m_bodyCenter[bodyIds[k] * nDim + 0])
2471 +
POW2(a_coordinate(cellId, 1) - m_bodyCenter[bodyIds[k] * nDim + 1])
2472 +
POW2(a_coordinate(cellId, 2) - m_bodyCenter[bodyIds[k] * nDim + 2]));
2474 if(
dist > delta0 &&
dist > minDist + delta1) {
2475 if(k < bodyCnt - 1) {
2476 bodyIds[k] = bodyIds[bodyCnt - 1];
2477 bodyDist[k] = bodyDist[bodyCnt - 1];
2485 if(bodyCnt > 0) descendLevelSetValue(cellId, &bodyIds[0], bodyCnt);
2487 MInt parentId = c_parentId(cellId);
2488 while(parentId > -1) {
2489 for(
MInt set = 0; set < m_noSets; set++) {
2490 a_levelSetValuesMb(c_parentId(cellId), set) = a_levelSetValuesMb(cellId, set);
2491 a_associatedBodyIds(parentId, set) = a_associatedBodyIds(cellId, set);
2493 parentId = c_parentId(parentId);
2503template <MInt nDim,
class SysEqn>
2508 if(!m_constructGField)
mTerm(1, AT_,
"m_constructGField not set.");
2509 if(m_noEmbeddedBodies == 0) {
2514 const MInt noBodies = m_noEmbeddedBodies + m_noPeriodicGhostBodies;
2519 constexpr MFloat safetyFac = 1.1;
2520 const MFloat deltaMax1 = safetyFac * (deltaMax + c_cellLengthAtLevel(minLevel()) + m_maxBodyRadius);
2521 bodyDist.
fill(deltaMax1);
2524 MInt maxBodyCnt = 0;
2525 for(
MInt i = 0; i < noMinCells(); i++) {
2526 MInt cellId = minCell(i);
2527 MInt bodyCnt = noBodies;
2528 IF_CONSTEXPR(nDim == 3) {
2529 if(m_bodyTypeMb == 1 || m_bodyTypeMb == 3) {
2530 MBool overflow =
false;
2531 Point<nDim> pt(a_coordinate(cellId, 0), a_coordinate(cellId, 1), a_coordinate(cellId, 2));
2532 if(deltaMax1 < m_bodyDistThreshold) {
2533 bodyCnt = m_bodyTreeLocal->locatenearest(pt, deltaMax1, &bodyIds[0], &bodyDist[0], noBodies, overflow);
2535 bodyCnt = m_bodyTree->locatenearest(pt, deltaMax1, &bodyIds[0], &bodyDist[0], noBodies, overflow);
2538 for(
MInt k = 0; k < noBodies; k++) {
2544 for(
MInt k = 0; k < noBodies; k++) {
2548 if(bodyCnt > 0) descendDistance(cellId, &bodyIds[0], bodyCnt, nearestBodies, nearestDist);
2549 maxBodyCnt =
mMax(maxBodyCnt, bodyCnt);
2551 MPI_Allreduce(MPI_IN_PLACE, &maxBodyCnt, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"maxBodyCnt");
2562template <MInt nDim,
class SysEqn>
2564 const MFloat FcellLength = F1 / c_cellLengthAtCell(cellId);
2565 normal[0] = numeric_limits<MFloat>::max();
2566 normal[1] = numeric_limits<MFloat>::max();
2567 IF_CONSTEXPR(nDim == 3) { normal[2] = numeric_limits<MFloat>::max(); }
2569 if(m_bodyTypeMb == 1) {
2570 getNormalSphere(cellId, set, normal);
2571 }
else if(m_bodyTypeMb == 3) {
2572 getNormalEllipsoid(cellId, set, normal);
2574 MInt cndId = (a_hasProperty(cellId, SolverCell::IsSplitChild))
2575 ? m_bndryCandidateIds[getAssociatedInternalCell(cellId)]
2576 : m_bndryCandidateIds[cellId];
2577 if(cndId < 0)
mTerm(1, AT_,
"candidate not found");
2578 for(
MInt node = 0; node < m_noCellNodes; node++) {
2579 if(!m_candidateNodeSet[cndId * m_noCellNodes + node])
mTerm(1, AT_,
"candidate node not set");
2581 IF_CONSTEXPR(nDim == 3) {
2582 normal[0] = F1B4 * FcellLength
2583 * (-m_candidateNodeValues[IDX_LSSETNODES(cndId, 0, set)]
2584 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 1, set)]
2585 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 2, set)]
2586 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 3, set)]
2587 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 4, set)]
2588 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 5, set)]
2589 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 6, set)]
2590 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 7, set)]);
2591 normal[1] = F1B4 * FcellLength
2592 * (-m_candidateNodeValues[IDX_LSSETNODES(cndId, 0, set)]
2593 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 1, set)]
2594 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 2, set)]
2595 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 3, set)]
2596 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 4, set)]
2597 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 5, set)]
2598 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 6, set)]
2599 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 7, set)]);
2600 normal[2] = F1B4 * FcellLength
2601 * (-m_candidateNodeValues[IDX_LSSETNODES(cndId, 0, set)]
2602 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 1, set)]
2603 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 2, set)]
2604 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 3, set)]
2605 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 4, set)]
2606 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 5, set)]
2607 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 6, set)]
2608 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 7, set)]);
2611 normal[0] = F1B4 * FcellLength
2612 * (-m_candidateNodeValues[IDX_LSSETNODES(cndId, 0, set)]
2613 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 1, set)]
2614 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 2, set)]
2615 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 3, set)]);
2616 normal[1] = F1B4 * FcellLength
2617 * (-m_candidateNodeValues[IDX_LSSETNODES(cndId, 0, set)]
2618 - m_candidateNodeValues[IDX_LSSETNODES(cndId, 1, set)]
2619 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 2, set)]
2620 + m_candidateNodeValues[IDX_LSSETNODES(cndId, 3, set)]);
2623 for(
MInt i = 0; i < nDim; i++) {
2624 sum +=
POW2(normal[i]);
2627 for(
MInt i = 0; i < nDim; i++) {
2638template <MInt nDim,
class SysEqn>
2640 const MInt bodyId = a_associatedBodyIds(cellId, set);
2641 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
2643 for(
MInt i = 0; i < nDim; i++) {
2647 for(
MInt i = 0; i < nDim; i++) {
2648 normal[i] = a_coordinate(cellId, i) - m_bodyCenter[nDim * bodyId + i];
2649 cnt +=
POW2(normal[i]);
2652 for(
MInt i = 0; i < nDim; i++) {
2662template <MInt nDim,
class SysEqn>
2664 const MInt bodyId = a_associatedBodyIds(cellId, set);
2665 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
2668 computeRotationMatrix(R, &(m_bodyQuaternion[4 * bodyId]));
2671 MFloat x = a_coordinate(cellId, 0) - m_bodyCenter[bodyId * nDim + 0];
2672 MFloat y = a_coordinate(cellId, 1) - m_bodyCenter[bodyId * nDim + 1];
2673 MFloat z = a_coordinate(cellId, 2) - m_bodyCenter[bodyId * nDim + 2];
2680 matrixVectorProduct(xb, R, xw);
2685 MFloat a = m_bodyRadii[bodyId * nDim + 0];
2686 MFloat b = m_bodyRadii[bodyId * nDim + 1];
2687 MFloat c = m_bodyRadii[bodyId * nDim + 2];
2691 MFloat xx[3] = {F0, F0, F0};
2694 distancePointEllipsoid(ee, yy, xx);
2698 for(
MInt i = 0; i < nDim; i++) {
2699 norm2[i] = F2 * xx[i] /
POW2(m_bodyRadii[bodyId * nDim + i]);
2700 n2sum +=
POW2(norm2[i]);
2702 n2sum = sqrt(n2sum);
2703 for(
MInt i = 0; i < nDim; i++) {
2707 matrixVectorProductTranspose(normal, R, norm2);
2715template <MInt nDim,
class SysEqn>
2719 if(m_bodyTypeMb == 1) {
2720 dist = getDistanceSphere(coordinates, bodyId);
2721 }
else if(m_bodyTypeMb == 2) {
2722 dist = getDistancePiston(coordinates, bodyId);
2723 }
else if(m_bodyTypeMb == 3) {
2724 dist = getDistanceEllipsoid(coordinates, bodyId);
2725 }
else if(m_bodyTypeMb == 7) {
2726 dist = getDistanceTetrahedron(coordinates, bodyId);
2728 mTerm(1, AT_,
"generalize here");
2739template <MInt nDim,
class SysEqn>
2741 return getDistance(&a_coordinate(cellId, 0), bodyId);
2749template <MInt nDim,
class SysEqn>
2751 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
2753 IF_CONSTEXPR(nDim == 2) {
2754 dist = sqrt(
POW2(coordinates[0] - m_bodyCenter[bodyId * nDim])
2755 +
POW2(coordinates[1] - m_bodyCenter[bodyId * nDim + 1]))
2756 - (m_bodyRadius[bodyId]);
2758 else IF_CONSTEXPR(nDim == 3) {
2760 sqrt(
POW2(coordinates[0] - m_bodyCenter[bodyId * nDim]) +
POW2(coordinates[1] - m_bodyCenter[bodyId * nDim + 1])
2761 +
POW2(coordinates[2] - m_bodyCenter[bodyId * nDim + 2]))
2762 - (m_bodyRadius[bodyId]);
2772template <MInt nDim,
class SysEqn>
2774 return getDistanceSphere(&a_coordinate(cellId, 0), bodyId);
2784template <MInt nDim,
class SysEqn>
2786 MFloat& h = m_static_getDistanceSplitSphere_h;
2787 MBool& first = m_static_getDistanceSplitSphere_first;
2789 MFloat h_default = m_bodyRadius[0] / 100;
2801 h = Context::getSolverProperty<MFloat>(
"splitSphereSlitHeight", m_solverId, AT_, &h_default);
2805 if(m_noEmbeddedBodies > 2)
mTerm(1, AT_,
"splitSphere does only work for one or two bodies");
2806 MFloat signCode[2] = {-F1, F1};
2808 MFloat x = a_coordinate(cellId, 0);
2809 MFloat y = a_coordinate(cellId, 1);
2810 MFloat r = sqrt(
POW2(a_coordinate(cellId, 0) - m_bodyCenter[0 * nDim])
2811 +
POW2(a_coordinate(cellId, 1) - m_bodyCenter[0 * nDim + 1]));
2813 const MInt k = bodyId;
2814 MFloat xIS = sqrt(m_bodyRadius[k] * m_bodyRadius[k] - yIS * yIS);
2815 MFloat phi1 = r - m_bodyRadius[k];
2816 MFloat phi2 = -signCode[k] * (
y - signCode[k] * yIS - m_bodyCenter[0 * nDim + 1]);
2818 sqrt((
y - signCode[k] * yIS - m_bodyCenter[0 * nDim + 1]) * (
y - signCode[k] * yIS - m_bodyCenter[0 * nDim + 1])
2819 + (x - xIS) * (x - xIS));
2821 sqrt((
y - signCode[k] * yIS - m_bodyCenter[0 * nDim + 1]) * (
y - signCode[k] * yIS - m_bodyCenter[0 * nDim + 1])
2822 + (x + xIS) * (x + xIS));
2824 if(x < -xIS && phi2 > F0)
2826 else if(x > xIS && phi2 > F0)
2839template <MInt nDim,
class SysEqn>
2845 ASSERT(nDim == 2,
"Untested for 3D");
2855 const MFloat XX = Context::getSolverProperty<MFloat>(
"NACA00XX", m_solverId, AT_, &XXTMP);
2857 const MFloat eps = 1e-10;
2858 const MInt maxIter = 1000;
2859 const MFloat p0 = coordinate[0];
2860 const MFloat q0 = coordinate[1];
2861 MFloat bodyRotation[3] = {0};
2862 getBodyRotation(0, bodyRotation);
2863 const MFloat p =
cos(-bodyRotation[2]) * p0 - sin(-bodyRotation[2]) * q0 + F1B4;
2864 const MFloat q = sin(-bodyRotation[2]) * p0 +
cos(-bodyRotation[2]) * q0;
2867 if(fabs(q) < m_eps) {
2881 * ((0.2969 * sqrt(x)) - (0.126 * x) - (0.3516 * x * x) + (0.2843 * x * x * x) - (0.1036 * x * x * x * x));
2885 * ((F1B2 * 0.2969 / sqrt(x)) - (0.126) - (F2 * 0.3516 * x) + (F3 * 0.2843 * x * x) - (F4 * 0.1036 * x * x * x));
2894 * ((0.2969 * sqrt(x)) - (0.126 * x) - (0.3516 * x * x) + (0.2843 * x * x * x) - (0.1036 * x * x * x * x));
2897 * ((F1B2 * 0.2969 / sqrt(x)) - (0.126) - (F2 * 0.3516 * x) + (F3 * 0.2843 * x * x) - (F4 * 0.1036 * x * x * x));
2898 f = (
p - x) + yp * (q -
y);
2938 x =
mMin(xb - m_eps,
mMax(xa + m_eps, p));
2939 while((res > eps) && (iter < maxIter) && (x > xa) && (x < xb)) {
2941 * ((0.2969 * sqrt(x)) - (0.126 * x) - (0.3516 * x * x) + (0.2843 * x * x * x) - (0.1036 * x * x * x * x));
2943 * ((F1B2 * 0.2969 / sqrt(x)) - (0.126) - (F2 * 0.3516 * x) + (F3 * 0.2843 * x * x)
2944 - (F4 * 0.1036 * x * x * x));
2947 * ((-F1B4 * 0.2969 / (x * sqrt(x))) - (F2 * 0.3516) + (6.0 * 0.2843 * x) - (12.0 * 0.1036 * x * x));
2948 f = (
p - x) + yp * (q -
y);
2960 while((res > eps) && (iter < maxIter)) {
2961 x = F1B2 * (xa + xb);
2964 * ((0.2969 * sqrt(x)) - (0.126 * x) - (0.3516 * x * x) + (0.2843 * x * x * x) - (0.1036 * x * x * x * x));
2967 * ((F1B2 * 0.2969 / sqrt(x)) - (0.126) - (F2 * 0.3516 * x) + (F3 * 0.2843 * x * x)
2968 - (F4 * 0.1036 * x * x * x));
2969 f = (
p - x) + yp * (q -
y);
2981 res =
mMax(fabs(f), fabs(xb - xa));
2984 if(iter >= maxIter) {
2985 cerr <<
"Warning: max iterations exceeded in bisection" << endl;
3007 if((p > F0) && (p < F1) && (sign * q < sign *
y))
dist *= -F1;
3012#ifndef NACA0012SPLIT
3018 * ((0.2969 * sqrt(xr)) - (0.126 * xr) - (0.3516 * xr * xr) + (0.2843 * xr * xr * xr)
3019 - (0.1036 * xr * xr * xr * xr));
3032template <MInt nDim,
class SysEqn>
3038 multimap<MFloat, MInt> approximateLSV;
3039 multimap<MFloat, MInt> initLSV;
3041 const MInt _far = 2;
3042 const MInt band = 1;
3043 const MInt accepted = 0;
3051 MInt firstLayerHaloCount = 0;
3052 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3053 isFirstLayerHalo[cellId] =
false;
3054 isFarHalo[cellId] =
false;
3055 if(!a_isHalo(cellId))
continue;
3056 isFarHalo[cellId] =
true;
3057 for(
MInt direction = 0; direction < (2 * nDim); direction++) {
3058 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + direction];
3059 j < m_identNghbrIds[2 * cellId * nDim + direction + 1];
3061 MInt nghbrId = m_storeNghbrIds[j];
3062 if(a_isWindow(nghbrId)) {
3063 isFirstLayerHalo[cellId] =
true;
3064 isFarHalo[cellId] =
false;
3065 firstLayerHalos[firstLayerHaloCount++] = cellId;
3073 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3074 flag[cellId] = _far;
3079 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3080 isStartCell[cellId] =
false;
3081 if(c_noChildren(cellId)) {
3082 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
3085 if(isFarHalo[cellId] || isFirstLayerHalo[cellId]) {
3086 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
3089 MFloat limitValue = c_cellLengthAtLevel(a_level(cellId)) * sqrt(nDim);
3090 if(a_levelSetValuesMb(cellId, 0) < 0 || (
false && a_levelSetValuesMb(cellId, 0) < limitValue)) {
3091 flag[cellId] = accepted;
3092 initLSV.insert(make_pair(a_levelSetValuesMb(cellId, 0), cellId));
3093 isStartCell[cellId] =
true;
3095 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
3099 while(!initLSV.empty()) {
3100 multimap<MFloat, MInt>::iterator it = initLSV.begin();
3101 MInt cellId = it->second;
3103 for(
MInt direction = 0; direction < (2 * nDim); direction++) {
3104 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + direction];
3105 j < m_identNghbrIds[2 * cellId * nDim + direction + 1];
3107 MInt nghbrId = m_storeNghbrIds[j];
3108 if(isFarHalo[nghbrId])
continue;
3109 if(flag[nghbrId] == accepted)
continue;
3110 if(!isFirstLayerHalo[nghbrId] && !isStartCell[nghbrId]) {
3111 a_levelSetValuesMb(nghbrId, 0) = CalculateLSV(nghbrId, flag);
3113 approximateLSV.insert(make_pair(a_levelSetValuesMb(nghbrId, 0), nghbrId));
3114 flag[nghbrId] = band;
3119 MBool somethingOnBoundaryChanged =
true;
3121 while(somethingOnBoundaryChanged) {
3123 somethingOnBoundaryChanged =
false;
3125 for(
MInt cellId = 0; cellId < a_noCells(); cellId++)
3126 oldLVS[cellId] = a_levelSetValuesMb(cellId, 0);
3130 while(!approximateLSV.empty()) {
3131 multimap<MFloat, MInt>::iterator it = approximateLSV.
begin();
3132 MInt cellId = it->second;
3133 approximateLSV.erase(it);
3134 if(flag[cellId] == accepted)
continue;
3135 flag[cellId] = accepted;
3136 for(
MInt direction = 0; direction < (m_noDirs); direction++) {
3137 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + direction];
3138 j < m_identNghbrIds[2 * cellId * nDim + direction + 1];
3140 MInt nghbrId = m_storeNghbrIds[j];
3141 if(isFarHalo[nghbrId])
continue;
3142 if(flag[nghbrId] == accepted)
continue;
3143 if(!isFirstLayerHalo[nghbrId]
3144 && !isStartCell[nghbrId]) {
3145 a_levelSetValuesMb(nghbrId, 0) = CalculateLSV(nghbrId, flag);
3147 approximateLSV.insert(make_pair(a_levelSetValuesMb(nghbrId, 0), nghbrId));
3148 flag[nghbrId] = band;
3156 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3157 if(isFirstLayerHalo[cellId] || isFarHalo[cellId])
continue;
3158 if(c_noChildren(cellId) > 0)
continue;
3160 (a_levelSetValuesMb(cellId, 0) - oldLVS[cellId]) * (a_levelSetValuesMb(cellId, 0) - oldLVS[cellId]);
3161 if(tmpChange > F0) {
3162 change += tmpChange;
3166 if(noCells > 0) change = sqrt(change) / noCells;
3169 if(noNeighborDomains() > 0) {
3173 MInt receiveCount = 0;
3174 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3175 sendCount += (signed)noWindowCells(i);
3176 receiveCount += (signed)noHaloCells(i);
3183 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3184 for(
MInt j = 0; j < (signed)noWindowCells(i); j++) {
3185 sendBuffer.
p[sendCount] = a_levelSetValuesMb(windowCellId(i, j), 0);
3191 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3192 MInt bufSize = (signed)noWindowCells(i);
3193 MPI_Issend(&(sendBuffer.
p[sendCount]), bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i],
3194 AT_,
"(sendBuffer.p[sendCount])");
3195 sendCount += noWindowCells(i);
3200 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3201 MInt bufSize = (signed)noHaloCells(i);
3202 MPI_Recv(&(receiveBuffer.
p[receiveCount]), bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &status, AT_,
3203 "(receiveBuffer.p[ receiveCount ])");
3204 receiveCount += noHaloCells(i);
3206 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3207 MPI_Wait(&g_mpiRequestMb[i], &status, AT_);
3212 for(
MInt i = 0; i < noNeighborDomains(); i++) {
3213 for(
MInt j = 0; j < (signed)noHaloCells(i); j++) {
3214 MInt cellId = haloCellId(i, j);
3215 valueChanged[cellId] =
false;
3216 if(abs(a_levelSetValuesMb(cellId, 0) - receiveBuffer.
p[receiveCount]) > eps) {
3217 valueChanged[cellId] =
true;
3219 a_levelSetValuesMb(cellId, 0) = receiveBuffer.
p[receiveCount];
3226 for(
MInt hc = 0; hc < firstLayerHaloCount; hc++) {
3227 isSource[hc] =
false;
3228 MInt haloId = firstLayerHalos[hc];
3229 for(
MInt direction = 0; direction < (2 * nDim); direction++) {
3230 for(
MInt j = m_identNghbrIds[2 * haloId * nDim + direction];
3231 j < m_identNghbrIds[2 * haloId * nDim + direction + 1];
3233 MInt nghbrId = m_storeNghbrIds[j];
3234 if(!isFarHalo[nghbrId] && !isFirstLayerHalo[nghbrId]
3235 && !isStartCell[nghbrId]) {
3236 if(a_levelSetValuesMb(haloId, 0) < a_levelSetValuesMb(nghbrId, 0)) {
3237 isSource[hc] =
true;
3245 MFloat minHaloVal = c_cellLengthAtLevel(0);
3246 for(
MInt hc = 0; hc < firstLayerHaloCount; hc++) {
3247 MInt haloId = firstLayerHalos[hc];
3248 if(isSource[hc] && valueChanged[haloId]) {
3249 minHaloVal =
mMin(minHaloVal, a_levelSetValuesMb(haloId, 0));
3250 somethingOnBoundaryChanged =
true;
3253 flag[haloId] = band;
3254 approximateLSV.insert(make_pair(a_levelSetValuesMb(haloId, 0), haloId));
3256 flag[haloId] = _far;
3262 MIntScratchSpace somethingChangedExchange(1, AT_,
"somethingChangedExchange");
3263 somethingChangedExchange[0] = somethingOnBoundaryChanged;
3265 mpiComm(), AT_,
"somethingChangedExchange.getPointer()",
"globalSomethingChanged.getPointer()");
3266 somethingOnBoundaryChanged = globalSomethingChanged[0];
3269 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3270 if(isFarHalo[cellId] || isFirstLayerHalo[cellId])
continue;
3271 if(c_noChildren(cellId) > 0)
continue;
3272 if(isStartCell[cellId]) {
3273 flag[cellId] = accepted;
3274 }
else if(abs(a_levelSetValuesMb(cellId, 0) - minHaloVal) < eps) {
3275 flag[cellId] = band;
3276 approximateLSV.insert(make_pair(a_levelSetValuesMb(cellId, 0), cellId));
3277 }
else if(a_levelSetValuesMb(cellId, 0) < minHaloVal) {
3278 flag[cellId] = accepted;
3280 flag[cellId] = _far;
3284 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3285 if(flag[cellId] != accepted)
continue;
3286 for(
MInt direction = 0; direction < (2 * nDim); direction++) {
3287 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + direction];
3288 j < m_identNghbrIds[2 * cellId * nDim + direction + 1];
3290 MInt nghbrId = m_storeNghbrIds[j];
3291 if(isFarHalo[nghbrId])
continue;
3292 if(flag[nghbrId] == _far) {
3293 flag[nghbrId] = band;
3294 approximateLSV.insert(make_pair(a_levelSetValuesMb(nghbrId, 0), nghbrId));
3300 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3301 if(flag[cellId] != _far)
continue;
3302 if(isFarHalo[cellId] || isFirstLayerHalo[cellId])
continue;
3303 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
3309 for(
MInt level = maxRefinementLevel() - 1; level >= maxUniformRefinementLevel(); level--) {
3310 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
3311 if(a_level(cellId) != level)
continue;
3312 if(c_isLeafCell(cellId))
continue;
3313 a_levelSetValuesMb(cellId, 0) = F0;
3314 for(
MInt child = 0; child <
IPOW2(nDim); child++) {
3315 MInt childId = c_childId(cellId, child);
3316 if(childId > -1) a_levelSetValuesMb(cellId, 0) += a_levelSetValuesMb(childId, 0);
3318 a_levelSetValuesMb(cellId, 0) /= c_noChildren(cellId);
3332template <MInt nDim,
class SysEqn>
3338 MFloat delta_cell[3] = {F0, F0, F0};
3340 MFloat delta_taylor[2][3] = {{F0, F0, F0}, {F0, F0, F0}};
3341 MFloat levelSetValues = c_cellLengthAtLevel(0);
3342 const MFloat eps = 1.0e-3 * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
3343 const MInt accepted = 0;
3346 for(
MInt direction = 0; direction < (2 * nDim); direction++) {
3348 for(
MInt j = m_identNghbrIds[2 * cellId * nDim + direction]; j < m_identNghbrIds[2 * cellId * nDim + direction + 1];
3350 MInt nghbrId = m_storeNghbrIds[j];
3351 if(flag[nghbrId] == accepted && a_levelSetValuesMb(nghbrId, 0) < a_levelSetValuesMb(cellId, 0)) {
3353 if(a_levelSetValuesMb(nghbrId, 0) <
a[index]) {
3354 a[index] = a_levelSetValuesMb(nghbrId, 0);
3355 delta_cell[index] = c_cellLengthAtLevel(a_level(nghbrId));
3358 a[index] = a_levelSetValuesMb(nghbrId, 0);
3359 delta_cell[index] = c_cellLengthAtLevel(a_level(nghbrId));
3365 IF_CONSTEXPR(nDim == 2) {
3366 if(!(
a[0] > F0) && !(
a[1] > F0)) {
3367 }
else if(!(
a[0] > F0)) {
3369 delta_taylor[0][1] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[1]) *
FFPOW2(1);
3370 levelSetValues =
a[1] + delta_taylor[0][1];
3371 }
else if(!(
a[1] > F0)) {
3373 delta_taylor[0][0] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[0]) *
FFPOW2(1);
3374 levelSetValues =
a[0] + delta_taylor[0][0];
3379 if(abs(delta_cell[0] - delta_cell[1]) < eps) {
3381 delta_taylor[0][0] = (delta_cell[0] + c_cellLengthAtLevel(a_level(cellId))) *
FFPOW2(1);
3383 q = (
a[0] *
a[0] +
a[1] *
a[1] - delta_taylor[0][0] * delta_taylor[0][0]) *
FFPOW2(1);
3385 delta_taylor[0][0] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[0]) *
FFPOW2(1);
3386 delta_taylor[0][1] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[1]) *
FFPOW2(1);
3387 p = -2 * (delta_taylor[0][1] * delta_taylor[0][1] *
a[0] + delta_taylor[0][0] * delta_taylor[0][0] *
a[1])
3388 / (delta_taylor[0][0] * delta_taylor[0][0] + delta_taylor[0][1] * delta_taylor[0][1]);
3389 q = (delta_taylor[0][1] * delta_taylor[0][1] *
a[0] *
a[0]
3390 + delta_taylor[0][0] * delta_taylor[0][0] *
a[1] *
a[1]
3391 - delta_taylor[0][1] * delta_taylor[0][1] * delta_taylor[0][0] * delta_taylor[0][0])
3392 / (delta_taylor[0][1] * delta_taylor[0][1] + delta_taylor[0][0] * delta_taylor[0][0]);
3395 if(psqf4mq < F0) psqf4mq = F0;
3396 levelSetValues = -p *
FFPOW2(1) + sqrt(psqf4mq);
3399 else IF_CONSTEXPR(nDim == 3) {
3401 if(!(
a[0] > F0) && !(
a[1] > F0) && !(
a[2] > F0)) {
3402 }
else if(!(
a[1] > F0) && !(
a[2] > F0)) {
3404 delta_taylor[0][0] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[0]) *
FFPOW2(1);
3405 levelSetValues =
a[0] + delta_taylor[0][0];
3406 }
else if(!(
a[0] > F0) && !(
a[2] > F0)) {
3408 delta_taylor[0][1] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[1]) *
FFPOW2(1);
3409 levelSetValues =
a[1] + delta_taylor[0][1];
3410 }
else if(!(
a[0] > F0) && !(
a[1] > F0)) {
3412 delta_taylor[0][2] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[2]) *
FFPOW2(1);
3413 levelSetValues =
a[2] + delta_taylor[0][2];
3414 }
else if(!(
a[2] > F0)) {
3417 if(abs(delta_cell[0] - delta_cell[1]) < eps) {
3419 delta_taylor[0][0] = (delta_cell[0] + c_cellLengthAtLevel(a_level(cellId))) *
FFPOW2(1);
3421 q = (
a[0] *
a[0] +
a[1] *
a[1] - delta_taylor[0][0] * delta_taylor[0][0]) *
FFPOW2(1);
3423 delta_taylor[0][0] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[0]) *
FFPOW2(1);
3424 delta_taylor[0][1] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[1]) *
FFPOW2(1);
3425 MFloat x2 = delta_taylor[0][0] * delta_taylor[0][0];
3426 MFloat y2 = delta_taylor[0][1] * delta_taylor[0][1];
3427 MFloat denominator = x2 + y2;
3429 p = -2 * (
a[0] * y2 +
a[1] * x2) / denominator;
3430 q = (
a[0] *
a[0] * y2 +
a[1] *
a[1] * x2 - x2y2) / denominator;
3433 if(psqf4mq < F0) psqf4mq = F0;
3434 levelSetValues = -p *
FFPOW2(1) + sqrt(psqf4mq);
3435 }
else if(!(
a[1] > F0)) {
3438 if(abs(delta_cell[0] - delta_cell[2]) < eps) {
3440 delta_taylor[0][0] = (delta_cell[0] + c_cellLengthAtLevel(a_level(cellId))) *
FFPOW2(1);
3442 q = (
a[0] *
a[0] +
a[2] *
a[2] - delta_taylor[0][0] * delta_taylor[0][0]) *
FFPOW2(1);
3444 delta_taylor[0][0] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[0]) *
FFPOW2(1);
3445 delta_taylor[0][2] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[2]) *
FFPOW2(1);
3446 MFloat x2 = delta_taylor[0][0] * delta_taylor[0][0];
3447 MFloat z2 = delta_taylor[0][2] * delta_taylor[0][2];
3448 MFloat denominator = x2 + z2;
3450 p = -2 * (
a[0] * z2 +
a[2] * x2) / denominator;
3451 q = (
a[0] *
a[0] * z2 +
a[2] *
a[2] * x2 - x2z2) / denominator;
3454 if(psqf4mq < F0) psqf4mq = F0;
3455 levelSetValues = -p *
FFPOW2(1) + sqrt(psqf4mq);
3456 }
else if(!(
a[0] > F0)) {
3459 if(abs(delta_cell[1] - delta_cell[2]) < eps) {
3461 delta_taylor[0][0] = (delta_cell[1] + c_cellLengthAtLevel(a_level(cellId))) *
FFPOW2(1);
3463 q = (
a[1] *
a[1] +
a[2] *
a[2] - delta_taylor[0][0] * delta_taylor[0][0]) *
FFPOW2(1);
3465 delta_taylor[0][1] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[1]) *
FFPOW2(1);
3466 delta_taylor[0][2] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[2]) *
FFPOW2(1);
3467 MFloat y2 = delta_taylor[0][1] * delta_taylor[0][1];
3468 MFloat z2 = delta_taylor[0][2] * delta_taylor[0][2];
3469 MFloat denominator = z2 + y2;
3471 p = -2 * (
a[1] * z2 +
a[2] * y2) / denominator;
3472 q = (
a[1] *
a[1] * z2 +
a[2] *
a[2] * y2 - z2y2) / denominator;
3475 if(psqf4mq < F0) psqf4mq = F0;
3476 levelSetValues = -p *
FFPOW2(1) + sqrt(psqf4mq);
3480 if(abs(delta_cell[0] - delta_cell[2]) < eps
3481 && abs(delta_cell[1] - delta_cell[2]) < eps) {
3483 delta_taylor[0][0] = (delta_cell[0] + c_cellLengthAtLevel(a_level(cellId))) *
FFPOW2(1);
3484 p = -F2B3 * (
a[0] +
a[1] +
a[2]);
3485 q = F1B3 * (
a[0] *
a[0] +
a[1] *
a[1] +
a[2] *
a[2] - delta_taylor[0][0] * delta_taylor[0][0]);
3487 delta_taylor[0][0] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[0]) *
FFPOW2(1);
3488 delta_taylor[0][1] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[1]) *
FFPOW2(1);
3489 delta_taylor[0][2] = (c_cellLengthAtLevel(a_level(cellId)) + delta_cell[2]) *
FFPOW2(1);
3490 MFloat x2y2 = delta_taylor[0][0] * delta_taylor[0][0] * delta_taylor[0][1] * delta_taylor[0][1];
3491 MFloat x2z2 = delta_taylor[0][0] * delta_taylor[0][0] * delta_taylor[0][2] * delta_taylor[0][2];
3492 MFloat y2z2 = delta_taylor[0][1] * delta_taylor[0][1] * delta_taylor[0][2] * delta_taylor[0][2];
3493 MFloat x2y2z2 = delta_taylor[0][0] * delta_taylor[0][0] * delta_taylor[0][1] * delta_taylor[0][1]
3494 * delta_taylor[0][2] * delta_taylor[0][2];
3495 MFloat denominator = (x2y2 + x2z2 + y2z2);
3496 p = -2 * (y2z2 *
a[0] + x2z2 *
a[1] + x2y2 *
a[2]) / denominator;
3497 q = (y2z2 *
a[0] *
a[0] + x2z2 *
a[1] *
a[1] + x2y2 *
a[2] *
a[2] - x2y2z2) / denominator;
3500 if(psqf4mq < F0) psqf4mq = F0;
3501 levelSetValues = -p *
FFPOW2(1) + sqrt(psqf4mq);
3505 return levelSetValues;
3513template <MInt nDim,
class SysEqn>
3515 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
3517 MFloat dist = fabs(coordinates[0] - m_bodyCenter[bodyId * nDim]) - m_bodyRadius[bodyId];
3527template <MInt nDim,
class SysEqn>
3529 return getDistancePiston(&a_coordinate(cellId, 0), bodyId);
3537template <MInt nDim,
class SysEqn>
3539 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
3540 if(bodyId != 0)
mTerm(1, AT_,
"Extend Naca00XX.");
3542 const MFloat phi0 = getLevelSetValueNaca00XX(&a_coordinate(cellId, 0), -F1);
3543 const MFloat phi1 = getLevelSetValueNaca00XX(&a_coordinate(cellId, 0), F1);
3544 const MFloat phi = (fabs(phi0) < fabs(phi1)) ? phi0 : phi1;
3554template <MInt nDim,
class SysEqn>
3556 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
3562 computeRotationMatrix(R, &(m_bodyQuaternion[4 * bodyId]));
3564 MFloat x = coordinates[0] - m_bodyCenter[bodyId * nDim + 0];
3565 MFloat y = coordinates[1] - m_bodyCenter[bodyId * nDim + 1];
3566 MFloat z = coordinates[2] - m_bodyCenter[bodyId * nDim + 2];
3571 matrixVectorProduct(xb, R, xw);
3576 const MFloat a = m_bodyRadii[bodyId * nDim + 0];
3577 const MFloat b = m_bodyRadii[bodyId * nDim + 1];
3578 const MFloat c = m_bodyRadii[bodyId * nDim + 2];
3582 MFloat xx[3] = {F0, F0, F0};
3583 MFloat dist = distancePointEllipsoid(ee, yy, xx);
3594template <MInt nDim,
class SysEqn>
3596 return getDistanceEllipsoid(&a_coordinate(cellId, 0), bodyId);
3604template <MInt nDim,
class SysEqn>
3612 computeRotationMatrix(R0, &(m_bodyQuaternion[4 * k0]));
3613 computeRotationMatrix(R1, &(m_bodyQuaternion[4 * k1]));
3615 for(
MInt i = 0; i < nDim; i++)
3616 xc0[i] = m_bodyCenter[k0 * nDim + i];
3617 for(
MInt i = 0; i < nDim; i++)
3618 xc1[i] = m_bodyCenter[k1 * nDim + i];
3620 MFloat x = xc1[0] - xc0[0];
3622 MFloat z = xc1[2] - xc0[2];
3627 MFloat dist0 = 9999998.0;
3631 const MInt maxIter = 200;
3632 const MFloat eps = 1e-3 * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
3633 while(fabs(dist0 -
dist) > eps && iter < maxIter) {
3634 id = (iter % 2 == 0) ? k0 : k1;
3635 xc = (iter % 2 == 0) ? xc1 : xc0;
3636 xc_next = (iter % 2 == 0) ? xc0 : xc1;
3638 x = xc[0] - m_bodyCenter[
id * nDim + 0];
3639 y = xc[1] - m_bodyCenter[
id * nDim + 1];
3640 z = xc[2] - m_bodyCenter[
id * nDim + 2];
3646 matrixVectorProduct(xb, R0, xw);
3648 matrixVectorProduct(xb, R1, xw);
3653 MFloat a = m_bodyRadii[
id * nDim + 0];
3654 MFloat b = m_bodyRadii[
id * nDim + 1];
3655 MFloat c = m_bodyRadii[
id * nDim + 2];
3659 MFloat xx[3] = {F0, F0, F0};
3662 dist = distancePointEllipsoid(ee, yy, xx);
3669 matrixVectorProductTranspose(xw, R0, xb);
3671 matrixVectorProductTranspose(xw, R1, xb);
3673 xc_next[0] = xw[0] + m_bodyCenter[
id * nDim + 0];
3674 xc_next[1] = xw[1] + m_bodyCenter[
id * nDim + 1];
3675 xc_next[2] = xw[2] + m_bodyCenter[
id * nDim + 2];
3679 if(iter >= maxIter && domainId() == 0)
3680 cerr << setprecision(12) << domainId() <<
": ellipsoid dist did not converge " << k0 <<
" " << k1 <<
" / "
3681 <<
dist - dist0 <<
" " <<
dist <<
" " << dist0 <<
" " << iter <<
" " << endl;
3694template <MInt nDim,
class SysEqn>
3697 constexpr MFloat eps = 1e-14;
3704 MFloat esqr[3] = {e[0] * e[0], e[1] * e[1], e[2] * e[2]};
3705 MFloat ey[3] = {e[0] *
y[0], e[1] *
y[1], e[2] *
y[2]};
3706 MFloat t0 = -esqr[2] + ey[2];
3707 MFloat t1 = -esqr[2] + sqrt(ey[0] * ey[0] + ey[1] * ey[1] + ey[2] * ey[2]);
3709 const MInt imax = 2 * std::numeric_limits<MFloat>::max_exponent;
3710 for(
MInt i = 0; i < imax; ++i) {
3711 t = ((
MFloat)0.5) * (t0 + t1);
3712 if(fabs(t - t0) < eps || fabs(t - t1) < eps) {
3715 MFloat r[3] = {ey[0] / (t + esqr[0]), ey[1] / (t + esqr[1]), ey[2] / (t + esqr[2])};
3716 MFloat f = r[0] * r[0] + r[1] * r[1] + r[2] * r[2] - (
MFloat)1;
3719 }
else if(f < (
MFloat)0) {
3726 x[0] = esqr[0] *
y[0] / (t + esqr[0]);
3727 x[1] = esqr[1] *
y[1] / (t + esqr[1]);
3728 x[2] = esqr[2] *
y[2] / (t + esqr[2]);
3729 MFloat d[3] = {x[0] -
y[0], x[1] -
y[1], x[2] -
y[2]};
3730 distance = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
3734 MFloat etmp[2] = {e[1], e[2]};
3737 distance = distancePointEllipseSpecial(etmp, ytmp, xtmp);
3745 MFloat etmp[2] = {e[0], e[2]};
3748 distance = distancePointEllipseSpecial(etmp, ytmp, xtmp);
3755 distance = fabs(
y[2] - e[2]);
3760 MFloat denom[2] = {e[0] * e[0] - e[2] * e[2], e[1] * e[1] - e[2] * e[2]};
3761 MFloat ey[2] = {e[0] *
y[0], e[1] *
y[1]};
3762 if(ey[0] < denom[0] && ey[1] < denom[1]) {
3766 MFloat xde[2] = {ey[0] / denom[0], ey[1] / denom[1]};
3767 MFloat xdesqr[2] = {xde[0] * xde[0], xde[1] * xde[1]};
3772 x[0] = e[0] * xde[0];
3773 x[1] = e[1] * xde[1];
3774 x[2] = e[2] * sqrt(discr);
3775 MFloat d[2] = {x[0] -
y[0], x[1] -
y[1]};
3776 distance = sqrt(d[0] * d[0] + d[1] * d[1] + x[2] * x[2]);
3782 distance = distancePointEllipseSpecial(e,
y, x);
3789 distance = distancePointEllipseSpecial(e,
y, x);
3807template <MInt nDim,
class SysEqn>
3810 constexpr MFloat eps0 = 1e-12;
3811 constexpr MFloat eps1 = 1e-6;
3812 const MFloat dist0 = c_cellLengthAtLevel(m_lsCutCellBaseLevel);
3813 const MFloat dist1 = m_maxBndryLayerWidth * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
3816 MFloat esqr[3] = {e[0] * e[0], e[1] * e[1], e[2] * e[2]};
3817 MFloat ey[3] = {e[0] *
y[0], e[1] *
y[1], e[2] *
y[2]};
3818 MFloat t0 = -esqr[2] + ey[2];
3819 MFloat t1 = -esqr[2] + sqrt(ey[0] * ey[0] + ey[1] * ey[1] + ey[2] * ey[2]);
3821 const MInt imax = 2 * std::numeric_limits<MFloat>::max_exponent;
3823 if(fabs(t1 - t0) < eps) t1 = t0 + F2 * eps;
3824 t = F1B2 * (t0 + t1);
3826 distance = c_cellLengthAtLevel(0);
3828 while(fabs(t1 - t0) > eps && i < imax) {
3830 while ( i < imax ) {
3832 t = F1B2 * (t0 + t1);
3833 MFloat f0 = (t + esqr[0]) * (t + esqr[0]);
3834 MFloat f1 = (t + esqr[1]) * (t + esqr[1]);
3835 MFloat f2 = (t + esqr[2]) * (t + esqr[2]);
3836 MFloat fs = f0 * f1 * f2;
3838 MFloat f = ey[0] * ey[0] * f1 * f2 + ey[1] * ey[1] * f0 * f2 + ey[2] * ey[2] * f0 * f1;
3844 if( fabs(t1 - t0) < eps || i >= imax )
break;
3847 t = F1B2 * (t0 + t1);
3848 f0 = (t + esqr[0])*(t + esqr[0]);
3849 f1 = (t + esqr[1])*(t + esqr[1]);
3850 f2 = (t + esqr[2])*(t + esqr[2]);
3852 f = ey[0] * ey[0] * f1 * f2 + ey[1] * ey[1] * f0 * f2 + ey[2] * ey[2] * f0 * f1;
3858 if(fabs(t1 - t0) < eps || i >= imax)
break;
3861 t = F1B2 * (t0 + t1);
3862 f0 = (t + esqr[0])*(t + esqr[0]);
3863 f1 = (t + esqr[1])*(t + esqr[1]);
3864 f2 = (t + esqr[2])*(t + esqr[2]);
3866 f = ey[0] * ey[0] * f1 * f2 + ey[1] * ey[1] * f0 * f2 + ey[2] * ey[2] * f0 * f1;
3872 if(fabs(t1 - t0) < eps || i >= imax)
break;
3875 t = F1B2 * (t0 + t1);
3876 f0 = (t + esqr[0])*(t + esqr[0]);
3877 f1 = (t + esqr[1])*(t + esqr[1]);
3878 f2 = (t + esqr[2])*(t + esqr[2]);
3880 f = ey[0] * ey[0] * f1 * f2 + ey[1] * ey[1] * f0 * f2 + ey[2] * ey[2] * f0 * f1;
3886 if(fabs(t1 - t0) < eps || i >= imax)
break;
3888 x[0] = esqr[0] *
y[0] / (t + esqr[0]);
3889 x[1] = esqr[1] *
y[1] / (t + esqr[1]);
3890 x[2] = esqr[2] *
y[2] / (t + esqr[2]);
3891 distance = sqrt(
POW2(x[0] -
y[0]) +
POW2(x[1] -
y[1]) +
POW2(x[2] -
y[2]));
3893 eps = eps0 +
mMin(F1,
mMax(F0, (distance - dist0) / (dist1 - dist0))) * (eps1 - eps0);
3895 if(fabs(t0 - t1) > eps) cerr << setprecision(16) <<
"ellipsoid dist not converged! " << i <<
" " << t1 - t0 << endl;
3906template <MInt nDim,
class SysEqn>
3911 for(i = 0; i < 3; ++i) {
3912 reflect[i] = (
y[i] < (
MFloat)0);
3922 }
else if(e[2] < e[1]) {
3936 }
else if(e[2] < e[0]) {
3947 for(i = 0; i < 3; ++i) {
3948 invpermute[permute[i]] = i;
3951 for(i = 0; i < 3; ++i) {
3960#define IMPROVEDDISTELLIPSOID
3961#ifdef IMPROVEDDISTELLIPSOID
3962 for(i = 0; i < 3; ++i) {
3963 ASSERT(!(locY[i] < F0),
"");
3964 locY[i] =
mMax(1e-15, locY[i]);
3966 MFloat distance = distancePointEllipsoidSpecial2(locE, locY, locX);
3968 MFloat distance = distancePointEllipsoidSpecial(locE, locY, locX);
3971 for(i = 0; i < 3; ++i) {
3988template <MInt nDim,
class SysEqn>
3991 constexpr MFloat eps = 1e-14;
3997 MFloat esqr[2] = {e[0] * e[0], e[1] * e[1]};
3998 MFloat ey[2] = {e[0] *
y[0], e[1] *
y[1]};
3999 MFloat t0 = -esqr[1] + ey[1];
4000 MFloat t1 = -esqr[1] + sqrt(ey[0] * ey[0] + ey[1] * ey[1]);
4002 const MInt imax = 2 * std::numeric_limits<MFloat>::max_exponent;
4003 for(
MInt i = 0; i < imax; ++i) {
4004 t = ((
MFloat)0.5) * (t0 + t1);
4005 if(fabs(t - t0) < eps || fabs(t - t1) < eps) {
4008 MFloat r[2] = {ey[0] / (t + esqr[0]), ey[1] / (t + esqr[1])};
4012 }
else if(f < (
MFloat)0) {
4018 if(fabs(t0 - t1) > eps) cerr <<
"ellipse dist not converged!" << endl;
4019 x[0] = esqr[0] *
y[0] / (t + esqr[0]);
4020 x[1] = esqr[1] *
y[1] / (t + esqr[1]);
4021 MFloat d[2] = {x[0] -
y[0], x[1] -
y[1]};
4022 distance = sqrt(d[0] * d[0] + d[1] * d[1]);
4027 distance = fabs(
y[1] - e[1]);
4031 MFloat denom0 = e[0] * e[0] - e[1] * e[1];
4035 MFloat x0de0 = e0y0 / denom0;
4036 MFloat x0de0sqr = x0de0 * x0de0;
4037 x[0] = e[0] * x0de0;
4038 x[1] = e[1] * sqrt(fabs((
MFloat)1 - x0de0sqr));
4040 distance = sqrt(d0 * d0 + x[1] * x[1]);
4046 distance = fabs(
y[0] - e[0]);
4057template <MInt nDim,
class SysEqn>
4059 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
4061 constexpr MFloat eps = 5e-3;
4062 const MFloat fac0 = F1 / sqrt(F3);
4063 const MFloat fac1 = F1B6 * pow(PI / F2, F1B3);
4064 const MFloat fac = fac1 * m_bodyDiameter[bodyId];
4065 constexpr MFloat dirs[4][3] = {{F1, F1, -F1}, {F1, -F1, F1}, {-F1, F1, F1}, {-F1, -F1, -F1}};
4067 MFloat innerDist = std::numeric_limits<MFloat>::lowest();
4073 computeRotationMatrix(R, &(m_bodyQuaternion[4 * bodyId]));
4074 MFloat x = coordinates[0] - m_bodyCenter[bodyId * nDim + 0];
4075 MFloat y = coordinates[1] - m_bodyCenter[bodyId * nDim + 1];
4077 IF_CONSTEXPR(nDim == 3) { z = coordinates[2] - m_bodyCenter[bodyId * nDim + 2]; }
4080 IF_CONSTEXPR(nDim == 3) { xw[2] = z; }
4081 matrixVectorProduct(xb, R, xw);
4084 IF_CONSTEXPR(nDim == 3) { z = xb[2]; }
4088 for(
MInt face = 0; face < 4; face++) {
4090 IF_CONSTEXPR(nDim == 2) {
4091 dist = dirs[face][0] * fac0 * (x - fac * dirs[face][0]) + dirs[face][1] * fac0 * (
y - fac * dirs[face][1]);
4093 else IF_CONSTEXPR(nDim == 3) {
4094 dist = dirs[face][0] * fac0 * (x - fac * dirs[face][0]) + dirs[face][1] * fac0 * (
y - fac * dirs[face][1])
4095 + dirs[face][2] * fac0 * (z - fac * dirs[face][2]);
4102 std::sort(dists, dists + 4, [](
const MFloat&
a,
const MFloat&
b) {
return fabs(
a) < fabs(
b); });
4104 if(innerDist < F0) {
4105 if(fabs(dists[1]) < eps * m_bodyDiameter[bodyId]) {
4107 for(
MInt face = 0; face < 4; face++) {
4108 if(fabs(dists[face]) < eps * m_bodyDiameter[bodyId]) {
4109 innerDist = -sqrt(
POW2(innerDist) +
POW2(dists[face]));
4114 if(fabs(dists[1]) < eps * m_bodyDiameter[bodyId]) {
4116 for(
MInt face = 0; face < 4; face++) {
4117 if(fabs(dists[face]) < eps * m_bodyDiameter[bodyId]) {
4118 outerDist +=
POW2(dists[face]);
4124 return (innerDist < F0) ? innerDist : sqrt(outerDist);
4132template <MInt nDim,
class SysEqn>
4134 R(0, 0) = q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3];
4135 R(1, 1) = q[0] * q[0] - q[1] * q[1] + q[2] * q[2] - q[3] * q[3];
4136 R(2, 2) = q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3];
4138 R(0, 1) = F2 * (q[1] * q[2] + q[0] * q[3]);
4139 R(0, 2) = F2 * (q[1] * q[3] - q[0] * q[2]);
4140 R(1, 0) = F2 * (q[1] * q[2] - q[0] * q[3]);
4141 R(1, 2) = F2 * (q[2] * q[3] + q[0] * q[1]);
4142 R(2, 0) = F2 * (q[1] * q[3] + q[0] * q[2]);
4143 R(2, 1) = F2 * (q[2] * q[3] - q[0] * q[1]);
4151template <MInt nDim,
class SysEqn>
4159 C(i, k) += A(i, j) * B(j, k);
4170template <MInt nDim,
class SysEqn>
4178 C(i, k) += A(i, j) * B(k, j);
4189template <MInt nDim,
class SysEqn>
4197 C(i, k) += A(j, i) * B(j, k);
4208template <MInt nDim,
class SysEqn>
4213 c[i] += A(i, j) *
b[j];
4223template <MInt nDim,
class SysEqn>
4229 c[i] += A(j, i) *
b[j];
4239template <MInt nDim,
class SysEqn>
4241 if(m_fixedBodyComponentsRotation[0] && m_fixedBodyComponentsRotation[1] && m_fixedBodyComponentsRotation[2])
return;
4257 const MFloat dt2 = F1B2 * timeStep();
4263 for(
MLong i = 0; i < noDomains(); i++) {
4264 MLong tmpv = (((
MLong)m_noEmbeddedBodies) * (i + 1)) / ((
MLong)noDomains());
4265 if(tmpv > numeric_limits<MInt>::max())
mTerm(1,
"MInt overflow");
4266 bodyOffsets(i + 1) = (
MInt)tmpv;
4269 for(
MInt k = bodyOffsets(domainId()); k < bodyOffsets(domainId() + 1); k++) {
4270 ASSERT(k > -1 && k < m_noEmbeddedBodies,
"");
4271 computeRotationMatrix(R0, &(m_bodyQuaternionDt1[4 * k]));
4272 computeRotationMatrix(R, &(m_bodyQuaternion[4 * k]));
4273 const MFloat w = m_bodyQuaternionDt1[4 * k + 0];
4274 const MFloat x = m_bodyQuaternionDt1[4 * k + 1];
4275 const MFloat y = m_bodyQuaternionDt1[4 * k + 2];
4276 const MFloat z = m_bodyQuaternionDt1[4 * k + 3];
4277 for(
MInt i = 0; i < 3; i++)
4278 tmp[i] = m_bodyAngularVelocityDt1[k * 3 + i];
4279 matrixVectorProduct(q0, R0, tmp);
4280 for(
MInt i = 0; i < 3; i++)
4281 tmp[i] = m_bodyTorqueDt1[k * 3 + i];
4282 matrixVectorProduct(tq0, R0, tmp);
4284 for(
MInt i = 0; i < 3; i++)
4285 tmp[i] = m_bodyTorque[k * 3 + i];
4286 matrixVectorProduct(tq, R, tmp);
4288 const MFloat* momi = &(m_bodyMomentOfInertia[3 * k]);
4289 const MFloat f0 = (momi[2] - momi[1]) / momi[0];
4290 const MFloat f1 = (momi[0] - momi[2]) / momi[1];
4291 const MFloat f2 = (momi[1] - momi[0]) / momi[2];
4293 for(
MInt i = 0; i < 3; i++)
4294 tmp[i] = m_bodyAngularVelocity[k * 3 + i];
4295 matrixVectorProduct(&(q[0]), R, tmp);
4297 for(
MInt i = 0; i < 3; i++) {
4298 if(std::isnan(tq[i]) || std::isnan(tq0[i]) || std::isnan(q[i])) {
4299 if(domainId() == 0) {
4300 cerr <<
"error rotation omega " << k <<
" " << i <<
" " << tq0[i] <<
" " << tq[i] <<
" " << q[i] <<
" ("
4301 << m_bodyTorque[k * 3 + 0] <<
"," << m_bodyTorque[k * 3 + 1] <<
"," << m_bodyTorque[k * 3 + 2] <<
")"
4304 if(std::isnan(tq0[i])) tq0[i] = F0;
4311 const MInt maxit = 100;
4316 while(delta > 1e-10 && it < maxit) {
4318 W(0, 1) = dt2 * q[2] * f0;
4319 W(0, 2) = dt2 * q[1] * f0;
4320 W(1, 0) = dt2 * q[2] * f1;
4322 W(1, 2) = dt2 * q[0] * f1;
4323 W(2, 0) = dt2 * q[1] * f2;
4324 W(2, 1) = dt2 * q[0] * f2;
4329 for(
MInt i = 0; i < 3; i++)
4330 rhs[i] = q[i] - q0[i] - dt2 * (tq0[i] + tq[i]) / momi[i];
4331 rhs[0] += dt2 * f0 * (q0[1] * q0[2] + q[1] * q[2]);
4332 rhs[1] += dt2 * f1 * (q0[0] * q0[2] + q[0] * q[2]);
4333 rhs[2] += dt2 * f2 * (q0[0] * q0[1] + q[0] * q[1]);
4335 for(
MInt i = 0; i < 3; i++) {
4337 for(
MInt j = 0; j < 3; j++) {
4338 q[i] -= iW(i, j) * rhs(j);
4340 delta =
mMax(delta, fabs(q[i] - qq));
4344 if(it >= maxit && domainId() == 0) {
4345 cerr <<
"Newton iterations did not converge " << k << endl;
4348 for(
MInt i = 0; i < 3; i++) {
4349 if(std::isnan(q[i])) {
4350 if(domainId() == 0) {
4351 cerr <<
"error rotation quaternion " << k <<
" " << i <<
" " << q[i] << endl;
4352 cerr << q[0] <<
" " << q[1] <<
" " << q[2] <<
" " << endl;
4353 cerr << tq0[0] <<
" " << tq0[1] <<
" " << tq0[2] << endl;
4354 cerr << tq[0] <<
" " << tq[1] <<
" " << tq[2] << endl;
4379 for(
MInt i = 0; i < 4; i++)
4380 for(
MInt j = 0; j < 4; j++)
4381 W(i, j) = -F1B2 * dt2 * W(i, j);
4382 for(
MInt i = 0; i < 4; i++)
4385 rhs(0) = w + F1B2 * dt2 * (-x * q0[0] -
y * q0[1] - z * q0[2]);
4386 rhs(1) = x + F1B2 * dt2 * (w * q0[0] - z * q0[1] +
y * q0[2]);
4387 rhs(2) =
y + F1B2 * dt2 * (z * q0[0] + w * q0[1] - x * q0[2]);
4388 rhs(3) = z + F1B2 * dt2 * (-
y * q0[0] + x * q0[1] + w * q0[2]);
4392 for(
MInt i = 0; i < 4; i++) {
4393 m_bodyQuaternion[4 * k + i] = F0;
4394 for(
MInt j = 0; j < 4; j++) {
4395 m_bodyQuaternion[4 * k + i] += iW(i, j) * rhs(j);
4400 for(
MInt i = 0; i < 4; i++)
4401 abs +=
POW2(m_bodyQuaternion[4 * k + i]);
4402 for(
MInt i = 0; i < 4; i++)
4403 m_bodyQuaternion[4 * k + i] /= sqrt(abs);
4406 computeRotationMatrix(R, &(m_bodyQuaternion[4 * k]));
4407 matrixVectorProductTranspose(tmp, R, &(q[0]));
4409 for(
MInt i = 0; i < 3; i++) {
4410 if(m_fixedBodyComponentsRotation[i])
continue;
4411 m_bodyAngularVelocity[k * 3 + i] = tmp[i];
4413 for(
MInt i = 0; i < 3; i++) {
4414 tmp[i] = (q[i] - q0[i]) / timeStep();
4416 matrixVectorProductTranspose(tmp2, R, &(tmp[0]));
4417 for(
MInt i = 0; i < 3; i++) {
4418 if(m_fixedBodyComponentsRotation[i])
continue;
4419 m_bodyAngularAcceleration[k * 3 + i] = tmp2[i];
4424 for(
MInt i = 0; i < noDomains(); i++) {
4425 recvDispl(i + 1) = 4 * bodyOffsets(i + 1);
4426 recvCnt(i) = recvDispl(i + 1) - recvDispl(i);
4428 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, m_bodyQuaternion, &recvCnt[0], &recvDispl[0], MPI_DOUBLE,
4429 mpiComm(), AT_,
"MPI_IN_PLACE",
"m_bodyQuaternion");
4432 for(
MInt i = 0; i < noDomains(); i++) {
4433 recvDispl(i + 1) = 3 * bodyOffsets(i + 1);
4434 recvCnt(i) = recvDispl(i + 1) - recvDispl(i);
4436 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, m_bodyAngularVelocity, &recvCnt[0], &recvDispl[0], MPI_DOUBLE,
4437 mpiComm(), AT_,
"MPI_IN_PLACE",
"m_bodyAngularVelocity");
4438 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, m_bodyAngularAcceleration, &recvCnt[0], &recvDispl[0], MPI_DOUBLE,
4439 mpiComm(), AT_,
"MPI_IN_PLACE",
"m_bodyAngularAcceleration");
4447template <MInt nDim,
class SysEqn>
4451 if(!m_constructGField)
return;
4453 const MFloat qw = m_bodyQuaternion[4 * bodyId + 0];
4454 const MFloat qx = m_bodyQuaternion[4 * bodyId + 1];
4455 const MFloat qy = m_bodyQuaternion[4 * bodyId + 2];
4456 const MFloat qz = m_bodyQuaternion[4 * bodyId + 3];
4457 bodyRotation[0] = atan2(F2 * qw * qx + 2 * qy * qz, F1 - F2 * qw * qw - F2 * qz * qz);
4458 bodyRotation[1] = asin(F2 * qx * qz - F2 * qw * qy);
4459 bodyRotation[2] = atan2(F2 * qx * qy + F2 * qw * qz, F1 - F2 * qy * qy - F2 * qz * qz);
4467template <MInt nDim,
class SysEqn>
4471 if(!m_constructGField)
return;
4473 const MFloat qw = m_bodyQuaternionDt1[4 * bodyId + 0];
4474 const MFloat qx = m_bodyQuaternionDt1[4 * bodyId + 1];
4475 const MFloat qy = m_bodyQuaternionDt1[4 * bodyId + 2];
4476 const MFloat qz = m_bodyQuaternionDt1[4 * bodyId + 3];
4477 bodyRotation[0] = atan2(F2 * qw * qx + 2 * qy * qz, F1 - F2 * qw * qw - F2 * qz * qz);
4478 bodyRotation[1] = asin(F2 * qx * qz - F2 * qw * qy);
4479 bodyRotation[2] = atan2(F2 * qx * qy + F2 * qw * qz, F1 - F2 * qy * qy - F2 * qz * qz);
4487template <MInt nDim,
class SysEqn>
4491 if(!m_constructGField)
return;
4493 m_bodyQuaternion[bodyId * 4 + 0] = cos(F1B2 * bodyRotation[1]) * cos(F1B2 * (bodyRotation[2] + bodyRotation[0]));
4494 m_bodyQuaternion[bodyId * 4 + 1] = sin(F1B2 * bodyRotation[1]) * sin(F1B2 * (bodyRotation[2] - bodyRotation[0]));
4495 m_bodyQuaternion[bodyId * 4 + 2] = sin(F1B2 * bodyRotation[1]) * cos(F1B2 * (bodyRotation[2] - bodyRotation[0]));
4496 m_bodyQuaternion[bodyId * 4 + 3] = cos(F1B2 * bodyRotation[1]) * sin(F1B2 * (bodyRotation[2] + bodyRotation[0]));
4505template <MInt nDim,
class SysEqn>
4509 ASSERT(m_constructGField,
"");
4511 NEW_TIMER_GROUP_STATIC(t_initTimer,
"GFieldPredictor");
4512 NEW_TIMER_STATIC(t_timertotal,
"GFieldPredictor", t_initTimer);
4513 NEW_SUB_TIMER_STATIC(t_init,
"init", t_timertotal);
4514 NEW_SUB_TIMER_STATIC(t_advance,
"advance", t_timertotal);
4515 NEW_SUB_TIMER_STATIC(t_transfer,
"transfer", t_timertotal);
4517 m_structureStep = 0;
4519 if(!m_trackMovingBndry || globalTimeStep < m_trackMbStart || globalTimeStep >= m_trackMbEnd)
return;
4521 RECORD_TIMER_START(t_timertotal);
4522 RECORD_TIMER_START(t_init);
4526 if(m_constructGField && m_bodyTypeMb > 0) {
4528 }
else if(m_motionEquation == 0) {
4529 updateBodyProperties();
4531 if(m_bodyTypeMb != 0) {
4532 createPeriodicGhostBodies();
4535 RECORD_TIMER_STOP(t_init);
4536 RECORD_TIMER_STOP(t_timertotal);
4540#if defined _MB_DEBUG_ || !defined NDEBUG
4541 m_solutionDiverged =
false;
4542 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4543 for(
MInt i = 0; i < nDim; i++) {
4544 m_solutionDiverged += std::isnan(m_bodyForce[k * nDim + i]);
4546 for(
MInt i = 0; i < 3; i++) {
4547 m_solutionDiverged += std::isnan(m_bodyTorque[k * 3 + i]);
4550 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
4551 "m_solutionDiverged");
4552 if(m_solutionDiverged) {
4553 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4554 for(
MInt i = 0; i < nDim; i++) {
4555 m_log << m_bodyForce[k * nDim + i] <<
" ";
4558 for(
MInt i = 0; i < 3; i++) {
4559 m_log << m_bodyTorque[k * 3 + i] <<
" ";
4563 const MInt writeHaloBack = m_haloCellOutput;
4564 m_haloCellOutput =
true;
4565 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
4566 m_haloCellOutput = writeHaloBack;
4568 mTerm(1, AT_,
"Solution diverged before structure predictor handling.");
4572 RECORD_TIMER_STOP(t_init);
4573 RECORD_TIMER_START(t_advance);
4576 MBool& firstRun = m_static_constructGFieldPredictor_firstRun;
4577 MBool& adaptiveGravity = m_static_constructGFieldPredictor_adaptiveGravity;
4592 adaptiveGravity = Context::getSolverProperty<MBool>(
"adaptiveGravity", m_solverId, AT_, &adaptiveGravity);
4597 m_gravity[2] = -m_bodyForce[2] / m_bodyMass[0];
4600 m_log <<
"adaptive gravity: " << m_gravity[2] <<
" " << m_bodyForce[2] <<
" " << m_bodyForce[nDim + 2] << endl;
4604 switch(m_motionEquation) {
4607 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4608 for(
MInt i = 0; i < nDim; i++) {
4609 if(m_fixedBodyComponents[i])
continue;
4611 m_bodyAcceleration[k * nDim + i] = m_bodyAccelerationDt1[k * nDim + i];
4612 m_bodyCenter[k * nDim + i] =
4613 m_bodyCenterDt1[k * nDim + i]
4614 + timeStep() * m_bodyVelocityDt1[k * nDim + i]
4615 + F1B4 *
POW2(timeStep()) * (m_bodyAccelerationDt1[k * nDim + i] + m_bodyAcceleration[k * nDim + i]);
4616 m_bodyVelocity[k * nDim + i] =
4617 m_bodyVelocityDt1[k * nDim + i]
4618 + timeStep() * F1B2 * (m_bodyAccelerationDt1[k * nDim + i] + m_bodyAcceleration[k * nDim + i]);
4619 if(fabs(m_bodyCenter[k * nDim + i] - m_bodyCenterDt1[k * nDim + i])
4620 > c_cellLengthAtLevel(m_lsCutCellBaseLevel))
4621 cerr <<
"displ " << k <<
" " << i <<
" " << m_bodyCenter[k * nDim + i] <<
" "
4622 << m_bodyCenterDt1[k * nDim + i] << endl;
4624 m_bodyTemperature[k] =
4625 m_bodyTemperatureDt1[k] + timeStep() * m_bodyHeatFlux[k] / (m_capacityConstantVolumeRatio * m_bodyMass[k]);
4627 integrateBodyRotation();
4634 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4635 for(
MInt i = 0; i < nDim; i++) {
4636 if(m_fixedBodyComponents[i])
continue;
4638 m_bodyCenterDt2[k * nDim + i] = m_bodyCenterDt1[k * nDim + i];
4639 m_bodyCenterDt1[k * nDim + i] = m_bodyCenter[k * nDim + i];
4640 m_bodyVelocityDt1[k * nDim + i] = m_bodyVelocity[k * nDim + i];
4642 const MFloat A = F4 * PI * m_bodyDampingCoefficient[k] * m_bodyReducedFrequency[k];
4643 const MFloat B = F4 *
POW2(PI) *
POW2(m_bodyReducedFrequency[k]);
4644 const MFloat C = m_bodyForce[k * nDim + i] / m_bodyReducedMass[k];
4645 m_bodyCenter[k * nDim + i] =
4646 m_bodyCenterDt1[k * nDim + i] + timeStep() * m_bodyVelocityDt1[k * nDim + i]
4648 * (C - A * m_bodyVelocityDt1[k * nDim + i]
4649 - B * (m_bodyCenterDt1[k * nDim + i] - m_bodyNeutralCenter[k * nDim + i]));
4650 m_bodyVelocity[k * nDim + i] = (m_bodyCenter[k * nDim + i] - m_bodyCenterDt1[k * nDim + i]) / timeStep();
4651 m_bodyAcceleration[k * nDim + i] =
4652 (m_bodyCenter[k * nDim + i] - F2 * m_bodyCenterDt1[k * nDim + i] + m_bodyCenterDt2[k * nDim + i])
4662 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4663 for(
MInt i = 0; i < nDim; i++) {
4664 if(m_fixedBodyComponents[i])
continue;
4666 m_bodyCenterDt1[k * nDim + i] = m_bodyCenter[k * nDim + i];
4667 m_bodyVelocityDt1[k * nDim + i] = m_bodyVelocity[k * nDim + i];
4669 const MFloat A = F4 * PI * m_bodyDampingCoefficient[k] * m_bodyReducedFrequency[k];
4670 const MFloat B = F4 *
POW2(PI) *
POW2(m_bodyReducedFrequency[k]);
4671 const MFloat C = m_bodyForce[k * nDim + i] / m_bodyReducedMass[k];
4673 m_bodyVelocity[k * nDim + i] =
4674 (m_bodyVelocityDt1[k * nDim + i] * (F1 - F1B2 *
POW2(timeStep()) * B) + timeStep() * C
4675 - timeStep() * B * (m_bodyCenterDt1[k * nDim + i] - m_bodyNeutralCenter[k * nDim + i]))
4676 / (F1 + timeStep() * A + F1B2 *
POW2(timeStep()) * B);
4677 m_bodyCenter[k * nDim + i] =
4678 m_bodyCenterDt1[k * nDim + i]
4679 + timeStep() * F1B2 * (m_bodyVelocity[k * nDim + i] + m_bodyVelocityDt1[k * nDim + i]);
4680 m_bodyAcceleration[k * nDim + i] =
4681 (m_bodyVelocity[k * nDim + i] - m_bodyVelocityDt1[k * nDim + i]) / timeStep();
4690 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4691 for(
MInt i = 0; i < nDim; i++) {
4692 if(m_fixedBodyComponents[i])
continue;
4694 m_bodyForceDt1[k * nDim + i] = m_bodyForce[k * nDim + i];
4695 m_bodyCenterDt1[k * nDim + i] = m_bodyCenter[k * nDim + i];
4696 m_bodyVelocityDt1[k * nDim + i] = m_bodyVelocity[k * nDim + i];
4698 const MFloat A = F4 * PI * m_bodyDampingCoefficient[k] * m_bodyReducedFrequency[k];
4699 const MFloat B = F4 *
POW2(PI) *
POW2(m_bodyReducedFrequency[k]);
4701 const MFloat C = F1B2 * (m_bodyForce[k * nDim + i] + m_bodyForceDt1[k * nDim + i]) / m_bodyReducedMass[k];
4702 const MFloat beta = F1B2 * timeStep() * (A + F1B2 * timeStep() * B);
4704 m_bodyVelocity[k * nDim + i] =
4705 (m_bodyVelocityDt1[k * nDim + i] * (F1 - beta) + timeStep() * C
4706 - timeStep() * B * (m_bodyCenterDt1[k * nDim + i] - m_bodyNeutralCenter[k * nDim + i]))
4708 m_bodyCenter[k * nDim + i] =
4709 m_bodyCenterDt1[k * nDim + i]
4710 + timeStep() * F1B2 * (m_bodyVelocity[k * nDim + i] + m_bodyVelocityDt1[k * nDim + i]);
4711 m_bodyAcceleration[k * nDim + i] =
4712 (m_bodyVelocity[k * nDim + i] - m_bodyVelocityDt1[k * nDim + i]) / timeStep();
4721 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4722 for(
MInt i = 0; i < nDim; i++) {
4723 if(m_fixedBodyComponents[i])
continue;
4725 m_bodyAcceleration[k * nDim + i] =
4726 m_bodyAccelerationDt1[k * nDim + i]
4727 + (timeStep() / m_previousTimeStep)
4728 * (m_bodyAccelerationDt1[k * nDim + i] - m_bodyAccelerationDt2[k * nDim + i]);
4729 m_bodyCenter[k * nDim + i] =
4730 m_bodyCenterDt1[k * nDim + i] + timeStep() * m_bodyVelocityDt1[k * nDim + i]
4731 + F1B6 *
POW2(timeStep()) * (m_bodyAcceleration[k * nDim + i] + F2 * m_bodyAccelerationDt1[k * nDim + i]);
4732 m_bodyVelocity[k * nDim + i] =
4733 m_bodyVelocityDt1[k * nDim + i]
4734 + timeStep() * F1B2 * (m_bodyAcceleration[k * nDim + i] + m_bodyAccelerationDt1[k * nDim + i]);
4737 integrateBodyRotation();
4744 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4745 for(
MInt i = 0; i < nDim; i++) {
4746 if(m_fixedBodyComponents[i])
continue;
4749 m_bodyAcceleration[k * nDim + i] = F3 * m_bodyAccelerationDt1[k * nDim + i]
4750 - F3 * m_bodyAccelerationDt2[k * nDim + i]
4751 + m_bodyAccelerationDt3[k * nDim + i];
4752 m_bodyCenter[k * nDim + i] =
4753 m_bodyCenterDt1[k * nDim + i] + timeStep() * m_bodyVelocityDt1[k * nDim + i]
4754 + F1B24 *
POW2(timeStep())
4755 * (F3 * m_bodyAcceleration[k * nDim + i] + F10 * m_bodyAccelerationDt1[k * nDim + i]
4756 - m_bodyAccelerationDt2[k * nDim + i]);
4757 m_bodyVelocity[k * nDim + i] =
4758 m_bodyVelocityDt1[k * nDim + i]
4759 + timeStep() * F1B12
4760 * (F5 * m_bodyAcceleration[k * nDim + i] + F8 * m_bodyAccelerationDt1[k * nDim + i]
4761 - m_bodyAccelerationDt2[k * nDim + i]);
4764 integrateBodyRotation();
4770 mTerm(1, AT_,
"Invalid motion equation specified!");
4774 RECORD_TIMER_STOP(t_advance);
4775 RECORD_TIMER_START(t_transfer);
4777#if defined _MB_DEBUG_ || !defined NDEBUG
4779 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4780 for(
MInt i = 0; i < nDim; i++) {
4781 if(std::isnan(m_bodyVelocity[k * nDim + i]) || std::isnan(m_bodyCenter[k * nDim + i])
4782 || std::isnan(m_bodyAcceleration[k * nDim + i])) {
4788 m_solutionDiverged =
true;
4789 cerr <<
"Solution diverged (SPRED) at solver " << domainId() << endl;
4791 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
4792 "m_solutionDiverged");
4793 if(m_solutionDiverged) {
4794 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
4796 mTerm(1, AT_,
"Solution diverged after structure predictor handling.");
4800 createPeriodicGhostBodies();
4803 RECORD_TIMER_STOP(t_transfer);
4804 RECORD_TIMER_STOP(t_timertotal);
4805 DISPLAY_TIMER_OFFSET(t_timertotal, m_restartInterval);
4813template <MInt nDim,
class SysEqn>
4819 if(!m_trackMovingBndry || globalTimeStep < m_trackMbStart || globalTimeStep >= m_trackMbEnd)
return true;
4820 if(m_motionEquation == 0)
return true;
4825 ASSERT(m_constructGField,
"");
4827 NEW_TIMER_GROUP_STATIC(t_initTimer,
"GFieldCorrector");
4828 NEW_TIMER_STATIC(t_timertotal,
"GFieldCorrector", t_initTimer);
4829 NEW_SUB_TIMER_STATIC(t_init,
"init", t_timertotal);
4830 NEW_SUB_TIMER_STATIC(t_advance,
"advance", t_timertotal);
4831 NEW_SUB_TIMER_STATIC(t_transfer,
"transfer", t_timertotal);
4832 RECORD_TIMER_START(t_timertotal);
4833 RECORD_TIMER_START(t_init);
4840 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4841 for(
MInt i = 0; i < nDim; i++)
4842 oldX(k, i) = m_bodyCenter[k * nDim + i];
4843 for(
MInt i = 0; i < nDim; i++)
4844 oldV(k, i) = m_bodyVelocity[k * nDim + i];
4845 for(
MInt i = 0; i < 3; i++)
4846 oldW(k, i) = m_bodyAngularVelocity[k * 3 + i];
4847 for(
MInt i = 0; i < 4; i++)
4848 oldQ(k, i) = m_bodyQuaternion[k * 4 + i];
4851 RECORD_TIMER_STOP(t_init);
4852 RECORD_TIMER_START(t_advance);
4855 switch(m_motionEquation) {
4858 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4859 for(
MInt i = 0; i < nDim; i++) {
4860 if(m_fixedBodyComponents[i])
continue;
4862 m_bodyAcceleration[k * nDim + i] = (m_bodyForce[k * nDim + i]) / m_bodyMass[k] + m_gravity[i];
4863 m_bodyCenter[k * nDim + i] =
4864 m_bodyCenterDt1[k * nDim + i]
4865 + timeStep() * m_bodyVelocityDt1[k * nDim + i]
4866 + F1B4 *
POW2(timeStep()) * (m_bodyAccelerationDt1[k * nDim + i] + m_bodyAcceleration[k * nDim + i]);
4867 m_bodyVelocity[k * nDim + i] =
4868 m_bodyVelocityDt1[k * nDim + i]
4869 + timeStep() * F1B2 * (m_bodyAccelerationDt1[k * nDim + i] + m_bodyAcceleration[k * nDim + i]);
4870 if(fabs(m_bodyCenter[k * nDim + i] - m_bodyCenterDt1[k * nDim + i])
4871 > c_cellLengthAtLevel(m_lsCutCellBaseLevel))
4872 cerr <<
"displ " << k <<
" " << i <<
" " << m_bodyCenter[k * nDim + i] <<
" "
4873 << m_bodyCenterDt1[k * nDim + i] << endl;
4875 m_bodyTemperature[k] = F1B2
4876 * (m_bodyTemperature[k] + m_bodyTemperatureDt1[k]
4877 + timeStep() * (m_bodyHeatFlux[k] / (m_capacityConstantVolumeRatio * m_bodyMass[k])));
4879 integrateBodyRotation();
4939 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4940 for(
MInt i = 0; i < nDim; i++) {
4941 if(m_fixedBodyComponents[i])
continue;
4943 const MFloat A = F4 * PI * m_bodyDampingCoefficient[k] * m_bodyReducedFrequency[k];
4944 const MFloat B = F4 *
POW2(PI) *
POW2(m_bodyReducedFrequency[k]);
4945 const MFloat C = m_bodyForce[k * nDim + i] / m_bodyReducedMass[k];
4947 m_bodyVelocity[k * nDim + i] =
4948 (m_bodyVelocityDt1[k * nDim + i] * (F1 - F1B2 *
POW2(timeStep()) * B) + timeStep() * C
4949 - timeStep() * B * (m_bodyCenterDt1[k * nDim + i] - m_bodyNeutralCenter[k * nDim + i]))
4950 / (F1 + timeStep() * A + F1B2 *
POW2(timeStep()) * B);
4951 m_bodyCenter[k * nDim + i] =
4952 m_bodyCenterDt1[k * nDim + i]
4953 + timeStep() * F1B2 * (m_bodyVelocity[k * nDim + i] + m_bodyVelocityDt1[k * nDim + i]);
4954 m_bodyAcceleration[k * nDim + i] =
4955 (m_bodyVelocity[k * nDim + i] - m_bodyVelocityDt1[k * nDim + i]) / timeStep();
4964 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4965 for(
MInt i = 0; i < nDim; i++) {
4966 if(m_fixedBodyComponents[i])
continue;
4968 const MFloat A = F4 * PI * m_bodyDampingCoefficient[k] * m_bodyReducedFrequency[k];
4969 const MFloat B = F4 *
POW2(PI) *
POW2(m_bodyReducedFrequency[k]);
4970 const MFloat C = F1B2 * (m_bodyForce[k * nDim + i] + m_bodyForceDt1[k * nDim + i]) / m_bodyReducedMass[k];
4971 const MFloat beta = F1B2 * timeStep() * (A + F1B2 * timeStep() * B);
4973 m_bodyVelocity[k * nDim + i] =
4974 (m_bodyVelocityDt1[k * nDim + i] * (F1 - beta) + timeStep() * C
4975 - timeStep() * B * (m_bodyCenterDt1[k * nDim + i] - m_bodyNeutralCenter[k * nDim + i]))
4977 m_bodyCenter[k * nDim + i] =
4978 m_bodyCenterDt1[k * nDim + i]
4979 + timeStep() * F1B2 * (m_bodyVelocity[k * nDim + i] + m_bodyVelocityDt1[k * nDim + i]);
4980 m_bodyAcceleration[k * nDim + i] =
4981 (m_bodyVelocity[k * nDim + i] - m_bodyVelocityDt1[k * nDim + i]) / timeStep();
4990 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
4991 for(
MInt i = 0; i < nDim; i++) {
4992 if(m_fixedBodyComponents[i])
continue;
4994 m_bodyAcceleration[k * nDim + i] = (m_bodyForce[k * nDim + i] + m_gravity[i]) / m_bodyMass[k];
4995 m_bodyCenter[k * nDim + i] =
4996 m_bodyCenterDt1[k * nDim + i] + timeStep() * m_bodyVelocityDt1[k * nDim + i]
4997 + F1B6 *
POW2(timeStep()) * (m_bodyAcceleration[k * nDim + i] + F2 * m_bodyAccelerationDt1[k * nDim + i]);
4998 m_bodyVelocity[k * nDim + i] =
4999 m_bodyVelocityDt1[k * nDim + i]
5000 + timeStep() * F1B2 * (m_bodyAcceleration[k * nDim + i] + m_bodyAccelerationDt1[k * nDim + i]);
5003 integrateBodyRotation();
5010 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
5011 for(
MInt i = 0; i < nDim; i++) {
5012 if(m_fixedBodyComponents[i])
continue;
5014 m_bodyAcceleration[k * nDim + i] = (m_bodyForce[k * nDim + i] + m_gravity[i]) / m_bodyMass[k];
5015 m_bodyCenter[k * nDim + i] =
5016 m_bodyCenterDt1[k * nDim + i] + timeStep() * m_bodyVelocityDt1[k * nDim + i]
5017 + F1B24 *
POW2(timeStep())
5018 * (F3 * m_bodyAcceleration[k * nDim + i] + F10 * m_bodyAccelerationDt1[k * nDim + i]
5019 - m_bodyAccelerationDt2[k * nDim + i]);
5020 m_bodyVelocity[k * nDim + i] =
5021 m_bodyVelocityDt1[k * nDim + i]
5022 + timeStep() * F1B12
5023 * (F5 * m_bodyAcceleration[k * nDim + i] + F8 * m_bodyAccelerationDt1[k * nDim + i]
5024 - m_bodyAccelerationDt2[k * nDim + i]);
5027 integrateBodyRotation();
5033 mTerm(1, AT_,
"Invalid motion equation specified!");
5037 RECORD_TIMER_STOP(t_advance);
5038 RECORD_TIMER_START(t_transfer);
5040#if defined _MB_DEBUG_ || !defined NDEBUG
5042 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
5043 for(
MInt i = 0; i < nDim; i++) {
5044 if(std::isnan(m_bodyVelocity[k * nDim + i]) || std::isnan(m_bodyCenter[k * nDim + i])
5045 || std::isnan(m_bodyAcceleration[k * nDim + i])) {
5051 m_solutionDiverged =
true;
5052 cerr <<
"Solution diverged (SCORR) at solver " << domainId() << endl;
5054 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
5055 "m_solutionDiverged");
5056 if(m_solutionDiverged) {
5057 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
5059 mTerm(1, AT_,
"Solution diverged after structure corrector handling.");
5063 createPeriodicGhostBodies();
5075 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
5076 for(
MInt i = 0; i < nDim; i++) {
5077 if(m_fixedBodyComponents[i])
continue;
5078 MFloat dx = fabs(m_bodyCenter[k * nDim + i] - oldX(k, i));
5079 MFloat du = fabs(m_bodyVelocity[k * nDim + i] - oldV(k, i));
5080 dumax =
mMax(dumax, du);
5081 dxmax =
mMax(dxmax, dx);
5087 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
5088 for(
MInt i = 0; i < 3; i++) {
5089 if(m_fixedBodyComponentsRotation[i])
continue;
5090 MFloat dw = fabs(m_bodyAngularVelocity[k * 3 + i] - oldW(k, i));
5091 dwmax =
mMax(dwmax, dw);
5094 for(
MInt i = 0; i < 4; i++) {
5095 MFloat dr = fabs(m_bodyQuaternion[k * 4 + i] - oldQ(k, i));
5096 drmax =
mMax(drmax, dr);
5101 dxavg /= ((
MFloat)m_noEmbeddedBodies);
5102 duavg /= ((
MFloat)m_noEmbeddedBodies);
5103 dravg /= ((
MFloat)m_noEmbeddedBodies);
5104 dwavg /= ((
MFloat)m_noEmbeddedBodies);
5107 cerr0 <<
"corr: " <<
globalTimeStep <<
" (" << m_structureStep <<
"): " << dxmax <<
" " << dumax <<
" / " << drmax
5108 <<
" " << dwmax <<
" (" << dxavg <<
" " << duavg <<
" / " << dravg <<
" " << dwavg <<
")" << endl;
5111 RECORD_TIMER_STOP(t_transfer);
5112 RECORD_TIMER_STOP(t_timertotal);
5113 DISPLAY_TIMER_OFFSET(t_timertotal, m_restartInterval);
5115 if((dxmax < m_FSIToleranceX) && (dumax < m_FSIToleranceU) && (drmax < m_FSIToleranceR) && (dwmax < m_FSIToleranceW)) {
5127template <MInt nDim,
class SysEqn>
5130 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5131 for(
MInt j = 0; j < noHaloCells(i); j++) {
5132 MInt cellId = haloCellId(i, j);
5134 if(c_noChildren(cellId) > 0)
continue;
5135 if(!a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
5137 for(
MInt var = 0; var < m_noFVars; var++) {
5138 a_rightHandSide(cellId, var) = F0;
5150template <MInt nDim,
class SysEqn>
5154 const MInt noCBytes = a_noCells() * m_noCVars *
sizeof(
MFloat);
5155 const MInt noFBytes = a_noCells() * m_noFVars *
sizeof(
MFloat);
5156 MFloat* RESTRICT cVars = (
MFloat*)(&(a_variable(0, 0)));
5157 MFloat* RESTRICT oCVars = (
MFloat*)(&(a_oldVariable(0, 0)));
5159 memcpy(oCVars, cVars, noCBytes);
5160 memcpy(&(m_rhs0[0][0]), &(a_rightHandSide(0, 0)), noFBytes);
5162 if(m_dualTimeStepping) memcpy(&(m_cellVolumesDt2[0]), &(m_cellVolumesDt1[0]), a_noCells() *
sizeof(
MFloat));
5163 memcpy(&(m_cellVolumesDt1[0]), &(a_cellVolume(0)), a_noCells() *
sizeof(
MFloat));
5165 for(
MInt cellId = 0; cellId < m_bndryGhostCellsOffset; cellId++) {
5166 a_hasProperty(cellId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::IsInactive);
5169 advanceExternalSource();
5171 m_nearBoundaryBackup.clear();
5173 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
5174 MInt cellId = m_bndryLayerCells[c];
5175 if(!m_constructGField) {
5176 ASSERT(a_hasProperty(cellId, SolverCell::NearWall),
5177 to_string(m_solverId) +
" " + to_string(
globalDomainId()) +
" " + to_string(domainId()));
5180 vector<MFloat> tmp(max(m_noCVars + m_noFVars, 0) + 1);
5181 tmp[0] = m_cellVolumesDt1[cellId];
5183 for(
MInt v = 0; v < m_noCVars; v++) {
5184 tmp[1 + v] = a_oldVariable(cellId, v);
5187 for(
MInt v = 0; v < m_noFVars; v++) {
5188 tmp[1 + m_noCVars + v] = m_rhs0[cellId][v];
5191 m_nearBoundaryBackup.insert(make_pair(cellId, tmp));
5194 m_oldBndryCells.clear();
5195 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
5196 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
5198 ASSERT(!a_isBndryGhostCell(cellId),
"");
5199 if(!m_constructGField) {
5200 ASSERT(a_hasProperty(cellId, SolverCell::IsMovingBnd),
"");
5203 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
5204 a_hasProperty(cellId, SolverCell::IsMovingBnd) =
false;
5205 a_hasProperty(cellId, SolverCell::NearWall) =
false;
5208 m_oldBndryCells.insert(make_pair(cellId, m_sweptVolume[bndryId]));
5210 m_reComputedBndry =
false;
5212 for(
MUint it = 0; it < m_temporarilyLinkedCells.size(); it++) {
5213 const MInt cellId = get<1>(m_temporarilyLinkedCells[it]);
5214 a_hasProperty(cellId, SolverCell::IsTempLinked) =
false;
5216 m_temporarilyLinkedCells.clear();
5217 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5218 m_linkedWindowCells[i].clear();
5219 m_linkedHaloCells[i].clear();
5228template <MInt nDim,
class SysEqn>
5232 const size_t dim3 = 3 * m_noEmbeddedBodies *
sizeof(
MFloat);
5233 const size_t dim4 = 4 * m_noEmbeddedBodies *
sizeof(
MFloat);
5234 const size_t dimD = nDim * m_noEmbeddedBodies *
sizeof(
MFloat);
5236 if(m_motionEquation > 1) {
5237 memcpy(m_bodyVelocityDt2, m_bodyVelocityDt1, dimD);
5238 memcpy(m_bodyCenterDt2, m_bodyCenterDt1, dimD);
5239 memcpy(m_bodyAccelerationDt3, m_bodyAccelerationDt2, dimD);
5240 memcpy(m_bodyAccelerationDt2, m_bodyAccelerationDt1, dimD);
5243 memcpy(m_bodyVelocityDt1, m_bodyVelocity, dimD);
5244 memcpy(m_bodyCenterDt1, m_bodyCenter, dimD);
5245 memcpy(m_bodyAccelerationDt1, m_bodyAcceleration, dimD);
5246 memcpy(m_bodyTorqueDt1, m_bodyTorque, dim3);
5247 memcpy(m_bodyAngularVelocityDt1, m_bodyAngularVelocity, dim3);
5248 memcpy(m_bodyAngularAccelerationDt1, m_bodyAngularAcceleration, dim3);
5249 memcpy(m_bodyQuaternionDt1, m_bodyQuaternion, dim4);
5250 memcpy(m_bodyTemperatureDt1, m_bodyTemperature, m_noEmbeddedBodies *
sizeof(
MFloat));
5252 if(!m_constructGField)
return;
5254 if(m_noPointParticles > 0) {
5255 m_fvBndryCnd->recorrectCellCoordinates();
5257 const MInt heatRelated = 2;
5258 const MInt dataSize = 7 * 3 + 2 * 4 + heatRelated;
5269 map<MLong, MInt> globalToLocal;
5274 for(
MInt i = 0; i < noNeighborDomains(); ++i) {
5275 sendVars[i].clear();
5276 recvVars[i].clear();
5281 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
5282 if(!a_isHalo(cellId) && c_globalId(cellId) > -1) {
5283 globalToLocal[(
MLong)c_globalId(cellId)] = cellId;
5285 globalIds(cellId) = (
MLong)c_globalId(cellId);
5288 exchangeDataFV(&globalIds[0]);
5290 for(
MUint p = 0; p < m_particleCellLink.size(); p++) {
5291 const MInt cellId = m_particleCellLink[p];
5292 const MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(cellId);
5293 MInt dirCode[3] = {0, 0, 0};
5294 for(
MInt i = 0; i < nDim; i++) {
5295 if(m_particleCoords[nDim * p + i] < a_coordinate(cellId, i) - cellHalfLength)
5297 else if(m_particleCoords[nDim * p + i] > a_coordinate(cellId, i) + cellHalfLength)
5300 if(dirCode[0] != 0 || dirCode[1] != 0 || dirCode[2] != 0) {
5301 MInt nghbrId = cellId;
5302 for(
MInt i = 0; i < nDim; i++) {
5303 if(dirCode[i] == 0)
continue;
5304 MInt dir = (dirCode[i] > 0) ? 2 * i + 1 : 2 * i;
5305 if(dirCode[i] > 0 && a_hasNeighbor(nghbrId, dir) == 0)
mTerm(1, AT_,
"particle moved into void");
5306 nghbrId = c_neighborId(nghbrId, dir);
5308 while(c_noChildren(nghbrId) > 0) {
5310 for(
MUint i = 0; i < nDim; i++) {
5311 if(m_particleCoords[nDim * p + i] > a_coordinate(nghbrId, i)) child +=
IPOW2(i);
5313 nghbrId = c_childId(nghbrId, child);
5314 if(nghbrId < 0 || nghbrId >= a_noCells())
mTerm(1, AT_,
"Point particle linking failed.");
5316 if(!a_isHalo(nghbrId)) {
5317 m_particleCellLink[p] = nghbrId;
5319 MLong globalId = globalIds(nghbrId);
5320 MInt nghbrDomain = -1;
5321 for(
MInt i = 0; i < noNeighborDomains(); ++i) {
5322 if(globalId >= domainOffset(neighborDomain(i)) && globalId < domainOffset(neighborDomain(i) + 1)) {
5327 if(nghbrDomain < 0)
mTerm(1, AT_,
"Neighbor domain not found " + to_string(globalId));
5328 for(
MInt i = 0; i < 3; i++) {
5329 sendVars[nghbrDomain].push_back(m_particleCoords[nDim * p + i] - a_coordinate(nghbrId, i));
5331 for(
MInt i = 0; i < 3; i++) {
5332 sendVars[nghbrDomain].push_back(m_particleVelocity[nDim * p + i]);
5334 for(
MInt i = 0; i < 3; i++) {
5335 sendVars[nghbrDomain].push_back(m_particleAcceleration[nDim * p + i]);
5337 for(
MInt i = 0; i < 4; i++) {
5338 sendVars[nghbrDomain].push_back(m_particleQuaternions[4 * p + i]);
5340 for(
MInt i = 0; i < 3; i++) {
5341 sendVars[nghbrDomain].push_back(m_particleAngularVelocity[3 * p + i]);
5343 for(
MInt i = 0; i < 3; i++) {
5344 sendVars[nghbrDomain].push_back(m_particleAngularAcceleration[3 * p + i]);
5346 for(
MInt i = 0; i < 4; i++) {
5347 sendVars[nghbrDomain].push_back(m_particleShapeParams[4 * p + i]);
5349 for(
MInt i = 0; i < 3; i++) {
5350 sendVars[nghbrDomain].push_back(m_particleRadii[3 * p + i]);
5353 sendVars[nghbrDomain].push_back(m_particleTemperature[p]);
5354 sendVars[nghbrDomain].push_back(m_particleHeatFlux[p]);
5356 sendIds[nghbrDomain].push_back(globalId);
5357 m_particleCellLink[p] = -1;
5358 sendCount(neighborDomain(nghbrDomain))++;
5359 sendParticleGlobalIds[nghbrDomain].push_back(m_particleGlobalId[p]);
5363 MPI_Alltoall(&sendCount[0], 1, MPI_INT, &recvCount[0], 1, MPI_INT, mpiComm(), AT_,
"sendCount[0]",
"recvCount[0]");
5364 for(
MInt i = 0; i < noNeighborDomains(); ++i) {
5365 if(recvCount[neighborDomain(i)] > 0) {
5366 recvVars[i].resize(dataSize * recvCount[neighborDomain(i)]);
5367 recvIds[i].resize(recvCount[neighborDomain(i)]);
5368 recvParticleGlobalIds[i].resize(recvCount[neighborDomain(i)]);
5371 sendReq.
fill(MPI_REQUEST_NULL);
5373 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5374 if(sendCount[neighborDomain(i)] == 0)
continue;
5375 MPI_Issend(&sendIds[i].front(), sendCount[neighborDomain(i)], MPI_LONG, neighborDomain(i), 78, mpiComm(),
5376 &sendReq[cnt], AT_,
"sendIds[i].front()");
5379 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5380 if(recvCount[neighborDomain(i)] == 0)
continue;
5381 MPI_Recv(&recvIds[i].front(), recvCount[neighborDomain(i)], MPI_LONG, neighborDomain(i), 78, mpiComm(),
5382 MPI_STATUS_IGNORE, AT_,
"recvIds[i].front()");
5384 if(cnt > 0)
MPI_Waitall(cnt, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
5385 sendReq.
fill(MPI_REQUEST_NULL);
5387 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5388 if(sendCount[neighborDomain(i)] == 0)
continue;
5389 MPI_Issend(&sendVars[i].front(), dataSize * sendCount[neighborDomain(i)], MPI_DOUBLE, neighborDomain(i), 79,
5390 mpiComm(), &sendReq[cnt], AT_,
"sendVars[i].front()");
5393 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5394 if(recvCount[neighborDomain(i)] == 0)
continue;
5395 MPI_Recv(&recvVars[i].front(), dataSize * recvCount[neighborDomain(i)], MPI_DOUBLE, neighborDomain(i), 79,
5396 mpiComm(), MPI_STATUS_IGNORE, AT_,
"recvVars[i].front()");
5398 if(cnt > 0)
MPI_Waitall(cnt, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
5399 sendReq.
fill(MPI_REQUEST_NULL);
5401 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5402 if(sendCount[neighborDomain(i)] == 0)
continue;
5403 MPI_Issend(&sendParticleGlobalIds[i].front(), sendCount[neighborDomain(i)], MPI_INT, neighborDomain(i), 80,
5404 mpiComm(), &sendReq[cnt], AT_,
"sendParticleGlobalIds[i].front()");
5407 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5408 if(recvCount[neighborDomain(i)] == 0)
continue;
5409 MPI_Recv(&recvParticleGlobalIds[i].front(), recvCount[neighborDomain(i)], MPI_INT, neighborDomain(i), 80,
5410 mpiComm(), MPI_STATUS_IGNORE, AT_,
"recvParticleGlobalIds[i].front()");
5413 if(cnt > 0)
MPI_Waitall(cnt, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
5415 vector<MFloat> tmpCoord;
5416 vector<MFloat> tmpVel;
5417 vector<MFloat> tmpTemp;
5418 vector<MFloat> tmpHeat;
5419 vector<MFloat> tmpAcc;
5420 vector<MFloat> tmpCoordsInitial;
5421 vector<MFloat> tmpQuat;
5422 vector<MFloat> tmpAngVel;
5423 vector<MFloat> tmpAngAcc;
5424 vector<MFloat> tmpShape;
5425 vector<MFloat> tmpRad;
5426 vector<MInt> tmpLink;
5427 vector<MInt> tmpParticleGlobalId;
5440 tmpParticleGlobalId.clear();
5442 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
5443 if(m_particleCellLink[p] > -1) {
5444 tmpLink.push_back(m_particleCellLink[p]);
5445 for(
MInt i = 0; i < 3; i++)
5446 tmpCoord.push_back(m_particleCoords[nDim * p + i]);
5447 for(
MInt i = 0; i < 3; i++)
5448 tmpVel.push_back(m_particleVelocity[nDim * p + i]);
5449 for(
MInt i = 0; i < 3; i++)
5450 tmpAcc.push_back(m_particleAcceleration[nDim * p + i]);
5451 for(
MInt i = 0; i < 4; i++)
5452 tmpQuat.push_back(m_particleQuaternions[4 * p + i]);
5453 for(
MInt i = 0; i < 3; i++)
5454 tmpAngVel.push_back(m_particleAngularVelocity[3 * p + i]);
5455 for(
MInt i = 0; i < 3; i++)
5456 tmpAngAcc.push_back(m_particleAngularAcceleration[3 * p + i]);
5457 for(
MInt i = 0; i < 4; i++)
5458 tmpShape.push_back(m_particleShapeParams[4 * p + i]);
5459 for(
MInt i = 0; i < 3; i++)
5460 tmpRad.push_back(m_particleRadii[3 * p + i]);
5461 tmpTemp.push_back(m_particleTemperature[p]);
5462 tmpHeat.push_back(m_particleHeatFlux[p]);
5463 tmpParticleGlobalId.push_back(m_particleGlobalId[p]);
5467 m_particleCellLink = tmpLink;
5468 m_particleCoords = tmpCoord;
5469 m_particleVelocity = tmpVel;
5470 m_particleTemperature = tmpTemp;
5471 m_particleHeatFlux = tmpHeat;
5472 m_particleAcceleration = tmpAcc;
5473 m_particleQuaternions = tmpQuat;
5474 m_particleAngularVelocity = tmpAngVel;
5475 m_particleAngularAcceleration = tmpAngAcc;
5476 m_particleShapeParams = tmpShape;
5477 m_particleRadii = tmpRad;
5478 m_particleGlobalId = tmpParticleGlobalId;
5480 for(
MInt i = 0; i < noNeighborDomains(); i++) {
5481 for(
MInt k = 0; k < recvCount[neighborDomain(i)]; k++) {
5482 if(globalToLocal.count(recvIds[i][k]) == 0)
mTerm(1, AT_,
"Global id invalid " + to_string(recvIds[i][k]));
5483 MInt cellId = globalToLocal[recvIds[i][k]];
5484 if(cellId < 0 || cellId >= a_noCells() || c_globalId(cellId) != recvIds[i][k]) {
5485 cerr << cellId <<
" " << c_globalId(cellId) <<
" " << recvIds[i][k] << endl;
5487 "Global id mismatch " + to_string(cellId) +
" " + to_string(c_globalId(cellId)) +
" "
5488 + to_string(recvIds[i][k]));
5490 m_particleCellLink.push_back(cellId);
5493 for(
MInt j = 0; j < 3; j++) {
5494 m_particleCoords.push_back(a_coordinate(cellId, j) + recvVars[i][dataSize * k +
id]);
5497 for(
MInt j = 0; j < 3; j++) {
5498 m_particleVelocity.push_back(recvVars[i][dataSize * k +
id]);
5501 for(
MInt j = 0; j < 3; j++) {
5502 m_particleAcceleration.push_back(recvVars[i][dataSize * k +
id]);
5505 for(
MInt j = 0; j < 4; j++) {
5506 m_particleQuaternions.push_back(recvVars[i][dataSize * k +
id]);
5509 for(
MInt j = 0; j < 3; j++) {
5510 m_particleAngularVelocity.push_back(recvVars[i][dataSize * k +
id]);
5513 for(
MInt j = 0; j < 3; j++) {
5514 m_particleAngularAcceleration.push_back(recvVars[i][dataSize * k +
id]);
5517 for(
MInt j = 0; j < 4; j++) {
5518 m_particleShapeParams.push_back(recvVars[i][dataSize * k +
id]);
5521 for(
MInt j = 0; j < 3; j++) {
5522 m_particleRadii.push_back(recvVars[i][dataSize * k +
id]);
5525 m_particleTemperature.push_back(recvVars[i][dataSize * k +
id]);
5527 m_particleHeatFlux.push_back(recvVars[i][dataSize * k +
id]);
5529 m_particleGlobalId.push_back(recvParticleGlobalIds[i][k]);
5533 m_fvBndryCnd->rerecorrectCellCoordinates();
5535 m_noPointParticlesLocal = (signed)m_particleCellLink.size();
5536 m_particleAccelerationDt1 = m_particleAcceleration;
5537 m_particleVelocityDt1 = m_particleVelocity;
5538 m_particleTemperatureDt1 = m_particleTemperature;
5539 m_particleCoordsDt1 = m_particleCoords;
5540 m_particleAngularAccelerationDt1 = m_particleAngularAcceleration;
5541 m_particleAngularVelocityDt1 = m_particleAngularVelocity;
5542 m_particleQuaternionsDt1 = m_particleQuaternions;
5543 m_particleVelocityFluid.resize(m_particleVelocity.size());
5544 m_particleFluidTemperature.resize(m_particleTemperature.size());
5545 m_particleVelocityGradientFluid.resize(nDim * m_particleVelocityFluid.size());
5547 if(m_noPointParticles == 1) {
5548 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
5549 cerr << domainId() <<
": particle " <<
globalTimeStep <<
" / " << m_particleCoords[nDim * p] <<
" "
5550 << m_particleCoords[nDim * p + 1] <<
" " << m_particleCoords[nDim * p + 2] <<
" / "
5551 << m_particleVelocity[nDim * p] <<
" " << m_particleVelocity[nDim * p + 1] <<
" "
5552 << m_particleVelocity[nDim * p + 2] <<
"/ " << m_particleTemperature[p] <<
"/ " << m_particleHeatFlux[p]
5564template <MInt nDim,
class SysEqn>
5568 if(!m_dualTimeStepping) {
5569 m_physicalTimeDt1 = m_physicalTime;
5570 m_physicalTime += timeStep();
5573 m_time += timeStep() * m_timeRef;
5581template <MInt nDim,
class SysEqn>
5586 const MFloat cellHalfLength = F1B2 * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
5587 const MFloat limitDistance = F2 * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
5588 const MFloat nodeStencil[3][8] = {
5589 {-F1, F1, -F1, F1, -F1, F1, -F1, F1}, {-F1, -F1, F1, F1, -F1, -F1, F1, F1}, {-F1, -F1, -F1, -F1, F1, F1, F1, F1}};
5590 const MInt dirStencil[8][3] = {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0},
5591 {0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {1, 1, 1}};
5593 m_bndryCandidateIds.resize(a_noCells());
5594 for(
MInt c = 0; c < a_noCells(); c++)
5595 m_bndryCandidateIds[c] = -1;
5596 m_bndryCandidates.clear();
5597 m_candidateNodeSet.clear();
5598 m_candidateNodeValues.clear();
5599 m_noBndryCandidates = 0;
5601 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
5602 const MInt cellId = m_bndryLayerCells[c];
5604 if(a_level(cellId) < m_lsCutCellMinLevel || !c_isLeafCell(cellId))
continue;
5606 ASSERT(m_bodyTypeMb > 0,
"");
5607 MFloat phi = a_levelSetValuesMb(cellId, 0);
5609 m_bndryCandidateIds[cellId] = -1;
5610 MInt candidate = -1;
5611 if(fabs(phi) < limitDistance) {
5612 candidate = m_noBndryCandidates;
5613 m_bndryCandidates.push_back(cellId);
5614 m_bndryCandidateIds[cellId] = candidate;
5615 m_noBndryCandidates++;
5618 m_candidateNodeSet.resize(m_noBndryCandidates * m_noCellNodes);
5619 m_candidateNodeValues.resize(m_noLevelSetsUsedForMb * m_noBndryCandidates * m_noCellNodes);
5620 for(
MInt candidate = 0; candidate < m_noBndryCandidates; candidate++) {
5621 for(
MInt node = 0; node < m_noCellNodes; node++) {
5622 m_candidateNodeSet[candidate * m_noCellNodes + node] =
false;
5626 for(
MInt candidate = 0; candidate < m_noBndryCandidates; candidate++) {
5627 MInt cellId = m_bndryCandidates[candidate];
5629 for(
MInt node = 0; node < m_noCellNodes; node++) {
5630 if(m_candidateNodeSet[candidate * m_noCellNodes + node])
continue;
5631 for(
MInt i = 0; i < nDim; i++) {
5632 dummyCoord[i] = a_coordinate(cellId, i) + nodeStencil[i][node] * cellHalfLength;
5634 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5635 const MInt b = a_associatedBodyIds(cellId, set);
5636 MFloat phi = m_bodyDistThreshold + 1e-14;
5638 phi = getDistance(&dummyCoord[0],
b);
5640 m_candidateNodeValues[IDX_LSSETNODES(candidate, node, set)] = phi;
5642 m_candidateNodeSet[candidate * m_noCellNodes + node] =
true;
5645 for(
MInt i = 0; i < nDim; i++) {
5646 MInt dir0 = 2 * i + dirStencil[node][i];
5647 if(a_hasNeighbor(cellId, dir0) == 0)
continue;
5648 MInt nghbrId0 = c_neighborId(cellId, dir0);
5649 MInt n0 = (dirStencil[node][i] == 0) ? node +
IPOW2(i) : node -
IPOW2(i);
5650 MInt cand0 = m_bndryCandidateIds[nghbrId0];
5653 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5654 if(a_associatedBodyIds(nghbrId0, set) == a_associatedBodyIds(cellId, set)) {
5655 m_candidateNodeValues[IDX_LSSETNODES(cand0, n0, set)] =
5656 m_candidateNodeValues[IDX_LSSETNODES(candidate, node, set)];
5660 if(match) m_candidateNodeSet[cand0 * m_noCellNodes + n0] =
true;
5662 for(
MInt j = i + 1; j < nDim; j++) {
5663 MInt dir1 = 2 * j + dirStencil[node][j];
5664 if(a_hasNeighbor(nghbrId0, dir1) == 0)
continue;
5665 MInt nghbrId1 = c_neighborId(nghbrId0, dir1);
5666 MInt n1 = (dirStencil[node][j] == 0) ? n0 +
IPOW2(j) : n0 -
IPOW2(j);
5667 MInt cand1 = m_bndryCandidateIds[nghbrId1];
5670 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5671 if(a_associatedBodyIds(nghbrId1, set) == a_associatedBodyIds(cellId, set)) {
5672 m_candidateNodeValues[IDX_LSSETNODES(cand1, n1, set)] =
5673 m_candidateNodeValues[IDX_LSSETNODES(candidate, node, set)];
5677 if(match) m_candidateNodeSet[cand1 * m_noCellNodes + n1] =
true;
5679 for(
MInt k = j + 1; k < nDim; k++) {
5680 MInt dir2 = 2 * k + dirStencil[node][k];
5681 if(a_hasNeighbor(nghbrId1, dir2) == 0)
continue;
5682 MInt nghbrId2 = c_neighborId(nghbrId1, dir2);
5683 MInt n2 = (dirStencil[node][k] == 0) ? n1 +
IPOW2(k) : n1 -
IPOW2(k);
5684 MInt cand2 = m_bndryCandidateIds[nghbrId2];
5687 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5688 if(a_associatedBodyIds(nghbrId2, set) == a_associatedBodyIds(cellId, set)) {
5689 m_candidateNodeValues[IDX_LSSETNODES(cand2, n2, set)] =
5690 m_candidateNodeValues[IDX_LSSETNODES(candidate, node, set)];
5694 if(match) m_candidateNodeSet[cand2 * m_noCellNodes + n2] =
true;
5713template <MInt nDim,
class SysEqn>
5717 ASSERT(!m_constructGField,
"");
5719 for(
MInt cnd = 0; cnd < m_noBndryCandidates; cnd++) {
5720 m_bndryCandidateIds[m_bndryCandidates[cnd]] = -1;
5723 m_bndryCandidateIds.resize(a_noCells());
5724 m_bndryCandidates.clear();
5725 m_noBndryCandidates = 0;
5727 const MFloat limitDistance = F2 * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
5729 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
5730 const MInt cellId = m_bndryLayerCells[c];
5731 if(a_bndryId(cellId) < -1)
continue;
5732 if(cellId >= a_noCells())
continue;
5733 if(fabs(a_levelSetValuesMb(cellId, 0)) < limitDistance
5734 && a_level(cellId) >= m_lsCutCellMinLevel && c_noChildren(cellId) == 0 && !a_isHalo(cellId)) {
5735 m_bndryCandidates.push_back(cellId);
5736 m_bndryCandidateIds[cellId] = m_noBndryCandidates;
5737 m_noBndryCandidates++;
5739 m_bndryCandidateIds[cellId] = -1;
5745 ASSERT(m_bndryCandidates.size() <= m_bndryLayerCells.size(),
"");
5746 ASSERT(m_noBndryCandidates == (
signed)m_bndryCandidates.size(),
"");
5748 for(
MInt cnd = 0; cnd < m_noBndryCandidates; cnd++) {
5749 ASSERT(cnd == m_bndryCandidateIds[m_bndryCandidates[cnd]],
5750 to_string(cnd) +
" " + to_string(m_bndryCandidates[cnd]) +
" "
5751 + to_string(m_bndryCandidateIds[m_bndryCandidates[cnd]]) +
" "
5752 + to_string(a_isHalo(m_bndryCandidates[cnd])));
5761template <MInt nDim,
class SysEqn>
5765 MBool gapClosure =
false;
5766 if(m_levelSet && m_closeGaps && (m_gapInitMethod > 0 || nDim == 3)) {
5771 m_cutCandidates.clear();
5773 for(
MInt cnd = 0; cnd < m_noBndryCandidates; cnd++) {
5774 const MInt cellId = m_bndryCandidates[cnd];
5775 ASSERT(!a_isHalo(cellId),
"");
5776 m_cutCandidates.emplace_back();
5777 m_cutCandidates[cnd].cellId = cellId;
5782 isGapCell.
fill(
false);
5783 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
5784 if(a_isGapCell(cellId)) isGapCell[cellId] =
true;
5787 m_geometryIntersection->computeNodalValues(m_cutCandidates, &m_bndryCandidateIds[0], &a_levelSetValuesMb(0, 0),
5788 &a_associatedBodyIds(0, 0), &isGapCell(0), gapClosure);
5790 ASSERT((
signed)m_cutCandidates.size() == m_noBndryCandidates,
"");
5795 for(
MInt d = 0; d < noNeighborDomains(); d++) {
5796 p_maxLevelWindowCells[d] = m_maxLevelWindowCells[d];
5797 p_maxLevelHaloCells[d] = m_maxLevelHaloCells[d];
5800 m_geometryIntersection->exchangeNodalValues(p_maxLevelWindowCells.
data(), &m_noMaxLevelWindowCells[0],
5801 p_maxLevelHaloCells.
data(), m_cutCandidates, &m_bndryCandidateIds[0]);
5804 if(grid().azimuthalPeriodicity()) {
5805 computeAzimuthalHaloNodalValues();
5808 ASSERT((
signed)m_cutCandidates.size() >= m_noBndryCandidates,
"");
5811 m_noBndryCandidates = (signed)m_cutCandidates.size();
5812 m_bndryCandidates.clear();
5814 m_candidateNodeSet.resize(m_noBndryCandidates * m_noCellNodes);
5815 m_candidateNodeValues.resize(m_noLevelSetsUsedForMb * m_noBndryCandidates * m_noCellNodes);
5817 for(
MInt cnd = 0; cnd < m_noBndryCandidates; cnd++) {
5818 const MInt cellId = m_cutCandidates[cnd].cellId;
5819 ASSERT(!m_cutCandidates[cnd].isbndryLvlJumpParent,
"");
5821 m_bndryCandidates.push_back(cellId);
5823 for(
MInt node = 0; node < m_noCellNodes; node++) {
5824 m_candidateNodeSet[cnd * m_noCellNodes + node] = m_cutCandidates[cnd].nodeValueSet[node];
5825 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5826 m_candidateNodeValues[IDX_LSSETNODES(cnd, node, set)] = m_cutCandidates[cnd].nodalValues[set][node];
5829 m_bndryCandidateIds[cellId] = cnd;
5837template <MInt nDim,
class SysEqn>
5841 MBool gapClosure =
false;
5842 if(m_levelSet && m_closeGaps && (m_gapInitMethod > 0 || nDim == 3)) {
5845 if(gapClosure) ASSERT(
false,
"Are you sure? AzimuthalPer with gapClosing is untested!");
5847 const MFloat limitDistance = F2 * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
5849 std::vector<MInt> azimuthalCandidateIds;
5850 std::vector<CutCandidate<nDim>> azimuthalCandidates;
5851 MInt noAzimuthalCandidates = 0;
5853 azimuthalCandidateIds.assign(a_noCells(), -1);
5854 azimuthalCandidates.clear();
5856 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5857 for(
MUint j = 0; j < m_azimuthalMaxLevelHaloCells[i].size(); j++) {
5858 const MInt cellId = m_azimuthalMaxLevelHaloCells[i][j];
5859 if(a_bndryId(cellId) < -1)
continue;
5860 if(cellId >= a_noCells())
continue;
5861 if(fabs(a_levelSetValuesMb(cellId, 0)) < limitDistance && a_level(cellId) >= m_lsCutCellMinLevel) {
5862 azimuthalCandidates.emplace_back();
5863 azimuthalCandidates[noAzimuthalCandidates].cellId = cellId;
5864 azimuthalCandidateIds[cellId] = noAzimuthalCandidates;
5865 noAzimuthalCandidates++;
5867 azimuthalCandidateIds[cellId] = -1;
5873 isGapCell.
fill(
false);
5874 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
5875 if(a_isGapCell(cellId)) isGapCell[cellId] =
true;
5878 m_geometryIntersection->computeNodalValues(azimuthalCandidates, &azimuthalCandidateIds[0], &a_levelSetValuesMb(0, 0),
5879 &a_associatedBodyIds(0, 0), &isGapCell(0), gapClosure);
5881 exchangeAzimuthalOuterNodalValues(azimuthalCandidates, azimuthalCandidateIds);
5883 for(
MUint i = 0; i < azimuthalCandidates.size(); i++) {
5885 MInt cellId = azimuthalCandidates[i].cellId;
5886 const MInt candId = m_cutCandidates.size();
5887 m_cutCandidates.emplace_back();
5888 m_cutCandidates[candId].cellId = cellId;
5891 for(
MInt node = 0; node < m_noCorners; node++) {
5892 m_cutCandidates[candId].nodeValueSet[node] =
true;
5893 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5894 m_cutCandidates[candId].nodalValues[set][node] = azimuthalCandidates[i].nodalValues[set][node];
5897 m_cutCandidates[candId].isGapCell = azimuthalCandidates[i].isGapCell;
5899 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
5900 m_cutCandidates[candId].associatedBodyIds[set] = azimuthalCandidates[i].associatedBodyIds[set];
5903 m_bndryCandidateIds[cellId] = candId;
5911template <MInt nDim,
class SysEqn>
5913 std::vector<MInt>& candidateIds) {
5916 const MFloat signStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
5917 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
5918 const MInt nodeStencil[3][8] = {{0, 1, 0, 1, 0, 1, 0, 1}, {2, 2, 3, 3, 2, 2, 3, 3}, {4, 4, 4, 4, 5, 5, 5, 5}};
5919 const MInt reverseNode[3][8] = {{1, 0, 3, 2, 5, 4, 7, 6}, {2, 3, 0, 1, 6, 7, 4, 5}, {4, 5, 6, 7, 0, 1, 2, 3}};
5923 notGradientIds.
fill(-1);
5925 MIntScratchSpace notGradientCells(noAzimuthalHalos, AT_,
"notGradientCells");
5926 MIntScratchSpace notGradientDomain(noAzimuthalHalos, AT_,
"notGradientDomain");
5927 MIntScratchSpace notGradientOffset(noAzimuthalHalos, AT_,
"notGradientOffset");
5928 MInt notGradientCntr = 0;
5929 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5930 for(
MUint j = 0; j < m_azimuthalMaxLevelHaloCells[i].size(); j++) {
5931 MInt cellId = m_azimuthalMaxLevelHaloCells[i][j];
5932 if(candidateIds[cellId] < 0)
continue;
5933 notGradientCells[notGradientCntr] = cellId;
5934 notGradientDomain[notGradientCntr] = i;
5935 notGradientOffset[notGradientCntr] = j;
5936 notGradientIds[cellId] = notGradientCntr;
5941 MIntScratchSpace notGradientCorners(notGradientCntr * m_noCorners, AT_,
"notGradientCorners");
5942 notGradientCorners.
fill(-2);
5944 MInt outerCnt = notGradientCntr * m_noCorners * (nDim + 1);
5946 outerNodes.fill(F0);
5949 MIntScratchSpace sndSize(grid().noAzimuthalNeighborDomains(), AT_,
"sndSize");
5952 MFloat angle = grid().azimuthalAngle();
5954 const MInt maxNoNghbrs = 56;
5959 nghbrNodes.
fill(-1);
5962 for(
MInt i = 0; i < notGradientCntr; i++) {
5963 MInt cellId = notGradientCells[i];
5965 MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(cellId);
5967 for(
MInt node = 0; node < m_noCorners; node++) {
5969 if(notGradientCorners[i * m_noCorners + node] > -2)
continue;
5970 MBool isOuter =
true;
5971 nghbrList[counter] = cellId;
5972 nghbrNodes[counter] = node;
5975 for(
MInt d0 = 0; d0 < nDim; d0++) {
5976 MInt dir0 = nodeStencil[d0][node];
5977 MInt nghbrId0 = c_neighborId(cellId, dir0);
5979 MInt parentId = c_parentId(cellId);
5980 if(parentId > -1) nghbrId0 = c_neighborId(parentId, dir0);
5982 if(nghbrId0 < 0)
continue;
5983 nghbrList[counter] = nghbrId0;
5984 nghbrNodes[counter] = reverseNode[d0][node];
5986 for(
MInt d1 = 0; d1 < nDim; d1++) {
5987 if(d1 == d0)
continue;
5988 MInt dir1 = nodeStencil[d1][node];
5989 MInt nghbrId1 = c_neighborId(nghbrId0, dir1);
5991 MInt parentId = c_parentId(nghbrId0);
5992 if(parentId > -1) nghbrId1 = c_neighborId(parentId, dir1);
5994 if(nghbrId1 < 0)
continue;
5995 nghbrList[counter] = nghbrId1;
5996 nghbrNodes[counter] = reverseNode[d1][reverseNode[d0][node]];
5998 for(
MInt d2 = 0; d2 < nDim; d2++) {
5999 if((d2 == d0) || (d2 == d1))
continue;
6000 MInt dir2 = nodeStencil[d2][node];
6001 MInt nghbrId2 = c_neighborId(nghbrId1, dir2);
6003 MInt parentId = c_parentId(nghbrId1);
6004 if(parentId > -1) nghbrId2 = c_neighborId(parentId, dir2);
6006 if(nghbrId2 < 0)
continue;
6007 nghbrList[counter] = nghbrId2;
6008 nghbrNodes[counter] = reverseNode[d2][reverseNode[d1][reverseNode[d0][node]]];
6014 for(
MInt n = 0; n < counter; n++) {
6015 MInt nghbrId = nghbrList[n];
6016 if(!a_isPeriodic(nghbrId) && m_bndryCandidateIds[nghbrId] > 1) {
6018 MInt nghbrNode = nghbrNodes[n];
6019 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
6020 nodalValue[set] = m_cutCandidates[m_bndryCandidateIds[nghbrId]].nodalValues[set][nghbrNode];
6027 outerNodes[outerCnt * (nDim + 1)] = (
MFloat)notGradientOffset[i];
6028 for(
MInt d = 0; d < nDim; d++) {
6029 corner[d] = c_coordinate(cellId, d) + signStencil[node][d] * cellHalfLength;
6031 MInt side = grid().determineAzimuthalBoundarySide(corner);
6032 grid().rotateCartesianCoordinates(corner, (side * angle));
6033 std::copy_n(&corner[0], nDim, &outerNodes[outerCnt * (nDim + 1) + 1]);
6034 sndSize[notGradientDomain[i]]++;
6036 for(
MInt n = 0; n < counter; n++) {
6037 MInt nghbrId = nghbrList[n];
6038 MInt nId = notGradientIds[nghbrId];
6040 MInt nghbrNode = nghbrNodes[n];
6041 notGradientCorners[nId * m_noCorners + nghbrNode] = outerCnt;
6046 for(
MInt n = 0; n < counter; n++) {
6047 MInt nghbrId = nghbrList[n];
6048 MInt cndId = candidateIds[nghbrId];
6049 MInt nghbrNode = nghbrNodes[n];
6050 MInt nId = notGradientIds[nghbrId];
6052 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
6053 candidates[cndId].nodalValues[set][nghbrNode] = nodalValue[set];
6057 notGradientCorners[nId * m_noCorners + nghbrNode] = -1;
6066 MIntScratchSpace rcvSize(grid().noAzimuthalNeighborDomains(), AT_,
"rcvBuffSize");
6068 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6069 MPI_Irecv(&rcvSize[i], 1, MPI_INT, grid().azimuthalNeighborDomain(i), 2, grid().mpiComm(), &mpi_recv_req[i], AT_,
6072 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6073 MPI_Isend(&sndSize[i], 1, MPI_INT, grid().azimuthalNeighborDomain(i), 2, grid().mpiComm(), &mpi_send_req[i], AT_,
6076 MPI_Waitall(grid().noAzimuthalNeighborDomains(), &mpi_recv_req[0], MPI_STATUSES_IGNORE, AT_);
6077 MPI_Waitall(grid().noAzimuthalNeighborDomains(), &mpi_send_req[0], MPI_STATUSES_IGNORE, AT_);
6079 MInt sndNodeCnt = 0;
6080 MInt rcvNodeCnt = 0;
6081 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6082 sndNodeCnt += sndSize[i];
6083 rcvNodeCnt += rcvSize[i];
6086 MInt fac =
mMax((nDim + 1), m_noLevelSetsUsedForMb);
6088 MFloatScratchSpace sndBuffers(rcvNodeCnt * m_noLevelSetsUsedForMb, AT_,
"sndBuffers");
6090 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6091 mpi_send_req[i] = MPI_REQUEST_NULL;
6092 mpi_recv_req[i] = MPI_REQUEST_NULL;
6096 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6097 if(rcvSize[i] > 0) {
6098 MInt bufSize = (nDim + 1) * rcvSize[i];
6099 MPI_Irecv(&rcvBuffers[offset], bufSize, MPI_DOUBLE, grid().azimuthalNeighborDomain(i), 2, grid().mpiComm(),
6100 &mpi_recv_req[i], AT_,
"rcvBuffers[offset]");
6106 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6107 if(sndSize[i] > 0) {
6108 MInt bufSize = (nDim + 1) * sndSize[i];
6109 MPI_Isend(&outerNodes[offset], bufSize, MPI_DOUBLE, grid().azimuthalNeighborDomain(i), 2, grid().mpiComm(),
6110 &mpi_send_req[i], AT_,
"outerNodes[offset]");
6115 MPI_Waitall(grid().noAzimuthalNeighborDomains(), &mpi_recv_req[0], MPI_STATUSES_IGNORE, AT_);
6116 MPI_Waitall(grid().noAzimuthalNeighborDomains(), &mpi_send_req[0], MPI_STATUSES_IGNORE, AT_);
6119 return static_cast<MBool>(grid().tree().hasNeighbor(cellId,
id));
6122 return static_cast<MFloat>(c_coordinate(cellId,
id));
6126 MFloat eps = F1 + pow(10, -12);
6127 MInt interpolationCells[8] = {0, 0, 0, 0, 0, 0, 0, 0};
6128 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6129 for(
MInt j = 0; j < rcvSize[i]; j++) {
6130 MInt cellId = m_azimuthalMaxLevelWindowCells[i][(
MInt)rcvBuffers[(offset + j) * (nDim + 1)]];
6131 for(
MInt d = 0; d < nDim; d++) {
6132 corner[d] = rcvBuffers[(offset + j) * (nDim + 1) + 1 + d];
6134 if(!this->inCell(cellId, corner, eps)) {
6135 MInt counter = grid().getAdjacentGridCells(cellId, 1, nghbrList, a_level(cellId), 2);
6136 for(
MInt n = 0; n < counter; n++) {
6137 MInt nghbrId = nghbrList[n];
6138 if(this->inCell(nghbrId, corner, eps)) {
6144 ASSERT(this->inCell(cellId, corner, eps),
"Coordindate not in cell!");
6146 position = this->setUpInterpolationStencil(cellId, interpolationCells, corner, neighborCheck,
false);
6147 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
6149 MFloat phi = interpolateLevelSet(interpolationCells, corner, set);
6150 sndBuffers[(offset + j) * m_noLevelSetsUsedForMb + set] = phi;
6152 sndBuffers[(offset + j) * m_noLevelSetsUsedForMb + set] = a_levelSetValuesMb(cellId, set);
6156 offset += rcvSize[i];
6159 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6160 mpi_send_req[i] = MPI_REQUEST_NULL;
6161 mpi_recv_req[i] = MPI_REQUEST_NULL;
6166 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6167 if(sndSize[i] > 0) {
6168 MInt bufSize = m_noLevelSetsUsedForMb * sndSize[i];
6169 MPI_Irecv(&rcvBuffers[offset], bufSize, MPI_DOUBLE, grid().azimuthalNeighborDomain(i), 2, grid().mpiComm(),
6170 &mpi_recv_req[i], AT_,
"rcvBuffers[offset]");
6176 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
6177 if(rcvSize[i] > 0) {
6178 MInt bufSize = m_noLevelSetsUsedForMb * rcvSize[i];
6179 MPI_Isend(&sndBuffers[offset], bufSize, MPI_DOUBLE, grid().azimuthalNeighborDomain(i), 2, grid().mpiComm(),
6180 &mpi_send_req[i], AT_,
"sndBuffers[offset]");
6185 MPI_Waitall(grid().noAzimuthalNeighborDomains(), &mpi_recv_req[0], MPI_STATUSES_IGNORE, AT_);
6186 MPI_Waitall(grid().noAzimuthalNeighborDomains(), &mpi_send_req[0], MPI_STATUSES_IGNORE, AT_);
6188 for(
MInt i = 0; i < notGradientCntr; i++) {
6189 MInt cellId = notGradientCells[i];
6190 MInt cndId = candidateIds[cellId];
6191 for(
MInt node = 0; node < m_noCorners; node++) {
6192 if(notGradientCorners[i * m_noCorners + node] < 0)
continue;
6193 offset = notGradientCorners[i * m_noCorners + node];
6194 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
6195 candidates[cndId].nodalValues[set][node] = rcvBuffers[offset * m_noLevelSetsUsedForMb + set];
6202template <MInt nDim,
class SysEqn>
6204 cerr0 <<
"initialize " << m_noPointParticles <<
" point particles." << endl;
6220 diameter = Context::getSolverProperty<MFloat>(
"pointParticleDiameter", m_solverId, AT_);
6221 if(m_pointParticleType == 3) {
6233 beta = Context::getSolverProperty<MFloat>(
"pointParticleAspectRatio", m_solverId, AT_);
6244 ? Context::getSolverProperty<MFloat>(
"randomDeviceSeed", m_solverId, AT_)
6246 const MUlong seed = (
MUlong)((seed0 > -1) ? seed0 : std::random_device()());
6248 MPI_Bcast(&seed1, 1, MPI_UNSIGNED_LONG, 0, mpiComm(), AT_,
"seed1");
6249 std::mt19937_64 gen(seed1);
6250 std::mt19937_64 gen2(seed1);
6252 std::uniform_real_distribution<> distr(-F1B2, F1B2);
6253 std::uniform_real_distribution<> distr2(F0, F1);
6254 m_noPointParticlesLocal = 0;
6255 particleCheck.fill(0);
6256 unordered_map<MLong, MInt> hilbertToLocal;
6257 hilbertToLocal.reserve(noMinCells());
6261 MFloat coords[3] = {F0, F0, F0};
6262 for(
MInt c = 0; c < noMinCells(); c++) {
6264 if(a_isHalo(cellId))
continue;
6265 MLong hilbertId = grid().raw().generateHilbertIndex(cellId);
6266 hilbertToLocal[hilbertId] =
cellId;
6268 for(
MInt p = 0;
p < m_noPointParticles;
p++) {
6269 MBool outside =
false;
6271 tt1 = F2 * PI * distr2(gen2);
6272 tt2 = F2 * PI * distr2(gen2);
6273 for(
MInt i = 0; i < nDim; i++) {
6274 coords[i] = distr(gen) * (m_bbox[nDim + i] - m_bbox[i]);
6275 if(coords[i] < m_bboxLocal[i] || coords[i] > m_bboxLocal[nDim + i]) outside =
true;
6277 if(outside)
continue;
6278 const MFloat delta = c_cellLengthAtLevel(minLevel());
6279 MFloat projCords[3] = {F0, F0, F0};
6280 for(
MInt i = 0; i < nDim; i++) {
6281 MInt div = (
MInt)(coords[i] / delta);
6282 projCords[i] = (div > 0) ? (F1B2 + ((
MFloat)div)) * delta : (-F1B2 + ((
MFloat)div)) * delta;
6284 MLong hilbertId = grid().raw().hilbertIndexGeneric(&projCords[0]);
6285 MInt linkedCell = -1;
6286 if(hilbertToLocal.count(hilbertId) > 0) {
6288 const MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(cellId);
6290 for(
MInt i = 0; i < nDim; i++) {
6291 if((coords[i] < a_coordinate(cellId, i) - cellHalfLength)
6292 || (coords[i] > a_coordinate(cellId, i) + cellHalfLength)) {
6300 if(linkedCell < 0) {
6301 for(
MInt c = 0; c < noMinCells(); c++) {
6303 if(a_isHalo(cellId))
continue;
6304 const MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(cellId);
6306 for(
MInt i = 0; i < nDim; i++) {
6307 if((coords[i] < a_coordinate(cellId, i) - cellHalfLength)
6308 || (coords[i] > a_coordinate(cellId, i) + cellHalfLength)) {
6318 if(linkedCell > -1) {
6319 for(
MInt i = 0; i < 3; i++)
6320 m_particleCoords.push_back(coords[i]);
6321 for(
MInt i = 0; i < 3; i++)
6322 m_particleVelocity.push_back(F0);
6323 for(
MInt i = 0; i < 3; i++)
6324 m_particleVelocityFluid.push_back(F0);
6325 m_particleTemperature.push_back(F0);
6326 m_particleFluidTemperature.push_back(F0);
6327 m_particleHeatFlux.push_back(F0);
6328 for(
MInt i = 0; i < 3; i++)
6329 m_particleAcceleration.push_back(F0);
6330 for(
MInt i = 0; i < 3; i++)
6331 m_particleAngularVelocity.push_back(F0);
6332 for(
MInt i = 0; i < 3; i++)
6333 m_particleAngularAcceleration.push_back(F0);
6334 for(
MInt i = 0; i < 9; i++)
6335 m_particleVelocityGradientFluid.push_back(F0);
6339 MFloat ex = sin(tt1) * sqrt(F1 - sr);
6341 MFloat ez = sin(tt2) * sqrt(sr);
6343 m_particleQuaternions.push_back(ew / sqrt(ew * ew + ex * ex + ey * ey + ez * ez));
6344 m_particleQuaternions.push_back(ex / sqrt(ew * ew + ex * ex + ey * ey + ez * ez));
6345 m_particleQuaternions.push_back(ey / sqrt(ew * ew + ex * ex + ey * ey + ez * ez));
6346 m_particleQuaternions.push_back(ez / sqrt(ew * ew + ex * ex + ey * ey + ez * ez));
6348 if(m_pointParticleType == 1) {
6349 for(
MInt i = 0; i < 3; i++)
6350 m_particleRadii.push_back(F1B2 * diameter);
6351 for(
MInt i = 0; i < 4; i++)
6352 m_particleShapeParams.push_back(F0);
6353 }
else if(m_pointParticleType == 3) {
6354 MFloat a = F1B2 * diameter * pow(beta, -F1B3);
6356 m_particleRadii.push_back(
a);
6357 m_particleRadii.push_back(
a);
6358 m_particleRadii.push_back(beta *
a);
6359 if(fabs(beta - F1) < 1e-14) {
6360 m_particleShapeParams.push_back(F2 *
POW2(
a));
6361 m_particleShapeParams.push_back(F2B3);
6362 m_particleShapeParams.push_back(F2B3);
6363 m_particleShapeParams.push_back(F2B3);
6364 }
else if(beta < F0) {
6366 }
else if(beta > F1) {
6367 MFloat kappa = log((beta - sqrt(beta2 - F1)) / (beta + sqrt(beta2 - F1)));
6368 m_particleShapeParams.push_back(-beta *
POW2(
a) * kappa / sqrt(beta2 - F1));
6369 m_particleShapeParams.push_back(beta2 / (beta2 - F1) + beta * kappa / (F2 * pow(beta2 - F1, F3B2)));
6370 m_particleShapeParams.push_back(beta2 / (beta2 - F1) + beta * kappa / (F2 * pow(beta2 - F1, F3B2)));
6371 m_particleShapeParams.push_back(-F2 / (beta2 - F1) - beta * kappa / (pow(beta2 - F1, F3B2)));
6372 }
else if(beta < F1) {
6374 MFloat kappa = F2 * atan2(beta, sqrt(F1 - beta2));
6375 m_particleShapeParams.push_back(beta *
POW2(
a) * (PI - kappa) / sqrt(F1 - beta2));
6376 m_particleShapeParams.push_back(-beta * (kappa - PI + F2 * beta * sqrt(F1 - beta2))
6377 / (F2 * pow(F1 - beta2, F3B2)));
6378 m_particleShapeParams.push_back(-beta * (kappa - PI + F2 * beta * sqrt(F1 - beta2))
6379 / (F2 * pow(F1 - beta2, F3B2)));
6380 m_particleShapeParams.push_back((beta * kappa - beta * PI + F2 * sqrt(F1 - beta2)) / (pow(F1 - beta2, F3B2)));
6382 if(domainId() == 0 && m_noPointParticlesLocal == 0) {
6383 cerr <<
"ellipsoid: " << diameter <<
" " << beta <<
" / " <<
a <<
" " <<
a <<
" " << beta *
a <<
" ("
6384 << pow(
a *
a *
a * beta, F1B3) <<
")" << endl;
6394 while(fabs(dlt) > 1e-8) {
6395 dlt =
a *
b * c / sqrt((
a *
a + x) * (
b *
b + x) * (c * c + x));
6397 tst1 += dx * dlt / (
a *
a + x);
6398 tst2 += dx * dlt / (
b *
b + x);
6399 tst3 += dx * dlt / (c * c + x);
6402 cerr <<
"value 0: " << tst0 <<
" " << m_particleShapeParams[0] << endl;
6403 cerr <<
"value 1: " << tst1 <<
" " << m_particleShapeParams[1] << endl;
6404 cerr <<
"value 2: " << tst2 <<
" " << m_particleShapeParams[2] << endl;
6405 cerr <<
"value 3: " << tst3 <<
" " << m_particleShapeParams[3] << endl;
6408 mTerm(1, AT_,
"point particle type");
6410 m_particleCellLink.push_back(linkedCell);
6412 m_noPointParticlesLocal++;
6413 m_particleGlobalId.push_back(p);
6416 MPI_Allreduce(MPI_IN_PLACE, &(particleCheck[0]), m_noPointParticles, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
6417 "(particleCheck[0])");
6418 if(domainId() == 0) {
6419 for(
MInt p = 0;
p < m_noPointParticles;
p++) {
6420 if(particleCheck[p] != 1)
6421 mTerm(1, AT_,
"Point particle init failed " + to_string(p) +
" " + to_string(particleCheck[p]));
6424 m_particleCoordsDt1 = m_particleCoords;
6425 m_particleVelocityDt1 = m_particleVelocity;
6426 m_particleTemperatureDt1 = m_particleTemperature;
6427 m_particleAccelerationDt1 = m_particleAcceleration;
6428 m_particleQuaternionsDt1 = m_particleQuaternions;
6429 m_particleAngularVelocityDt1 = m_particleAngularVelocity;
6430 m_particleAngularAccelerationDt1 = m_particleAngularAcceleration;
6431 for(
MUint p = 0;
p < m_particleCellLink.size();
p++) {
6433 while(c_noChildren(cellId) > 0) {
6435 for(
MUint i = 0; i < nDim; i++) {
6436 if(m_particleCoords[nDim * p + i] > a_coordinate(cellId, i)) child +=
IPOW2(i);
6438 cellId = c_childId(cellId, child);
6439 if(cellId < 0 || cellId >= a_noCells())
mTerm(1, AT_,
"Point particle linking failed.");
6441 m_particleCellLink[
p] =
cellId;
6452template <MInt nDim,
class SysEqn>
6456 cerr0 <<
"Init body properties...";
6458 if(m_noEmbeddedBodies == 0) {
6459 cerr0 <<
" m_noEmbeddedBodies = 0. Body properties will not be initialized." << endl;
6460 if(m_noPointParticles > 0 && noMinCells() > 0) {
6461 initPointParticleProperties();
6466 if(m_constructGField) updateInfinityVariables();
6479 MFloat bodyTemperatureRatio = 1;
6480 bodyTemperatureRatio =
6481 Context::getSolverProperty<MFloat>(
"bodyTemperatureRatio", m_solverId, AT_, &bodyTemperatureRatio);
6483 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6484 for(
MInt i = 0; i < nDim; i++) {
6485 m_bodyCenter[k * nDim + i] = F0;
6486 m_bodyVelocity[k * nDim + i] = F0;
6487 m_bodyForce[k * nDim + i] = F0;
6488 m_bodyAcceleration[k * nDim + i] = F0;
6489 if(m_motionEquation > 1) {
6490 m_bodyNeutralCenter[k * nDim + i] = F0;
6493 for(
MInt i = 0; i < 3; i++) {
6494 m_bodyAngularVelocity[k * 3 + i] = F0;
6495 m_bodyAngularAcceleration[k * 3 + i] = F0;
6496 m_bodyTorque[k * 3 + i] = F0;
6498 for(
MInt i = 0; i < 4; i++) {
6499 m_bodyQuaternion[k * 4 + i] = F0;
6501 m_bodyTemperature[k] = bodyTemperatureRatio * m_TInfinity;
6502 m_bodyTemperatureDt1[k] = bodyTemperatureRatio * m_TInfinity;
6503 if(m_motionEquation > 1) {
6504 m_bodyReducedVelocity[k] = 9.0;
6505 m_bodyReducedFrequency[k] = m_Ma / m_bodyReducedVelocity[k];
6506 m_bodyReducedMass[k] = F2;
6507 m_bodyDampingCoefficient[k] = F0;
6509 m_bodyInCollision[k] = 0;
6512 m_log <<
"Inititial body temperature of body 0 " << m_bodyTemperature[0] << endl;
6514 cerr <<
"Warning: Body temperature will not be updated" << endl;
6518 if(m_motionEquation == 0 && !m_constructGField && m_LsMovement) {
6519 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6520 m_bodyEquation[k] = 4520;
6522 }
else if(m_motionEquation == 0) {
6523 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6524 m_bodyEquation[k] = m_initialCondition;
6529 for(
MInt i = 0; i < nDim; i++) {
6530 m_U2 +=
POW2(m_VVInfinity[i]);
6532 m_rhoU2 = m_U2 * m_rhoInfinity;
6545 for(
MInt i = 0; i < nDim; i++) {
6546 m_fixedBodyComponents[i] = 0;
6548 for(
MInt i = 0; i < nDim; i++) {
6549 m_fixedBodyComponents[i] =
6550 Context::getSolverProperty<MInt>(
"fixedBodyComponents", m_solverId, AT_, &m_fixedBodyComponents[i], i);
6563 for(
MInt i = 0; i < 3; i++) {
6564 m_fixedBodyComponentsRotation[i] = Context::getSolverProperty<MInt>(
"fixedBodyComponentsRotation", m_solverId, AT_,
6565 &m_fixedBodyComponentsRotation[i], i);
6568 if(m_motionEquation > 1 && m_noEmbeddedBodies > 0) {
6579 MFloat reducedMass = Context::getSolverProperty<MFloat>(
"reducedMass", m_solverId, AT_, &m_bodyReducedMass[0]);
6581 Context::getSolverProperty<MFloat>(
"dampingCoefficient", m_solverId, AT_, &m_bodyDampingCoefficient[0]);
6582 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6583 m_bodyReducedMass[k] = reducedMass;
6584 m_bodyDampingCoefficient[k] = dampCoeff;
6586 m_bodyReducedVelocity[k] =
6587 Context::getSolverProperty<MFloat>(
"reducedVelocity", m_solverId, AT_, &m_bodyReducedVelocity[0]);
6588 m_bodyReducedFrequency[k] = m_Ma / m_bodyReducedVelocity[k];
6590 if(fabs(m_bodyReducedVelocity[k]) < m_eps) {
6591 mTerm(1, AT_,
"Division by zero in FvMbCartesianSolverXD::initBodyProperties(). Quit.");
6607 MFloat bodyRadius = F1B2;
6608 bodyRadius = Context::getSolverProperty<MFloat>(
"bodyRadius", m_solverId, AT_, &bodyRadius);
6609 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6610 m_bodyRadius[k] = bodyRadius;
6611 m_bodyDiameter[k] = F2 * bodyRadius;
6627 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6628 m_bodyDiameter[k] = Context::getSolverProperty<MFloat>(
"bodyDiameters", m_solverId, AT_, k);
6629 m_bodyRadius[k] = F1B2 * m_bodyDiameter[k];
6632 mTerm(1, AT_,
"bodyDiameters wrong dimension " + to_string(m_noEmbeddedBodies));
6647 if(m_noEmbeddedBodies > 0) {
6648 if(m_bodyTypeMb == 3) {
6650 for(
MInt i = 0; i < 3; i++) {
6651 m_bodyRadii[i] = Context::getSolverProperty<MFloat>(
"bodyRadii", m_solverId, AT_, i);
6653 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6654 for(
MInt i = 0; i < 3; i++) {
6655 m_bodyRadii[k * 3 + i] = m_bodyRadii[i];
6659 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6660 for(
MInt i = 0; i < 3; i++) {
6661 m_bodyRadii[k * 3 + i] = Context::getSolverProperty<MFloat>(
"bodyRadii", m_solverId, AT_, k * 3 + i);
6665 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6666 m_bodyRadius[k] = F0;
6667 for(
MInt i = 0; i < 3; i++) {
6670 m_bodyRadius[k] = pow(m_bodyRadii[k * 3 + 0] * m_bodyRadii[k * 3 + 1] * m_bodyRadii[k * 3 + 2], F1B3);
6671 m_bodyDiameter[k] = F2 * m_bodyRadius[k];
6674 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6675 for(
MInt i = 0; i < 3; i++) {
6676 m_bodyRadii[k * 3 + i] = m_bodyRadius[k];
6683 if(m_motionEquation > 1) {
6684 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6685 m_bodyReducedVelocity[k] *= m_bodyDiameter[k];
6686 m_bodyReducedFrequency[k] /= m_bodyDiameter[k];
6687 for(
MInt i = 0; i < nDim; i++) {
6688 m_bodyReducedMass[k] *= m_bodyDiameter[k];
6704 m_densityRatio = F1;
6705 m_densityRatio = Context::getSolverProperty<MFloat>(
"densityRatio", m_solverId, AT_, &m_densityRatio);
6706 m_log <<
"density ratio: " << m_densityRatio << endl;
6716 m_capacityConstantVolumeRatio =
6718 ? Context::getSolverProperty<MFloat>(
"capacityConstantVolumeRatio", m_solverId, AT_)
6721 if(domainId() == 0) {
6722 m_log <<
"Heat capacity at constant volume Cv_particle/Cv_fluid: " << m_capacityConstantVolumeRatio << endl;
6725 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6726 m_bodyDensity[k] = m_densityRatio * m_rhoInfinity;
6727 m_bodyVolume[k] = F4B3 * PI;
6728 m_projectedArea[k] = PI;
6730 for(
MInt i = 0; i < nDim; i++) {
6731 m_bodyVolume[k] *= m_bodyRadii[k * nDim + i];
6732 m_projectedArea[k] *= m_bodyRadii[k * nDim + i];
6733 tmp += m_bodyRadii[k * nDim + i] * fabs(m_VVInfinity[i]) / sqrt(m_U2);
6735 m_projectedArea[k] /= tmp;
6736 m_bodyMass[k] = m_bodyDensity[k] * m_bodyVolume[k];
6740 IF_CONSTEXPR(nDim == 2) {
6741 m_addedMassCoefficient = F1;
6742 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6743 m_projectedArea[k] = F2 * m_bodyRadius[k];
6746 IF_CONSTEXPR(nDim == 3) {
6748 if(m_bodyTypeMb == 1) {
6749 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6750 for(
MInt i = 0; i < 3; i++) {
6751 m_bodyMomentOfInertia[3 * k + i] = F2B5 * m_bodyMass[k] *
POW2(m_bodyRadius[k]);
6754 }
else if(m_bodyTypeMb == 3) {
6755 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6756 const MFloat a = m_bodyRadii[k * nDim + 0];
6757 const MFloat b = m_bodyRadii[k * nDim + 1];
6758 const MFloat c = m_bodyRadii[k * nDim + 2];
6759 m_bodyMomentOfInertia[3 * k + 0] = (4.0 / 15.0) * (
b *
b + c * c) * PI * m_bodyDensity[k] *
a *
b * c;
6760 m_bodyMomentOfInertia[3 * k + 1] = (4.0 / 15.0) * (
a *
a + c * c) * PI * m_bodyDensity[k] *
a *
b * c;
6761 m_bodyMomentOfInertia[3 * k + 2] = (4.0 / 15.0) * (
a *
a +
b *
b) * PI * m_bodyDensity[k] *
a *
b * c;
6764 m_addedMassCoefficient = F1B2;
6767 if(m_noEmbeddedBodies > 1 || m_initialCondition == 471) {
6769 for(
MInt i = 0; i < nDim; i++) {
6770 VVInf +=
POW2(m_VVInfinity[i]);
6772 VVInf = sqrt(VVInf);
6773 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6774 m_bodyDensity[k] = m_densityRatio * m_rhoInfinity;
6775 m_bodyVolume[k] = F4B3 * PI;
6776 m_projectedArea[k] = PI;
6778 for(
MInt i = 0; i < nDim; i++) {
6779 m_bodyVolume[k] *= m_bodyRadii[k * nDim + i];
6780 m_projectedArea[k] *= m_bodyRadii[k * nDim + i];
6781 tmp += m_bodyRadii[k * nDim + i] * fabs(m_VVInfinity[i]) / VVInf;
6783 m_projectedArea[k] /= tmp;
6784 m_bodyMass[k] = m_bodyDensity[k] * m_bodyVolume[k];
6787 if(m_initialCondition == 471) {
6789 m_g = F3B4 * CdLaw(m_Re) *
POW2(m_Ma) / (m_referenceLength * m_densityRatio);
6790 m_log <<
"g=" << m_g <<
", Fr=" << m_Ma / sqrt(m_g) << endl;
6794 m_minBodyRadius = numeric_limits<MFloat>::max();
6795 m_maxBodyRadius = F0;
6796 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6797 m_maxBodyRadius =
mMax(m_maxBodyRadius, m_bodyRadius[k]);
6798 m_minBodyRadius =
mMin(m_minBodyRadius, m_bodyRadius[k]);
6799 for(
MInt i = 0; i < 3; i++) {
6800 m_maxBodyRadius =
mMax(m_maxBodyRadius, m_bodyRadii[k * 3 + i]);
6801 m_minBodyRadius =
mMin(m_minBodyRadius, m_bodyRadii[k * 3 + i]);
6807 for(
MInt i = 0; i < nDim; i++) {
6808 VVInf +=
POW2(m_VVInfinity[i]);
6810 VVInf = sqrt(VVInf);
6812 if(m_initialCondition != 45299 && m_initialCondition != 45300 && m_initialCondition != 45301
6813 && m_initialCondition != 45302 && m_initialCondition != 4520
6814 && (m_noEmbeddedBodies > 1 || m_initialCondition == 471)) {
6815 for(
MInt i = 0; i < nDim; i++) {
6816 m_bodyVelocity[i] = F0;
6830 m_bodyVelocity[i] = Context::getSolverProperty<MFloat>(
"initialBodyVelocity", m_solverId, AT_, i);
6833 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6835 for(
MInt i = 0; i < nDim; i++) {
6836 m_bodyVelocity[k * nDim + i] = m_bodyVelocity[i];
6838 for(
MInt i = 0; i < nDim; i++) {
6839 m_bodyVelocity[k * nDim + i] *= m_UInfinity;
6924 m_bodyCenter[k * nDim] = Context::getSolverProperty<MFloat>(
"xBodyCenter", m_solverId, AT_, k);
6925 m_bodyCenter[k * nDim + 1] = Context::getSolverProperty<MFloat>(
"yBodyCenter", m_solverId, AT_, k);
6927 m_bodyVelocity[k * nDim] = Context::getSolverProperty<MFloat>(
"xBodyVelocity", m_solverId, AT_, k) * VVInf;
6929 m_bodyVelocity[k * nDim + 1] =
6930 Context::getSolverProperty<MFloat>(
"yBodyVelocity", m_solverId, AT_, k) * VVInf;
6931 if(m_initialCondition == 450) {
6932 if(m_motionEquation > 1) {
6933 if(m_restart) cerr <<
"consider" << endl;
6934 m_bodyNeutralCenter[k * nDim] =
6935 Context::getSolverProperty<MFloat>(
"xBodyNeutralCenter", m_solverId, AT_, k);
6936 m_bodyNeutralCenter[k * nDim + 1] =
6937 Context::getSolverProperty<MFloat>(
"yBodyNeutralCenter", m_solverId, AT_, k);
6940 IF_CONSTEXPR(nDim == 3) {
6941 m_bodyCenter[k * nDim + 2] = Context::getSolverProperty<MFloat>(
"zBodyCenter", m_solverId, AT_, k);
6943 m_bodyVelocity[k * nDim + 2] =
6944 Context::getSolverProperty<MFloat>(
"zBodyVelocity", m_solverId, AT_, k) * VVInf;
6945 if(m_initialCondition == 450) {
6946 if(m_motionEquation > 1) {
6947 if(m_restart) cerr <<
"consider" << endl;
6948 m_bodyNeutralCenter[k * nDim + 2] =
6949 Context::getSolverProperty<MFloat>(
"zBodyNeutralCenter", m_solverId, AT_, k);
6953 if(m_initialCondition == 450) {
6954 if(m_motionEquation > 1) {
6956 m_bodyReducedVelocity[k] = Context::getSolverProperty<MFloat>(
"bodyReducedVelocity", m_solverId, AT_, k);
6957 m_bodyReducedFrequency[k] = m_Ma / m_bodyReducedVelocity[k];
6974 if(m_noEmbeddedBodies > 0) {
6976 for(
MInt i = 0; i < nDim; i++) {
6978 Context::getSolverProperty<MFloat>(
"initialBodyCenter", m_solverId, AT_, i) * m_bodyDiameter[0];
6982 for(
MInt i = 0; i < nDim; i++) {
6983 m_bodyVelocity[i] = Context::getSolverProperty<MFloat>(
"initialBodyVelocity", m_solverId, AT_, i);
6985 for(
MInt i = 0; i < nDim; i++) {
6986 m_bodyVelocity[i] *= m_UInfinity;
6993 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
6994 m_bodyQuaternion[k * 4 + 0] = F1;
6995 m_bodyQuaternion[k * 4 + 1] = F0;
6996 m_bodyQuaternion[k * 4 + 2] = F0;
6997 m_bodyQuaternion[k * 4 + 3] = F0;
7000 if((m_initialCondition == 15 || m_initialCondition == 16) && m_noEmbeddedBodies > 0) {
7001 MString fileName =
"out/bodyData_init.Netcdf";
7002 MBool foundFile =
false;
7004 if(!m_restart && ParallelIo::fileExists(fileName, mpiComm())) {
7005 cerr0 <<
"Loading initial body distribution from file " << fileName << endl;
7007 ParallelIo parallelIo(fileName, PIO_READ, mpiComm());
7009 ParallelIo::size_type start = 0;
7010 ParallelIo::size_type count = 0;
7012 const MLong DOF = m_noEmbeddedBodies;
7013 const MLong DOF_TRANS = nDim * m_noEmbeddedBodies;
7014 const MLong DOF_ROT = 3 * m_noEmbeddedBodies;
7015 const MLong DOF_QUAT = 4 * m_noEmbeddedBodies;
7018 parallelIo.getAttribute(&noBodies,
"noBodies");
7019 parallelIo.getAttribute(radii,
"bodyRadii", 3);
7022 if(noBodies < DOF) {
7024 cerr0 <<
"Not enough embedded bodies in file " << fileName << endl;
7026 if(fabs(m_bodyRadii[0] - radii[0]) > 1e-12 || fabs(m_bodyRadii[1] - radii[1]) > 1e-12
7027 || fabs(m_bodyRadii[2] - radii[2]) > 1e-12) {
7029 cerr0 <<
"Body radii mismatch in file " << fileName << endl;
7033 parallelIo.setOffset(count, start);
7034 parallelIo.readArray(m_bodyTemperature,
"bodyTemperature");
7037 parallelIo.setOffset(count, start);
7038 parallelIo.readArray(m_bodyCenter,
"bodyCenter");
7039 if(parallelIo.hasDataset(
"bodyVelocity")) {
7040 parallelIo.readArray(m_bodyVelocity,
"bodyVelocity");
7044 parallelIo.setOffset(count, start);
7045 if(parallelIo.hasDataset(
"bodyAngularVelocity")) {
7046 parallelIo.readArray(m_bodyAngularVelocity,
"bodyAngularVelocity");
7050 parallelIo.setOffset(count, start);
7051 parallelIo.readArray(m_bodyQuaternion,
"bodyQuaternion");
7055 const MFloat dist0 = 3.0 * c_cellLengthAtLevel(maxRefinementLevel());
7056 const MFloat dist1 = F2 * m_maxBodyRadius + dist0;
7057 const MBool storeBodyDistribution =
7059 ? Context::getSolverProperty<MBool>(
"storeBodyDistribution", m_solverId, AT_)
7062 if(domainId() == 0) {
7072 ? Context::getSolverProperty<MFloat>(
"randomDeviceSeed", m_solverId, AT_)
7074 const MUlong seed = (
MUlong)((seed0 > -1) ? seed0 : std::random_device()());
7075 const MUlong seed1 = seed;
7077 std::mt19937_64 gen(seed);
7078 std::mt19937_64 gen2(seed1);
7079 std::mt19937_64 gen3(seed1);
7081 std::uniform_real_distribution<> distr(-F1B2, F1B2);
7082 std::uniform_real_distribution<> distr2(F0, F1);
7083 std::uniform_real_distribution<> distr3(0.25, 1.75);
7085 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7086 for(
MInt i = 0; i < nDim; i++) {
7087 m_bodyCenter[k * nDim + i] = m_bbox[nDim + i] + 1000000.0 * (m_bbox[nDim + i] - m_bbox[i]);
7093 MFloat bboxThreshold[6]{};
7094 MFloat bboxThreshold2[6]{};
7095 for(
MInt i = 0; i < nDim; i++) {
7096 dx[i] = m_bbox[nDim + i] - m_bbox[i];
7097 bboxThreshold[i] = m_bbox[i] + dist1;
7098 bboxThreshold2[i] = m_bbox[i] - dist1;
7099 bboxThreshold[nDim + i] = m_bbox[nDim + i] - dist1;
7100 bboxThreshold2[nDim + i] = m_bbox[nDim + i] + dist1;
7102 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7103 maxRadius[k] =
mMax(m_bodyRadii[k * 3 + 0],
mMax(m_bodyRadii[k * 3 + 1], m_bodyRadii[k * 3 + 2]));
7105 const MInt statFac = (m_noEmbeddedBodies > 100000) ? 100 : ((m_noEmbeddedBodies > 10000) ? 10 : -1);
7106 const MFloat time0 = MPI_Wtime();
7107 cerr <<
"No body distribution file found. Creating new distribution for " << m_noEmbeddedBodies <<
" bodies."
7110 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7112 && (
MInt)(k / (m_noEmbeddedBodies / statFac)) < (
MInt)((k + 1) / (m_noEmbeddedBodies / statFac))) {
7113 cerr <<
"body init completed: " << (
MInt)(100 * (k + 1) / (m_noEmbeddedBodies)) <<
"%" << endl;
7117 for(
MInt i = 0; i < nDim; i++) {
7118 m_bodyCenter[k * nDim + i] = distr(gen) * (m_bbox[nDim + i] - m_bbox[i]);
7122 for(
MInt s = 0; s < 4; s++) {
7127 for(
MInt p = 0;
p < k;
p++) {
7128 const MFloat dkp = maxRadius[k] + maxRadius[
p];
7130 (
POW2(m_bodyCenter[k * nDim] - m_bodyCenter[p * nDim])
7131 +
POW2(m_bodyCenter[k * nDim + 1] - m_bodyCenter[p * nDim + 1])
7132 +
POW2(m_bodyCenter[k * nDim + 2] - m_bodyCenter[p * nDim + 2]))
7133 <
POW2(dist0 + dkp)) {
7139 MBool isOutsideThreshold =
false;
7140 IF_CONSTEXPR(nDim == 2) {
7141 if(m_bodyCenter[p * nDim] < bboxThreshold[0] || m_bodyCenter[p * nDim] > bboxThreshold[3]
7142 || m_bodyCenter[p * nDim + 1] < bboxThreshold[1]
7143 || m_bodyCenter[p * nDim + 1] > bboxThreshold[4]) {
7144 isOutsideThreshold =
true;
7147 IF_CONSTEXPR(nDim == 3) {
7148 if(m_bodyCenter[p * nDim] < bboxThreshold[0] || m_bodyCenter[p * nDim] > bboxThreshold[3]
7149 || m_bodyCenter[p * nDim + 1] < bboxThreshold[1] || m_bodyCenter[p * nDim + 1] > bboxThreshold[4]
7150 || m_bodyCenter[p * nDim + 2] < bboxThreshold[2]
7151 || m_bodyCenter[p * nDim + 2] > bboxThreshold[5]) {
7152 isOutsideThreshold =
true;
7156 if(isOutsideThreshold) {
7158 for(
MInt i = 0; i < nDim; i++) {
7159 coords[1][i] = m_bodyCenter[
p * nDim + i];
7160 coords[0][i] = coords[1][i] - dx[i];
7161 coords[2][i] = coords[1][i] + dx[i];
7163 for(
MInt s0 = -1; s0 <= 1; s0++) {
7164 if(s0 != 0 && !grid().periodicCartesianDir(0))
continue;
7165 for(
MInt s1 = -1; s1 <= 1; s1++) {
7166 if(s1 != 0 && !grid().periodicCartesianDir(1))
continue;
7167 for(
MInt s2 = -1; s2 <= 1; s2++) {
7168 if(s0 == 0 && s1 == 0 && s2 == 0)
continue;
7169 if(s2 != 0 && !grid().periodicCartesianDir(2))
continue;
7171 if(coords[1 + s0][0] < bboxThreshold2[0] || coords[1 + s0][0] > bboxThreshold2[3])
continue;
7172 if(coords[1 + s1][1] < bboxThreshold2[1] || coords[1 + s1][1] > bboxThreshold2[4])
continue;
7173 if(coords[1 + s2][2] < bboxThreshold2[2] || coords[1 + s2][2] > bboxThreshold2[5])
continue;
7176 (
POW2(m_bodyCenter[k * nDim] - coords[1 + s0][0])
7177 +
POW2(m_bodyCenter[k * nDim + 1] - coords[1 + s1][1])
7178 +
POW2(m_bodyCenter[k * nDim + 2] - coords[1 + s2][2]))
7179 <
POW2(dist0 + dkp)) {
7193 if(m_bodyTypeMb == 3 || m_bodyTypeMb == 1 || m_bodyTypeMb == 7) {
7194 MFloat sr = distr2(gen2);
7195 MFloat tt1 = F2 * PI * distr2(gen2);
7196 MFloat tt2 = F2 * PI * distr2(gen2);
7198 MFloat ex = sin(tt1) * sqrt(F1 - sr);
7200 MFloat ez = sin(tt2) * sqrt(sr);
7201 m_bodyQuaternion[4 * k + 0] = ew / sqrt(ew * ew + ex * ex + ey * ey + ez * ez);
7202 m_bodyQuaternion[4 * k + 1] = ex / sqrt(ew * ew + ex * ex + ey * ey + ez * ez);
7203 m_bodyQuaternion[4 * k + 2] = ey / sqrt(ew * ew + ex * ex + ey * ey + ez * ez);
7204 m_bodyQuaternion[4 * k + 3] = ez / sqrt(ew * ew + ex * ex + ey * ey + ez * ez);
7207 if(m_movingBndryCndId == 3008) {
7208 m_bodyTemperature[k] = distr3(gen3) * m_TInfinity;
7211 const MFloat time1 = MPI_Wtime();
7212 cerr <<
"body init time: " << time1 - time0 <<
"s." << endl;
7215 MPI_Bcast(&m_bodyCenter[0], nDim * m_noEmbeddedBodies, MPI_DOUBLE, 0, mpiComm(), AT_,
"m_bodyCenter[0]");
7216 MPI_Bcast(&m_bodyQuaternion[0], 4 * m_noEmbeddedBodies, MPI_DOUBLE, 0, mpiComm(), AT_,
"m_bodyQuaternion[0]");
7217 MPI_Bcast(&m_bodyTemperature[0], m_noEmbeddedBodies, MPI_DOUBLE, 0, mpiComm(), AT_,
"m_bodyTemperature[0]");
7219 if(storeBodyDistribution) {
7220 cerr0 <<
"Storing initial body distribution to file " << fileName << endl;
7221 const MLong DOF = m_noEmbeddedBodies;
7222 const MLong DOF_TRANS = nDim * m_noEmbeddedBodies;
7223 const MLong DOF_QUAT = 4 * m_noEmbeddedBodies;
7225 ParallelIo::size_type start = 0;
7226 ParallelIo::size_type count = 0;
7228 ParallelIo parallelIo(fileName, PIO_REPLACE, mpiComm());
7231 parallelIo.setAttributes(&m_noEmbeddedBodies,
"noBodies", 1);
7232 parallelIo.setAttributes(m_bodyRadii,
"bodyRadii", 3);
7234 parallelIo.defineArray(PIO_FLOAT,
"bodyTemperature", count);
7236 parallelIo.defineArray(PIO_FLOAT,
"bodyCenter", count);
7238 parallelIo.defineArray(PIO_FLOAT,
"bodyQuaternion", count);
7241 parallelIo.setOffset(count, start);
7242 parallelIo.writeArray(m_bodyTemperature,
"bodyTemperature");
7244 parallelIo.setOffset(count, start);
7245 parallelIo.writeArray(m_bodyCenter,
"bodyCenter");
7247 parallelIo.setOffset(count, start);
7248 parallelIo.writeArray(m_bodyQuaternion,
"bodyQuaternion");
7252 createPeriodicGhostBodies();
7253 memset(m_bodyVelocity, 0, m_noEmbeddedBodies * nDim *
sizeof(
MFloat));
7269 for(
MInt i = 0; i < m_noEmbeddedBodies * 4; i++) {
7270 m_bodyQuaternion[i] = Context::getSolverProperty<MFloat>(
"initialBodyQuaternion", m_solverId, AT_, i);
7289 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
7290 for(
MInt j = 0; j < 3; j++) {
7291 bodyRotation[3 * i + j] =
7292 Context::getSolverProperty<MFloat>(
"initialBodyRotation", m_solverId, AT_, j) * PI / 180.0;
7296 for(
MInt i = 0; i < m_noEmbeddedBodies * nDim; i++) {
7297 bodyRotation[i] = Context::getSolverProperty<MFloat>(
"initialBodyRotation", m_solverId, AT_, i) * PI / 180.0;
7300 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7301 setBodyQuaternions(k, &bodyRotation[k * 3]);
7320 const MFloat radius = pow(m_bodyRadii[0] * m_bodyRadii[1] * m_bodyRadii[2], F1B3);
7322 (9.0 / 2.0) * sysEqn().m_muInfinity / (sysEqn().m_Re0 * m_densityRatio * m_rhoInfinity *
POW2(radius));
7323 for(
MInt dir = 0; dir < nDim; dir++) {
7324 m_bodyTerminalVelocity[dir] = Context::getSolverProperty<MFloat>(
"bodyTerminalVelocity", m_solverId, AT_,
7325 &m_bodyTerminalVelocity[dir], dir);
7327 for(
MInt dir = 0; dir < nDim; dir++) {
7328 m_gravity[dir] = FAC0 * m_bodyTerminalVelocity[dir];
7330 for(
MInt k = 0; k < m_noEmbeddedBodies + m_noPeriodicGhostBodies; k++) {
7331 for(
MInt dir = 0; dir < nDim; dir++) {
7332 m_bodyVelocity[nDim * k + dir] += m_bodyTerminalVelocity[dir];
7338 if(m_trackMovingBndry && !m_restart && (m_motionEquation == 0)) {
7339 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7340 for(
MInt i = 0; i < nDim; i++) {
7341 m_bodyCenterDt1[k * nDim + i] = m_bodyCenter[k * nDim + i];
7345 updateBodyProperties();
7350 loadBodyRestartFile(0);
7354 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7355 for(
MInt i = 0; i < nDim; i++) {
7356 m_bodyVelocityDt1[k * nDim + i] = m_bodyVelocity[k * nDim + i];
7357 m_bodyCenterDt1[k * nDim + i] = m_bodyCenter[k * nDim + i];
7358 m_bodyAccelerationDt1[k * nDim + i] = m_bodyAcceleration[k * nDim + i];
7359 if(m_motionEquation > 1) {
7360 m_bodyVelocityDt2[k * nDim + i] = m_bodyVelocity[k * nDim + i];
7361 m_bodyCenterDt2[k * nDim + i] = m_bodyCenter[k * nDim + i];
7362 m_bodyAccelerationDt2[k * nDim + i] = m_bodyAcceleration[k * nDim + i];
7363 m_bodyAccelerationDt3[k * nDim + i] = m_bodyAcceleration[k * nDim + i];
7366 for(
MInt i = 0; i < 3; i++) {
7367 m_bodyTorqueDt1[k * 3 + i] = m_bodyTorque[k * 3 + i];
7368 m_bodyAngularVelocityDt1[k * 3 + i] = m_bodyAngularVelocity[k * 3 + i];
7369 m_bodyAngularAccelerationDt1[k * 3 + i] = m_bodyAngularAcceleration[k * 3 + i];
7371 for(
MInt i = 0; i < 4; i++) {
7372 m_bodyQuaternionDt1[k * 4 + i] = m_bodyQuaternion[k * 4 + i];
7376 if(m_initialCondition == 466) {
7379 m_geometry->getBoundingBox(bbox);
7380 const MFloat delta = F2 * m_UInfinity / (bbox[1 + nDim] - bbox[1]);
7381 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
7382 m_log <<
"Reynolds number "
7384 *
POW2(
mMax(m_bodyRadii[k * nDim + 0],
mMax(m_bodyRadii[k * nDim + 1], m_bodyRadii[k * nDim + 2])))
7386 << sysEqn().m_Re0 * F4 * delta
7387 *
POW2(
mMax(m_bodyRadii[k * nDim + 0],
mMax(m_bodyRadii[k * nDim + 1], m_bodyRadii[k * nDim + 2])))
7394 m_periodicGhostBodyDist = 1.1
7395 * (m_outerBandWidth[
mMin(maxUniformRefinementLevel(), maxRefinementLevel() - 1)]
7396 + ((
MFloat)noHaloLayers()) * c_cellLengthAtLevel(minLevel()) + m_maxBodyRadius);
7397 m_adaptationDampingDistance = m_bodyDiameter[0];
7399 m_periodicGhostBodyDist = 1.1 * ((
MFloat)noHaloLayers()) * c_cellLengthAtLevel(minLevel()) + m_maxBodyRadius;
7402 if(grid().periodicCartesianDir(0) + grid().periodicCartesianDir(1) + grid().periodicCartesianDir(2) > 0) {
7403 createPeriodicGhostBodies();
7405 IF_CONSTEXPR(nDim == 3) { createBodyTree(); }
7407 cerr0 <<
"done." << endl;
7415template <MInt nDim,
class SysEqn>
7417 const MBool saffmanLift =
false;
7419 if(m_pointParticleType == 1) {
7424 const MFloat dt = timeStep();
7425 const MFloat Cvp = m_capacityConstantVolumeRatio;
7428 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
7429 for(
MInt i = 0; i < nDim; i++) {
7430 m_particleCoords[nDim * p + i] =
7431 m_particleCoordsDt1[nDim * p + i]
7432 + F1B2 * dt * (m_particleVelocity[nDim * p + i] + m_particleVelocityDt1[nDim * p + i])
7433 + F1B4 *
POW2(dt) * (m_particleAcceleration[nDim * p + i] + m_particleAccelerationDt1[nDim * p + i]);
7434 m_particleVelocity[nDim * p + i] =
7435 m_particleVelocityDt1[nDim * p + i] + dt * m_particleAcceleration[nDim * p + i];
7437 m_particleTemperature[p] = m_particleTemperatureDt1[p] + dt * m_particleHeatFlux[p];
7441 setParticleFluidVelocities();
7444 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
7445 const MInt cellId = m_particleCellLink[p];
7447 F2 * pow(m_particleRadii[3 * p] * m_particleRadii[3 * p + 1] * m_particleRadii[3 * p + 2], F1B3);
7448 const MFloat T = sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
7449 const MFloat mue = SUTHERLANDLAW(T);
7450 const MFloat FAC = 18.0 * mue / (sysEqn().m_Re0 * m_densityRatio * m_rhoInfinity *
POW2(diameter));
7452 for(
MInt i = 0; i < nDim; i++) {
7453 vrel[i] = m_particleVelocityFluid[nDim * p + i] - m_particleVelocity[nDim * p + i];
7454 Rep +=
POW2(vrel[i]);
7456 Rep = sqrt(Rep) * diameter * a_pvariable(cellId, PV->RHO) * sysEqn().m_Re0 / mue;
7457 vort[0] = a_slope(cellId, PV->VV[2], 1) - a_slope(cellId, PV->VV[1], 2);
7458 vort[1] = a_slope(cellId, PV->VV[0], 2) - a_slope(cellId, PV->VV[2], 0);
7459 vort[2] = a_slope(cellId, PV->VV[1], 0) - a_slope(cellId, PV->VV[0], 1);
7460 lift[0] = vort[2] * vrel[1] - vort[1] * vrel[2];
7461 lift[1] = vort[0] * vrel[2] - vort[2] * vrel[0];
7462 lift[2] = vort[1] * vrel[0] - vort[0] * vrel[1];
7463 MFloat Res = a_pvariable(cellId, PV->RHO) *
POW2(diameter) * sqrt(
POW2(vort[0]) +
POW2(vort[1]) +
POW2(vort[2]))
7464 * sysEqn().m_Re0 / mue;
7465 MFloat beta = F1B2 * Res / Rep;
7466 MFloat CLS = 4.1126 * ((F1 - 0.3314 * sqrt(beta)) * exp(-0.1 * Rep) + 0.3314 * sqrt(beta)) / sqrt(Res);
7467 if(Rep > 40.0) CLS = 0.0524 * sqrt(beta * Rep);
7468 for(
MInt i = 0; i < nDim; i++) {
7469 m_particleAcceleration[nDim * p + i] =
7470 FAC * (F1 + 0.15 * pow(Rep, 0.687)) * vrel[i] + FAC * m_particleTerminalVelocity[i];
7471 if(saffmanLift) m_particleAcceleration[nDim * p + i] += F3B4 * CLS * lift[i] / (m_densityRatio * diameter);
7472 m_particleVelocity[nDim * p + i] =
7473 m_particleVelocityDt1[nDim * p + i]
7474 + dt * F1B2 * (m_particleAcceleration[nDim * p + i] + m_particleAccelerationDt1[nDim * p + i]);
7475 m_particleCoords[nDim * p + i] =
7476 m_particleCoordsDt1[nDim * p + i]
7477 + dt * F1B2 * (m_particleVelocity[nDim * p + i] + m_particleVelocityDt1[nDim * p + i]);
7481 const MFloat particleSurface = PI *
POW2(diameter);
7482 const MFloat mass = F1B6 * PI *
POW3(diameter) * m_densityRatio * m_rhoInfinity;
7485 const MFloat mueParticle = SUTHERLANDLAW(m_particleTemperature[p]);
7488 + pow(m_Pr, 2.0 / 5.0) * (2.0 / 5.0 * pow(Rep, F1B2) + 0.06 * pow(Rep, F2B3)) * pow(mue / mueParticle, 0.25);
7489 const MFloat lambdaFluid = (T * sqrt(T) * m_sutherlandPlusOneThermal) / (T + m_sutherlandConstantThermal);
7490 const MFloat alpha = nusselt * lambdaFluid / diameter;
7491 const MFloat deltaT = m_particleFluidTemperature[p] - m_particleTemperature[p];
7492 m_particleHeatFlux[p] = (particleSurface * alpha * m_gamma) / (mass * Cvp * m_Pr * sysEqn().m_Re0) * deltaT;
7493 m_particleTemperature[p] =
7494 F1B2 * (m_particleTemperature[p] + m_particleTemperatureDt1[p] + dt * m_particleHeatFlux[p]);
7497 }
else if(m_pointParticleType == 3) {
7498 const MFloat dt = timeStep();
7499 const MFloat dt2 = F1B2 * timeStep();
7516 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
7517 const MFloat w = m_particleQuaternionsDt1[4 * p + 0];
7518 const MFloat x = m_particleQuaternionsDt1[4 * p + 1];
7519 const MFloat y = m_particleQuaternionsDt1[4 * p + 2];
7520 const MFloat z = m_particleQuaternionsDt1[4 * p + 3];
7521 for(
MInt i = 0; i < 3; i++) {
7522 q0[i] = m_particleAngularVelocityDt1[3 * p + i];
7524 m_particleQuaternions[4 * p + 0] = w + F1B2 * dt * (-x * q0[0] -
y * q0[1] - z * q0[2]);
7525 m_particleQuaternions[4 * p + 1] = x + F1B2 * dt * (w * q0[0] - z * q0[1] +
y * q0[2]);
7526 m_particleQuaternions[4 * p + 2] =
y + F1B2 * dt * (z * q0[0] + w * q0[1] - x * q0[2]);
7527 m_particleQuaternions[4 * p + 3] = z + F1B2 * dt * (-
y * q0[0] + x * q0[1] + w * q0[2]);
7528 for(
MInt i = 0; i < 3; i++) {
7529 m_particleAngularVelocity[3 * p + i] =
7530 m_particleAngularVelocityDt1[3 * p + i] + dt * m_particleAngularAccelerationDt1[3 * p + i];
7532 for(
MInt i = 0; i < nDim; i++) {
7533 m_particleCoords[nDim * p + i] =
7534 m_particleCoordsDt1[nDim * p + i]
7535 + F1B2 * dt * (m_particleVelocity[nDim * p + i] + m_particleVelocityDt1[nDim * p + i])
7536 + F1B4 *
POW2(dt) * (m_particleAcceleration[nDim * p + i] + m_particleAccelerationDt1[nDim * p + i]);
7537 m_particleVelocity[nDim * p + i] =
7538 m_particleVelocityDt1[nDim * p + i] + dt * m_particleAcceleration[nDim * p + i];
7541 m_particleTemperature[p] = m_particleTemperatureDt1[p] + dt * m_particleHeatFlux[p];
7545 setParticleFluidVelocities();
7548 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
7549 const MInt cellId = m_particleCellLink[p];
7550 const MFloat beta = m_particleRadii[3 * p + 2] / m_particleRadii[3 * p];
7552 const MFloat radius = pow(m_particleRadii[3 * p] * m_particleRadii[3 * p + 1] * m_particleRadii[3 * p + 2], F1B3);
7553 const MFloat diameter = F2 * radius;
7554 const MFloat T = sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
7555 const MFloat mue = SUTHERLANDLAW(T);
7556 const MFloat taup = F2 * m_densityRatio *
POW2(radius) / (9.0 * mue / sysEqn().m_Re0);
7557 const MFloat FAC = (8.0 / 3.0) * pow(beta, F2B3) / taup;
7558 const MFloat FAC2 = (40.0 / 9.0) * pow(beta, F2B3) / taup;
7559 const MFloat FAC0 = (9.0 / 2.0) * mue / (sysEqn().m_Re0 * m_densityRatio * m_rhoInfinity *
POW2(radius));
7562 const MInt maxit = 100;
7566 W(0, 0) = F1 + dt2 * FAC2 / (m_particleShapeParams[4 * p + 1] + beta2 * m_particleShapeParams[4 * p + 3]);
7567 W(1, 1) = F1 + dt2 * FAC2 / (m_particleShapeParams[4 * p + 1] + beta2 * m_particleShapeParams[4 * p + 3]);
7568 W(2, 2) = F1 + dt2 * FAC2 / (F2 * m_particleShapeParams[4 * p + 1]);
7571 for(
MInt i = 0; i < 3; i++) {
7572 tq0[i] = m_particleAngularAccelerationDt1[3 * p + i];
7573 q0[i] = m_particleAngularVelocityDt1[3 * p + i];
7578 for(
MInt i = 0; i < 3; i++) {
7579 MInt id0 = (i + 1) % 3;
7580 MInt id1 = (id0 + 1) % 3;
7582 * (m_particleVelocityGradientFluid[9 * p + 3 * id1 + id0]
7583 + m_particleVelocityGradientFluid[9 * p + 3 * id0 + id1]);
7585 * (m_particleVelocityGradientFluid[9 * p + 3 * id1 + id0]
7586 - m_particleVelocityGradientFluid[9 * p + 3 * id0 + id1]);
7590 while(delta > 1e-10 && it < maxit) {
7591 W(0, 1) = -dt2 * q[2] * (beta2 - F1) / (beta2 + F1);
7592 W(0, 2) = -dt2 * q[1] * (beta2 - F1) / (beta2 + F1);
7593 W(1, 0) = -dt2 * q[2] * (F1 - beta2) / (beta2 + F1);
7594 W(1, 2) = -dt2 * q[0] * (F1 - beta2) / (beta2 + F1);
7598 tq[0] = q[1] * q[2] * (beta2 - F1) / (beta2 + F1)
7599 + FAC2 * (((F1 - beta2) / (F1 + beta2)) * strain[0] + vort[0] - q[0])
7600 / (m_particleShapeParams[4 * p + 1] + beta2 * m_particleShapeParams[4 * p + 3]);
7601 tq[1] = q[0] * q[2] * (F1 - beta2) / (beta2 + F1)
7602 + FAC2 * (((beta2 - F1) / (F1 + beta2)) * strain[1] + vort[1] - q[1])
7603 / (m_particleShapeParams[4 * p + 1] + beta2 * m_particleShapeParams[4 * p + 3]);
7604 tq[2] = FAC2 * (vort[2] - q[2]) / (F2 * m_particleShapeParams[4 * p + 1]);
7606 for(
MInt i = 0; i < 3; i++)
7607 rhs[i] = q[i] - q0[i] - dt2 * (tq0[i] + tq[i]);
7610 for(
MInt i = 0; i < 3; i++) {
7612 for(
MInt j = 0; j < 3; j++) {
7613 q[i] -= W(i, j) * rhs(j);
7615 delta =
mMax(delta, fabs(q[i] - qq));
7619 if(it >= maxit || it <= 0) {
7620 cerr <<
"Newton iterations did not converge " << p << endl;
7623 m_particleAngularVelocity[3 * p + 0] = q[0];
7624 m_particleAngularVelocity[3 * p + 1] = q[1];
7625 m_particleAngularVelocity[3 * p + 2] = q[2];
7626 m_particleAngularAcceleration[3 * p + 0] = tq[0];
7627 m_particleAngularAcceleration[3 * p + 1] = tq[1];
7628 m_particleAngularAcceleration[3 * p + 2] = tq[2];
7631 const MFloat w = m_particleQuaternionsDt1[4 * p + 0];
7632 const MFloat x = m_particleQuaternionsDt1[4 * p + 1];
7633 const MFloat y = m_particleQuaternionsDt1[4 * p + 2];
7634 const MFloat z = m_particleQuaternionsDt1[4 * p + 3];
7653 for(
MInt i = 0; i < 4; i++)
7654 for(
MInt j = 0; j < 4; j++)
7655 W(i, j) = -F1B2 * dt2 * W(i, j);
7656 for(
MInt i = 0; i < 4; i++)
7659 rhs(0) = w + F1B2 * dt2 * (-x * q0[0] -
y * q0[1] - z * q0[2]);
7660 rhs(1) = x + F1B2 * dt2 * (w * q0[0] - z * q0[1] +
y * q0[2]);
7661 rhs(2) =
y + F1B2 * dt2 * (z * q0[0] + w * q0[1] - x * q0[2]);
7662 rhs(3) = z + F1B2 * dt2 * (-
y * q0[0] + x * q0[1] + w * q0[2]);
7666 for(
MInt i = 0; i < 4; i++) {
7667 m_particleQuaternions[4 * p + i] = F0;
7668 for(
MInt j = 0; j < 4; j++) {
7669 m_particleQuaternions[4 * p + i] += W(i, j) * rhs(j);
7674 for(
MInt i = 0; i < 4; i++)
7675 abs +=
POW2(m_particleQuaternions[4 * p + i]);
7676 for(
MInt i = 0; i < 4; i++)
7677 m_particleQuaternions[4 * p + i] /= sqrt(abs);
7681 K(0, 0) = F1 / (m_particleShapeParams[4 * p] /
POW2(m_particleRadii[3 * p]) + m_particleShapeParams[4 * p + 1]);
7684 F1 / (m_particleShapeParams[4 * p] /
POW2(m_particleRadii[3 * p]) + beta2 * m_particleShapeParams[4 * p + 3]);
7685 computeRotationMatrix(R, &(m_particleQuaternions[4 * p]));
7686 for(
MInt i = 0; i < nDim; i++) {
7687 vrel[i] = m_particleVelocityFluid[nDim * p + i] - m_particleVelocity[nDim * p + i];
7689 matrixVectorProduct(vrelhat, R, vrel);
7690 matrixVectorProduct(tmp, K, vrelhat);
7691 matrixVectorProductTranspose(vrel, R, tmp);
7693 for(
MInt i = 0; i < nDim; i++) {
7694 m_particleAcceleration[nDim * p + i] = FAC * vrel[i] + FAC0 * m_particleTerminalVelocity[i];
7695 m_particleVelocity[nDim * p + i] =
7696 m_particleVelocityDt1[nDim * p + i]
7697 + dt * F1B2 * (m_particleAcceleration[nDim * p + i] + m_particleAccelerationDt1[nDim * p + i]);
7698 m_particleCoords[nDim * p + i] =
7699 m_particleCoordsDt1[nDim * p + i]
7700 + dt * F1B2 * (m_particleVelocity[nDim * p + i] + m_particleVelocityDt1[nDim * p + i])
7701 + F1B4 *
POW2(dt) * (m_particleAcceleration[nDim * p + i] + m_particleAccelerationDt1[nDim * p + i]);
7705 const MFloat mass = F4B3 * PI * m_particleRadii[3 * p] * m_particleRadii[3 * p + 1] * m_particleRadii[3 * p + 2]
7706 * m_densityRatio * m_rhoInfinity;
7707 const MFloat Cvp = m_capacityConstantVolumeRatio;
7709 MFloat particleSurface = 0;
7710 if(fabs(beta - F1) < 1e-14)
7711 particleSurface = 4 * PI *
POW2(m_particleRadii[3 * p]);
7714 const MFloat factor = sqrt(1 - beta2);
7716 2 * PI * m_particleRadii[3 * p] * m_particleRadii[3 * p + 1] * (1 + (beta2 / factor * atanh(factor)));
7718 const MFloat factor = sqrt(1 - 1 / beta2);
7719 particleSurface = 2 * PI * m_particleRadii[3 * p] * m_particleRadii[3 * p + 1]
7720 * (1 + m_particleRadii[3 * p + 2] / (m_particleRadii[3 * p] * factor) * asin(factor));
7725 const MFloat nusselt = 2;
7726 const MFloat lambdaFluid = (T * sqrt(T) * m_sutherlandPlusOneThermal) / (T + m_sutherlandConstantThermal);
7727 const MFloat alpha = nusselt * lambdaFluid / diameter;
7728 const MFloat deltaT = m_particleFluidTemperature[p] - m_particleTemperature[p];
7729 m_particleHeatFlux[p] = (particleSurface * alpha * m_gamma) / (mass * Cvp * m_Pr * sysEqn().m_Re0) * deltaT;
7730 m_particleTemperature[p] =
7731 F1B2 * (m_particleTemperature[p] + m_particleTemperatureDt1[p] + dt * m_particleHeatFlux[p]);
7734 mTerm(1, AT_,
"part type.");
7743template <MInt nDim,
class SysEqn>
7745 IF_CONSTEXPR(nDim == 2)
mTerm(1, AT_,
"Go for 3D.");
7747 const MBool fourthOrder =
false;
7748 const MInt maxNoNghbrs = 150;
7749 const MInt recDim = fourthOrder ? 19 : 10;
7756 for(
MUint p = 0; p < m_particleCellLink.size(); p++) {
7757 const MInt cellId = m_particleCellLink[p];
7758 const MFloat normalizationFactor =
7759 F1 / c_cellLengthAtCell(cellId);
7760 const MInt counter = 1 + this->
template getAdjacentLeafCells<2>(cellId, 1, nghbrList, layerId);
7761 for(
MInt i = counter - 1; i > 0; i--)
7762 nghbrList[i] = nghbrList[i - 1];
7763 nghbrList[0] = cellId;
7765 for(
MInt c = 0; c < counter; c++) {
7766 const MInt nghbrId = nghbrList(c);
7769 for(
MInt i = 0; i < nDim; i++) {
7770 deltaX[i] = (a_coordinate(nghbrId, i) - m_particleCoords[nDim * p + i]) * normalizationFactor;
7776 for(
MInt i = 0; i < nDim; i++) {
7777 mat(c, cnt) = deltaX[i];
7780 for(
MInt i = 0; i < nDim; i++) {
7781 for(
MInt j = i; j < nDim; j++) {
7782 const MFloat fac = (i == j) ? F1B2 : F1;
7783 mat(c, cnt) = fac * deltaX[i] * deltaX[j];
7788 for(
MInt i = 0; i < nDim; i++) {
7789 for(
MInt j = i; j < nDim; j++) {
7790 for(
MInt k = j; k < nDim; k++) {
7791 const MFloat fac = (i == j && i == k) ? F1B6 : ((i == j || i == k || j == k) ? F1B2 : F1);
7792 mat(c, cnt) = fac * deltaX[i] * deltaX[j] * deltaX[k];
7801 for(
MInt c = 0; c < counter; c++) {
7803 for(
MInt i = 0; i < nDim; i++) {
7804 mat(cnt, c) *= normalizationFactor;
7807 for(
MInt i = 0; i < nDim; i++) {
7808 for(
MInt j = i; j < nDim; j++) {
7809 mat(cnt, c) *=
POW2(normalizationFactor);
7814 for(
MInt i = 0; i < nDim; i++) {
7815 for(
MInt j = i; j < nDim; j++) {
7816 for(
MInt k = j; k < nDim; k++) {
7817 mat(cnt, c) *=
POW3(normalizationFactor);
7826 computeRotationMatrix(R, &(m_particleQuaternions[4 * p]));
7828 for(
MInt i = 0; i < nDim; i++) {
7829 m_particleVelocityFluid[nDim * p + i] = F0;
7831 m_particleFluidTemperature[p] = F0;
7832 for(
MInt c = 0; c < counter; c++) {
7833 for(
MInt i = 0; i < nDim; i++) {
7834 m_particleVelocityFluid[nDim * p + i] += mat(0, c) * a_pvariable(nghbrList[c], PV->VV[i]);
7836 m_particleFluidTemperature[p] +=
7837 mat(0, c) * sysEqn().temperature_ES(a_pvariable(nghbrList[c], PV->RHO), a_pvariable(nghbrList[c], PV->P));
7840 MFloat velGrad[3][3] = {{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}};
7841 for(
MInt c = 0; c < counter; c++) {
7842 MFloat coeffs0[3] = {mat(1, c), mat(2, c), mat(3, c)};
7843 MFloat vel0[3] = {a_pvariable(nghbrList[c], PV->U), a_pvariable(nghbrList[c], PV->V),
7844 a_pvariable(nghbrList[c], PV->W)};
7847 matrixVectorProduct(coeffs, R, coeffs0);
7848 matrixVectorProduct(vel, R, vel0);
7849 for(
MInt i = 0; i < nDim; i++) {
7850 for(
MInt j = 0; j < nDim; j++) {
7851 velGrad[i][j] += coeffs[j] * vel[i];
7856 for(
MInt i = 0; i < nDim; i++) {
7857 for(
MInt j = 0; j < nDim; j++) {
7858 m_particleVelocityGradientFluid[9 * p + 3 * i + j] = velGrad[i][j];
7862 if(pressure !=
nullptr) {
7864 for(
MInt c = 0; c < counter; c++) {
7865 pressure[p] += mat(0, c) * a_pvariable(nghbrList[c], PV->P);
7876template <MInt nDim,
class SysEqn>
7877template <
class _, std::enable_if_t<nDim == 3, _*>>
7881 if(m_noLevelSetsUsedForMb > 1 && m_buildCollectedLevelSetFunction) {
7882 const MFloat delta0 = F2 * c_cellLengthAtLevel(maxRefinementLevel());
7883 const MFloat deltaMax = F2 * m_maxBodyRadius + delta0;
7887 for(
MInt i = 0; i < m_noLevelSetsUsedForMb; i++) {
7888 for(
MInt j = 0; j < m_maxNoEmbeddedBodiesPeriodic; j++) {
7889 m_setToBodiesTable[i][j] = -1;
7891 m_noBodiesInSet[i] = 0;
7893 for(
MInt i = 0; i < m_maxNoEmbeddedBodiesPeriodic; i++) {
7894 m_bodyToSetTable[i] = -1;
7896 if(m_startSet > 0) {
7897 m_noBodiesInSet[0] = 0;
7898 for(
MInt i = 0; i < m_noEmbeddedBodies + m_noPeriodicGhostBodies; i++) {
7899 m_setToBodiesTable[0][m_noBodiesInSet[0]] = i;
7900 m_noBodiesInSet[0]++;
7903 m_noSets = m_startSet;
7906 for(
MInt p = 0; p < m_noEmbeddedBodies + m_noPeriodicGhostBodies; p++) {
7907 MInt id = m_startSet;
7909 if(m_noEmbeddedBodies > (m_noLevelSetsUsedForMb - m_startSet)) {
7910 Point<3> pt(m_bodyCenter[p * nDim], m_bodyCenter[p * nDim + 1], m_bodyCenter[p * nDim + 2]);
7911 MInt noNearBodies = locatenear(pt, deltaMax, &nearBodies[0], m_noEmbeddedBodies);
7912 MBool overlap =
true;
7913 minDist.
fill(c_cellLengthAtLevel(0));
7915 while(overlap &&
id < m_noLevelSetsUsedForMb) {
7917 for(
MInt b = 0;
b < noNearBodies;
b++) {
7918 const MInt q = nearBodies[
b];
7919 if(p == q)
continue;
7920 if(m_bodyToSetTable[q] ==
id) {
7922 MFloat dist = sqrt(
POW2(m_bodyCenter[p * nDim] - m_bodyCenter[q * nDim])
7923 +
POW2(m_bodyCenter[p * nDim + 1] - m_bodyCenter[q * nDim + 1])
7924 +
POW2(m_bodyCenter[p * nDim + 2] - m_bodyCenter[q * nDim + 2]))
7925 - F2 * m_maxBodyRadius;
7926 minDist(
id) =
mMin(minDist(
id),
dist);
7927 ASSERT(
dist < delta0 + m_eps,
"");
7936 for(
MInt i = m_startSet; i < m_noLevelSetsUsedForMb; i++) {
7937 if(minDist(i) > minDist(
id))
id = i;
7940 cerr0 << domainId() <<
": Not enough level sets to prevent overlap: " << p <<
" " <<
id <<
" "
7941 << minDist(
id) / c_cellLengthAtLevel(m_lsCutCellMinLevel) <<
" " << m_maxBodyRadius << endl;
7944 m_bodyToSetTable[p] =
id;
7945 m_setToBodiesTable[
id][m_noBodiesInSet[
id]] = p;
7946 m_noBodiesInSet[
id]++;
7948 id = m_startSet + p % (m_noLevelSetsUsedForMb - 1);
7949 if(
id >= m_noLevelSetsUsedForMb)
mTerm(1, AT_,
"Wrong set handling");
7950 m_bodyToSetTable[p] =
id;
7951 m_setToBodiesTable[
id][m_noBodiesInSet[
id]] = p;
7952 m_noBodiesInSet[
id]++;
7954 m_noSets =
mMax(m_noSets,
id + 1);
7966template <MInt nDim,
class SysEqn>
7967template <
class _, std::enable_if_t<nDim == 2, _*>>
7975template <MInt nDim,
class SysEqn>
7979 m_noPeriodicGhostBodies = 0;
7980 if(grid().periodicCartesianDir(0) + grid().periodicCartesianDir(1) + grid().periodicCartesianDir(2) == 0)
return;
7981 if(m_bodyTypeMb == 2)
return;
7982 if(grid().azimuthalPeriodicity()) {
7987 for(
MInt i = 0; i < nDim; i++) {
7988 dx[i] = m_bbox[nDim + i] - m_bbox[i];
7991 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
7993 m_internalBodyId[
b] =
b;
7994 for(
MInt i = 0; i < nDim; i++) {
7995 const MFloat displ = m_bodyCenter[
b * nDim + i] - m_bodyCenterDt1[
b * nDim + i];
7996 const MFloat displ2 = (m_motionEquation > 1) ? m_bodyCenter[
b * nDim + i] - m_bodyCenterDt2[
b * nDim + i] : F0;
7997 if(m_bodyCenter[
b * nDim + i] < m_bbox[i]) {
7998 m_bodyCenter[
b * nDim + i] += dx[i];
7999 }
else if(m_bodyCenter[
b * nDim + i] > m_bbox[nDim + i]) {
8000 m_bodyCenter[
b * nDim + i] -= dx[i];
8002 m_bodyCenterDt1[
b * nDim + i] = m_bodyCenter[
b * nDim + i] - displ;
8003 if(m_motionEquation > 1) {
8004 m_bodyCenterDt2[
b * nDim + i] = m_bodyCenter[
b * nDim + i] - displ2;
8009 m_periodicGhostBodies[
b].clear();
8010 IF_CONSTEXPR(nDim == 2) {
8011 if(m_bodyCenter[
b * nDim] > m_bbox[0] + m_periodicGhostBodyDist
8012 && m_bodyCenter[
b * nDim] < m_bbox[3] - m_periodicGhostBodyDist
8013 && m_bodyCenter[
b * nDim + 1] > m_bbox[1] + m_periodicGhostBodyDist
8014 && m_bodyCenter[
b * nDim + 1] < m_bbox[4] - m_periodicGhostBodyDist) {
8018 else IF_CONSTEXPR(nDim == 3) {
8019 if(m_bodyCenter[
b * nDim] > m_bbox[0] + m_periodicGhostBodyDist
8020 && m_bodyCenter[
b * nDim] < m_bbox[3] - m_periodicGhostBodyDist
8021 && m_bodyCenter[
b * nDim + 1] > m_bbox[1] + m_periodicGhostBodyDist
8022 && m_bodyCenter[
b * nDim + 1] < m_bbox[4] - m_periodicGhostBodyDist
8023 && m_bodyCenter[
b * nDim + 2] > m_bbox[2] + m_periodicGhostBodyDist
8024 && m_bodyCenter[
b * nDim + 2] < m_bbox[5] - m_periodicGhostBodyDist) {
8028 for(
MInt s0 = -1; s0 <= 1; s0++) {
8029 if(s0 != 0 && !grid().periodicCartesianDir(0))
continue;
8030 for(
MInt s1 = -1; s1 <= 1; s1++) {
8031 if(s1 != 0 && !grid().periodicCartesianDir(1))
continue;
8032 for(
MInt s2 = -1; s2 <= 1; s2++) {
8033 if(s2 != 0 && !grid().periodicCartesianDir(2))
continue;
8034 if(s0 == 0 && s1 == 0 && s2 == 0)
continue;
8036 MFloat coords[3] = {F0, F0, F0};
8037 MBool tooFar =
false;
8038 for(
MInt i = 0; i < nDim; i++) {
8039 coords[i] = m_bodyCenter[
b * nDim + i] + sign[i] * dx[i];
8040 if(coords[i] < m_bbox[i] - m_periodicGhostBodyDist
8041 || coords[i] > m_bbox[nDim + i] + m_periodicGhostBodyDist)
8044 if(tooFar)
continue;
8045 const MInt k = m_noEmbeddedBodies + m_noPeriodicGhostBodies;
8046 if(k >= m_maxNoEmbeddedBodiesPeriodic)
8048 "Increase m_maxNoEmbeddedBodiesPeriodic " + to_string(m_noEmbeddedBodies) +
" "
8049 + to_string(m_noPeriodicGhostBodies));
8050 transferBodyState(k,
b);
8051 for(
MInt i = 0; i < nDim; i++) {
8052 m_bodyCenter[k * nDim + i] = coords[i];
8054 m_internalBodyId[k] =
b;
8055 m_periodicGhostBodies[
b].push_back(k);
8056 m_noPeriodicGhostBodies++;
8063 m_log <<
"No periodic ghost bodies: " << m_noPeriodicGhostBodies <<
" ("
8064 << 100.0 * ((
MFloat)m_noPeriodicGhostBodies) / ((
MFloat)m_noEmbeddedBodies) <<
"%)" << endl;
8073template <MInt nDim,
class SysEqn>
8077 m_bodyRadius[k] = m_bodyRadius[
b];
8078 m_bodyDiameter[k] = m_bodyDiameter[
b];
8079 for(
MInt i = 0; i < nDim; i++) {
8080 m_bodyVelocity[k * nDim + i] = m_bodyVelocity[
b * nDim + i];
8081 m_bodyAcceleration[k * nDim + i] = m_bodyAcceleration[
b * nDim + i];
8083 for(
MInt i = 0; i < 3; i++) {
8084 m_bodyRadii[k * 3 + i] = m_bodyRadii[
b * 3 + i];
8085 m_bodyAngularVelocity[k * 3 + i] = m_bodyAngularVelocity[
b * 3 + i];
8086 m_bodyAngularAcceleration[k * 3 + i] = m_bodyAngularAcceleration[
b * 3 + i];
8088 for(
MInt i = 0; i < 4; i++) {
8089 m_bodyQuaternion[k * 4 + i] = m_bodyQuaternion[
b * 4 + i];
8099template <MInt nDim,
class SysEqn>
8103 ASSERT(!m_LsMovement,
"");
8105 for(
MInt body = 0; body < m_noEmbeddedBodies; body++) {
8106 MFloat bodyRotation[3] = {0};
8107 getBodyRotation(body, bodyRotation);
8109 switch(m_bodyEquation[body]) {
8115 timeOffset = Context::getSolverProperty<MFloat>(
"timeOffset", m_solverId, AT_, &timeOffset);
8116 MFloat targetBodyVelocity = F0;
8117 targetBodyVelocity =
8118 Context::getSolverProperty<MFloat>(
"targetBodyVelocity", m_solverId, AT_, &targetBodyVelocity);
8120 m_bodyCenter[0] += m_bodyVelocity[0] * timeStep();
8121 m_bodyVelocity[0] = targetBodyVelocity * m_UInfinity * F1B2 * (tanh(100.0 * (m_time - timeOffset)) + F1);
8122 m_bodyAcceleration[0] =
8123 targetBodyVelocity * m_UInfinity * F1B2
8124 * (tanh(100.0 * (m_time + 0.0001 - timeOffset)) - tanh(100.0 * (m_time - 0.0001 - timeOffset))) / 0.0002;
8125 cerr <<
"DEBUG DANIEL " <<
globalTimeStep <<
" " << m_time <<
" " << m_bodyCenter[0] <<
" " << m_bodyVelocity[0]
8126 <<
" " << m_bodyAcceleration[0] << endl;
8137 MFloat elapsedTime = m_physicalTime - timeOffset;
8139 const MFloat D = F2 * m_bodyRadius[0];
8151 MFloat amplitudeFactor = 0.1;
8152 amplitudeFactor = Context::getSolverProperty<MFloat>(
"amplitudeFactor", m_solverId, AT_, &litudeFactor);
8166 freqFactor = Context::getSolverProperty<MFloat>(
"freqFactor", m_solverId, AT_, &freqFactor);
8168 Strouhal = Context::getSolverProperty<MFloat>(
"Strouhal", m_solverId, AT_, &Strouhal);
8169 const MFloat A = amplitudeFactor * D;
8171 Strouhal * m_UInfinity / m_referenceLength;
8172 const MFloat mu = freqFactor * freq0 * F2 * PI;
8174 if(elapsedTime > F0) {
8175 m_bodyCenter[1] = -A *
cos(mu * elapsedTime);
8176 m_bodyVelocity[1] = mu * A * sin(mu * elapsedTime);
8177 m_bodyAcceleration[1] = mu * mu * A *
cos(mu * elapsedTime);
8179 m_bodyCenter[1] = -A;
8180 m_bodyVelocity[1] = F0;
8181 m_bodyAcceleration[1] = F0;
8189 MFloat deltaT = timeStep();
8190 if(m_dualTimeStepping) forceTimeStep(m_physicalTimeStep);
8191 for(
MInt i = 0; i < nDim; i++) {
8192 m_bodyVelocity[i] = m_VVInfinity[i];
8193 m_bodyCenter[i] += deltaT * m_bodyVelocity[i];
8201 const MFloat frequency = m_UInfinity / KC;
8203 m_bodyVelocity[0] = KC * frequency *
cos(F2 * PI * frequency * m_time);
8204 m_bodyVelocity[1] = F0;
8205 m_bodyCenter[0] = KC / (F2 * PI) * sin(F2 * PI * frequency * m_time);
8206 m_bodyCenter[1] = F0;
8218 const MFloat deltaT = m_physicalTime - m_physicalTimeDt1;
8219 for(
MInt i = 0; i < nDim; i++) {
8220 m_bodyCenter[nDim * body + i] = m_bodyCenterDt1[nDim * body + i] + deltaT * m_bodyVelocity[nDim * body + i];
8228 for(
MInt i = 0; i < nDim; i++) {
8229 m_bodyCenter[i] = F0;
8230 m_bodyVelocity[i] = F0;
8231 m_bodyAcceleration[i] = F0;
8233 m_bodyCenter[0] = m_UInfinity * m_physicalTime;
8234 m_bodyVelocity[0] = m_UInfinity;
8240 for(
MInt i = 0; i < nDim; i++) {
8241 m_bodyCenter[i] = F0;
8242 m_bodyVelocity[i] = F0;
8243 m_bodyAcceleration[i] = F0;
8246 const MFloat t = m_physicalTime / T1;
8248 m_bodyCenter[0] = m_UInfinity * (m_physicalTime - F1B2 * T1);
8249 m_bodyVelocity[0] = m_UInfinity;
8250 m_bodyAcceleration[0] = F0;
8252 m_bodyCenter[0] = m_UInfinity *
POW3(t) * T1 * (F1 - F1B2 * t);
8253 m_bodyVelocity[0] = m_UInfinity *
POW2(t) * (F3 - F2 * t);
8254 m_bodyAcceleration[0] = m_UInfinity * F6 * t * (F1 - t) / T1;
8262 MFloat elapsedTime = m_physicalTime + ddt;
8263 const MFloat D = F2 * m_bodyRadius[0];
8264 MFloat amplitudeFactor = 0.1;
8265 amplitudeFactor = Context::getSolverProperty<MFloat>(
"amplitudeFactor", m_solverId, AT_, &litudeFactor);
8267 freqFactor = Context::getSolverProperty<MFloat>(
"freqFactor", m_solverId, AT_, &freqFactor);
8269 Strouhal = Context::getSolverProperty<MFloat>(
"Strouhal", m_solverId, AT_, &Strouhal);
8270 const MFloat A = amplitudeFactor * D;
8271 const MFloat freq0 = Strouhal * m_UInfinity / m_referenceLength;
8272 const MFloat mu = freqFactor * freq0 * F2 * PI;
8280 MFloat dt = timeStep() * ((
MFloat)Context::getSolverProperty<MInt>(
"outputOffset", m_solverId, AT_));
8285 m_bodyVelocityDt1[1] = m_bodyVelocity[1];
8286 m_bodyCenterDt1[1] = m_bodyCenter[1];
8288 if(elapsedTime > F0) {
8290 -A *
cos(mu * elapsedTime);
8291 m_bodyVelocity[1] = mu * A * sin(mu * elapsedTime);
8292 m_bodyAcceleration[1] = mu * mu * A *
cos(mu * elapsedTime);
8294 m_bodyCenter[1] = -A;
8295 m_bodyVelocity[1] = F0;
8296 m_bodyAcceleration[1] = F0;
8307 const MInt k = body;
8308 for(
MInt i = 0; i < 3; i++) {
8309 globalMI[3 * k + i] = F0;
8310 m_bodyMomentOfInertia[3 * k + i] = F0;
8312 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
8313 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
8314 if(a_associatedBodyIds(cellId, 0) != k)
continue;
8315 if(a_isHalo(cellId))
continue;
8316 if(a_isBndryGhostCell(cellId))
continue;
8317 MFloat dx[3] = {F0, F0, F0};
8318 MFloat normal[3] = {F0, F0, F0};
8319 MFloat fac[3] = {F0, F0, F0};
8320 for(
MInt i = 0; i < nDim; i++) {
8321 dx[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[i] - m_bodyCenter[nDim * k + i];
8322 normal[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[i];
8324 IF_CONSTEXPR(nDim == 3) {
8325 fac[0] = normal[1] *
POW3(dx[1]) + normal[2] *
POW3(dx[2]);
8326 fac[1] = normal[0] *
POW3(dx[0]) + normal[2] *
POW3(dx[2]);
8328 fac[2] = normal[0] *
POW3(dx[0]) + normal[1] *
POW3(dx[1]);
8329 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_area;
8330 for(
MInt i = 0; i < 3; i++) {
8331 m_bodyMomentOfInertia[3 * k + i] += area * fac[i];
8334 for(
MInt i = 0; i < 3; i++) {
8335 m_bodyMomentOfInertia[3 * k + i] *= F1B3 * m_bodyDensity[k];
8336 m_log <<
"BMI " << k <<
" " << i <<
" " << m_bodyMomentOfInertia[3 * k + i] << endl;
8350 MPI_Allreduce(MPI_IN_PLACE, &(m_bodyMomentOfInertia[3 * k]), 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
8351 "MPI_IN_PLACE",
"(m_bodyMomentOfInertia[3*k])");
8371 KC = Context::getSolverProperty<MFloat>(
"KeuleganCarpenter", m_solverId, AT_, &KC);
8385 Sf = Context::getSolverProperty<MFloat>(
"nonDimensionalFreq", m_solverId, AT_, &Sf);
8387 const MFloat elapsedTime = m_physicalTime;
8388 const MFloat freq = Sf * m_UInfinity / m_referenceLength;
8389 const MFloat mu = F2 * PI * freq;
8390 const MFloat A = m_referenceLength * KC;
8392 m_bodyCenter[0] = A * sin(mu * elapsedTime);
8393 m_bodyVelocity[0] = mu * A *
cos(mu * elapsedTime);
8394 m_bodyAcceleration[0] = -mu * mu * A * sin(mu * elapsedTime);
8401 IF_CONSTEXPR(nDim == 2) {
8402 const MFloat t = m_time + timeStep() * m_timeRef;
8403 m_bodyCenter[0] = -0.125 *
cos(F2 * PI * t);
8404 m_bodyVelocity[0] = m_timeRef * 0.25 * PI * sin(F2 * PI * t);
8405 m_bodyAcceleration[0] = m_timeRef * m_timeRef * 0.5 * PI * PI *
cos(F2 * PI * t);
8434 MFloat StokesNumber = F4;
8435 StokesNumber = Context::getSolverProperty<MFloat>(
"StokesNumber", m_solverId, AT_, &StokesNumber);
8437 const MFloat Strouhal = F4 *
POW2(StokesNumber) / m_Re;
8440 const MFloat elapsedTime = m_physicalTime;
8441 const MFloat freq = F2 * Strouhal * m_UInfinity / m_referenceLength;
8443 MBool& firstRun = m_static_updateBodyProperties_c453_firstRun;
8445 cerr << StokesNumber <<
" " << Strouhal <<
" " << m_Re <<
" " << sysEqn().m_Re0 << endl;
8449 m_bodyCenter[0] = -m_UInfinity *
cos(freq * elapsedTime) / freq;
8450 m_bodyVelocity[0] = m_UInfinity * sin(freq * elapsedTime);
8451 m_bodyAcceleration[0] = freq * m_UInfinity *
cos(freq * elapsedTime);
8453 const MFloat t = m_physicalTime;
8454 const MFloat w = F2 * m_Ma * F4 *
POW2(StokesNumber) / m_Re;
8455 m_bodyCenter[0] = -m_Ma *
cos(w * t) / w;
8456 m_bodyVelocity[0] = m_Ma * sin(w * t);
8457 m_bodyAcceleration[0] = m_Ma * w *
cos(w * t);
8471 const MFloat speedOfSoundInf = sysEqn().speedOfSound(m_rhoInfinity, m_PInfinity);
8473 const MFloat T1 = T0 + 20.0 * m_bodyRadius[0] / speedOfSoundInf;
8474 const MFloat elapsedTime = m_physicalTime + timeStep();
8475 const MFloat alpha = 6e-4;
8476 const MFloat accel = -alpha *
POW2(speedOfSoundInf) / m_bodyRadius[0];
8478 if(elapsedTime < T0) {
8479 m_bodyCenter[0] = F0;
8480 m_bodyVelocity[0] = F0;
8481 m_bodyAcceleration[0] = F0;
8482 }
else if(elapsedTime < T1) {
8483 m_bodyAcceleration[0] = accel;
8484 m_bodyVelocity[0] = accel * (elapsedTime - T0);
8485 m_bodyCenter[0] = F1B2 * accel *
POW2(elapsedTime - T0);
8487 m_bodyAcceleration[0] = F0;
8488 m_bodyCenter[0] = F1B2 * accel *
POW2(T1 - T0) + m_bodyVelocity[0] * (elapsedTime - T1);
8498 const MFloat elapsedTime = m_physicalTime + timeStep();
8499 m_bodyAcceleration[0] = F0;
8500 m_bodyVelocity[0] = m_Ma;
8501 m_bodyCenter[0] = elapsedTime * m_Ma;
8507 MBool oscil =
false;
8521 const MFloat degToRad = -PI / 180.0;
8522 const MFloat t = m_physicalTime + timeStep();
8526 MFloat w = F2 * f * m_UInfinity;
8534 bodyRotation[2] = (a0 + a1 * sin(w * t)) * degToRad;
8535 m_bodyAngularVelocity[2] = (a1 * w *
cos(w * t)) * degToRad;
8536 m_bodyAngularAcceleration[2] = (-a1 * w * w * sin(w * t)) * degToRad;
8548 const MFloat degToRad = -PI / 180.0;
8550 const MFloat t =
mMax(F0, m_physicalTime + timeStep() - t0);
8554 const MFloat w = F2 * m_UInfinity * f;
8559 bodyRotation[2] = (a0 * (F1 -
cos(w * t))) * degToRad;
8560 m_bodyAngularVelocity[2] = (a0 * w * sin(w * t)) * degToRad;
8561 m_bodyAngularAcceleration[2] = (a0 * w * w *
cos(w * t)) * degToRad;
8563 const MFloat degToRad = -PI / 180.0;
8564 const MFloat fac = m_UInfinity / m_Ma;
8565 const MFloat b = 2.2918312 * fac;
8566 const MFloat c = 1.84 * fac;
8569 const MFloat t =
mMax(F0, m_physicalTime + timeStep() - t0);
8573 factor = Context::getSolverProperty<MFloat>(
"freqFactor", m_solverId, AT_, &factor);
8575 t0p = Context::getSolverProperty<MFloat>(
"amplitudeFactor", m_solverId, AT_, &t0p);
8577 if((t < m_eps) || (fabs(factor) < m_eps)) {
8578 bodyRotation[2] = F0;
8579 m_bodyAngularVelocity[2] = F0;
8580 m_bodyAngularAcceleration[2] = F0;
8584 bodyRotation[2] = (
b * t +
a * (F1 - exp(-c * t))) * degToRad;
8585 m_bodyAngularVelocity[2] = (
b +
a * c * exp(-c * t)) * degToRad;
8586 m_bodyAngularAcceleration[2] = (-
a * c * c * exp(-c * t)) * degToRad;
8588 const MFloat omega0 = -factor * m_UInfinity;
8589 const MFloat it0 = 4.6 * m_UInfinity / t0p;
8590 const MFloat et = exp(-it0 * t);
8592 bodyRotation[2] = omega0 * (t + (et - F1) / it0);
8593 m_bodyAngularVelocity[2] = omega0 * (F1 - et);
8594 m_bodyAngularAcceleration[2] = omega0 * it0 * et;
8598 cerr <<
globalTimeStep <<
" alpha " << -bodyRotation[2] * 180 / PI
8599 <<
" deg, TE:" <<
cos(bodyRotation[2]) * 0.75 <<
"/" << sin(bodyRotation[2]) * 0.75 << endl;
8606 MFloat A = 0.1 * (F2 * m_bodyRadius[0]);
8608 MFloat C = f * F2 * PI * m_UInfinity;
8610 const MFloat t = m_physicalTime + timeStep();
8611 m_bodyCenter[0] = -A *
cos(C * t);
8612 m_bodyVelocity[0] = A * C * sin(C * t);
8613 m_bodyAcceleration[0] = A *
POW2(C) *
cos(C * t);
8618 MFloat elapsedTime = m_physicalTime;
8621 MFloat freq0 = F2 * PI * m_UInfinity;
8635 freq0 = m_UInfinity / 0.1;
8636 m_bodyCenter[0] = -m_UInfinity *
cos(freq0 * elapsedTime) / freq0;
8637 m_bodyVelocity[0] = m_UInfinity * sin(freq0 * elapsedTime);
8638 m_bodyAcceleration[0] = freq0 * m_UInfinity *
cos(freq0 * elapsedTime);
8642 MFloat w = F2 * PI * m_Ma;
8643 m_bodyCenter[0] = -
a *
cos(w * m_physicalTime);
8644 m_bodyVelocity[0] =
a * w * sin(w * m_physicalTime);
8645 m_bodyAcceleration[0] =
a * w * w *
cos(w * m_physicalTime);
8650 factor = Context::getSolverProperty<MFloat>(
"freqFactor", m_solverId, AT_, &factor);
8652 freq0 = factor * F2 * PI * m_Ma;
8653 MBool& firstRun = m_static_updateBodyProperties_c455_firstRun;
8655 cerr <<
"maximum cylinder offset: " << m_Ma / freq0 << endl;
8656 cerr <<
"maximum drag coeff: " << F1B2 * PI * freq0 / m_Ma << endl;
8657 cerr << m_globalUpwindCoefficient <<
" " << m_Ma << endl;
8660 m_bodyCenter[0] = -m_Ma / freq0 *
cos(freq0 * m_physicalTime);
8661 m_bodyVelocity[0] = m_Ma * sin(freq0 * m_physicalTime);
8662 m_bodyAcceleration[0] = freq0 * m_Ma *
cos(freq0 * m_physicalTime);
8665 const MFloat t0 = m_physicalTime + timeStep();
8667 MFloat w0 = F2 * PI * f0 * m_Ma / m_referenceLength;
8668 MFloat a0 = 0.1 * m_referenceLength;
8669 m_bodyCenter[0] = -a0 *
cos(w0 * t0);
8670 m_bodyVelocity[0] = a0 * w0 * sin(w0 * t0);
8671 m_bodyAcceleration[0] = a0 * w0 * w0 *
cos(w0 * t0);
8683 m_bodyCenter[0] = F1B2 * m_Ma / deltaT *
POW2(m_physicalTime);
8684 m_bodyVelocity[0] = m_Ma *
mMin(F1, m_physicalTime / deltaT);
8685 m_bodyAcceleration[0] = m_Ma / deltaT;
8687 if(m_physicalTime / deltaT >= F1) {
8688 m_bodyCenter[0] = (F1B2 * m_Ma * deltaT) + m_Ma * (m_physicalTime - deltaT);
8689 m_bodyVelocity[0] = m_Ma;
8690 m_bodyAcceleration[0] = F0;
8698 m_bodyCenter[0] = m_Ma * m_physicalTime;
8699 m_bodyVelocity[0] = m_Ma;
8700 m_bodyAcceleration[0] = F0;
8716 const MFloat x0 = 0.002332491063;
8717 const MFloat x1 = 0.002332491064;
8724 m_bodyVelocity[0] = F0;
8725 m_bodyAcceleration[0] = F0;
8726 m_bodyCenter[0] = x0;
8728 if(m_time / deltaT >= F1) {
8729 m_bodyCenter[0] = x1;
8731 MBool& firstTime = m_static_updateBodyProperties_firstTime;
8733 cerr <<
"switch applied now (delta_x=" << x1 - x0 <<
", u/u_0=" << (x1 - x0) / (timeStep() * m_UInfinity)
8734 <<
", delta_x/h=" << (x1 - x0) / (c_cellLengthAtLevel(m_lsCutCellBaseLevel))
8735 <<
", accel=" << (x1 - x0) * m_referenceLength /
POW2(timeStep() * m_UInfinity) <<
")" << endl;
8736 m_bodyVelocity[0] = (x1 - x0) / timeStep();
8737 m_bodyAcceleration[0] = (m_bodyVelocity[0] - m_bodyVelocityDt1[0]) / timeStep();
8739 MFloat Cd = F1B4 * PI * m_referenceLength * (x1 - x0) /
POW2(timeStep() * m_UInfinity);
8740 cerr <<
"C_d: " << Cd << endl;
8751 setBodyQuaternions(body, bodyRotation);
8760template <MInt nDim,
class SysEqn>
8766 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
8767 for(
MInt i = 0; i < 3; i++) {
8768 globalMI[3 * k + i] = F0;
8769 m_bodyMomentOfInertia[3 * k + i] = F0;
8772 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
8773 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
8774 if(a_associatedBodyIds(cellId, 0) != k)
continue;
8775 if(a_isHalo(cellId))
continue;
8776 if(a_isBndryGhostCell(cellId))
continue;
8777 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
8778 MFloat dx[3] = {F0, F0, F0};
8779 MFloat normal[3] = {F0, F0, F0};
8780 MFloat fac[3] = {F0, F0, F0};
8781 for(
MInt i = 0; i < nDim; i++) {
8782 dx[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[i] - m_bodyCenter[nDim * k + i];
8783 normal[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
8785 IF_CONSTEXPR(nDim == 3) {
8786 fac[0] = normal[1] *
POW3(dx[1]) + normal[2] *
POW3(dx[2]);
8787 fac[1] = normal[0] *
POW3(dx[0]) + normal[2] *
POW3(dx[2]);
8789 fac[2] = normal[0] *
POW3(dx[0]) + normal[1] *
POW3(dx[1]);
8790 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
8792 for(
MInt i = 0; i < 3; i++) {
8793 m_bodyMomentOfInertia[3 * k + i] += area * fac[i];
8797 for(
MInt i = 0; i < 3; i++) {
8798 m_bodyMomentOfInertia[3 * k + i] *= F1B3 * m_bodyDensity[k];
8802 MPI_Allreduce(m_bodyMomentOfInertia, globalMI.
begin(), 3 * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
8803 "m_bodyMomentOfInertia",
"globalMI.begin()");
8805 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
8806 for(
MInt i = 0; i < 3; i++) {
8807 m_bodyMomentOfInertia[3 * k + i] = globalMI[3 * k + i];
8817template <MInt nDim,
class SysEqn>
8821 if(m_timeStepAdaptationStart < 0 || m_timeStepAdaptationEnd < 0)
return;
8824 m_cfl = m_cflTarget;
8826 m_cfl = m_cflInitial;
8831 m_cfl = m_cflInitial + (t - t0) * (m_cflTarget - m_cflInitial) / (t1 - t0);
8832 m_log <<
"Adapted CFL number: " << m_cfl <<
" at time step " <<
globalTimeStep <<
";" << endl;
8841template <MInt nDim,
class SysEqn>
8843 c[0] =
a[1] *
b[2] -
a[2] *
b[1];
8844 c[1] =
a[2] *
b[0] -
a[0] *
b[2];
8845 c[2] =
a[0] *
b[1] -
a[1] *
b[0];
8858template <MInt nDim,
class SysEqn>
8862 ASSERT(a_noCells() == c_noCells(),
"");
8863 ASSERT(m_fvBndryCnd->m_bndryCells->size() == m_noOuterBndryCells,
"");
8865 NEW_SUB_TIMER_STATIC(tInit,
"init", m_tCutGroup);
8866 NEW_SUB_TIMER_STATIC(tCutFaceNew,
"cutFaceNew", m_tCutGroup);
8867 NEW_SUB_TIMER_STATIC(tCutPointNew,
"cutPoint", m_tCutGroup);
8868 NEW_SUB_TIMER_STATIC(tReinit,
"reinit", m_tCutGroup);
8869 NEW_SUB_TIMER_STATIC(tMassRedist,
"massRedist", m_tCutGroup);
8870 RECORD_TIMER_START(tInit);
8873 if(m_structureStep > 0 && mode != 2) {
8874 for(map<
MInt, vector<MFloat>>::iterator it = m_nearBoundaryBackup.begin(); it != m_nearBoundaryBackup.end(); it++) {
8875 const MInt cellId = it->first;
8876 a_cellVolume(cellId) = (it->second)[0];
8877 m_cellVolumesDt1[cellId] = (it->second)[0];
8878 for(
MInt v = 0; v < m_noCVars; v++) {
8879 a_oldVariable(cellId, v) = (it->second)[1 + v];
8881 for(
MInt v = 0; v < m_noFVars; v++) {
8882 m_rhs0[
cellId][v] = (it->second)[1 + m_noCVars + v];
8887 if(m_bodyTypeMb && m_constructGField) {
8888 setupBoundaryCandidatesAnalytical();
8890 determineBndryCandidates();
8891 computeNodalLSValues();
8894 RECORD_TIMER_STOP(tInit);
8897 RECORD_TIMER_START(tCutPointNew);
8898 computeCutPointsMb_MGC();
8899 RECORD_TIMER_STOP(tCutPointNew);
8902 m_fvBndryCnd->checkCutPointsValidity();
8905 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
8906 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
8907 const MInt cndId = m_bndryCandidateIds[
cellId];
8908 ASSERT(cndId >= 0,
"ERROR: cutCell is not a bndryCandidate? ");
8909 for(
MInt p = 0;
p < m_noCellNodes;
p++) {
8910 ASSERT(m_candidateNodeSet[cndId * m_noCellNodes + p],
"ERROR: nodeValue not set for bndryCel!");
8916 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
8917 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
8918 const MInt cndId = m_bndryCandidateIds[
cellId];
8919 ASSERT(cndId >= 0,
"ERROR: cutCell is not a bndryCandidate? ");
8920 ASSERT(a_hasProperty(cellId, SolverCell::IsMovingBnd),
"");
8923 if(m_noLevelSetsUsedForMb > 1 && m_complexBoundary && !a_isGapCell(cellId)) {
8925 endSet = m_noLevelSetsUsedForMb;
8929 if(a_hasProperty(cellId, SolverCell::IsInactive)) {
8930 cerr <<
"Unusual, mb-bndryCell was inactive: react " << c_globalId(cellId) << endl;
8932 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
8934 if(c_noChildren(cellId) == 0 && (a_hasProperty(cellId, SolverCell::IsSplitChild) || c_isLeafCell(cellId))) {
8935 if(!a_hasProperty(cellId, SolverCell::IsNotGradient)) {
8936 a_hasProperty(cellId, SolverCell::IsFlux) =
true;
8937 a_hasProperty(cellId, SolverCell::IsActive) =
true;
8939 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
8941 a_isBndryGhostCell(cellId) =
false;
8943 for(
MInt p = 0;
p < m_noCellNodes;
p++) {
8944 m_pointIsInside[bndryId][IDX_LSSETMB(p, 0)] =
false;
8946 for(
MInt set = startSet; set < endSet; set++) {
8947 m_pointIsInside[bndryId][IDX_LSSETMB(p, set)] = (m_candidateNodeValues[IDX_LSSETNODES(cndId, p, set)] < F0);
8948 m_pointIsInside[bndryId][IDX_LSSETMB(p, 0)] =
8949 (m_pointIsInside[bndryId][IDX_LSSETMB(p, 0)] || m_pointIsInside[bndryId][IDX_LSSETMB(p, set)]);
8954 m_gapOpened =
false;
8955 if(m_levelSet && m_closeGaps && m_gapInitMethod == 0) setGapOpened();
8958 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
8959 restoreSurfaces(m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId);
8963 RECORD_TIMER_START(tCutFaceNew);
8964 createCutFaceMb_MGC();
8965 RECORD_TIMER_STOP(tCutFaceNew);
8967#if defined _MB_DEBUG_ || !defined NDEBUG
8968 MInt noSplitChilds = m_totalnosplitchilds;
8969 MPI_Allreduce(MPI_IN_PLACE, &noSplitChilds, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noSplitChilds");
8971 if(noSplitChilds > 0 && domainId() == 0) {
8972 cerr <<
"Global-Number of Split-Childs are " << noSplitChilds << endl;
8977 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
8979 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8980 m_cutFaceArea[a_bndryId(cellId)][dir] = F0;
8982 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
8983 const MInt splitChildId = m_splitChilds[sc][ssc];
8984 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8985 m_cutFaceArea[a_bndryId(cellId)][dir] += m_cutFaceArea[a_bndryId(splitChildId)][dir];
8987 a_hasProperty(splitChildId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::WasInactive);
8993 for(
MInt bndryId = 0; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
8994 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
8995 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
8996 for(
MInt dir = 0; dir < m_noDirs; dir++) {
8997 if(a_hasNeighbor(cellId, dir) == 0)
continue;
8998 const MInt nghbrId = c_neighborId(cellId, dir);
8999 if(a_bndryId(nghbrId) > -1) {
9000 const MFloat a0 = m_cutFaceArea[a_bndryId(cellId)][dir];
9001 const MFloat a1 = m_cutFaceArea[a_bndryId(nghbrId)][
m_revDir[dir]];
9002 m_cutFaceArea[a_bndryId(cellId)][dir] =
mMax(a0, a1);
9003 m_cutFaceArea[a_bndryId(nghbrId)][
m_revDir[dir]] =
mMax(a0, a1);
9009 ASSERT(!m_fvBndryCnd->m_cellCoordinatesCorrected,
"");
9010 for(
MInt bndryId = 0; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
9011 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9012 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
9013 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance = F0;
9014 for(
MInt i = 0; i < nDim; i++) {
9015 m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVectorCentroid[i] =
9016 m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
9017 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance +=
9018 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i]
9019 * (a_coordinate(cellId, i) + m_bndryCells->a[bndryId].m_coordinates[i]
9020 - m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[i]);
9022 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance =
9023 mMax(F0, m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance);
9027 constexpr MFloat dirStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
9028 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
9031 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
9033 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9034 levelSets.fill(std::numeric_limits<MFloat>::max());
9035 std::array<MFloat, nDim> coordsBak{};
9036 if(m_constructGField) {
9037 std::copy_n(&a_coordinate(cellId, 0), nDim, coordsBak.data());
9038 std::transform(&a_coordinate(cellId, 0), &a_coordinate(cellId, 0) + nDim,
9039 &m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[0], &a_coordinate(cellId, 0),
9040 std::plus<MFloat>());
9042 const MInt startSet = 0;
9043 const MInt endSet = (m_complexBoundary && m_noLevelSetsUsedForMb > 1) ? m_noLevelSetsUsedForMb : 1;
9044 for(
MInt set = startSet; set < endSet; set++) {
9045 if(a_associatedBodyIds(cellId, set) < 0)
continue;
9046 if(m_constructGField && (m_bodyTypeMb == 1 || m_bodyTypeMb == 3)) {
9047 levelSets(set) = getDistance(cellId, a_associatedBodyIds(cellId, set));
9049 MFloat coord[3] = {F0, F0, F0};
9050 for(
MInt i = 0; i < nDim; i++) {
9051 coord[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[i] / c_cellLengthAtCell(cellId);
9053 MInt cndId = (a_hasProperty(cellId, SolverCell::IsSplitChild))
9054 ? m_bndryCandidateIds[getAssociatedInternalCell(cellId)]
9055 : m_bndryCandidateIds[
cellId];
9056 if(cndId < 0)
mTerm(1, AT_,
"candidate not found");
9057 for(
MInt node = 0; node < m_noCellNodes; node++) {
9058 if(!m_candidateNodeSet[cndId * m_noCellNodes + node]) {
9059 mTerm(1, AT_,
"candidate node not set");
9063 for(
MInt node = 0; node < m_noCellNodes; node++) {
9064 IF_CONSTEXPR(nDim == 2) {
9065 phi += (F1B2 + dirStencil[node][0] * coord[0]) * (F1B2 + dirStencil[node][1] * coord[1])
9066 * m_candidateNodeValues[IDX_LSSETNODES(cndId, node, set)];
9068 else IF_CONSTEXPR(nDim == 3) {
9069 phi += (F1B2 + dirStencil[node][0] * coord[0]) * (F1B2 + dirStencil[node][1] * coord[1])
9070 * (F1B2 + dirStencil[node][2] * coord[2])
9071 * m_candidateNodeValues[IDX_LSSETNODES(cndId, node, set)];
9074 levelSets(set) = phi;
9076 levelSets(set) =
mMax(F0, levelSets(set));
9079 MFloat phiSum = m_bndryCells->a[bndryId].m_gapDistance = std::numeric_limits<MFloat>::max();
9080 for(
MInt p = 1;
p < m_noLevelSetsUsedForMb - 1;
p++) {
9081 for(
MInt q = p + 1; q < m_noLevelSetsUsedForMb; q++) {
9082 phiSum =
mMin(phiSum, levelSets(p) + levelSets(q));
9085 m_bndryCells->a[bndryId].m_gapDistance = phiSum;
9088 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
9090 for(
MInt s = m_startSet; s < m_noSets; s++) {
9091 if(a_associatedBodyIds(cellId, s) == m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0]) {
9096 if(set < 0)
mTerm(1, AT_,
"set not found.");
9098 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance = levelSets(set);
9101 getNormal(cellId, set, normal);
9103 if(bndryId > -1 && srfc > -1) {
9104 const MFloat vfrac =
mMax(m_volumeThreshold, m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume)
9105 / grid().gridCellVolume(a_level(cellId));
9108 for(
MInt i = 0; i < nDim; i++) {
9109 normal[i] = fac * normal[i] + (F1 - fac) * m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
9110 cnt +=
POW2(normal[i]);
9113 for(
MInt i = 0; i < nDim; i++) {
9116 for(
MInt i = 0; i < nDim; i++) {
9117 m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVectorCentroid[i] = normal[i];
9121 if(m_constructGField) {
9122 std::copy_n(coordsBak.data(), nDim, &a_coordinate(cellId, 0));
9128 if((mode > 0) && m_restart) {
9129 RECORD_TIMER_STOP(m_tCutGroup);
9130 RECORD_TIMER_STOP(m_tCutGroupTotal);
9131 const MFloat time0 = MPI_Wtime();
9132 if(m_geometryChange ==
nullptr) {
9133 loadBodyRestartFile(1);
9135 setOldGeomBndryCellVolume();
9137 const MFloat time1 = MPI_Wtime();
9138 if(domainId() == 0)
m_log <<
"loadBodyRestartFile time " << time1 - time0 << endl;
9139 RECORD_TIMER_START(m_tCutGroupTotal);
9140 RECORD_TIMER_START(m_tCutGroup);
9143 RECORD_TIMER_START(tReinit);
9148 correctRefinedBndryCell();
9153 if(m_closeGaps && m_gapInitMethod == 0) {
9155 interpolateGapBodyVelocity();
9158 deleteNeighbourLinks();
9159 computeVolumeFraction();
9167 if(m_levelSet && m_closeGaps && m_gapInitMethod > 0) {
9171 m_fvBndryCnd->createSortedBndryCellList();
9175 initCutOffBoundaryCondition();
9177 if(m_fvBndryCnd->m_createBoundaryAtCutoff && m_alwaysResetCutOff) {
9179 m_fvBndryCnd->createBoundaryAtCutoff();
9180 m_fvBndryCnd->initBndryCommunications();
9183 m_fvBndryCnd->setBCTypes(m_movingBndryCndId);
9184 determineNearBndryCells();
9187 IF_CONSTEXPR(nDim == 3) {
9188 const MFloat deltaDomain =
mMin(F1B2 * (m_bbox[nDim + 1] - m_bbox[1]), F1B2 * (m_bbox[nDim + 2] - m_bbox[2]));
9190 ? Context::getSolverProperty<MFloat>(
"deltaSpongePart", m_solverId, AT_)
9192 const MFloat deltaSponge =
mMax(F0, deltaDomain - deltaSpongePart);
9193 if(deltaSpongePart > F0 && deltaSponge > F0) {
9195 if(a_isBndryGhostCell(cellId))
continue;
9196 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
9200 mMax(fabs(a_coordinate(cellId, 1) - m_bodyCenter[1]), fabs(a_coordinate(cellId, 2) - m_bodyCenter[2]));
9201 for(
MUint i = 0; i < m_periodicGhostBodies[0].size(); i++) {
9202 MInt l = m_periodicGhostBodies[0][i];
9203 dist =
mMin(
dist,
mMax(fabs(a_coordinate(cellId, 1) - m_bodyCenter[nDim * l + 1]),
9204 fabs(a_coordinate(cellId, 2) - m_bodyCenter[nDim * l + 2])));
9206 MFloat constant = m_sigmaSponge *
mMin(F1,
mMax(F0, (
dist - deltaSponge) / (deltaDomain - deltaSponge)));
9207 if(a_hasProperty(cellId, SolverCell::IsInSpongeLayer)) {
9208 a_spongeFactor(cellId) =
mMax(a_spongeFactor(cellId), constant);
9209 }
else if(constant > 1e-12) {
9210 m_cellsInsideSpongeLayer[m_noCellsInsideSpongeLayer] =
cellId;
9211 m_noCellsInsideSpongeLayer++;
9212 a_hasProperty(cellId, SolverCell::IsInSpongeLayer) =
true;
9213 a_spongeFactor(cellId) = constant;
9219 if(m_createSpongeBoundary) m_fvBndryCnd->createSpongeAtSpongeBndryCnds();
9222 checkBoundaryCells();
9224 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
9225 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9226 const MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(cellId);
9227 const MFloat deltaMax = (sqrt((
MFloat)nDim) + 0.1) * cellHalfLength;
9228 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
9229 if(m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0] < 0) {
9230 cerr <<
": " << domainId() <<
" " << srfc <<
" " << m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0] <<
" "
9231 << a_associatedBodyIds(cellId, srfc) <<
" " <<
cellId <<
" " << c_globalId(cellId) << endl;
9232 mTerm(1, AT_,
"body id mismatch.");
9233 }
else if(m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0]
9234 != a_associatedBodyIds(cellId, m_bodyToSetTable[m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0]])) {
9235 cerr <<
": " << domainId() <<
" " << srfc <<
" " << m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0] <<
" "
9236 <<
" " <<
cellId <<
" " << c_globalId(cellId) << endl;
9237 mTerm(1, AT_,
"body id mismatch2.");
9239 if(m_bodyTypeMb == 1) {
9240 MInt k = m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0];
9242 for(
MInt i = 0; i < nDim; i++) {
9243 dist +=
POW2(a_coordinate(cellId, i) - m_bodyCenter[nDim * k + i]);
9245 dist = sqrt(
dist) - m_bodyRadius[k];
9246 if(
dist > deltaMax) {
9247 cerr <<
"distance check: " << domainId() <<
" " << srfc <<
" "
9248 << m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0] <<
" "
9249 <<
" " <<
cellId <<
" " << c_globalId(cellId) <<
" / " <<
dist <<
" " << deltaMax <<
" / "
9250 << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" " << a_coordinate(cellId, 2) <<
" / "
9251 << m_bodyCenter[nDim * k + 0] <<
" " << m_bodyCenter[nDim * k + 1] <<
" " << m_bodyCenter[nDim * k + 2]
9253 cerr <<
"body too far away, body id might be wrong." << endl;
9262 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
9263 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9264 for(
MInt dir = 0; dir < m_noDirs; dir++) {
9265 MInt srfcId = m_cellSurfaceMapping[
cellId][dir];
9267 MInt nghbrId0 = a_surfaceNghbrCellId(srfcId, 0);
9268 MInt nghbrId1 = a_surfaceNghbrCellId(srfcId, 1);
9269 ASSERT(nghbrId0 > -1 && nghbrId1 > -1,
"");
9270 a_surfaceFactor(srfcId, 0) = F0;
9272 for(
MInt i = 0; i < nDim; i++) {
9273 a_surfaceFactor(srfcId, 0) +=
POW2(a_surfaceCoordinate(srfcId, i) - a_coordinate(nghbrId0, i));
9274 tmp +=
POW2(a_surfaceCoordinate(srfcId, i) - a_coordinate(nghbrId1, i));
9276 a_surfaceFactor(srfcId, 0) = sqrt(a_surfaceFactor(srfcId, 0));
9278 a_surfaceFactor(srfcId, 0) = tmp / (a_surfaceFactor(srfcId, 0) + tmp);
9279 a_surfaceFactor(srfcId, 1) = F1 - a_surfaceFactor(srfcId, 0);
9280 for(
MInt i = 0; i < nDim; i++) {
9281 a_surfaceDeltaX(srfcId, i) =
9282 a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 0), i);
9283 a_surfaceDeltaX(srfcId, nDim + i) =
9284 a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 1), i);
9289 RECORD_TIMER_STOP(tReinit);
9292 RECORD_TIMER_START(tMassRedist);
9294 m_temporarilyLinkedCells.clear();
9295 for(
MInt i = 0; i < noNeighborDomains(); i++) {
9296 m_linkedWindowCells[i].clear();
9297 m_linkedHaloCells[i].clear();
9300 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
9304 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
9306 a_hasProperty(cellId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::IsInactive);
9310 for(
MInt bndryId = 0; bndryId < noBCells; bndryId++) {
9311 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9312 a_cellVolume(cellId) =
mMax(m_volumeThreshold, m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume);
9313 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
9314 m_cellVolumesDt1[
cellId] = a_cellVolume(cellId);
9315 if(m_dualTimeStepping) m_cellVolumesDt2[
cellId] = a_cellVolume(cellId);
9318 }
else if(mode == 2) {
9319 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
9321 a_hasProperty(cellId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::IsInactive);
9323 for(
MInt bndryId = 0; bndryId < noBCells; bndryId++) {
9324 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9325 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
9329#if defined _MB_DEBUG_ || !defined NDEBUG
9330 checkHaloBndryCells(
false);
9337 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
9338 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9339 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
9340 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
9344 m_cellVolumesDt1[
cellId] = F0;
9345 if(m_dualTimeStepping) m_cellVolumesDt2[
cellId] = F0;
9346 m_sweptVolumeDt1[bndryId] = F0;
9347 for(
MInt v = 0; v < m_noFVars; v++) {
9348 a_rightHandSide(cellId, v) = F0;
9353 if(m_oldBndryCells.count(cellId))
continue;
9356 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
9358 if(m_cellVolumesDt1[cellId] < grid().gridCellVolume(a_level(cellId))) {
9365 <<
"*************** Strange behavior " << domainId() <<
" " <<
globalTimeStep <<
" " <<
cellId <<
" "
9366 << c_globalId(cellId) <<
" /wi " << a_hasProperty(cellId, SolverCell::WasInactive) <<
" /ii "
9367 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" /l " << a_level(cellId) <<
" /v "
9368 << m_cellVolumesDt1[
cellId] / grid().gridCellVolume(a_level(cellId)) <<
" "
9369 << (grid().gridCellVolume(a_level(cellId)) - m_cellVolumesDt1[
cellId])
9370 / grid().gridCellVolume(a_level(cellId))
9371 <<
" " << m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume / grid().gridCellVolume(a_level(cellId))
9372 <<
" /h " << a_hasProperty(cellId, Cell::IsHalo) <<
" /sl "
9373 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" /sd "
9374 << a_hasProperty(cellId, SolverCell::IsSplitChild) <<
" " << m_sweptVolumeDt1[bndryId] <<
" "
9375 << a_bndryId(cellId) <<
" " <<
globalTimeStep <<
" " << a_levelSetValuesMb(cellId, 0) <<
" "
9376 << m_oldBndryCells.size() <<
" " << m_oldBndryCells.count(cellId) <<
" "
9377 << m_nearBoundaryBackup.count(cellId) << endl
9379 if(m_cellVolumesDt1[cellId] < 0.9 * grid().gridCellVolume(a_level(cellId))) {
9380 mTerm(1, AT_,
"strange behavior.");
9383 m_sweptVolumeDt1[bndryId] = F0;
9389#if defined _MB_DEBUG_ || !defined NDEBUG
9390 if(noNeighborDomains() > 0) {
9392 gid.fill((
MLong)-2);
9393 for(
MInt i = 0; i < noNeighborDomains(); i++) {
9394 for(
MInt j = 0; j < (signed)m_linkedHaloCells[i].size(); j++) {
9396 gid(cellId) = c_globalId(cellId);
9402 &gid(0), &recvBuffer[0]);
9405 for(
MInt i = 0; i < noNeighborDomains(); i++) {
9407 for(
MInt j = 0; j < noWindowCells(i); j++) {
9409 if(recvBuffer(recvSize) != -2 && c_globalId(cellId) != recvBuffer(recvSize))
9410 cerr << c_globalId(cellId) <<
" " << recvBuffer(recvSize) << endl;
9411 if(recvBuffer(recvSize) != -2 && c_globalId(cellId) != recvBuffer(recvSize))
9412 mTerm(1, AT_,
"linked halo cell connection failed.");
9413 if(recvBuffer(recvSize) != -2) {
9414 ASSERT(recvBuffer(recvSize) > -1,
"");
9416 for(
MInt p = 0;
p < (signed)m_linkedWindowCells[i].size();
p++) {
9417 if(c_globalId(m_linkedWindowCells[i][p]) == recvBuffer(recvSize)) commCnt++;
9422 if(commCnt != m_linkedWindowCells[i].size()) {
9423 cerr << domainId() <<
": ERR LINK " << neighborDomain(i) <<
" " << commCnt <<
" "
9424 << m_linkedWindowCells[i].size() << endl;
9425 for(
MInt j = 0; j < (signed)m_linkedWindowCells[i].size(); j++) {
9426 cerr << domainId() <<
" LW " << j <<
" " << m_linkedWindowCells[i][j] <<
" "
9427 << c_globalId(m_linkedWindowCells[i][j]) << endl;
9429 for(
MInt j = 0; j < (signed)m_linkedHaloCells[i].size(); j++) {
9430 cerr << domainId() <<
" LH " << j <<
" " << m_linkedHaloCells[i][j] <<
" "
9431 << c_globalId(m_linkedHaloCells[i][j]) << endl;
9441 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
9442 m_sweptVolumeDt1[bndryId] = F0;
9446 for(map<MInt, MFloat>::iterator it = m_oldBndryCells.begin(); it != m_oldBndryCells.end(); it++) {
9447 if(a_bndryId(it->first) > -1) {
9448 m_sweptVolumeDt1[a_bndryId(it->first)] = it->second;
9453 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
9454 m_sweptVolume[bndryId] = F0;
9458 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
9461 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
9462 const MInt splitChildId = m_splitChilds[sc][ssc];
9463 MFloat vol = m_fvBndryCnd->m_bndryCells->a[a_bndryId(splitChildId)].m_volume;
9465 a_cellVolume(splitChildId) = vol * a_cellVolume(cellId);
9466 m_cellVolumesDt1[splitChildId] = vol * m_cellVolumesDt1[
cellId];
9467 m_sweptVolume[a_bndryId(splitChildId)] = vol * m_sweptVolume[a_bndryId(cellId)];
9468 m_sweptVolumeDt1[a_bndryId(splitChildId)] = vol * m_sweptVolumeDt1[a_bndryId(cellId)];
9469 for(
MInt v = 0; v < m_noFVars; v++) {
9470 m_rhs0[splitChildId][v] = vol * m_rhs0[
cellId][v];
9473 cvol =
mMax(1e-15, cvol);
9474 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
9475 const MInt splitChildId = m_splitChilds[sc][ssc];
9476 a_cellVolume(splitChildId) /= cvol;
9477 m_cellVolumesDt1[splitChildId] /= cvol;
9478 m_sweptVolume[a_bndryId(splitChildId)] /= cvol;
9479 m_sweptVolumeDt1[a_bndryId(splitChildId)] /= cvol;
9480 for(
MInt v = 0; v < m_noFVars; v++) {
9481 m_rhs0[splitChildId][v] /= cvol;
9490 if(m_levelSet && m_closeGaps && m_gapInitMethod > 0) {
9491 updateGapBoundaryCells();
9495 correctRefinedBndryCellVolume();
9496 correctCoarsenedBndryCellVolume();
9502 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
9503 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9504 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
9506 const MFloat vol0 = a_cellVolume(cellId);
9507 const MFloat deltaVol = updateCellVolumeGCL(bndryId);
9510 if((mode == 1) || (m_gapInitMethod == 0 && m_gapOpened)) {
9512 a_cellVolume(cellId) =
mMax(m_volumeThreshold, m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume);
9513 m_cellVolumesDt1[
cellId] = a_cellVolume(cellId) - deltaVol;
9514 m_sweptVolumeDt1[bndryId] = m_sweptVolume[bndryId];
9518 if(m_geometryChange !=
nullptr) {
9519 auto it0 = m_oldGeomBndryCells.find(cellId);
9520 if(it0 != m_oldGeomBndryCells.end()) {
9521 m_sweptVolumeDt1[bndryId] = 0;
9522 m_sweptVolume[bndryId] = 0;
9523 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
9524 m_cellVolumesDt1[
cellId] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
9528 }
else if(mode == 2) {
9541 m_sweptVolumeDt1[bndryId] = m_sweptVolume[bndryId];
9542 a_cellVolume(cellId) = vol0;
9543 m_cellVolumesDt1[
cellId] = vol0 - m_sweptVolume[bndryId];
9544 }
else if(a_cellVolume(cellId) < m_volumeThreshold && !a_isPeriodic(cellId) && !a_isHalo(cellId)) {
9571 if(a_cellVolume(cellId) < F0 && !a_isPeriodic(cellId) && !a_isHalo(cellId)) {
9576 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
9577 m_volumeFraction[bndryId] = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
9580 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
9581 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9582 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
9583 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
9584 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
9585 m_volumeFraction[bndryId] = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
9589#if defined _MB_DEBUG_ || !defined NDEBUG
9592 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
9593 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9594 if(a_isHalo(cellId))
continue;
9595 if(a_hasProperty(cellId, SolverCell::IsSplitCell)) {
9596 ASSERT(m_bndryCells->a[bndryId].m_noSrfcs == 0,
"");
9599 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
9600 MInt body = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0];
9601 MInt bodyId = m_internalBodyId[body];
9603 MFloat dt = timeStep(
true);
9604 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
9605 for(
MInt i = 0; i < nDim; i++) {
9606 MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
9607 dV -= dt * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] * nml * area;
9608 testvol(bodyId, i) += nml * area;
9610 testvol(bodyId, nDim) += dV;
9612 testvol(m_noEmbeddedBodies, 0) += m_sweptVolume[bndryId];
9613 testvol(m_noEmbeddedBodies, 1) += m_sweptVolumeDt1[bndryId];
9615 MPI_Allreduce(MPI_IN_PLACE, &testvol(0), testvol.size(), MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
9617 if(domainId() == 0) {
9618 for(
MInt b = 0;
b <
mMin(4, m_noEmbeddedBodies);
b++) {
9619 cerr <<
b <<
" " << testvol(
b, 0) <<
" " << testvol(
b, 1) <<
" " << testvol(
b, 2) <<
" " << testvol(
b, 3) << endl;
9621 cerr <<
"VOL CHECK -- " << testvol(m_noEmbeddedBodies, 0) <<
" " << testvol(m_noEmbeddedBodies, 1) << endl << endl;
9626 for(map<MInt, MFloat>::iterator it = m_oldBndryCells.begin(); it != m_oldBndryCells.end(); it++) {
9631 if(a_bndryId(cellId) > -1)
continue;
9634 MBool conserveMass1 =
true;
9635 MBool conserveMass2 =
true;
9636 if(m_levelSet && m_closeGaps && m_gapInitMethod == 0) {
9637 MBool isGapCell = (a_hasProperty(cellId, SolverCell::IsGapCell));
9638 MBool wasGapCell = (a_hasProperty(cellId, SolverCell::WasGapCell));
9640 if(isGapCell || wasGapCell) conserveMass1 =
false;
9641 if(wasGapCell) conserveMass2 =
false;
9649 }
else if(m_levelSet && m_closeGaps && m_gapInitMethod > 0 && (a_isGapCell(cellId) || a_wasGapCell(cellId))
9650 && !a_isHalo(cellId) && !a_isPeriodic(cellId)) {
9653 const MInt regionId = m_gapCells[m_gapCellId[
cellId]].region;
9654 if(regionId <= m_noGapRegions) {
9678 if(m_gapState[regionId] == 2) {
9680 if(a_wasGapCell(cellId)) {
9682 cerr <<
"Trying massRedistribution-2 of Cell " << c_globalId(cellId) <<
" "
9683 << m_gapCells[m_gapCellId[
cellId]].status << endl;
9690 for(
MInt v = 0; v < m_noFVars; v++) {
9691 a_rightHandSide(cellId, v) = F0;
9694 if(a_hasProperty(cellId, SolverCell::IsInactive) && a_bndryId(cellId) < 0
9695 && !a_hasProperty(cellId, SolverCell::WasInactive)) {
9696 if(!a_isPeriodic(cellId) && !a_isHalo(cellId) && conserveMass1) {
9697 if(m_levelSet && m_closeGaps && m_gapInitMethod > 0 && (a_isGapCell(cellId) || a_wasGapCell(cellId))) {
9698 MInt regionId = m_gapCells[m_gapCellId[
cellId]].region;
9699 if(regionId < m_noGapRegions && (m_gapState[regionId] == -2 || m_gapState[regionId] == 2)) {
9700 cerr <<
"Trying massRedistribution of GapCell" << c_globalId(cellId)
9701 <<
" Type: " << m_gapCells[m_gapCellId[
cellId]].status
9702 <<
" This should not happen during Opening or Closing!" << endl;
9706 m_massRedistributionIds.push_back(cellId);
9707 m_massRedistributionVariables.resize(m_massRedistributionIds.size() * m_noCVars);
9708 m_massRedistributionRhs.resize(m_massRedistributionIds.size() * m_noFVars);
9709 m_massRedistributionVolume.resize(m_massRedistributionIds.size());
9710 m_massRedistributionSweptVol.resize(m_massRedistributionIds.size());
9711 for(
MInt v = 0; v < m_noCVars; v++) {
9712 m_massRedistributionVariables[(m_massRedistributionIds.size() - 1) * m_noCVars + v] =
9713 a_oldVariable(cellId, v);
9715 for(
MInt v = 0; v < m_noFVars; v++) {
9716 m_massRedistributionRhs[(m_massRedistributionIds.size() - 1) * m_noFVars + v] = m_rhs0[cellId][v];
9719 m_massRedistributionVolume[m_massRedistributionIds.size() - 1] = m_cellVolumesDt1[
cellId];
9720 m_massRedistributionSweptVol[m_massRedistributionIds.size() - 1] = it->second;
9722 removeSurfaces(cellId);
9723 a_cellVolume(cellId) = grid().gridCellVolume(a_level(cellId));
9724 m_cellVolumesDt1[
cellId] = grid().gridCellVolume(a_level(cellId));
9725 if(m_dualTimeStepping) m_cellVolumesDt2[
cellId] = grid().gridCellVolume(a_level(cellId));
9726 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
9729 else if(a_hasProperty(cellId, SolverCell::WasInactive) && a_bndryId(cellId) > -1) {
9730 m_cellVolumesDt1[
cellId] = F0;
9731 if(m_dualTimeStepping)
9732 m_cellVolumesDt2[
cellId] = F0;
9733 for(
MInt v = 0; v < m_noFVars; v++) {
9736 cerr <<
"case should not appear " << domainId() <<
" " <<
globalTimeStep <<
" " <<
cellId << endl;
9739 if(!a_hasProperty(cellId, SolverCell::IsInactive) && a_bndryId(cellId) < 0) {
9740 if(!a_isPeriodic(cellId) && !a_isHalo(cellId)) {
9742 const MFloat deltaVol = m_cellVolumesDt1[
cellId] - grid().gridCellVolume(a_level(cellId));
9743 if(fabs(deltaVol) > 1e-16 && conserveMass2) {
9744 m_massRedistributionIds.push_back(cellId);
9745 m_massRedistributionVariables.resize(m_massRedistributionIds.size() * m_noCVars);
9746 m_massRedistributionRhs.resize(m_massRedistributionIds.size() * m_noFVars);
9747 m_massRedistributionVolume.resize(m_massRedistributionIds.size());
9748 m_massRedistributionSweptVol.resize(m_massRedistributionIds.size());
9749 for(
MInt v = 0; v < m_noCVars; v++) {
9750 m_massRedistributionVariables[(m_massRedistributionIds.size() - 1) * m_noCVars + v] =
9751 a_oldVariable(cellId, v);
9753 for(
MInt v = 0; v < m_noFVars; v++) {
9754 m_massRedistributionRhs[(m_massRedistributionIds.size() - 1) * m_noFVars + v] =
9755 -it->second * a_oldVariable(cellId, v) / timeStep();
9756 m_rhs0[
cellId][v] += it->second * a_oldVariable(cellId, v) / timeStep();
9758 m_massRedistributionVolume[m_massRedistributionIds.size() - 1] = deltaVol;
9759 m_massRedistributionSweptVol[m_massRedistributionIds.size() - 1] = it->second;
9763 a_cellVolume(cellId) = grid().gridCellVolume(a_level(cellId));
9764 m_cellVolumesDt1[
cellId] = grid().gridCellVolume(a_level(cellId));
9765 if(m_dualTimeStepping) m_cellVolumesDt2[
cellId] = grid().gridCellVolume(a_level(cellId));
9766 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
9773 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
9779 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
9780 const MInt splitChildId = m_splitChilds[sc][ssc];
9782 vol += a_cellVolume(splitChildId);
9783 vol1 += m_cellVolumesDt1[splitChildId];
9784 svol += m_sweptVolume[a_bndryId(splitChildId)];
9785 svol1 += m_sweptVolumeDt1[a_bndryId(splitChildId)];
9787 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
9791 a_cellVolume(cellId) = vol;
9792 m_cellVolumesDt1[
cellId] = vol1;
9793 m_sweptVolume[a_bndryId(cellId)] = svol;
9794 m_sweptVolumeDt1[a_bndryId(cellId)] = svol1;
9798#if defined _MB_DEBUG_ || !defined NDEBUG
9800 checkHaloBndryCells(
true);
9803 if(m_levelSet && m_closeGaps && m_gapInitMethod > 0) {
9809 if(a_cellVolume(cellId) < 0) {
9810 cerr <<
"Negative cell-Volume " << c_globalId(cellId) << endl;
9812 if(m_cellVolumesDt1[cellId] < 0 && mode != 1) {
9814 if(m_closeGaps && m_gapInitMethod > 0 && m_gapCellId[cellId] > 1) {
9815 status = m_gapCells[m_gapCellId[
cellId]].status;
9817 cerr <<
"Negative cell-Volume-Dt1 " << c_globalId(cellId) <<
" " << m_cellVolumesDt1[
cellId] <<
" " << status
9824 MInt noSplitFaces = 0;
9825 MInt noSplitFacesHalo = 0;
9826 MInt noSplitCells = 0;
9827 MInt noSplitCellsHalo = 0;
9828 for(
MInt bndryId = 0; bndryId < noBCells; bndryId++) {
9829 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
9830 if(a_hasProperty(cellId, SolverCell::HasSplitFace)) noSplitFaces++;
9831 if(a_hasProperty(cellId, SolverCell::HasSplitFace) && a_isHalo(cellId)) noSplitFacesHalo++;
9833 if(a_hasProperty(cellId, SolverCell::HasSplitFace) && a_isHalo(cellId))
9834 cerr << domainId() <<
": halo split face!" << endl;
9835 if(a_hasProperty(cellId, SolverCell::HasSplitFace) && a_isWindow(cellId))
9836 cerr << domainId() <<
": window split face!" << endl;
9838 const MInt noSrfcs = m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs;
9839 for(
MInt srfc = 0; srfc < noSrfcs; srfc++) {
9840 ASSERT(m_fvBndryCnd->m_bndryCell[bndryId].m_srfcs[srfc]->m_bndryCndId > -1,
"");
9843 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
9856 if(a_isHalo(cellId)) noSplitCellsHalo++;
9858 if(a_isHalo(cellId)) cerr << domainId() <<
": halo split cell!" << endl;
9859 if(a_isWindow(cellId)) cerr << domainId() <<
": window split cell!" << endl;
9861 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
9862 if(a_hasProperty(m_splitChilds[sc][ssc], SolverCell::IsTempLinked))
9863 cerr << domainId() <<
": linked split child " << m_splitChilds[sc][ssc] <<
" (" <<
cellId <<
")" << endl;
9865 for(
MUint it = 0; it < m_temporarilyLinkedCells.size(); it++) {
9866 if(cellId == get<1>(m_temporarilyLinkedCells[it])) cerr << domainId() <<
": master split cell " <<
cellId << endl;
9875 if(m_splitCells.size() > 0 || noSplitFaces > 0) {
9876 cerr << domainId() <<
": " << noSplitCells <<
"(" << noSplitCellsHalo <<
")"
9877 <<
" split cells and " << noSplitFaces <<
"(" << noSplitFacesHalo <<
")"
9886 if(mode > 0 && m_massRedistributionIds.size() > 0) {
9887 mTerm(1, AT_,
"Not supposed to happen.");
9890 if(mode == 1 && m_initialCondition == 16 && !m_restart) {
9891 initBodyVelocities();
9905 ? Context::getSolverProperty<MFloat>(
"particleTemperatureRatio", m_solverId, AT_)
9918 const MFloat initPPVelocitiesFactor =
9920 ? Context::getSolverProperty<MFloat>(
"initPPVelocitiesFactor", m_solverId, AT_)
9922 if(mode == 1 && m_noPointParticles > 0) {
9923 setParticleFluidVelocities();
9924 for(
MUint p = 0;
p < m_particleCellLink.size();
p++) {
9925 for(
MInt i = 0; i < nDim; i++) {
9926 m_particleVelocity[nDim *
p + i] =
9927 initPPVelocitiesFactor * m_particleVelocityFluid[nDim *
p + i] + m_particleTerminalVelocity[i];
9928 m_particleVelocityDt1[nDim *
p + i] = m_particleVelocity[nDim *
p + i];
9930 m_particleTemperature[
p] = ratio * m_particleFluidTemperature[
p];
9931 m_particleTemperatureDt1[
p] = m_particleTemperature[
p];
9936 MInt noLinked = (signed)m_temporarilyLinkedCells.size();
9937 MPI_Allreduce(MPI_IN_PLACE, &noLinked, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noLinked");
9941 RECORD_TIMER_STOP(tMassRedist);
9949template <MInt nDim,
class SysEqn>
9953 constexpr MFloat eps0 = 1e-12;
9954 constexpr MFloat eps1 = 1e-11;
9957 cellCheck.
fill(std::numeric_limits<MFloat>::max());
9959 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
9960 cellCheck(cellId, 0) = (
MFloat)a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel);
9961 cellCheck(cellId, 1) = a_bndryId(cellId) > -1 ? (
MFloat)m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_noSrfcs
9962 : std::numeric_limits<MFloat>::max();
9963 cellCheck(cellId, 2) = a_levelSetValuesMb(cellId, 0);
9964 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
9965 cellCheck(cellId, 3) = (
MFloat)a_hasProperty(cellId, SolverCell::IsInactive);
9966 cellCheck(cellId, 4) = (
MFloat)a_hasProperty(cellId, SolverCell::WasInactive);
9967 cellCheck(cellId, 5) = (
MFloat)a_hasProperty(cellId, SolverCell::IsSplitCell);
9968 cellCheck(cellId, 6) = (
MFloat)a_hasProperty(cellId, SolverCell::IsSplitChild);
9969 cellCheck(cellId, 7) = (
MFloat)a_hasProperty(cellId, SolverCell::IsGapCell);
9970 cellCheck(cellId, 8) = (
MFloat)a_hasProperty(cellId, SolverCell::WasGapCell);
9971 cellCheck(cellId, 9) = a_cellVolume(cellId);
9972 cellCheck(cellId, 10) = m_cellVolumesDt1[cellId];
9973 cellCheck(cellId, 11) =
9974 a_bndryId(cellId) > -1 ? m_sweptVolume[a_bndryId(cellId)] : std::numeric_limits<MFloat>::max();
9975 cellCheck(cellId, 12) =
9976 a_bndryId(cellId) > -1 ? m_sweptVolumeDt1[a_bndryId(cellId)] : std::numeric_limits<MFloat>::max();
9977 cellCheck(cellId, 13) = F1;
9979 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
9980 const MInt cellId = m_splitCells[sc];
9981 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
9982 cellCheck(cellId, 9) += a_cellVolume(m_splitChilds[sc][ssc]);
9983 cellCheck(cellId, 10) += m_cellVolumesDt1[m_splitChilds[sc][ssc]];
9984 cellCheck(cellId, 11) += m_sweptVolume[a_bndryId(m_splitChilds[sc][ssc])];
9985 cellCheck(cellId, 12) += m_sweptVolumeDt1[a_bndryId(m_splitChilds[sc][ssc])];
9986 cellCheck(cellId, 13) += F1;
9991 exchangeData(&cellCheck(0), 14);
9993 for(
MInt cellId = noInternalCells(); cellId < a_noCells(); cellId++) {
9994 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
9996 if(grid().azimuthalPeriodicity() && a_isPeriodic(cellId))
continue;
9998 if((
MInt)cellCheck(cellId, 0) != a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
9999 cerr << domainId() <<
": ERR0 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10000 << c_globalId(cellId) <<
" " << cellCheck(cellId, 0) <<
" "
10001 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" "
10002 << (((a_hasProperty(cellId, SolverCell::IsSplitChild)) ? getAssociatedInternalCell(cellId) : cellId)) <<
" "
10003 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild)
10004 <<
" " << a_isHalo(cellId) <<
" " << a_isWindow(cellId) <<
" "
10005 << a_levelSetValuesMb(cellId, 0) / c_cellLengthAtCell(cellId) <<
" " << a_bndryId(cellId) <<
" "
10006 << a_level(((a_hasProperty(cellId, SolverCell::IsSplitChild)) ? getAssociatedInternalCell(cellId) : cellId))
10008 if((
MInt)cellCheck(cellId, 1)
10009 != (
MInt)(a_bndryId(cellId) > -1 ? (
MFloat)m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_noSrfcs
10010 : std::numeric_limits<MFloat>::max())) {
10011 MFloat noSurfaces = std::numeric_limits<MFloat>::max();
10012 if(a_bndryId(cellId) > -1) {
10013 noSurfaces = (
MFloat)m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_noSrfcs;
10015 cerr << domainId() <<
": ERR1 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10016 << m_noOuterBndryCells <<
" " << a_bndryId(cellId) <<
" " << noSurfaces <<
" " << c_globalId(cellId) << endl;
10018 if(fabs(cellCheck(cellId, 2) - a_levelSetValuesMb(cellId, 0)) > eps1)
10020 ||
mMin(cellCheck(cellId, 2), a_levelSetValuesMb(cellId, 0)) < m_outerBandWidth[maxUniformRefinementLevel()])
10021 cerr << domainId() <<
": ERR2 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10022 << cellCheck(cellId, 2) <<
" " << a_levelSetValuesMb(cellId, 0) <<
" "
10023 << cellCheck(cellId, 2) - a_levelSetValuesMb(cellId, 0) <<
" " << c_globalId(cellId) <<
" "
10024 << m_bodyDistThreshold << endl;
10025 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
10026 if(!a_isHalo(cellId))
continue;
10027 if((
MInt)cellCheck(cellId, 3) != a_hasProperty(cellId, SolverCell::IsInactive))
10028 cerr << domainId() <<
": ERR3 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10029 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild)
10030 <<
" " << a_isHalo(cellId) <<
" " << a_isWindow(cellId) <<
" " << a_levelSetValuesMb(cellId, 0) << endl;
10031 if((
MInt)cellCheck(cellId, 4) != a_hasProperty(cellId, SolverCell::WasInactive))
10032 cerr << domainId() <<
": ERR4 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10033 if((
MInt)cellCheck(cellId, 5) != a_hasProperty(cellId, SolverCell::IsSplitCell))
10034 cerr << domainId() <<
": ERR5 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10035 if((
MInt)cellCheck(cellId, 6) != a_hasProperty(cellId, SolverCell::IsSplitChild))
10036 cerr << domainId() <<
": ERR6 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10037 if((
MInt)cellCheck(cellId, 7) != a_hasProperty(cellId, SolverCell::IsGapCell))
10038 cerr << domainId() <<
": ERR7 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10039 if((
MInt)cellCheck(cellId, 8) != a_hasProperty(cellId, SolverCell::WasGapCell))
10040 cerr << domainId() <<
": ERR8 generateBndryCellsMb " <<
globalTimeStep <<
" " << c_globalId(cellId) << endl;
10041 if(!a_hasProperty(cellId, SolverCell::IsSplitCell) && !a_hasProperty(cellId, SolverCell::IsSplitCell)) {
10042 if(fabs(cellCheck(cellId, 9) - a_cellVolume(cellId)) > eps0)
10043 cerr << domainId() <<
": ERR9 generateBndryCellsMb " << cellId <<
" " << c_globalId(cellId) <<
" "
10044 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild)
10045 <<
" " << a_isHalo(cellId) <<
" " << a_isWindow(cellId) <<
" ls " << a_levelSetValuesMb(cellId, 0) <<
" "
10046 << a_isGapCell(cellId) <<
" " << a_wasGapCell(cellId) <<
" " << a_bndryId(cellId) <<
" " << a_level(cellId)
10047 <<
" " << a_cellVolume(cellId) <<
" "
10048 << (cellCheck(cellId, 9) - grid().gridCellVolume(a_level(cellId))) / grid().gridCellVolume(a_level(cellId))
10050 << (a_cellVolume(cellId) - grid().gridCellVolume(a_level(cellId))) / grid().gridCellVolume(a_level(cellId))
10051 <<
" " << fabs(cellCheck(cellId, 9) - a_cellVolume(cellId)) / grid().gridCellVolume(a_level(cellId))
10054 if(fabs(cellCheck(cellId, 10) - m_cellVolumesDt1[cellId]) > eps0)
10055 cerr << domainId() <<
": ERR10 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10056 << c_globalId(cellId) <<
" " << a_isGapCell(cellId) << a_wasGapCell(cellId) << endl;
10058 if(a_bndryId(cellId) > -1 && fabs(cellCheck(cellId, 11) - m_sweptVolume[a_bndryId(cellId)]) > eps0)
10059 cerr << domainId() <<
": ERR11 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10060 << c_globalId(cellId) <<
" " << cellCheck(cellId, 11) <<
" " << m_sweptVolume[a_bndryId(cellId)] <<
" "
10061 << a_bndryId(cellId) <<
" " << m_noOuterBndryCells <<
" "
10062 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" "
10063 << a_hasProperty(cellId, SolverCell::IsSplitChild) <<
" " << a_isGapCell(cellId) <<
" "
10064 << a_wasGapCell(cellId) << endl;
10065 if(a_bndryId(cellId) > -1 && fabs(cellCheck(cellId, 12) - m_sweptVolumeDt1[a_bndryId(cellId)]) > eps0)
10066 cerr << domainId() <<
": ERR12 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId <<
" "
10067 << a_isGapCell(cellId) <<
" " << a_wasGapCell(cellId) << endl;
10071 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
10072 const MInt cellId = m_splitCells[sc];
10073 if(a_isHalo(cellId)) {
10075 if(grid().azimuthalPeriodicity() && a_isPeriodic(cellId))
continue;
10077 MFloat test1 = a_cellVolume(cellId);
10078 MFloat test2 = m_cellVolumesDt1[cellId];
10079 MFloat test33 = m_sweptVolume[a_bndryId(cellId)];
10080 MFloat test4 = m_sweptVolumeDt1[a_bndryId(cellId)];
10081 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
10083 test1 += a_cellVolume(m_splitChilds[sc][ssc]);
10084 test2 += m_cellVolumesDt1[m_splitChilds[sc][ssc]];
10085 test33 += m_sweptVolume[a_bndryId(m_splitChilds[sc][ssc])];
10086 test4 += m_sweptVolumeDt1[a_bndryId(m_splitChilds[sc][ssc])];
10088 if((
MInt)test0 != (
MInt)cellCheck(cellId, 13))
10089 cerr << domainId() <<
": ERR13 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10090 if(fabs(test1 - cellCheck(cellId, 9)) > eps0)
10091 cerr << domainId() <<
": ERR14 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10092 if(fabs(test2 - cellCheck(cellId, 10)) > eps0)
10093 cerr << domainId() <<
": ERR15 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10095 if(fabs(test33 - cellCheck(cellId, 11)) > eps0)
10096 cerr << domainId() <<
": ERR16 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10097 if(fabs(test4 - cellCheck(cellId, 12)) > eps0)
10098 cerr << domainId() <<
": ERR17 generateBndryCellsMb " <<
globalTimeStep <<
" " << cellId << endl;
10109template <MInt nDim,
class SysEqn>
10115 MIntScratchSpace haloBufferOffsets(noNeighborDomains() + 1, AT_,
"haloBufferOffsets");
10116 MIntScratchSpace windowBufferOffsets(noNeighborDomains() + 1, AT_,
"windowBufferOffsets");
10121 MInt windowSize = 0;
10122 haloBufferCnts.
fill(0);
10123 windowBufferCnts.
fill(0);
10124 haloBufferOffsets.
fill(0);
10125 windowBufferOffsets.
fill(0);
10127 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10128 haloBufferCnts(i) = (m_noCVars + m_noFVars + 3) * (
signed)m_fvBndryCnd->m_nearBoundaryHaloCells[i].
size();
10129 windowBufferCnts(i) = (m_noCVars + m_noFVars + 3) * (
signed)m_fvBndryCnd->m_nearBoundaryWindowCells[i].
size();
10130 haloBufferOffsets(i + 1) = haloBufferOffsets(i) + haloBufferCnts(i);
10131 windowBufferOffsets(i + 1) = windowBufferOffsets(i) + windowBufferCnts(i);
10132 haloSize += haloBufferCnts(i);
10133 windowSize += windowBufferCnts(i);
10151 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
10152 const MInt cellId = m_bndryLayerCells[c];
10153 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
10154 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
10155 for(
MUint v = 0; v < noPVars; v++) {
10156 a_slope(cellId, v, 0) = F0;
10157 a_slope(cellId, v, 1) = F0;
10159 redistVol(cellId) = F0;
10160 redistSweptVol(cellId) = F0;
10164 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10165 for(
MInt j = 0; j < (signed)m_fvBndryCnd->m_nearBoundaryHaloCells[i].size(); j++) {
10166 MInt cellId = m_fvBndryCnd->m_nearBoundaryHaloCells[i][j];
10167 for(
MUint v = 0; v < noPVars; v++) {
10168 a_slope(cellId, v, 0) = F0;
10169 a_slope(cellId, v, 1) = F0;
10171 redistVol(cellId) = F0;
10172 redistSweptVol(cellId) = F0;
10173 const MInt offset = haloBufferOffsets(i) + (noCVars + noFVars + 3) * j;
10174 haloBuffer(offset + 2) = -F1;
10176 for(
MInt j = 0; j < (signed)m_fvBndryCnd->m_nearBoundaryWindowCells[i].size(); j++) {
10177 MInt cellId = m_fvBndryCnd->m_nearBoundaryWindowCells[i][j];
10178 for(
MUint v = 0; v < noPVars; v++) {
10179 a_slope(cellId, v, 0) = F0;
10180 a_slope(cellId, v, 1) = F0;
10182 redistVol(cellId) = F0;
10183 redistSweptVol(cellId) = F0;
10188 for(
MUint i = 0; i < m_massRedistributionIds.size(); ++i) {
10189 const MInt cellId = m_massRedistributionIds[i];
10190 ASSERT(!(a_isPeriodic(cellId)),
"");
10191 ASSERT(!(a_isHalo(cellId)),
"");
10192 if(a_isHalo(cellId))
continue;
10194 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
10195 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
10199 for(
MInt dir = 0; dir < m_noDirs; dir++) {
10200 if(!checkNeighborActive(cellId, dir) || a_hasNeighbor(cellId, dir) == 0)
continue;
10201 const MInt nghbrId = c_neighborId(cellId, dir);
10202 if(nghbrId < 0)
continue;
10203 if(!a_hasProperty(nghbrId, SolverCell::IsOnCurrentMGLevel))
continue;
10204 if(a_bndryId(nghbrId) < 0)
continue;
10205 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
10208 if(grid().azimuthalPeriodicity() && a_isPeriodic(nghbrId))
continue;
10210 MInt bndryId = (a_bndryId(cellId) > -1) ? a_bndryId(cellId) : a_bndryId(nghbrId);
10211 if(bndryId < 0)
mTerm(1, AT_,
"not expected");
10214 for(
MInt k = 0; k < nDim; k++) {
10215 normal[k] = m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVectorCentroid[k];
10217 const MFloat nml = normal[dir / 2];
10218 const MFloat ncut = 0.01;
10220 weights[counter] =
mMax(F0, (
POW2(nml) - ncut) / (F1 - ncut))
10221 *
mMin(F1,
mMax(F0,
mMin(a_cellVolume(nghbrId), m_cellVolumesDt1[nghbrId]))
10222 /
mMax(0.5 * m_volumeThreshold, fabs(m_massRedistributionVolume[i])));
10224 volCnt += weights[counter];
10225 nghbrList[counter] = nghbrId;
10228 for(
MInt n = 0; n < counter; n++) {
10229 weights[n] /=
mMax(1e-14, volCnt);
10232 if(
true || volCnt < 0.1) {
10233 counter = this->
template getAdjacentLeafCells<2, true>(cellId, 1, nghbrList, layerId);
10235 for(
MInt n = 0; n < counter; n++) {
10237 MInt nghbrId = nghbrList[n];
10238 if(nghbrId < 0)
continue;
10239 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
10240 if(a_bndryId(nghbrId) < 0)
continue;
10242 if(grid().azimuthalPeriodicity() && a_isPeriodic(nghbrId))
continue;
10244 if(a_hasProperty(nghbrId, SolverCell::IsSplitCell))
continue;
10245 if(a_hasProperty(nghbrId, SolverCell::IsSplitChild))
continue;
10248 +
mMax(F0, (a_cellVolume(nghbrId) + m_cellVolumesDt1[nghbrId]))
10249 / (F2 * grid().gridCellVolume(a_level(cellId)));
10252 MInt bndryId = a_bndryId(nghbrId);
10253 if(bndryId < 0)
mTerm(1, AT_,
"not expected");
10254 weights[n] = grid().gridCellVolume(a_level(cellId))
10255 /
mMax(1e-10, fabs(a_cellVolume(nghbrId) + m_massRedistributionVolume[i]
10256 + m_RKalpha[m_noRKSteps - 2] * m_massRedistributionSweptVol[i]
10257 - m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume));
10259 volCnt += weights[n];
10261 for(
MInt n = 0; n < counter; n++) {
10262 weights[n] /=
mMax(1e-14, volCnt);
10266 for(
MInt n = 0; n < counter; n++) {
10267 MInt nghbrId = nghbrList[n];
10268 if(nghbrId < 0)
continue;
10269 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
10270 if(a_bndryId(nghbrId) < 0)
continue;
10272 if(a_hasProperty(nghbrId, SolverCell::IsSplitCell))
continue;
10273 if(a_hasProperty(nghbrId, SolverCell::IsSplitChild))
continue;
10275 const MFloat fac = weights[n];
10277 if(!a_hasProperty(nghbrId, SolverCell::NearWall)) {
10278 cerr <<
"[" << domainId() <<
"]: "
10279 <<
" nghbr " << nghbrId <<
" of cell " << cellId <<
" does not lie in bndryLayer! " << endl;
10280 cerr <<
" nghbr is a split cell: " << a_hasProperty(nghbrId, SolverCell::IsSplitCell)
10281 <<
" is split child: " << a_hasProperty(nghbrId, SolverCell::IsSplitChild) << endl;
10284 for(
MUint v = 0; v < noPVars; v++) {
10285 a_slope(nghbrId, v, 0) += fac * m_massRedistributionVolume[i] * m_massRedistributionVariables[i * noPVars + v];
10286 a_slope(nghbrId, v, 1) += fac * m_massRedistributionRhs[i * noPVars + v];
10289 redistVol(nghbrId) += fac * m_massRedistributionVolume[i];
10290 redistSweptVol(nghbrId) += fac * m_massRedistributionSweptVol[i];
10292 m_massRedistributionVolume[i] = F0;
10293 m_massRedistributionSweptVol[i] = F0;
10296 m_massRedistributionIds.clear();
10297 m_massRedistributionVolume.clear();
10298 m_massRedistributionSweptVol.clear();
10299 m_massRedistributionVariables.clear();
10300 m_massRedistributionRhs.clear();
10305 haloReq.
fill(MPI_REQUEST_NULL);
10306 windowReq.
fill(MPI_REQUEST_NULL);
10307 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10308 if(m_fvBndryCnd->m_nearBoundaryHaloCells[i].empty())
continue;
10309 for(
MInt j = 0; j < (signed)m_fvBndryCnd->m_nearBoundaryHaloCells[i].size(); j++) {
10310 MInt cellId = m_fvBndryCnd->m_nearBoundaryHaloCells[i][j];
10311 MInt offset = haloBufferOffsets(i) + (noPVars + noFVars + 3) * j;
10313 haloBuffer(offset) = redistVol(cellId);
10314 haloBuffer(offset + 1) = redistSweptVol(cellId);
10315 for(
MInt v = 0; v < (signed)noPVars; v++) {
10316 haloBuffer(offset + 3 + v) = a_slope(cellId, v, 0);
10317 haloBuffer(offset + 3 + noPVars + v) = a_slope(cellId, v, 1);
10322 MInt windowCnt = 0;
10323 if(m_nonBlockingComm) {
10324 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10325 if(windowBufferCnts(i) == 0)
continue;
10326 MPI_Irecv(&windowBuffer[windowBufferOffsets[i]], windowBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 17,
10327 mpiComm(), &windowReq[windowCnt], AT_,
"windowBuffer[windowBufferOffsets[i]]");
10330 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10331 if(haloBufferCnts(i) == 0)
continue;
10332 MPI_Isend(&haloBuffer[haloBufferOffsets[i]], haloBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 17, mpiComm(),
10333 &haloReq[haloCnt], AT_,
"haloBuffer[haloBufferOffsets[i]]");
10336 if(windowCnt > 0)
MPI_Waitall(windowCnt, &windowReq[0], MPI_STATUSES_IGNORE, AT_);
10338 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10339 if(haloBufferCnts(i) == 0)
continue;
10340 MPI_Issend(&haloBuffer[haloBufferOffsets[i]], haloBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 17, mpiComm(),
10341 &haloReq[haloCnt], AT_,
"haloBuffer[haloBufferOffsets[i]]");
10344 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10345 if(windowBufferCnts(i) == 0)
continue;
10346 MPI_Recv(&windowBuffer[windowBufferOffsets[i]], windowBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 17,
10347 mpiComm(), MPI_STATUS_IGNORE, AT_,
"windowBuffer[windowBufferOffsets[i]]");
10352 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10353 if(m_fvBndryCnd->m_nearBoundaryWindowCells[i].empty())
continue;
10354 for(
MInt j = 0; j < (signed)m_fvBndryCnd->m_nearBoundaryWindowCells[i].size(); j++) {
10355 MInt cellId = m_fvBndryCnd->m_nearBoundaryWindowCells[i][j];
10356 MInt offset = windowBufferOffsets(i) + (noCVars + noFVars + 3) * j;
10358 redistVol(cellId) += windowBuffer(offset);
10359 redistSweptVol(cellId) += windowBuffer(offset + 1);
10361 for(
MInt v = 0; v < (signed)noPVars; v++) {
10362 a_slope(cellId, v, 0) += windowBuffer(offset + 3 + v);
10363 a_slope(cellId, v, 1) += windowBuffer(offset + 3 + noPVars + v);
10367 if(haloCnt > 0)
MPI_Waitall(haloCnt, &haloReq[0], MPI_STATUSES_IGNORE, AT_);
10370 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
10371 MInt cellId = m_bndryLayerCells[c];
10372 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
10373 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
10374 if(a_isPeriodic(cellId))
continue;
10375 if(a_isHalo(cellId))
continue;
10376 if(fabs(redistVol(cellId)) < 1e-12)
continue;
10378 MFloat vol = m_cellVolumesDt1[cellId] + redistVol(cellId);
10379 if(fabs(vol) > 1e-14) {
10380 for(
MUint v = 0; v < noCVars; v++) {
10381 a_oldVariable(cellId, v) = (a_oldVariable(cellId, v) * m_cellVolumesDt1[cellId] + a_slope(cellId, v, 0))
10382 / (m_cellVolumesDt1[cellId] + redistVol(cellId));
10383 m_rhs0[cellId][v] += a_slope(cellId, v, 1);
10386 m_cellVolumesDt1[cellId] = vol;
10387#ifdef GEOM_CONS_LAW
10388 if(a_bndryId(cellId) > -1) {
10389 a_cellVolume(cellId) += redistVol(cellId);
10390 m_sweptVolumeDt1[a_bndryId(cellId)] += redistSweptVol(cellId);
10391 if(m_gclIntermediate) {
10392 if(m_levelSetMb) a_cellVolume(cellId) += redistSweptVol(cellId);
10394 if(m_levelSetMb) a_cellVolume(cellId) += F1B2 * redistSweptVol(cellId);
10396 a_cellVolume(cellId) =
mMax(m_volumeThreshold, a_cellVolume(cellId));
10397 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10398 m_volumeFraction[a_bndryId(cellId)] = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
10400 cerr <<
"not supposed to happen at redist" << endl;
10406#ifdef GEOM_CONS_LAW
10407 MBool& firstRun = m_static_redistributeMass_firstRun;
10409 MBool conserveMass =
true;
10410 if(m_gapInitMethod == 0 && m_gapOpened) {
10411 conserveMass =
false;
10412 }
else if(m_gapInitMethod > 0) {
10413 conserveMass =
true;
10416 if(!firstRun && conserveMass) {
10417 if(m_gclIntermediate) {
10419 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
10420 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
10421 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10422 MFloat dV0 = m_sweptVolumeDt1[bndryId];
10423 MFloat dV1 = m_sweptVolume[bndryId];
10424 MFloat vol = m_cellVolumesDt1[cellId] + dV0;
10425 for(
MInt r = 1; r < m_noRKSteps; r++) {
10426 const MFloat deltaVol = m_RKalpha[r - 1] * dV1 + (F1 - m_RKalpha[r - 1]) * dV0;
10427 vol =
mMin(m_cellVolumesDt1[cellId] + deltaVol, vol);
10429 vol =
mMax(F0, vol);
10430 a_cellVolume(cellId) = vol;
10431 a_cellVolume(cellId) =
mMax(a_cellVolume(cellId), m_volumeThreshold);
10432 m_volumeFraction[bndryId] = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
10433 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10436 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
10437 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
10438 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10439 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
10440 MFloat dV0 = m_sweptVolumeDt1[bndryId];
10441 MFloat dV1 = m_sweptVolume[bndryId];
10442 a_cellVolume(cellId) =
10443 m_cellVolumesDt1[cellId] + m_RKalpha[m_noRKSteps - 2] * dV1 + (F1 - m_RKalpha[m_noRKSteps - 2]) * dV0;
10444 a_cellVolume(cellId) =
mMax(a_cellVolume(cellId), m_volumeThreshold);
10445 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10454 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
10455 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10456 const MFloat V0 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume - 0.1 * grid().gridCellVolume(a_level(cellId));
10457 const MFloat V1 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume + 0.1 * grid().gridCellVolume(a_level(cellId));
10458 a_cellVolume(cellId) =
mMin(V1,
mMax(V0, a_cellVolume(cellId)));
10459 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10464 haloReq.
fill(MPI_REQUEST_NULL);
10465 windowReq.
fill(MPI_REQUEST_NULL);
10466 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10467 if(m_fvBndryCnd->m_nearBoundaryWindowCells[i].empty())
continue;
10468 for(
MInt j = 0; j < (signed)m_fvBndryCnd->m_nearBoundaryWindowCells[i].size(); j++) {
10469 MInt cellId = m_fvBndryCnd->m_nearBoundaryWindowCells[i][j];
10470 MInt offset = windowBufferOffsets(i) + (noCVars + noFVars + 3) * j;
10471 windowBuffer(offset) = a_cellVolume(cellId);
10472 windowBuffer(offset + 1) = m_cellVolumesDt1[cellId];
10473 windowBuffer(offset + 2) = (a_bndryId(cellId) > -1) ? m_sweptVolumeDt1[a_bndryId(cellId)] : F0;
10474 for(
MInt v = 0; v < (signed)noCVars; v++) {
10475 windowBuffer(offset + 3 + v) = a_oldVariable(cellId, v);
10477 for(
MInt v = 0; v < (signed)noFVars; v++) {
10478 windowBuffer(offset + 3 + noCVars + v) = m_rhs0[cellId][v];
10482 MInt windowCnt = 0;
10484 if(m_nonBlockingComm) {
10485 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10486 if(haloBufferCnts(i) == 0)
continue;
10487 MPI_Irecv(&haloBuffer[haloBufferOffsets[i]], haloBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 18, mpiComm(),
10488 &haloReq[haloCnt], AT_,
"haloBuffer[haloBufferOffsets[i]]");
10491 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10492 if(windowBufferCnts(i) == 0)
continue;
10493 MPI_Isend(&windowBuffer[windowBufferOffsets[i]], windowBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 18,
10494 mpiComm(), &windowReq[windowCnt], AT_,
"windowBuffer[windowBufferOffsets[i]]");
10497 if(haloCnt > 0)
MPI_Waitall(haloCnt, &haloReq[0], MPI_STATUSES_IGNORE, AT_);
10499 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10500 if(windowBufferCnts(i) == 0)
continue;
10501 MPI_Issend(&windowBuffer[windowBufferOffsets[i]], windowBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 18,
10502 mpiComm(), &windowReq[windowCnt], AT_,
"windowBuffer[windowBufferOffsets[i]]");
10505 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10506 if(haloBufferCnts(i) == 0)
continue;
10507 MPI_Recv(&haloBuffer[haloBufferOffsets[i]], haloBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 18, mpiComm(),
10508 MPI_STATUS_IGNORE, AT_,
"haloBuffer[haloBufferOffsets[i]]");
10512 for(
MInt i = 0; i < noNeighborDomains(); i++) {
10513 if(m_fvBndryCnd->m_nearBoundaryHaloCells[i].empty())
continue;
10514 for(
MInt j = 0; j < (signed)m_fvBndryCnd->m_nearBoundaryHaloCells[i].size(); j++) {
10515 MInt cellId = m_fvBndryCnd->m_nearBoundaryHaloCells[i][j];
10516 MInt offset = haloBufferOffsets(i) + (noCVars + noFVars + 3) * j;
10517 a_cellVolume(cellId) = haloBuffer(offset);
10518 m_cellVolumesDt1[cellId] = haloBuffer(offset + 1);
10519 for(
MInt v = 0; v < (signed)noCVars; v++) {
10520 a_oldVariable(cellId, v) = haloBuffer(offset + 3 + v);
10522 for(
MInt v = 0; v < (signed)noFVars; v++) {
10523 m_rhs0[cellId][v] = haloBuffer(offset + 3 + noCVars + v);
10525 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10526 if(a_bndryId(cellId) > -1) {
10527 m_volumeFraction[a_bndryId(cellId)] = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
10528 m_sweptVolumeDt1[a_bndryId(cellId)] = haloBuffer(offset + 2);
10532 if(windowCnt > 0)
MPI_Waitall(windowCnt, &windowReq[0], MPI_STATUSES_IGNORE, AT_);
10535#ifndef GEOM_CONS_LAW
10536 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
10537 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10538 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
10539 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10540 m_volumeFraction[a_bndryId(cellId)] = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
10546#ifdef LOG_DELTA_VOL
10547 MFloat maxdv = -99999.0;
10552 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
10553 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10554 if(a_isHalo(cellId))
continue;
10555 MFloat dv = (a_cellVolume(cellId) - m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume)
10556 / grid().gridCellVolume(a_level(cellId));
10557 if(dv > maxdv) maxId = cellId;
10558 maxdv =
mMax(maxdv, dv);
10559 mindv =
mMin(mindv, dv);
10563 MPI_Allreduce(MPI_IN_PLACE, &maxdv, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"maxdv");
10564 MPI_Allreduce(MPI_IN_PLACE, &mindv, 1, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"mindv");
10565 MPI_Allreduce(MPI_IN_PLACE, &avgdv, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"avgdv");
10566 MPI_Allreduce(MPI_IN_PLACE, &cnt, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"cnt");
10568 if(domainId() == 0) {
10569 cerr <<
"dv: " <<
globalTimeStep <<
" " << avgdv <<
" " << maxdv <<
" " << mindv <<
" -- "
10570 << a_cellVolume(maxId) / grid().gridCellVolume(a_level(maxId)) <<
" "
10571 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(maxId)].m_volume / grid().gridCellVolume(a_level(maxId)) <<
" ("
10572 << m_cellVolumesDt1[maxId] / grid().gridCellVolume(a_level(maxId)) <<
" "
10573 << m_sweptVolume[a_bndryId(maxId)] / grid().gridCellVolume(a_level(maxId)) <<
" "
10574 << m_sweptVolumeDt1[a_bndryId(maxId)] / grid().gridCellVolume(a_level(maxId)) <<
" " << maxId <<
")" << endl;
10576 ofl.open(
"vol_err", ios_base::out | ios_base::app);
10577 if(ofl.is_open() && ofl.good()) {
10578 ofl << setprecision(12) <<
globalTimeStep <<
" " << avgdv <<
" " << maxdv <<
" " << mindv <<
" "
10579 << a_cellVolume(maxId) / grid().gridCellVolume(a_level(maxId)) <<
" "
10580 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(maxId)].m_volume / grid().gridCellVolume(a_level(maxId)) <<
" "
10581 << m_cellVolumesDt1[maxId] / grid().gridCellVolume(a_level(maxId)) <<
" "
10582 << m_sweptVolume[a_bndryId(maxId)] / grid().gridCellVolume(a_level(maxId)) <<
" "
10583 << m_sweptVolumeDt1[a_bndryId(maxId)] / grid().gridCellVolume(a_level(maxId)) <<
" " << maxId << endl;
10591 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
10592 const MInt cellId = m_bndryLayerCells[c];
10593 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
10594 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
10595 setPrimitiveVariables(cellId);
10599#if defined _MB_DEBUG_ || !defined NDEBUG
10600 m_solutionDiverged =
false;
10602 for(
MInt i = a_noCells(); i--;) {
10603 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
10604 if(!a_hasProperty(i, SolverCell::IsOnCurrentMGLevel))
continue;
10605 if(a_isHalo(i))
continue;
10606 if(a_isBndryGhostCell(i))
continue;
10607 if(a_hasProperty(i, SolverCell::IsInactive))
continue;
10608 for(
MInt v = 0; v < m_noCVars; v++) {
10609 if(!(a_variable(i, v) >= F0 || a_variable(i, v) < F0) || std::isnan(a_variable(i, v))) {
10611 cerr << setprecision(12) << domainId() <<
": MRED " << i <<
" " << a_bndryId(i) <<
" " << v <<
" "
10612 << a_variable(i, v) <<
" "
10613 <<
"cells[i].b_properties.to_string()"
10614 <<
" " << c_noChildren(i) <<
" " << a_hasProperty(i, SolverCell::IsInactive) <<
" "
10615 << a_hasProperty(i, SolverCell::IsSplitCell) <<
" " << a_hasProperty(i, SolverCell::IsSplitChild) <<
" "
10616 << a_cellVolume(i) / grid().gridCellVolume(a_level(i)) <<
" "
10617 << m_cellVolumesDt1[i] / grid().gridCellVolume(a_level(i));
10618 if(i < c_noCells()) cerr <<
" " << c_globalId(i) << endl;
10619 m_solutionDiverged =
true;
10624 IF_CONSTEXPR(nDim == 2) {
10626 sysEqn().pressure(1.0, a_pvariable(i, PV->RHO) * (
POW2(a_pvariable(i, PV->U)) +
POW2(a_pvariable(i, PV->V))),
10627 a_variable(i, CV->RHO_E));
10629 else IF_CONSTEXPR(nDim == 3) {
10630 pres = sysEqn().pressure(
10632 a_pvariable(i, PV->RHO)
10633 * (
POW2(a_pvariable(i, PV->U)) +
POW2(a_pvariable(i, PV->V)) +
POW2(a_pvariable(i, PV->W))),
10634 a_variable(i, CV->RHO_E));
10636 if(a_cellVolume(i) / grid().gridCellVolume(a_level(i)) > m_fvBndryCnd->m_volumeLimitWall) {
10637 if(a_variable(i, CV->RHO) < F0 || pres < F0) {
10639 cerr << domainId() <<
": MRED " << i <<
" " << a_bndryId(i) <<
" " << a_level(i) <<
" /r "
10640 << a_variable(i, CV->RHO) <<
" /p " << pres <<
" /v "
10641 << a_cellVolume(i) / grid().gridCellVolume(a_level(i)) <<
" "
10642 << m_cellVolumesDt1[i] / grid().gridCellVolume(a_level(i)) <<
" "
10643 <<
"cells[i].b_properties.to_string()"
10644 <<
" " << a_hasProperty(i, SolverCell::IsSplitCell) <<
" " << a_hasProperty(i, SolverCell::IsSplitChild)
10645 <<
" " << a_isPeriodic(i) <<
" " << a_coordinate(i, 0) <<
" " << a_coordinate(i, 1) <<
" "
10646 << a_coordinate(i,
mMin((
MInt)FD, 2));
10647 if(i < c_noCells()) cerr <<
" " << c_globalId(i) << endl;
10648 m_solutionDiverged =
true;
10653 if(m_solutionDiverged) {
10654 cerr <<
"Solution diverged after mass redistribution at solver " << domainId() <<
" " <<
globalTimeStep <<
" "
10655 << m_RKStep << endl;
10657 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
10658 "m_solutionDiverged");
10659 if(m_solutionDiverged) {
10660 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
10662 mTerm(1, AT_,
"Solution diverged after mass redistribution.");
10672template <MInt nDim,
class SysEqn>
10674 for(
MUint it = 0; it < m_temporarilyLinkedCells.size(); it++) {
10675 activeFlag(get<0>(m_temporarilyLinkedCells[it])) = 1;
10676 activeFlag(get<1>(m_temporarilyLinkedCells[it])) = 1;
10677 if(get<2>(m_temporarilyLinkedCells[it]) > 0) {
10678 activeFlag(get<2>(m_temporarilyLinkedCells[it])) = 1;
10688template <MInt nDim,
class SysEqn>
10693 MInt globalErrorId = 0;
10696 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
10697 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10699 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
10700 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
10701 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
10704 const MFloat faceArea = (nDim == 3) ?
POW2(sqrt(F3) * c_cellLengthAtLevel(a_cutCellLevel(cellId)))
10705 : sqrt(F2) * c_cellLengthAtLevel(a_cutCellLevel(cellId));
10706 const MFloat faceArea0 =
10707 (nDim == 3) ?
POW2(c_cellLengthAtLevel(a_cutCellLevel(cellId))) : c_cellLengthAtLevel(a_cutCellLevel(cellId));
10709 ASSERT(m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs > 0,
"");
10711 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume < F0)
10713 else if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume > (grid().gridCellVolume(a_level(cellId)) + m_eps))
10715 else if(std::isnan(m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume))
10717 if(errorId == 1)
m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId << endl;
10719 if(m_volumeFraction[bndryId] < F0)
10721 else if(m_volumeFraction[bndryId] > (F1 + m_eps))
10723 else if(std::isnan(m_volumeFraction[bndryId]))
10726 m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId <<
" " << m_volumeFraction[bndryId] << endl;
10733 for(
MInt i = 0; i < nDim; i++)
10734 if(std::isnan(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[i])) errorId = 3;
10736 m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId << endl;
10739 for(
MInt i = 0; i < nDim; i++)
10740 if(fabs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[i]) > (F1 + m_eps)) errorId = 4;
10742 IF_CONSTEXPR(nDim == 2) {
10743 m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId <<
" "
10744 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[0] <<
" "
10745 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[1] <<
" " << scientific
10746 << setprecision(16) << m_volumeFraction[bndryId] << endl;
10748 else IF_CONSTEXPR(nDim == 3) {
10749 m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId <<
" "
10750 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[0] <<
" "
10751 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[1] <<
" "
10752 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[2] <<
" " << scientific
10753 << setprecision(16) << m_volumeFraction[bndryId] << endl;
10757 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_area < F0)
10759 else if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_area > (faceArea + m_eps))
10761 else if(std::isnan(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_area))
10763 if(errorId == 5)
m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId << endl;
10765 if(a_hasProperty(cellId, SolverCell::IsInactive))
10767 else if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
10769 if(errorId == 6)
m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId << endl;
10771 for(
MInt i = 0; i < nDim; i++)
10772 if(fabs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[i] - a_coordinate(cellId, i))
10773 > (F1B2 * c_cellLengthAtLevel(a_cutCellLevel(cellId)) + m_eps))
10775 for(
MInt i = 0; i < nDim; i++)
10776 if(std::isnan(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[i])) errorId = 7;
10786 m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId << endl;
10790 for(
MInt dir = 0; dir < m_noDirs; dir++) {
10791 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
10793 if(a_surfaceArea(srfcId) < F0)
10795 else if(a_surfaceArea(srfcId) > (faceArea0 + 100 * m_eps))
10797 else if(std::isnan(a_surfaceArea(srfcId)))
10799 for(
MInt i = 0; i < nDim; i++) {
10800 if(fabs(a_surfaceCoordinate(srfcId, i) - a_coordinate(cellId, i))
10801 > (F1B2 * c_cellLengthAtLevel(a_level(cellId)) + 100 * m_eps))
10803 if(std::isnan(a_surfaceCoordinate(srfcId, i))) errorId = 8;
10805 if(errorId == 8)
m_log << a_surfaceCoordinate(srfcId, 0) <<
" " << a_surfaceCoordinate(srfcId, 1) << endl;
10806 if(errorId == 8)
m_log << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) << endl;
10807 ar = a_surfaceArea(srfcId);
10811 m_log <<
"BC: " << bndryId <<
" " << cellId <<
" " << errorId <<
" " << ar <<
" " << ar - faceArea0 << endl;
10812 for(
MInt i = 0; i < nDim; i++)
10813 m_log << a_coordinate(cellId, i) <<
" ";
10815 MInt cndId = m_bndryCandidateIds[cellId];
10817 for(
MInt node = 0; node < m_noCellNodes; node++) {
10818 m_log << node <<
" ";
10819 if(m_candidateNodeSet[cndId * m_noCellNodes + node])
10820 m_log << m_candidateNodeValues[IDX_LSSETNODES(cndId, node, 0)] <<
", ";
10826 for(
MInt dir = 0; dir < m_noDirs; dir++) {
10827 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
10829 m_log << setprecision(12) << dir <<
" " << srfcId <<
": " << a_surfaceArea(srfcId) / faceArea0 <<
" ";
10830 for(
MInt i = 0; i < nDim; i++)
10831 m_log << F1B2 * c_cellLengthAtLevel(a_level(cellId))
10832 - fabs(a_surfaceCoordinate(srfcId, i) - a_coordinate(cellId, i))
10839 for(
MInt i = 0; i < nDim; i++) {
10840 if(fabs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[i])
10841 > (F1B2 * c_cellLengthAtLevel(a_cutCellLevel(cellId)) + m_eps)) {
10842 m_log <<
"check BC: " << bndryId <<
" " << errorId <<
" " << setprecision(16) << m_volumeFraction[bndryId]
10843 << setprecision(8) <<
" "
10844 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[i] / c_cellLengthAtLevel(a_cutCellLevel(cellId))
10845 <<
" " << F1B2 * c_cellLengthAtLevel(a_cutCellLevel(cellId)) << endl;
10848 if(std::isnan(m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[i])) {
10849 m_log <<
"check BC: " << bndryId <<
" " << errorId <<
" " << setprecision(16) << m_volumeFraction[bndryId]
10850 << setprecision(8) <<
" "
10851 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_coordinates[i] / c_cellLengthAtLevel(a_cutCellLevel(cellId))
10852 <<
" " << F1B2 * c_cellLengthAtLevel(a_cutCellLevel(cellId)) << endl;
10856 globalErrorId =
mMax(globalErrorId, errorId);
10859 if(globalErrorId > 0) {
10860 m_log <<
"Warning " << globalErrorId <<
" in FvMbCartesianSolverXD::checkBoundaryCells at timestep "
10862 cerr <<
"Warning " << globalErrorId <<
" in FvMbCartesianSolverXD::checkBoundaryCells at timestep "
10864 stringstream GName;
10866 GName << m_solutionOutput;
10867 GName <<
"solver_data/GEOM";
10868 GName <<
"_B" << domainId();
10870 GName <<
"_warning";
10877template <MInt nDim,
class SysEqn>
10881 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
10884 if(m_dualTimeStepping) {
10885 mTerm(1, AT_,
"TODO DTS");
10886 a_cellVolume(cellId) = F4B3 * m_cellVolumesDt1[cellId] - F1B3 * m_cellVolumesDt2[cellId];
10887 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
10888 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
10889 for(
MInt i = 0; i < nDim; i++) {
10890 MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
10891 dV -= F2B3 * m_physicalTimeStep
10892 * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] * nml * area;
10896 MFloat dt = timeStep(
true);
10897 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
10898 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
10899 for(
MInt i = 0; i < nDim; i++) {
10900 MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
10901 dV -= dt * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] * nml * area;
10907 m_sweptVolume[bndryId] = dV;
10910 if(m_gclIntermediate) {
10914 deltaVol = m_RKalpha[m_noRKSteps - 2] * m_sweptVolume[bndryId]
10915 + (F1 - m_RKalpha[m_noRKSteps - 2]) * m_sweptVolumeDt1[bndryId];
10919 deltaVol = (m_levelSetMb) ? m_RKalpha[m_noRKSteps - 2] * m_sweptVolume[bndryId]
10920 + (F1 - m_RKalpha[m_noRKSteps - 2]) * m_sweptVolumeDt1[bndryId]
10923 a_cellVolume(cellId) = m_cellVolumesDt1[cellId] + deltaVol;
10925 const MFloat V0 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume - 0.1 * grid().gridCellVolume(a_level(cellId));
10926 const MFloat V1 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume + 0.1 * grid().gridCellVolume(a_level(cellId));
10927 a_cellVolume(cellId) =
mMin(V1,
mMax(V0, a_cellVolume(cellId)));
10929 a_cellVolume(cellId) =
mMax(a_cellVolume(cellId), m_volumeThreshold);
10930 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
10937 if(m_levelSet && m_closeGaps) {
10938 if(a_wasGapCell(cellId) || a_isGapCell(cellId)) {
10941 if(m_gapInitMethod > 0) {
10942 MInt regionId = m_gapCells[m_gapCellId[cellId]].region;
10943 ASSERT(regionId > -1,
"Negative region in Cell" << to_string(c_globalId(cellId)) <<
" " << m_gapCellId[cellId]);
10946 if(regionId == m_noGapRegions) {
10949 a_cellVolume(cellId) = m_cellVolumesDt1[cellId];
10950 m_sweptVolume[bndryId] = 0;
10951 m_sweptVolumeDt1[bndryId] = 0;
10954 if(m_gapState[regionId] == -2 || m_gapState[regionId] == 3 || m_gapState[regionId] == -1) {
10958 if(a_isGapCell(cellId)) {
10959 if(fabs(a_cellVolume(cellId) - m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume)
10960 > m_volumeThreshold * 10) {
10975 if(m_sweptVolume[bndryId] > 0 || m_sweptVolume[bndryId] < 0 || m_sweptVolumeDt1[bndryId] < 0
10976 || m_sweptVolumeDt1[bndryId] < 0) {
10977 cerr <<
" Incorrect swetVolume-Innitialisation " << m_sweptVolume[bndryId] << m_sweptVolumeDt1[bndryId]
10982 }
else if(m_gapState[regionId] == 2) {
10983 ASSERT(a_wasGapCell(cellId) && !a_isGapCell(cellId),
"");
10984 MInt status = m_gapCells[m_gapCellId[cellId]].status;
10988 if(status != 22 && status != 24 && status != 28 && status != 29 && status != 99 && status != 98) {
10989 cerr <<
"UnExpected Status for Volume (1) " << c_globalId(cellId) <<
" " << status << endl;
10995 if(deltaVol > m_sweptVolumeDt1[bndryId] || deltaVol < m_sweptVolumeDt1[bndryId]) {
10996 if(m_gapCells[m_gapCellId[cellId]].status != 98)
10997 cerr <<
"Incorrect Initialisation " << c_globalId(cellId) <<
" "
10998 << m_gapCells[m_gapCellId[cellId]].status << endl;
11001 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
11003 if(deltaVol > a_cellVolume(cellId)) {
11004 deltaVol = a_cellVolume(cellId);
11005 m_sweptVolume[bndryId] = deltaVol;
11007 m_cellVolumesDt1[cellId] = a_cellVolume(cellId) - deltaVol;
11008 m_sweptVolumeDt1[bndryId] = m_sweptVolume[bndryId];
11013 if(a_cellVolume(cellId) < 0 || m_cellVolumesDt1[cellId] < 0) {
11014 cerr <<
"Negative Cell-Volume : " << c_globalId(cellId) <<
" " << a_cellVolume(cellId) <<
" "
11015 << m_cellVolumesDt1[cellId] <<
" " << deltaVol <<
" " << dV <<
" " << m_sweptVolume[bndryId]
11016 <<
" status " << m_gapCells[m_gapCellId[cellId]].status << endl;
11019 if(a_cellVolume(cellId) > 1.03 * grid().gridCellVolume(a_level(cellId))) {
11020 cerr <<
"Volume exeeds Limit " << c_globalId(cellId) <<
" "
11021 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" "
11022 << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) <<
" status "
11023 << m_gapCells[m_gapCellId[cellId]].status << endl;
11026 if(m_cellVolumesDt1[cellId] > 1.03 * grid().gridCellVolume(a_level(cellId))) {
11027 cerr <<
"Dt-Volume exeeds Limit " << c_globalId(cellId) <<
" "
11028 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" "
11029 << m_cellVolumesDt1[cellId] / grid().gridCellVolume(a_level(cellId)) <<
" " << deltaVol <<
" "
11030 << m_gapCells[m_gapCellId[cellId]].status << endl;
11035 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
11036 m_cellVolumesDt1[cellId] = a_cellVolume(cellId) - deltaVol;
11050template <MInt nDim,
class SysEqn>
11054 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
11055 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
11056 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
11058 a_cellVolume(cellId) =
mMax(m_volumeThreshold, m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume);
11059 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
11060 m_volumeFraction[bndryId] =
mMax(m_volumeThreshold, m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume)
11061 / grid().gridCellVolume(a_level(cellId));
11070template <MInt nDim,
class SysEqn>
11074 if(m_timeStepAdaptationStart > -1 && m_timeStepAdaptationEnd > -1) {
11078 m_previousTimeStep = timeStep(
true);
11080 const MFloat newTimeStep = timeStep(
true);
11083 if(m_constructGField) {
11084 MFloat maxDispl = F2 * newTimeStep * m_UInfinity;
11086 m_periodicGhostBodyDist =
11088 * (m_outerBandWidth[
mMin(maxUniformRefinementLevel(), maxRefinementLevel() - 1)]
11089 + ((
MFloat)noHaloLayers()) * c_cellLengthAtLevel(minLevel()) + m_maxBodyRadius + maxDispl);
11091 m_periodicGhostBodyDist =
11092 1.1 * (((
MFloat)noHaloLayers()) * c_cellLengthAtLevel(minLevel()) + m_maxBodyRadius + maxDispl);
11098 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
11099 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
11100 if(a_bndryId(cellId) < -1)
continue;
11101 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
11102 const MFloat a = sysEqn().speedOfSound(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
11103 for(
MInt i = 0; i < nDim; i++) {
11104 cflMax =
mMax(cflMax, newTimeStep * (fabs(a_pvariable(cellId, PV->VV[i])) +
a) / c_cellLengthAtCell(cellId));
11108 MPI_Allreduce(MPI_IN_PLACE, &cflMax, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"cflMax");
11109 m_log <<
"Maximum CFL number: " << cflMax <<
" (" << m_cfl <<
")" << endl;
11112 auto oldBndryCellsBak(m_oldBndryCells);
11113 m_oldBndryCells.clear();
11114 for(
auto it = oldBndryCellsBak.begin(); it != oldBndryCellsBak.end(); ++it) {
11115 const MInt cellId = it->first;
11116 const MFloat sweptVol = it->second;
11117 const MFloat sweptVolUpdate = sweptVol * (newTimeStep / m_previousTimeStep);
11118 m_oldBndryCells.insert(make_pair(cellId, sweptVolUpdate));
11122 if(m_hasExternalSource) {
11123 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
11124 if(!a_hasProperty(cellId, SolverCell::IsActive))
continue;
11125 for(
MInt var = 0; var < CV->noVariables; var++) {
11126 a_externalSource(cellId, var) *= m_previousTimeStep / newTimeStep;
11137template <MInt nDim,
class SysEqn>
11142 for(
MInt dir0 = 0; dir0 < m_noDirs; dir0++) {
11143 MInt nghbrId0 = -1;
11145 if(a_hasNeighbor(cellId, dir0) > 0)
11146 nghbrId0 = c_neighborId(cellId, dir0);
11147 else if(c_parentId(cellId) > -1)
11148 if(a_hasNeighbor(c_parentId(cellId), dir0) > 0) nghbrId0 = c_neighborId(c_parentId(cellId), dir0);
11150 if(nghbrId0 < 0)
continue;
11152 if(c_noChildren(nghbrId0) > 0) {
11153 for(
MInt child = 0; child < m_noCellNodes; child++) {
11154 if(!childCode[dir0][child])
continue;
11155 if(c_childId(nghbrId0, child) > -1) nghbrs.insert(c_childId(nghbrId0, child));
11158 nghbrs.insert(nghbrId0);
11160 for(
MInt dir1 = 0; dir1 < m_noDirs; dir1++) {
11161 if((dir1 / 2) == (dir0 / 2))
continue;
11163 MInt nghbrId1 = -1;
11165 if(a_hasNeighbor(nghbrId0, dir1) > 0)
11166 nghbrId1 = c_neighborId(nghbrId0, dir1);
11167 else if(c_parentId(nghbrId0) > -1)
11168 if(a_hasNeighbor(c_parentId(nghbrId0), dir1) > 0) nghbrId1 = c_neighborId(c_parentId(nghbrId0), dir1);
11170 if(nghbrId1 < 0)
continue;
11172 if(c_noChildren(nghbrId1) > 0) {
11173 for(
MInt child = 0; child < m_noCellNodes; child++) {
11174 if(!childCode[dir0][child] || !childCode[dir1][child])
continue;
11175 if(c_childId(nghbrId1, child) > -1) nghbrs.insert(c_childId(nghbrId1, child));
11178 nghbrs.insert(nghbrId1);
11179 IF_CONSTEXPR(nDim == 3) {
11180 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
11181 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
11182 MInt nghbrId2 = -1;
11183 if(a_hasNeighbor(nghbrId1, dir2) > 0)
11184 nghbrId2 = c_neighborId(nghbrId1, dir2);
11185 else if(c_parentId(nghbrId1) > -1)
11186 if(a_hasNeighbor(c_parentId(nghbrId1), dir2) > 0) nghbrId2 = c_neighborId(c_parentId(nghbrId1), dir2);
11187 if(nghbrId2 < 0)
continue;
11189 if(c_noChildren(nghbrId2) > 0) {
11190 for(
MInt child = 0; child < m_noCellNodes; child++) {
11191 if(!childCode[dir0][child] || !childCode[dir1][child] || !childCode[dir2][child])
continue;
11192 if(c_childId(nghbrId2, child) > -1) nghbrs.insert(c_childId(nghbrId2, child));
11195 nghbrs.insert(nghbrId2);
11200 set<MInt>::iterator it = nghbrs.begin();
11201 for(it = nghbrs.begin(); it != nghbrs.end(); it++) {
11202 ASSERT(cnt < 27 * m_noCellNodes,
"");
11203 adjacentCells[cnt] = *it;
11214template <MInt nDim,
class SysEqn>
11216 constexpr MInt offs[3] = {1, 3, 9};
11217 auto nbIdx0 = [&]() {
return 13; };
11218 auto nbIdx1 = [&](
MInt dir0,
MInt sign0) {
return nbIdx0() + offs[dir0] * sign0; };
11220 return nbIdx0() + offs[dir0] * sign0 + offs[dir1] * sign1;
11222 std::fill_n(nghbrs, 27, -1);
11223 nghbrs[nbIdx0()] = cellId;
11225 for(
MInt dir0 = 0; dir0 < m_noDirs; dir0++) {
11226 MInt nghbrId0 = -1;
11228 if(a_hasNeighbor(cellId, dir0) > 0) {
11229 nghbrId0 = c_neighborId(cellId, dir0);
11232 if(nghbrId0 < 0)
continue;
11234 MInt sign0 = (dir0 % 2 == 0) ? -1 : 1;
11235 ASSERT(nghbrs[nbIdx1(dir0 / 2, sign0)] == -1 || nghbrs[nbIdx1(dir0 / 2, sign0)] == nghbrId0,
"");
11236 nghbrs[nbIdx1(dir0 / 2, sign0)] = nghbrId0;
11238 for(
MInt dir1 = 0; dir1 < m_noDirs; dir1++) {
11239 if((dir1 / 2) == (dir0 / 2))
continue;
11240 MInt nghbrId1 = -1;
11241 if(a_hasNeighbor(nghbrId0, dir1) > 0) {
11242 nghbrId1 = c_neighborId(nghbrId0, dir1);
11244 if(nghbrId1 < 0)
continue;
11245 MInt sign1 = (dir1 % 2 == 0) ? -1 : 1;
11246 ASSERT(nghbrs[nbIdx2(dir0 / 2, sign0, dir1 / 2, sign1)] == -1
11247 || nghbrs[nbIdx2(dir0 / 2, sign0, dir1 / 2, sign1)] == nghbrId1,
11249 nghbrs[nbIdx2(dir0 / 2, sign0, dir1 / 2, sign1)] = nghbrId1;
11250 IF_CONSTEXPR(nDim == 3) {
11252 return nbIdx0() + offs[ldir0] * lsign0 + offs[ldir1] * lsign1 + offs[ldir2] * lsign2;
11254 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
11255 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
11256 MInt nghbrId2 = -1;
11257 if(a_hasNeighbor(nghbrId1, dir2) > 0) {
11258 nghbrId2 = c_neighborId(nghbrId1, dir2);
11260 if(nghbrId2 < 0)
continue;
11261 MInt sign2 = (dir2 % 2 == 0) ? -1 : 1;
11262 ASSERT(nghbrs[nbIdx3(dir0 / 2, sign0, dir1 / 2, sign1, dir2 / 2, sign2)] == -1
11263 || nghbrs[nbIdx3(dir0 / 2, sign0, dir1 / 2, sign1, dir2 / 2, sign2)] == nghbrId2,
11265 nghbrs[nbIdx3(dir0 / 2, sign0, dir1 / 2, sign1, dir2 / 2, sign2)] = nghbrId2;
11271 return (std::count_if(nghbrs, nghbrs + 27, [](
const MInt&
a) {
return (
a > -1); }));
11279template <MInt nDim,
class SysEqn>
11284 for(
MInt dir0 = 0; dir0 < m_noDirs; dir0++) {
11285 if(a_hasNeighbor(cellId, dir0) == 0)
continue;
11287 const MInt nghbrId0 = c_neighborId(cellId, dir0);
11289 if(nghbrId0 < 0)
continue;
11291 if(a_hasProperty(nghbrId0, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId0, SolverCell::IsInactive)
11292 && !a_isBndryGhostCell(nghbrId0)) {
11293 adjacentCells[cnt] = nghbrId0;
11296 for(
MInt dir1 = 0; dir1 < m_noDirs; dir1++) {
11297 if((dir1 / 2) == (dir0 / 2))
continue;
11298 if(a_hasNeighbor(nghbrId0, dir1) == 0)
continue;
11299 const MInt nghbrId1 = c_neighborId(nghbrId0, dir1);
11300 if(nghbrId1 < 0)
continue;
11301 if(a_hasProperty(nghbrId1, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId1, SolverCell::IsInactive)
11302 && !a_isBndryGhostCell(nghbrId1))
11303 nghbrs.insert(nghbrId1);
11304#ifdef __REMOVE_TO_USE__
11305 IF_CONSTEXPR(nDim == 3) {
11306 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
11307 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
11308 if(a_hasNeighbor(nghbrId1, dir2) == 0)
continue;
11309 const MInt nghbrId2 = c_neighborId(nghbrId1, dir2);
11310 if(nghbrId2 < 0)
continue;
11311 if(a_hasProperty(nghbrId2, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId2, SolverCell::IsInactive)
11312 && !a_isBndryGhostCell(nghbrId2))
11313 nghbrs.insert(nghbrId2);
11319 set<MInt>::iterator it = nghbrs.begin();
11320 for(it = nghbrs.begin(); it != nghbrs.end(); it++) {
11321 adjacentCells[cnt] = *it;
11332template <MInt nDim,
class SysEqn>
11336 for(
MInt dir0 = 0; dir0 < m_noDirs; dir0++) {
11337 MInt nghbrId0 = -1;
11339 if(a_hasNeighbor(cellId, dir0) > 0)
11340 nghbrId0 = c_neighborId(cellId, dir0);
11341 else if(c_parentId(cellId) > -1)
11342 if(a_hasNeighbor(c_parentId(cellId), dir0) > 0) nghbrId0 = c_neighborId(c_parentId(cellId), dir0);
11344 if(nghbrId0 < 0)
continue;
11346 const MInt noC0 = c_noChildren(nghbrId0);
11348 for(
MInt c0 = 0; c0 <
mMax(1, noC0); c0++) {
11349 if(noC0 && !childCode[dir0][c0])
continue;
11350 MInt nghbrId00 = noC0 ? c_childId(nghbrId0, c0) : nghbrId0;
11351 if(nghbrId00 < 0)
continue;
11352 if(a_hasProperty(nghbrId00, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId00, SolverCell::IsInactive)
11353 && !a_isBndryGhostCell(nghbrId00)) {
11354 nghbrs.insert(nghbrId00);
11356 for(
MInt dir1 = 0; dir1 < m_noDirs; dir1++) {
11357 if((dir1 / 2) == (dir0 / 2))
continue;
11358 MInt nghbrId1 = -1;
11359 if(a_hasNeighbor(nghbrId00, dir1) > 0)
11360 nghbrId1 = c_neighborId(nghbrId00, dir1);
11361 else if(c_parentId(nghbrId00) > -1)
11362 if(a_hasNeighbor(c_parentId(nghbrId00), dir1) > 0) nghbrId1 = c_neighborId(c_parentId(nghbrId00), dir1);
11363 if(nghbrId1 < 0)
continue;
11364 const MInt noC1 = c_noChildren(nghbrId1);
11365 for(
MInt c1 = 0; c1 <
mMax(1, noC1); c1++) {
11366 if(noC1 && !childCode[dir1][c1])
continue;
11367 MInt nghbrId11 = noC1 ? c_childId(nghbrId1, c1) : nghbrId1;
11368 if(nghbrId11 < 0)
continue;
11369 MBool facing =
true;
11370 for(
MInt i = 0; i < nDim; i++) {
11371 if(fabs(a_coordinate(cellId, i) - a_coordinate(nghbrId00, i))
11372 > ((F1 + 1e-8) * c_cellLengthAtLevel(a_level(cellId))
11373 + (F1 + 1e-8) * c_cellLengthAtLevel(a_level(nghbrId00))))
11376 if(!facing)
continue;
11377 if(a_hasProperty(nghbrId11, SolverCell::IsOnCurrentMGLevel)
11378 && !a_hasProperty(nghbrId11, SolverCell::IsInactive) && !a_isBndryGhostCell(nghbrId11)) {
11379 nghbrs.insert(nghbrId11);
11382#ifdef __REMOVE_TO_USE__
11383 IF_CONSTEXPR(nDim == 3) {
11384 mTerm(1, AT_,
"TODO");
11385 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
11386 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
11387 if(a_hasNeighbor(nghbrId1, dir2) == 0)
continue;
11388 const MInt nghbrId2 = c_neighborId(nghbrId1, dir2);
11389 if(nghbrId2 < 0)
continue;
11390 if(a_hasProperty(nghbrId2, SolverCell::IsOnCurrentMGLevel)
11391 && !a_hasProperty(nghbrId2, SolverCell::IsInactive) && !a_isBndryGhostCell(nghbrId2))
11392 nghbrs.insert(nghbrId2);
11402 for(set<MInt>::iterator it = nghbrs.begin(); it != nghbrs.end(); it++) {
11403 adjacentCells[cnt] = *it;
11414template <MInt nDim,
class SysEqn>
11416 MInt cnt = getAdjacentCells(cellId, adjacentCells);
11419 for(
MInt dir0 = 0; dir0 < m_noDirs; dir0++) {
11420 if(a_hasNeighbor(cellId, dir0) == 0)
continue;
11421 const MInt nghbrId00 = c_neighborId(cellId, dir0);
11422 if(a_hasNeighbor(nghbrId00, dir0) == 0)
continue;
11423 const MInt nghbrId0 = c_neighborId(nghbrId00, dir0);
11424 if(nghbrId0 < 0)
continue;
11425 if(a_hasProperty(nghbrId0, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId0, SolverCell::IsInactive)
11426 && !a_isBndryGhostCell(nghbrId0)) {
11427 adjacentCells[cnt] = nghbrId0;
11431 for(
MInt dir1 = 0; dir1 < m_noDirs; dir1++) {
11432 if((dir1 / 2) == (dir0 / 2))
continue;
11433 if(a_hasNeighbor(nghbrId0, dir1) == 0)
continue;
11434 const MInt nghbrId1 = c_neighborId(nghbrId0, dir1);
11435 if(nghbrId1 < 0)
continue;
11436 if(a_hasProperty(nghbrId1, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId1, SolverCell::IsInactive)
11437 && !a_isBndryGhostCell(nghbrId1))
11438 nghbrs.insert(nghbrId1);
11439#ifdef __REMOVE_TO_USE__
11440 IF_CONSTEXPR(nDim == 3) {
11441 for(
MInt dir2 = 0; dir2 < m_noDirs; dir2++) {
11442 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2)))
continue;
11443 if(a_hasNeighbor(nghbrId1, dir2) == 0)
continue;
11444 const MInt nghbrId2 = c_neighborId(nghbrId1, dir2);
11445 if(nghbrId2 < 0)
continue;
11446 if(a_hasProperty(nghbrId2, SolverCell::IsOnCurrentMGLevel) && !a_hasProperty(nghbrId2, SolverCell::IsInactive)
11447 && !a_isBndryGhostCell(nghbrId2))
11448 nghbrs.insert(nghbrId2);
11454 set<MInt>::iterator it = nghbrs.begin();
11455 for(it = nghbrs.begin(); it != nghbrs.end(); it++) {
11456 adjacentCells[cnt] = *it;
11467template <MInt nDim,
class SysEqn>
11471 mTerm(1, AT_,
"deprecated, ghost cells are not anticipated for memory efficiency.");
11473 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
11474 const MInt cellId = m_bndryLayerCells[c];
11476 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
11477 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
11478 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
11479 if(a_isBndryGhostCell(cellId))
continue;
11480 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
11481 if(a_bndryId(cellId) < -1)
continue;
11482 if(c_noChildren(cellId) > 0)
continue;
11484 const MInt bndryId = a_bndryId(cellId);
11485 MFloatScratchSpace dummyPvariables(m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs, PV->noVariables, AT_,
11486 "dummyPvariables");
11487 for(
MInt set = m_startSet; set < m_noSets; set++) {
11488 if(a_associatedBodyIds(cellId, set) < 0)
continue;
11490 const MInt ghostCellId = -1;
11492 if(ghostCellId < 0)
continue;
11493 const MInt bodyId = a_associatedBodyIds(cellId, set);
11495 cerr <<
"Warning: no associated body" << endl;
11498 const MFloat phi = a_levelSetValuesMb(cellId, set);
11499 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
11500 MFloat vel[3] = {F0, F0, F0};
11501 MFloat xsurf[3] = {F0, F0, F0};
11502 MFloat normal[3] = {F0, F0, F0};
11504 if(bndryId >= m_noOuterBndryCells) {
11505 for(
MInt s = 0; s < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; s++) {
11506 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[s]->m_bodyId[0] == bodyId) {
11511 if(srfc < 0 && m_noLevelSetsUsedForMb == 1)
mTerm(1, AT_,
"srfc not found.");
11514 for(
MInt i = 0; i < nDim; i++) {
11515 normal[i] = m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVectorCentroid[i];
11518 for(
MInt i = 0; i < nDim; i++) {
11519 vel[i] = m_bodyVelocity[bodyId * nDim + i];
11520 xsurf[i] = a_coordinate(cellId, i) - phi * normal[i];
11523 MFloat dx[3] = {F0, F0, F0};
11524 MFloat omega[3] = {F0, F0, F0};
11526 for(
MInt i = 0; i < nDim; i++) {
11527 dx[i] = xsurf[i] - m_bodyCenter[bodyId * nDim + i];
11530 for(
MInt i = 0; i < 3; i++) {
11531 omega[i] = m_bodyAngularVelocity[bodyId * 3 + i];
11534 vel[0] += omega[1] * dx[2] - omega[2] * dx[1];
11535 vel[1] += omega[2] * dx[0] - omega[0] * dx[2];
11536 IF_CONSTEXPR(nDim == 3) { vel[2] += omega[0] * dx[1] - omega[1] * dx[0]; }
11540 for(
MInt i = 0; i < nDim; i++) {
11541 vel2[i] = a_pvariable(cellId, PV->VV[i]);
11542 for(
MInt j = 0; j < nDim; j++) {
11543 vel2[i] += m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i]
11544 * (vel[i] - a_pvariable(cellId, PV->VV[j]))
11545 * m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[j];
11548 for(
MInt i = 0; i < nDim; i++) {
11554 for(
MInt i = 0; i < nDim; i++) {
11555 imageVel[i] = a_pvariable(cellId, PV->VV[i]);
11557 if(bndryId >= m_noOuterBndryCells && srfc > -1) {
11558 for(
MInt s = 0; s <
mMin((
signed)m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size(),
11559 m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs);
11561 for(
MInt i = 0; i < nDim; i++) {
11562 dummyPvariables(s, PV->VV[i]) = vel[i];
11565 for(
MInt i = 0; i < nDim; i++) {
11568 for(
MInt n = 0; n < (signed)m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size(); n++) {
11569 const MInt nghbrId = m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n];
11570 for(
MInt i = 0; i < nDim; i++) {
11571 const MFloat nghbrPvariable = (n < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs)
11572 ? dummyPvariables(n, PV->VV[i])
11573 : a_pvariable(nghbrId, PV->VV[i]);
11575 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_imagePointRecConst[n] * nghbrPvariable;
11578 MFloat vf = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
11580 for(
MInt i = 0; i < nDim; i++) {
11581 imageVel[i] = (fac * a_pvariable(cellId, PV->VV[i]) + (F1 - fac) * imageVel[i]);
11586 for(
MInt i = 0; i < nDim; i++) {
11587 a_pvariable(ghostCellId, PV->VV[i]) = F2 * vel[i] - imageVel[i];
11592 for(
MInt i = 0; i < nDim; i++) {
11593 dn += (a_coordinate(cellId, i) - a_coordinate(ghostCellId, i)) * normal[i];
11596 if(dn + phi < 1e-8) {
11597 cerr << domainId() <<
": warning very small distance " << c_globalId(cellId) <<
" " << phi <<
" " << dn << endl;
11600 MFloat delta[3] = {F0, F0, F0};
11601 MFloat dr[3] = {F0, F0, F0};
11602 MFloat dw[3] = {F0, F0, F0};
11603 MFloat dg[3] = {F0, F0, F0};
11604 MFloat du[3] = {F0, F0, F0};
11605 MFloat dv[3] = {F0, F0, F0};
11606 for(
MInt i = 0; i < nDim; i++) {
11607 dr[i] = a_coordinate(cellId, i) - phi * normal[i] - m_bodyCenter[bodyId * nDim + i];
11608 du[i] = m_bodyAcceleration[bodyId * nDim + i];
11609 dv[i] = vel[i] - m_bodyVelocity[bodyId * nDim + i];
11611 for(
MInt i = 0; i < 3; i++) {
11612 dw[i] = m_bodyAngularAcceleration[bodyId * 3 + i];
11613 dg[i] = m_bodyAngularVelocity[bodyId * 3 + i];
11616 delta[0] = du[0] + dw[1] * dr[2] - dw[2] * dr[1] + dg[1] * dv[2] - dg[2] * dv[1];
11617 delta[1] = du[1] + dw[2] * dr[0] - dw[0] * dr[2] + dg[2] * dv[0] - dg[0] * dv[2];
11618 delta[2] = du[2] + dw[0] * dr[1] - dw[1] * dr[0] + dg[0] * dv[1] - dg[1] * dv[0];
11621 for(
MInt i = 0; i < nDim; i++) {
11622 an += normal[i] * delta[i];
11625 MFloat surfTemp = sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
11626 const MFloat beta = sysEqn().density_ES(an, surfTemp);
11627 const MFloat fac = (F1 + F1B2 * beta * (dn + phi)) / (F1 - F1B2 * beta * (dn + phi));
11629 a_pvariable(ghostCellId, PV->P) = fac * a_pvariable(cellId, PV->P);
11630 a_pvariable(ghostCellId, PV->RHO) = fac * a_pvariable(cellId, PV->RHO);
11640template <MInt nDim,
class SysEqn>
11644 const MInt recDim = (m_orderOfReconstruction == 2) ? (
IPOW2(nDim) + 1) : nDim;
11652#if defined _MB_DEBUG_ || !defined NDEBUG
11659 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
11660 const MInt cellId = m_bndryLayerCells[c];
11661 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
11662 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
11663 a_hasProperty(cellId, SolverCell::IsFlux) =
true;
11664 a_noReconstructionNeighbors(cellId) = 0;
11668 for(
MUint c = 0; c < m_bndryLayerCells.size(); c++) {
11669 const MInt cellId = m_bndryLayerCells[c];
11670 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
11671 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
11672 if(a_isBndryGhostCell(cellId))
continue;
11673 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
11674 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
11675 if(a_bndryId(cellId) < -1)
continue;
11676 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
11677 ASSERT(a_noReconstructionNeighbors(cellId) == 0,
11678 to_string(cellId) +
" " + to_string(c) +
" " + to_string(a_noReconstructionNeighbors(cellId)));
11680 const MInt bndryId = a_bndryId(cellId);
11683 if(bndryId >= m_noOuterBndryCells) {
11684 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
11685 const MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
11686 ASSERT(ghostCellId > -1,
"");
11687 a_reconstructionNeighborId(cellId, a_noReconstructionNeighbors(cellId)) = ghostCellId;
11688 a_noReconstructionNeighbors(cellId)++;
11692 const MInt rootCell =
11693 (a_hasProperty(cellId, SolverCell::IsSplitChild)) ? getAssociatedInternalCell(cellId) : cellId;
11694 ASSERT(rootCell > -1 && rootCell < a_noCells(),
"");
11701 MInt noactiveNeighbors = 1;
11702 if(!m_bndryLevelJumps && !m_dynamicStencil) {
11703 counter = this->
template getAdjacentLeafCells<2, true>(rootCell, 1, nghbrList, layerId);
11712 counter = this->
template getAdjacentLeafCells<2, true>(rootCell, 1, nghbrList, layerId);
11714 if(m_engineSetup) {
11715 noactiveNeighbors = a_noReconstructionNeighbors(cellId);
11717 for(
MInt n = 0; n < counter; n++) {
11718 const MInt nghbrId = nghbrList[n];
11719 if(nghbrId < 0)
continue;
11720 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
11721 noactiveNeighbors++;
11723 if(noactiveNeighbors > m_cells.noRecNghbrs() - 1) {
11724 counter = this->
template getAdjacentLeafCells<0, true>(rootCell, 1, nghbrList, layerId);
11729 for(
MInt n = 0; n < counter; n++) {
11730 const MInt nghbrId = nghbrList[n];
11731 if(nghbrId < 0)
continue;
11732 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
11733 if(a_noReconstructionNeighbors(cellId) < m_cells.noRecNghbrs()) {
11734 a_reconstructionNeighborId(cellId, a_noReconstructionNeighbors(cellId)) = nghbrId;
11735 a_noReconstructionNeighbors(cellId)++;
11737 cerr <<
"Warning: too many reconstruction neighbors for cell " << cellId;
11738 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
11741 cerr <<
"/" << c_globalId(cellId);
11743 cerr <<
" " << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" " << a_coordinate(cellId, 2)
11744 <<
" " << a_noReconstructionNeighbors(cellId) <<
"/" << counter << endl;
11749 const MInt offset = m_cells.noRecNghbrs() * cellId;
11752 const MInt mode = (m_fvBndryCnd->m_cbcSmallCellCorrection && a_hasProperty(cellId, SolverCell::IsCutOff))
11754 : m_reConstSVDWeightMode;
11755 MFloat condNum = computeRecConstSVD(cellId, offset, tmpA, tmpC, weights, recDim, mode, 1);
11759 if((condNum < F0 || condNum > 1e6 || std::isnan(condNum))) {
11760#if defined _MB_DEBUG_ || !defined NDEBUG
11762 const MFloat vf = (a_bndryId(cellId) > -1) ? m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_volume
11763 / grid().gridCellVolume(a_level(cellId))
11766 cerr << domainId() <<
" " <<
globalTimeStep <<
" recompute stencil for cell " << cellId <<
"/"
11767 << c_globalId(cellId) <<
" level " << a_level(cellId) <<
" vol "
11768 << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) <<
" " << vf <<
" cond " << condNum <<
" "
11774 if(a_noReconstructionNeighbors(cellId) > m_cells.noRecNghbrs()) {
11775 mTerm(1, AT_,
"Error in buildAdditionalReconstructionStencil too many rec neighbors.");
11778#if defined _MB_DEBUG_ || !defined NDEBUG
11780 maxCnd =
mMax(maxCnd, condNum);
11785 m_reconstructionDataSize = 0;
11786 a_reconstructionData(a_noCells()) = -1;
11788#if defined _MB_DEBUG_ || !defined NDEBUG
11790 MPI_Allreduce(MPI_IN_PLACE, &maxCnd, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"maxCnd");
11791 MPI_Allreduce(MPI_IN_PLACE, &avgCnd, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"avgCnd");
11792 MPI_Allreduce(MPI_IN_PLACE, &cntCnd, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"cntCnd");
11794 m_log <<
"Singular value decomposition: near-boundary maximum/average condition number: " << maxCnd <<
"/"
11795 << avgCnd / cntCnd << endl;
11805template <MInt nDim,
class SysEqn>
11807 if(noNeighborDomains() == 0) {
11808 if(noDomains() > 1)
mTerm(1, AT_,
"Unexpected situation in updateMultiSolverInformation");
11818 mAlloc(g_mpiRequestMb, noNeighborDomains(),
"g_mpiRequestMb", MPI_REQ_NULL, AT_);
11819 mAlloc(m_linkedWindowCells, noNeighborDomains(),
"m_linkedWindowCells", AT_);
11820 mAlloc(m_linkedHaloCells, noNeighborDomains(),
"m_linkedHaloCells", AT_);
11821 mAlloc(m_gapWindowCells, noNeighborDomains(),
"m_gapWindowCells", AT_);
11822 mAlloc(m_gapHaloCells, noNeighborDomains(),
"m_gapHaloCells", AT_);
11833template <MInt nDim,
class SysEqn>
11837 ASSERT(!m_onlineRestart,
"");
11840 if(!isActive())
return;
11842 const MFloat time0 = MPI_Wtime();
11845 if(m_constructGField) {
11846 if(m_initialCondition == 465) {
11847 m_initialCondition = -1;
11848 setInfinityState();
11849 m_initialCondition = 465;
11854 initBodyProperties();
11858 initializeRungeKutta();
11862 initBodyProperties();
11863 if(m_geometryChange ==
nullptr) {
11864 loadBodyRestartFile(0);
11866 loadBodyRestartFile(2);
11870 applyInitialCondition();
11871 for(
MInt cellId = a_noCells(); cellId--;) {
11872 setPrimitiveVariables(cellId);
11877 if(this->m_zonal) {
11878 resetZonalSolverData();
11879 if(this->m_STGSponge) this->initSTGSponge();
11881 if(this->m_resetInitialCondition && m_solverId == this->m_zonalRestartInterpolationSolverId) {
11882 if(domainId() == 0) cerr <<
"resetInitialCondition: loadRestartFile for solver " << m_solverId << endl;
11887 if(grid().azimuthalPeriodicity()) initAzimuthalCartesianHaloInterpolation();
11890 if(noNeighborDomains() > 0) {
11891 exchangeDataFV(&a_variable(0, 0), m_noCVars,
false, m_rotIndVarsCV);
11892 if(m_restartOldVariables) {
11893 exchangeDataFV(&a_oldVariable(0, 0), m_noCVars,
false, m_rotIndVarsCV);
11895 exchangeDataFV(&a_pvariable(0, 0), m_noPVars,
false, m_rotIndVarsPV);
11896 exchangeData(&a_cellVolume(0), 1);
11899 const MFloat time1 = MPI_Wtime();
11901 if(domainId() == 0)
m_log <<
"Init solution time " << time1 - time0 << endl;
11909template <MInt nDim,
class SysEqn>
11914 if(!isActive())
return;
11917 ASSERT(!m_onlineRestart,
"");
11918 initSolutionStep(-1);
11921 applyInitialCondition();
11926 reInitActiveCellIdsMemory();
11929 determineLESAverageCells();
11930 resetZonalLESAverage();
11933 writeListOfActiveFlowCells();
11939 preSolutionStep(1);
11942 initCutOffBoundaryCondition();
11943 cutOffBoundaryCondition();
11944 if(grid().azimuthalPeriodicity()) {
11945 exchangeFloatDataAzimuthal(&a_pvariable(0, 0), PV->noVariables, m_rotIndVarsPV);
11948 if(!m_levelSetRans && !m_standardRK) {
11951 prepareNextTimeStep();
11961template <MInt nDim,
class SysEqn>
11964 setAdditionalCellProperties();
11972template <MInt nDim,
class SysEqn>
11982template <MInt nDim,
class SysEqn>
11984 const MFloat epsilon = 1e-12;
11990 for(
MInt i = 0; i < nDim; i++) {
11991 for(
MInt j = 0; j < nDim; j++) {
11992 m_A[i][nDim + j] = F0;
11994 m_A[i][nDim + i] = F1;
12001 maximum = fabs(m_A[s][s]);
12003 for(
MInt i = s + 1; i < nDim; i++) {
12004 if(fabs(m_A[i][s]) > maximum) {
12005 maximum = fabs(m_A[i][s]);
12010 if(maximum < epsilon) {
12016 for(
MInt j = s; j < 2 * nDim; j++) {
12018 m_A[s][j] = m_A[pRow][j];
12024 for(
MInt j = s; j < 2 * nDim; j++)
12028 for(
MInt i = 0; i < nDim; i++) {
12031 for(
MInt j = s; j < 2 * nDim; j++)
12032 m_A[i][j] += f * m_A[s][j];
12039 cerr <<
"Domain " << domainId() << endl;
12040 cerr <<
"Error in GJ matrix inverse computation " << s <<
" " << m_A[s][s] << endl;
12041 for(
MInt i = 0; i < nDim; i++) {
12042 for(
MInt j = 0; j < nDim; j++) {
12043 cerr << m_A[i][j] <<
" ";
12058template <MInt nDim,
class SysEqn>
12062 exchangeDataFV(&(a_levelSetValuesMb(0, 0)), m_noLevelSetsUsedForMb);
12063 exchangeDataFV(&(a_associatedBodyIds(0, 0)), m_noLevelSetsUsedForMb);
12073template <MInt nDim,
class SysEqn>
12074template <MInt timeStepMethod>
12078 MFloat dt = m_RKalpha[m_RKStep] * timeStep();
12079 const MInt xdim = a_noCells();
12080 const MInt ydim = m_noCVars;
12082 MFloat* RESTRICT cVars = (
MFloat*)(&(a_variable(0, 0)));
12083 MFloat* RESTRICT oCVars = (
MFloat*)(&(a_oldVariable(0, 0)));
12084 MFloat* RESTRICT RHS = (
MFloat*)(&(a_rightHandSide(0, 0)));
12085 MFloat* RESTRICT vol1 = (
MFloat*)(&(m_cellVolumesDt1[0]));
12086 MFloat* RESTRICT fVol = (
MFloat*)(&(a_FcellVolume(0)));
12088 for(
MUint it = 0; it < m_temporarilyLinkedCells.size(); it++) {
12089 const MInt cellId = get<0>(m_temporarilyLinkedCells[it]);
12090 const MInt masterId = get<1>(m_temporarilyLinkedCells[it]);
12091 const MInt tripleLink = get<2>(m_temporarilyLinkedCells[it]);
12093 if(tripleLink < 0) {
12094 MFloat fac0 = a_cellVolume(cellId) / (a_cellVolume(cellId) + a_cellVolume(masterId));
12095 MFloat fac1 = F1 - fac0;
12096 for(
MInt v = 0; v < m_noCVars; v++) {
12098 (fac1 * vol1[cellId] * oCVars[ydim * cellId + v] - fac0 * vol1[masterId] * oCVars[ydim * masterId + v])
12100 + fac0 * a_rightHandSide(masterId, v) - fac1 * a_rightHandSide(cellId, v);
12102 a_rightHandSide(cellId, v) += delta;
12103 a_rightHandSide(masterId, v) -= delta;
12106 mTerm(1, AT_,
"Not implemented yet!");
12108 a_cellVolume(cellId) / (a_cellVolume(cellId) + a_cellVolume(tripleLink) + a_cellVolume(masterId));
12110 a_cellVolume(tripleLink) / (a_cellVolume(cellId) + a_cellVolume(tripleLink) + a_cellVolume(masterId));
12111 const MFloat fac2 = F1 - fac0 - fac1;
12112 for(
MInt v = 0; v < m_noCVars; v++) {
12114 (fac2 * vol1[
cellId] * oCVars[ydim *
cellId + v] - fac0 * vol1[masterId] * oCVars[ydim * masterId + v])
12116 + fac0 * a_rightHandSide(masterId, v) - fac1 * a_rightHandSide(cellId, v);
12118 a_rightHandSide(cellId, v) += delta;
12119 a_rightHandSide(masterId, v) -= delta;
12124 for(
MInt i = xdim; i--;) {
12125 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
12129 if(a_isBndryGhostCell(i)) {
12133 IF_CONSTEXPR(timeStepMethod == 1) {
12134 ASSERT(a_localTimeStep(i) < std::numeric_limits<MFloat>::max() && a_localTimeStep(i) > 0,
12135 "Invalid local time-step for " + to_string(i) +
" " + to_string(xdim));
12136 dt = m_RKalpha[m_RKStep] * a_localTimeStep(i);
12139 cVars[ydim * i + 0] = fVol[i] * (vol1[i] * oCVars[ydim * i + 0] - dt * RHS[ydim * i + 0]);
12140 cVars[ydim * i + 1] = fVol[i] * (vol1[i] * oCVars[ydim * i + 1] - dt * RHS[ydim * i + 1]);
12141 cVars[ydim * i + 2] = fVol[i] * (vol1[i] * oCVars[ydim * i + 2] - dt * RHS[ydim * i + 2]);
12142 cVars[ydim * i + 3] = fVol[i] * (vol1[i] * oCVars[ydim * i + 3] - dt * RHS[ydim * i + 3]);
12143 IF_CONSTEXPR(nDim == 3) {
12144 cVars[ydim * i + 4] = fVol[i] * (vol1[i] * oCVars[ydim * i + 4] - dt * RHS[ydim * i + 4]);
12148 cVars[ydim * i + 0] = oCVars[ydim * i + 0] - dt * fVol[i] * RHS[ydim * i + 0];
12149 cVars[ydim * i + 1] = oCVars[ydim * i + 1] - dt * fVol[i] * RHS[ydim * i + 1];
12150 cVars[ydim * i + 2] = oCVars[ydim * i + 2] - dt * fVol[i] * RHS[ydim * i + 2];
12151 cVars[ydim * i + 3] = oCVars[ydim * i + 3] - dt * fVol[i] * RHS[ydim * i + 3];
12152 IF_CONSTEXPR(nDim == 3) { cVars[ydim * i + 4] = oCVars[ydim * i + 4] - dt * fVol[i] * RHS[ydim * i + 4]; }
12158 updateSplitParentVariables();
12160 if(m_RKStep < m_noRKSteps) {
12178template <MInt nDim,
class SysEqn>
12179template <MInt timeStepMethod>
12183 NEW_TIMER_GROUP_STATIC(t_initTimer,
"RK");
12184 NEW_TIMER_STATIC(t_timertotal,
"RK", t_initTimer);
12185 NEW_SUB_TIMER_STATIC(t_init,
"init", t_timertotal);
12186 NEW_SUB_TIMER_STATIC(t_exec,
"exec", t_timertotal);
12187 NEW_SUB_TIMER_STATIC(t_finalize,
"finalize", t_timertotal);
12188 RECORD_TIMER_START(t_timertotal);
12189 RECORD_TIMER_START(t_init);
12191 MFloat* RESTRICT cVars = (
MFloat*)(&(a_variable(0, 0)));
12192 MFloat* RESTRICT oCVars = (
MFloat*)(&(a_oldVariable(0, 0)));
12193 MFloat* RESTRICT RHS = (
MFloat*)(&(a_rightHandSide(0, 0)));
12195 MFloat* RESTRICT fVol = (
MFloat*)(&(a_FcellVolume(0)));
12196 MFloat* RESTRICT vol1 = (
MFloat*)(&(m_cellVolumesDt1[0]));
12197 const MInt xdim = noInternalCells();
12198 const MInt ydim = m_noCVars;
12202 const MInt gId = -1;
12205#ifdef GEOM_CONS_LAW
12206 if(m_gclIntermediate) {
12207 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
12208 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
12209 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
12210 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
12212 const MFloat deltaVol = (m_RKStep == 0) ? m_sweptVolumeDt1[bndryId]
12213 : m_RKalpha[m_RKStep - 1] * m_sweptVolume[bndryId]
12214 + (F1 - m_RKalpha[m_RKStep - 1]) * m_sweptVolumeDt1[bndryId];
12215 a_cellVolume(cellId) = m_cellVolumesDt1[
cellId] + deltaVol;
12217 const MFloat V0 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume - 0.1 * grid().gridCellVolume(a_level(cellId));
12218 const MFloat V1 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume + 0.1 * grid().gridCellVolume(a_level(cellId));
12219 a_cellVolume(cellId) =
mMin(V1,
mMax(V0, a_cellVolume(cellId)));
12221 a_cellVolume(cellId) =
mMax(a_cellVolume(cellId), m_volumeThreshold);
12222 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
12227 RECORD_TIMER_STOP(t_init);
12228 RECORD_TIMER_START(t_exec);
12231 const MFloat beta1 = m_RKalpha[m_RKStep - 1];
12232 const MFloat beta0 = F1 - beta1;
12234 for(
MInt i = xdim; i--;) {
12235 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
12237 IF_CONSTEXPR(timeStepMethod == 1) { dt = timeStep() *
FPOW2(maxLevel() - a_level(i)); }
12239 cVars[ydim * i + 0] =
12240 fVol[i] * (vol1[i] * oCVars[ydim * i + 0] - dt * (beta1 * RHS[ydim * i + 0] + beta0 * RHS0[ydim * i + 0]));
12241 cVars[ydim * i + 1] =
12242 fVol[i] * (vol1[i] * oCVars[ydim * i + 1] - dt * (beta1 * RHS[ydim * i + 1] + beta0 * RHS0[ydim * i + 1]));
12243 cVars[ydim * i + 2] =
12244 fVol[i] * (vol1[i] * oCVars[ydim * i + 2] - dt * (beta1 * RHS[ydim * i + 2] + beta0 * RHS0[ydim * i + 2]));
12245 cVars[ydim * i + 3] =
12246 fVol[i] * (vol1[i] * oCVars[ydim * i + 3] - dt * (beta1 * RHS[ydim * i + 3] + beta0 * RHS0[ydim * i + 3]));
12247 IF_CONSTEXPR(nDim == 3) {
12248 cVars[ydim * i + 4] =
12249 fVol[i] * (vol1[i] * oCVars[ydim * i + 4] - dt * (beta1 * RHS[ydim * i + 4] + beta0 * RHS0[ydim * i + 4]));
12251 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
12252 for(
MInt r = 0; r < m_noRansEquations; ++r) {
12253 cVars[ydim * i + 5 + r] = fVol[i]
12254 * (vol1[i] * oCVars[ydim * i + 5 + r]
12255 - dt * (beta1 * RHS[ydim * i + 5 + r] + beta0 * RHS0[ydim * i + 5 + r]));
12259 for(
MInt s = 0; s < m_noSpecies; s++)
12260 cVars[ydim * i + 5 + s + m_noRansEquations] =
12262 * (vol1[i] * oCVars[ydim * i + 5 + s + m_noRansEquations]
12264 * (beta1 * RHS[ydim * i + 5 + s + m_noRansEquations]
12265 + beta0 * RHS0[ydim * i + 5 + s + m_noRansEquations]));
12268 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
12269 for(
MInt r = 0; r < m_noRansEquations; ++r) {
12270 cVars[ydim * i + 4 + r] = fVol[i]
12271 * (vol1[i] * oCVars[ydim * i + 4 + r]
12272 - dt * (beta1 * RHS[ydim * i + 4 + r] + beta0 * RHS0[ydim * i + 4 + r]));
12276 for(
MInt s = 0; s < m_noSpecies; s++)
12277 cVars[ydim * i + 4 + s + m_noRansEquations] =
12279 * (vol1[i] * oCVars[ydim * i + 4 + s + m_noRansEquations]
12281 * (beta1 * RHS[ydim * i + 4 + s + m_noRansEquations]
12282 + beta0 * RHS0[ydim * i + 4 + s + m_noRansEquations]));
12287 if(gId > -1 && c_globalId(i) == gId)
12288 cerr <<
globalTimeStep <<
" " << m_RKStep <<
" RK update " << gId <<
" " << fVol[i] <<
" " << vol1[i] <<
" "
12289 << fVol[i] * vol1[i] <<
" / " << cVars[ydim * i + 0] <<
" " << cVars[ydim * i + 1] <<
" "
12290 << cVars[ydim * i + 2] <<
" " << cVars[ydim * i + 3] <<
" " << cVars[ydim * i + 4] <<
" / "
12291 << oCVars[ydim * i + 0] <<
" " << oCVars[ydim * i + 1] <<
" " << oCVars[ydim * i + 2] <<
" "
12292 << oCVars[ydim * i + 3] <<
" " << oCVars[ydim * i + 4] << endl;
12297 ASSERT(m_RKStep == 0,
"");
12298 for(
MInt i = xdim; i--;) {
12299 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
12301 IF_CONSTEXPR(timeStepMethod == 1) { dt = timeStep() *
FPOW2(maxLevel() - a_level(i)); }
12303 cVars[ydim * i + 0] = fVol[i] * (vol1[i] * oCVars[ydim * i + 0] - dt * RHS0[ydim * i + 0]);
12304 cVars[ydim * i + 1] = fVol[i] * (vol1[i] * oCVars[ydim * i + 1] - dt * RHS0[ydim * i + 1]);
12305 cVars[ydim * i + 2] = fVol[i] * (vol1[i] * oCVars[ydim * i + 2] - dt * RHS0[ydim * i + 2]);
12306 cVars[ydim * i + 3] = fVol[i] * (vol1[i] * oCVars[ydim * i + 3] - dt * RHS0[ydim * i + 3]);
12307 IF_CONSTEXPR(nDim == 3) {
12308 cVars[ydim * i + 4] = fVol[i] * (vol1[i] * oCVars[ydim * i + 4] - dt * RHS0[ydim * i + 4]);
12309 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
12310 for(
MInt r = 0; r < m_noRansEquations; ++r) {
12311 cVars[ydim * i + 5 + r] = fVol[i] * (vol1[i] * oCVars[ydim * i + 5 + r] - dt * RHS0[ydim * i + 5 + r]);
12315 for(
MInt s = 0; s < m_noSpecies; s++)
12316 cVars[ydim * i + 5 + s + m_noRansEquations] = fVol[i]
12317 * (vol1[i] * oCVars[ydim * i + 5 + s + m_noRansEquations]
12318 - dt * RHS0[ydim * i + 5 + s + m_noRansEquations]);
12321 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
12322 for(
MInt r = 0; r < m_noRansEquations; ++r) {
12323 cVars[ydim * i + 4 + r] = fVol[i] * (vol1[i] * oCVars[ydim * i + 4 + r] - dt * RHS0[ydim * i + 4 + r]);
12326 for(
MInt s = 0; s < m_noSpecies; s++)
12327 cVars[ydim * i + 4 + s + m_noRansEquations] = fVol[i]
12328 * (vol1[i] * oCVars[ydim * i + 4 + s + m_noRansEquations]
12329 - dt * RHS0[ydim * i + 4 + s + m_noRansEquations]);
12332 if(gId > -1 && c_globalId(i) == gId)
12333 cerr <<
globalTimeStep <<
" " << m_RKStep <<
" RK update " << gId <<
" " << fVol[i] <<
" " << vol1[i] <<
" "
12334 << fVol[i] * vol1[i] <<
" / " << cVars[ydim * i + 0] <<
" " << cVars[ydim * i + 1] <<
" "
12335 << cVars[ydim * i + 2] <<
" " << cVars[ydim * i + 3] <<
" " << cVars[ydim * i + 4] <<
" / "
12336 << oCVars[ydim * i + 0] <<
" " << oCVars[ydim * i + 1] <<
" " << oCVars[ydim * i + 2] <<
" "
12337 << oCVars[ydim * i + 3] <<
" " << oCVars[ydim * i + 4] << endl;
12341 RECORD_TIMER_STOP(t_exec);
12342 RECORD_TIMER_START(t_finalize);
12344 updateLinkedCells();
12347 RECORD_TIMER_STOP(t_finalize);
12348 RECORD_TIMER_STOP(t_timertotal);
12350 if(m_RKStep < m_noRKSteps) {
12364template <MInt nDim,
class SysEqn>
12368 MFloat* RESTRICT cVars = (
MFloat*)(&(a_variable(0, 0)));
12369 MFloat* RESTRICT oCVars = (
MFloat*)(&(a_oldVariable(0, 0)));
12370 MFloat* RESTRICT RHS = (
MFloat*)(&(a_rightHandSide(0, 0)));
12372 MFloat* RESTRICT fVol = (
MFloat*)(&(a_FcellVolume(0)));
12373 MFloat* RESTRICT vol1 = (
MFloat*)(&(m_cellVolumesDt1[0]));
12374 const MInt xdim = noInternalCells();
12375 const MInt ydim = m_noCVars;
12378 const MInt gId = -1;
12381#ifdef GEOM_CONS_LAW
12382 if(m_gclIntermediate) {
12383 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
12384 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
12385 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
12386 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
12387 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
12388 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
12390 const MFloat deltaVol = (m_RKStep == 0) ? m_sweptVolumeDt1[bndryId]
12391 : m_RKalpha[m_RKStep - 1] * m_sweptVolume[bndryId]
12392 + (F1 - m_RKalpha[m_RKStep - 1]) * m_sweptVolumeDt1[bndryId];
12393 a_cellVolume(cellId) = m_cellVolumesDt1[
cellId] + deltaVol;
12395 const MFloat V0 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume - 0.1 * grid().gridCellVolume(a_level(cellId));
12396 const MFloat V1 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume + 0.1 * grid().gridCellVolume(a_level(cellId));
12397 a_cellVolume(cellId) =
mMin(V1,
mMax(V0, a_cellVolume(cellId)));
12399 a_cellVolume(cellId) =
mMax(a_cellVolume(cellId), m_volumeThreshold);
12400 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
12406 const MFloat beta1 = m_RKalpha[m_RKStep - 1];
12407 const MFloat beta0 = F1 - beta1;
12409 for(
MInt i = xdim; i--;) {
12410 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
12411 const MFloat dt = timeStep() *
FPOW2(maxRefinementLevel() - a_level(i));
12412 cVars[ydim * i + 0] =
12413 fVol[i] * (vol1[i] * oCVars[ydim * i + 0] - dt * (beta1 * RHS[ydim * i + 0] + beta0 * RHS0[ydim * i + 0]));
12414 cVars[ydim * i + 1] =
12415 fVol[i] * (vol1[i] * oCVars[ydim * i + 1] - dt * (beta1 * RHS[ydim * i + 1] + beta0 * RHS0[ydim * i + 1]));
12416 cVars[ydim * i + 2] =
12417 fVol[i] * (vol1[i] * oCVars[ydim * i + 2] - dt * (beta1 * RHS[ydim * i + 2] + beta0 * RHS0[ydim * i + 2]));
12418 cVars[ydim * i + 3] =
12419 fVol[i] * (vol1[i] * oCVars[ydim * i + 3] - dt * (beta1 * RHS[ydim * i + 3] + beta0 * RHS0[ydim * i + 3]));
12420 IF_CONSTEXPR(nDim == 3) {
12421 cVars[ydim * i + 4] =
12422 fVol[i] * (vol1[i] * oCVars[ydim * i + 4] - dt * (beta1 * RHS[ydim * i + 4] + beta0 * RHS0[ydim * i + 4]));
12425 if(gId > -1 && c_globalId(i) == gId)
12426 cerr <<
globalTimeStep <<
" " << m_RKStep <<
" RK update " << gId <<
" " << cVars[ydim * i + 0] <<
" "
12427 << cVars[ydim * i + 1] <<
" " << cVars[ydim * i + 2] <<
" " << cVars[ydim * i + 3] <<
" "
12428 << cVars[ydim * i + 4] << endl;
12433 ASSERT(m_RKStep == 0,
"");
12434 for(
MInt i = xdim; i--;) {
12435 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
12436 const MFloat dt = timeStep() *
FPOW2(maxRefinementLevel() - a_level(i));
12437 cVars[ydim * i + 0] = fVol[i] * (vol1[i] * oCVars[ydim * i + 0] - dt * RHS0[ydim * i + 0]);
12438 cVars[ydim * i + 1] = fVol[i] * (vol1[i] * oCVars[ydim * i + 1] - dt * RHS0[ydim * i + 1]);
12439 cVars[ydim * i + 2] = fVol[i] * (vol1[i] * oCVars[ydim * i + 2] - dt * RHS0[ydim * i + 2]);
12440 cVars[ydim * i + 3] = fVol[i] * (vol1[i] * oCVars[ydim * i + 3] - dt * RHS0[ydim * i + 3]);
12441 IF_CONSTEXPR(nDim == 3) {
12442 cVars[ydim * i + 4] = fVol[i] * (vol1[i] * oCVars[ydim * i + 4] - dt * RHS0[ydim * i + 4]);
12445 if(gId > -1 && c_globalId(i) == gId)
12446 cerr <<
globalTimeStep <<
" " << m_RKStep <<
" RK update " << gId <<
" " << cVars[ydim * i + 0] <<
" "
12447 << cVars[ydim * i + 1] <<
" " << cVars[ydim * i + 2] <<
" " << cVars[ydim * i + 3] <<
" "
12448 << cVars[ydim * i + 4] << endl;
12453 updateLinkedCells();
12457 if(m_RKStep < m_noRKSteps) {
12471template <MInt nDim,
class SysEqn>
12473 MFloat* RESTRICT cVars = (
MFloat*)(&(a_variable(0, 0)));
12474 const MInt ydim = m_noCVars;
12479 MIntScratchSpace haloBufferOffsets(noNeighborDomains() + 1, AT_,
"haloBufferOffsets");
12480 MIntScratchSpace windowBufferOffsets(noNeighborDomains() + 1, AT_,
"windowBufferOffsets");
12485 MInt windowSize = 0;
12486 haloBufferCnts.
fill(0);
12487 windowBufferCnts.
fill(0);
12488 haloBufferOffsets.
fill(0);
12489 windowBufferOffsets.
fill(0);
12491 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12492 haloBufferCnts(i) = m_noCVars * (signed)m_linkedHaloCells[i].size();
12493 windowBufferCnts(i) = m_noCVars * (signed)m_linkedWindowCells[i].size();
12494 haloBufferOffsets(i + 1) = haloBufferOffsets(i) + haloBufferCnts(i);
12495 windowBufferOffsets(i + 1) = windowBufferOffsets(i) + windowBufferCnts(i);
12496 haloSize += haloBufferCnts(i);
12497 windowSize += windowBufferCnts(i);
12503 updateSplitParentVariables();
12505 haloReq.
fill(MPI_REQUEST_NULL);
12506 windowReq.
fill(MPI_REQUEST_NULL);
12507 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12508 if(m_linkedWindowCells[i].empty())
continue;
12509 for(
MInt j = 0; j < (signed)m_linkedWindowCells[i].size(); j++) {
12510 MInt cellId = m_linkedWindowCells[i][j];
12511 MInt offset = windowBufferOffsets(i) + noCVars * j;
12512 for(
MInt v = 0; v < (signed)noCVars; v++) {
12513 windowBuffer(offset + v) = a_variable(cellId, v);
12517 MInt windowCnt = 0;
12519 if(m_nonBlockingComm) {
12520 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12521 if(haloBufferCnts(i) == 0)
continue;
12522 MPI_Irecv(&haloBuffer[haloBufferOffsets[i]], haloBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 23, mpiComm(),
12523 &haloReq[haloCnt], AT_,
"haloBuffer[haloBufferOffsets[i]]");
12526 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12527 if(windowBufferCnts(i) == 0)
continue;
12528 MPI_Isend(&windowBuffer[windowBufferOffsets[i]], windowBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 23,
12529 mpiComm(), &windowReq[windowCnt], AT_,
"windowBuffer[windowBufferOffsets[i]]");
12532 if(haloCnt > 0)
MPI_Waitall(haloCnt, &haloReq[0], MPI_STATUSES_IGNORE, AT_);
12534 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12535 if(windowBufferCnts(i) == 0)
continue;
12536 MPI_Issend(&windowBuffer[windowBufferOffsets[i]], windowBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 23,
12537 mpiComm(), &windowReq[windowCnt], AT_,
"windowBuffer[windowBufferOffsets[i]]");
12540 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12541 if(haloBufferCnts(i) == 0)
continue;
12542 MPI_Recv(&haloBuffer[haloBufferOffsets[i]], haloBufferCnts(i), MPI_DOUBLE, neighborDomain(i), 23, mpiComm(),
12543 MPI_STATUS_IGNORE, AT_,
"haloBuffer[haloBufferOffsets[i]]");
12547 for(
MInt i = 0; i < noNeighborDomains(); i++) {
12548 if(m_linkedHaloCells[i].empty())
continue;
12549 for(
MInt j = 0; j < (signed)m_linkedHaloCells[i].size(); j++) {
12550 MInt cellId = m_linkedHaloCells[i][j];
12551 MInt offset = haloBufferOffsets(i) + noCVars * j;
12552 for(
MInt v = 0; v < (signed)noCVars; v++) {
12553 a_variable(cellId, v) = haloBuffer(offset + v);
12557 if(windowCnt > 0)
MPI_Waitall(windowCnt, &windowReq[0], MPI_STATUSES_IGNORE, AT_);
12559 if(grid().azimuthalPeriodicity()) {
12560 exchangeLinkedHaloCellsForAzimuthalReconstruction();
12561 azimuthalNearBoundaryExchange();
12564 for(
MUint it = 0; it < m_temporarilyLinkedCells.size(); it++) {
12565 const MInt cellId = get<0>(m_temporarilyLinkedCells[it]);
12566 const MInt masterId = get<1>(m_temporarilyLinkedCells[it]);
12567 const MInt tripleLink = get<2>(m_temporarilyLinkedCells[it]);
12568 if(tripleLink < 0) {
12569 const MFloat fac0 = a_cellVolume(cellId) / (a_cellVolume(cellId) + a_cellVolume(masterId));
12570 const MFloat fac1 = F1 - fac0;
12571 if(
false && m_RKStep == 0) {
12572 for(
MInt v = 0; v < m_noCVars; v++) {
12573 const MFloat var = fac1 * cVars[ydim * masterId + v];
12574 cVars[ydim * cellId + v] = var;
12575 cVars[ydim * masterId + v] = var;
12578 for(
MInt v = 0; v < m_noCVars; v++) {
12582 const MFloat var = fac0 * cVars[ydim * cellId + v] + fac1 * cVars[ydim * masterId + v];
12583 cVars[ydim * cellId + v] = var;
12584 cVars[ydim * masterId + v] = var;
12587 if(a_hasProperty(cellId, SolverCell::IsSplitCell)) {
12588 vector<MInt>::iterator it0 = find(m_splitCells.begin(), m_splitCells.end(), cellId);
12589 if(it0 == m_splitCells.end())
mTerm(1, AT_,
"split cells inconsistency.");
12590 const MInt pos = distance(m_splitCells.begin(), it0);
12591 ASSERT(m_splitCells[pos] == cellId,
"");
12592 for(
MUint s = 0; s < m_splitChilds[pos].size(); s++) {
12593 MInt splitChildId = m_splitChilds[pos][s];
12594 for(
MInt v = 0; v < m_noCVars; v++) {
12595 cVars[ydim * splitChildId + v] = cVars[ydim * cellId + v];
12599 if(a_hasProperty(masterId, SolverCell::IsSplitCell)) {
12600 vector<MInt>::iterator it0 = find(m_splitCells.begin(), m_splitCells.end(), masterId);
12601 if(it0 == m_splitCells.end())
mTerm(1, AT_,
"split cells inconsistency.");
12602 const MInt pos = distance(m_splitCells.begin(), it0);
12603 ASSERT(m_splitCells[pos] == masterId,
"");
12604 for(
MUint s = 0; s < m_splitChilds[pos].size(); s++) {
12605 MInt splitChildId = m_splitChilds[pos][s];
12606 for(
MInt v = 0; v < m_noCVars; v++) {
12607 cVars[ydim * splitChildId + v] = cVars[ydim * masterId + v];
12615 a_cellVolume(cellId) / (a_cellVolume(cellId) + a_cellVolume(tripleLink) + a_cellVolume(masterId));
12617 a_cellVolume(tripleLink) / (a_cellVolume(cellId) + a_cellVolume(tripleLink) + a_cellVolume(masterId));
12618 const MFloat fac2 = F1 - fac0 - fac1;
12620 for(
MInt v = 0; v < m_noCVars; v++) {
12622 fac0 * cVars[ydim * cellId + v] + fac1 * cVars[ydim * tripleLink + v] + fac2 * cVars[ydim * tripleLink + v];
12623 cVars[ydim * cellId + v] = var;
12624 cVars[ydim * tripleLink + v] = var;
12625 cVars[ydim * masterId + v] = var;
12628 if(a_hasProperty(cellId, SolverCell::IsSplitCell)) {
12629 vector<MInt>::iterator it0 = find(m_splitCells.begin(), m_splitCells.end(), cellId);
12630 if(it0 == m_splitCells.end())
mTerm(1, AT_,
"split cells inconsistency.");
12631 const MInt pos = distance(m_splitCells.begin(), it0);
12632 ASSERT(m_splitCells[pos] == cellId,
"");
12633 for(
MUint s = 0; s < m_splitChilds[pos].size(); s++) {
12634 MInt splitChildId = m_splitChilds[pos][s];
12635 for(
MInt v = 0; v < m_noCVars; v++) {
12636 cVars[ydim * splitChildId + v] = cVars[ydim * cellId + v];
12640 if(a_hasProperty(masterId, SolverCell::IsSplitCell)) {
12641 vector<MInt>::iterator it0 = find(m_splitCells.begin(), m_splitCells.end(), masterId);
12642 if(it0 == m_splitCells.end())
mTerm(1, AT_,
"split cells inconsistency.");
12643 const MInt pos = distance(m_splitCells.begin(), it0);
12644 ASSERT(m_splitCells[pos] == masterId,
"");
12645 for(
MUint s = 0; s < m_splitChilds[pos].size(); s++) {
12646 MInt splitChildId = m_splitChilds[pos][s];
12647 for(
MInt v = 0; v < m_noCVars; v++) {
12648 cVars[ydim * splitChildId + v] = cVars[ydim * masterId + v];
12652 if(a_hasProperty(tripleLink, SolverCell::IsSplitCell)) {
12653 vector<MInt>::iterator it0 = find(m_splitCells.begin(), m_splitCells.end(), tripleLink);
12654 if(it0 == m_splitCells.end())
mTerm(1, AT_,
"split cells inconsistency.");
12655 const MInt pos = distance(m_splitCells.begin(), it0);
12656 ASSERT(m_splitCells[pos] == tripleLink,
"");
12657 for(
MUint s = 0; s < m_splitChilds[pos].size(); s++) {
12658 MInt splitChildId = m_splitChilds[pos][s];
12659 for(
MInt v = 0; v < m_noCVars; v++) {
12660 cVars[ydim * splitChildId + v] = cVars[ydim * tripleLink + v];
12673template <MInt nDim,
class SysEqn>
12677 m_fvBndryCnd->copyVarsToSmallCells();
12685template <MInt nDim,
class SysEqn>
12693 IF_CONSTEXPR(nDim == 2)
12698 IF_CONSTEXPR(nDim == 2)
12703 IF_CONSTEXPR(nDim == 2)
12704 return "<< INVALID INDEX FOR CONSERVATIVE VAR >>";
12708 return "<< INVALID INDEX FOR CONSERVATIVE VAR >>";
12717template <MInt nDim,
class SysEqn>
12725 IF_CONSTEXPR(nDim == 2)
12730 IF_CONSTEXPR(nDim == 2)
12735 IF_CONSTEXPR(nDim == 2)
12736 return "<< INVALID INDEX FOR CONSERVATIVE VAR >>";
12740 return "<< INVALID INDEX FOR CONSERVATIVE VAR >>";
12749template <MInt nDim,
class SysEqn>
12753 if(!m_logBoundaryData && !forceOutput)
return;
12754 if(m_noLsMbBndryCells == 0)
return;
12755 IF_CONSTEXPR(nDim == 3)
return;
12758 const MFloat xOffset = m_bodyCenter[0];
12759 const MFloat yOffset = m_bodyCenter[1];
12760 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
12761 const MFloat radToDeg = 360.0 / (2.0 * PI);
12764 MFloat gradV[nDim][nDim];
12766 MFloat angle, u, v, cp, ma, vorticity, tmp;
12768 for(
MInt i = 0; i < nDim; i++) {
12769 rhoU2 +=
POW2(m_VVInfinity[i]);
12771 rhoU2 *= m_rhoInfinity;
12782 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
12783 cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
12784 centerLine =
false;
12785 IF_CONSTEXPR(nDim == 3) {
12786 if(a_coordinate(cellId, 2) >= F0 && a_hasNeighbor(cellId, 4) > 0
12787 && a_coordinate(c_neighborId(cellId, 4), 2) < F0) {
12791 IF_CONSTEXPR(nDim == 3) {
12792 if(!centerLine)
continue;
12796 if(a_coordinate(cellId, 1) - yOffset > 0 && a_coordinate(cellId, 0) - xOffset > 0) {
12797 angle = 180 - radToDeg * atan((a_coordinate(cellId, 1) - yOffset) / (a_coordinate(cellId, 0) - xOffset));
12798 }
else if(a_coordinate(cellId, 1) - yOffset > 0 && a_coordinate(cellId, 0) - xOffset < 0) {
12799 angle = -radToDeg * atan((a_coordinate(cellId, 1) - yOffset) / (a_coordinate(cellId, 0) - xOffset));
12800 }
else if(a_coordinate(cellId, 1) - yOffset < 0 && a_coordinate(cellId, 0) - xOffset > 0) {
12801 angle = 180.0 - radToDeg * atan((a_coordinate(cellId, 1) - yOffset) / (a_coordinate(cellId, 0) - xOffset));
12803 angle = 360.0 - radToDeg * atan((a_coordinate(cellId, 1) - yOffset) / (a_coordinate(cellId, 0) - xOffset));
12806 MFloat dx = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[0] - xOffset;
12807 MFloat dy = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[1] - yOffset;
12808 angle = 180.0 - (radToDeg * atan2(dy, dx));
12810 sortedAngle.
p[noCells] = angle;
12811 sortedList.
p[noCells] = cellId;
12815 for(
MInt i = 0; i < noCells - 1; i++) {
12816 for(
MInt j = i + 1; j < noCells; j++) {
12817 if(sortedAngle.
p[j] < sortedAngle.
p[i]) {
12818 iTmp = sortedList.
p[i];
12819 sortedList.
p[i] = sortedList.
p[j];
12820 sortedList.
p[j] = iTmp;
12821 fTmp = sortedAngle.
p[i];
12822 sortedAngle.
p[i] = sortedAngle.
p[j];
12823 sortedAngle.
p[j] = fTmp;
12830 ofl2.open(fileName);
12831 if(ofl2.is_open() && ofl2.good()) {
12832 for(
MInt c = 0; c < noCells; c++) {
12833 cellId = sortedList.
p[c];
12835 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
12836 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
12837 if(a_isHalo(cellId))
continue;
12838 if(a_isPeriodic(cellId))
continue;
12840 MInt bndryId = a_bndryId(cellId);
12841 angle = sortedAngle.
p[c];
12842 MFloat rhoSurface = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->RHO];
12843 MFloat pSurface = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->P];
12844 MFloat T = sysEqn().temperature_ES(rhoSurface, pSurface);
12845 MFloat mue = SUTHERLANDLAW(T);
12848 for(
MInt i = 0; i < nDim; i++) {
12849 dist += (a_coordinate(cellId, i) - m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[i])
12850 * m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[i];
12854 MFloat shear2[3] = {F0, F0, F0};
12855 for(
MInt i = 0; i < nDim; i++) {
12856 MFloat grad = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_normalDeriv[PV->VV[i]];
12857 shear[i] = mue * grad;
12860 MFloat cf = (m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[1] * shear[0]
12861 - m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[0] * shear[1])
12862 / (F1B2 * rhoU2 * m_referenceLength * sysEqn().m_Re0);
12864 u = a_pvariable(cellId, PV->VV[0]);
12865 v = a_pvariable(cellId, PV->VV[1]);
12866 ma = sqrt(u * u + v * v);
12867 ma /= sysEqn().speedOfSound(rhoSurface, pSurface);
12868 cp = (pSurface - m_PInfinity) / (F1B2 * rhoU2);
12873 for(
MInt i = 0; i < nDim; i++) {
12874 nablaPhi[i] = (a_levelSetValuesMb(c_neighborId(cellId, 2 * i + 1), 0)
12875 - a_levelSetValuesMb(c_neighborId(cellId, 2 * i), 0))
12876 / (F2 * c_cellLengthAtLevel(a_level(cellId)));
12877 nablaAbs +=
POW2(nablaPhi[i]);
12879 nablaAbs = sqrt(nablaAbs);
12880 for(
MInt i = 0; i < nDim; i++) {
12881 nablaPhi[i] /= nablaAbs;
12884 for(
MInt i = 0; i < nDim; i++) {
12885 for(
MInt j = 0; j < nDim; j++) {
12893 for(
MInt i = 0; i < nDim; i++) {
12894 dudn[i] = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_normalDeriv[PV->VV[i]];
12898 for(
MInt i = 0; i < nDim; i++) {
12899 tmp += m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[i] * gradP[i];
12901 for(
MInt i = 0; i < nDim; i++) {
12902 gradP[1] = -m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[0] * gradP[1]
12903 + m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[1] * gradP[0];
12907 MFloat u2 = m_bodyVelocity[0];
12908 MFloat v2 = m_bodyVelocity[1];
12909 for(
MInt j = 0; j < nDim; j++) {
12910 u2 += 0.5 * c_cellLengthAtLevel(maxRefinementLevel())
12911 * m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[j] * 0.5
12912 * (a_slope(cellId, PV->U, j) + gradV[PV->U][j]);
12913 v2 += 0.5 * c_cellLengthAtLevel(maxRefinementLevel())
12914 * m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[j] * 0.5
12915 * (a_slope(cellId, PV->V, j) + gradV[PV->V][j]);
12919 vorticity = (gradV[1][0] - gradV[0][1]) / m_UInfinity;
12921 MFloat bodyRotation[3] = {0};
12922 getBodyRotation(0, bodyRotation);
12924 const MFloat p0 = a_coordinate(cellId, 0);
12925 const MFloat q0 = a_coordinate(cellId, 1);
12926 const MFloat p = cos(-bodyRotation[2]) * p0 - sin(-bodyRotation[2]) * q0 + F1B4;
12928 ofl2 << cellId <<
" ";
12929 ofl2 << angle <<
" ";
12930 ofl2 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume <<
" ";
12931 ofl2 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_area <<
" ";
12932 ofl2 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[0] <<
" ";
12933 ofl2 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[1] <<
" ";
12934 ofl2 << m_volumeFraction[bndryId] <<
" ";
12935 ofl2 <<
dist <<
" ";
12936 ofl2 << pSurface <<
" ";
12937 ofl2 << rhoSurface <<
" ";
12939 ofl2 << shear[0] <<
" ";
12940 ofl2 << shear[1] <<
" ";
12941 ofl2 << a_pvariable(cellId, PV->P) <<
" ";
12942 ofl2 << vorticity <<
" ";
12943 ofl2 << gradP[0] <<
" ";
12944 ofl2 << gradP[1] <<
" ";
12945 ofl2 << dudn[0] <<
" ";
12946 ofl2 << dudn[1] <<
" ";
12947 ofl2 << (u - m_bodyVelocity[0]) /
dist <<
" ";
12948 ofl2 << (v - m_bodyVelocity[1]) /
dist <<
" ";
12950 ofl2 << (u2 - m_bodyVelocity[0]) / (0.5 * c_cellLengthAtLevel(maxRefinementLevel())) <<
" ";
12951 ofl2 << (v2 - m_bodyVelocity[1]) / (0.5 * c_cellLengthAtLevel(maxRefinementLevel())) <<
" ";
12952 ofl2 << dundn <<
" ";
12953 ofl2 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[0] <<
" ";
12954 ofl2 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates[1] <<
" ";
12955 ofl2 << shear2[0] <<
" ";
12956 ofl2 << shear2[1] <<
" ";
12957 ofl2 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->U] <<
" ";
12958 ofl2 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->V] <<
" ";
12959 ofl2 << a_coordinate(cellId, 0) <<
" ";
12960 ofl2 << a_coordinate(cellId, 1) <<
" ";
12964 ofl2 << nablaPhi[0] <<
" ";
12965 ofl2 << nablaPhi[1] <<
" ";
12972 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing!" << endl;
12982template <MInt nDim,
class SysEqn>
12986 NEW_TIMER_GROUP_STATIC(t_bodyTimer,
"computeBodySurfaceData");
12987 NEW_TIMER_STATIC(t_timertotal,
"computeBodySurfaceData", t_bodyTimer);
12988 NEW_SUB_TIMER_STATIC(t_local,
"localForce", t_timertotal);
12989 NEW_SUB_TIMER_STATIC(t_reduce,
"reduce", t_timertotal);
12990 NEW_SUB_TIMER_STATIC(t_collision,
"collision", t_timertotal);
12991 RECORD_TIMER_START(t_timertotal);
12992 RECORD_TIMER_START(t_local);
12995 MBool returnCoeffs =
false;
12996 MInt noValues = nDim + 3 + 1;
12997 MInt noReturnCoeffs = nDim;
12999 if(pressureForce !=
nullptr) {
13000 returnCoeffs =
true;
13001 noValues += noReturnCoeffs;
13004 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
13005 const MFloat F1BRe = F1 / (m_referenceLength * sysEqn().m_Re0);
13006 const MFloat F1BPr = F1 / (m_Pr);
13009 bodyForce.
fill(F0);
13012 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
13013 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
13015 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
13016 if(a_isHalo(cellId))
continue;
13017 if(a_isPeriodic(cellId))
continue;
13018 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
13019 if(a_isBndryGhostCell(cellId))
continue;
13020 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
13022 MFloatScratchSpace dummyPvariables(m_bndryCells->a[bndryId].m_noSrfcs, PV->noVariables, AT_,
"dummyPvariables");
13023 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
13024 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area < 1e-14)
continue;
13025 MInt k = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0];
13026 ASSERT(m_internalBodyId[k] > -1 && m_internalBodyId[k] < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
13027 MInt body = m_internalBodyId[k];
13028 ASSERT(body > -1 && body < m_noEmbeddedBodies,
"");
13032 MInt surfVars =
mMin((
signed)m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size(),
13033 m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs);
13035 for(
MInt s = 0; s < surfVars; s++) {
13036 dummyPvariables(s, PV->P) = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[s]->m_primVars[PV->P];
13037 dummyPvariables(s, PV->RHO) = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[s]->m_primVars[PV->RHO];
13039 for(
MInt n = 0; n < (signed)m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size(); n++) {
13040 const MInt nghbrId = m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n];
13041 const MFloat nghbrPvariableP = (n < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs)
13042 ? dummyPvariables(n, PV->P)
13043 : a_pvariable(nghbrId, PV->P);
13044 const MFloat nghbrPvariableRho = (n < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs)
13045 ? dummyPvariables(n, PV->RHO)
13046 : a_pvariable(nghbrId, PV->RHO);
13048 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_imagePointRecConst[n] * nghbrPvariableRho;
13049 pSurface += m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_imagePointRecConst[n] * nghbrPvariableP;
13052 MFloat normal0[3] = {F0, F0, F0};
13053 MFloat normal[3] = {F0, F0, F0};
13054 for(
MInt i = 0; i < nDim; i++) {
13055 normal0[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
13056 normal[i] = m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVectorCentroid[i];
13059 MFloat dn = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance;
13060 MFloat T = sysEqn().temperature_ES(rhoSurface, pSurface);
13061 MFloat mue = SUTHERLANDLAW(T);
13062 MFloat dx[3] = {F0, F0, F0};
13063 MFloat df[3] = {F0, F0, F0};
13064 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
13066 for(
MInt i = 0; i < nDim; i++) {
13067 const MFloat dp0 = -pSurface * normal0[i] * area;
13068 const MFloat dp = -pSurface * normal[i] * area;
13069 MFloat grad = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[i]];
13070 for(
MInt j = 0; j < nDim; j++)
13071 grad += F1B3 * normal[i] * normal[j]
13072 * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[j]];
13073 MFloat ds0 = F1BRe * mue * grad * area;
13082 dx[i] = a_coordinate(cellId, i) - dn * normal[i] - m_bodyCenter[nDim * k + i];
13083 bodyForce(body, i) += dp0 + ds0;
13084 if(returnCoeffs ==
true) {
13085 bodyForce(body, nDim + 3 + 1 + i) += dp0;
13087 coupling -= (dp0 + ds0) * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]];
13089#
if defined _MB_DEBUG_ || !defined NDEBUG
13090 if(std::isnan(dp0) || std::isnan(ds0)) {
13091 const MInt rootId =
13092 (a_hasProperty(cellId, SolverCell::IsSplitChild)) ? getAssociatedInternalCell(cellId) : cellId;
13093 cerr << domainId() <<
" local body force diverged " <<
globalTimeStep <<
" " << body <<
" " << i <<
" " << k
13094 <<
" / " << ds0 <<
" " << dp0 <<
" " << pSurface <<
" " << rhoSurface <<
" " << mue <<
" " << grad
13095 <<
" / " << area / m_gridCellArea[a_level(rootId)] <<
" " << normal0[i] <<
" " << normal[i] <<
" "
13096 << dn / c_cellLengthAtCell(rootId) <<
" / " << cellId <<
" " << c_globalId(rootId) <<
" "
13097 << a_level(rootId) <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild) <<
" "
13098 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs << endl;
13103 if(std::isnan(dx[1] * df[2] - dx[2] * df[1]) || std::isnan(dx[2] * df[0] - dx[0] * df[2])
13104 || std::isnan(dx[0] * df[1] - dx[1] * df[0]))
13105 cerr << domainId() <<
": torque0 " <<
globalTimeStep <<
" " << c_globalId(cellId) <<
" " << bndryId <<
" "
13106 << srfc <<
" = " << pSurface <<
" " << rhoSurface <<
" / " << dx[0] <<
" " << dx[1] <<
" " << dx[2]
13107 <<
" / " << df[0] <<
" " << df[1] <<
" " << df[2] <<
" // " << area / m_gridCellArea[a_level(cellId)]
13108 <<
" " << pSurface <<
" " << mue <<
" "
13109 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[0]] <<
" "
13110 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[1]] <<
" "
13111 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[2]] << endl;
13113 IF_CONSTEXPR(nDim == 3) {
13114 bodyForce(body, nDim + 0) += dx[1] * df[2] - dx[2] * df[1];
13115 bodyForce(body, nDim + 1) += dx[2] * df[0] - dx[0] * df[2];
13117 bodyForce(body, nDim + 2) += dx[0] * df[1] - dx[1] * df[0];
13119 MFloat gradP = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->P];
13120 MFloat gradRho = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->RHO];
13121 MFloat gradT = m_gamma * (rhoSurface * gradP - pSurface * gradRho) /
POW2(rhoSurface);
13122 const MFloat lambdaFluid = (T * sqrt(T) * m_sutherlandPlusOneThermal) / (T + m_sutherlandConstantThermal);
13123 MFloat heatFlux = gradT * area * F1BRe * F1BPr * lambdaFluid * m_gamma;
13124 bodyForce(body, nDim + 3) += heatFlux;
13127 RECORD_TIMER_STOP(t_local);
13128 RECORD_TIMER_START(t_reduce);
13130 if(m_nonBlockingComm) {
13131#ifndef MAIA_MS_COMPILER
13132 MPI_Request redReq1 = MPI_REQUEST_NULL;
13133 MPI_Request redReq2 = MPI_REQUEST_NULL;
13134 MPI_Iallreduce(MPI_IN_PLACE, &bodyForce[0], bodyForce.
size(), MPI_DOUBLE, MPI_SUM, mpiComm(), &redReq1, AT_,
13135 "MPI_IN_PLACE",
"bodyForce[0]");
13136 MPI_Iallreduce(MPI_IN_PLACE, &coupling, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), &redReq2, AT_,
"MPI_IN_PLACE",
13138 MPI_Wait(&redReq1, MPI_STATUSES_IGNORE, AT_);
13139 MPI_Wait(&redReq2, MPI_STATUSES_IGNORE, AT_);
13141 MPI_Allreduce(MPI_IN_PLACE, &bodyForce[0], bodyForce.
size(), MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
13143 MPI_Allreduce(MPI_IN_PLACE, &coupling, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"coupling");
13146 MPI_Allreduce(MPI_IN_PLACE, &bodyForce[0], bodyForce.
size(), MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
13148 MPI_Allreduce(MPI_IN_PLACE, &coupling, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"coupling");
13150 RECORD_TIMER_STOP(t_reduce);
13155 m_couplingRate = coupling;
13156 if(pressureForce !=
nullptr) {
13157 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
13158 for(
MInt i = 0; i < nDim; i++) {
13159 pressureForce[k * nDim + i] = bodyForce(k, nDim + 3 + 1 + i);
13162 RECORD_TIMER_STOP(t_timertotal);
13165 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
13166 for(
MInt i = 0; i < nDim; i++) {
13167 m_bodyForce[k * nDim + i] = bodyForce(k, i);
13168 m_hydroForce[k * nDim + i] = bodyForce(k, i);
13171 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
13172 m_bodyHeatFlux[k] = bodyForce(k, nDim + 3);
13173 for(
MInt i = 0; i < 3; i++) {
13174 m_bodyTorque[k * 3 + i] = bodyForce(k, nDim + i);
13179 RECORD_TIMER_START(t_collision);
13180 IF_CONSTEXPR(nDim == 3) {
13181 const MFloat S = (m_noLevelSetsUsedForMb > 1) ? F2 * c_cellLengthAtLevel(maxRefinementLevel())
13182 : F3 * c_cellLengthAtLevel(maxRefinementLevel());
13183 const MFloat deltaMax = 1.5 * S + F2 * m_maxBodyRadius;
13185 if(m_noEmbeddedBodies > 1 && m_applyCollisionModel) {
13188 for(
MInt p = 0; p < m_noEmbeddedBodies; p++) {
13189 m_bodyInCollision[p] = 0;
13192 for(
MInt p = 0; p < m_noEmbeddedBodies; p++) {
13193 ASSERT(m_bodyTree !=
nullptr,
"");
13195 Point<nDim> pt(m_bodyCenter[p * nDim], m_bodyCenter[p * nDim + 1], m_bodyCenter[p * nDim + 2]);
13196 MInt noNearBodies = m_bodyTree->locatenear(pt, deltaMax, &nearBodies[0], m_noEmbeddedBodies);
13198 for(
MInt b = 0;
b < noNearBodies;
b++) {
13199 const MInt q = nearBodies[
b];
13200 if(p == q)
continue;
13202 m_bodyInCollision[p] = 1;
13204 const MFloat dp = F2 *
mMax(m_bodyRadii[p * 3 + 0],
mMax(m_bodyRadii[p * 3 + 1], m_bodyRadii[p * 3 + 2]));
13205 const MFloat dq = F2 *
mMax(m_bodyRadii[q * 3 + 0],
mMax(m_bodyRadii[q * 3 + 1], m_bodyRadii[q * 3 + 2]));
13206 const MFloat D = F1B2 * (dp + dq);
13208 sqrt(
POW2(m_bodyTerminalVelocity[0]) +
POW2(m_bodyTerminalVelocity[1]) +
POW2(m_bodyTerminalVelocity[2]));
13209 const MFloat delta = sqrt(
POW2(m_bodyCenter[p * nDim] - m_bodyCenter[q * nDim])
13210 +
POW2(m_bodyCenter[p * nDim + 1] - m_bodyCenter[q * nDim + 1])
13211 +
POW2(m_bodyCenter[p * nDim + 2] - m_bodyCenter[q * nDim + 2]));
13214 if(
dist > S)
continue;
13216 if(m_bodyTypeMb == 1) {
13217 if(
dist < F0 && domainId() == 0) cerr <<
"Warning: potential overlap for bodies " << p <<
" " << q << endl;
13219 const MFloat C = CdLaw(m_Re * D) * F1B2 * m_rhoU2 * F1B4 * PI *
POW2(D);
13220 const MFloat M = F1B2 * (m_bodyMass[m_internalBodyId[p]] + m_bodyMass[m_internalBodyId[q]]);
13221 const MFloat C0 = 8.0 * M *
POW2(m_UInfinity + termv) / c_cellLengthAtLevel(maxRefinementLevel());
13223 m_bodyInCollision[p] = 2;
13225 for(
MInt i = 0; i < nDim; i++) {
13227 * (m_bodyCenter[p * nDim + i] - m_bodyCenter[q * nDim + i]) /
dist;
13228 m_bodyForce[p * nDim + i] += df;
13230 if(domainId() == 0 &&
dist / c_cellLengthAtLevel(maxRefinementLevel()) < 1.5)
13231 cerr <<
globalTimeStep <<
" ---- repulsive force " << m_internalBodyId[q] <<
" -> " << p <<
": "
13233 << C0 / (C / eps) <<
") dist=" <<
dist / c_cellLengthAtLevel(maxRefinementLevel()) << endl;
13235 }
else if(m_bodyTypeMb == 3) {
13236 const MFloat M = F1B2 * (m_bodyMass[m_internalBodyId[p]] + m_bodyMass[m_internalBodyId[q]]);
13237 const MFloat C0 = 16.0 * M *
POW2(m_UInfinity + termv) / c_cellLengthAtLevel(maxRefinementLevel());
13242 dist = distEllipsoidEllipsoid(p, q, xcp, xcq);
13245 m_bodyInCollision[p] = 2;
13248 for(
MInt i = 0; i < nDim; i++) {
13250 m_bodyForce[p * nDim + i] += df[i];
13253 if(domainId() == 0 &&
dist / c_cellLengthAtLevel(maxRefinementLevel()) < 1.5)
13254 cerr <<
globalTimeStep <<
" ---- repulsive force " << m_internalBodyId[q] <<
" -> " << p <<
": "
13256 <<
" dist=" <<
dist / c_cellLengthAtLevel(maxRefinementLevel()) << endl;
13261 if(m_saveSlipInterval > 0) {
13262 MInt noParticlesLocal = m_particleOffsets[domainId() + 1] - m_particleOffsets[domainId()];
13263 MInt noTimeStepsSaved = m_slipDataTimeSteps.size();
13265 for(
MInt p = 0; p < noParticlesLocal; p++) {
13266 m_slipDataParticleCollision[noParticlesLocal * noTimeStepsSaved + p] =
13267 m_bodyInCollision[p + m_particleOffsets[domainId()]];
13273#if defined _MB_DEBUG_ || !defined NDEBUG
13274 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
13275 for(
MInt i = 0; i < nDim; i++) {
13276 if(std::isnan(m_bodyForce[k * nDim + i]) && domainId() == 0) {
13277 cerr <<
"force " << setprecision(15) << k <<
" " << i <<
" " << m_bodyForce[k * nDim + i] << endl;
13278 m_log <<
"force " << setprecision(15) << k <<
" " << i <<
" " << m_bodyForce[k * nDim + i];
13279 for(
MInt j = 0; j < nDim; j++)
13280 m_log <<
" " << m_bodyCenter[nDim * k + j];
13281 for(
MInt j = 0; j < 4; j++)
13282 m_log <<
" " << m_bodyQuaternion[4 * k + j];
13287 for(
MInt i = 0; i < 3; i++) {
13288 if(std::isnan(m_bodyTorque[k * 3 + i]) && domainId() == 0) {
13289 cerr <<
"torque " << setprecision(15) << k <<
" " << i <<
" " << m_bodyTorque[k * 3 + i] << endl;
13290 m_log <<
"torque " << setprecision(15) << k <<
" " << i <<
" " << m_bodyTorque[k * 3 + i];
13291 for(
MInt j = 0; j < nDim; j++)
13292 m_log <<
" " << m_bodyCenter[nDim * k + j];
13293 for(
MInt j = 0; j < 4; j++)
13294 m_log <<
" " << m_bodyQuaternion[4 * k + j];
13300 RECORD_TIMER_STOP(t_collision);
13301 RECORD_TIMER_STOP(t_timertotal);
13302 DISPLAY_TIMER_OFFSET(t_timertotal, m_restartInterval);
13310template <MInt nDim,
class SysEqn>
13311template <
typename T>
13313 return (std::isnan(val) || std::isinf(val));
13321template <MInt nDim,
class SysEqn>
13323 if(m_noEmbeddedBodies == 0)
return;
13324 cerr0 <<
"Init body velocities" << endl;
13339 ? Context::getSolverProperty<MInt>(
"initBodyRotation", m_solverId, AT_)
13342 memset(m_bodyVelocity, 0, m_noEmbeddedBodies * nDim *
sizeof(
MFloat));
13343 memset(m_bodyAngularVelocity, 0, m_noEmbeddedBodies * 3 *
sizeof(
MFloat));
13345 if(initBodyRotation == 1) {
13358 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
13359 if(a_isHalo(cellId))
continue;
13360 ASSERT(!a_isPeriodic(cellId),
"");
13361 if(a_isPeriodic(cellId))
continue;
13362 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
13363 if(a_bndryId(cellId) < -1)
continue;
13366 for(
MInt i = 0; i < nDim; i++) {
13367 U2 +=
POW2(a_variable(cellId, CV->RHO_VV[i]) / a_variable(cellId, CV->RHO));
13370 Ek0 += F1B2 * a_cellVolume(cellId) * U2;
13371 volm += a_cellVolume(cellId);
13373 if(a_levelSetValuesMb(cellId, 0) < F0 || a_bndryId(cellId) >= m_noOuterBndryCells) {
13374 if(a_associatedBodyIds(cellId, 0) < 0) {
13375 cerr << domainId() <<
": negative body id A" << endl;
13379 MInt bodyId = m_internalBodyId[a_associatedBodyIds(cellId, 0)];
13380 MFloat vol = grid().gridCellVolume(a_level(cellId));
13382 if(a_bndryId(cellId) > -1) vol -= a_cellVolume(cellId);
13384 for(
MInt i = 0; i < nDim; i++)
13385 m_bodyVelocity[nDim * bodyId + i] += vol * a_pvariable(cellId, PV->VV[i]);
13390 for(
MInt i = 0; i < nDim; i++) {
13391 dx[i] = a_coordinate(cellId, i) - m_bodyCenter[bodyId * nDim + i];
13395 if(initBodyRotation) {
13396 m_bodyAngularVelocity[3 * bodyId + 0] +=
13397 vol * (dx[1] * a_pvariable(cellId, PV->VV[2]) - dx[2] * a_pvariable(cellId, PV->VV[1])) / r2;
13398 m_bodyAngularVelocity[3 * bodyId + 1] +=
13399 vol * (dx[2] * a_pvariable(cellId, PV->VV[0]) - dx[0] * a_pvariable(cellId, PV->VV[2])) / r2;
13400 m_bodyAngularVelocity[3 * bodyId + 2] +=
13401 vol * (dx[0] * a_pvariable(cellId, PV->VV[1]) - dx[1] * a_pvariable(cellId, PV->VV[0])) / r2;
13403 for(
MInt i = 0; i < nDim; i++)
13404 Ek[bodyId] += vol *
POW2(a_pvariable(cellId, PV->VV[i]));
13405 bodyVol(bodyId) += vol;
13407 for(
MInt i = 0; i < nDim; i++)
13408 EkB += vol *
POW2(a_pvariable(cellId, PV->VV[i]));
13411 if(a_levelSetValuesMb(cellId, 0) > F0 || a_bndryId(cellId) >= m_noOuterBndryCells) {
13412 MFloat vol = a_cellVolume(cellId);
13416 if(a_bndryId(cellId) >= m_noOuterBndryCells) {
13417 MFloat vol = m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_srfcs[0]->m_area;
13421 MPI_Allreduce(MPI_IN_PLACE, m_bodyVelocity, m_noEmbeddedBodies * nDim, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
13422 "MPI_IN_PLACE",
"m_bodyVelocity");
13423 MPI_Allreduce(MPI_IN_PLACE, m_bodyAngularVelocity, m_noEmbeddedBodies * 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
13424 "MPI_IN_PLACE",
"m_bodyAngularVelocity");
13425 MPI_Allreduce(MPI_IN_PLACE, &bodyVol[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
13427 MPI_Allreduce(MPI_IN_PLACE, &vol0, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"vol0");
13428 MPI_Allreduce(MPI_IN_PLACE, &vol1, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"vol1");
13429 MPI_Allreduce(MPI_IN_PLACE, &vol2, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"vol2");
13430 MPI_Allreduce(MPI_IN_PLACE, &Ek[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
13432 MPI_Allreduce(MPI_IN_PLACE, &Ek0, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"Ek0");
13433 MPI_Allreduce(MPI_IN_PLACE, &volm, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"volm");
13434 MPI_Allreduce(MPI_IN_PLACE, &EkB, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"EkB");
13435 MPI_Allreduce(MPI_IN_PLACE, &volB, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"volB");
13440 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
13441 if(domainId() == 0 && fabs(bodyVol[
b] - m_bodyVolume[
b]) / m_bodyVolume[
b] > 0.1)
13442 cerr <<
"bad body volume " <<
b <<
" " << bodyVol[
b] <<
" " << m_bodyVolume[
b] << endl;
13443 Ek[
b] /=
mMax(1e-14, bodyVol[
b]);
13445 for(
MInt i = 0; i < nDim; i++) {
13446 m_bodyVelocity[nDim *
b + i] /=
mMax(1e-14, bodyVol[
b]);
13447 m_bodyVelocityDt1[nDim *
b + i] = m_bodyVelocity[nDim *
b + i];
13448 if(domainId() == 0 && std::isnan(m_bodyVelocity[nDim *
b + i]))
13449 cerr <<
"Warning: body velocity " <<
b <<
" " << i <<
" " << m_bodyVelocity[nDim *
b + i] << endl;
13450 EkB2 += F1B2 *
POW2(m_bodyVelocity[nDim *
b + i]);
13453 if(initBodyRotation) {
13454 for(
MInt i = 0; i < 3; i++) {
13455 m_bodyAngularVelocity[3 *
b + i] /=
mMax(1e-14, bodyVol[
b]);
13456 m_bodyAngularVelocityDt1[3 *
b + i] = m_bodyAngularVelocity[3 *
b + i];
13457 if(domainId() == 0 && std::isnan(m_bodyAngularVelocity[3 *
b + i]))
13458 cerr <<
"Warning: body angular velocity " <<
b <<
" " << i <<
" " << m_bodyAngularVelocity[3 *
b + i]
13463 for(
MUint j = 0; j < m_periodicGhostBodies[
b].size(); j++) {
13464 MInt k = m_periodicGhostBodies[
b][j];
13465 transferBodyState(k,
b);
13469 for(
MInt k = 0; k < m_noEmbeddedBodies + m_noPeriodicGhostBodies; k++) {
13470 for(
MInt dir = 0; dir < nDim; dir++) {
13471 m_bodyVelocity[nDim * k + dir] += m_bodyTerminalVelocity[dir];
13475 if(domainId() == 0) {
13476 cerr <<
"domain volumes upon init: " << setprecision(12) << vol0 <<
" " << vol1 <<
" "
13477 << vol0 /
POW3(m_bbox[3] - m_bbox[0]) <<
" " << (vol0 + vol1) /
POW3(m_bbox[3] - m_bbox[0]) <<
" "
13478 << Ek0 /
POW2(m_UInfinity) <<
" " << EkB /
POW2(m_UInfinity) <<
" "
13479 << (Ek0 * volm + EkB * volB) / ((volm + volB) *
POW2(m_UInfinity)) <<
" "
13480 << EkB2 / (
POW2(m_UInfinity) * m_noEmbeddedBodies) << endl;
13481 m_log <<
"domain volumes upon init: " << setprecision(12) << vol0 <<
" " << vol1 <<
" "
13482 << vol0 /
POW3(m_bbox[3] - m_bbox[0]) <<
" " << (vol0 + vol1) /
POW3(m_bbox[3] - m_bbox[0]) <<
" "
13483 << Ek0 /
POW2(m_UInfinity) <<
" " << EkB /
POW2(m_UInfinity) <<
" "
13484 << (Ek0 * volm + EkB * volB) / ((volm + volB) *
POW2(m_UInfinity)) <<
" "
13485 << EkB2 / (
POW2(m_UInfinity) * m_noEmbeddedBodies) << endl;
13488 MIntScratchSpace nearestCellToCenter(m_noEmbeddedBodies, AT_,
"nearestCellToCenter");
13490 nearestCellToCenter.fill(-1);
13491 nearestDist.fill(std::numeric_limits<MFloat>::max());
13496 MFloat EkFluidInBodyVol = F0;
13497 MFloat dx[3] = {F0, F0, F0};
13500 if(a_isHalo(cellId))
continue;
13501 ASSERT(!a_isPeriodic(cellId),
"");
13502 if(a_isPeriodic(cellId))
continue;
13503 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
13504 if(a_bndryId(cellId) < -1)
continue;
13507 for(
MInt i = 0; i < nDim; i++) {
13508 U2 +=
POW2(a_variable(cellId, CV->RHO_VV[i]) / a_variable(cellId, CV->RHO));
13511 EkFluid += F1B2 * a_cellVolume(cellId) * U2;
13512 volF += a_cellVolume(cellId);
13514 if(a_levelSetValuesMb(cellId, 0) < F0 || a_bndryId(cellId) >= m_noOuterBndryCells) {
13515 MInt bodyId = a_associatedBodyIds(cellId, 0);
13516 if(bodyId < 0)
continue;
13517 bodyId = m_internalBodyId[bodyId];
13518 MFloat vol = grid().gridCellVolume(a_level(cellId));
13519 if(a_bndryId(cellId) > -1) vol -= a_cellVolume(cellId);
13521 for(
MInt i = 0; i < nDim; i++) {
13522 EkFluidInBodyVol += F1B2 * vol *
POW2(a_variable(cellId, CV->RHO_VV[i]) / a_variable(cellId, CV->RHO));
13525 for(
MInt i = 0; i < nDim; i++) {
13526 dx[i] = a_coordinate(cellId, i) - m_bodyCenter[bodyId * nDim + i];
13529 if(sqrt(r2) < nearestDist(bodyId)) {
13530 nearestCellToCenter(bodyId) =
cellId;
13531 nearestDist(bodyId) = sqrt(r2);
13536 MPI_Allreduce(MPI_IN_PLACE, &EkFluid, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"EkFluid");
13537 MPI_Allreduce(MPI_IN_PLACE, &EkFluidInBodyVol, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
13538 "EkFluidInBodyVol");
13539 MPI_Allreduce(MPI_IN_PLACE, &volF, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"volF");
13540 MPI_Allreduce(MPI_IN_PLACE, &volB, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"volB");
13541 MPI_Allreduce(MPI_IN_PLACE, &nearestDist(0), m_noEmbeddedBodies, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
13542 "MPI_IN_PLACE",
"nearestDist(0)");
13544 if(initBodyRotation) exchangeAll();
13546 for(
MInt bodyId = 0; bodyId < m_noEmbeddedBodies; bodyId++) {
13548 if(cellId < 0)
continue;
13550 for(
MInt i = 0; i < nDim; i++) {
13551 dx[i] = a_coordinate(cellId, i) - m_bodyCenter[bodyId * nDim + i];
13554 if(sqrt(r2) > (nearestDist(bodyId) + std::numeric_limits<MFloat>::epsilon()))
continue;
13555 for(
MInt i = 0; i < nDim; i++) {
13556 m_bodyVelocity[nDim * bodyId + i] = a_variable(cellId, CV->RHO_VV[i]) / a_variable(cellId, CV->RHO);
13558 if(initBodyRotation) {
13559 while(a_level(cellId) > maxUniformRefinementLevel()) {
13560 cellId = c_parentId(cellId);
13562 vector<vector<MFloat>> slope(nDim, vector<MFloat>(nDim));
13563 for(
MInt dir = 0; dir < m_noDirs / 2; dir++) {
13564 MInt nghbrId1 = -1;
13565 MInt nghbrId2 = -1;
13566 if(a_hasNeighbor(cellId, dir) > 0)
13567 nghbrId1 = c_neighborId(cellId, 2 * dir);
13569 mTerm(0, AT_,
"neighbor not found. PartitionLevelShift?");
13570 if(a_hasNeighbor(cellId, dir + 1) > 0)
13571 nghbrId2 = c_neighborId(cellId, 2 * dir + 1);
13573 mTerm(0, AT_,
"neighbor not found. PartitionLevelShift?");
13574 for(
MInt i = 0; i < nDim; i++) {
13575 slope[i][dir] = F1 / (F2 * grid().cellLengthAtCell(cellId))
13576 * (a_pvariable(nghbrId2, PV->VV[i]) - a_pvariable(nghbrId1, PV->VV[i]));
13579 for(
MInt i = 0; i < nDim; i++) {
13580 MInt id0 = (i + 1) % 3;
13581 MInt id1 = (id0 + 1) % 3;
13582 m_bodyAngularVelocity[3 * bodyId + i] += F1B2 * (slope[id1][id0] - slope[id0][id1]);
13587 MPI_Allreduce(MPI_IN_PLACE, m_bodyVelocity, m_noEmbeddedBodies * nDim, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
13588 "MPI_IN_PLACE",
"m_bodyVelocity");
13589 if(initBodyRotation)
13590 MPI_Allreduce(MPI_IN_PLACE, m_bodyAngularVelocity, m_noEmbeddedBodies * 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
13591 "MPI_IN_PLACE",
"m_bodyAngularVelocity");
13597 MFloat volBAnalytical = F0;
13598 for(
MInt bodyId = 0; bodyId < m_noEmbeddedBodies; bodyId++) {
13599 for(
MInt i = 0; i < nDim; i++) {
13600 m_bodyVelocityDt1[nDim * bodyId + i] = m_bodyVelocity[nDim * bodyId + i];
13601 EkBLin += F1B2 *
POW2(m_bodyVelocity[nDim * bodyId + i]);
13602 EkBTot += F1B2 *
POW2(m_bodyVelocity[nDim * bodyId + i]);
13603 EkBTerm += F1B2 *
POW2(m_bodyVelocity[nDim * bodyId + i] + m_bodyTerminalVelocity[i]);
13604 if(domainId() == 0 && std::isnan(m_bodyVelocity[nDim * bodyId + i]))
13605 cerr <<
"Warning: body velocity " << bodyId <<
" " << i <<
" " << m_bodyVelocity[nDim * bodyId + i] << endl;
13608 if(initBodyRotation) {
13613 for(
MInt i = 0; i < 3; i++)
13614 tmp[i] = m_bodyAngularVelocity[bodyId * 3 + i];
13616 for(
MInt i = 0; i < nDim; i++) {
13617 m_bodyAngularVelocityDt1[3 * bodyId + i] = m_bodyAngularVelocity[3 * bodyId + i];
13618 EkBRot += F1B2 *
POW2(q[i]) * m_bodyMomentOfInertia[3 * bodyId + i] / m_bodyMass[bodyId];
13620 if(domainId() == 0 && std::isnan(m_bodyAngularVelocity[3 * bodyId + i]))
13621 cerr <<
"Warning: body angular velocity " << bodyId <<
" " << i <<
" "
13622 << m_bodyAngularVelocity[3 * bodyId + i] << endl;
13626 for(
MUint j = 0; j < m_periodicGhostBodies[bodyId].size(); j++) {
13627 MInt k = m_periodicGhostBodies[bodyId][j];
13628 transferBodyState(k, bodyId);
13630 volBAnalytical += F4B3 * PI * m_bodyRadii[bodyId] * m_bodyRadii[bodyId + 1] * m_bodyRadii[bodyId + 2];
13632 for(
MInt k = 0; k < m_noEmbeddedBodies + m_noPeriodicGhostBodies; k++) {
13633 for(
MInt dir = 0; dir < nDim; dir++) {
13634 m_bodyVelocity[nDim * k + dir] += m_bodyTerminalVelocity[dir];
13637 MFloat volFAnalytical = F1;
13638 for(
MInt dim = 0; dim < nDim; dim++) {
13639 volFAnalytical *= (m_bbox[nDim + dim] - m_bbox[dim]);
13641 volFAnalytical -= volBAnalytical;
13642 if(domainId() == 0) {
13643 cerr <<
"InitBodyFluidVelocities: mean kinetic Energy " << setprecision(12) <<
"fluid "
13644 << EkFluid / (
POW2(m_UInfinity) * volF) <<
" fluid in bodies "
13645 << EkFluidInBodyVol / (
POW2(m_UInfinity) * volB) <<
" bodies: total "
13646 << EkBTot / (
POW2(m_UInfinity) * m_noEmbeddedBodies) <<
" linear "
13647 << EkBLin / (
POW2(m_UInfinity) * m_noEmbeddedBodies) <<
" rotational "
13648 << EkBRot / (
POW2(m_UInfinity * m_noEmbeddedBodies)) <<
" terminal "
13649 << EkBTerm / (
POW2(m_UInfinity) * m_noEmbeddedBodies) << endl;
13650 cerr <<
"InitBodyFluidVelocities: volumes " << setprecision(12) <<
"fluid " << volF <<
" analytical "
13651 << volFAnalytical <<
" bodies " << volB <<
" volBAnalytical " << volBAnalytical << endl;
13652 m_log <<
"InitBodyFluidVelocities: mean kinetic Energy " << setprecision(12) <<
"fluid "
13653 << EkFluid / (
POW2(m_UInfinity) * volF) <<
" fluid in bodies "
13654 << EkFluidInBodyVol / (
POW2(m_UInfinity) * volB) <<
" bodies total "
13655 << EkBTot / (
POW2(m_UInfinity) * m_noEmbeddedBodies) <<
" linear "
13656 << EkBLin / (
POW2(m_UInfinity) * m_noEmbeddedBodies) <<
" rotational "
13657 << EkBRot / (
POW2(m_UInfinity * m_noEmbeddedBodies)) <<
" terminal "
13658 << EkBTerm / (
POW2(m_UInfinity) * m_noEmbeddedBodies) << endl;
13659 m_log <<
"InitBodyFluidVelocities: volumes " << setprecision(12) <<
"fluid " << volF <<
" analytical "
13660 << volFAnalytical <<
" bodies " << volB <<
" volBAnalytical " << volBAnalytical << endl;
13669template <MInt nDim,
class SysEqn>
13700template <MInt nDim,
class SysEqn>
13705 execRungeKuttaStep =
nullptr;
13718 ? Context::getSolverProperty<MBool>(
"rungeKuttaStandardMb", m_solverId, AT_)
13722 if(!m_standardRK && !m_dualTimeStepping) {
13725 }
else if(m_standardRK && !m_dualTimeStepping) {
13728 }
else if(m_dualTimeStepping) {
13733 m_noRKSteps = Context::getSolverProperty<MInt>(
"noRKSteps", m_solverId, AT_);
13736 if(m_RKalpha !=
nullptr) {
13739 mAlloc(m_RKalpha, m_noRKSteps,
"m_RKalpha", F0, AT_);
13741 for(
MInt i = 0; i < m_noRKSteps; i++) {
13742 m_RKalpha[i] = Context::getSolverProperty<MFloat>(
"rkalpha-step", m_solverId, AT_, i);
13752template <MInt nDim,
class SysEqn>
13756 setRungeKuttaFunctionPointer();
13760 m_physicalTimeDt1 = m_physicalTime;
13763 for(
MInt cellId = a_noCells() - 1; cellId >= 0; --cellId) {
13764 for(
MInt varId = 0; varId < m_noCVars; varId++) {
13765 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
13769 computeCellVolumes();
13777template <MInt nDim,
class SysEqn>
13781 if(!m_levelSetMb) applyBoundaryConditionMb();
13782 if(m_trackBodySurfaceData) computeBodySurfaceData();
13790template <MInt nDim,
class SysEqn>
13794 for(
MInt i = 0; i < noNeighborDomains(); i++) {
13795 for(
MInt j = 0; j < m_noMaxLevelHaloCells[i]; j++) {
13796 MInt cellId = m_maxLevelHaloCells[i][j];
13797 setConservativeVariables(cellId);
13801 if(grid().azimuthalPeriodicity()) {
13802 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
13803 for(
MUint j = 0; j < m_azimuthalMaxLevelHaloCells[i].size(); j++) {
13804 MInt cellId = m_azimuthalMaxLevelHaloCells[i][j];
13805 setConservativeVariables(cellId);
13811 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
13812 const MInt cellId = m_splitCells[sc];
13813 if(!a_isHalo(cellId))
continue;
13815 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
13816 const MInt splitChildId = m_splitChilds[sc][ssc];
13817 for(
MInt v = 0; v < m_noCVars; v++) {
13818 a_variable(splitChildId, v) = a_variable(cellId, v);
13820 for(
MInt v = 0; v < m_noFVars; v++) {
13821 a_rightHandSide(splitChildId, v) = a_rightHandSide(cellId, v);
13822 m_rhs0[splitChildId][v] = m_rhs0[cellId][v];
13824 volCnt += a_cellVolume(splitChildId);
13826 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
13827 const MInt splitChildId = m_splitChilds[sc][ssc];
13828 volCnt =
mMax(volCnt, 1e-15);
13829 for(
MInt v = 0; v < m_noFVars; v++) {
13830 a_rightHandSide(splitChildId, v) *= a_cellVolume(splitChildId) / volCnt;
13831 m_rhs0[splitChildId][v] *= a_cellVolume(splitChildId) / volCnt;
13833 setPrimitiveVariables(splitChildId);
13839 if(m_RKStep == 0 && m_noPointParticles > 0) advancePointParticles();
13842 if(m_conservationCheck) {
13843 MBool& firstRun = m_static_applyBoundaryCondition_firstRun;
13855 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
13856 if(a_isBndryGhostCell(cellId))
continue;
13857 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
13858 if(a_isPeriodic(cellId))
continue;
13859 if(a_isHalo(cellId))
continue;
13860 if(c_noChildren(cellId) > 0)
continue;
13861 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
13863 if(a_coordinate(cellId, 0) > m_bodyCenter[0])
continue;
13864 rhs += a_rightHandSide(cellId, CV->RHO);
13866 for(
MInt i = 0; i < nDim; i++)
13867 vel +=
POW2(a_pvariable(cellId, PV->VV[i]) - m_VVInfinity[i]);
13869 eRhoL1 += fabs(a_pvariable(cellId, PV->RHO) - m_rhoInfinity);
13870 eRhoL2 +=
POW2(a_pvariable(cellId, PV->RHO) - m_rhoInfinity);
13871 eRhoLoo =
mMax(eRhoLoo, fabs(a_pvariable(cellId, PV->RHO) - m_rhoInfinity));
13872 eVelL1 += fabs(vel);
13873 eVelL2 +=
POW2(vel);
13874 eVelLoo =
mMax(eVelLoo, fabs(vel));
13876 mass += a_cellVolume(cellId) * a_variable(cellId, CV->RHO);
13877 vol += a_cellVolume(cellId);
13878 oldVol += m_cellVolumesDt1[cellId];
13882 for(
MInt bs = 0; bs < m_fvBndryCnd->m_noBoundarySurfaces; bs++) {
13883 MInt srfcId = m_fvBndryCnd->m_boundarySurfaces[bs];
13884 if(a_surfaceBndryCndId(srfcId) / 1000 == 3) {
13887 if(a_isBndryGhostCell(a_surfaceNghbrCellId(srfcId, 0)))
13888 delta -= a_surfaceFlux(srfcId, CV->RHO);
13890 delta += a_surfaceFlux(srfcId, CV->RHO);
13891 area += a_surfaceArea(srfcId);
13893 MPI_Allreduce(MPI_IN_PLACE, &mass, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"mass");
13894 MPI_Allreduce(MPI_IN_PLACE, &delta, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"delta");
13895 MPI_Allreduce(MPI_IN_PLACE, &vol, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"vol");
13896 MPI_Allreduce(MPI_IN_PLACE, &oldVol, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"oldVol");
13897 MFloat& ERhoL1 = m_static_applyBoundaryCondition_ERhoL1;
13898 MFloat& ERhoL2 = m_static_applyBoundaryCondition_ERhoL2;
13899 MFloat& ERhoLoo = m_static_applyBoundaryCondition_ERhoLoo;
13900 MFloat& EVelL1 = m_static_applyBoundaryCondition_EVelL1;
13901 MFloat& EVelL2 = m_static_applyBoundaryCondition_EVelL2;
13902 MFloat& EVelLoo = m_static_applyBoundaryCondition_EVelLoo;
13903 MFloat& refMass = m_static_applyBoundaryCondition_refMass;
13904 MFloat& oldMass = m_static_applyBoundaryCondition_oldMass;
13905 MFloat& oldVol2 = m_static_applyBoundaryCondition_oldVol2;
13919 ERhoLoo =
mMax(ERhoLoo, eRhoLoo);
13922 EVelLoo =
mMax(EVelLoo, eVelLoo);
13923 refMass -= timeStep() * delta;
13924 oldMass -= timeStep() * delta;
13926 if(domainId() == 0) {
13929 ofl.open(
"mass_loss", ios_base::out | ios_base::trunc);
13931 ofl.open(
"mass_loss", ios_base::out | ios_base::app);
13932 cerr <<
"mass defect" <<
globalTimeStep <<
" (" << delta * timeStep() <<
") " << refMass - mass <<
" "
13934 <<
" //vol " << vol - oldVol <<
" (" << oldVol - oldVol2 <<
") " << setprecision(16)
13935 << timeStep() * (rhs - delta);
13936 if(m_noCellsInsideSpongeLayer > 0) cerr <<
" | Warning: sponge is on!";
13937 cerr << setprecision(6) << endl;
13938 if(ofl.is_open() && ofl.good()) {
13939 ofl <<
"mass defect" << setprecision(10) <<
globalTimeStep <<
" (" << delta * timeStep() <<
") "
13940 << refMass - mass <<
" " << oldMass - mass
13941 <<
" //vol " << vol - oldVol <<
" (" << oldVol - oldVol2 <<
") " << timeStep() * (rhs - delta) << endl;
13945 if(m_initialCondition == 474) {
13946 cerr << domainId() <<
": ERROR rho " <<
globalTimeStep <<
" " << m_bodyCenter[0] / m_bodyDiameter[0] <<
" // "
13947 << eRhoLoo <<
" " << eRhoL1 / counter <<
" " << sqrt(eRhoL2 / counter) <<
" // " << ERhoLoo <<
" "
13948 << ERhoL1 / (counter * FTS) <<
" " << sqrt(ERhoL2 / (counter * FTS));
13949 cerr <<
" ||| ERROR vel " << eVelLoo <<
" " << eVelL1 / counter <<
" " << sqrt(eVelL2 / counter) <<
" // "
13950 << EVelLoo <<
" " << EVelL1 / (counter * FTS) <<
" " << sqrt(EVelL2 / (counter * FTS)) << endl;
13951 if(domainId() == 0) {
13953 ofl.open(
"mass_error", ios_base::out | ios_base::app);
13954 if(ofl.is_open() && ofl.good()) {
13955 ofl << setprecision(16) << m_time <<
" " << fabs(refMass - mass) <<
" " << fabs(oldMass - mass) <<
" "
13956 << eRhoLoo <<
" " << eRhoL1 / counter <<
" " << eVelLoo <<
" " << eVelL1 / counter << endl;
13960 if(m_bodyCenter[0] > m_bodyDiameter[0])
mTerm(0, AT_,
"one diameter traveled.");
13973template <MInt nDim,
class SysEqn>
13977 if(m_dualTimeStepping)
return;
13979 const MUint noFluxVars = FV->noVariables;
13980 const MUint noPVars = PV->noVariables;
13981 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
13982 const MUint surfaceVarMemory = 2 * noPVars;
13983 MFloat* RESTRICT area = &a_surfaceArea(0);
13984 MFloat*
const RESTRICT fluxes = ALIGNED_MF(&a_surfaceFlux(0, 0));
13985 MFloat*
const RESTRICT surfaceVars = ALIGNED_F(&a_surfaceVariable(0, 0, 0));
13987 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
13988 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
13990 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
13991 if(a_isHalo(cellId))
continue;
13993#if defined _ALE_FORM_
13994 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
13996 if(a_hasProperty(cellId, SolverCell::IsSplitCell) || a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
14001 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
14002 totalArea += m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
14006 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
14007 for(
MInt i = 0; i < nDim; i++) {
14008 MInt srfcId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i];
14009 if(srfcId < 0)
continue;
14011#if defined _MB_DEBUG_ || !defined NDEBUG
14012 MFloat area0 = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
14013 MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
14014 ASSERT(fabs(area[srfcId] - area0 * fabs(nml)) < 1e-12,
14015 to_string(area[srfcId]) +
" " + to_string(area0 * fabs(nml)));
14019#if defined _ALE_FORM_
14020 const MUint fluxOffset = srfcId * noFluxVars;
14021 const MUint offset = srfcId * surfaceVarMemory;
14022 MFloat*
const RESTRICT flux = ALIGNED_MF(fluxes + fluxOffset);
14023 MFloat*
const RESTRICT leftSurface = ALIGNED_F(surfaceVars + offset);
14024 const MFloat*
const bndrySurf = &m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_primVars[0];
14026 sysEqn().AusmALECorrection(i, area[srfcId], flux, leftSurface, bndrySurf);
14029 const MFloat PLR = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_primVars[PV->P];
14030 const MFloat VLR = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]];
14034 for(
MInt v = 0; v < m_noCVars; v++) {
14037 work[CV->RHO_VV[i]] = PLR * area[srfcId];
14038 work[CV->RHO_E] = PLR * VLR * area[srfcId];
14040 a_surfaceVariable(srfcId, 0, PV->VV[i]) = VLR;
14041 a_surfaceVariable(srfcId, 1, PV->VV[i]) = VLR;
14043 const MFloat sign = (nml > F0) ? -F1 : F1;
14044 const MFloat dVdt = (a_cellVolume(cellId) - m_cellVolumesDt1[cellId]) / timeStep();
14047 for(
MInt v = 0; v < m_noCVars; v++) {
14048 if(std::isnan(work[v]) || std::isnan(sign * fac * a_oldVariable(cellId, v) * dVdt)) {
14049 cerr << domainId() <<
": cell " << cellId <<
" diverged after ALE formulation at " <<
globalTimeStep <<
" "
14050 << srfc <<
" " << i <<
" " << v <<
" " << a_hasProperty(cellId, SolverCell::WasInactive) <<
" /flx "
14051 << work[v] <<
" " << sign <<
" " << fac <<
" " << a_oldVariable(cellId, v) <<
" /vol " << dVdt <<
" "
14052 << a_cellVolume(cellId) <<
" " << m_cellVolumesDt1[cellId] <<
" /var " << PLR <<
" "
14053 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_primVars[v] << endl;
14057 for(
MInt v = 0; v < m_noCVars; v++) {
14058 a_surfaceFlux(srfcId, v) = (sign * fac * a_oldVariable(cellId, v) * dVdt) + work[v];
14072template <MInt nDim,
class SysEqn>
14076 MBool& mbSpongeLayer = m_static_updateSpongeLayer_mbSpongeLayer;
14077 MBool& first = m_static_updateSpongeLayer_first;
14092 mbSpongeLayer = Context::getSolverProperty<MBool>(
"mbSpongeLayer", m_solverId, AT_, &mbSpongeLayer);
14095 if(!mbSpongeLayer) {
14098 if(m_spongeLayerThickness > F0) {
14100 MFloat deltaP, deltaRho;
14101 MFloat FgammaMinusOne = F1 / (m_gamma - F1);
14105 for(
MInt c = 0; c < m_noCellsInsideSpongeLayer; c++) {
14106 cellId = m_cellsInsideSpongeLayer[c];
14109 deltaP = (a_pvariable(cellId, PV->P) - m_PInfinity) * FgammaMinusOne;
14110 deltaRho = a_pvariable(cellId, PV->RHO) - m_rhoInfinity * m_targetDensityFactor;
14112 if((m_initialCondition == 455) || (m_initialCondition == 456) || (m_initialCondition == 45300)) {
14113 a_rightHandSide(cellId, CV->RHO) +=
14114 a_spongeFactor(cellId) * fac * (a_variable(cellId, CV->RHO) - m_rhoInfinity) * a_cellVolume(cellId);
14115 a_rightHandSide(cellId, CV->RHO_E) +=
14116 a_spongeFactor(cellId) * fac * (a_variable(cellId, CV->RHO_E) - m_rhoEInfinity) * a_cellVolume(cellId);
14117 for(
MInt i = 0; i < nDim; i++) {
14118 a_rightHandSide(cellId, CV->RHO_VV[i]) +=
14119 a_spongeFactor(cellId) * fac * (a_variable(cellId, CV->RHO_VV[i]) - F0) * a_cellVolume(cellId);
14123 else if(m_initialCondition == 45301) {
14124 a_rightHandSide(cellId, CV->RHO) +=
14125 a_spongeFactor(cellId) * fac * (a_variable(cellId, CV->RHO) - m_rhoInfinity) * a_cellVolume(cellId);
14126 a_rightHandSide(cellId, CV->RHO_E) +=
14127 a_spongeFactor(cellId) * fac * (a_variable(cellId, CV->RHO_E) - m_rhoEInfinity) * a_cellVolume(cellId);
14128 for(
MInt i = 0; i < nDim; i++) {
14129 a_rightHandSide(cellId, CV->RHO_VV[i]) += a_spongeFactor(cellId) * fac
14130 * (a_variable(cellId, CV->RHO_VV[i]) - m_rhoVVInfinity[i])
14131 * a_cellVolume(cellId);
14136 a_rightHandSide(cellId, CV->RHO_E) += a_spongeFactor(cellId) * deltaP * fac * a_cellVolume(cellId);
14137 a_rightHandSide(cellId, CV->RHO) += a_spongeFactor(cellId) * deltaRho * fac * a_cellVolume(cellId);
14140 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
14141 for(
MInt r = 0; r < m_noRansEquations; ++r) {
14142 a_rightHandSide(cellId, CV->RHO_NN[r]) +=
14143 a_spongeFactor(cellId) * deltaRho * a_pvariable(cellId, PV->NN[r]) * fac * a_cellVolume(cellId);
14147 for(
MInt s = 0; s < m_noSpecies; s++)
14148 a_rightHandSide(cellId, CV->RHO_Y[s]) +=
14149 a_spongeFactor(cellId) * deltaRho * a_pvariable(cellId, PV->Y[s]) * fac * a_cellVolume(cellId);
14161template <MInt nDim,
class SysEqn>
14165 if(m_RKStep == m_noRKSteps - 1) {
14169 MFloat beta = 1 / m_RKalpha[m_RKStep - 1];
14170 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14171 if(!a_hasProperty(cellId, SolverCell::IsActive))
continue;
14172 for(
MInt var = 0; var < CV->noVariables; var++) {
14173 a_rightHandSide(cellId, var) += beta * a_externalSource(cellId, var);
14174 if(std::isnan(a_externalSource(cellId, var))) {
14175 cerr << domainId() <<
" " << cellId <<
" " << var <<
" " << a_coordinate(cellId, 0) <<
" "
14176 << a_coordinate(cellId, 1) <<
" " << a_coordinate(cellId, nDim - 1) <<
" " << var << endl;
14177 mTerm(1, AT_,
"External source is nan!");
14182 if(m_RKStep != 3) {
14186 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14187 if(!a_hasProperty(cellId, SolverCell::IsActive))
continue;
14188 for(
MInt var = 0; var < CV->noVariables; var++) {
14189 a_rightHandSide(cellId, var) += a_externalSource(cellId, var);
14194 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14195 if(!a_hasProperty(cellId, SolverCell::IsActive))
continue;
14196 for(
MInt var = 0; var < CV->noVariables; var++) {
14197 a_rightHandSide(cellId, var) += m_externalSourceDt1[cellId][var];
14207template <MInt nDim,
class SysEqn>
14211 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14212 if(!a_hasProperty(cellId, SolverCell::IsActive))
continue;
14213 for(
MInt var = 0; var < CV->noVariables; var++) {
14214 m_rhs0[cellId][var] -= m_externalSourceDt1[cellId][var];
14223template <MInt nDim,
class SysEqn>
14225 if(!m_hasExternalSource)
return;
14227 const MInt noCBytes = a_noCells() * m_noCVars *
sizeof(
MFloat);
14228 memcpy(&m_externalSourceDt1[0][0], &(a_externalSource(0, 0)), noCBytes);
14235template <MInt nDim,
class SysEqn>
14239 if(m_initialCondition == 22) {
14240 MFloat noPeriodicDirs = 0;
14241 for(
MInt dim = 0; dim < nDim; dim++) {
14242 if(grid().periodicCartesianDir(dim)) {
14243 m_volumeForcingDir = dim;
14247 if(noPeriodicDirs > 1)
mTerm(1, AT_,
"Only one periodic direction is implemented for the pipe case");
14248 if(m_volumeForcingDir == -1)
mTerm(-1, AT_,
"IC 22 requires a volumeForcingDir");
14251 MInt Re_r = Context::getSolverProperty<MFloat>(
"Re", m_solverId, AT_) * m_pipeRadius;
14252 m_pipeRadius = Context::getSolverProperty<MFloat>(
"pipeRadius", m_solverId, AT_);
14255 const MInt rDir1 = ((m_volumeForcingDir + 1) % nDim);
14256 const MInt rDir2 = ((rDir1 + 1) % nDim);
14257 if(rDir1 == rDir2 || rDir1 == m_volumeForcingDir || rDir2 == m_volumeForcingDir)
14258 mTerm(-1, AT_,
"Inconsistent dirs.");
14260 const MFloat pipeLength = computeDomainLength(m_volumeForcingDir);
14262 cerr0 <<
"Update infinity state for IC 22: found pipeRadius = " << m_pipeRadius
14263 <<
" and pipeLength = " << pipeLength << endl;
14267 lambda = 32.0 / Re_r;
14268 if(domainId() == 0) cerr <<
"IC 22, using case Re<1500" << endl;
14270 lambda = 0.316 / pow(Re_r * F2, 0.25);
14271 if(domainId() == 0) cerr <<
"IC 22, using case Re>=1500" << endl;
14273 MFloat reTau = Re_r * sqrt(lambda / F8);
14274 MFloat uTau = reTau * m_Ma * sqrt(m_TInfinity) / Re_r;
14275 MFloat deltaP = F2 * m_rhoInfinity *
POW2(uTau) * (pipeLength) / m_pipeRadius;
14276 m_volumeAcceleration[m_volumeForcingDir] = deltaP / (m_rhoInfinity * pipeLength);
14280 if(!m_constructGField)
return;
14282 if(m_initialCondition == 15 || m_initialCondition == 16 || m_initialCondition == 467) {
14283 m_rhoInfinity = F1;
14285 m_PInfinity = sysEqn().pressure_ES(m_TInfinity, m_rhoInfinity);
14286 m_UInfinity = m_Ma;
14290 m_rhoUInfinity = m_rhoInfinity * m_UInfinity;
14291 m_rhoVInfinity = m_rhoInfinity * m_VInfinity;
14292 m_rhoWInfinity = m_rhoInfinity * m_WInfinity;
14293 m_rhoEInfinity = sysEqn().internalEnergy(m_PInfinity, m_rhoInfinity,
POW2(m_Ma));
14294 m_hInfinity = sysEqn().enthalpy(m_PInfinity, m_rhoInfinity);
14295 sysEqn().m_Re0 = m_Re * SUTHERLANDLAW(m_TInfinity) / (m_rhoInfinity * m_UInfinity);
14296 sysEqn().m_muInfinity = SUTHERLANDLAW(m_TInfinity);
14298 m_VVInfinity[0] = m_UInfinity;
14299 m_VVInfinity[1] = m_VInfinity;
14300 m_VVInfinity[2] = m_WInfinity;
14301 m_rhoVVInfinity[0] = m_rhoUInfinity;
14302 m_rhoVVInfinity[1] = m_rhoVInfinity;
14303 m_rhoVVInfinity[2] = m_rhoWInfinity;
14305 if(m_restartFile) {
14306 m_log <<
"Restart Reynolds number: " << setprecision(15) << m_Re <<
" (Re_L=" << m_Re * (m_bbox[3] - m_bbox[0])
14308 <<
" " << sysEqn().m_Re0 << endl;
14312 if((m_initialCondition == 465 || m_initialCondition == 466) && m_constructGField) {
14313 m_rhoInfinity = F1;
14315 m_PInfinity = sysEqn().pressure_ES(m_TInfinity, m_rhoInfinity);
14316 m_UInfinity = m_Ma;
14319 m_VVInfinity[0] = m_UInfinity;
14320 m_VVInfinity[1] = m_VInfinity;
14321 m_VVInfinity[2] = m_WInfinity;
14322 m_rhoUInfinity = m_rhoInfinity * m_UInfinity;
14323 m_rhoVInfinity = m_rhoInfinity * m_VInfinity;
14324 m_rhoWInfinity = m_rhoInfinity * m_WInfinity;
14325 m_rhoEInfinity = sysEqn().internalEnergy(m_PInfinity, m_rhoInfinity,
POW2(m_Ma));
14326 m_hInfinity = sysEqn().enthalpy(m_PInfinity, m_rhoInfinity);
14327 sysEqn().m_Re0 = m_Re * SUTHERLANDLAW(m_TInfinity) / (m_rhoInfinity * m_UInfinity);
14333 for(
MInt i = 0; i < nDim; i++) {
14334 m_U2 +=
POW2(m_VVInfinity[i]);
14336 m_rhoU2 = m_U2 * m_rhoInfinity;
14344template <MInt nDim,
class SysEqn>
14346 return sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
14352template <MInt nDim,
class SysEqn>
14364 IF_CONSTEXPR(SysEqn::m_noRansEquations == 0) {
14368 mAlloc(m_LESVarAverageBal, m_LESNoVarAverage,
"m_LESVarAverage", AT_);
14369 for(
MInt var = 0; var < m_LESNoVarAverage; var++) {
14370 m_LESVarAverageBal[var].resize(noInternalCells());
14378 m_onlineRestart =
true;
14381 m_maxLevelBeforeAdaptation = -1;
14383 m_maxLevelBeforeAdaptation = maxLevel();
14386 mAlloc(m_sweptVolumeBal, c_noCells(),
"m_sweptVolumeBal", -F1, AT_);
14393template <MInt nDim,
class SysEqn>
14397 m_loadBalancingReinitStage = 1;
14400 m_cells.append(c_noCells() - m_cells.size());
14402 copyGridProperties();
14404 m_totalnoghostcells = 0;
14405 m_totalnosplitchilds = 0;
14406 ASSERT(m_cells.size() == c_noCells() && c_noCells() == a_noCells(),
"");
14409 m_oldBndryCells.clear();
14410 std::map<MInt, std::vector<MFloat>>().swap(m_nearBoundaryBackup);
14411 std::vector<MInt>().swap(m_bndryLayerCells);
14412 std::vector<MInt>().swap(m_massRedistributionIds);
14413 std::vector<MFloat>().swap(m_massRedistributionVariables);
14414 std::vector<MFloat>().swap(m_massRedistributionRhs);
14415 std::vector<MFloat>().swap(m_massRedistributionVolume);
14416 std::vector<MFloat>().swap(m_massRedistributionSweptVol);
14417 std::vector<std::tuple<MInt, MInt, MInt>>().swap(m_temporarilyLinkedCells);
14429 if(!grid().isActive()) {
14433 m_bndryGhostCellsOffset = a_noCells();
14434 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
14435 a_bndryId(cellId) = -1;
14436 a_isBndryGhostCell(cellId) =
false;
14437 a_hasProperty(cellId, SolverCell::IsSplitChild) =
false;
14441 this->checkNoHaloLayers();
14445 computeDomainAndSpongeDimensions();
14448 allocateCommunicationMemory();
14450 if(!m_fvBndryCnd->m_cellMerging) {
14451 mDeallocate(m_fvBndryCnd->m_nearBoundaryWindowCells);
14452 mDeallocate(m_fvBndryCnd->m_nearBoundaryHaloCells);
14453 mAlloc(m_fvBndryCnd->m_nearBoundaryWindowCells, noNeighborDomains(),
"m_nearBoundaryWindowCells", AT_);
14454 mAlloc(m_fvBndryCnd->m_nearBoundaryHaloCells, noNeighborDomains(),
"m_nearBoundaryHaloCells", AT_);
14457 std::vector<MInt>().swap(m_splitCells);
14458 std::vector<std::vector<MInt>>().swap(m_splitChilds);
14459 std::map<MInt, MInt>().swap(m_splitChildToSplitCell);
14460 m_totalnosplitchilds = 0;
14463 if(this->m_adaptation) {
14464 for(
MInt i = 0; i < maxNoGridCells(); i++)
14465 m_recalcIds[i] = i;
14469 if(grid().azimuthalPeriodicity()) {
14470 m_azimuthalNearBoundaryBackup.clear();
14471 initAzimuthalCartesianHaloInterpolation();
14473 MInt noFloatData_ = nDim + m_noFloatDataBalance;
14474 MInt noLongData = m_azimuthalNearBoundaryBackupMaxCount * m_noLongDataBalance;
14475 MInt noFloatData = m_azimuthalNearBoundaryBackupMaxCount * noFloatData_;
14477 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14478 for(
MInt cnt = 0; cnt < m_azimuthalNearBoundaryBackupMaxCount; cnt++) {
14479 MInt longIndex = cnt * m_noLongDataBalance;
14481 MLong gCellId = m_azimuthalNearBoundaryBackupBalLong[cellId * noLongData + longIndex];
14483 if(gCellId == -1) {
14487 ASSERT(gCellId == c_globalId(cellId),
"Azimuthal balance, this is not correct. " + to_string(cellId) +
" "
14488 + to_string(c_globalId(cellId)) +
" " + to_string(gCellId) +
" "
14489 + to_string(domainId()));
14491 MInt offset = cnt * noFloatData_;
14492 vector<MFloat> tmpF(noFloatData_);
14493 vector<MUlong> tmpI(m_noLongData);
14495 for(
MInt d = offset; d < offset + noFloatData_; d++) {
14496 tmpF[d - offset] = m_azimuthalNearBoundaryBackupBalFloat[cellId * noFloatData + d];
14499 tmpI[0] = (
MUlong)m_azimuthalNearBoundaryBackupBalLong[cellId * noLongData + longIndex + 1];
14500 tmpI[1] = (
MUlong)m_azimuthalNearBoundaryBackupBalLong[cellId * noLongData + longIndex + 2];
14502 m_azimuthalNearBoundaryBackup.insert(make_pair(gCellId, make_pair(tmpF, tmpI)));
14506 mDeallocate(m_azimuthalNearBoundaryBackupBalFloat);
14507 mDeallocate(m_azimuthalNearBoundaryBackupBalLong);
14509 m_wasBalanced =
true;
14512 exchangeData(&a_variable(0, 0), CV->noVariables);
14513 exchangeData(&a_cellVolume(0), 1);
14514 exchangeData(&a_rightHandSide(0, 0), m_noFVars);
14515 if(m_dualTimeStepping) {
14516 exchangeData(&m_cellVolumesDt1[0], 1);
14519 exchangeData(&m_sweptVolumeBal[0], 1);
14523 &a_properties(0), a_noCells());
14528 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
14529 setPrimitiveVariables(cellId);
14530 for(
MInt v = 0; v < CV->noVariables; v++) {
14531 a_oldVariable(cellId, v) = a_variable(cellId, v);
14533 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
14544 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14545 a_resetPropertiesSolver(cellId);
14548 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14549 assertValidGridCellId(cellId);
14550 if(m_dualTimeStepping) {
14551 m_cellVolumesDt2[cellId] = m_cellVolumesDt1[cellId];
14553 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
14554 for(
MInt j = 0; j < m_noFVars; j++) {
14555 m_rhs0[cellId][j] = a_rightHandSide(cellId, j);
14557 a_hasProperty(cellId, SolverCell::IsMovingBnd) = propsBalance[cellId][
maia::fv::cell::p(SolverCell::IsMovingBnd)];
14558 a_hasProperty(cellId, SolverCell::NearWall) = propsBalance[cellId][
maia::fv::cell::p(SolverCell::NearWall)];
14559 a_hasProperty(cellId, SolverCell::IsInactive) = propsBalance[cellId][
maia::fv::cell::p(SolverCell::IsInactive)];
14560 a_hasProperty(cellId, SolverCell::WasInactive) = propsBalance[cellId][
maia::fv::cell::p(SolverCell::IsInactive)];
14563 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14564 if(a_hasProperty(cellId, SolverCell::NearWall)) {
14565 vector<MFloat> tmp(max(m_noCVars + m_noFVars, 0) + 1);
14566 tmp[0] = m_cellVolumesDt1[cellId];
14567 for(
MInt v = 0; v < m_noCVars; v++) {
14568 tmp[1 + v] = a_oldVariable(cellId, v);
14570 for(
MInt v = 0; v < m_noFVars; v++) {
14571 tmp[1 + m_noCVars + v] = m_rhs0[cellId][v];
14573 m_nearBoundaryBackup.insert(make_pair(cellId, tmp));
14574 m_bndryLayerCells.push_back(cellId);
14579 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14580 if(a_hasProperty(cellId, SolverCell::IsMovingBnd)) {
14582 ASSERT(m_sweptVolumeBal[cellId] > -1,
"something is wrong with m_sweptVolumeBal");
14583 m_oldBndryCells.insert(make_pair(cellId, m_sweptVolumeBal[cellId]));
14587 if(grid().azimuthalPeriodicity()) {
14588 commAzimuthalPeriodicData(1);
14594 determineLESAverageCells();
14595 resetZonalLESAverage();
14596 resetZonalSolverData();
14598 IF_CONSTEXPR(SysEqn::m_noRansEquations == 0) {
14600 for(
MInt var = 0; var < m_LESNoVarAverage; var++) {
14602 MFloatScratchSpace exchangeLESVarAverageBal(c_noCells(), FUN_,
"exchangeIsMovingBnd");
14603 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14604 exchangeLESVarAverageBal[cellId] = m_LESVarAverageBal[var][cellId];
14606 exchangeData(&exchangeLESVarAverageBal[0], 1);
14607 for(
MInt i = 0; i < (
MInt)m_LESAverageCells.size(); i++) {
14608 MInt cellId = m_LESAverageCells[i];
14609 m_LESVarAverage[var][i] = exchangeLESVarAverageBal[cellId];
14615 MPI_Allreduce(MPI_IN_PLACE, &cnt, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"cnt");
14616 if(domainId() == 0) cerr <<
"m_noLESAverageCells: " << cnt << endl;
14619 for(
MInt var = 0; var < m_LESNoVarAverage; var++) {
14620 m_LESVarAverageBal[var].clear();
14625 copyGridProperties();
14632 mAlloc(m_sendBufferSize, noNeighborDomains(),
"m_sendBufferSize", 0, AT_);
14633 mAlloc(m_receiveBufferSize, noNeighborDomains(),
"m_receiveBufferSize", 0, AT_);
14634 mAlloc(g_mpiRequestMb, noNeighborDomains(),
"g_mpiRequestMb", MPI_REQ_NULL, AT_);
14635 mAlloc(m_linkedWindowCells, noNeighborDomains(),
"m_linkedWindowCells", AT_);
14636 mAlloc(m_linkedHaloCells, noNeighborDomains(),
"m_linkedHaloCells", AT_);
14638 for(
MInt i = 0; i < noNeighborDomains(); i++) {
14639 m_linkedWindowCells[i].clear();
14640 m_linkedHaloCells[i].clear();
14644 mAlloc(m_gapWindowCells, noNeighborDomains(),
"m_gapWindowCells", AT_);
14645 mAlloc(m_gapHaloCells, noNeighborDomains(),
"m_gapHaloCells", AT_);
14646 for(
MInt i = 0; i < noNeighborDomains(); i++) {
14647 m_gapWindowCells[i].clear();
14648 m_gapHaloCells[i].clear();
14652 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
14653 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
14656 computeLocalBoundingBox();
14658 ASSERT(m_cells.size() == c_noCells(),
"");
14660 if(this->m_adaptation) {
14661 m_adaptationSinceLastRestart =
true;
14662 m_adaptationSinceLastRestartBackup =
true;
14665 m_loadBalancingReinitStage = 2;
14667#if defined _MB_DEBUG_ || !defined NDEBUG
14668 if(domainId() == 0) {
14669 cerr <<
"Checking cells after balance... ";
14671 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
14672 for(
MInt v = 0; v < CV->noVariables; v++) {
14673 if(std::isnan(a_variable(cellId, v)) && !a_hasProperty(cellId, SolverCell::IsInactive)) {
14674 cerr <<
"Nan in variable after balance " << cellId <<
" "
14675 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) << endl;
14678 if((a_variable(cellId, CV->RHO) < 0 || a_pvariable(cellId, PV->RHO) < 0)
14679 && !a_hasProperty(cellId, SolverCell::IsInactive)) {
14680 cerr <<
"Neg. density after balance" << cellId << endl;
14683 if(domainId() == 0) cerr <<
"finished. " << endl;
14692template <MInt nDim,
class SysEqn>
14694 const MInt*
const noCellsToSendByDomain,
14695 const MInt*
const sortedCellId,
const MInt oldNoCells) {
14699 m_onlineRestart =
true;
14716 MFloatScratchSpace RHS(noCellsToReceiveByDomain[noDomains()], CV->noVariables, FUN_,
"RHS");
14717 MFloatScratchSpace cellVolumesDt1((m_dualTimeStepping ? noCellsToReceiveByDomain[noDomains()] : 1), FUN_,
14720 MFloatScratchSpace sweptVol(noCellsToReceiveByDomain[noDomains()], FUN_,
"sweptVol");
14722 MBool azimuthal = grid().azimuthalPeriodicity();
14727 MFloatScratchSpace rightHandSideBalance(oldNoCells, CV->noVariables, FUN_,
"rightHandSideBalance");
14730 sweptVolBalance.
fill(std::numeric_limits<MFloat>::lowest());
14733 rightHandSideBalance.
fill(-1);
14734 volumeDt1Balance.
fill(-1);
14736 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14737 assertValidGridCellId(cellId);
14738 MInt gridCellId = grid().tree().solver2grid(cellId);
14740 propsBalance(gridCellId) = a_properties(cellId);
14742 for(
MInt variable = 0; variable < CV->noVariables; variable++) {
14743 rightHandSideBalance(gridCellId, variable) = a_rightHandSide(cellId, variable);
14746 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
14747 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
14748 ASSERT(!a_isBndryGhostCell(cellId),
"");
14749 if(a_isHalo(cellId))
continue;
14750 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
14751 assertValidGridCellId(cellId);
14752 MInt gridCellId = grid().tree().solver2grid(cellId);
14754 ASSERT(a_hasProperty(cellId, SolverCell::IsMovingBnd),
"");
14755 sweptVolBalance(gridCellId) = m_sweptVolume[bndryId];
14758 if(m_dualTimeStepping) {
14759 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14760 MInt gridCellId = grid().tree().solver2grid(cellId);
14761 volumeDt1Balance(gridCellId) = m_cellVolumesDt1[cellId];
14768 MInt noAziDataToSend = 1;
14769 MInt noAziDataToReceive = 1;
14771 sndSizeAzi.
fill(0);
14773 rcvSizeAzi.
fill(0);
14775 sortedIdMap.
fill(0);
14777 m_wasBalanced =
true;
14780 sortedCntsAzi.
fill(0);
14781 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14782 MInt gridCellId = grid().tree().solver2grid(cellId);
14783 if(sortedCellId[gridCellId] < 0)
continue;
14784 MLong gCellId = c_globalId(cellId);
14785 sortedCntsAzi[sortedCellId[gridCellId]] = m_azimuthalNearBoundaryBackup.count(gCellId);
14788 for(
MInt i = 0; i < oldNoCells; i++) {
14789 sortedIdMap[i] = cnt;
14790 cnt += sortedCntsAzi[i];
14793 for(
MInt i = 0; i < noDomains(); i++) {
14794 for(
MInt j = 0; j < noCellsToSendByDomain[i]; j++) {
14795 sndSizeAzi[i] += sortedCntsAzi[offset + j];
14797 offset += noCellsToSendByDomain[i];
14800 dummyScratch.
fill(1);
14802 &dummyScratch[0], &rcvSizeAzi[0]);
14804 noAziDataToSend =
mMax(1, std::accumulate(&sndSizeAzi[0], &sndSizeAzi[0] + noDomains(), 0));
14805 noAziDataToReceive =
mMax(1, std::accumulate(&rcvSizeAzi[0], &rcvSizeAzi[0] + noDomains(), 0));
14810 MFloatScratchSpace cellVolumesDt1Azi(noAziDataToReceive, FUN_,
"cellVolumesDt1Azi");
14814 MFloatScratchSpace variablesAzi(noAziDataToReceive, CV->noVariables, FUN_,
"variablesAzi");
14815 MFloatScratchSpace imageCoordsAzi(noAziDataToReceive, nDim, FUN_,
"imageCoordsAzi");
14816 globalIdAzi.
fill(-1);
14817 cellVolumesAzi.
fill(-1.0);
14818 cellVolumesDt1Azi.
fill(-1.0);
14819 sweptVolAzi.
fill(std::numeric_limits<MFloat>::lowest());
14820 bndryCntAzi.
fill(0);
14822 variablesAzi.
fill(-1.0);
14823 imageCoordsAzi.
fill(-1.0);
14824 MLongScratchSpace globalIdAziBalance(noAziDataToSend, FUN_,
"globalIdAziBalance");
14825 MFloatScratchSpace cellVolumesAziBalance(noAziDataToSend, FUN_,
"cellVolumesAziBalance");
14826 MFloatScratchSpace cellVolumesDt1AziBalance(noAziDataToSend, FUN_,
"cellVolumesDt1AziBalance");
14830 MFloatScratchSpace variablesAziBalance(noAziDataToSend, CV->noVariables, FUN_,
"variablesAziBalance");
14831 MFloatScratchSpace imageCoordsAziBalance(noAziDataToSend, nDim, FUN_,
"imageCoordsAziAziBalance");
14832 globalIdAziBalance.
fill(-1);
14833 cellVolumesAziBalance.
fill(-1);
14834 cellVolumesDt1AziBalance.
fill(-1);
14835 sweptVolAziBalance.
fill(std::numeric_limits<MFloat>::lowest());
14836 bndryCntAziBalance.
fill(0);
14837 propsAziBalance.
fill(0);
14838 variablesAziBalance.
fill(-1.0);
14839 imageCoordsAziBalance.
fill(-1.0);
14842 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
14843 MInt gridCellId = grid().tree().solver2grid(cellId);
14844 if(sortedCellId[gridCellId] < 0)
continue;
14845 MLong gCellId = c_globalId(cellId);
14846 if(m_azimuthalNearBoundaryBackup.count(gCellId) != 0) {
14848 auto range = m_azimuthalNearBoundaryBackup.equal_range(gCellId);
14849 for(
auto it = range.first; it != range.second; ++it) {
14850 globalIdAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt) = gCellId;
14851 cellVolumesAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt) = (it->second).first[nDim];
14852 cellVolumesDt1AziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt) = (it->second).first[nDim + 1];
14853 sweptVolAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt) = (it->second).first[nDim + 2];
14854 bndryCntAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt) = (it->second).second[0];
14855 propsAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt) = (it->second).second[1];
14856 for(
MInt v = 0; v < CV->noVariables; v++) {
14857 variablesAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt, v) = (it->second).first[nDim + 3 + v];
14859 for(
MInt d = 0; d < nDim; d++) {
14860 imageCoordsAziBalance(sortedIdMap[sortedCellId[gridCellId]] + cnt, d) = (it->second).first[d];
14868 &rcvSizeAzi[0], &globalIdAzi[0]);
14870 &rcvSizeAzi[0], &cellVolumesAzi[0]);
14872 &rcvSizeAzi[0], &cellVolumesDt1Azi[0]);
14874 &rcvSizeAzi[0], &sweptVolAzi[0]);
14876 &rcvSizeAzi[0], &bndryCntAzi[0]);
14878 &rcvSizeAzi[0], &propsAzi[0]);
14880 &sndSizeAzi[0], &rcvSizeAzi[0], &variablesAzi[0]);
14882 &rcvSizeAzi[0], &imageCoordsAzi[0]);
14886 m_azimuthalNearBoundaryBackup.clear();
14887 MInt noFloatData = nDim + sysEqn().CV->noVariables + 3;
14888 MInt noIntData = 2;
14889 for(
MInt i = 0; i < noDomains(); i++) {
14890 for(
MInt j = 0; j < rcvSizeAzi[i]; j++) {
14891 MInt ind = offset + j;
14892 MLong gCellId = globalIdAzi[ind];
14893 vector<MFloat> tmpF(
mMax(noFloatData + nDim, nDim + 3));
14894 vector<MUlong> tmpI(noIntData);
14895 for(
MInt d = 0; d < nDim; d++) {
14896 tmpF[d] = imageCoordsAzi(ind, d);
14898 tmpF[nDim] = cellVolumesAzi[ind];
14899 tmpF[nDim + 1] = cellVolumesDt1Azi[ind];
14900 tmpF[nDim + 2] = sweptVolAzi[ind];
14901 for(
MInt v = 0; v < CV->noVariables; v++) {
14902 tmpF[nDim + 3 + v] = variablesAzi(ind, v);
14905 tmpI[0] = bndryCntAzi[ind];
14906 tmpI[1] = propsAzi[ind];
14907 m_azimuthalNearBoundaryBackup.insert(make_pair(gCellId, make_pair(tmpF, tmpI)));
14909 offset += rcvSizeAzi[i];
14915 cellVolumesDt1.
fill(-1.0);
14917 sweptVol.
fill(std::numeric_limits<MFloat>::lowest());
14920 mpiComm(), noCellsToSendByDomain, noCellsToReceiveByDomain, CV->noVariables, &RHS[0]);
14921 if(m_dualTimeStepping) {
14923 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &cellVolumesDt1[0]);
14927 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &props[0]);
14929 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &sweptVol[0]);
14974 ASSERT(m_cells.size() == c_noCells(),
"");
14980 sweptVolBak.
fill(std::numeric_limits<MFloat>::lowest());
14987 for(
MInt gridCellId = 0; gridCellId < noCellsToReceiveByDomain[noDomains()]; gridCellId++) {
14988 if(!grid().raw().treeb().solver(gridCellId, m_solverId))
continue;
14992 if(!grid().raw().bitOffset()) {
14993 ASSERT(grid().tree().solver2grid(cellId) == gridCellId,
"");
14997 for(
MInt j = 0; j < CV->noVariables; j++) {
14998 a_rightHandSide(cellId, j) = RHS(gridCellId, j);
15000 if(m_dualTimeStepping) {
15001 m_cellVolumesDt1[cellId] = cellVolumesDt1(gridCellId);
15003 assertValidGridCellId(cellId);
15005 sweptVolBak(cellId) = sweptVol(gridCellId);
15006 propsBak(cellId) = props(gridCellId);
15014 &propsBak[0], m_cells.
size());
15015 exchangeData(&a_rightHandSide(0, 0), CV->noVariables);
15016 exchangeData(&sweptVolBak[0], 1);
15017 if(m_dualTimeStepping) {
15018 exchangeData(&m_cellVolumesDt1[0], 1);
15023 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
15024 assertValidGridCellId(cellId);
15025 if(m_dualTimeStepping) {
15026 m_cellVolumesDt2[cellId] = m_cellVolumesDt1[cellId];
15028 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
15029 for(
MInt j = 0; j < CV->noVariables; j++) {
15030 m_rhs0[cellId][j] = a_rightHandSide(cellId, j);
15032 a_hasProperty(cellId, SolverCell::IsMovingBnd) = propsBak[cellId][
maia::fv::cell::p(SolverCell::IsMovingBnd)];
15033 a_hasProperty(cellId, SolverCell::NearWall) = propsBak[cellId][
maia::fv::cell::p(SolverCell::NearWall)];
15034 a_hasProperty(cellId, SolverCell::IsInactive) = propsBak[cellId][
maia::fv::cell::p(SolverCell::IsInactive)];
15035 a_hasProperty(cellId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::IsInactive);
15042 m_nearBoundaryBackup.clear();
15043 m_bndryLayerCells.clear();
15044 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
15045 if(a_hasProperty(cellId, SolverCell::NearWall)) {
15046 vector<MFloat> tmp(max(m_noCVars + m_noFVars, 0) + 1);
15047 tmp[0] = m_cellVolumesDt1[cellId];
15048 for(
MInt v = 0; v < m_noCVars; v++) {
15049 tmp[1 + v] = a_oldVariable(cellId, v);
15051 for(
MInt v = 0; v < m_noFVars; v++) {
15052 tmp[1 + m_noCVars + v] = m_rhs0[cellId][v];
15054 m_nearBoundaryBackup.insert(make_pair(cellId, tmp));
15055 m_bndryLayerCells.push_back(cellId);
15059 m_oldBndryCells.clear();
15060 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
15061 if(a_hasProperty(cellId, SolverCell::IsMovingBnd)) {
15063 m_oldBndryCells.insert(make_pair(cellId, sweptVolBak[cellId]));
15068 initAzimuthalCartesianHaloInterpolation();
15069 commAzimuthalPeriodicData(1);
15078 mAlloc(m_sendBufferSize, noNeighborDomains(),
"m_sendBufferSize", 0, AT_);
15079 mAlloc(m_receiveBufferSize, noNeighborDomains(),
"m_receiveBufferSize", 0, AT_);
15080 mAlloc(g_mpiRequestMb, noNeighborDomains(),
"g_mpiRequestMb", MPI_REQ_NULL, AT_);
15081 mAlloc(m_linkedWindowCells, noNeighborDomains(),
"m_linkedWindowCells", AT_);
15082 mAlloc(m_linkedHaloCells, noNeighborDomains(),
"m_linkedHaloCells", AT_);
15085 for(
MInt i = 0; i < noNeighborDomains(); i++) {
15086 m_linkedWindowCells[i].clear();
15087 m_linkedHaloCells[i].clear();
15095 mAlloc(m_gapWindowCells, noNeighborDomains(),
"m_gapWindowCells", AT_);
15096 mAlloc(m_gapHaloCells, noNeighborDomains(),
"m_gapHaloCells", AT_);
15097 for(
MInt i = 0; i < noNeighborDomains(); i++) {
15098 m_gapWindowCells[i].clear();
15099 m_gapHaloCells[i].clear();
15103 m_massRedistributionIds.clear();
15104 m_massRedistributionVariables.clear();
15105 m_massRedistributionRhs.clear();
15106 m_massRedistributionVolume.clear();
15107 m_massRedistributionSweptVol.clear();
15108 m_temporarilyLinkedCells.clear();
15110 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
15111 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
15114 computeLocalBoundingBox();
15117 initAzimuthalCartesianHaloInterpolation();
15120 ASSERT(m_cells.size() == c_noCells(),
"");
15124#if defined _MB_DEBUG_ || !defined NDEBUG
15125 if(domainId() == 0) {
15126 cerr <<
"Checking cells after balance... ";
15128 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
15129 for(
MInt v = 0; v < CV->noVariables; v++) {
15130 if(std::isnan(a_variable(cellId, v)) && !a_hasProperty(cellId, SolverCell::IsInactive)
15131 && a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
15132 cerr <<
"Nan in variable after balance " << cellId <<
" "
15133 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) << endl;
15136 if((a_variable(cellId, CV->RHO) < 0 || a_pvariable(cellId, PV->RHO) < 0)
15137 && !a_hasProperty(cellId, SolverCell::IsInactive)) {
15138 cerr <<
"Neg. density after balance" << cellId << endl;
15141 cerr0 <<
"finished. " << endl;
15148template <MInt nDim,
class SysEqn>
15156 if(!grid().isActive()) {
15160 setRungeKuttaFunctionPointer();
15163 if(!m_trackMovingBndry) {
15164 m_fvBndryCnd->m_cellCoordinatesCorrected =
false;
15168 preSolutionStep(0);
15171 leastSquaresReconstruction();
15180template <MInt nDim,
class SysEqn>
15184 ASSERT(grid().raw().a_hasProperty(gridCellId, Cell::WasRefined),
"");
15186 const MInt childLevel = grid().raw().a_level(gridCellId) + 1;
15187 const MFloat childVolume = grid().cellVolumeAtLevel(childLevel);
15189 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
15193 if(solverCellId < 0)
return;
15196 ASSERT(c_noChildren(solverCellId) > 0,
"");
15198 MInt noAddedChilds = 0;
15200 for(
MInt c = 0; c < grid().m_maxNoChilds; c++) {
15201 const MInt gridChildId = grid().raw().a_childId(gridCellId, c);
15203 if(gridChildId < 0)
continue;
15206 if(!grid().raw().a_hasProperty(gridChildId, Cell::WasNewlyCreated)
15207 && grid().raw().a_hasProperty(gridCellId, Cell::IsPartLvlAncestor)) {
15211 const MInt solverChildId = grid().tree().grid2solver(gridChildId);
15213 if(solverChildId < 0)
continue;
15215 ASSERT(solverChildId == c_childId(solverCellId, c),
"");
15218 for(
MInt v = 0; v < m_noFVars; v++) {
15219 m_rhs0[solverChildId][v] =
FFPOW2(nDim) * m_rhs0[solverCellId][v];
15222 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
15223 a_levelSetValuesMb(solverChildId, set) = a_levelSetValuesMb(solverCellId, set);
15224 a_associatedBodyIds(solverChildId, set) = a_associatedBodyIds(solverCellId, set);
15226 m_cellVolumesDt1[solverChildId] = childVolume;
15227 if(m_dualTimeStepping) m_cellVolumesDt2[solverChildId] = childVolume;
15229 a_isGapCell(solverChildId) = a_isGapCell(solverCellId);
15230 a_wasGapCell(solverChildId) = a_wasGapCell(solverCellId);
15232 a_hasProperty(solverChildId, SolverCell::WasInactive) = a_hasProperty(solverCellId, SolverCell::WasInactive);
15237 auto it = m_oldBndryCells.find(solverCellId);
15238 if(it != m_oldBndryCells.end()) {
15239 const MFloat sweptVol = it->second;
15240 m_oldBndryCells.insert(make_pair(solverChildId, sweptVol));
15241 ASSERT(m_bndryLevelJumps,
"");
15244 if(grid().azimuthalPeriodicity()) {
15249 if(noAddedChilds > 0) {
15250 a_isGapCell(solverCellId) =
false;
15251 a_wasGapCell(solverCellId) =
false;
15260template <MInt nDim,
class SysEqn>
15262 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
15263 ASSERT(solverCellId > -1 && solverCellId < m_cells.size(),
"");
15266 ASSERT(solverCellId == gridCellId,
"");
15267 ASSERT((m_cells.size() - grid().raw().treeb().size()) <= grid().m_maxNoChilds,
"");
15270 ASSERT(grid().raw().a_noChildren(gridCellId) > 0,
"");
15276 m_cellVolumesDt1[solverCellId] = F0;
15277 for(
MInt v = 0; v < m_noCVars; v++) {
15278 a_oldVariable(solverCellId, v) = F0;
15280 for(
MInt v = 0; v < m_noFVars; v++) {
15281 m_rhs0[solverCellId][v] = F0;
15284 a_hasProperty(solverCellId, SolverCell::WasInactive) =
false;
15286 MBool wasGapCell =
false;
15287 MBool isGapCell =
false;
15288 MBool hasBndryCell =
false;
15291 MInt wasInactive = 0;
15292 MInt noRemovedChilds = 0;
15294 for(
MInt c = 0; c < grid().m_maxNoChilds; c++) {
15295 const MInt gridChildId = grid().raw().a_childId(gridCellId, c);
15296 const MInt childId = c_childId(solverCellId, c);
15297 if(childId < 0)
continue;
15300 ASSERT(grid().tree().solver2grid(childId) == gridChildId,
"");
15304 if(a_wasGapCell(childId)) wasGapCell =
true;
15305 if(a_isGapCell(childId)) isGapCell =
true;
15307 if(a_hasProperty(childId, SolverCell::WasInactive)) {
15310 MFloat vol1 = m_cellVolumesDt1[childId];
15311 m_cellVolumesDt1[solverCellId] += vol1;
15312 for(
MInt v = 0; v < m_noCVars; v++) {
15313 a_oldVariable(solverCellId, v) += vol1 * a_oldVariable(childId, v);
15315 for(
MInt v = 0; v < m_noFVars; v++) {
15316 m_rhs0[solverCellId][v] += m_rhs0[childId][v];
15321 auto it = m_oldBndryCells.find(childId);
15322 if(it != m_oldBndryCells.end()) {
15323 hasBndryCell =
true;
15324 sweptVol += it->second;
15325 ASSERT(!a_hasProperty(childId, SolverCell::WasInactive) || m_maxLevelDecrease,
"");
15326 m_oldBndryCells.erase(it);
15327 ASSERT(m_bndryLevelJumps,
"");
15331 auto it = m_nearBoundaryBackup.find(childId);
15332 if(it != m_nearBoundaryBackup.end()) {
15333 m_nearBoundaryBackup.erase(it);
15337 if(grid().azimuthalPeriodicity()) {
15343 if(wasInactive == noRemovedChilds) {
15344 a_hasProperty(solverCellId, SolverCell::WasInactive) =
true;
15347 m_cellVolumesDt1[solverCellId] = grid().gridCellVolume(a_level(solverCellId));
15348 for(
MInt v = 0; v < m_noFVars; v++) {
15349 m_rhs0[solverCellId][v] = 0;
15352 a_oldVariable(solverCellId, CV->RHO) = m_rhoInfinity;
15353 a_oldVariable(solverCellId, CV->RHO_E) = m_rhoEInfinity;
15354 for(
MInt dir = 0; dir < nDim; dir++) {
15355 a_oldVariable(solverCellId, CV->RHO_VV[dir]) = m_rhoVVInfinity[dir];
15359 for(
MInt v = 0; v < m_noCVars; v++) {
15360 a_oldVariable(solverCellId, v) /=
mMax(m_volumeThreshold, m_cellVolumesDt1[solverCellId]);
15364 if(wasGapCell) a_wasGapCell(solverCellId) =
true;
15365 if(isGapCell) a_isGapCell(solverCellId) =
true;
15370 m_coarseOldBndryCells.insert(solverCellId);
15371 m_oldBndryCells.insert(make_pair(solverCellId, sweptVol));
15378 if(!
g_multiSolverGrid) ASSERT((m_cells.size() - grid().raw().treeb().size()) <= grid().m_maxNoChilds,
"");
15386template <MInt nDim,
class SysEqn>
15390 MBool forceAdaptation =
false;
15392 if(m_engineSetup) {
15393 static const MInt cadInterval = 5;
15395 const MInt cad = this->crankAngle(m_physicalTime, 0);
15396 const MInt cad_dt1 = this->crankAngle(m_physicalTime - timeStep(), 0);
15398 if(cad % cadInterval == 0 && cad_dt1 % cadInterval != 0) {
15399 forceAdaptation =
true;
15400 if(domainId() == 0) {
15401 cerr <<
" FvMb-Solver is forcing a mesh-adaptation at time step " <<
globalTimeStep << endl;
15406 if(m_forceAdaptation) {
15407 forceAdaptation =
true;
15408 m_forceAdaptation =
false;
15411 return forceAdaptation;
15419template <MInt nDim,
class SysEqn>
15423 if(!isActive())
return;
15428 if(m_constructGField) {
15429 constructGFieldPredictor();
15430 }
else if(!m_LsMovement) {
15431 updateBodyProperties();
15433 ASSERT(m_structureStep == 0,
"");
15436 setLevelSetMbCellProperties();
15438 if(grid().azimuthalPeriodicity()) {
15439 storeAzimuthalPeriodicData();
15444 auto oldBndryCellsBak(m_oldBndryCells);
15445 m_oldBndryCells.clear();
15446 for(
auto it = oldBndryCellsBak.begin(); it != oldBndryCellsBak.end(); ++it) {
15447 if(it->first >= noInternalCells())
continue;
15448 ASSERT(!a_isHalo(it->first),
"");
15449 m_oldBndryCells.insert(*it);
15455 auto nearBoundaryBackupBak(m_nearBoundaryBackup);
15456 m_nearBoundaryBackup.clear();
15457 for(
auto it = nearBoundaryBackupBak.begin(); it != nearBoundaryBackupBak.end(); ++it) {
15458 if(it->first >= noInternalCells())
continue;
15459 ASSERT(!a_isHalo(it->first),
"");
15460 m_nearBoundaryBackup.insert(*it);
15465 m_coarseOldBndryCells.clear();
15475template <MInt nDim,
class SysEqn>
15477 std::vector<MFloat>& sensorWeight,
15478 std::vector<std::bitset<64>>& sensorCellFlag,
15479 std::vector<MInt>& sensorSolverId) {
15484 const auto sensorOffset = (signed)sensors.size();
15489 if(m_bndryLevelJumps && (maxRefinementLevel() - m_lsCutCellMinLevel > 1)) {
15491 for(
auto it = m_coarseOldBndryCells.begin(); it != m_coarseOldBndryCells.end(); it++) {
15492 const MInt cellId = *it;
15493 const MInt gridId = grid().tree().solver2grid(cellId);
15494 for(
MInt s = 0; s < this->m_noSensors; s++) {
15495 sensorCellFlag[gridId][sensorOffset + s] =
false;
15496 sensors[sensorOffset + s][gridId] = 0.0;
15498 const MInt parentId = c_parentId(cellId);
15499 if(parentId < 0)
continue;
15500 const MInt gridParent = grid().tree().solver2grid(parentId);
15501 sensorCellFlag[gridParent][sensorOffset] =
true;
15502 sensors[sensorOffset][gridParent] = 1.0;
15505 for(
auto it = m_oldBndryCells.begin(); it != m_oldBndryCells.end(); it++) {
15506 const MInt cellId = it->first;
15507 if(c_isLeafCell(cellId))
continue;
15508 for(
MInt childId = 0; childId <
IPOW2(nDim); childId++) {
15509 const MInt child = c_childId(cellId, childId);
15510 if(child < 0)
continue;
15511 const MInt gridId = grid().tree().solver2grid(child);
15512 for(
MInt s = 0; s < this->m_noSensors; s++) {
15513 sensorCellFlag[gridId][sensorOffset + s] =
false;
15514 sensors[sensorOffset + s][gridId] = 0.0;
15526template <MInt nDim,
class SysEqn>
15530 if(grid().azimuthalPeriodicity()) {
15531 initAzimuthalCartesianHaloInterpolation();
15532 this->exchangeAzimuthalPer(&(a_levelSetValuesMb(0, 0)), m_noLevelSetsUsedForMb);
15541template <MInt nDim,
class SysEqn>
15544 m_onlineRestart =
false;
15547 if(maxLevel() != maxRefinementLevel()) {
15548 if(domainId() == 0) {
15549 cerr <<
"MaxLevel is " << maxLevel() <<
" and maxRefinementLevel is " << maxRefinementLevel() << endl;
15553 if(m_maxLevelChange && maxLevel() == maxRefinementLevel()) {
15554 m_maxLevelChange =
false;
15555 m_lsCutCellMinLevel = maxLevel();
15556 m_bndryLevelJumps =
false;
15557 if(domainId() == 0) {
15558 cerr <<
"MaxLevel reached maxRefinementLevel! " << endl;
15566 if(!isActive())
return;
15569 oldBCData.
fill(std::numeric_limits<MFloat>::lowest());
15571 exchangeData(&a_cellVolume(0), 1);
15572 exchangeData(&m_cellVolumesDt1[0], 1);
15582 m_refOldBndryCells.clear();
15583 vector<MInt> deletedBndryCells;
15585 for(
auto it = m_oldBndryCells.begin(); it != m_oldBndryCells.end(); it++) {
15586 const MInt cellId = it->first;
15587 ASSERT(!a_isHalo(cellId),
"");
15588 const MFloat sweptVol = it->second;
15589 if(!c_isLeafCell(cellId)) {
15590 deletedBndryCells.push_back(cellId);
15591 for(
MInt childId = 0; childId <
IPOW2(nDim); childId++) {
15592 const MInt child = c_childId(cellId, childId);
15593 if(child < 0)
continue;
15594 if(!c_isLeafCell(child)) {
15595 cerr <<
"Cell is " << c_globalId(child) <<
" " << c_coordinate(child, 0) <<
" " << c_coordinate(child, 1)
15596 <<
" " << c_coordinate(child, nDim - 1) <<
" parent " << c_globalId(cellId) <<
" "
15597 << c_coordinate(cellId, 0) <<
" " << c_coordinate(cellId, 1) <<
" " << c_coordinate(cellId, nDim - 1)
15599 mTerm(1, AT_,
"Multiple-levell changes in a bndry-cells not supported yet!");
15601 m_refOldBndryCells.push_back(child);
15602 oldBCData(child, 0) = 2;
15617 auto it1 = m_coarseOldBndryCells.find(cellId);
15618 if(it1 != m_coarseOldBndryCells.end()) {
15619 oldBCData(cellId, 0) = 3;
15621 if(oldBCData(cellId, 0) < F0) {
15622 oldBCData(cellId, 0) = 1;
15624 oldBCData(cellId, 1) = sweptVol;
15628 for(
MInt i = 0; i < (signed)deletedBndryCells.size(); i++) {
15629 const MInt cellId = deletedBndryCells[i];
15630 auto it = m_oldBndryCells.find(cellId);
15631 m_oldBndryCells.erase(it);
15632 ASSERT(!c_isLeafCell(cellId),
"");
15633 ASSERT(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel),
"");
15636 for(
auto it = m_nearBoundaryBackup.begin(); it != m_nearBoundaryBackup.end(); it++) {
15637 const MInt cellId = it->first;
15638 ASSERT(!a_isHalo(cellId), to_string(a_isHalo(cellId)));
15639 oldBCData(cellId, 2) = F1;
15643 for(
MInt i = 0; i < noNeighborDomains(); i++) {
15644 for(
MInt j = 0; j < noWindowCells(i); j++) {
15645 const MInt cellId = windowCellId(i, j);
15646 oldBCData(cellId, 3) = (
MFloat)a_hasProperty(cellId, SolverCell::WasInactive);
15647 oldBCData(cellId, 4) = (
MFloat)a_hasProperty(cellId, SolverCell::WasGapCell);
15651 exchangeData(&oldBCData[0], 5);
15655 for(
MInt cellId = noInternalCells(); cellId < c_noCells(); cellId++) {
15656 ASSERT(a_isHalo(cellId),
"");
15658 setConservativeVariables(cellId);
15659 for(
MInt v = 0; v < m_noCVars; v++) {
15660 a_oldVariable(cellId, v) = a_variable(cellId, v);
15662 if(oldBCData(cellId, 3) > -1) {
15663 a_hasProperty(cellId, SolverCell::WasInactive) = (
MInt)oldBCData(cellId, 3);
15665 if(oldBCData(cellId, 4) > -1) {
15666 a_hasProperty(cellId, SolverCell::WasGapCell) = (
MInt)oldBCData(cellId, 4);
15669 if((
MInt)oldBCData(cellId, 0) > F0) {
15670 ASSERT(c_isLeafCell(cellId),
"");
15671 m_oldBndryCells.insert(make_pair(cellId, oldBCData(cellId, 1)));
15672 if((
MInt)oldBCData(cellId, 0) == 2) {
15673 m_refOldBndryCells.push_back(cellId);
15674 }
else if((
MInt)oldBCData(cellId, 0) == 3) {
15675 m_coarseOldBndryCells.insert(cellId);
15678 if(oldBCData(cellId, 2) > F0) {
15679 vector<MFloat> tmp(max(m_noCVars + m_noFVars, 0) + 1);
15680 tmp[0] = m_cellVolumesDt1[cellId];
15681 for(
MInt v = 0; v < m_noCVars; v++) {
15682 tmp[1 + v] = std::numeric_limits<MFloat>::lowest();
15684 for(
MInt v = 0; v < m_noFVars; v++) {
15685 tmp[1 + m_noCVars + v] = std::numeric_limits<MFloat>::lowest();
15687 m_nearBoundaryBackup.insert(make_pair(cellId, tmp));
15692 if(grid().azimuthalPeriodicity()) {
15693 commAzimuthalPeriodicData();
15696 m_surfaces.size(m_initialSurfacesOffset);
15698 m_fvBndryCnd->recorrectCellCoordinates();
15700 m_cells.size(m_bndryGhostCellsOffset);
15701 m_totalnoghostcells = 0;
15702 m_totalnosplitchilds = 0;
15704 for(
MInt bndryId = 0; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
15705 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
15706 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId = -1;
15710#if defined _MB_DEBUG_ || !defined NDEBUG
15712 MInt noRefBndryCells = m_refOldBndryCells.size();
15713 MInt noCoBndryCells = m_coarseOldBndryCells.size();
15715 MPI_Allreduce(MPI_IN_PLACE, &noRefBndryCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noRefBndryCells");
15716 MPI_Allreduce(MPI_IN_PLACE, &noCoBndryCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noCoBndryCells");
15718 if(noRefBndryCells > 0) {
15719 m_log <<
"Refining " << noRefBndryCells <<
" bndryCells in adaptation!" << endl;
15722 if(noCoBndryCells > 0) {
15723 m_log <<
"Coarsening " << noCoBndryCells <<
" bndryCells in adaptation!" << endl;
15735template <MInt nDim,
class SysEqn>
15737 if(m_constructGField || m_levelSetAdaptationScheme != 2) {
15738 distance.fill(std::numeric_limits<MFloat>::max());
15740 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
15741 ASSERT(!a_isBndryGhostCell(cellId),
"");
15742 ASSERT(!a_isHalo(cellId),
"");
15743 ASSERT(!c_isToDelete(cellId),
"");
15744 distance(cellId) = a_levelSetValuesMb(cellId, 0);
15750 MInt listCount = 0;
15751 distance.fill(0.0);
15754 const MInt linerSet = 1;
15755 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
15758 const MInt set = 0;
15759 if((
MInt)distance(cellId) == 1)
continue;
15760 MBool addParents =
false;
15761 if(
approx(a_levelSetValuesMb(cellId, set), F0, MFloatEps)) {
15762 if(c_isLeafCell(cellId)) {
15763 const MInt bodySet = m_bodyToSetTable[a_associatedBodyIds(cellId, set)];
15764 MInt maxLvl = m_lsCutCellLevel[bodySet];
15765 if(bodySet == linerSet && m_linerLvlJump && a_coordinate(cellId, 0) > -0.51
15766 && a_coordinate(cellId, 0) < 0.51) {
15767 maxLvl = m_lsCutCellLevel[bodySet] + 1;
15769 if(a_level(cellId) < maxLvl) {
15770 distance(cellId) = 1.0;
15774 distance(cellId) = 1.0;
15779 for(
MInt dir = 0; dir < m_noDirs; dir++) {
15780 if(a_hasNeighbor(cellId, dir,
false) > 0) {
15781 const MInt nghbrId = c_neighborId(cellId, dir,
false);
15782 if((a_levelSetValuesMb(nghbrId, set) * a_levelSetValuesMb(cellId, set) < F0)) {
15783 if(c_isLeafCell(cellId)) {
15784 const MInt bodySet = m_bodyToSetTable[a_associatedBodyIds(cellId, set)];
15785 MInt maxLvl = m_lsCutCellLevel[bodySet];
15786 if(bodySet == linerSet && m_linerLvlJump && a_coordinate(cellId, 0) > -0.51
15787 && a_coordinate(cellId, 0) < 0.51) {
15788 maxLvl = m_lsCutCellLevel[bodySet] + 1;
15790 if(a_level(cellId) < maxLvl) {
15791 distance(cellId) = 1.0;
15795 distance(cellId) = 1.0;
15805 MInt parentId = c_parentId(cellId);
15806 while(parentId > -1 && parentId < a_noCells()) {
15807 distance(parentId) = 1.0;
15808 parentId = c_parentId(parentId);
15813#if defined _MB_DEBUG_ || !defined NDEBUG
15814 MPI_Allreduce(MPI_IN_PLACE, &listCount, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"listCount");
15816 if(listCount == 0)
mTerm(1, AT_,
"No Cells found for fv-mb-refinement!");
15820 exchangeDataFV(distance.data());
15828template <MInt nDim,
class SysEqn>
15832 const MInt noCells = a_noCells();
15836 for(
MInt c = 0; c < noCells; c++) {
15837 prop13.
p[c] = a_hasProperty(c, SolverCell::IsOnCurrentMGLevel);
15838 bghost.
p[c] = a_isBndryGhostCell(c);
15839 inact.
p[c] = a_hasProperty(c, SolverCell::IsInactive);
15840 if(c_isToDelete(c))
continue;
15841 a_hasProperty(c, SolverCell::IsOnCurrentMGLevel) =
true;
15842 a_hasProperty(c, SolverCell::IsInactive) =
false;
15844 a_isBndryGhostCell(c) =
false;
15847 const MInt haloCellOutput = m_haloCellOutput;
15848 const MInt vtuGeometryOutputExtended = m_vtuGeometryOutputExtended;
15849 const MInt vtuGlobalIdOutput = m_vtuGlobalIdOutput;
15850 const MInt vtuDomainIdOutput = m_vtuDomainIdOutput;
15851 const MInt vtuLevelSetOutput = m_vtuLevelSetOutput;
15852 const MInt vtuVelocityGradientOutput = m_vtuVelocityGradientOutput;
15854 m_haloCellOutput =
true;
15855 m_vtuGeometryOutputExtended =
true;
15856 m_vtuGlobalIdOutput =
true;
15857 m_vtuDomainIdOutput =
true;
15858 m_vtuLevelSetOutput =
false;
15859 m_vtuVelocityGradientOutput =
true;
15861 writeVtkXmlFiles(
"QOUT_" + suffix,
"GEOM_" + suffix, 0, 0);
15863 m_haloCellOutput = haloCellOutput;
15864 m_vtuGeometryOutputExtended = vtuGeometryOutputExtended;
15865 m_vtuGlobalIdOutput = vtuGlobalIdOutput;
15866 m_vtuDomainIdOutput = vtuDomainIdOutput;
15867 m_vtuLevelSetOutput = vtuLevelSetOutput;
15868 m_vtuVelocityGradientOutput = vtuVelocityGradientOutput;
15870 for(
MInt c = 0; c < noCells; c++) {
15871 a_hasProperty(c, SolverCell::IsOnCurrentMGLevel) = prop13.
p[c];
15872 a_hasProperty(c, SolverCell::IsInactive) = inact.
p[c];
15873 a_isBndryGhostCell(c) = bghost.
p[c];
15875 const MInt cellId = -1;
15876 if(domainId() == 0 && cellId > -1) {
15877 m_log <<
"CLOG " <<
globalTimeStep <<
" " << cellId <<
" " << a_level(cellId) <<
" " << c_noChildren(cellId)
15878 <<
" # " << a_isBndryGhostCell(cellId) <<
" " << a_isHalo(cellId) <<
" " << a_noCells() <<
" # "
15879 << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" " << a_coordinate(cellId, 2) <<
" # ";
15880 for(
MInt dir = 0; dir < m_noDirs; dir++) {
15881 MInt cId = (c_neighborId(cellId, dir) > -1) ? m_bndryCandidateIds[c_neighborId(cellId, dir)] : -1;
15882 MInt bId = (c_neighborId(cellId, dir) > -1) ? a_isBndryGhostCell(c_neighborId(cellId, dir)) : -1;
15883 m_log <<
" / (" << dir <<
") " << a_hasNeighbor(cellId, dir) <<
" " << c_neighborId(cellId, dir) <<
" " << cId
15891 if(noDomains() > 1)
15892 MPI_Gather(&m_noLsMbBndryCells, 1, MPI_INT, &(noLsMbCells[0]), 1, MPI_INT, 0, mpiComm(), AT_,
"m_noLsMbBndryCells",
15893 "(noLsMbCells[0])");
15894 if(domainId() == 0) {
15895 ofstream ofile((
"out/QOUT_" + suffix +
".pvd").c_str(), ios_base::out | ios_base::trunc);
15896 if(ofile.is_open() && ofile.good()) {
15897 ofile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
15898 ofile <<
"<Collection>" << endl;
15899 for(
MInt p = 0; p < noDomains(); p++) {
15900 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" <<
globalTimeStep <<
"\" file=\""
15901 <<
"./solver_data/"
15902 <<
"QOUT_" << suffix <<
"_B" << p <<
".vtu\"/>" << endl;
15904 ofile <<
"</Collection>" << endl;
15905 ofile <<
"</VTKFile>" << endl;
15909 cerr <<
"Error opening file out/QOUT_" << suffix <<
".pvd" << endl;
15911 ofstream ofile2((
"out/GEOM_" + suffix +
".pvd").c_str(), ios_base::out | ios_base::trunc);
15912 if(ofile2.is_open() && ofile2.good()) {
15913 ofile2 <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
15914 ofile2 <<
"<Collection>" << endl;
15915 for(
MInt p = 0; p < noDomains(); p++) {
15916 if(noLsMbCells(p) > 0) {
15917 ofile2 <<
"<DataSet part=\"" << p <<
"\" timestep=\"" <<
globalTimeStep <<
"\" file=\""
15918 <<
"./solver_data/"
15919 <<
"GEOM_" << suffix <<
"_B" << p <<
".vtp\"/>" << endl;
15922 ofile2 <<
"</Collection>" << endl;
15923 ofile2 <<
"</VTKFile>" << endl;
15927 cerr <<
"Error opening file out/GEOM_" << suffix <<
".pvd" << endl;
15939template <MInt nDim,
class SysEqn>
15943 if(!m_engineSetup)
return;
15945 static const MInt cadStart = -10;
15946 static const MInt cadEnd = 725;
15947 static const MInt cadEndSlice = 365;
15948 static const MInt cadInterval = 5;
15950 static const MInt sliceInterval = 1;
15952 const MFloat cad = this->crankAngle(m_physicalTime, 0);
15953 const MFloat cad_prev = this->crankAngle(m_physicalTime - timeStep(), 0);
15954 const MFloat cad_next = this->crankAngle(m_physicalTime + timeStep(), 0);
15956 if(cad > cadEnd)
return;
15958 if(cad < cadStart - cadInterval)
return;
15960 const MInt cadMaxIter = (cadEnd - cadStart) / cadInterval;
15961 const MInt sliceMaxIter = (cadEndSlice - cadStart) / sliceInterval;
15964 for(
MInt i = 0; i < cadMaxIter; i++) {
15965 const MFloat cadTarget = cadStart + i * cadInterval;
15967 if(cad < cadTarget && cad_next > cadTarget) {
15968 if(fabs(cad - cadTarget) <= fabs(cad_next - cadTarget)) {
15969 if(domainId() == 0) {
15970 cerr <<
"Saving output at crankAngle " << cad << endl;
15974 MFloat* backUpCoordinate = NULL;
15975 if(m_vtuCoordinatesThreshold != NULL) {
15976 mAlloc(backUpCoordinate, 6,
"backUpCoordinate", F0, AT_);
15977 for(
MInt j = 0; j < 2 * nDim; j++) {
15978 backUpCoordinate[j] = m_vtuCoordinatesThreshold[j];
15981 m_vtuCoordinatesThreshold = NULL;
15983 MString fileName =
"FieldData_" + to_string(solverId()) +
"_" + to_string((
MInt)round(cad));
15984 writeVtkXmlFiles(fileName,
"GEO_",
false,
false);
15985 if(backUpCoordinate != NULL) {
15986 mAlloc(m_vtuCoordinatesThreshold, 6,
"backUpCoordinate", F0, AT_);
15987 for(
MInt j = 0; j < 2 * nDim; j++) {
15988 m_vtuCoordinatesThreshold[j] = backUpCoordinate[j];
15993 }
else if(cad > cadTarget && cad_prev < cadTarget) {
15994 if(abs(cad - cadTarget) < fabs(cad_prev - cadTarget)) {
15995 if(domainId() == 0) {
15996 cerr <<
"Saving output at crankAngle " << cad << endl;
15999 MFloat* backUpCoordinate = NULL;
16000 if(m_vtuCoordinatesThreshold != NULL) {
16001 mAlloc(backUpCoordinate, 6,
"backUpCoordinate", F0, AT_);
16002 for(
MInt j = 0; j < 2 * nDim; j++) {
16003 backUpCoordinate[j] = m_vtuCoordinatesThreshold[j];
16006 m_vtuCoordinatesThreshold = NULL;
16008 MString fileName =
"FieldData_" + to_string(solverId()) +
"_" + to_string((
MInt)round(cad));
16009 writeVtkXmlFiles(fileName,
"GEO_",
false,
false);
16010 if(backUpCoordinate != NULL) {
16011 mAlloc(m_vtuCoordinatesThreshold, 6,
"backUpCoordinate", F0, AT_);
16012 for(
MInt j = 0; j < 2 * nDim; j++) {
16013 m_vtuCoordinatesThreshold[j] = backUpCoordinate[j];
16021 if(cad > cadEndSlice)
return;
16024 for(
MInt i = 0; i < sliceMaxIter; i++) {
16025 const MFloat sliceTarget = cadStart + i * sliceInterval;
16027 if(cad < sliceTarget && cad_next > sliceTarget) {
16028 if(fabs(cad - sliceTarget) <= fabs(cad_next - sliceTarget)) {
16029 if(domainId() == 0) {
16030 cerr <<
"Saving output Slice at crankAngle " << cad << endl;
16032 MString fileName =
"Slice_" + to_string(solverId()) +
"_" + to_string((
MInt)round(cad));
16033 writeVtkXmlFiles(fileName,
"SLICE_GEO",
false,
false);
16036 }
else if(cad > sliceTarget && cad_prev < sliceTarget) {
16037 if(abs(cad - sliceTarget) < fabs(cad_prev - sliceTarget)) {
16038 if(domainId() == 0) {
16039 cerr <<
"Saving output Slice at crankAngle " << cad << endl;
16041 MString fileName =
"Slice_" + to_string(solverId()) +
"_" + to_string((
MInt)round(cad));
16042 writeVtkXmlFiles(fileName,
"SLICE_GEO",
false,
false);
16054template <MInt nDim,
class SysEqn>
16058 if(noNeighborDomains() == 0 && grid().noAzimuthalNeighborDomains() == 0) {
16059 if(noDomains() > 1)
mTerm(1, AT_,
"Unexpected situation in initializeMaxLevelExchange!");
16068 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16069 sndbuf[neighborDomain(i)] = 1;
16072 "rcvbuf.getPointer()");
16073 for(
MInt i = 0; i < noDomains(); i++) {
16074 if(i == domainId())
continue;
16075 if(sndbuf[i] != rcvbuf[i]) {
16076 cerr << domainId() <<
": warning exchange mismatch with domain " << i <<
" (" << sndbuf[i] <<
"/" << rcvbuf[i]
16083#ifdef NEW_INITMAXLVLEX
16084 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16085 m_noMaxLevelHaloCells[i] = 0;
16086 for(
MInt j = 0; j < noHaloCells(i); j++) {
16087 MInt cellId = haloCellId(i, j);
16088 ASSERT(cellId > -1,
"");
16089 MBool structuredCell = a_hasProperty(cellId, SolverCell::AtStructuredRegion);
16090 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16091 if(a_hasNeighbor(cellId, dir)) {
16092 if(a_hasProperty(c_neighborId(cellId, dir), SolverCell::AtStructuredRegion)) {
16093 structuredCell =
true;
16097 if(c_isLeafCell(cellId) || structuredCell) {
16098 m_maxLevelHaloCells[i][m_noMaxLevelHaloCells[i]] = cellId;
16099 m_noMaxLevelHaloCells[i]++;
16103 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16104 m_noMaxLevelWindowCells[i] = 0;
16105 for(
MInt j = 0; j < noWindowCells(i); j++) {
16106 MInt cellId = windowCellId(i, j);
16107 ASSERT(cellId > -1,
"");
16108 MBool structuredCell = a_hasProperty(cellId, SolverCell::AtStructuredRegion);
16109 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16110 if(a_hasNeighbor(cellId, dir)) {
16111 if(a_hasProperty(c_neighborId(cellId, dir), SolverCell::AtStructuredRegion)) {
16112 if(a_isWindow(c_neighborId(cellId, dir))) structuredCell =
true;
16116 if(c_isLeafCell(cellId) || structuredCell) {
16117 m_maxLevelWindowCells[i][m_noMaxLevelWindowCells[i]] = cellId;
16118 m_noMaxLevelWindowCells[i]++;
16131 for(
MInt d = 0; d < noNeighborDomains(); d++) {
16132 haloCellsCnt[d] = noHaloCells(d);
16133 windowCellsCnt[d] = noWindowCells(d);
16136 if(noNeighborDomains() > 0) {
16138 mAlloc(m_maxLevelHaloCells, noNeighborDomains(), &haloCellsCnt[0],
"m_maxLevelHaloCells", AT_);
16140 mAlloc(m_maxLevelWindowCells, noNeighborDomains(), &windowCellsCnt[0],
"m_maxLevelWindowCells", AT_);
16145 sendReq.
fill(MPI_REQUEST_NULL);
16146 recvReq.
fill(MPI_REQUEST_NULL);
16149 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16150 m_noMaxLevelHaloCells[i] = 0;
16151 for(
MInt j = 0; j < noHaloCells(i); j++) {
16152 MInt cellId = haloCellId(i, j);
16153 m_receiveBuffers[i][j] = -F1;
16154 MBool structuredCell = a_hasProperty(cellId, SolverCell::AtStructuredRegion);
16155 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16156 if(a_hasNeighbor(cellId, dir)) {
16157 if(a_hasProperty(c_neighborId(cellId, dir), SolverCell::AtStructuredRegion)) {
16158 structuredCell =
true;
16162 if(!c_isLeafCell(cellId) && !structuredCell)
continue;
16163 m_maxLevelHaloCells[i][m_noMaxLevelHaloCells[i]] = cellId;
16164 m_noMaxLevelHaloCells[i]++;
16165 ASSERT(cellId > -1,
"");
16166 m_receiveBuffers[i][j] = (
MFloat)cellId;
16171 if(noNeighborDomains() > 0) {
16172 if(m_nonBlockingComm) {
16173 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16174 MPI_Irecv(m_sendBuffers[i], noWindowCells(i), MPI_DOUBLE, neighborDomain(i), 5, mpiComm(), &recvReq[i], AT_,
16175 "m_sendBuffers[i]");
16177 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16178 MPI_Isend(m_receiveBuffers[i], noHaloCells(i), MPI_DOUBLE, neighborDomain(i), 5, mpiComm(), &sendReq[i], AT_,
16179 "m_receiveBuffers[i]");
16181 MPI_Waitall(noNeighborDomains(), &recvReq[0], MPI_STATUSES_IGNORE, AT_);
16182 MPI_Waitall(noNeighborDomains(), &sendReq[0], MPI_STATUSES_IGNORE, AT_);
16184 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16185 MPI_Issend(m_receiveBuffers[i], noHaloCells(i), MPI_DOUBLE, neighborDomain(i), 5, mpiComm(), &sendReq[i], AT_,
16186 "m_receiveBuffers[i]");
16188 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16189 MPI_Recv(m_sendBuffers[i], noWindowCells(i), MPI_DOUBLE, neighborDomain(i), 5, mpiComm(), MPI_STATUS_IGNORE,
16190 AT_,
"m_sendBuffers[i]");
16192 MPI_Waitall(noNeighborDomains(), &sendReq[0], MPI_STATUSES_IGNORE, AT_);
16197 for(
MInt i = 0; i < noNeighborDomains(); i++) {
16198 m_noMaxLevelWindowCells[i] = 0;
16199 for(
MInt j = 0; j < noWindowCells(i); j++) {
16200 if(m_sendBuffers[i][j] > -F1B2) {
16201 ASSERT(windowCellId(i, j) > -1,
"");
16202 m_maxLevelWindowCells[i][m_noMaxLevelWindowCells[i]] = windowCellId(i, j);
16203 m_noMaxLevelWindowCells[i]++;
16210 this->prepareMpiExchange();
16212 if(grid().azimuthalPeriodicity()) {
16213 initAzimuthalMaxLevelExchange();
16222template <MInt nDim,
class SysEqn>
16226 ASSERT((srfcId > -1) && (nghbrId0 > -1) && (nghbrId1 > -1),
"createSurface(..) error");
16227 ASSERT((srfcId < a_noSurfaces()) && (nghbrId0 < a_noCells()) && (nghbrId1 < a_noCells()),
16228 to_string(nghbrId0) +
" " + to_string(nghbrId1) +
" " + to_string(c_noCells()) +
" " + to_string(a_noCells()));
16229 ASSERT(c_noChildren(nghbrId0) == 0 && c_noChildren(nghbrId1) == 0,
"");
16231 a_surfaceOrientation(srfcId) = orientation;
16232 a_surfaceNghbrCellId(srfcId, 0) = nghbrId0;
16233 a_surfaceNghbrCellId(srfcId, 1) = nghbrId1;
16235 if(a_bndryId(nghbrId0) > -1) {
16236 m_bndryCells->a[a_bndryId(nghbrId0)].m_associatedSrfc[2 * orientation + 1] = srfcId;
16238 if(a_bndryId(nghbrId1) > -1) {
16239 m_bndryCells->a[a_bndryId(nghbrId1)].m_associatedSrfc[2 * orientation] = srfcId;
16242 if(a_level(nghbrId1) > a_level(nghbrId0)) {
16243 const MFloat cellLength = c_cellLengthAtLevel(a_level(nghbrId1));
16244 for(
MInt i = 0; i < nDim; i++) {
16245 a_surfaceCoordinate(srfcId, i) = a_coordinate(nghbrId1, i);
16247 a_surfaceCoordinate(srfcId, orientation) -= F1B2 * cellLength;
16248 a_surfaceArea(srfcId) = F1;
16249 for(
MInt i = 0; i < nDim - 1; i++)
16250 a_surfaceArea(srfcId) *= cellLength;
16251 m_cellSurfaceMapping[nghbrId0][2 * orientation + 1] = -1;
16252 m_cellSurfaceMapping[nghbrId1][2 * orientation] = srfcId;
16254 const MFloat cellLength = c_cellLengthAtLevel(a_level(nghbrId0));
16255 for(
MInt i = 0; i < nDim; i++) {
16256 a_surfaceCoordinate(srfcId, i) = a_coordinate(nghbrId0, i);
16258 a_surfaceCoordinate(srfcId, orientation) += F1B2 * cellLength;
16259 a_surfaceArea(srfcId) = F1;
16260 for(
MInt i = 0; i < nDim - 1; i++)
16261 a_surfaceArea(srfcId) *= cellLength;
16262 m_cellSurfaceMapping[nghbrId0][2 * orientation + 1] = srfcId;
16263 m_cellSurfaceMapping[nghbrId1][2 * orientation] = -1;
16266 if(a_level(nghbrId0) == a_level(nghbrId1)) {
16267 a_surfaceUpwindCoefficient(srfcId) = m_globalUpwindCoefficient;
16268 a_surfaceFactor(srfcId, 0) = F1B2;
16269 a_surfaceFactor(srfcId, 1) = F1B2;
16270 m_cellSurfaceMapping[nghbrId0][2 * orientation + 1] = srfcId;
16271 m_cellSurfaceMapping[nghbrId1][2 * orientation] = srfcId;
16273 a_surfaceUpwindCoefficient(srfcId) = m_chi;
16275 a_surfaceFactor(srfcId, 0) = F0;
16276 for(
MInt i = 0; i < nDim; i++) {
16277 a_surfaceFactor(srfcId, 0) +=
POW2(a_surfaceCoordinate(srfcId, i) - a_coordinate(nghbrId0, i));
16278 tmp +=
POW2(a_surfaceCoordinate(srfcId, i) - a_coordinate(nghbrId1, i));
16280 a_surfaceFactor(srfcId, 0) = sqrt(a_surfaceFactor(srfcId, 0));
16282 a_surfaceFactor(srfcId, 0) = tmp / (a_surfaceFactor(srfcId, 0) + tmp);
16283 a_surfaceFactor(srfcId, 1) = F1 - a_surfaceFactor(srfcId, 0);
16285 for(
MInt i = 0; i < nDim; i++) {
16286 a_surfaceDeltaX(srfcId, i) = a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 0), i);
16287 a_surfaceDeltaX(srfcId, nDim + i) =
16288 a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 1), i);
16290 MBool flag =
false;
16291 for(
MInt side = 0; side < 2; side++) {
16292 for(
MInt d = 0; d < m_noDirs; d++) {
16293 if(a_hasNeighbor(a_surfaceNghbrCellId(srfcId, side), d) > 0)
continue;
16294 if(c_parentId(a_surfaceNghbrCellId(srfcId, side)) == -1)
continue;
16295 if(a_hasNeighbor(c_parentId(a_surfaceNghbrCellId(srfcId, side)), d) == 0)
continue;
16296 if(c_noChildren(c_neighborId(c_parentId(a_surfaceNghbrCellId(srfcId, side)), d)) > 0)
continue;
16302 if(flag) a_surfaceUpwindCoefficient(srfcId) = m_chi;
16303 a_surfaceBndryCndId(srfcId) = -1;
16311template <MInt nDim,
class SysEqn>
16314 ASSERT((srfcId > -1),
"createSurface(..) error");
16315 ASSERT((srfcId < a_noSurfaces()) && (cellId < a_noCells()) && (splitChildId < a_noCells()),
16316 "createSurface(..) error");
16317 ASSERT(c_isLeafCell(cellId),
"");
16319 MInt orientation = direction / 2;
16320 a_surfaceOrientation(srfcId) = orientation;
16321 MInt nghbr0 = splitChildId;
16323 if(direction % 2 == 0) {
16325 nghbr1 = splitChildId;
16327 a_surfaceNghbrCellId(srfcId, 0) = nghbr0;
16328 a_surfaceNghbrCellId(srfcId, 1) = nghbr1;
16330 MInt nghbrId = c_neighborId(cellId, direction);
16331 ASSERT(nghbrId > -1,
"");
16341 const MFloat cellLength = c_cellLengthAtLevel(a_level(cellId));
16342 for(
MInt i = 0; i < nDim; i++) {
16343 a_surfaceCoordinate(srfcId, i) = a_coordinate(cellId, i);
16345 a_surfaceCoordinate(srfcId, orientation) += F1B2 * cellLength;
16346 a_surfaceArea(srfcId) = F1;
16347 for(
MInt i = 0; i < nDim - 1; i++)
16348 a_surfaceArea(srfcId) *= cellLength;
16349 a_surfaceUpwindCoefficient(srfcId) = m_globalUpwindCoefficient;
16351 a_surfaceFactor(srfcId, 0) = F1B2;
16352 a_surfaceFactor(srfcId, 1) = F1B2;
16354 for(
MInt i = 0; i < nDim; i++) {
16355 a_surfaceDeltaX(srfcId, i) = a_surfaceCoordinate(srfcId, i) - a_coordinate(nghbr0, i);
16356 a_surfaceDeltaX(srfcId, nDim + i) = a_surfaceCoordinate(srfcId, i) - a_coordinate(nghbr1, i);
16358 a_surfaceBndryCndId(srfcId) = -1;
16360 m_splitSurfaces.insert(srfcId);
16368template <MInt nDim,
class SysEqn>
16370 ASSERT((fromSrfcId > -1) && (toSrfcId > -1) && (fromSrfcId < a_noSurfaces()) && (toSrfcId < a_noSurfaces()),
16371 "moveSurface(..) error");
16373 const MInt ori = a_surfaceOrientation(fromSrfcId);
16374 a_surfaceOrientation(toSrfcId) = ori;
16376 const MInt nghbrId0 = a_surfaceNghbrCellId(fromSrfcId, 0);
16377 const MInt nghbrId1 = a_surfaceNghbrCellId(fromSrfcId, 1);
16378 ASSERT(nghbrId0 > -1 && nghbrId1 > -1,
"");
16379 ASSERT(nghbrId0 < a_noCells() && nghbrId1 < a_noCells(),
"");
16383 ASSERT(((m_cellSurfaceMapping[nghbrId0][2 * ori + 1] > -1) && (m_cellSurfaceMapping[nghbrId1][2 * ori] > -1))
16384 || (a_bndryId(nghbrId0) > -1 && a_bndryId(nghbrId1) > -1) || a_level(nghbrId0) != a_level(nghbrId1),
16387 if(nghbrId0 > -1) {
16388 if(m_cellSurfaceMapping[nghbrId0][2 * ori + 1] > -1) {
16389 ASSERT(m_cellSurfaceMapping[nghbrId0][2 * ori + 1] == fromSrfcId,
16390 to_string(m_cellSurfaceMapping[nghbrId1][2 * ori + 1]));
16391 m_cellSurfaceMapping[nghbrId0][2 * ori + 1] = toSrfcId;
16394 if(nghbrId1 > -1) {
16395 if(m_cellSurfaceMapping[nghbrId1][2 * ori] > -1) {
16396 ASSERT(m_cellSurfaceMapping[nghbrId1][2 * ori] == fromSrfcId, to_string(m_cellSurfaceMapping[nghbrId1][2 * ori]));
16397 m_cellSurfaceMapping[nghbrId1][2 * ori] = toSrfcId;
16401 if(a_bndryId(nghbrId0) > -1) {
16406 if(m_bndryCells->a[a_bndryId(nghbrId0)].m_associatedSrfc[2 * ori + 1] == fromSrfcId)
16407 m_bndryCells->a[a_bndryId(nghbrId0)].m_associatedSrfc[2 * ori + 1] = toSrfcId;
16408 MInt bndryId = a_bndryId(nghbrId0);
16409 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
16410 for(
MInt i = 0; i < nDim; i++) {
16411 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] == fromSrfcId) {
16412 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] = toSrfcId;
16417 if(a_bndryId(nghbrId1) > -1) {
16422 if(m_bndryCells->a[a_bndryId(nghbrId1)].m_associatedSrfc[2 * ori] == fromSrfcId)
16423 m_bndryCells->a[a_bndryId(nghbrId1)].m_associatedSrfc[2 * ori] = toSrfcId;
16424 MInt bndryId = a_bndryId(nghbrId1);
16425 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
16426 for(
MInt i = 0; i < nDim; i++) {
16427 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] == fromSrfcId) {
16428 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] = toSrfcId;
16434 if(m_splitSurfaces.erase(fromSrfcId)) m_splitSurfaces.insert(toSrfcId);
16436 a_surfaceNghbrCellId(toSrfcId, 0) = nghbrId0;
16437 a_surfaceNghbrCellId(toSrfcId, 1) = nghbrId1;
16438 a_surfaceNghbrCellId(fromSrfcId, 0) = -1;
16439 a_surfaceNghbrCellId(fromSrfcId, 1) = -1;
16442 for(
MInt i = 0; i < nDim; i++) {
16443 a_surfaceCoordinate(toSrfcId, i) = a_surfaceCoordinate(fromSrfcId, i);
16445 a_surfaceArea(toSrfcId) = a_surfaceArea(fromSrfcId);
16447 a_surfaceUpwindCoefficient(toSrfcId) = a_surfaceUpwindCoefficient(fromSrfcId);
16448 a_surfaceFactor(toSrfcId, 0) = a_surfaceFactor(fromSrfcId, 0);
16449 a_surfaceFactor(toSrfcId, 1) = a_surfaceFactor(fromSrfcId, 1);
16451 for(
MInt i = 0; i < nDim; i++) {
16452 a_surfaceDeltaX(toSrfcId, i) = a_surfaceDeltaX(fromSrfcId, i);
16453 a_surfaceDeltaX(toSrfcId, nDim + i) = a_surfaceDeltaX(fromSrfcId, nDim + i);
16456 a_surfaceBndryCndId(toSrfcId) = a_surfaceBndryCndId(fromSrfcId);
16458 for(
MInt v = 0; v < m_noCVars; v++) {
16459 a_surfaceVariable(toSrfcId, 0, v) = a_surfaceVariable(fromSrfcId, 0, v);
16460 a_surfaceVariable(toSrfcId, 1, v) = a_surfaceVariable(fromSrfcId, 1, v);
16463 m_noSurfaces = a_noSurfaces();
16471template <MInt nDim,
class SysEqn>
16475 MInt lastSrfcId = a_noSurfaces() - 1;
16477 if(a_noSurfaces() > 0) {
16478 for(set<MInt>::iterator it = m_freeSurfaceIndices.begin(); it != m_freeSurfaceIndices.end(); ++it) {
16480 if((a_surfaceNghbrCellId(srfcId, 0) > -1) || (a_surfaceNghbrCellId(srfcId, 1) > -1)) {
16481 cerr <<
"Warning: not expected in compactSurfaces()" << endl;
16484 while((a_surfaceNghbrCellId(lastSrfcId, 0) < 0) || (a_surfaceNghbrCellId(lastSrfcId, 1) < 0)) {
16485 if(lastSrfcId < a_noSurfaces()) {
16486 m_surfaces.erase(lastSrfcId);
16487 m_surfaces.size(lastSrfcId);
16489 lastSrfcId = a_noSurfaces() - 1;
16490 if(lastSrfcId == -1)
break;
16492 if(lastSrfcId == -1 || srfcId >= a_noSurfaces()) {
16495 lastSrfcId = a_noSurfaces() - 1;
16496 moveSurface(srfcId, lastSrfcId);
16497 m_surfaces.erase(lastSrfcId);
16498 m_surfaces.size(lastSrfcId);
16504 m_freeSurfaceIndices.clear();
16505 m_noSurfaces = a_noSurfaces();
16513template <MInt nDim,
class SysEqn>
16515 if(a_isBndryGhostCell(cellId))
return;
16516 if(c_noChildren(cellId) > 0)
return;
16517 if(a_hasProperty(cellId, SolverCell::IsInactive))
return;
16520 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16521 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
16523 if((a_surfaceNghbrCellId(srfcId, 0) < 0) || (a_surfaceNghbrCellId(srfcId, 1) < 0)) {
16524 cerr << srfcId <<
" " << cellId <<
" " << dir <<
" " << a_coordinate(cellId, 0) <<
" "
16525 << a_coordinate(cellId, 1) <<
" " << c_neighborId(cellId, dir) << endl;
16526 cerr << a_isHalo(cellId) <<
" " << a_isHalo(c_neighborId(cellId, dir)) <<
" "
16527 << a_hasProperty(c_neighborId(cellId, dir), SolverCell::IsNotGradient) << endl;
16529 createSurface(srfcId, a_surfaceNghbrCellId(srfcId, 0), a_surfaceNghbrCellId(srfcId, 1),
16530 a_surfaceOrientation(srfcId));
16532 if(a_hasNeighbor(cellId, dir) > 0) {
16533 MInt nghbrId = c_neighborId(cellId, dir);
16534 if(c_noChildren(nghbrId) > 0) {
16535 for(
MInt child = 0; child < m_noCellNodes; child++) {
16536 if(!childCode[dir][child])
continue;
16537 MInt childId = c_childId(nghbrId, child);
16538 if(childId < 0)
continue;
16539 srfcId = m_cellSurfaceMapping[childId][
m_revDir[dir]];
16541 createSurface(srfcId, a_surfaceNghbrCellId(srfcId, 0), a_surfaceNghbrCellId(srfcId, 1),
16542 a_surfaceOrientation(srfcId));
16551 restoreSurfaces(cellId);
16559template <MInt nDim,
class SysEqn>
16561 if(a_isBndryGhostCell(cellId))
mTerm(1, AT_,
"Unexpected situation 0 in FvMbCartesianSolverXD::restoreSurfaces()");
16562 if(c_noChildren(cellId) > 0)
return;
16563 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
return;
16564 if(a_hasProperty(cellId, SolverCell::IsInactive))
return;
16566 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16567 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
16570 if(a_hasNeighbor(cellId, dir) > 0) {
16571 const MInt nghbrId = c_neighborId(cellId, dir);
16572 if(c_noChildren(nghbrId) > 0) {
16573 for(
MInt child = 0; child < m_noCellNodes; child++) {
16574 if(!childCode[dir][child])
continue;
16575 const MInt childId = c_childId(nghbrId, child);
16576 if(childId < 0)
continue;
16577 ASSERT(!a_isBndryGhostCell(childId),
"");
16578 srfcId = m_cellSurfaceMapping[childId][
m_revDir[dir]];
16580 ASSERT(srfcId < a_noSurfaces(), to_string(srfcId) +
" " + to_string(a_noSurfaces()));
16581 if(a_surfaceNghbrCellId(srfcId,
m_revDir[dir] % 2) != cellId) {
16582 cerr << cellId <<
" " << nghbrId <<
" " << srfcId <<
" " << a_isHalo(cellId) <<
" " << a_level(cellId)
16583 <<
" " << a_level(nghbrId) << endl;
16584 cerr << dir <<
" " << child <<
" " << childId << endl;
16585 cerr << a_surfaceNghbrCellId(srfcId, 0) <<
" " << a_surfaceNghbrCellId(srfcId, 1) <<
" " << endl;
16586 if(a_surfaceNghbrCellId(srfcId, 0) > -1 && a_surfaceNghbrCellId(srfcId, 1) > -1) {
16587 cerr << a_level(a_surfaceNghbrCellId(srfcId, 0)) <<
" " << a_level(a_surfaceNghbrCellId(srfcId, 1))
16590 cerr << c_parentId(cellId) <<
" " << c_noChildren(cellId) << endl;
16591 for(
MInt d = 0; d < m_noDirs; d++) {
16592 cerr << d <<
": " << a_hasNeighbor(cellId, d) <<
"/" << c_neighborId(cellId, d);
16593 if(c_parentId(cellId) > -1) {
16594 cerr <<
" # " << a_hasNeighbor(c_parentId(cellId), d) <<
"/" << c_neighborId(c_parentId(cellId), d);
16599 mTerm(1, AT_,
"Unexpected situation in restoreSurfaces");
16602 if(a_hasProperty(childId, SolverCell::IsInactive))
continue;
16603 if(a_hasProperty(childId, SolverCell::IsNotGradient))
continue;
16604 if(a_isHalo(cellId) && a_isHalo(childId))
continue;
16605 srfcId = getNewSurfaceId();
16607 ASSERT(a_level(cellId) != a_level(childId),
"");
16610 createSurface(srfcId, childId, cellId, dir / 2);
16612 createSurface(srfcId, cellId, childId, dir / 2);
16616 ASSERT(!a_isBndryGhostCell(nghbrId),
"");
16617 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
16618 if(a_hasProperty(nghbrId, SolverCell::IsNotGradient))
continue;
16619 if(a_isHalo(cellId) && a_isHalo(nghbrId))
continue;
16620 srfcId = getNewSurfaceId();
16622 createSurface(srfcId, nghbrId, cellId, dir / 2);
16624 createSurface(srfcId, cellId, nghbrId, dir / 2);
16627 if(c_parentId(cellId) > -1) {
16628 if(a_hasNeighbor(c_parentId(cellId), dir) > 0) {
16629 const MInt nghbrId = c_neighborId(c_parentId(cellId), dir);
16630 ASSERT(!a_isBndryGhostCell(nghbrId),
"");
16631 srfcId = m_cellSurfaceMapping[nghbrId][
m_revDir[dir]];
16633 m_log <<
"nghb surf " <<
globalTimeStep <<
" " << srfcId <<
" " << nghbrId <<
" " << cellId <<
" "
16634 << a_noSurfaces() <<
" / " << c_isToDelete(cellId) <<
" "
16635 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << c_isToDelete(nghbrId) <<
" "
16636 << a_hasProperty(nghbrId, SolverCell::IsInactive) <<
" " << a_surfaceNghbrCellId(srfcId, 0) <<
" "
16637 << a_surfaceNghbrCellId(srfcId, 1) << endl;
16639 ASSERT(srfcId < a_noSurfaces(),
"");
16641 cerr << domainId() <<
": " << srfcId <<
" " << cellId <<
" " << nghbrId <<
" / "
16642 << a_surfaceNghbrCellId(srfcId, 0) <<
" " << a_surfaceNghbrCellId(srfcId, 1) <<
" / "
16643 << a_level(cellId) <<
" " << a_level(nghbrId) <<
" / " << a_coordinate(cellId, 0) <<
" "
16644 << a_coordinate(cellId, 1) <<
" / " << a_coordinate(nghbrId, 0) <<
" " << a_coordinate(nghbrId, 1)
16647 ASSERT(srfcId < 0,
"");
16648 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
16649 if(a_hasProperty(nghbrId, SolverCell::IsNotGradient))
continue;
16650 if(a_isHalo(cellId) && a_isHalo(nghbrId))
continue;
16651 if(c_noChildren(nghbrId) > 0) {
16652 cerr << domainId() <<
": error surf " << dir <<
" " << cellId <<
" " << nghbrId <<
" "
16653 << c_globalId(cellId) <<
" " << c_globalId(nghbrId) <<
" " << c_neighborId(cellId, dir,
false) <<
" "
16654 << c_noChildren(nghbrId) <<
" " << c_childId(nghbrId, 0) <<
" " << a_level(cellId) <<
" "
16655 << a_level(nghbrId) <<
" " << a_isHalo(cellId) <<
" " << a_isHalo(nghbrId) <<
" "
16656 << a_levelSetValuesMb(cellId, 0) / c_cellLengthAtCell(cellId) <<
" "
16657 << a_levelSetValuesMb(nghbrId, 0) / c_cellLengthAtCell(nghbrId) << endl;
16659 ASSERT(c_noChildren(nghbrId) == 0,
"");
16660 if(srfcId < 0) srfcId = getNewSurfaceId();
16662 ASSERT(a_level(cellId) != a_level(nghbrId),
"");
16664 createSurface(srfcId, nghbrId, cellId, dir / 2);
16666 createSurface(srfcId, cellId, nghbrId, dir / 2);
16671 if(a_surfaceNghbrCellId(srfcId, 0) < 0 || a_surfaceNghbrCellId(srfcId, 1) < 0) {
16672 cerr <<
"srcf neighbors: " << srfcId <<
" " << cellId <<
" " << a_surfaceNghbrCellId(srfcId, 0) <<
" "
16673 << a_surfaceNghbrCellId(srfcId, 0) << endl;
16685template <MInt nDim,
class SysEqn>
16689 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16690 if(a_hasNeighbor(cellId, dir) > 0) {
16691 MInt nghbrId = c_neighborId(cellId, dir);
16692 if(c_noChildren(nghbrId) > 0) {
16693 for(
MInt child = 0; child < m_noCellNodes; child++) {
16694 if(!includeAllChilds && !childCode[dir][child])
continue;
16695 MInt childId = c_childId(nghbrId, child);
16696 if(childId < 0)
continue;
16697 if(a_isBndryGhostCell(childId))
continue;
16698 if(!childCode[dir][child] && c_noChildren(childId) > 0)
continue;
16700 if(!((c_noChildren(childId) == 0) || (a_isHalo(cellId)))) {
16701 cerr << cellId <<
" " << nghbrId <<
" " << childId <<
" " << c_childId(childId, 0) <<
" " << dir <<
" "
16702 << child <<
" / " << a_isHalo(cellId) <<
" " << a_isWindow(cellId) <<
" " << a_isHalo(childId) <<
" "
16703 << a_isWindow(childId) <<
" " << a_isHalo(nghbrId) <<
" " << a_isWindow(nghbrId) <<
" // "
16704 << c_noChildren(cellId) <<
" " << c_noChildren(childId) <<
" " << a_level(cellId) <<
" /// "
16705 << (c_childId(childId, 0) > -1 ? c_noChildren(c_childId(childId, 0)) : -1) <<
" "
16706 << (c_childId(childId, 1) > -1 ? c_noChildren(c_childId(childId, 1)) : -1) <<
" "
16707 << (c_childId(childId, 2) > -1 ? c_noChildren(c_childId(childId, 2)) : -1) <<
" "
16708 << (c_childId(childId, 3) > -1 ? c_noChildren(c_childId(childId, 3)) : -1) <<
" "
16709 << (c_childId(childId, 4) > -1 ? c_noChildren(c_childId(childId, 4)) : -1) <<
" "
16710 << (c_childId(childId, 5) > -1 ? c_noChildren(c_childId(childId, 5)) : -1) <<
" "
16711 << (c_childId(childId, 6) > -1 ? c_noChildren(c_childId(childId, 6)) : -1) <<
" "
16712 << (c_childId(childId, 7) > -1 ? c_noChildren(c_childId(childId, 7)) : -1) << endl;
16714 ASSERT((c_noChildren(childId) == 0) || (a_isHalo(cellId)),
16715 "(1) No children expected FvMbCartesianSolverXD::getFacingNghbrs(..) "
16716 << cellId <<
" " << nghbrId <<
" " << childId <<
" " << c_childId(childId, 0) <<
" " << dir <<
" "
16717 << child <<
" " << c_noChildren(childId));
16718 m_nghbrList[counter++] = childId;
16721 ASSERT(nghbrId > -1,
"Invalid neighbor id in FvMbCartesianSolverXD::getFacingNghbrs(..)");
16722 if(a_isBndryGhostCell(nghbrId))
continue;
16723 m_nghbrList[counter++] = nghbrId;
16726 if(c_parentId(cellId) > -1) {
16727 if(a_hasNeighbor(c_parentId(cellId), dir) > 0) {
16728 MInt nghbrId = c_neighborId(c_parentId(cellId), dir);
16729 ASSERT(nghbrId > -1,
"Invalid neighbor id in FvMbCartesianSolverXD::getFacingNghbrs(..)");
16730 if(a_isBndryGhostCell(nghbrId))
continue;
16731 if(c_noChildren(nghbrId) == 0) m_nghbrList[counter++] = nghbrId;
16744template <MInt nDim,
class SysEqn>
16746 const MInt dir = a_surfaceOrientation(srfcId);
16747 const MInt nghbr0 = a_surfaceNghbrCellId(srfcId, 0);
16748 const MInt nghbr1 = a_surfaceNghbrCellId(srfcId, 1);
16751 ASSERT(m_cellSurfaceMapping[nghbr0][2 * dir + 1] < 0 || m_cellSurfaceMapping[nghbr0][2 * dir + 1] == srfcId,
16752 to_string(m_cellSurfaceMapping[nghbr0][2 * dir + 1]));
16753 m_cellSurfaceMapping[nghbr0][2 * dir + 1] = -1;
16754 if(a_bndryId(nghbr0) > -1) {
16755 m_bndryCells->a[a_bndryId(nghbr0)].m_associatedSrfc[2 * dir + 1] = -1;
16756 MInt bndryId = a_bndryId(nghbr0);
16757 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
16758 for(
MInt i = 0; i < nDim; i++) {
16759 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] == srfcId) {
16760 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] = -1;
16768 ASSERT(m_cellSurfaceMapping[nghbr1][2 * dir] < 0 || m_cellSurfaceMapping[nghbr1][2 * dir] == srfcId,
16769 to_string(m_cellSurfaceMapping[nghbr1][2 * dir]));
16770 m_cellSurfaceMapping[nghbr1][2 * dir] = -1;
16771 if(a_bndryId(nghbr1) > -1) {
16772 m_bndryCells->a[a_bndryId(nghbr1)].m_associatedSrfc[2 * dir] = -1;
16773 MInt bndryId = a_bndryId(nghbr1);
16774 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
16775 for(
MInt i = 0; i < nDim; i++) {
16776 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] == srfcId) {
16777 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] = -1;
16784 a_surfaceNghbrCellId(srfcId, 0) = -1;
16785 a_surfaceNghbrCellId(srfcId, 1) = -1;
16786 a_surfaceBndryCndId(srfcId) = -1;
16787 m_splitSurfaces.erase(srfcId);
16789 if(srfcId >= a_noSurfaces()) {
16790 mTerm(1, AT_,
"Invalid surface.");
16791 }
else if(srfcId == (a_noSurfaces() - 1)) {
16792 m_surfaces.erase(a_noSurfaces() - 1);
16793 m_surfaces.size(a_noSurfaces() - 1);
16794 m_noSurfaces = a_noSurfaces();
16796 m_freeSurfaceIndices.insert(srfcId);
16805template <MInt nDim,
class SysEqn>
16807 for(
MInt dir = 0; dir < m_noDirs; dir++) {
16808 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
16811 deleteSurface(srfcId);
16813 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && checkNeighborActive(cellId, dir)
16814 && a_hasNeighbor(cellId, dir) > 0) {
16815 MInt nghbrId = c_neighborId(cellId, dir);
16816 if(c_noChildren(nghbrId) > 0) {
16817 for(
MInt child = 0; child < m_noCellNodes; child++) {
16818 if(!childCode[dir][child])
continue;
16819 MInt childId = c_childId(nghbrId, child);
16820 if(childId < 0)
continue;
16821 srfcId = m_cellSurfaceMapping[childId][
m_revDir[dir]];
16823 deleteSurface(srfcId);
16837template <MInt nDim,
class SysEqn>
16839 if(cellId1 == cellId0)
return;
16843 for(
MInt v = 0; v < m_noFVars; v++) {
16844 std::swap(m_rhs0[cellId1][v], m_rhs0[cellId0][v]);
16847 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
16848 std::swap(a_levelSetValuesMb(cellId1, set), a_levelSetValuesMb(cellId0, set));
16849 std::swap(a_associatedBodyIds(cellId1, set), a_associatedBodyIds(cellId0, set));
16852 std::swap(m_cellVolumesDt1[cellId1], m_cellVolumesDt1[cellId0]);
16853 if(m_dualTimeStepping) std::swap(m_cellVolumesDt2[cellId1], m_cellVolumesDt2[cellId0]);
16855 if(!m_oldBndryCells.empty()) {
16856 auto it0 = m_oldBndryCells.find(cellId0);
16857 auto it1 = m_oldBndryCells.find(cellId1);
16858 if(it0 != m_oldBndryCells.end() && it1 != m_oldBndryCells.end()) {
16859 std::swap(it0->second, it1->second);
16860 }
else if(it0 != m_oldBndryCells.end()) {
16861 MFloat val = it0->second;
16862 m_oldBndryCells.erase(it0);
16863 m_oldBndryCells.insert(make_pair(cellId1, val));
16864 }
else if(it1 != m_oldBndryCells.end()) {
16865 MFloat val = it1->second;
16866 m_oldBndryCells.erase(it1);
16867 m_oldBndryCells.insert(make_pair(cellId0, val));
16871 if(!m_nearBoundaryBackup.empty()) {
16872 auto it0 = m_nearBoundaryBackup.find(cellId0);
16873 auto it1 = m_nearBoundaryBackup.find(cellId1);
16874 if(it0 != m_nearBoundaryBackup.end() && it1 != m_nearBoundaryBackup.end()) {
16875 std::swap(it0->second, it1->second);
16876 }
else if(it0 != m_nearBoundaryBackup.end()) {
16877 vector<MFloat> val(it0->second);
16878 m_nearBoundaryBackup.erase(it0);
16879 m_nearBoundaryBackup.insert(make_pair(cellId1, val));
16880 }
else if(it1 != m_nearBoundaryBackup.end()) {
16881 vector<MFloat> val(it1->second);
16882 m_nearBoundaryBackup.erase(it1);
16883 m_nearBoundaryBackup.insert(make_pair(cellId0, val));
16887 if(!m_coarseOldBndryCells.empty()) {
16888 auto it0 = m_coarseOldBndryCells.find(cellId0);
16889 auto it1 = m_coarseOldBndryCells.find(cellId1);
16890 if(it0 != m_coarseOldBndryCells.end() && it1 == m_coarseOldBndryCells.end()) {
16892 }
else if(it0 != m_coarseOldBndryCells.end()) {
16893 m_coarseOldBndryCells.erase(it0);
16894 m_coarseOldBndryCells.insert(cellId1);
16895 }
else if(it1 != m_coarseOldBndryCells.end()) {
16896 m_coarseOldBndryCells.erase(it1);
16897 m_coarseOldBndryCells.insert(cellId0);
16901 if(!m_oldGeomBndryCells.empty()) {
16902 auto it0 = m_oldGeomBndryCells.find(cellId0);
16903 auto it1 = m_oldGeomBndryCells.find(cellId1);
16904 if(it0 != m_oldGeomBndryCells.end() && it1 == m_oldGeomBndryCells.end()) {
16905 std::swap(it0->second, it1->second);
16906 }
else if(it0 != m_oldGeomBndryCells.end()) {
16907 const MFloat volume = it0->second;
16908 m_oldGeomBndryCells.erase(it0);
16909 m_oldGeomBndryCells.insert(make_pair(cellId1, volume));
16910 }
else if(it1 != m_oldGeomBndryCells.end()) {
16911 const MFloat volume = it1->second;
16912 m_oldGeomBndryCells.erase(it1);
16913 m_oldGeomBndryCells.insert(make_pair(cellId0, volume));
16918 if(grid().azimuthalPeriodicity()) {
16919 MInt cnt0 = m_azimuthalNearBoundaryBackup.count(cellId0);
16920 MInt cnt1 = m_azimuthalNearBoundaryBackup.count(cellId1);
16921 ASSERT(cnt0 < 3 && cnt1 < 3,
"cnt should not exceed 2");
16923 auto range = m_azimuthalNearBoundaryBackup.equal_range(cellId0);
16924 auto it00 = range.first;
16925 auto it01 = it00++;
16928 pair<vector<MFloat>, vector<MUlong>> tmp(it00->second.first, it00->second.second);
16929 m_azimuthalNearBoundaryBackup.erase(it00);
16930 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId1, tmp));
16933 pair<vector<MFloat>, vector<MUlong>> tmp(it01->second.first, it01->second.second);
16934 m_azimuthalNearBoundaryBackup.erase(it01);
16935 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId1, tmp));
16937 }
else if(cnt1 == 1) {
16939 auto it10 = m_azimuthalNearBoundaryBackup.find(cellId1);
16940 std::swap(it00->second, it10->second);
16943 pair<vector<MFloat>, vector<MUlong>> tmp(it01->second.first, it01->second.second);
16944 m_azimuthalNearBoundaryBackup.erase(it01);
16945 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId1, tmp));
16948 auto range2 = m_azimuthalNearBoundaryBackup.equal_range(cellId1);
16949 auto it10 = range2.first;
16950 auto it11 = it10++;
16951 std::swap(it00->second, it10->second);
16952 std::swap(it01->second, it11->second);
16954 }
else if(cnt0 == 1) {
16955 auto it00 = m_azimuthalNearBoundaryBackup.find(cellId0);
16957 pair<vector<MFloat>, vector<MUlong>> tmp(it00->second.first, it00->second.second);
16958 m_azimuthalNearBoundaryBackup.erase(it00);
16959 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId1, tmp));
16960 }
else if(cnt1 == 1) {
16961 auto it10 = m_azimuthalNearBoundaryBackup.find(cellId1);
16962 std::swap(it00->second, it10->second);
16964 auto range = m_azimuthalNearBoundaryBackup.equal_range(cellId1);
16965 auto it10 = range.first;
16966 auto it11 = it10++;
16967 std::swap(it00->second, it10->second);
16968 pair<vector<MFloat>, vector<MUlong>> tmp(it11->second.first, it11->second.second);
16969 m_azimuthalNearBoundaryBackup.erase(it11);
16970 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId0, tmp));
16975 }
else if(cnt1 == 1) {
16976 auto it10 = m_azimuthalNearBoundaryBackup.find(cellId1);
16977 pair<vector<MFloat>, vector<MUlong>> tmp(it10->second.first, it10->second.second);
16978 m_azimuthalNearBoundaryBackup.erase(it10);
16979 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId0, tmp));
16981 auto range = m_azimuthalNearBoundaryBackup.equal_range(cellId1);
16982 auto it10 = range.first;
16983 auto it11 = it10++;
16985 pair<vector<MFloat>, vector<MUlong>> tmp(it10->second.first, it10->second.second);
16986 m_azimuthalNearBoundaryBackup.erase(it10);
16987 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId0, tmp));
16990 pair<vector<MFloat>, vector<MUlong>> tmp(it11->second.first, it11->second.second);
16991 m_azimuthalNearBoundaryBackup.erase(it11);
16992 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId0, tmp));
17004template <MInt nDim,
class SysEqn>
17008 if(m_freeSurfaceIndices.size() > 0) {
17009 set<MInt>::iterator it = m_freeSurfaceIndices.begin();
17011 m_freeSurfaceIndices.erase(it);
17012 if(srfcId >= a_noSurfaces()) {
17014 m_freeSurfaceIndices.clear();
17018 srfcId = a_noSurfaces();
17019 m_surfaces.append();
17020 m_noSurfaces = a_noSurfaces();
17031template <MInt nDim,
class SysEqn>
17035 m_log <<
"Creating initial surfaces..." << endl;
17037 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
17040 surfArea.
fill(sqrt(-F1));
17041 surfCentroid.
fill(sqrt(-F1));
17042 for(
MInt srfcId = 0; srfcId < a_noSurfaces(); srfcId++) {
17043 for(
MInt side = 0; side < 2; side++) {
17044 MInt ori = a_surfaceOrientation(srfcId);
17045 MInt cellId = a_surfaceNghbrCellId(srfcId, side);
17047 MInt bndryId = a_bndryId(cellId);
17049 MInt dir = (side == 0) ? 2 * ori + 1 : 2 * ori;
17050 surfArea(bndryId, dir) = a_surfaceArea(srfcId);
17052 for(
MInt i = 0; i < nDim; i++) {
17053 surfCentroid(bndryId, dir, i) = a_surfaceCoordinate(srfcId, i);
17066 MInt otherDir[] = {1, 0, 3, 2, 5, 4};
17067 for(
MInt bndryId = 0; bndryId < noBndryCells; bndryId++) {
17068 MInt cell = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
17070 if(!a_hasProperty(cell, SolverCell::IsOnCurrentMGLevel))
continue;
17072 for(
MInt dirId = 0; dirId < m_noDirs; dirId++) {
17073 if(a_hasNeighbor(cell, dirId) > 0) {
17074 nghbrId = c_neighborId(cell, dirId);
17076 if(c_parentId(cell) > -1) {
17077 if(a_hasNeighbor(c_parentId(cell), dirId) > 0) {
17078 nghbrId = c_neighborId(c_parentId(cell), dirId);
17087 if(a_bndryId(nghbrId) < 0)
continue;
17088 MBool createSrfc =
true;
17093 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId > -1) {
17094 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId == nghbrId
17095 || m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId
17096 == m_fvBndryCnd->m_bndryCells->a[a_bndryId(nghbrId)].m_linkedCellId) {
17097 createSrfc =
false;
17100 if(m_fvBndryCnd->m_bndryCells->a[a_bndryId(nghbrId)].m_linkedCellId > -1) {
17101 if(m_fvBndryCnd->m_bndryCells->a[a_bndryId(nghbrId)].m_linkedCellId == (
MInt)cell
17102 || m_fvBndryCnd->m_bndryCells->a[a_bndryId(nghbrId)].m_linkedCellId
17103 == m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId) {
17104 createSrfc =
false;
17107 if(a_isPeriodic(cell) && a_isPeriodic(nghbrId)) createSrfc =
false;
17111 if(a_isHalo(cell) && a_isHalo(nghbrId)) {
17112 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId == -1
17113 && m_fvBndryCnd->m_bndryCells->a[a_bndryId(nghbrId)].m_linkedCellId == -1) {
17114 createSrfc =
false;
17119 if(!createSrfc)
continue;
17121 if((a_level(cell) > a_level(nghbrId)) || ((a_level(cell) == a_level(nghbrId)) && dirId % 2 == 0)) {
17122 MInt oldSrfcId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_associatedSrfc[dirId];
17124 if(oldSrfcId < 0)
continue;
17126 if(oldSrfcId != counter) {
17127 m_surfaces.copy(oldSrfcId, counter);
17128 m_surfaces.erase(oldSrfcId);
17129 if(a_level(cell) == a_level(nghbrId))
17130 m_fvBndryCnd->m_bndryCells->a[a_bndryId(nghbrId)].m_associatedSrfc[otherDir[dirId]] = counter;
17138 while(a_noSurfaces() > counter) {
17139 MInt size = a_noSurfaces();
17140 m_surfaces.erase(size - 1);
17141 m_surfaces.size(size - 1);
17145 MInt noSurfaces = a_noSurfaces();
17146 MIntScratchSpace surfaceOrientation(noSurfaces, AT_,
"surfaceOrientation");
17148 MIntScratchSpace surfaceNeighbors(noSurfaces, 2, AT_,
"surfaceNeighbors");
17150 for(
MInt s = 0; s < noSurfaces; s++) {
17151 surfaceOrientation[s] = a_surfaceOrientation(s);
17152 surfaceArea[s] = a_surfaceArea(s);
17153 surfaceNeighbors(s, 0) = a_surfaceNghbrCellId(s, 0);
17154 surfaceNeighbors(s, 1) = a_surfaceNghbrCellId(s, 1);
17155 for(
MInt i = 0; i < nDim; i++) {
17156 surfaceCentroid(s, i) = a_surfaceCoordinate(s, i);
17160 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
17161 if(a_isBndryGhostCell(cellId))
continue;
17162 if(c_noChildren(cellId) > 0)
continue;
17163 removeSurfaces(cellId);
17165 m_surfaces.clear();
17167 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
17168 if(a_bndryId(cellId) < -1)
continue;
17169 if(a_isBndryGhostCell(cellId))
continue;
17170 if(c_noChildren(cellId) > 0)
continue;
17171 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
17172 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
17174 restoreSurfaces(cellId);
17177 m_log << a_noSurfaces() << endl;
17181 for(
MInt bndryId = 0; bndryId < m_bndryCells->size(); bndryId++)
17182 for(
MInt dir = 0; dir < m_noDirs; dir++)
17183 m_fvBndryCnd->m_bndryCells->a[bndryId].m_associatedSrfc[dir] = -1;
17185 for(
MInt srfcId = 0; srfcId < a_noSurfaces(); srfcId++) {
17186 MInt nghbr0 = a_surfaceNghbrCellId(srfcId, 0);
17187 MInt nghbr1 = a_surfaceNghbrCellId(srfcId, 1);
17188 ASSERT(nghbr0 > -1 && nghbr1 > -1 && nghbr0 < a_noCells() && nghbr1 < a_noCells(),
"");
17189 MInt bndryIdN0 = a_bndryId(nghbr0);
17190 MInt bndryIdN1 = a_bndryId(nghbr1);
17191 if(bndryIdN0 > -1 && bndryIdN1 > -1) {
17192 MInt dirN0 = 2 * a_surfaceOrientation(srfcId) + 1;
17193 MInt dirN1 = 2 * a_surfaceOrientation(srfcId) + 0;
17194 MInt level0 = a_level(nghbr0);
17195 MInt level1 = a_level(nghbr1);
17196 if(level0 >= level1) m_fvBndryCnd->m_bndryCells->a[bndryIdN0].m_associatedSrfc[dirN0] = srfcId;
17197 if(level1 >= level0) m_fvBndryCnd->m_bndryCells->a[bndryIdN1].m_associatedSrfc[dirN1] = srfcId;
17200 a_surfaceArea(srfcId) = surfArea(bndryIdN0, dirN0);
17201 for(
MInt i = 0; i < nDim; i++) {
17202 a_surfaceCoordinate(srfcId, i) = surfCentroid(bndryIdN0, dirN0, i);
17208 for(
MInt s = 0; s < noSurfaces; s++) {
17209 MInt nghbr0 = surfaceNeighbors(s, 0);
17210 MInt nghbr1 = surfaceNeighbors(s, 1);
17211 if(nghbr0 < 0 || nghbr1 < 0)
continue;
17212 ASSERT(nghbr0 > -1 && nghbr1 > -1 && nghbr0 < a_noCells() && nghbr1 < a_noCells(),
"");
17213 MInt bndryIdN0 = a_bndryId(nghbr0);
17214 MInt bndryIdN1 = a_bndryId(nghbr1);
17215 if(bndryIdN0 > -1 && bndryIdN1 > -1) {
17216 MInt dirN0 = 2 * surfaceOrientation(s) + 1;
17217 MInt dirN1 = 2 * surfaceOrientation(s) + 0;
17218 MInt level0 = a_level(nghbr0);
17219 MInt level1 = a_level(nghbr1);
17220 if(level0 == level1) {
17221 MInt associatedSrfc0 = m_fvBndryCnd->m_bndryCells->a[bndryIdN0].m_associatedSrfc[dirN0];
17222 MInt associatedSrfc1 = m_fvBndryCnd->m_bndryCells->a[bndryIdN1].m_associatedSrfc[dirN1];
17223 ASSERT(associatedSrfc0 == associatedSrfc1,
"");
17225 MInt associatedSrfc = (level0 > level1) ? m_fvBndryCnd->m_bndryCells->a[bndryIdN0].m_associatedSrfc[dirN0]
17226 : m_fvBndryCnd->m_bndryCells->a[bndryIdN1].m_associatedSrfc[dirN1];
17227 if(associatedSrfc < 0)
17228 cerr <<
"surface info " << nghbr0 <<
" " << nghbr1 <<
" " << c_globalId(nghbr0) <<
" " << c_globalId(nghbr1)
17229 <<
" / " << level0 <<
" " << level1 <<
" " << dirN0 <<
" " << dirN1 <<
" / "
17230 << m_fvBndryCnd->m_bndryCells->a[bndryIdN0].m_associatedSrfc[dirN0] <<
" "
17231 << m_fvBndryCnd->m_bndryCells->a[bndryIdN1].m_associatedSrfc[dirN1] <<
" / "
17232 << a_hasProperty(nghbr0, SolverCell::IsInactive) <<
" " << a_hasProperty(nghbr1, SolverCell::IsInactive)
17233 <<
" / " << a_hasProperty(nghbr0, SolverCell::IsNotGradient) <<
" "
17234 << a_hasProperty(nghbr1, SolverCell::IsNotGradient) <<
" / " << surfaceCentroid(s, 0) <<
" "
17235 << surfaceCentroid(s, 1) <<
" " << surfaceCentroid(s, nDim - 1) << endl;
17237 if(associatedSrfc > -1) {
17238 ASSERT(associatedSrfc > -1 && associatedSrfc < a_noSurfaces(), to_string(associatedSrfc));
17239 ASSERT(a_surfaceOrientation(associatedSrfc) == surfaceOrientation(s),
"");
17240 ASSERT(a_surfaceNghbrCellId(associatedSrfc, 0) == surfaceNeighbors(s, 0),
"");
17241 ASSERT(a_surfaceNghbrCellId(associatedSrfc, 1) == surfaceNeighbors(s, 1),
"");
17246 m_log <<
"...done." << endl;
17247 m_log << a_noSurfaces() <<
" surfaces created." << endl;
17255template <MInt nDim,
class SysEqn>
17259 m_reconstructionConstants.clear();
17260 m_reconstructionCellIds.clear();
17261 m_reconstructionNghbrIds.clear();
17263 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
17266 a_noReconstructionNeighbors(cellId) = 0;
17268 if(a_isBndryGhostCell(cellId))
continue;
17269 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
17270 if(!a_hasProperty(cellId, SolverCell::IsFlux))
continue;
17271 if(a_bndryId(cellId) == -2)
continue;
17272 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
17273 if(c_noChildren(cellId) > 0)
continue;
17274 if(a_bndryId(cellId) > -1) {
17275 if(m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_linkedCellId > -1)
continue;
17277 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
17280 rebuildReconstructionConstants(cellId);
17289template <MInt nDim,
class SysEqn>
17293#if defined _MB_DEBUG_ || !defined NDEBUG
17295 for(
MInt i = 0; i < noNeighborDomains(); i++) {
17296 for(
MInt j = 0; j < m_noMaxLevelWindowCells[i]; j++) {
17297 MInt cellId = m_maxLevelWindowCells[i][j];
17298 for(
MInt v = 0; v < m_noPVars; v++) {
17299 if(std::isnan(a_pvariable(cellId, v))) {
17300 cerr << domainId() <<
": nan send " << cellId <<
" " << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)
17301 <<
" " << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << c_noChildren(cellId) <<
" "
17302 << a_levelSetValuesMb(cellId, 0) << endl;
17312 for(
MInt sc = 0; (unsigned)sc < m_splitCells.size(); sc++) {
17313 MInt scId = m_splitCells[sc];
17314 for(
MInt ssc = 0; (unsigned)ssc < m_splitChilds[sc].size(); ssc++) {
17315 MInt splitChildId = m_splitChilds[sc][ssc];
17316 for(
MInt v = 0; v < m_noCVars; v++) {
17317 a_variable(splitChildId, v) = a_variable(scId, v);
17319 for(
MInt v = 0; v < m_noPVars; v++) {
17320 a_pvariable(splitChildId, v) = a_pvariable(scId, v);
17328 if(!isMultilevel() || isMultilevelPrimary()) {
17329 m_solutionDiverged =
false;
17331 for(
MInt i = 0; i < noNeighborDomains(); i++) {
17332 for(
MInt j = 0; j < m_noMaxLevelHaloCells[i]; j++) {
17334 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
17335 ASSERT(a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel),
"");
17336 for(
MInt v = 0; v < m_noPVars; v++) {
17337 if(!(a_pvariable(cellId, v) >= F0 || a_pvariable(cellId, v) < F0) || std::isnan(a_pvariable(cellId, v))) {
17338 cerr << domainId() <<
": EXC " << i <<
" " << j <<
" " << c_globalId(cellId) <<
" " << a_bndryId(cellId)
17339 <<
" " << a_level(cellId) <<
" /v " << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId))
17340 <<
" " << m_cellVolumesDt1[
cellId] / grid().gridCellVolume(a_level(cellId)) <<
" " << v <<
" "
17341 << a_variable(cellId, v) <<
" /l " << a_levelSetValuesMb(cellId, 0) / c_cellLengthAtCell(cellId) <<
" "
17342 << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" "
17343 << a_coordinate(cellId,
mMin((
MInt)FD, 2)) <<
" "
17344 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) << endl;
17345 m_solutionDiverged =
true;
17350 if(a_pvariable(cellId, PV->RHO) < F0 || a_pvariable(cellId, PV->P) < F0) {
17351 cerr << domainId() <<
": EXC2 " << i <<
" " << j <<
" " << neighborDomain(i) <<
" / " << c_globalId(cellId)
17352 <<
" " << a_bndryId(cellId) <<
" " << a_level(cellId) <<
" /r " << a_pvariable(cellId, PV->RHO) <<
" /p "
17353 << a_pvariable(cellId, PV->P) <<
" /v " << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId))
17354 <<
" " << m_cellVolumesDt1[
cellId] / grid().gridCellVolume(a_level(cellId)) <<
" /l "
17355 << a_levelSetValuesMb(cellId, 0) / c_cellLengthAtCell(cellId) <<
" " << a_coordinate(cellId, 0) <<
" "
17356 << a_coordinate(cellId, 1) <<
" " << a_coordinate(cellId,
mMin((
MInt)FD, 2)) <<
" "
17357 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) << endl;
17358 m_solutionDiverged =
true;
17362 if(cnt >= 10)
break;
17364 if(cnt >= 10)
break;
17366 if(cnt >= 10) cerr <<
"More than 10 errors. Not reporting any more." << endl;
17367 if(m_solutionDiverged) {
17368 cerr <<
"Solution diverged (EXC) at solver " << domainId() <<
" " <<
globalTimeStep <<
" " << m_RKStep << endl;
17370 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
17371 "m_solutionDiverged");
17373 if(m_solutionDiverged) {
17374 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
17376 mTerm(1, AT_,
"Solution diverged after exchange.");
17382 for(
MInt i = 0; i < noNeighborDomains(); i++) {
17383 for(
MInt j = 0; j < m_noMaxLevelHaloCells[i]; j++) {
17384 const MInt cellId = m_maxLevelHaloCells[i][j];
17385 setConservativeVariables(cellId);
17395template <MInt nDim,
class SysEqn>
17397 const MInt recDim = (m_orderOfReconstruction == 2) ? (
IPOW2(nDim) + 1) : nDim;
17398 const MInt maxNoNghbrs = 150;
17403 if(c_noChildren(cellId) > 0 || a_hasProperty(cellId, SolverCell::IsNotGradient)
17404 || !a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
17405 cerr << domainId() <<
" Warning: trying to rebuild stencil of cell " << cellId <<
" with " << c_noChildren(cellId)
17406 <<
" children and prop-7=" << a_hasProperty(cellId, SolverCell::IsNotGradient)
17407 <<
", prop-13=" << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
", level=" << a_level(cellId)
17408 <<
", inact=" << a_hasProperty(cellId, SolverCell::IsInactive) <<
". Skipped." << endl;
17409 a_noReconstructionNeighbors(cellId) = 0;
17413 const MInt counter = this->
template getAdjacentLeafCells<0, true>(cellId, 1, nghbrList, layerId);
17415 if(counter > maxNoNghbrs) {
17416 mTerm(1, AT_,
"too many nghbrs " + to_string(counter));
17418 a_noReconstructionNeighbors(cellId) = 0;
17420 if(a_bndryId(cellId) > -1) {
17421 for(
MInt srfc = 0; srfc < m_bndryCells->a[a_bndryId(cellId)].m_noSrfcs; srfc++) {
17422 MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_srfcVariables[srfc]->m_ghostCellId;
17423 if(ghostCellId < 0) cerr << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) << endl;
17424 if(ghostCellId < 0)
17426 "ghostCellId not set! " + to_string(cellId) +
" " + to_string(a_bndryId(cellId)) +
" "
17427 + to_string(ghostCellId) +
" " + to_string(srfc) +
" " + to_string(a_isHalo(cellId)) +
" "
17428 + to_string(a_isBndryGhostCell(cellId)));
17429 a_reconstructionNeighborId(cellId, a_noReconstructionNeighbors(cellId)) = ghostCellId;
17430 a_noReconstructionNeighbors(cellId)++;
17434 MBool atInterface =
false;
17435 for(
MInt k = 0; k < counter; k++) {
17436 MInt nghbrId = nghbrList[k];
17437 if(nghbrId < 0)
continue;
17438 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
17439 a_reconstructionNeighborId(cellId, a_noReconstructionNeighbors(cellId)) = nghbrId;
17440 a_noReconstructionNeighbors(cellId)++;
17441 if(a_noReconstructionNeighbors(cellId) > m_cells.noRecNghbrs()) {
17442 mTerm(1, AT_,
"too many rec nghbrs " + to_string(cellId));
17444 if(a_level(nghbrId) < a_level(cellId)) {
17445 atInterface =
true;
17451 if(m_localTS && atInterface) {
17452 const MInt counter2 = this->
template getAdjacentLeafCells<2, true>(cellId, 1, nghbrList, layerId);
17453 for(
MInt k = 0; k < counter2; k++) {
17454 MInt nghbrId = nghbrList[k];
17458 if(a_hasProperty(nghbrId, SolverCell::IsInvalid)) {
17461 if(a_level(nghbrId) >= a_level(cellId)) {
17464 MBool exist =
false;
17465 for(
MInt i = 0; i < a_noReconstructionNeighbors(cellId); i++) {
17466 if(a_reconstructionNeighborId(cellId, i) == nghbrId) {
17472 a_reconstructionNeighborId(cellId, a_noReconstructionNeighbors(cellId)) = nghbrId;
17473 a_noReconstructionNeighbors(cellId)++;
17475 if(a_noReconstructionNeighbors(cellId) > m_cells.noRecNghbrs()) {
17476 mTerm(1, AT_,
"too many rec nghbrs " + to_string(cellId) +
" " + to_string(counter));
17482 const MInt noNghbrIds = a_noReconstructionNeighbors(cellId);
17488 ASSERT(!a_hasProperty(cellId, SolverCell::IsNotGradient) && c_isLeafCell(cellId),
17489 "a_hasProperty(cellId, SolverCell::IsNotGradient) "
17490 + std::to_string(a_hasProperty(cellId, SolverCell::IsNotGradient)) +
" c_isLeafCell(cellId) "
17491 + std::to_string(c_isLeafCell(cellId)));
17493 const MInt offset = m_cells.noRecNghbrs() * cellId;
17494 computeRecConstSVD(cellId, offset, tmpA, tmpC, weights, recDim, 0, -1);
17503template <MInt nDim,
class SysEqn>
17506 TERMM_IF_COND(m_reConstSVDWeightMode == 3 || m_reConstSVDWeightMode == 4,
"Not yet implemented!");
17508 MFloat* RESTRICT slope = (
MFloat*)(&(a_slope(0, 0, 0)));
17509 MFloat* RESTRICT vars = (
MFloat*)(&(a_pvariable(0, 0)));
17510 const MInt noCells = a_noCells();
17512 std::fill_n(slope, noCells * m_noSlopes, 0.0);
17515#pragma omp parallel for
17517 for(
MInt cellId = 0; cellId < noCells; cellId++) {
17518 if(a_hasProperty(cellId, SolverCell::IsNotGradient)) {
17521 if(a_isBndryGhostCell(cellId)) {
17524 if(a_hasProperty(cellId, SolverCell::IsInactive)) {
17528 const MInt k = m_noSlopes * cellId;
17529 const MInt offset = nDim * a_reconstructionData(cellId);
17530 for(
MInt n = a_noReconstructionNeighbors(cellId); n--;) {
17531 for(
MInt v = 0; v < m_noPVars; v++) {
17532 IF_CONSTEXPR(nDim == 3) {
17536 slope[k + nDim * v + 2] +=
17537 m_reconstructionConstants[offset + n * nDim + 2]
17538 * (vars[m_noPVars * a_reconstructionNeighborId(cellId, n) + v] - vars[m_noPVars * cellId + v]);
17543 slope[k + nDim * v + 1] +=
17544 m_reconstructionConstants[offset + n * nDim + 1]
17545 * (vars[m_noPVars * a_reconstructionNeighborId(cellId, n) + v] - vars[m_noPVars * cellId + v]);
17549 slope[k + nDim * v] +=
17550 m_reconstructionConstants[offset + n * nDim]
17551 * (vars[m_noPVars * a_reconstructionNeighborId(cellId, n) + v] - vars[m_noPVars * cellId + v]);
17556 if(!m_useCentralDifferencingSlopes) {
17563 nearBnd.
fill(
false);
17564 array<MFloat, 20> centralDiffConst;
17565 std::vector<std::vector<MInt>> structuredCells(maxLevel() - minLevel() + 1);
17566 std::vector<MInt> nearBoundaryCells;
17568 for(
MInt level = minLevel(); level <= maxLevel(); level++) {
17569 structuredCells[level - minLevel()].clear();
17572 for(
MInt level = minLevel(); level <= maxRefinementLevel(); level++) {
17573 centralDiffConst[level] = 1.0 / (2.0 * c_cellLengthAtLevel(level));
17577#pragma omp parallel for
17579 for(
MInt bndryId = 0; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
17580 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
17581 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
17585 atBnd(cellId) =
true;
17586 MInt parentId = a_hasProperty(cellId, SolverCell::IsSplitChild) ? c_parentId(getAssociatedInternalCell(cellId))
17587 : c_parentId(cellId);
17588 while(parentId > -1) {
17589 atBnd(parentId) =
true;
17590 parentId = c_parentId(parentId);
17595#pragma omp parallel for
17597 for(
MInt cellId = 0; cellId < noCells; cellId++) {
17598 if(a_bndryId(cellId) < -1)
continue;
17599 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
17600 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
17601 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
17602 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
17604 if(atBnd(cellId)) {
17605 nearBoundaryCells.push_back(cellId);
17606 nearBnd(cellId) =
true;
17609 MBool nearb =
false;
17610 for(
MInt dir = 0; dir < m_noDirs; dir++) {
17611 if(!a_hasNeighbor(cellId, dir)) {
17612 MInt parentId = c_parentId(cellId);
17613 while(parentId > -1) {
17614 if(a_hasNeighbor(parentId, dir)) {
17615 if(atBnd(c_neighborId(parentId, dir))) {
17620 parentId = c_parentId(parentId);
17622 }
else if(atBnd(c_neighborId(cellId, dir))) {
17628 nearBoundaryCells.push_back(cellId);
17629 nearBnd(cellId) =
true;
17635#pragma omp parallel for
17637 for(
MInt cellId = 0; cellId < noCells; cellId++) {
17638 if(a_bndryId(cellId) != -1)
continue;
17639 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
17640 if(nearBnd(cellId))
continue;
17641 if(!c_isLeafCell(cellId))
continue;
17642 if(a_hasProperty(cellId, SolverCell::IsInactive)) {
17643 nearBnd(cellId) =
true;
17644 MInt parentId = c_parentId(cellId);
17645 while(parentId > -1) {
17646 nearBnd(parentId) =
true;
17647 parentId = c_parentId(parentId);
17652 for(
MInt level = minLevel(); level <= maxLevel(); level++) {
17653 structuredCells[level - minLevel()].clear();
17656#pragma omp parallel for
17658 for(
MInt cellId = 0; cellId < noCells; cellId++) {
17659 if(a_bndryId(cellId) < -1)
continue;
17660 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
17661 if(nearBnd(cellId))
continue;
17662 if(a_hasProperty(cellId, SolverCell::AtStructuredRegion)) {
17663 structuredCells[c_level(cellId) - minLevel()].push_back(cellId);
17668#pragma omp parallel for
17671 for(
MInt cellId = 0; cellId < noCells; cellId++) {
17672 if(a_bndryId(cellId) < -1)
continue;
17673 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
17674 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
17675 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
17676 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
17677 if(!a_hasProperty(cellId, SolverCell::AtStructuredRegion) && !nearBnd(cellId)
17678 && !(c_parentId(cellId) > -1 && a_hasProperty(c_parentId(cellId), SolverCell::AtStructuredRegion)))
17679 cerr <<
"strng " << c_globalId(cellId) <<
" " << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" "
17680 << a_hasProperty(cellId, Cell::IsHalo) <<
" " << c_neighborId(cellId, 0) <<
" " << c_neighborId(cellId, 1)
17681 <<
" " << c_neighborId(cellId, 2) <<
" " << c_neighborId(cellId, 3) << endl;
17682 ASSERT(a_hasProperty(cellId, SolverCell::AtStructuredRegion) || nearBnd(cellId)
17683 || (c_parentId(cellId) > -1 && a_hasProperty(c_parentId(cellId), SolverCell::AtStructuredRegion)),
17684 to_string(c_globalId(cellId)));
17688 for(
MInt level = minLevel(); level <= maxRefinementLevel(); level++) {
17689 const MFloat fdx = centralDiffConst[level];
17690 for(
MUint c = 0; c < structuredCells[level - minLevel()].size(); c++) {
17691 MInt cellId = structuredCells[level - minLevel()][c];
17692 const MInt k = m_noSlopes * cellId;
17693 for(
MInt i = 0; i < nDim; i++) {
17694 MInt n0 = c_neighborId(cellId, 2 * i);
17695 MInt n1 = c_neighborId(cellId, 2 * i + 1);
17696 ASSERT(!atBnd(n0) && !atBnd(n1) && !nearBnd(cellId),
"");
17697 for(
MInt v = 0; v < m_noPVars; v++) {
17698 slope[k + nDim * v + i] = fdx * (a_pvariable(n1, v) - a_pvariable(n0, v));
17701 if(!c_isLeafCell(cellId)) {
17702 for(
MInt child = 0; child < m_noCellNodes; child++) {
17703 const MInt childId = c_childId(cellId, child);
17704 if(childId < 0)
continue;
17705 if(a_hasProperty(childId, SolverCell::AtStructuredRegion))
continue;
17706 for(
MInt i = 0; i < nDim; i++) {
17707 for(
MInt v = 0; v < m_noPVars; v++) {
17708 a_slope(childId, v, i) = a_slope(cellId, v, i);
17717#pragma omp parallel for
17719 for(
MInt cellId = noCells; cellId > 0; cellId--) {
17720 if(!nearBnd(cellId))
continue;
17722 const MInt k = m_noSlopes * cellId;
17723 const MInt offset = nDim * a_reconstructionData(cellId);
17724 std::fill_n(&slope[k], m_noPVars * nDim, F0);
17725 for(
MInt n = a_noReconstructionNeighbors(cellId); n--;) {
17726 for(
MInt v = m_noPVars; v--;) {
17727 IF_CONSTEXPR(nDim == 3) {
17731 slope[k + nDim * v + 2] +=
17732 m_reconstructionConstants[offset + n * nDim + 2]
17733 * (vars[m_noPVars * a_reconstructionNeighborId(cellId, n) + v] - vars[m_noPVars * cellId + v]);
17738 slope[k + nDim * v + 1] +=
17739 m_reconstructionConstants[offset + n * nDim + 1]
17740 * (vars[m_noPVars * a_reconstructionNeighborId(cellId, n) + v] - vars[m_noPVars * cellId + v]);
17744 slope[k + nDim * v] +=
17745 m_reconstructionConstants[offset + n * nDim]
17746 * (vars[m_noPVars * a_reconstructionNeighborId(cellId, n) + v] - vars[m_noPVars * cellId + v]);
17752 static constexpr MBool test1 =
false;
17753 static constexpr MBool test2 =
false;
17758 for(
MInt level = minLevel(); level <= maxRefinementLevel(); level++) {
17759 for(
MInt cellId = noCells; cellId--;) {
17760 if(atBnd(cellId))
continue;
17761 if(nearBnd(cellId))
continue;
17762 if(a_bndryId(cellId) < -1)
continue;
17763 if(a_hasProperty(cellId, SolverCell::AtStructuredRegion))
continue;
17765 if(level != c_level(cellId))
continue;
17766 const MFloat fdx = centralDiffConst[level];
17767 const MInt k = m_noSlopes * cellId;
17768 for(
MInt i = 0; i < nDim; i++) {
17769 MInt n0 = c_neighborId(cellId, 2 * i);
17770 MInt n1 = c_neighborId(cellId, 2 * i + 1);
17771 if(n0 > -1 && n1 > -1) {
17772 if(!atBnd(n0) && !atBnd(n1)) {
17773 ASSERT(!atBnd(n0) && !atBnd(n1) && !nearBnd(cellId),
"");
17774 for(
MInt v = 0; v < m_noPVars; v++) {
17775 slope[k + nDim * v + i] = fdx * (a_pvariable(n1, v) - a_pvariable(n0, v));
17779 if(!c_isLeafCell(cellId)) {
17780 for(
MInt child = 0; child < m_noCellNodes; child++) {
17781 MInt childId = c_childId(cellId, child);
17782 if(childId < 0)
continue;
17783 if(a_hasProperty(childId, SolverCell::AtStructuredRegion))
continue;
17784 for(
MInt v = 0; v < m_noPVars; v++) {
17785 a_slope(childId, v, i) = a_slope(cellId, v, i);
17799 for(
MInt cellId = noCells; cellId--;) {
17800 if(atBnd(cellId))
continue;
17801 if(nearBnd(cellId))
continue;
17802 if(a_bndryId(cellId) < -1)
continue;
17803 if(!a_hasProperty(cellId, SolverCell::AtStructuredRegion))
continue;
17804 if(!c_isLeafCell(cellId)) {
17805 for(
MInt child = 0; child < m_noCellNodes; child++) {
17806 MInt childId = c_childId(cellId, child);
17807 if(childId < 0)
continue;
17808 if(a_hasProperty(childId, SolverCell::AtStructuredRegion))
continue;
17810 const MInt k = m_noSlopes * childId;
17812 const MInt offset = nDim * a_reconstructionData(childId);
17813 std::fill_n(&slope[k], m_noPVars * nDim, F0);
17814 for(
MInt n = a_noReconstructionNeighbors(childId); n--;) {
17815 for(
MInt v = m_noPVars; v--;) {
17816 IF_CONSTEXPR(nDim == 3) {
17817 slope[k + nDim * v + 2] +=
17818 m_reconstructionConstants[offset + n * nDim + 2]
17819 * (vars[m_noPVars * a_reconstructionNeighborId(childId, n) + v] - vars[m_noPVars * childId + v]);
17821 slope[k + nDim * v + 1] +=
17822 m_reconstructionConstants[offset + n * nDim + 1]
17823 * (vars[m_noPVars * a_reconstructionNeighborId(childId, n) + v] - vars[m_noPVars * childId + v]);
17824 slope[k + nDim * v] +=
17825 m_reconstructionConstants[offset + n * nDim]
17826 * (vars[m_noPVars * a_reconstructionNeighborId(childId, n) + v] - vars[m_noPVars * childId + v]);
17841template <MInt nDim,
class SysEqn>
17844 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
17845 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
17846 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
17847 ASSERT(a_associatedBodyIds(cellId, 0) > -1
17848 && a_associatedBodyIds(cellId, 0) < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
17849 "associated body is invalid: " + to_string(0) +
"/" + to_string(a_associatedBodyIds(cellId, 0)) +
" "
17850 + to_string(c_globalId(cellId)));
17854 m_fvBndryCnd->updateGhostCellVariables();
17862template <MInt nDim,
class SysEqn>
17865 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
17866 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
17867 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
17868 ASSERT(a_associatedBodyIds(cellId, 0) > -1
17869 && a_associatedBodyIds(cellId, 0) < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
17870 "associated body is invalid: " + to_string(0) +
"/" + to_string(a_associatedBodyIds(cellId, 0)));
17874 m_fvBndryCnd->applyNeumannBoundaryCondition();
17883template <MInt nDim,
class SysEqn>
17887 if(!m_constructGField) {
17890 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
17891 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
17892 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
17894 if(a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
17895 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
17896 const MInt bodyId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0];
17897 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
17898 for(
MInt i = 0; i < nDim; i++) {
17899 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] =
17900 m_bodyVelocity[bodyId * nDim + i];
17904 MFloat vrad[3] = {F0, F0, F0};
17905 MFloat dx[3] = {F0, F0, F0};
17906 MFloat omega[3] = {F0, F0, F0};
17907 for(
MInt i = 0; i < nDim; i++) {
17908 dx[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[i]
17909 - m_bodyCenter[bodyId * nDim + i];
17912 for(
MInt i = 0; i < 3; i++) {
17913 omega[i] = m_bodyAngularVelocity[bodyId * 3 + i];
17916 vrad[0] = omega[1] * dx[2] - omega[2] * dx[1];
17917 vrad[1] = omega[2] * dx[0] - omega[0] * dx[2];
17919 IF_CONSTEXPR(nDim == 3) { vrad[2] = omega[0] * dx[1] - omega[1] * dx[0]; }
17921 mTerm(1, AT_,
"TODO");
17924 for(
MInt i = 0; i < nDim; i++) {
17925 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] += vrad[i];
17929 if(m_closeGaps && m_gapInitMethod == 0 && a_isGapCell(cellId)) {
17930 const MInt gapCellId = m_gapCellId[cellId];
17931 ASSERT(gapCellId > -1,
"");
17932 for(
MInt i = 0; i < nDim; i++) {
17933 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] =
17934 m_gapCells[gapCellId].surfaceVelocity[i];
17942 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
17943 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
17944 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
17945 const MInt bodyId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0];
17946 ASSERT(bodyId > -1 && bodyId < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
"");
17947 for(
MInt i = 0; i < nDim; i++) {
17948 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] =
17949 m_bodyVelocity[bodyId * nDim + i];
17951 MFloat dx[3] = {F0, F0, F0};
17952 MFloat omega[3] = {F0, F0, F0};
17953 MFloat vrad[3] = {F0, F0, F0};
17954 for(
MInt i = 0; i < nDim; i++) {
17956 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[i] - m_bodyCenter[bodyId * nDim + i];
17958 for(
MInt i = 0; i < 3; i++) {
17959 omega[i] = m_bodyAngularVelocity[bodyId * 3 + i];
17961 vrad[0] = omega[1] * dx[2] - omega[2] * dx[1];
17962 vrad[1] = omega[2] * dx[0] - omega[0] * dx[2];
17963 IF_CONSTEXPR(nDim == 3) { vrad[2] = omega[0] * dx[1] - omega[1] * dx[0]; }
17964 for(
MInt i = 0; i < nDim; i++) {
17965 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] += vrad[i];
17970 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
17971 for(
MInt i = 0; i < nDim; i++) {
17972 vel[i] = a_pvariable(cellId, PV->VV[i]);
17973 for(
MInt j = 0; j < nDim; j++) {
17974 vel[i] += m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i]
17975 * (m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]]
17976 - a_pvariable(cellId, PV->VV[j]))
17977 * m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[j];
17980 for(
MInt i = 0; i < nDim; i++) {
17981 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] = vel[i];
17994template <MInt nDim,
class SysEqn>
17996 ASSERT(!m_deleteNeighbour,
"");
17998 std::function<
MBool(
const MInt,
const MInt)> alwaysTrue = [&](
const MInt,
const MInt) {
return true; };
18000 for(
MUint it = 0; it < m_gapCells.size(); it++) {
18001 const MInt cellId = m_gapCells[it].cellId;
18002 const MInt bndryId = a_bndryId(cellId);
18003 if(bndryId < 0)
continue;
18005 MInt gridCellId = cellId;
18006 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
18007 gridCellId = getAssociatedInternalCell(cellId);
18009 const MInt regionId = m_gapCells[it].region;
18010 if(m_gapInitMethod > 0 && regionId != m_noGapRegions)
continue;
18012 const MInt body1 = a_associatedBodyIds(gridCellId, 0);
18014 for(
MInt i = 0; i < nDim; i++) {
18015 m_gapCells[it].surfaceVelocity[i] = m_bodyVelocity[body1 * nDim + i];
18018 const MInt body2 = m_gapCells[it].bodyIds[1];
18019 ASSERT(m_gapCells[it].bodyIds[0] == body1,
"");
18020 if(body2 == -1)
continue;
18024 MInt interpolationCells[8] = {0, 0, 0, 0, 0, 0, 0, 0};
18025 this->setUpInterpolationStencil(gridCellId, interpolationCells, m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates,
18026 alwaysTrue,
false);
18028 const MFloat dist1 = interpolateLevelSet(interpolationCells, m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates,
18029 m_bodyToSetTable[body1]);
18031 const MFloat dist2 = interpolateLevelSet(interpolationCells, m_bndryCells->a[bndryId].m_srfcs[0]->m_coordinates,
18032 m_bodyToSetTable[body2]);
18034 for(
MInt i = 0; i < nDim; i++) {
18035 vel1 += m_bodyVelocity[body1 * nDim + i] * m_bodyVelocity[body1 * nDim + i];
18036 vel2 += m_bodyVelocity[body2 * nDim + i] * m_bodyVelocity[body2 * nDim + i];
18039 MInt fixedBody = body1;
18040 MInt movingBody = body2;
18041 MFloat distFixed = dist1;
18044 if(m_gapInitMethod > 0 && vel1 < vel2) {
18046 }
else if(m_gapInitMethod > 0) {
18047 for(
MInt i = 0; i < nDim; i++) {
18048 m_gapCells[it].surfaceVelocity[i] = m_bodyVelocity[body2 * nDim + i];
18055 movingBody = body1;
18059 MFloat F = distFixed / (2.0 * c_cellLengthAtLevel(m_lsCutCellBaseLevel));
18061 if(F > 1.0) F = 1.0;
18064 for(
MInt i = 0; i < nDim; i++) {
18065 m_gapCells[it].surfaceVelocity[i] =
18066 (F * m_bodyVelocity[movingBody * nDim + i] + (1 - F) * m_bodyVelocity[fixedBody * nDim + i]);
18077template <MInt nDim,
class SysEqn>
18079 MInt referenceSet) {
18083 return static_cast<MFloat>(a_levelSetValuesMb(cellId, set));
18087 return static_cast<MFloat>(c_coordinate(cellId,
id));
18090 return this->
template interpolateFieldData<true>(&interpolationCells[0], &point[0], referenceSet, scalarField,
18099template <MInt nDim,
class SysEqn>
18103 applyDirichletCondition();
18104 applyNeumannCondition();
18106#if defined _MB_DEBUG_ || !defined NDEBUG
18107 m_solutionDiverged =
false;
18108 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
18109 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
18110 const MInt cellId = m_fvBndryCnd->m_bndryCell[bndryId].m_cellId;
18111 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
18112 const MInt noSrfcs = m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs;
18113 for(
MInt srfc = 0; srfc < noSrfcs; srfc++) {
18114 for(
MInt v = 0; v < m_noPVars; v++) {
18115 const MFloat val = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[v];
18116 const MFloat val2 = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_normalDeriv[v];
18117 if(std::isnan(val) || std::isinf(val)) {
18118 cerr << setprecision(16) << domainId() <<
": bnd surf var div after BC: " <<
globalTimeStep <<
"/" << m_RKStep
18119 <<
" " << cellId <<
" " << c_globalId(cellId) <<
" "
18120 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume / grid().gridCellVolume(a_level(cellId)) <<
" "
18121 << c_noChildren(cellId) <<
" " << a_isHalo(cellId) <<
" "
18122 << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" "
18123 << m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size() <<
" "
18124 << a_hasProperty(cellId, SolverCell::IsInactive) <<
", " << srfc <<
" " << getPrimitiveVarName(v) <<
" "
18125 << val <<
" " << a_pvariable(cellId, v) << endl;
18126 m_solutionDiverged =
true;
18128 if(std::isnan(val2) || std::isinf(val2)) {
18129 cerr << domainId() <<
": bnd surf grad div after BC: " <<
globalTimeStep <<
"/" << m_RKStep <<
" " << cellId
18130 <<
" " << c_globalId(cellId) <<
" " << m_volumeFraction[bndryId] <<
" " << c_noChildren(cellId) <<
" "
18131 << a_isHalo(cellId) <<
" " << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" "
18132 << m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size() <<
" "
18133 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" / " << srfc <<
" " << getPrimitiveVarName(v) <<
" "
18135 m_solutionDiverged =
true;
18138 if(m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->P] < F0
18139 || m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->RHO] < F0) {
18140 MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
18141 cerr << domainId() <<
": bnd surf var negative after BC: " <<
globalTimeStep <<
"/" << m_RKStep <<
" " << cellId
18142 <<
" " << c_globalId(cellId) <<
" " << m_volumeFraction[bndryId] <<
" " << a_level(cellId) <<
" "
18143 << c_noChildren(cellId) <<
" " << a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" "
18144 << a_isHalo(cellId) <<
" " << a_hasProperty(cellId, SolverCell::IsNotGradient) <<
" "
18145 << m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size() <<
" "
18146 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" / " << srfc <<
" " << a_pvariable(cellId, PV->P)
18147 <<
" " << a_pvariable(cellId, PV->RHO) <<
" / "
18148 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->P] <<
" "
18149 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->RHO] <<
" / "
18150 << a_pvariable(ghostCellId, PV->P) <<
" " << a_pvariable(ghostCellId, PV->RHO) <<
" v "
18151 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[0]] <<
" "
18152 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[1]] <<
" "
18153 << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[2]] <<
" "
18154 << c_coordinate(cellId, 0) <<
" " << c_coordinate(cellId, 1) <<
" " << c_coordinate(cellId, nDim - 1)
18156 m_solutionDiverged =
true;
18160 if(m_solutionDiverged) {
18161 cerr <<
"Solution diverged (BC) at solver " << domainId() <<
" " <<
globalTimeStep <<
" " << m_RKStep << endl;
18163 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
18164 "m_solutionDiverged");
18166 if(m_solutionDiverged) {
18167 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
18169 mTerm(1, AT_,
"Solution diverged after BC handling.");
18179template <MInt nDim,
class SysEqn>
18181 m_fvBndryCnd->updateGhostCellSlopesInviscid();
18189template <MInt nDim,
class SysEqn>
18191 if(m_euler)
return;
18192 m_fvBndryCnd->updateGhostCellSlopesViscous();
18200template <MInt nDim,
class SysEqn>
18204 m_fvBndryCnd->correctBoundarySurfaceVariables();
18208template <MInt nDim,
class SysEqn>
18210 return (!(x <
a) && !(x >
b));
18218template <MInt nDim,
class SysEqn>
18222 const MInt noSrfcs = a_noSurfaces();
18223 MInt nghbrCells[2];
18225 MFloat totalDistance, distance;
18226 MFloat factor0, factor1;
18232 for(srfcId = m_bndrySurfacesOffset; srfcId < noSrfcs; srfcId++) {
18233 nghbrCells[0] = a_surfaceNghbrCellId(srfcId, 0);
18234 nghbrCells[1] = a_surfaceNghbrCellId(srfcId, 1);
18236 totalDistance = F0;
18238 for(
MInt i = 0; i < nDim; i++) {
18239 coords[0][i] = a_coordinate(nghbrCells[0], i);
18240 coords[1][i] = a_coordinate(nghbrCells[1], i);
18243 for(
MInt i = 0; i < nDim; i++) {
18244 distance +=
POW2(a_surfaceCoordinate(srfcId, i) - coords[0][i]);
18245 totalDistance +=
POW2(a_surfaceCoordinate(srfcId, i) - coords[1][i]);
18247 distance = sqrt(distance);
18248 totalDistance = sqrt(totalDistance) + distance;
18249 factor1 = distance /
mMax(eps, totalDistance);
18250 factor0 = F1 - factor1;
18251 a_surfaceFactor(srfcId, 0) = factor0;
18252 a_surfaceFactor(srfcId, 1) = factor1;
18256 for(
MInt bs = 0; bs < m_fvBndryCnd->m_noBoundarySurfaces; bs++) {
18257 srfcId = m_fvBndryCnd->m_boundarySurfaces[bs];
18258 if(a_surfaceBndryCndId(srfcId) != m_movingBndryCndId)
continue;
18260 a_surfaceFactor(srfcId, 0) = F1B2;
18261 a_surfaceFactor(srfcId, 1) = F1B2;
18272template <MInt nDim,
class SysEqn>
18276 const MInt DOFStencil[12] = {1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 2, 2};
18278 const MInt signStencil[3][12] = {{-1, 1, 0, 0, -1, 1, 0, 0, -1, 1, -1, 1},
18279 {0, 0, -1, 1, 0, 0, -1, 1, -1, -1, 1, 1},
18280 {-1, -1, -1, -1, 1, 1, 1, 1, 0, 0, 0, 0}};
18282 const MBool redirect =
true;
18283 if(redirect && !m_constructGField) {
18284 vector<MInt> candidatesOrder;
18286 m_geometryIntersection->computeCutPoints(m_cutCandidates, &m_bndryCandidateIds[0], candidatesOrder);
18289 if(m_geometryIntersection->m_scaledCutCell) {
18290 for(
MInt cnd = 0; cnd < (signed)m_cutCandidates.size(); cnd++) {
18291 const MInt cellId = m_cutCandidates[cnd].cellId;
18292 const MFloat cellLength = c_cellLengthAtLevel(a_cutCellLevel(cellId));
18293 const MFloat cellHalfLength = F1B2 * cellLength;
18296 for(
MInt cpId = 0; cpId < m_cutCandidates[cnd].noCutPoints; cpId++) {
18297 const MInt cutEdge = m_cutCandidates[cnd].cutEdges[cpId];
18299 for(
MInt i = 0; i < nDim; i++) {
18300 MFloat cutCoordinate = m_cutCandidates[cnd].cutPoints[cpId][i];
18301 const MInt sign = signStencil[i][cutEdge];
18304 cutCoordinate = a_coordinate(cellId, i) + cellHalfLength * m_cutCandidates[cnd].cutPoints[cpId][i];
18306 cutCoordinate = a_coordinate(cellId, i) + signStencil[i][cutEdge] * cellHalfLength;
18308 m_cutCandidates[cnd].cutPoints[cpId][i] = cutCoordinate;
18319 for(
MInt i = 0; i < (signed)candidatesOrder.size(); i++) {
18320 const MInt cndt = candidatesOrder[i];
18321 const MInt cellId = m_cutCandidates[cndt].cellId;
18322 ASSERT(m_cutCandidates[cndt].noCutPoints > 0,
"");
18324 if(!a_isBndryCell(cellId)) {
18325 ASSERT(a_bndryId(cellId) == -1, to_string(a_bndryId(cellId)));
18326 bndryId = createBndryCellMb(cellId);
18328 bndryId = a_bndryId(cellId);
18329 ASSERT(bndryId > -1,
"");
18331 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints = m_cutCandidates[cndt].noCutPoints;
18333 for(
MInt noCPs = 0; noCPs < m_cutCandidates[cndt].noCutPoints; noCPs++) {
18334 for(
MInt dim = 0; dim < nDim; dim++) {
18335 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutCoordinates[noCPs][dim] =
18336 m_cutCandidates[cndt].cutPoints[noCPs][dim];
18338 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_bodyId[noCPs] = m_cutCandidates[cndt].cutBodyIds[noCPs];
18339 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutEdge[noCPs] = m_cutCandidates[cndt].cutEdges[noCPs];
18346 const MInt edgesPerDim =
IPOW2(nDim - 1);
18348 const MInt faceStencil[2][12] = {{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 0, 1}, {4, 4, 4, 4, 5, 5, 5, 5, 2, 2, 3, 3}};
18355 const MInt reverseEdgeStencil[3][12] = {{1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10},
18356 {4, 5, 6, 7, 0, 1, 2, 3, 10, 11, 8, 9},
18357 {5, 4, 7, 6, 1, 0, 3, 2, 11, 10, 9, 8}};
18362 const MInt nodeStencil[2][12] = {{0, 1, 0, 2, 4, 5, 4, 6, 0, 1, 2, 3}, {2, 3, 1, 3, 6, 7, 5, 7, 4, 5, 6, 7}};
18365 const MBool multiCutCell =
false;
18366 const MFloat eps = multiCutCell ? 10 * m_eps : m_eps;
18367 MInt errorFlag = 0;
18370 ASSERT(m_noBndryCandidates == (
signed)m_bndryCandidates.size(),
"");
18372 edgeChecked.
fill(
false);
18374 for(
MInt i = 0; i < m_noBndryCandidates; i++) {
18375 for(
MInt e = 0; e < m_noEdges; e++) {
18376 edgeChecked.
p[i * m_noEdges + e] =
false;
18379 MIntScratchSpace noCutPointsOnEdge(m_fvBndryCnd->m_maxNoBndryCells, m_noEdges, AT_,
"noCutPointsOnEdge");
18380 noCutPointsOnEdge.
fill(0);
18382 for(
MInt i = 0; i < m_fvBndryCnd->m_maxNoBndryCells; i++)
18383 for(
MInt e = 0; e < m_noEdges; e++)
18384 noCutPointsOnEdge(i, e) = 0;
18388 for(
MInt cndt = 0; cndt < m_noBndryCandidates; cndt++) {
18389 MInt cellId = m_bndryCandidates[cndt];
18391 const MFloat cellLength = c_cellLengthAtLevel(a_cutCellLevel(cellId));
18392 const MFloat cellHalfLength = F1B2 * cellLength;
18395 for(
MInt edge = 0; edge < m_noEdges; edge++) {
18396 if(edgeChecked.
p[cndt * m_noEdges + edge])
continue;
18399 face[0] = faceStencil[0][edge];
18400 IF_CONSTEXPR(nDim == 3) {
18401 face[1] = faceStencil[1][edge];
18403 MInt edgeDOF = DOFStencil[edge];
18405 MInt directNeighbourIds[4]{-1, -1, -1, -1};
18407 directNeighbourIds[0] = cellId;
18408 directNeighbourIds[1] = -1;
18409 if(a_hasNeighbor(cellId, face[0]) > 0) directNeighbourIds[1] = c_neighborId(cellId, face[0]);
18411 MInt reverseEdge[4] = {0, 0, 0, 0};
18412 reverseEdge[0] = edge;
18413 reverseEdge[1] = reverseEdgeStencil[0][edge];
18414 IF_CONSTEXPR(nDim == 3) {
18415 directNeighbourIds[2] = -1;
18416 if(a_hasNeighbor(cellId, face[1]) > 0) {
18417 directNeighbourIds[2] = c_neighborId(cellId, face[1]);
18419 directNeighbourIds[3] = -1;
18420 if(a_hasNeighbor(cellId, face[0]) > 0) {
18421 if(a_hasNeighbor(c_neighborId(cellId, face[0]), face[1]) > 0) {
18422 directNeighbourIds[3] = c_neighborId(c_neighborId(cellId, face[0]), face[1]);
18425 if(directNeighbourIds[3] < 0) {
18426 if(a_hasNeighbor(cellId, face[1]) > 0) {
18427 if(a_hasNeighbor(c_neighborId(cellId, face[1]), face[0]) > 0) {
18428 directNeighbourIds[3] = c_neighborId(c_neighborId(cellId, face[1]), face[0]);
18432 reverseEdge[2] = reverseEdgeStencil[1][edge];
18433 reverseEdge[3] = reverseEdgeStencil[2][edge];
18439 MBool isGapCell =
false;
18440 if(m_levelSet && m_closeGaps) {
18441 isGapCell = (a_hasProperty(cellId, SolverCell::IsGapCell));
18443 if(m_complexBoundary && m_noLevelSetsUsedForMb > 1 && (!isGapCell)) {
18445 endSet = m_noLevelSetsUsedForMb;
18446 }
else if(m_complexBoundary && m_noLevelSetsUsedForMb > 1 && (isGapCell)) {
18452 for(
MInt set = startSet; set < endSet; set++) {
18454 phi[0] = m_candidateNodeValues[IDX_LSSETNODES(cndt, nodeStencil[0][edge], set)];
18455 phi[1] = m_candidateNodeValues[IDX_LSSETNODES(cndt, nodeStencil[1][edge], set)];
18456 if(!m_candidateNodeSet[cndt * m_noCellNodes + nodeStencil[0][edge]])
18457 cerr << domainId() <<
": warning node value 0 not set at " <<
globalTimeStep <<
", " << cellId <<
" " << cndt
18458 <<
" " << edge <<
" " << nodeStencil[0][edge] <<
" " << set <<
" " << a_isHalo(cellId) << endl;
18459 if(!m_candidateNodeSet[cndt * m_noCellNodes + nodeStencil[1][edge]])
18460 cerr << domainId() <<
": warning node value 1 not set at " <<
globalTimeStep <<
", " << cellId <<
" " << cndt
18461 <<
" " << edge <<
" " << nodeStencil[1][edge] <<
" " << set <<
" " << a_isHalo(cellId) << endl;
18464 if(fabs(phi[0]) < eps) {
18470 if(fabs(phi[1]) < eps) {
18482 if(
approx(fabs(phi[0]), cellHalfLength, eps)) {
18484 phi[0] = cellHalfLength - eps;
18486 phi[0] = -cellHalfLength + eps;
18488 if(
approx(fabs(phi[1]), cellHalfLength, eps)) {
18490 phi[1] = cellHalfLength - eps;
18492 phi[1] = -cellHalfLength + eps;
18497 if(phi[0] * phi[1] < 0) {
18500 MFloat deltaCutpoint = cellHalfLength * (phi[0] + phi[1]) / (phi[0] - phi[1]);
18501 ASSERT((phi[0] + phi[1]) / (phi[0] - phi[1]) < 1 && (phi[0] + phi[1]) / (phi[0] - phi[1]) > -1,
"");
18502 for(
MInt dim = 0; dim < nDim; dim++) {
18503 if(dim == edgeDOF)
continue;
18504 cutpoint[dim] = a_coordinate(cellId, dim) + signStencil[dim][edge] * cellHalfLength;
18506 cutpoint[edgeDOF] = a_coordinate(cellId, edgeDOF) + deltaCutpoint;
18509 for(
MInt nb = 0; nb < edgesPerDim; nb++) {
18510 MInt nbCell = directNeighbourIds[nb];
18511 if(nbCell < 0)
continue;
18512 if(m_bndryCandidateIds[nbCell] < 0) {
18516 if(edgeChecked.
p[m_bndryCandidateIds[nbCell] * m_noEdges + reverseEdge[nb]]) {
18517 cerr <<
"Strange behaviour! " << endl;
18521 MInt nbBndryCell = -1;
18522 if(!a_isBndryCell(nbCell)) {
18523 if(a_bndryId(nbCell) != -1) {
18524 cerr << domainId() <<
"Missing boundary cell: " << cellId <<
" " << nbCell <<
" " << a_level(cellId)
18525 <<
" " << a_level(nbCell) <<
" " << c_neighborId(cellId, face[0]) <<
" " << face[0] <<
" "
18526 << a_isHalo(cellId) <<
" " << a_isHalo(nbCell) << endl;
18528 ASSERT(a_bndryId(nbCell) == -1, to_string(a_bndryId(nbCell)));
18529 nbBndryCell = createBndryCellMb(nbCell);
18531 nbBndryCell = a_bndryId(nbCell);
18532 if(nbBndryCell < 0) {
18539 MInt noCPs = m_fvBndryCnd->m_bndryCells->a[nbBndryCell].m_srfcs[0]->m_noCutPoints;
18540 if(noCPs == 2 * m_noEdges) {
18541 mTerm(1, AT_,
"Error: Too many cut points, can't store more... Please check!");
18543 if(noCutPointsOnEdge(nbBndryCell, reverseEdge[nb]) == 2) {
18544 mTerm(1, AT_,
"Error: Already two cut points on edge, can't store more... Please check!");
18547 ASSERT(a_associatedBodyIds(cellId, set) > -1
18548 && a_associatedBodyIds(cellId, set) < m_noEmbeddedBodies + m_noPeriodicGhostBodies,
18551 if(set >= m_startSet && a_associatedBodyIds(cellId, set) != a_associatedBodyIds(nbCell, set)) {
18552 cerr << domainId() <<
": warning associated body mismatch! " <<
globalTimeStep <<
" " << set <<
" "
18553 << isGapCell <<
", " << c_globalId(cellId) <<
" " << c_globalId(nbCell) <<
", "
18554 << a_isPeriodic(cellId) <<
" " << a_isPeriodic(nbCell) <<
"/ " << a_associatedBodyIds(cellId, set)
18555 <<
" " << a_associatedBodyIds(nbCell, set) <<
", " << a_associatedBodyIds(cellId, 0) <<
" "
18556 << a_associatedBodyIds(nbCell, 0) <<
"/ " << a_levelSetValuesMb(cellId, set) <<
" "
18557 << a_levelSetValuesMb(nbCell, set) <<
", " << a_levelSetValuesMb(cellId, 0) <<
" "
18558 << a_levelSetValuesMb(nbCell, 0) <<
"/ " << a_hasProperty(cellId, Cell::IsHalo) <<
" "
18559 << a_hasProperty(nbCell, Cell::IsHalo) <<
", " << a_hasProperty(cellId, SolverCell::IsGapCell) <<
" "
18560 << a_hasProperty(nbCell, SolverCell::IsGapCell) << endl;
18561 directNeighbourIds[nb] = -1;
18565 for(
MInt dim = 0; dim < nDim; dim++)
18566 m_fvBndryCnd->m_bndryCells->a[nbBndryCell].m_srfcs[0]->m_cutCoordinates[noCPs][dim] = cutpoint[dim];
18568 m_fvBndryCnd->m_bndryCells->a[nbBndryCell].m_srfcs[0]->m_bodyId[noCPs] = a_associatedBodyIds(nbCell, set);
18569 m_fvBndryCnd->m_bndryCells->a[nbBndryCell].m_srfcs[0]->m_cutEdge[noCPs] = reverseEdge[nb];
18570 m_fvBndryCnd->m_bndryCells->a[nbBndryCell].m_srfcs[0]->m_noCutPoints++;
18571 noCutPointsOnEdge(nbBndryCell, reverseEdge[nb])++;
18577 for(
MInt nb = 0; nb < edgesPerDim; nb++) {
18578 if(directNeighbourIds[nb] < 0)
continue;
18579 MInt nbCndt = m_bndryCandidateIds[directNeighbourIds[nb]];
18580 if(nbCndt < 0)
continue;
18581 edgeChecked.
p[nbCndt * m_noEdges + reverseEdge[nb]] =
true;
18651 MPI_Allreduce(MPI_IN_PLACE, &errorFlag, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"errorFlag");
18654 writeVtkDebug(
"error" + getIdentifier(
false,
"_",
"_"));
18655 mTerm(1, AT_,
"Critical error in computeCutPointsMb_MGC! Quit.");
18665template <MInt nDim,
class SysEqn>
18669 MFloat* RESTRICT RHS = (
MFloat*)(&(a_rightHandSide(0, 0)));
18670 fill(RHS, RHS + (a_noCells() * m_noFVars), F0);
18676template <MInt nDim,
class SysEqn>
18680#ifdef VISCOUS_FLUX_FREEZING
18681 MFloat* RESTRICT RHS = (
MFloat*)(&(a_rightHandSide(0, 0)));
18682 MFloat* RESTRICT RHSV = (
MFloat*)(&(m_rhsViscous[0][0]));
18683 MFloat* RESTRICT flux = (
MFloat*)(&(a_surfaceFlux(0, 0)));
18684 const MInt xdim = m_noSurfaces;
18685 const MInt ydim = m_noFVars;
18686 const MInt size0 = m_noSurfaces * m_noFVars *
sizeof(
MFloat);
18687 const MInt size1 = a_noCells() * m_noFVars *
sizeof(
MFloat);
18689 for(
MInt srfcId = xdim; srfcId--;) {
18690 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 0] += flux[srfcId * ydim + 0];
18691 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 0] -= flux[srfcId * ydim + 0];
18692 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 1] += flux[srfcId * ydim + 1];
18693 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 1] -= flux[srfcId * ydim + 1];
18694 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 2] += flux[srfcId * ydim + 2];
18695 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 2] -= flux[srfcId * ydim + 2];
18696 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 3] += flux[srfcId * ydim + 3];
18697 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 3] -= flux[srfcId * ydim + 3];
18698 IF_CONSTEXPR(nDim == 3) {
18699 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4] += flux[srfcId * ydim + 4];
18700 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4] -= flux[srfcId * ydim + 4];
18701 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
18702 for(
MInt r = 0; r < m_noRansEquations; r++) {
18703 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 5 + r] += flux[srfcId * ydim + 5 + r];
18704 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 5 + r] -= flux[srfcId * ydim + 5 + r];
18707 for(
MUint s = 0; s < noSpecies; ++s) {
18708 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 5 + m_noRansEquations + s] +=
18709 flux[srfcId * ydim + 5 + m_noRansEquations + s];
18710 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 5 + m_noRansEquations + s] -=
18711 flux[srfcId * ydim + 5 + m_noRansEquations + s];
18715 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
18716 for(
MInt r = 0; r < m_noRansEquations; r++) {
18717 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4 + r] += flux[srfcId * ydim + 4 + r];
18718 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4 + r] -= flux[srfcId * ydim + 4 + r];
18721 for(
MUint s = 0; s < noSpecies; ++s) {
18722 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4 + m_noRansEquations + s] +=
18723 flux[srfcId * ydim + 4 + m_noRansEquations + s] RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4
18724 + m_noRansEquations + s] -=
18725 flux[srfcId * ydim + 4 + m_noRansEquations + s];
18730 if(m_RKStep == 1) {
18731 memset(flux, 0, size0);
18732 memset(RHSV, 0, size1);
18733 (this->*computeViscousFlux)();
18735 for(
MInt srfcId = xdim; srfcId--;) {
18736 RHSV[a_surfaceNghbrCellId(srfcId, 0) * ydim + 0] += flux[srfcId * ydim + 0];
18737 RHSV[a_surfaceNghbrCellId(srfcId, 1) * ydim + 0] -= flux[srfcId * ydim + 0];
18738 RHSV[a_surfaceNghbrCellId(srfcId, 0) * ydim + 1] += flux[srfcId * ydim + 1];
18739 RHSV[a_surfaceNghbrCellId(srfcId, 1) * ydim + 1] -= flux[srfcId * ydim + 1];
18740 RHSV[a_surfaceNghbrCellId(srfcId, 0) * ydim + 2] += flux[srfcId * ydim + 2];
18741 RHSV[a_surfaceNghbrCellId(srfcId, 1) * ydim + 2] -= flux[srfcId * ydim + 2];
18742 RHSV[a_surfaceNghbrCellId(srfcId, 0) * ydim + 3] += flux[srfcId * ydim + 3];
18743 RHSV[a_surfaceNghbrCellId(srfcId, 1) * ydim + 3] -= flux[srfcId * ydim + 3];
18744 IF_CONSTEXPR(nDim == 3) {
18745 RHSV[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4] += flux[srfcId * ydim + 4];
18746 RHSV[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4] -= flux[srfcId * ydim + 4];
18751 Base::viscousFlux();
18760template <MInt nDim,
class SysEqn>
18764 MFloat* RESTRICT RHS = (
MFloat*)(&(a_rightHandSide(0, 0)));
18765 MFloat* RESTRICT flux = (
MFloat*)(&(a_surfaceFlux(0, 0)));
18766 const MInt xdim = m_noSurfaces;
18767 const MInt ydim = m_noFVars;
18769#ifdef VISCOUS_FLUX_FREEZING
18770 MFloat* RESTRICT RHSV = (
MFloat*)(&(m_rhsViscous[0][0]));
18771 const MInt xdim0 = a_noCells();
18773 for(
MInt i = xdim0; i--;) {
18774 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
18775 RHS[ydim * i + 0] += RHSV[ydim * i + 0];
18776 RHS[ydim * i + 1] += RHSV[ydim * i + 1];
18777 RHS[ydim * i + 2] += RHSV[ydim * i + 2];
18778 RHS[ydim * i + 3] += RHSV[ydim * i + 3];
18779 IF_CONSTEXPR(nDim == 3) {
18780 RHS[ydim * i + 4] += RHSV[ydim * i + 4];
18781 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
18782 for(
MInt r = 0; r < m_noRansEquations; ++r) {
18783 RHS[ydim * i + 5 + r] += RHSV[ydim * i + 5 + r];
18786 for(
MInt s = 0; s < m_noSpecies; s++)
18787 RHS[ydim * i + 5 + s + m_noRansEquations] += RHSV[ydim * i + 5 + m_noRansEquations];
18790 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
18791 for(
MInt r = 0; r < m_noRansEquations; ++r) {
18792 RHS[ydim * i + 4 + r] += RHSV[ydim * i + 4 + r];
18795 for(
MInt s = 0; s < m_noSpecies; s++)
18796 RHS[ydim * i + 4 + s + m_noRansEquations] += RHSV[ydim * i + 4 + m_noRansEquations];
18804 const MInt blk = -1;
18806 const MInt gId = -1;
18807 const MInt varId = CV->RHO;
18808 const MInt pvarId = PV->RHO;
18809 MFloat area_check[3] = {F0, F0, F0};
18810 MFloat flux_check[3] = {F0, F0, F0};
18812 for(
MInt srfcId = xdim; srfcId--;) {
18814 if((blk > -1 && domainId() == blk && a_surfaceNghbrCellId(srfcId, 0) == cll)
18815 || (gId > -1 && c_globalId(a_surfaceNghbrCellId(srfcId, 0)) == gId
18816 && !a_isHalo(a_surfaceNghbrCellId(srfcId, 0)))) {
18817 if(gId > -1) cll = a_surfaceNghbrCellId(srfcId, 0);
18818 MInt n0 = a_surfaceNghbrCellId(srfcId, 0);
18819 MInt n1 = a_surfaceNghbrCellId(srfcId, 1);
18820 cerr << domainId() <<
": flux " <<
globalTimeStep <<
" " << m_RKStep <<
" " << srfcId <<
" "
18821 << flux[srfcId * ydim + varId] <<
" " << a_rightHandSide(cll, varId)
18822 <<
" /srf " << a_surfaceArea(srfcId) <<
" " << a_surfaceOrientation(srfcId) <<
" "
18823 << a_surfaceBndryCndId(srfcId) <<
" /ict "
18824 << a_hasProperty(a_surfaceNghbrCellId(srfcId, 0), SolverCell::IsInactive) <<
" "
18825 << a_hasProperty(a_surfaceNghbrCellId(srfcId, 1), SolverCell::IsInactive) <<
" /vol "
18826 << a_cellVolume(n0) / grid().gridCellVolume(a_level(n0)) <<
" "
18827 << a_cellVolume(n1) / grid().gridCellVolume(a_level(n1)) <<
" /vol0 " << a_cellVolume(n0) * a_FcellVolume(n0)
18828 <<
" " << a_cellVolume(n1) * a_FcellVolume(n1) <<
" /vol1 " << m_cellVolumesDt1[n0] * a_FcellVolume(n0)
18829 <<
" " << m_cellVolumesDt1[n1] * a_FcellVolume(n1) <<
" /ngb " << a_surfaceNghbrCellId(srfcId, 0) <<
" "
18830 << a_surfaceNghbrCellId(srfcId, 1) <<
" /ngbg " << c_globalId(a_surfaceNghbrCellId(srfcId, 0)) <<
" "
18831 << c_globalId(a_surfaceNghbrCellId(srfcId, 1)) <<
" /var "
18832 << a_variable(a_surfaceNghbrCellId(srfcId, 0), pvarId) <<
" "
18833 << a_variable(a_surfaceNghbrCellId(srfcId, 1), pvarId) << endl;
18834 area_check[a_surfaceOrientation(srfcId)] += a_surfaceArea(srfcId);
18835 flux_check[a_surfaceOrientation(srfcId)] += flux[srfcId * ydim + varId];
18837 if((blk > -1 && domainId() == blk && a_surfaceNghbrCellId(srfcId, 1) == cll)
18838 || (gId > -1 && c_globalId(a_surfaceNghbrCellId(srfcId, 1)) == gId
18839 && !a_isHalo(a_surfaceNghbrCellId(srfcId, 1)))) {
18840 if(gId > -1) cll = a_surfaceNghbrCellId(srfcId, 1);
18841 MInt n0 = a_surfaceNghbrCellId(srfcId, 0);
18842 MInt n1 = a_surfaceNghbrCellId(srfcId, 1);
18843 cerr << domainId() <<
": flux " <<
globalTimeStep <<
" " << m_RKStep <<
" " << srfcId <<
" "
18844 << -flux[srfcId * ydim + varId] <<
" "
18845 << a_rightHandSide(cll, varId) <<
" /srf " << a_surfaceArea(srfcId) <<
" " << a_surfaceOrientation(srfcId)
18846 <<
" " << a_surfaceBndryCndId(srfcId) <<
" /ict "
18847 << a_hasProperty(a_surfaceNghbrCellId(srfcId, 0), SolverCell::IsInactive) <<
" "
18848 << a_hasProperty(a_surfaceNghbrCellId(srfcId, 1), SolverCell::IsInactive) <<
" /vol "
18849 << a_cellVolume(n0) / grid().gridCellVolume(a_level(n0)) <<
" "
18850 << a_cellVolume(n1) / grid().gridCellVolume(a_level(n1)) <<
" /vol0 " << a_cellVolume(n0) * a_FcellVolume(n0)
18851 <<
" " << a_cellVolume(n1) * a_FcellVolume(n1) <<
" /vol1 " << m_cellVolumesDt1[n0] * a_FcellVolume(n0)
18852 <<
" " << m_cellVolumesDt1[n1] * a_FcellVolume(n1) <<
" /ngb " << a_surfaceNghbrCellId(srfcId, 0) <<
" "
18853 << a_surfaceNghbrCellId(srfcId, 1) <<
" /var " << a_variable(a_surfaceNghbrCellId(srfcId, 0), pvarId) <<
" "
18854 << a_variable(a_surfaceNghbrCellId(srfcId, 1), pvarId);
18855 if(!a_isBndryGhostCell(a_surfaceNghbrCellId(srfcId, 0))) {
18856 cerr <<
" /ngbg " << c_globalId(a_surfaceNghbrCellId(srfcId, 0)) <<
" "
18857 << c_globalId(a_surfaceNghbrCellId(srfcId, 1));
18860 area_check[a_surfaceOrientation(srfcId)] -= a_surfaceArea(srfcId);
18861 flux_check[a_surfaceOrientation(srfcId)] -= flux[srfcId * ydim + varId];
18865 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim] += flux[srfcId * ydim];
18866 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim] -= flux[srfcId * ydim];
18867 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 1] += flux[srfcId * ydim + 1];
18868 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 1] -= flux[srfcId * ydim + 1];
18869 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 2] += flux[srfcId * ydim + 2];
18870 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 2] -= flux[srfcId * ydim + 2];
18871 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 3] += flux[srfcId * ydim + 3];
18872 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 3] -= flux[srfcId * ydim + 3];
18873 IF_CONSTEXPR(nDim == 3) {
18874 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4] += flux[srfcId * ydim + 4];
18875 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4] -= flux[srfcId * ydim + 4];
18876 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
18877 for(
MInt r = 0; r < m_noRansEquations; ++r) {
18878 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 5 + r] += flux[srfcId * ydim + 5 + r];
18879 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 5 + r] -= flux[srfcId * ydim + 5 + r];
18882 for(
MInt s = 0; s < m_noSpecies; s++) {
18883 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 5 + s + m_noRansEquations] +=
18884 flux[srfcId * ydim + 5 + s + m_noRansEquations];
18885 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 5 + s + m_noRansEquations] -=
18886 flux[srfcId * ydim + 5 + s + m_noRansEquations];
18890 IF_CONSTEXPR(SysEqn::m_noRansEquations > 0) {
18891 for(
MInt r = 0; r < m_noRansEquations; ++r) {
18892 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4 + r] += flux[srfcId * ydim + 4 + r];
18893 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4 + r] -= flux[srfcId * ydim + 4 + r];
18896 for(
MInt s = 0; s < m_noSpecies; s++) {
18897 RHS[a_surfaceNghbrCellId(srfcId, 0) * ydim + 4 + s + m_noRansEquations] +=
18898 flux[srfcId * ydim + 4 + s + m_noRansEquations];
18899 RHS[a_surfaceNghbrCellId(srfcId, 1) * ydim + 4 + s + m_noRansEquations] -=
18900 flux[srfcId * ydim + 4 + s + m_noRansEquations];
18906 for(
MInt v = 0; v < m_noFVars; v++) {
18907 if(std::isnan(flux[srfcId * ydim + v])) {
18908 cerr << domainId() <<
": flux is nan " <<
globalTimeStep <<
" " << m_RKStep <<
" " << srfcId <<
" "
18909 << getPrimitiveVarName(v) <<
" /n " << a_surfaceNghbrCellId(srfcId, 0) <<
" "
18910 << a_surfaceNghbrCellId(srfcId, 1) <<
" /v " << a_pvariable(a_surfaceNghbrCellId(srfcId, 0), v) <<
" "
18911 << a_pvariable(a_surfaceNghbrCellId(srfcId, 1), v) <<
" /b " << a_bndryId(a_surfaceNghbrCellId(srfcId, 0))
18912 <<
" " << a_bndryId(a_surfaceNghbrCellId(srfcId, 1)) <<
" /p " << a_isHalo(a_surfaceNghbrCellId(srfcId, 0))
18913 <<
" " << a_isHalo(a_surfaceNghbrCellId(srfcId, 1)) <<
" " << a_isWindow(a_surfaceNghbrCellId(srfcId, 0))
18914 <<
" " << a_isWindow(a_surfaceNghbrCellId(srfcId, 1)) <<
" /s "
18915 << a_slope(a_surfaceNghbrCellId(srfcId, 0), v, 0) <<
" " << a_slope(a_surfaceNghbrCellId(srfcId, 0), v, 1)
18916 <<
" " << a_slope(a_surfaceNghbrCellId(srfcId, 1), v, 0) <<
" "
18917 << a_slope(a_surfaceNghbrCellId(srfcId, 1), v, 1) << endl;
18925 if((gId > -1 && cll > -1) && (blk > -1 && domainId() == blk)) {
18926 if(!a_hasProperty(cll, SolverCell::IsInactive)) {
18927 MInt bcll = a_bndryId(cll);
18928 cerr << domainId() <<
": area check " << cll <<
": " << area_check[0] <<
" " << area_check[1] <<
" "
18929 << area_check[2] <<
" / " << a_rightHandSide(cll, varId) <<
" /vols "
18930 << a_cellVolume(cll) / grid().gridCellVolume(a_level(cll)) <<
" "
18931 << m_cellVolumesDt1[cll] / grid().gridCellVolume(a_level(cll)) <<
" "
18932 << ((bcll > -1) ? m_fvBndryCnd->m_bndryCells->a[bcll].m_volume / grid().gridCellVolume(a_level(cll)) : -1)
18933 <<
" / " << a_isHalo(cll) << endl;
18934 cerr << domainId() <<
": flux check " << cll <<
": " << flux_check[0] <<
" " << flux_check[1] <<
" "
18935 << flux_check[2] <<
" / " << a_variable(cll, pvarId) <<
" "
18936 << a_variable(cll, pvarId) / a_variable(cll, CV->RHO) << endl;
18937 cerr << domainId() <<
": rhs " << cll <<
" ";
18938 for(
MInt v = 0; v < m_noFVars; v++) {
18939 cerr << a_rightHandSide(cll, v) <<
" ";
18942 for(
MInt v = 0; v < m_noCVars; v++) {
18943 cerr << a_oldVariable(cll, v) <<
" ";
18946 for(
MInt v = 0; v < m_noFVars; v++) {
18947 cerr << timeStep() * a_FcellVolume(cll) * a_rightHandSide(cll, v) <<
" ";
18950 for(
MInt v = 0; v < m_noCVars; v++) {
18951 cerr << a_FcellVolume(cll)
18952 * (m_cellVolumesDt1[cll] * a_oldVariable(cll, v) - timeStep() * a_rightHandSide(cll, v))
18960 if(m_pointParticleTwoWayCoupling && m_noPointParticles > 0) {
18962 for(
MInt dim = 0; dim < nDim; dim++) {
18963 m_coupling[
cellId][dim] = F0;
18966 const MInt noCouplingLayers = 2;
18967 const MInt maxNoNghbrs = 150;
18971 nghbrList.fill(-1);
18972 m_couplingRate = F0;
18973 for(
MInt i = 0; i < noNeighborDomains(); i++) {
18974 for(
MInt j = 0; j < m_noMaxLevelHaloCells[i]; j++) {
18976 for(
MInt v = 0; v < m_noFVars; v++) {
18977 a_rightHandSide(cellId, v) = F0;
18982 for(
MUint p = 0;
p < m_particleCellLink.size();
p++) {
18984 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) cerr <<
"Warning: not a leaf cell!" << endl;
18985 const MFloat mass = F4B3 * PI * m_particleRadii[3 *
p] * m_particleRadii[3 *
p + 1] * m_particleRadii[3 *
p + 2]
18986 * m_densityRatio * m_rhoInfinity;
18988 F2 * pow(m_particleRadii[3 * p] * m_particleRadii[3 * p + 1] * m_particleRadii[3 * p + 2], F1B3);
18989 const MFloat T = sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
18990 const MFloat mue = SUTHERLANDLAW(T);
18991 const MFloat FAC = 18.0 * mue / (sysEqn().m_Re0 * m_densityRatio * m_rhoInfinity *
POW2(diameter));
18992 const MInt counter =
18993 (noCouplingLayers > 0)
18994 ? 1 + this->
template getAdjacentLeafCells<2>(cellId, noCouplingLayers, nghbrList, layerId)
18998 m_particleHeatFlux[
p] * 1 / m_gamma * 1 / (m_gamma - 1) * mass * m_capacityConstantVolumeRatio;
19000 if(noCouplingLayers > 0) nghbrList[counter - 1] = nghbrList[0];
19003 for(
MInt c = 0; c < counter; c++) {
19005 MInt nghbrId = nghbrList(c);
19006 for(
MInt i = 0; i < nDim; i++) {
19007 dx +=
POW2(a_coordinate(nghbrId, i) - m_particleCoords[nDim * p + i]);
19009 weights(c) = exp(-expFac * dx /
POW2(c_cellLengthAtLevel(a_level(cellId))));
19012 for(
MInt c = 0; c < counter; c++) {
19015 for(
MInt c = 0; c < counter; c++) {
19016 MInt nghbrId = nghbrList(c);
19017 for(
MInt i = 0; i < nDim; i++) {
19018 MFloat acc = m_particleAcceleration[nDim *
p + i] - FAC * m_particleTerminalVelocity[i];
19019 a_rightHandSide(nghbrId, CV->RHO_VV[i]) += weights(c) * mass * acc;
19020 a_rightHandSide(nghbrId, CV->RHO_E) += weights(c) * a_pvariable(nghbrId, PV->VV[i]) * mass * acc;
19021 m_couplingRate -= weights(c) * mass * acc * a_pvariable(nghbrId, PV->VV[i]);
19022 m_coupling[nghbrId][i] -= weights(c) * mass * acc;
19024 a_rightHandSide(nghbrId, CV->RHO_E) += weights(c) * heatFlux;
19027 MPI_Allreduce(MPI_IN_PLACE, &m_couplingRate, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
19029 MIntScratchSpace haloBufferOffsets(noNeighborDomains() + 1, AT_,
"haloBufferOffsets");
19030 MIntScratchSpace windowBufferOffsets(noNeighborDomains() + 1, AT_,
"windowBufferOffsets");
19032 haloBufferOffsets.fill(0);
19033 windowBufferOffsets.fill(0);
19034 for(
MInt i = 0; i < noNeighborDomains(); i++) {
19035 haloBufferOffsets(i + 1) = haloBufferOffsets(i) + m_noFVars * m_noMaxLevelHaloCells[i];
19036 windowBufferOffsets(i + 1) = windowBufferOffsets(i) + m_noFVars * m_noMaxLevelWindowCells[i];
19038 MFloatScratchSpace haloBuffer(haloBufferOffsets(noNeighborDomains()), AT_,
"haloBuffer");
19039 MFloatScratchSpace windowBuffer(windowBufferOffsets(noNeighborDomains()), AT_,
"windowBuffer");
19040 haloBuffer.fill(F0);
19041 for(
MInt i = 0; i < noNeighborDomains(); i++) {
19042 for(
MInt j = 0; j < m_noMaxLevelHaloCells[i]; j++) {
19044 for(
MInt v = 0; v < m_noFVars; v++) {
19045 haloBuffer(haloBufferOffsets(i) + m_noFVars * j + v) += a_rightHandSide(cellId, v);
19049 sendReq.fill(MPI_REQUEST_NULL);
19050 for(
MInt i = 0; i < noNeighborDomains(); i++) {
19051 MPI_Issend(&haloBuffer[haloBufferOffsets(i)], m_noFVars * m_noMaxLevelHaloCells[i], MPI_DOUBLE, neighborDomain(i),
19052 81, mpiComm(), &sendReq[i], AT_,
"haloBuffer[haloBufferOffsets(i)]");
19054 for(
MInt i = 0; i < noNeighborDomains(); i++) {
19055 MPI_Recv(&windowBuffer[windowBufferOffsets(i)], m_noFVars * m_noMaxLevelWindowCells[i], MPI_DOUBLE,
19056 neighborDomain(i), 81, mpiComm(), MPI_STATUS_IGNORE, AT_,
"windowBuffer[windowBufferOffsets(i)]");
19058 MPI_Waitall(noNeighborDomains(), &sendReq[0], MPI_STATUSES_IGNORE, AT_);
19059 for(
MInt i = 0; i < noNeighborDomains(); i++) {
19060 for(
MInt j = 0; j < m_noMaxLevelWindowCells[i]; j++) {
19062 for(
MInt v = 0; v < m_noFVars; v++) {
19063 a_rightHandSide(cellId, v) += windowBuffer(windowBufferOffsets(i) + m_noFVars * j + v);
19065 for(
MInt v = 0; v < nDim; v++) {
19066 m_coupling[
cellId][v] -= windowBuffer(windowBufferOffsets(i) + m_noFVars * j + CV->RHO_VV[v]);
19074 m_solutionDiverged =
false;
19075 for(
MInt i = a_noCells(); i--;) {
19076 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
19077 if(!a_hasProperty(i, SolverCell::IsOnCurrentMGLevel))
continue;
19078 if(a_isHalo(i))
continue;
19079 if(a_isBndryGhostCell(i))
continue;
19080 for(
MInt v = 0; v < m_noFVars; v++) {
19081 if(!(a_rightHandSide(i, v) >= F0 || a_rightHandSide(i, v) < F0) || std::isnan(a_rightHandSide(i, v))) {
19082 cerr <<
"RHS0 " << i <<
" " << a_bndryId(i) <<
" " << v <<
" " << a_rightHandSide(i, v) <<
" "
19083 <<
"cells[i].b_properties.to_string()" << endl;
19084 m_solutionDiverged =
true;
19088 if(m_solutionDiverged) {
19089 cerr <<
"Solution diverged (RHS0) at solver " << domainId() <<
" " <<
globalTimeStep <<
" " << m_RKStep << endl;
19092 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
19093 "m_solutionDiverged");
19094 if(m_solutionDiverged) {
19095 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
19097 mTerm(1, AT_,
"Solution diverged after RHS0 handling.");
19101 if(m_initialCondition == 452) {
19102 computeVolumeForces();
19111template <MInt nDim,
class SysEqn>
19121template <MInt nDim,
class SysEqn>
19123 return (this->*execRungeKuttaStep)();
19135template <MInt nDim,
class SysEqn>
19138 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
19139 if(!a_isHalo(cellId) && c_isLeafCell(cellId)) noCells++;
19145 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noCells");
19148 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_LONG, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"noCells");
19151 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_LONG, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"noCells");
19154 MPI_Allreduce(MPI_IN_PLACE, &noCells, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noCells");
19158 mTerm(1, AT_,
"Unknown case.");
19175template <MInt nDim,
class SysEqn>
19183 if(mode == 0 && (!m_trackMovingBndry || globalTimeStep < m_trackMbStart || globalTimeStep > m_trackMbEnd)) {
19190 for(
MInt i = 0; i < nDim; i++) {
19191 bbox[i] = std::numeric_limits<MFloat>::max();
19192 bbox[nDim + i] = -std::numeric_limits<MFloat>::max();
19195 const MInt oldRKStep[5] = {4, 0, 1, 2, 3};
19202 const MInt size = a_noCells();
19203 for(
MInt cellId = size; cellId--;) {
19204 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
19205 if(a_isBndryGhostCell(cellId))
continue;
19206 if(a_isHalo(cellId))
continue;
19207 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
19208 if(a_bndryId(cellId) == -2)
continue;
19210 if(fabs(a_rightHandSide(cellId, CV->RHO)) > maxR) {
19211 maxR = fabs(a_rightHandSide(cellId, CV->RHO));
19215 if((!(a_rightHandSide(cellId, CV->RHO) >= F0 || a_rightHandSide(cellId, CV->RHO) < F0))) {
19216 m_log <<
"RHS[rho] is " << a_rightHandSide(cellId, CV->RHO) <<
" in cell " << cellId <<
"(" << a_bndryId(cellId)
19219 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << a_levelSetValuesMb(cellId, 0)
19220 <<
" vol:" << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) <<
" / ";
19221 for(
MInt i = 0; i < nDim; i++)
19222 m_log <<
" " << a_coordinate(cellId, i);
19223 m_log <<
" " << a_hasProperty(cellId, SolverCell::NearWall);
19224 m_log <<
" / " << a_noReconstructionNeighbors(cellId);
19225 m_log <<
" " << a_isHalo(cellId);
19226 m_log <<
" " << a_hasProperty(cellId, SolverCell::IsNotGradient);
19227 IF_CONSTEXPR(nDim == 2) {
19228 m_log <<
" p7: " << a_isHalo(c_neighborId(cellId, 0)) <<
" " << a_isHalo(c_neighborId(cellId, 1)) <<
" "
19229 << a_isHalo(c_neighborId(cellId, 2)) <<
" " << a_isHalo(c_neighborId(cellId, 3));
19231 else IF_CONSTEXPR(nDim == 3) {
19232 m_log <<
" p7: " << a_isHalo(c_neighborId(cellId, 0)) <<
" " << a_isHalo(c_neighborId(cellId, 1)) <<
" "
19233 << a_isHalo(c_neighborId(cellId, 2)) <<
" " << a_isHalo(c_neighborId(cellId, 3)) <<
" "
19234 << a_isHalo(c_neighborId(cellId, 4)) <<
" " << a_isHalo(c_neighborId(cellId, 5));
19237 for(
MInt i = 0; i < nDim; i++) {
19238 bbox[i] =
mMin(bbox[i], a_coordinate(cellId, i));
19239 bbox[nDim + i] =
mMax(bbox[nDim + i], a_coordinate(cellId, i));
19246 if(counter > 1000) {
19247 m_log <<
"More than 1000 nan's; output suspended." << endl;
19253 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[0]");
19254 MPI_Allreduce(MPI_IN_PLACE, &bbox[nDim], nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"bbox[nDim]");
19259 m_log <<
"Maximum residual at time step " <<
globalTimeStep <<
" is " << maxR <<
" in cell " << maxRC <<
" at";
19260 for(
MInt i = 0; i < nDim; i++)
19261 m_log <<
" " << a_coordinate(maxRC, i);
19262 m_log <<
", res: " << scientific;
19263 for(
MInt v = 0; v < m_noFVars; v++)
19264 m_log <<
" " << a_rightHandSide(maxRC, v);
19265 m_log <<
", vol.: " << a_cellVolume(maxRC);
19266 m_log <<
", vol.frac.: " << a_cellVolume(maxRC) / c_cellLengthAtLevel(a_level(maxRC));
19270 MFloat minVol = std::numeric_limits<MFloat>::max();
19271 MFloat minVolFrac = std::numeric_limits<MFloat>::max();
19272 MInt partitionCell = -1;
19273 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
19274 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
19275 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume < minVol) {
19276 minVolFrac = m_volumeFraction[bndryId];
19277 minVol = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
19278 partitionCell = cellId;
19281 if(partitionCell > -1) {
19282 IF_CONSTEXPR(nDim == 2) {
19283 m_log <<
"Smallest cell: " << partitionCell <<
" " << minVol <<
" " << minVolFrac <<
" / "
19284 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(partitionCell)].m_srfcs[0]->m_normalVector[0] <<
" "
19285 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(partitionCell)].m_srfcs[0]->m_normalVector[1] <<
" "
19286 <<
" / " << a_rightHandSide(partitionCell, CV->RHO) <<
" " << a_rightHandSide(partitionCell, CV->RHO_U)
19289 else IF_CONSTEXPR(nDim == 3) {
19290 m_log <<
"Smallest cell: " << partitionCell <<
" " << minVol <<
" " << minVolFrac <<
" / "
19291 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(partitionCell)].m_srfcs[0]->m_normalVector[0] <<
" "
19292 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(partitionCell)].m_srfcs[0]->m_normalVector[1] <<
" "
19293 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(partitionCell)].m_srfcs[0]->m_normalVector[2] <<
" "
19294 <<
" / " << a_rightHandSide(partitionCell, CV->RHO) <<
" " << a_rightHandSide(partitionCell, CV->RHO_U)
19298 cerr <<
"========================" << endl;
19299 cerr <<
"time step " <<
globalTimeStep <<
", Runge Kutta step " << oldRKStep[m_RKStep] <<
", solver " << solverId()
19301 cerr << domainId() <<
": Solution diverged (e.g. " << c_globalId(nanC) <<
") in region ";
19302 for(
MInt i = 0; i < nDim; i++) {
19303 cerr <<
"[" << bbox[i] <<
"," << bbox[nDim + i] <<
"]";
19304 if(i < nDim - 1) cerr <<
"x";
19306 cerr <<
". Quit." << endl;
19307 m_solutionDiverged =
true;
19310 MPI_Allreduce(MPI_IN_PLACE, &m_solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
19311 "m_solutionDiverged");
19313 if(m_solutionDiverged) {
19315 m_log <<
"=========== BOUNDARY LOG ================" << endl;
19316 const MInt noBndryCells = m_fvBndryCnd->m_bndryCells->size();
19317 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBndryCells; bndryId++) {
19318 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
19319 m_log << bndryId <<
" " << cellId;
19320 for(
MInt dir = 0; dir < m_noDirs; dir++) {
19321 MInt cId = (c_neighborId(cellId, dir) > -1) ? m_bndryCandidateIds[c_neighborId(cellId, dir)] : -1;
19322 m_log <<
" / " << dir <<
" " << a_hasNeighbor(cellId, dir) <<
" " << c_neighborId(cellId, dir) <<
" " << cId;
19327 saveSolverSolution(1);
19348 mTerm(1, AT_,
"Solution diverged.");
19351 if(nan)
mTerm(1, AT_,
"Solution diverged.");
19364template <MInt nDim,
class SysEqn>
19376template <MInt nDim,
class SysEqn>
19379 cerr <<
"Critical error in createBndryCellMb: "
19380 <<
", cell: " << cellId << endl;
19381 saveSolverSolution(1);
19382 mTerm(1, AT_,
"Critical error in createBndryCellMb");
19385 ASSERT(!a_isBndryCell(cellId),
"");
19387 MInt bCellId = m_fvBndryCnd->m_bndryCells->size();
19388 m_fvBndryCnd->m_bndryCells->append();
19390#if defined _MB_DEBUG_ || !defined NDEBUG
19392 if(a_levelSetValuesMb(cellId, 0) < F0 && !a_hasProperty(cellId, SolverCell::IsSplitChild)) {
19394 if(!a_isGapCell(cellId)) {
19395 if(!a_hasProperty(cellId, SolverCell::IsInactive)) {
19396 cerr <<
"not inact " << c_globalId(cellId) << endl;
19398 if(m_oldBndryCells.size() > 0 && !m_oldBndryCells.count(cellId)) {
19399 if(!a_hasProperty(cellId, SolverCell::WasInactive)) {
19400 auto it = std::find(m_refOldBndryCells.begin(), m_refOldBndryCells.end(), c_parentId(cellId));
19401 if(it == m_refOldBndryCells.end()) {
19402 cerr <<
"CellId " << cellId <<
" " << c_globalId(cellId) <<
" isHalo " << a_isHalo(cellId)
19403 <<
" is GapCell " << a_isGapCell(cellId) <<
" was GapCell " << a_wasGapCell(cellId)
19404 <<
" was not inactive before and is a new bndryCell with Id " << bCellId <<
" ls-value "
19405 << a_levelSetValuesMb(cellId, 0) <<
" at timeStep " <<
globalTimeStep << endl;
19414 for(
MInt face = 0; face < m_noDirs; face++)
19415 m_fvBndryCnd->m_bndryCells->a[bCellId].m_associatedSrfc[face] = -1;
19417 a_bndryId(cellId) = bCellId;
19418 m_fvBndryCnd->m_bndryCells->a[bCellId].m_cellId = cellId;
19420 for(
MInt srfc = 0; srfc < FvBndryCell<nDim, SysEqn>::m_maxNoSurfaces; srfc++) {
19421 m_fvBndryCnd->m_bndryCells->a[bCellId].m_srfcs[srfc]->m_noCutPoints = 0;
19422 m_fvBndryCnd->m_bndryCells->a[bCellId].m_srfcVariables[srfc]->m_ghostCellId = -1;
19423 for(
MInt i = 0; i < nDim; i++)
19424 m_fvBndryCnd->m_bndryCells->a[bCellId].m_srfcVariables[srfc]->m_srfcId[i] = -1;
19425 m_fvBndryCnd->m_bndryCells->a[bCellId].m_srfcs[srfc]->m_bndryCndId = -1;
19426 for(
MInt v = 0; v < m_noCVars; v++) {
19427 m_fvBndryCnd->m_bndryCell[bCellId].m_srfcVariables[srfc]->m_variablesType[v] =
BC_UNSET;
19429 m_fvBndryCnd->m_bndryCells->a[bCellId].m_srfcs[srfc]->m_area = F0;
19431 m_fvBndryCnd->m_bndryCell[bCellId].m_recNghbrIds.clear();
19432 m_fvBndryCnd->m_bndryCell[bCellId].m_faceVertices.clear();
19433 m_fvBndryCnd->m_bndryCell[bCellId].m_faceStream.resize(0);
19435 m_fvBndryCnd->m_bndryCells->a[bCellId].m_linkedCellId = -1;
19436 m_fvBndryCnd->m_bndryCells->a[bCellId].m_noSrfcs = 1;
19437 m_fvBndryCnd->m_bndryCells->a[bCellId].m_volume = F0;
19439 m_sweptVolume[bCellId] = F0;
19440 m_sweptVolumeDt1[bCellId] = F0;
19442 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
19443 a_hasProperty(cellId, SolverCell::IsFlux) =
true;
19444 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
19445 a_hasProperty(cellId, SolverCell::IsMovingBnd) =
true;
19447 for(
MInt i = 0; i < nDim; i++) {
19448 m_fvBndryCnd->m_bndryCells->a[bCellId].m_coordinates[i] = F0;
19451 for(
MInt dir = 0; dir < m_noDirs; dir++) {
19452 m_cutFaceArea[bCellId][dir] = F0;
19453 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
19455 m_bndryCells->a[bCellId].m_associatedSrfc[dir] = m_cellSurfaceMapping[cellId][dir];
19459 m_noLsMbBndryCells++;
19469template <MInt nDim,
class SysEqn>
19473 const MInt splitId = m_splitCells.size();
19474 m_splitCells.push_back(cellId);
19475 m_splitChilds.resize(m_splitCells.size());
19476 m_splitChilds[splitId].resize(noSplitChilds);
19477 a_hasProperty(cellId, SolverCell::IsSplitCell) =
false;
19479 for(
MInt n = 0; n < noSplitChilds; n++) {
19480 const MInt splitChildId = a_noCells();
19483 m_totalnosplitchilds++;
19485 ASSERT(splitChildId == a_noCells() - 1,
"Error in the cell-count, for splitchilds!");
19487 for(
MInt dir = 0; dir < m_noDirs; dir++) {
19488 m_cellSurfaceMapping[splitChildId][dir] = -1;
19490 a_cellVolume(splitChildId) = a_cellVolume(cellId);
19491 m_cellVolumesDt1[splitChildId] = m_cellVolumesDt1[cellId];
19492 for(
MInt k = 0; k < nDim; k++) {
19493 a_coordinate(splitChildId, k) = a_coordinate(cellId, k);
19495 a_level(splitChildId) = a_level(cellId);
19497 a_isBndryGhostCell(splitChildId) =
false;
19498 a_noReconstructionNeighbors(splitChildId) = 0;
19500 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
19501 a_associatedBodyIds(splitChildId, set) = a_associatedBodyIds(cellId, set);
19502 a_levelSetValuesMb(splitChildId, set) = a_levelSetValuesMb(cellId, set);
19505 a_copyPropertiesSolver(cellId, splitChildId);
19507 a_hasProperty(splitChildId, SolverCell::IsSplitCell) =
false;
19508 a_hasProperty(splitChildId, SolverCell::IsSplitChild) =
true;
19509 a_hasProperty(splitChildId, SolverCell::IsInactive) =
false;
19510 a_hasProperty(splitChildId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::WasInactive);
19512 for(
MInt var = 0; var < CV->noVariables; var++) {
19513 a_variable(splitChildId, var) = a_variable(cellId, var);
19514 a_oldVariable(splitChildId, var) = a_variable(cellId, var);
19515 a_pvariable(splitChildId, var) = a_pvariable(cellId, var);
19518 a_bndryId(splitChildId) = createBndryCellMb(splitChildId);
19519 ASSERT(a_bndryId(splitChildId) > -1,
"");
19520 MInt splitChildBndryId = a_bndryId(splitChildId);
19521 for(
MInt dir = 0; dir < m_noDirs; dir++) {
19522 m_bndryCells->a[splitChildBndryId].m_associatedSrfc[dir] = -1;
19523 m_bndryCells->a[splitChildBndryId].m_externalFaces[dir] =
false;
19525 m_splitChilds[splitId][n] = splitChildId;
19526 m_splitChildToSplitCell.insert(pair<MInt, MInt>(splitChildId, cellId));
19528 m_bndryLayerCells.push_back(splitChildId);
19529 a_hasProperty(splitChildId, SolverCell::NearWall) =
true;
19531 ASSERT(a_level(splitChildId) == a_level(m_splitChildToSplitCell.find(splitChildId)->second),
"");
19534 a_hasProperty(cellId, SolverCell::IsSplitCell) =
true;
19536 ASSERT(splitId > -1,
"");
19545template <MInt nDim,
class SysEqn>
19549 m_bndryGhostCellsOffset = a_noCells();
19550 m_fvBndryCnd->computeGhostCells();
19552 for(
MInt bndryId = 0; bndryId < m_noOuterBndryCells; bndryId++) {
19553 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
19554 const MInt noSrfcs = m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs;
19555 for(
MInt srfc = 0; srfc < noSrfcs; srfc++) {
19556 a_reconstructionNeighborId(cellId, srfc) =
19557 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
19559 for(
MInt srfc = 0; srfc < noSrfcs; srfc++) {
19560 const MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
19561 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
19562 a_associatedBodyIds(ghostCellId, set) = -1;
19573template <MInt nDim,
class SysEqn>
19577 correctMasterSlaveSurfaces();
19578 m_bndrySurfacesOffset = a_noSurfaces();
19579 m_fvBndryCnd->addBoundarySurfaces();
19581 for(
MInt srfcId = m_bndrySurfacesOffset; srfcId < a_noSurfaces(); srfcId++) {
19582 a_surfaceUpwindCoefficient(srfcId) = m_globalUpwindCoefficient;
19583 a_surfaceFactor(srfcId, 0) = F1B2;
19584 a_surfaceFactor(srfcId, 1) = F1B2;
19585 for(
MInt i = 0; i < nDim; i++) {
19586 a_surfaceDeltaX(srfcId, i) = a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 0), i);
19587 a_surfaceDeltaX(srfcId, nDim + i) =
19588 a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 1), i);
19591 m_noOuterBoundarySurfaces = m_fvBndryCnd->m_noBoundarySurfaces;
19601template <MInt nDim,
class SysEqn>
19605 MInt noOuterBndryGhostCells = 0;
19606 for(
MInt bndryId = 0; bndryId < m_noOuterBndryCells; bndryId++) {
19607 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
19608 noOuterBndryGhostCells++;
19611 m_associatedInternalCells.resize(noOuterBndryGhostCells);
19613 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
19614 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
19615 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId = -1;
19619 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
19620 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
19622 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
19623 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
19624 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
19626 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
19629 m_totalnoghostcells++;
19631 MInt ghostCellId = a_noCells() - 1;
19632 m_associatedInternalCells.push_back(cellId);
19634 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId = ghostCellId;
19636 a_cellVolume(ghostCellId) = grid().gridCellVolume(a_level(cellId));
19637 m_cellVolumesDt1[ghostCellId] = grid().gridCellVolume(a_level(cellId));
19638 a_FcellVolume(ghostCellId) = F1 / a_cellVolume(ghostCellId);
19640 const MFloat cellLength = c_cellLengthAtLevel(a_level(cellId));
19641 const MFloat cellHalfLength = F1B2 * cellLength;
19643 MFloat dn = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_centroidDistance;
19645 for(
MInt i = 0; i < nDim; i++) {
19646 a_coordinate(ghostCellId, i) =
19647 a_coordinate(cellId, i)
19648 -
mMax(F2 * dn, dn + cellHalfLength) * m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVectorCentroid[i];
19651 for(
MInt set0 = 0; set0 < m_noLevelSetsUsedForMb; set0++) {
19652 a_associatedBodyIds(ghostCellId, set0) = -1;
19654 a_resetPropertiesSolver(ghostCellId);
19655 a_noReconstructionNeighbors(ghostCellId) = 0;
19656 a_level(ghostCellId) = a_level(cellId);
19658 for(
MInt var = 0; var < CV->noVariables; var++) {
19659 a_variable(ghostCellId, var) = a_variable(cellId, var);
19660 a_oldVariable(ghostCellId, var) = a_variable(cellId, var);
19661 a_pvariable(ghostCellId, var) = a_pvariable(cellId, var);
19662 for(
MInt i = 0; i < nDim; i++)
19663 a_slope(ghostCellId, var, i) = F0;
19666 a_bndryId(ghostCellId) = -2;
19667 a_isBndryGhostCell(ghostCellId) = 1;
19668 ASSERT(a_level(ghostCellId) == a_level(getAssociatedInternalCell(ghostCellId)),
"");
19672 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
19673 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
19674 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
19676 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
19677 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
19678 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
19679 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId < 0)
19680 mTerm(1, AT_,
"Ghost cell missing.");
19682 for(
MInt srfc = 1; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
19683 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId
19684 == m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc - 1]->m_ghostCellId)
19685 mTerm(1, AT_,
"Ghost cell duplicate.");
19695template <MInt nDim,
class SysEqn>
19699 if(noDomains() > 1) {
19700 const MFloat Y0 = F1B2 * (m_bbox[4] + m_bbox[1]);
19701 const MFloat DX = c_cellLengthAtLevel(maxRefinementLevel());
19702 const MInt bodyId = 0;
19703 const MInt noPoints = (
MInt)((m_bbox[3] - m_bbox[0]) / DX);
19704 const MInt noAngles = (
MInt)(m_bodyDiameter[bodyId] / DX);
19714 lineCoords.
fill(F0);
19716 angleData.
fill(F0);
19719 MFloat meanBodyTemp = F0;
19721 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
19722 if(a_isBndryGhostCell(cellId))
continue;
19723 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
19724 if(a_isHalo(cellId))
continue;
19725 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
19727 MBool isInside =
false;
19728 IF_CONSTEXPR(nDim == 2) {
19729 if(fabs(a_coordinate(cellId, 1) - Y0) < c_cellLengthAtCell(cellId)) {
19733 IF_CONSTEXPR(nDim == 3) {
19734 const MFloat Z0 = F1B2 * (m_bbox[5] + m_bbox[2]);
19735 if(fabs(a_coordinate(cellId, 1) - Y0) < c_cellLengthAtCell(cellId)
19736 && fabs(a_coordinate(cellId, 2) - Z0) < c_cellLengthAtCell(cellId)) {
19742 if(fabs(a_coordinate(cellId, 1) - Y0) < c_cellLengthAtCell(cellId)) {
19743 MInt id = (
MInt)((a_coordinate(cellId, 0) - m_bbox[0]) / DX);
19744 if(id < 0 || id >= noPoints) {
19748 for(
MInt i = 0; i < nDim; i++)
19749 lineCoords(
id, i) += a_coordinate(cellId, i);
19750 for(
MInt i = 0; i < nDim; i++)
19751 lineData(
id, i) += a_pvariable(cellId, PV->VV[i]) / m_UInfinity;
19752 lineData(
id, nDim) += a_pvariable(cellId, PV->P) / m_PInfinity;
19753 lineData(
id, nDim + 1) += a_pvariable(cellId, PV->RHO) / m_rhoInfinity;
19759 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
19760 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
19761 if(a_isHalo(cellId))
continue;
19762 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
19763 if(m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bodyId[0] != bodyId)
continue;
19765 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[0] - m_bodyCenter[bodyId * nDim];
19767 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area < 0.001 * m_gridCellArea[maxRefinementLevel()])
19770 IF_CONSTEXPR(nDim == 2) {
19771 dr = sqrt(
POW2(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[1]
19772 - m_bodyCenter[bodyId * nDim + 1]));
19774 else IF_CONSTEXPR(nDim == 3) {
19775 dr = sqrt(
POW2(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[1]
19776 - m_bodyCenter[bodyId * nDim + 1])
19777 +
POW2(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[2]
19778 - m_bodyCenter[bodyId * nDim + 2]));
19780 MFloat angle = atan2(dr, dx);
19782 if(id < 0 || id >= noAngles)
mTerm(1, AT_,
"index out of range (angle data): " + to_string(
id));
19784 for(
MInt i = 0; i < nDim; i++) {
19785 rhoU2 +=
POW2(m_VVInfinity[i]);
19787 rhoU2 *= m_rhoInfinity;
19788 MFloat rhoSurface = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->RHO];
19789 MFloat pSurface = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->P];
19790 MFloat T = sysEqn().temperature_ES(rhoSurface, pSurface);
19791 MFloat cp = (pSurface - m_PInfinity) / (F1B2 * rhoU2);
19794 MFloat mue = SUTHERLANDLAW(T) / sysEqn().m_Re0;
19795 for(
MInt i = 0; i < nDim; i++) {
19796 MFloat grad = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[i]];
19797 shear[i] = mue * grad;
19800 MFloat cf = sqrt(
POW2(shear[0]) +
POW2(shear[1]) +
POW2(shear[2])) / (F1B2 * rhoU2);
19801 if(m_euler) cf = (a_pvariable(cellId, PV->P) - m_PInfinity) / (F1B2 * rhoU2);
19804 angleData(
id, 0) += weight * cp;
19805 angleData(
id, 1) += weight * cf;
19806 angleData(
id, 2) += weight * m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
19807 angleCnt(
id) += weight;
19811 MPI_Allreduce(MPI_IN_PLACE, &lineCoords[0], noPoints * nDim, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
19813 MPI_Allreduce(MPI_IN_PLACE, &lineData[0], noPoints * m_noPVars, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
19815 MPI_Allreduce(MPI_IN_PLACE, &lineCnt[0], noPoints, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
19817 MPI_Allreduce(MPI_IN_PLACE, &angleData[0], noAngles * 3, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
19819 MPI_Allreduce(MPI_IN_PLACE, &angleCnt[0], noAngles, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
19822 if(domainId() == 0) {
19824 ofl.open(fileName);
19825 if(ofl.is_open() && ofl.good()) {
19826 const MInt maxSkipCnt =
IPOW2(maxRefinementLevel() - maxUniformRefinementLevel());
19828 for(
MInt p = 0; p < noPoints; p++) {
19829 if(lineCnt(p) < F1) {
19831 if(skipCnt == maxSkipCnt) ofl << endl;
19836 for(
MInt i = 0; i < nDim; i++) {
19837 ofl <<
" " << lineCoords(p, i) / lineCnt(p);
19839 for(
MInt i = 0; i < m_noPVars; i++) {
19840 ofl <<
" " << lineData(p, i) / lineCnt(p);
19842 ofl <<
" " << lineCnt(p) << endl;
19847 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing!" << endl;
19850 if(domainId() == 1) {
19852 ofl.open(
"surfaceData");
19853 if(ofl.is_open() && ofl.good()) {
19854 for(
MInt p = 0; p < noAngles; p++) {
19855 if(angleCnt(p) < 1e-10)
continue;
19858 ofl <<
" " << angleData(p, 0) / angleCnt(p);
19859 ofl <<
" " << angleData(p, 1) / angleCnt(p);
19860 ofl <<
" " << angleData(p, 2) / (angleCnt(p) * m_gridCellArea[maxRefinementLevel()]);
19861 ofl <<
" " << angleCnt(p) << endl;
19867 ofl.open(
"surfaceTemp", ios_base::out | ios_base::trunc);
19868 ofl <<
"# 1:ts 2:t 3:tf 4:Tf 5:Tp" << endl;
19870 ofl.open(
"surfaceTemp", ios_base::out | ios_base::app);
19871 if(ofl.is_open() && ofl.good()) {
19873 <<
" " << setprecision(12) << TfluidMean / m_TInfinity <<
" " << setprecision(12)
19874 << meanBodyTemp / m_TInfinity
19878 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing!" << endl;
19882 MInt noCells = a_noCells();
19885 MBool centerLine, centerLine2;
19888 MFloat tmpCellId, tmpCellCoordinate;
19891 for(
MInt cellId = 0; cellId < noCells; cellId++) {
19892 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
19893 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
19894 if(a_isBndryGhostCell(cellId))
continue;
19895 centerLine =
false;
19896 centerLine2 =
false;
19898 if(a_coordinate(cellId, 1) >= F0 && a_hasNeighbor(cellId, 2) > 0
19899 && a_coordinate(c_neighborId(cellId, 2), 1) < F0) {
19903 IF_CONSTEXPR(nDim == 2) { centerLine2 =
true; }
19904 IF_CONSTEXPR(nDim == 3) {
19905 if(a_coordinate(cellId, 2) >= F0 && a_hasNeighbor(cellId, 4) > 0
19906 && a_coordinate(c_neighborId(cellId, 4), 2) < F0) {
19907 centerLine2 =
true;
19910 if(!centerLine || !centerLine2)
continue;
19912 cellIdList(0, counter) = (
MFloat)cellId;
19913 cellIdList(1, counter) = a_coordinate(cellId, 0);
19917 for(
MInt c = 0; c < counter; c++) {
19918 for(
MInt d = c + 1; d < counter; d++) {
19919 if(cellIdList(1, d) < cellIdList(1, c)) {
19920 tmpCellId = cellIdList(0, c);
19921 tmpCellCoordinate = cellIdList(1, c);
19922 cellIdList(0, c) = cellIdList(0, d);
19923 cellIdList(1, c) = cellIdList(1, d);
19924 cellIdList(0, d) = tmpCellId;
19925 cellIdList(1, d) = tmpCellCoordinate;
19930 ofl.open(fileName);
19931 if(ofl.is_open() && ofl.good()) {
19932 for(
MInt c = 0; c < counter; c++) {
19933 MInt cellId = (
MInt)cellIdList(0, c);
19935 u = a_variable(cellId, 0) / a_variable(cellId, CV->RHO) - a_coordinate(cellId, 1) * a_slope(cellId, PV->U, 1);
19936 v = a_variable(cellId, 1) / a_variable(cellId, CV->RHO) - a_coordinate(cellId, 1) * a_slope(cellId, PV->V, 1);
19938 IF_CONSTEXPR(nDim == 3) {
19939 u -= a_coordinate(cellId, 2) * a_slope(cellId, PV->U, 2);
19940 v -= a_coordinate(cellId, 2) * a_slope(cellId, PV->V, 2);
19943 ofl << a_coordinate(cellId, 0) <<
" ";
19944 ofl << u / m_UInfinity <<
" ";
19945 ofl << v / m_UInfinity <<
" ";
19946 ofl << a_variable(cellId, CV->RHO) <<
" ";
19947 ofl << a_pvariable(cellId, PV->P) <<
" ";
19948 ofl << a_variable(cellId, CV->RHO) / m_rhoInfinity <<
" ";
19949 ofl << a_pvariable(cellId, PV->P) / m_PInfinity <<
" ";
19955 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing!" << endl;
19972 const MFloat vs = m_Ma * (m_gamma + F1) / F4 + sqrt(
POW2(m_Ma * (m_gamma + F1) / F4) + F1);
19973 const MFloat xs = F1B2 + vs * (m_physicalTime - timeStep());
19974 const MFloat xp = m_Ma * (m_physicalTime - timeStep());
19976 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
19977 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
19978 if(a_hasProperty(cellId, SolverCell::IsCutOff))
continue;
19979 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
19980 if(a_isPeriodic(cellId))
continue;
19981 if(a_isBndryGhostCell(cellId))
continue;
19982 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
19983 if(a_coordinate(cellId, 0) > xp) {
19984 xsa += a_pvariable(cellId, PV->U) * a_cellVolume(cellId);
19986 if(a_coordinate(cellId, 0) < xp) {
19987 p0 += a_pvariable(cellId, PV->P) * a_cellVolume(cellId);
19988 if(!checkNeighborActive(cellId, 1) || a_hasNeighbor(cellId, 1) == 0) {
19989 p00 += a_pvariable(cellId, PV->P);
19993 if(a_coordinate(cellId, 0) > xp && a_coordinate(cellId, 0) < xs) {
19994 vel += a_cellVolume(cellId) * a_pvariable(cellId, PV->U);
19996 a_cellVolume(cellId) * sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
19997 vol += a_cellVolume(cellId);
19999 if(a_coordinate(cellId, 0) < xp || a_coordinate(cellId, 0) > xp + 5.0)
continue;
20000 pavg += a_pvariable(cellId, PV->P);
20001 rhoavg += a_pvariable(cellId, PV->RHO);
20002 uavg += a_pvariable(cellId, PV->U);
20004 if(a_coordinate(cellId, 0) < xp || a_coordinate(cellId, 0) > xp + 2.5)
continue;
20005 pavg2 += a_pvariable(cellId, PV->P);
20006 rhoavg2 += a_pvariable(cellId, PV->RHO);
20007 uavg2 += a_pvariable(cellId, PV->U);
20009 cerr <<
"piston front vars: " << setprecision(14) << xp <<
" " << xs <<
" "
20010 << timeStep() * m_Ma / c_cellLengthAtLevel(maxRefinementLevel()) <<
" " << pavg / cnt <<
" " << rhoavg / cnt
20013 <<
" " << vel /
mMax(1e-14, vol) <<
" " << temp /
mMax(1e-14, vol) <<
" " << xp + F1B2 + xsa / (m_Ma * 16.0)
20014 <<
" " << p0 / 16.0 <<
" " << p00 / p00cnt << endl;
20023template <MInt nDim,
class SysEqn>
20029 for(
MInt cellId = 0; cellId < maxNoGridCells(); cellId++) {
20030 for(
MInt v = 0; v < m_noFVars; v++) {
20031 m_rhs0[cellId][v] = F0;
20033 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20034 m_cellSurfaceMapping[cellId][dir] = -1;
20036 m_cellVolumesDt1[cellId] = F0;
20037 a_levelSetValuesMb(cellId, 0) = c_cellLengthAtLevel(0);
20040 m_initialSurfacesOffset = 0;
20041 m_nearBoundaryBackup.clear();
20042 m_oldBndryCells.clear();
20044 std::map<MInt, std::vector<MFloat>>().swap(m_nearBoundaryBackup);
20045 std::map<MInt, MFloat>().swap(m_oldBndryCells);
20046 std::vector<MInt>().swap(m_bndryCandidateIds);
20047 std::vector<MInt>().swap(m_bndryCandidates);
20048 std::vector<MFloat>().swap(m_candidateNodeValues);
20049 std::vector<MInt>().swap(m_candidateNodeSet);
20050 std::set<MInt>().swap(m_splitSurfaces);
20051 std::vector<CutCandidate<nDim>>().swap(m_cutCandidates);
20059template <MInt nDim,
class SysEqn>
20061 if(m_fvBndryCnd->m_cellCoordinatesCorrected) m_fvBndryCnd->recorrectCellCoordinates();
20063 restoreNeighbourLinks();
20072template <MInt nDim,
class SysEqn>
20076 if(m_deleteNeighbour) {
20077 restoreNeighbourLinks();
20080 for(
MInt bs = 0; bs < m_fvBndryCnd->m_noBoundarySurfaces; bs++) {
20081 MInt srfcId = m_fvBndryCnd->m_boundarySurfaces[bs];
20082 a_surfaceNghbrCellId(srfcId, 0) = -1;
20083 a_surfaceNghbrCellId(srfcId, 1) = -1;
20085 m_fvBndryCnd->m_noBoundarySurfaces = 0;
20087 m_surfaces.size(m_bndrySurfacesOffset);
20089 if(m_fvBndryCnd->m_cellCoordinatesCorrected) m_fvBndryCnd->recorrectCellCoordinates();
20091 set<MInt> tmpSplitSurf(m_splitSurfaces);
20092 m_splitSurfaces.clear();
20093 for(set<MInt>::iterator it = tmpSplitSurf.begin(); it != tmpSplitSurf.end(); ++it) {
20095 deleteSurface(srfcId);
20098 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
20099 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
20100 if(a_isBndryGhostCell(cellId) || a_hasProperty(cellId, SolverCell::IsSplitChild)) {
20101 removeSurfaces(cellId);
20104 resetSurfaces(cellId);
20105 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20106 m_cutFaceArea[bndryId][dir] = F0;
20111 m_noLsMbBndryCells = 0;
20119template <MInt nDim,
class SysEqn>
20125 for(
MInt cellId = 0; cellId < maxNoGridCells(); cellId++) {
20126 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20127 m_cellSurfaceMapping[cellId][dir] = -1;
20130 m_freeSurfaceIndices.clear();
20139template <MInt nDim,
class SysEqn>
20144 MInt noCells = m_fvBndryCnd->m_bndryCells->size();
20147 for(
MInt bndryId = noCells - 1; bndryId >= m_noOuterBndryCells; bndryId--) {
20148 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
20150 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
20151 MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
20152 if(ghostCellId > -1) {
20153 ASSERT(a_bndryId(ghostCellId) == -2,
"");
20154 a_bndryId(ghostCellId) = -1;
20156 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId = -1;
20159 a_bndryId(cellId) = -1;
20161 size = m_fvBndryCnd->m_bndryCells->size();
20162 m_fvBndryCnd->m_bndryCells->resetSize(size - 1);
20164 a_hasProperty(cellId, SolverCell::IsSplitCell) =
false;
20165 a_hasProperty(cellId, SolverCell::IsSplitChild) =
false;
20166 a_hasProperty(cellId, SolverCell::HasSplitFace) =
false;
20167 a_hasProperty(cellId, SolverCell::IsTempLinked) =
false;
20168 a_hasProperty(cellId, SolverCell::IsMovingBnd) =
false;
20170 a_noReconstructionNeighbors(cellId) = 0;
20171 m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.resize(0);
20172 m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst.resize(0);
20173 m_fvBndryCnd->m_bndryCell[bndryId].m_faceVertices.clear();
20174 for(
MUint i = 0; i < m_fvBndryCnd->m_bndryCell[bndryId].m_faceStream.size(); i++) {
20175 m_fvBndryCnd->m_bndryCell[bndryId].m_faceStream[i].resize(0);
20177 m_fvBndryCnd->m_bndryCell[bndryId].m_faceStream.resize(0);
20178 for(
MInt srfc = 0; srfc < FvBndryCell<nDim, SysEqn>::m_maxNoSurfaces; srfc++) {
20179 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_imagePointRecConst.resize(0);
20180 for(
MInt v = 0; v < m_noCVars; v++) {
20181 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_variablesType[v] =
BC_UNSET;
20185 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20186 m_cutFaceArea[bndryId][dir] = F0;
20189 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId > -1) {
20190 cerr <<
"linking not expected" << endl;
20191 MInt pm = m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId;
20192 a_cellVolume(pm) = grid().gridCellVolume(a_level(pm));
20193 a_FcellVolume(pm) = F1 /
mMax(m_volumeThreshold, a_cellVolume(pm));
20194 m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId = -1;
20197 m_noLsMbBndryCells = 0;
20199 for(
MInt cellId = 0; cellId < c_noCells(); cellId++) {
20200 ASSERT(!a_hasProperty(cellId, SolverCell::IsMovingBnd),
"");
20209template <MInt nDim,
class SysEqn>
20214 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
20215 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
20218 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20219 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && a_hasNeighbor(cellId, dir) > 0) {
20220 const MInt nghbrId = c_neighborId(cellId, dir);
20221 if(a_hasProperty(nghbrId, SolverCell::IsInactive)) {
20222 a_hasProperty(cellId, SolverCell::IsBndryActive) =
true;
20228 m_deleteNeighbour =
true;
20236template <MInt nDim,
class SysEqn>
20240 m_deleteNeighbour =
false;
20241 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
20242 a_hasProperty(cellId, SolverCell::IsBndryActive) =
false;
20253template <MInt nDim,
class SysEqn>
20257 cerr <<
globalTimeStep <<
" Calling initializeEmergedCells(), due to Gap-opening " << endl;
20266 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
20267 gapCell[cellId] =
false;
20268 if(m_levelSet && m_closeGaps) {
20269 if(a_hasProperty(cellId, SolverCell::WasGapCell) && !a_hasProperty(cellId, SolverCell::IsGapCell)
20270 && a_hasProperty(cellId, SolverCell::WasInactive) && !a_hasProperty(cellId, SolverCell::IsInactive)) {
20271 gapCell[cellId] =
true;
20273 cerr <<
"initializeEmergedCells: GapCells are " << cellId <<
" " << c_globalId(cellId) <<
" bndry-ghostCell "
20274 << a_isBndryGhostCell(cellId) << endl;
20283 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
20284 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
20286 if(a_isHalo(cellId))
continue;
20287 if(a_isPeriodic(cellId))
continue;
20288 if(!a_hasProperty(cellId, SolverCell::WasInactive))
continue;
20289 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
20292 cerr <<
"initializeEmergedCell: resetting Gap-Cells " << cellId <<
" " << c_globalId(cellId) << endl;
20294 a_variable(cellId, CV->RHO) = m_rhoInfinity;
20295 a_variable(cellId, CV->RHO_E) = m_rhoEInfinity;
20296 a_pvariable(cellId, PV->RHO) = m_rhoInfinity;
20297 a_pvariable(cellId, PV->P) = m_PInfinity;
20299 for(
MInt v = 0; v < nDim; v++) {
20300 a_variable(cellId, CV->RHO_VV[v]) = F0;
20301 a_pvariable(cellId, PV->VV[v]) = F0;
20307 initEmergingGapCells();
20310 m_noEmergedCells = 0;
20311 m_noEmergedWindowCells = 0;
20313 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
20314 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
20315 ASSERT(cellId < a_noCells(),
"");
20316 if(a_isHalo(cellId))
continue;
20317 if(a_isPeriodic(cellId))
continue;
20318 if(!a_hasProperty(cellId, SolverCell::WasInactive))
continue;
20319 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
20320 m_noEmergedCells++;
20321 if(a_isWindow(cellId)) m_noEmergedWindowCells++;
20323 if(a_hasProperty(cellId, SolverCell::IsSplitCell)) {
20324 for(
MInt v = 0; v < m_noCVars; v++) {
20325 a_variable(cellId, v) = F0;
20327 for(
MInt v = 0; v < m_noPVars; v++) {
20328 a_pvariable(cellId, v) = F0;
20333 cerr <<
"initializeEmergedCell: init Cells " << cellId <<
" " << c_globalId(cellId) << endl;
20336 if(!gapCell[cellId]) {
20338 const MInt counter = this->
template getAdjacentLeafCells<2>(cellId, 1, nghbrList, layerId);
20340 for(
MInt v = 0; v < m_noCVars; v++)
20343 for(
MInt n = 0; n < counter; n++) {
20344 MInt nghbrId = nghbrList[n];
20345 if(nghbrId < 0)
continue;
20346 if(a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
20347 MFloat fac = m_cellVolumesDt1[nghbrId];
20348 for(
MInt v = 0; v < m_noCVars; v++) {
20349 vars[v] += fac * a_oldVariable(nghbrId, v);
20353 if(fabs(facCnt) / c_cellLengthAtCell(cellId) > 0.1) {
20354 for(
MInt v = 0; v < m_noCVars; v++) {
20356 a_variable(cellId, v) = vars[v];
20358 setPrimitiveVariables(cellId);
20360 cerr <<
"Warning cell init " << fabs(facCnt) / c_cellLengthAtCell(cellId) << endl;
20361 if(m_levelSet && m_closeGaps) {
20362 cerr << m_closeGaps <<
" " << a_hasProperty(cellId, SolverCell::WasGapCell) <<
" "
20363 << a_hasProperty(cellId, SolverCell::IsGapCell) <<
" " << a_hasProperty(cellId, SolverCell::WasInactive)
20364 <<
" " << a_hasProperty(cellId, SolverCell::IsInactive) << endl;
20366 a_variable(cellId, CV->RHO) = m_rhoInfinity;
20367 a_variable(cellId, CV->RHO_E) = m_rhoEInfinity;
20368 a_pvariable(cellId, PV->RHO) = m_rhoInfinity;
20369 a_pvariable(cellId, PV->P) = m_PInfinity;
20370 for(
MInt v = 0; v < nDim; v++) {
20371 a_variable(cellId, CV->RHO_VV[v]) = F0;
20372 a_pvariable(cellId, PV->VV[v]) = F0;
20376 for(
MInt i = 0; i < nDim; i++) {
20377 a_pvariable(cellId, PV->VV[i]) =
20378 delta * a_pvariable(cellId, PV->VV[i])
20379 + (F1 - delta) * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->VV[i]];
20383 setConservativeVariables(cellId);
20385 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
20386 MInt splitParent = getAssociatedInternalCell(cellId);
20387 MInt splitParentBndryId = a_bndryId(splitParent);
20388 ASSERT(splitParentBndryId > -1,
" this is too bad... split cells inconsistency");
20389 MFloat factor = m_bndryCells->a[bndryId].m_volume /
mMax(m_eps, m_bndryCells->a[splitParentBndryId].m_volume);
20390 for(
MInt v = 0; v < m_noCVars; v++) {
20391 a_variable(splitParent, v) += factor * a_variable(cellId, v);
20393 for(
MInt v = 0; v < m_noPVars; v++) {
20394 a_pvariable(splitParent, v) += factor * a_pvariable(cellId, v);
20399 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
20400 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
20402 if(m_dualTimeStepping) {
20403 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
20411 MInt globalNoEmerged = m_noEmergedWindowCells + m_gapOpened;
20412 MPI_Allreduce(MPI_IN_PLACE, &globalNoEmerged, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
20413 "globalNoEmerged");
20414 if(globalNoEmerged > 0) {
20416 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20417 for(
MInt j = 0; j < noHaloCells(i); j++) {
20418 setConservativeVariables(haloCellId(i, j));
20424 cerr <<
"initializeEmergedCell: noEmergedCells " << m_noEmergedCells << endl;
20432template <MInt nDim,
class SysEqn>
20436 ASSERT(m_gapOpened,
"");
20438 MIntScratchSpace gapCells(m_fvBndryCnd->m_maxNoBndryCells, AT_,
"gapCells");
20441 MIntScratchSpace NNghbrs(m_fvBndryCnd->m_maxNoBndryCells, AT_,
"NNghbrs");
20442 MIntScratchSpace NNghbrs2(m_fvBndryCnd->m_maxNoBndryCells * nDim, AT_,
"NNghbrs2");
20443 MFloatScratchSpace NFactors(m_fvBndryCnd->m_maxNoBndryCells * nDim, AT_,
"NFactors");
20447 MInt noGapCells = 0;
20451 MInt normalDir = 0;
20452 MInt noSteps = 100;
20453 MBool NeumannVariante =
true;
20456 const MFloat eps = sqrt(nDim) * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
20458 if(domainId() == 0) {
20459 cerr <<
"Initializing emerging gap cells at time step " <<
globalTimeStep << endl;
20464 restoreNeighbourLinks();
20467 for(
MInt c = 0; c < a_noCells(); c++) {
20468 isGapCell.
p[c] =
false;
20469 isDCell.
p[c] =
false;
20470 isNCell.
p[c] =
false;
20476 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
20477 if(a_isBndryGhostCell(cellId))
continue;
20478 if(!a_hasProperty(cellId, SolverCell::WasGapCell))
continue;
20479 if(a_levelSetValuesMb(cellId, 0) < -eps)
continue;
20480 if(!a_hasProperty(cellId, SolverCell::IsGapCell) && !a_hasProperty(cellId, SolverCell::IsInactive)
20481 && a_hasProperty(cellId, SolverCell::WasInactive)) {
20482 gapCells.
p[noGapCells++] = cellId;
20483 isGapCell.
p[cellId] =
true;
20484 cerr <<
"initEmergingGapCell: Gap-CellId" << cellId <<
" " << c_globalId(cellId) << endl;
20489 for(
MInt c = 0; c < noGapCells; c++) {
20490 MInt cellId = gapCells.
p[c];
20491 if(a_isHalo(cellId))
continue;
20492 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20493 if(!a_hasNeighbor(cellId, dir)) {
20494 cerr <<
" [" << domainId() <<
"]: Error in FvMbCartesianSolverXD::initEmergingGapCells(): no nghbr in dir "
20495 << dir <<
" found for cell " << cellId <<
". Please check! " << endl;
20498 MInt nghbrId = c_neighborId(cellId, dir);
20499 if(isGapCell.
p[nghbrId])
continue;
20500 if(isDCell.
p[nghbrId])
continue;
20501 if(isNCell.
p[nghbrId])
continue;
20502 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
20503 if(a_bndryId(nghbrId) > -1) {
20504 if(!a_hasProperty(nghbrId, SolverCell::WasInactive)) {
20507 isDCell.
p[nghbrId] =
true;
20508 DCells.
p[noDCells++] = nghbrId;
20509 cerr <<
"initEmergingGapCell: D-CellId" << nghbrId <<
" " << c_globalId(nghbrId) << endl;
20513 }
else if(a_levelSetValuesMb(nghbrId, 0) < F0) {
20516 isNCell.
p[nghbrId] =
true;
20517 NCells.
p[noNCells++] = nghbrId;
20518 cerr <<
"initEmergingGapCell: N-CellId" << nghbrId <<
" " << c_globalId(nghbrId) << endl;
20522 cerr <<
" [" << domainId() <<
"]: Warning in FvMbCartesianSolverXD::initEmergingGapCells(): nghbr in dir "
20523 << dir <<
" with id " << nghbrId <<
" of cell " << cellId
20524 <<
" is no Gap cell, no D and no N cell (was inactive, is bndryCell, has levelset >= 0 but is no gap "
20525 "cell)! Please check! "
20527 mTerm(1, AT_,
"Error 1");
20530 if(a_hasProperty(nghbrId, SolverCell::IsInactive)) {
20532 isNCell.
p[nghbrId] =
true;
20533 NCells.
p[noNCells++] = nghbrId;
20534 cerr <<
"initEmergingGapCell: N-CellId" << nghbrId <<
" " << c_globalId(nghbrId) << endl;
20537 if(!a_hasProperty(nghbrId, SolverCell::WasInactive)) {
20539 isDCell.
p[nghbrId] =
true;
20540 DCells.
p[noDCells++] = nghbrId;
20541 cerr <<
"initEmergingGapCell: D-CellId" << nghbrId <<
" " << c_globalId(nghbrId) << endl;
20544 cerr <<
" [" << domainId() <<
"]: Warning in FvMbCartesianSolverXD::initEmergingGapCells(): nghbr in dir "
20545 << dir <<
" with id " << nghbrId <<
" of cell " << cellId
20546 <<
" is no Gap cell, no D and no N cell (is active, was inactive, but is no gap cell and no bndry "
20547 "cell! Please check! "
20549 mTerm(1, AT_,
"Error 2");
20560 MIntScratchSpace noExchangeWindowCells(noNeighborDomains(), AT_,
"noExchangeWindowCells");
20561 MIntScratchSpace noExchangeHaloCells(noNeighborDomains(), AT_,
"noExchangeHaloCells");
20562 MIntScratchSpace exchangeWindowCells(noNeighborDomains(), noGapCells + noDCells + noNCells, AT_,
20563 "exchangeWindowCells");
20566 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20567 noExchangeWindowCells[i] = 0;
20568 for(
MInt j = 0; j < noWindowCells(i); j++) {
20569 MInt cellId = windowCellId(i, j);
20570 if(isDCell[cellId] || isNCell[cellId] || isGapCell[cellId]) {
20571 exchangeWindowCells(i, noExchangeWindowCells[i]++) = j;
20577 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20578 MPI_Issend(&noExchangeWindowCells.
p[i], 1, MPI_INT, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
20579 "noExchangeWindowCells.p[i]");
20581 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20582 MPI_Recv(&noExchangeHaloCells.
p[i], 1, MPI_INT, neighborDomain(i), 0, mpiComm(), &status, AT_,
20583 "noExchangeHaloCells.p[i]");
20585 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20586 MPI_Wait(&g_mpiRequestMb[i], &status, AT_);
20589 MInt maxNoExchangeHaloCells = 0;
20590 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20591 if(noExchangeHaloCells[i] > maxNoExchangeHaloCells) maxNoExchangeHaloCells = noExchangeHaloCells[i];
20593 MIntScratchSpace exchangeHaloCells(noNeighborDomains(), maxNoExchangeHaloCells, AT_,
"exchangeHaloCells");
20596 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20597 for(
MInt j = 0; j < noExchangeWindowCells[i]; j++) {
20598 m_sendBuffers[i][j] = exchangeWindowCells(i, j);
20601 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20602 MPI_Issend(m_sendBuffers[i], noExchangeWindowCells[i], MPI_DOUBLE, neighborDomain(i), 0, mpiComm(),
20603 &g_mpiRequestMb[i], AT_,
"m_sendBuffers[i]");
20605 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20606 MPI_Recv(m_receiveBuffers[i], noExchangeHaloCells[i], MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &status, AT_,
20607 "m_receiveBuffers[i]");
20609 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20610 MPI_Wait(&g_mpiRequestMb[i], &status, AT_);
20612 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20613 for(
MInt j = 0; j < noExchangeHaloCells[i]; j++) {
20614 exchangeHaloCells(i, j) = m_receiveBuffers[i][j];
20620 if(!NeumannVariante) {
20621 for(
MInt nc = 0; nc < noNCells; nc++) {
20622 MInt cellId = NCells.
p[nc];
20623 if(a_bndryId(cellId) > -1) {
20624 MInt bndryId = a_bndryId(cellId);
20627 for(
MInt d = 0; d < nDim; d++) {
20628 if(abs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[d]) > maxNormal) {
20629 maxNormal = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[d];
20631 if(maxNormal > F0) normalDir += 1;
20632 maxNormal = abs(maxNormal);
20635 if(!a_hasNeighbor(cellId, normalDir)) {
20636 cerr <<
" [" << domainId() <<
"]:"
20637 <<
" Error in FvMbCartesianSolverXD::initEmergingGapCells(): no nghbr in primary dir " << normalDir
20638 <<
" found for cell " << cellId <<
". Please check! " << endl;
20639 mTerm(1, AT_,
"Error 3");
20641 NNghbrs.
p[nc] = c_neighborId(cellId, normalDir);
20645 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20646 if(!a_hasNeighbor(cellId, dir)) {
20649 MInt nghbrId = c_neighborId(cellId, dir);
20650 MInt bndryId = a_bndryId(nghbrId);
20651 if(!isGapCell.
p[nghbrId] && !isDCell.
p[nghbrId])
continue;
20652 if(bndryId < 0)
continue;
20653 for(
MInt d = 0; d < nDim; d++) {
20654 if(abs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[d]) > maxNormal) {
20655 maxNormal = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[d];
20657 if(maxNormal > F0) normalDir += 1;
20658 maxNormal = abs(maxNormal);
20662 NNghbrs.
p[nc] = c_neighborId(cellId, normalDir);
20663 if(!a_hasNeighbor(cellId, normalDir)) {
20664 cerr <<
" [" << domainId() <<
"]:"
20665 <<
" Error in FvMbCartesianSolverXD::initEmergingGapCells(): no nghbr in primary dir " << normalDir
20666 <<
" found for cell " << cellId <<
". Please check! " << endl;
20667 mTerm(1, AT_,
"Error 4");
20675 for(
MInt nc = 0; nc < noNCells; nc++) {
20676 MInt cellId = NCells.
p[nc];
20677 if(a_bndryId(cellId) > -1) {
20680 MInt bndryId = a_bndryId(cellId);
20681 for(
MInt d = 0; d < nDim; d++) {
20683 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[d] > F0) {
20686 ASSERT(a_hasNeighbor(cellId, normalDir),
"NCell has no neighbor in normalDir!");
20687 NNghbrs2.
p[nc * nDim + d] = c_neighborId(cellId, normalDir);
20688 NFactors.
p[nc * nDim + d] =
POW2(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_normalVector[d]);
20694 for(
MInt i = 0; i < nDim; i++) {
20695 nablaPhi[i] = (a_levelSetValuesMb(c_neighborId(cellId, 2 * i), 0)
20696 - a_levelSetValuesMb(c_neighborId(cellId, 2 * i + 1), 0))
20697 / (F2 * c_cellLengthAtLevel(a_level(cellId)));
20698 nablaAbs +=
POW2(nablaPhi[i]);
20700 nablaAbs = sqrt(nablaAbs);
20701 for(
MInt i = 0; i < nDim; i++) {
20702 nablaPhi[i] /= nablaAbs;
20704 for(
MInt d = 0; d < nDim; d++) {
20706 if(nablaPhi[d] > F0) {
20709 ASSERT(a_hasNeighbor(cellId, normalDir),
"NCell has no neighbor in normalDir!");
20710 NNghbrs2.
p[nc * nDim + d] = c_neighborId(cellId, normalDir);
20711 NFactors.
p[nc * nDim + d] =
POW2(nablaPhi[d]);
20719 for(
MInt nc = 0; nc < noNCells; nc++) {
20720 if(!NeumannVariante) {
20721 MInt cellId = NCells.
p[nc];
20722 MInt nghbrId = NNghbrs.
p[nc];
20723 if(isNCell.
p[nghbrId] || (a_hasProperty(nghbrId, SolverCell::WasInactive) && !isGapCell.
p[nghbrId])) {
20724 cerr <<
" [" << domainId() <<
"]:"
20725 <<
" Error in FvMbCartesianSolverXD::initEmergingGapCells(): nghbr " << nghbrId <<
" found for cell "
20726 << cellId <<
" is no gap cell and no dirichlet cell. Please check! " << endl;
20727 mTerm(1, AT_,
"Error 7");
20729 }
else if(NeumannVariante) {
20730 MInt cellId = NCells.
p[nc];
20731 for(
MInt d = 0; d < nDim; d++) {
20732 MInt nghbrId = NNghbrs2.
p[nc * nDim + d];
20733 if(!isNCell.
p[nghbrId] && !isDCell.
p[nghbrId] && !isGapCell.
p[nghbrId] && a_levelSetValuesMb(nghbrId, 0) < F0) {
20734 cerr << domainId() <<
": Warning NNghbrs2 " << nghbrId <<
" found for cell " << cellId
20735 <<
" is no gap cell and no dirichlet cell! " << endl;
20736 if(!a_hasProperty(nghbrId, SolverCell::WasInactive)) {
20737 cerr <<
" Nghbr was not inactive, so has a valid time history. Setting as Dirichlet cell... " << endl;
20738 isDCell.
p[nghbrId] =
true;
20739 DCells.
p[noDCells++] = nghbrId;
20741 cerr <<
" Nghbr was inactive, so problem can not be resolved.. try nevertheless..." << endl;
20749 for(
MInt nc = 0; nc < noNCells; nc++) {
20750 const MInt cellId = NCells.
p[nc];
20751 const MInt bodyId = a_associatedBodyIds(cellId, 0);
20752 ASSERT(bodyId >= 0,
"associated body Id not matching!");
20753 for(
MInt dir = 0; dir < nDim; dir++) {
20754 a_pvariable(cellId, PV->VV[dir]) = m_bodyVelocity[bodyId * nDim + dir];
20761 MFloat lambdaRelax = 1.2;
20762 MInt backupSteps = noSteps;
20766 for(
MInt step = noSteps; step > 0; step--) {
20768 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20769 MInt sendBufferCounter = 0;
20770 for(
MInt j = 0; j < noExchangeWindowCells[i]; j++) {
20771 MInt cellId = windowCellId(i, exchangeWindowCells(i, j));
20772 memcpy((
void*)&m_sendBuffers[i][sendBufferCounter], (
void*)&a_pvariable(cellId, 0),
20773 m_dataBlockSize *
sizeof(
MFloat));
20774 sendBufferCounter += m_dataBlockSize;
20778 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20779 MInt bufSize = noExchangeWindowCells[i] * m_dataBlockSize;
20780 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
20781 "m_sendBuffers[i]");
20784 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20785 MInt bufSize = noExchangeHaloCells[i] * m_dataBlockSize;
20786 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &status, AT_,
20787 "m_receiveBuffers[i]");
20789 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20790 MPI_Wait(&g_mpiRequestMb[i], &status, AT_);
20793 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20794 MInt receiveBufferCounter = 0;
20795 for(
MInt j = 0; j < noExchangeHaloCells[i]; j++) {
20796 MInt cellId = haloCellId(i, exchangeHaloCells(i, j));
20797 memcpy((
void*)&a_pvariable(cellId, 0), (
void*)&m_receiveBuffers[i][receiveBufferCounter],
20798 m_dataBlockSize *
sizeof(
MFloat));
20799 receiveBufferCounter += m_dataBlockSize;
20803 for(
MInt var = 0; var < m_noPVars; var++) {
20810 if(!NeumannVariante) {
20811 for(
MInt n = 0; n < noNCells; n++) {
20812 MInt cellId = NCells.
p[n];
20813 MInt nghbrId = NNghbrs.
p[n];
20814 a_pvariable(cellId, PV->RHO) = a_pvariable(nghbrId, PV->RHO);
20815 a_pvariable(cellId, PV->P) = a_pvariable(nghbrId, PV->P);
20819 for(
MInt n = 0; n < noNCells; n++) {
20820 tmpVars.
p[n * 2 + 0] = F0;
20821 tmpVars.
p[n * 2 + 1] = F0;
20822 for(
MInt d = 0; d < nDim; d++) {
20823 MInt nghbrId = NNghbrs2.
p[n * nDim + d];
20824 tmpVars.
p[n * 2 + 0] += a_pvariable(nghbrId, PV->RHO) * NFactors.
p[n * nDim + d];
20825 tmpVars.
p[n * 2 + 1] += a_pvariable(nghbrId, PV->P) * NFactors.
p[n * nDim + d];
20828 for(
MInt n = 0; n < noNCells; n++) {
20829 MInt cellId = NCells.
p[n];
20830 a_pvariable(cellId, PV->RHO) = tmpVars.
p[n * 2 + 0];
20831 a_pvariable(cellId, PV->P) = tmpVars.
p[n * 2 + 1];
20837 for(
MInt g = 0; g < noGapCells; g++) {
20838 MInt cellId = gapCells.
p[g];
20839 if(a_isHalo(cellId))
continue;
20840 for(
MInt var = 0; var < m_noPVars; var++) {
20841 tmp[var] = a_pvariable(cellId, var);
20842 a_pvariable(cellId, var) = F0;
20844 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20845 MInt nghbrId = c_neighborId(cellId, dir);
20846 for(
MInt var = 0; var < m_noPVars; var++) {
20847 a_pvariable(cellId, var) += a_pvariable(nghbrId, var) / m_noDirs;
20850 for(
MInt var = 0; var < m_noPVars; var++) {
20851 a_pvariable(cellId, var) = (F1 - lambdaRelax) * tmp[var] + lambdaRelax * a_pvariable(cellId, var);
20852 resL2[var] +=
POW2(a_pvariable(cellId, var) - tmp[var]);
20853 resMax[var] =
mMax(resMax[var], fabs(a_pvariable(cellId, var) - tmp[var]));
20857 for(
MInt var = 0; var < m_noPVars; var++) {
20858 resL2[var] = sqrt(resL2[var]);
20861 if((backupSteps - step) % (backupSteps / 10) == 0) {
20862 m_log <<
" * " << 100 * (backupSteps - step) / backupSteps <<
" % - residual (L2) rho: " << resL2[PV->RHO]
20863 <<
" - residual (max) rho: " << resMax[PV->RHO] << endl;
20869 <<
" % - residual (L2) rho: " << resL2[PV->RHO] <<
" - residual (max) rho: " << resMax[PV->RHO] << endl;
20871 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20872 MInt sendBufferCounter = 0;
20873 for(
MInt j = 0; j < noExchangeWindowCells[i]; j++) {
20874 MInt cellId = windowCellId(i, exchangeWindowCells(i, j));
20875 memcpy((
void*)&m_sendBuffers[i][sendBufferCounter], (
void*)&a_pvariable(cellId, 0),
20876 m_dataBlockSize *
sizeof(
MFloat));
20877 sendBufferCounter += m_dataBlockSize;
20881 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20882 MInt bufSize = noExchangeWindowCells[i] * m_dataBlockSize;
20883 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
20884 "m_sendBuffers[i]");
20887 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20888 MInt bufSize = noExchangeHaloCells[i] * m_dataBlockSize;
20889 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &status, AT_,
20890 "m_receiveBuffers[i]");
20892 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20893 MPI_Wait(&g_mpiRequestMb[i], &status, AT_);
20896 for(
MInt i = 0; i < noNeighborDomains(); i++) {
20897 MInt receiveBufferCounter = 0;
20898 for(
MInt j = 0; j < noExchangeHaloCells[i]; j++) {
20899 MInt cellId = haloCellId(i, exchangeHaloCells(i, j));
20900 memcpy((
void*)&a_pvariable(cellId, 0), (
void*)&m_receiveBuffers[i][receiveBufferCounter],
20901 m_dataBlockSize *
sizeof(
MFloat));
20902 receiveBufferCounter += m_dataBlockSize;
20907 deleteNeighbourLinks();
20909 for(
MInt g = 0; g < noGapCells; g++) {
20910 MInt cellId = gapCells.
p[g];
20912 setConservativeVariables(cellId);
20914 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
20915 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
20918 if(m_dualTimeStepping) {
20919 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
20920 a_dt2Variable(cellId, varId) = a_variable(cellId, varId);
20921 a_dt1Variable(cellId, varId) = a_variable(cellId, varId);
20925 if(c_isLeafCell(cellId)) {
20926 a_hasProperty(cellId, SolverCell::IsFlux) =
true;
20927 a_hasProperty(cellId, SolverCell::IsActive) =
true;
20928 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
20940template <MInt nDim,
class SysEqn>
20944 m_log <<
"Generating FV boundary cells..." << endl;
20946 if(m_generateOuterBndryCells) {
20950 if(!m_constructGField) {
20951 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
20952 const MFloat limitDistance = c_cellLengthAtLevel(a_level(cellId) + 1) * sqrt(nDim) + 0.0001;
20953 if(a_levelSetValuesMb(cellId, 0) < F0 && a_levelSetValuesMb(cellId, 0) > -limitDistance) {
20957 MBool needsCheck =
false;
20958 for(
MInt dir = 0; dir < m_noDirs; dir++) {
20959 if(a_hasNeighbor(cellId, dir,
false))
continue;
20960 if(c_parentId(cellId) > -1 && a_hasNeighbor(c_parentId(cellId), dir,
false))
continue;
20964 if(!needsCheck)
continue;
20965 MInt noActiveCorners = returnNoActiveCorners(cellId);
20966 if(noActiveCorners > 0) {
20967 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
20968 if(c_noChildren(cellId) == 0 && c_isLeafCell(cellId)) {
20969 a_hasProperty(cellId, SolverCell::IsActive) =
true;
20970 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
20978 exchangeD.
fill(-1);
20979 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
20980 exchangeD(cellId, 0) = (
MInt)a_hasProperty(cellId, SolverCell::IsInactive);
20981 exchangeD(cellId, 1) = (
MInt)a_hasProperty(cellId, SolverCell::IsActive);
20982 exchangeD(cellId, 2) = (
MInt)a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel);
20985 exchangeDataFV(&exchangeD(0), 3,
false);
20987 for(
MInt cellId = noInternalCells(); cellId < c_noCells(); cellId++) {
20988 a_hasProperty(cellId, SolverCell::IsInactive) = (
MBool)exchangeD(cellId, 0);
20989 a_hasProperty(cellId, SolverCell::IsActive) = (
MBool)exchangeD(cellId, 1);
20990 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) = (
MBool)exchangeD(cellId, 2);
20993 if(grid().azimuthalPeriodicity()) {
20995 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
20996 for(
MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
20997 MInt cellId = grid().azimuthalHaloCell(i, j);
20998 const MFloat limitDistance = c_cellLengthAtLevel(a_level(cellId) + 1) * sqrt(nDim) + 0.0001;
20999 if(a_levelSetValuesMb(cellId, 0) < F0 && a_levelSetValuesMb(cellId, 0) > -limitDistance) {
21003 MBool needsCheck =
false;
21004 for(
MInt dir = 0; dir < m_noDirs; dir++) {
21005 if(a_hasNeighbor(cellId, dir,
false))
continue;
21006 if(c_parentId(cellId) > -1 && a_hasNeighbor(c_parentId(cellId), dir,
false))
continue;
21010 if(!needsCheck)
continue;
21011 MInt noActiveCorners = returnNoActiveCorners(cellId);
21012 if(noActiveCorners > 0) {
21013 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
21014 if(c_noChildren(cellId) == 0 && c_isLeafCell(cellId)) {
21015 a_hasProperty(cellId, SolverCell::IsActive) =
true;
21016 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
21027 createBoundaryCells();
21029 m_fvBndryCnd->generateBndryCells();
21031 ASSERT(a_noCells() == c_noCells(),
"");
21034#if defined _MB_DEBUG_ || !defined NDEBUG
21035 MInt noOuterBoundaryCells = m_fvBndryCnd->m_bndryCells->size();
21036 m_log << noOuterBoundaryCells <<
" boundary cells created" << endl;
21037 MPI_Allreduce(MPI_IN_PLACE, &noOuterBoundaryCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
21038 "noOuterBoundaryCells");
21039 cerr0 <<
"No of outer-boundary-Cells: " << noOuterBoundaryCells << endl;
21051template <MInt nDim,
class SysEqn>
21055 MInt nghbrIds[m_noCorners];
21056 MFloat lsValues[m_noCorners];
21057 MInt noActiveCorners = 0;
21058 const MInt nodeStencil[3][8] = {{0, 1, 0, 1, 0, 1, 0, 1}, {2, 2, 3, 3, 2, 2, 3, 3}, {4, 4, 4, 4, 5, 5, 5, 5}};
21059 std::set<std::pair<MInt, MInt>> nghbrSet;
21061 for(
MInt node = 0; node < m_noCorners; node++) {
21064 nghbrSet.insert(std::make_pair(cellId, node));
21066 for(
MInt i = 0; i < nDim; i++) {
21067 MInt firstDir = nodeStencil[i][node];
21068 MInt firstNghbrId = c_neighborId(cellId, firstDir);
21069 if(firstNghbrId > -1) {
21070 nghbrSet.insert(make_pair(firstNghbrId, node));
21071 for(
MInt j = 0; j < nDim; j++) {
21072 MInt secondDir = nodeStencil[j][node];
21073 if(secondDir == firstDir)
continue;
21074 MInt secondNghbrId = c_neighborId(firstNghbrId, secondDir);
21075 if(secondNghbrId > -1) {
21076 nghbrSet.insert(make_pair(secondNghbrId, node));
21077 IF_CONSTEXPR(nDim == 3) {
21078 for(
MInt k = 0; k < nDim; k++) {
21079 MInt thirdDir = nodeStencil[k][node];
21080 if(thirdDir == firstDir || thirdDir == secondDir)
continue;
21081 MInt thirdNghbrId = c_neighborId(secondNghbrId, thirdDir);
21082 if(thirdNghbrId > -1) {
21083 nghbrSet.insert(make_pair(thirdNghbrId, node));
21095 MInt noNeighborsPerNode = 0;
21096 for(
const auto& it : nghbrSet) {
21097 nghbrIds[noNeighborsPerNode] = it.first;
21098 noNeighborsPerNode++;
21104 for(
MInt nghbrNode = 0; nghbrNode < noNeighborsPerNode; nghbrNode++) {
21105 phi += a_levelSetValuesMb(nghbrIds[nghbrNode], 0);
21107 phi /= noNeighborsPerNode;
21108 lsValues[node] = phi;
21112 for(
MInt node = 0; node < m_noCorners; node++) {
21113 if(lsValues[node] > F0) {
21117 ASSERT(noActiveCorners >= 0 && noActiveCorners <= m_noCorners,
" ");
21119 return noActiveCorners;
21127template <MInt nDim,
class SysEqn>
21131 const MInt noSrfcs = a_noSurfaces();
21133 for(
MInt s = m_bndrySurfacesOffset; s < noSrfcs; s++) {
21134 for(
MInt i = 0; i < nDim; i++) {
21135 a_surfaceDeltaX(s, i) = a_surfaceCoordinate(s, i) - a_coordinate(a_surfaceNghbrCellId(s, 0), i);
21136 a_surfaceDeltaX(s, nDim + i) = a_surfaceCoordinate(s, i) - a_coordinate(a_surfaceNghbrCellId(s, 1), i);
21146template <MInt nDim,
class SysEqn>
21151 for(
MInt i = 0; i < nDim; i++) {
21152 a_surfaceDeltaX(srfcId, i) = a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 0), i);
21153 a_surfaceDeltaX(srfcId, nDim + i) =
21154 a_surfaceCoordinate(srfcId, i) - a_coordinate(a_surfaceNghbrCellId(srfcId, 1), i);
21155 fac0 +=
POW2(a_surfaceDeltaX(srfcId, i));
21156 fac1 +=
POW2(a_surfaceDeltaX(srfcId, nDim + i));
21160 IF_CONSTEXPR(nDim == 3) {
21161 a_surfaceFactor(srfcId, 0) = fac1 / (fac0 + fac1);
21162 a_surfaceFactor(srfcId, 1) = F1 - a_surfaceFactor(srfcId, 0);
21167template <MInt nDim,
class SysEqn>
21169 ASSERT(exId > -1 && exId < m_extractedCells->size() && node > -1 && node <
IPOW2(nDim),
"");
21171 MInt cellId = m_extractedCells->a[exId].m_cellId;
21172 MInt bndryId = a_bndryId(cellId);
21173 if(bndryId < 0)
return false;
21175 if(bndryId < m_noOuterBndryCells) {
21178 return m_pointIsInside[bndryId][IDX_LSSETMB(node, 0)];
21187template <MInt nDim,
class SysEqn>
21189 cerr <<
"FvMbCartesianSolverXD::computeForceCoefficients(..) is empty. " << forceCoefficients[0] << endl;
21197template <MInt nDim,
class SysEqn>
21201 MInt noCells = m_fvBndryCnd->m_bndryCells->size();
21202 MFloat epsilon = pow(10.0, -13.0);
21203 m_fvBndryCnd->m_noBoundarySurfaces = m_noOuterBoundarySurfaces;
21205 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noCells; bndryId++) {
21206 for(
MInt srfc = 0; srfc < FvBndryCell<nDim, SysEqn>::m_maxNoSurfaces; srfc++) {
21207 for(
MInt i = 0; i < nDim; i++) {
21208 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] = -1;
21211 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
21213 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
21214 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
21215 if(a_isHalo(cellId))
continue;
21216 if(a_isPeriodic(cellId))
continue;
21218 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId > -1) {
21219 cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_linkedCellId;
21222 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
21223 const MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
21224 if(a_hasProperty(cellId, SolverCell::IsSplitChild)
21225 || (c_noChildren(cellId) == 0 && a_level(cellId) <= maxRefinementLevel())
21226 || (c_noChildren(cellId) > 0 && a_level(cellId) == maxRefinementLevel())) {
21228 for(
MInt i = 0; i < nDim; i++) {
21231 if(fabs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i]) > epsilon) {
21232 m_surfaces.append();
21233 const MInt srfcId = a_noSurfaces() - 1;
21236 m_fvBndryCnd->m_boundarySurfaces[m_fvBndryCnd->m_noBoundarySurfaces] = srfcId;
21237 m_fvBndryCnd->m_noBoundarySurfaces++;
21240 a_surfaceBndryCndId(srfcId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bndryCndId;
21243 for(
MInt j = 0; j < nDim; j++) {
21244 a_surfaceCoordinate(srfcId, j) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[j];
21248 a_surfaceArea(srfcId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area
21249 * fabs(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i]);
21251 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[i] = srfcId;
21253 if(a_surfaceArea(srfcId) < F0) {
21254 cerr <<
"Warning: negative surface area of surface " << srfcId <<
" at time step " <<
globalTimeStep
21255 <<
" !!!!!!" << endl;
21259 a_surfaceOrientation(srfcId) = i;
21260 a_surfaceUpwindCoefficient(srfcId) = m_globalUpwindCoefficient;
21263 for(
MInt k = 0; k < nDim; k++) {
21265 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[k]
21266 * (a_coordinate(cellId, k) - m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[k]);
21269 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i] > F0) {
21270 a_surfaceNghbrCellId(srfcId, 0) = ghostCellId;
21271 a_surfaceNghbrCellId(srfcId, 1) = cellId;
21272 a_surfaceFactor(srfcId, 0) = F1B2;
21273 a_surfaceFactor(srfcId, 1) = F1B2;
21275 a_surfaceNghbrCellId(srfcId, 1) = ghostCellId;
21276 a_surfaceNghbrCellId(srfcId, 0) = cellId;
21277 a_surfaceFactor(srfcId, 1) = F1B2;
21278 a_surfaceFactor(srfcId, 0) = F1B2;
21281 for(
MInt k = 0; k < nDim; k++) {
21282 a_surfaceDeltaX(srfcId, k) =
21283 a_surfaceCoordinate(srfcId, k) - a_coordinate(a_surfaceNghbrCellId(srfcId, 0), k);
21284 a_surfaceDeltaX(srfcId, nDim + k) =
21285 a_surfaceCoordinate(srfcId, k) - a_coordinate(a_surfaceNghbrCellId(srfcId, 1), k);
21299template <MInt nDim,
class SysEqn>
21303 std::fill(&a_slope(0, 0, 0), &a_slope(0, 0, 0) + a_noCells() * m_noPVars * nDim, F0);
21311template <MInt nDim,
class SysEqn>
21315 leastSquaresReconstruction();
21323template <MInt nDim,
class SysEqn>
21328 globalSignal.
p[0] = signal;
21329 MPI_Bcast(globalSignal.
getPointer(), 1, MPI_INT, sender, mpiComm(), AT_,
"globalSignal.getPointer()");
21331 return globalSignal.
p[0];
21340template <MInt nDim,
class SysEqn>
21345 if(m_engineSetup && m_solutionInterval > 0) {
21346 crankAngleSolutionOutput();
21349 MBool& firstRun = m_static_saveSolverSolutionxd_firstRun;
21350 if(m_restartFile) firstRun =
false;
21352 if(m_bodySamplingInterval > 0 &&
globalTimeStep % m_bodySamplingInterval == 0) {
21355 if(m_particleSamplingInterval > 0 &&
globalTimeStep % m_particleSamplingInterval == 0) {
21356 saveParticleSamples();
21360 if(m_initialCondition == 15 || m_initialCondition == 16) {
21361 computeFlowStatistics(
false);
21364 if((m_dragOutputInterval > 0) && (
globalTimeStep % m_dragOutputInterval) == 0 && m_noEmbeddedBodies > 0) {
21365 if(m_writeCenterLineData) {
21367 writeCenterLineVel(fileName.c_str());
21370 MFloat bodyRotation[3] = {F0, F0, F0};
21372 getBodyRotation(0, bodyRotation);
21373 computeBodySurfaceData(&pressureForce[0]);
21374 printDynamicCoefficients(firstRun, &pressureForce[0]);
21375 if(m_recordBodyData) recordBodyData(firstRun);
21379 if(((noComputedTimeSteps % m_solutionInterval) == 0 &&
globalTimeStep >= m_solutionOffset && m_solutionInterval > -1)
21380 || forceOutput || (m_solutionTimeSteps.count(
globalTimeStep) > 0)) {
21381 writeVtkXmlFiles(
"QOUT",
"GEOM", !forceOutput, m_solutionDiverged);
21383 mTerm(1, AT_,
"NETCDF output not defined, see FvMbCartesianSolverXD::saveGridFlowVariablesMB");
21391template <MInt nDim,
class SysEqn>
21397 MFloat forceCoeffs[3] = {F0, F0, F0};
21398 MFloat pressureForceCoeffs[3] = {F0, F0, F0};
21399 MFloat momentCoeffs[3] = {F0, F0, F0};
21400 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
21401 forceCoeffs[spaceId] = m_hydroForce[bodyId * nDim + spaceId] / (F1B2 * m_rhoU2);
21402 IF_CONSTEXPR(nDim == 2) {
21403 forceCoeffs[spaceId] /= m_bodyDiameter[bodyId];
21404 pressureForceCoeffs[spaceId] = pressureForce[bodyId * nDim + spaceId] / m_bodyDiameter[bodyId];
21406 else IF_CONSTEXPR(nDim == 3) {
21407 forceCoeffs[spaceId] /= PI *
POW2(F1B2 * m_bodyDiameter[bodyId]);
21408 pressureForceCoeffs[spaceId] =
21409 pressureForce[bodyId * nDim + spaceId] / (PI *
POW2(F1B2 * m_bodyDiameter[bodyId]));
21412 for(
MInt i = 0; i < 3; i++) {
21413 momentCoeffs[i] = m_bodyTorque[bodyId * 3 + i] / (F1B2 * m_rhoU2);
21414 IF_CONSTEXPR(nDim == 2) { momentCoeffs[i] /= m_bodyDiameter[bodyId]; }
21415 else IF_CONSTEXPR(nDim == 3) {
21416 momentCoeffs[i] /= PI *
POW3(F1B2 * m_bodyDiameter[bodyId]);
21421 if(!m_multipleFvSolver) {
21422 surname =
"forceCoef";
21424 surname =
"forceCoef_s" + to_string(solverId());
21428 if(domainId() == 0) {
21430 MString surnameBAK = surname +
"_BAK";
21431 MString surnameBAK0 = surname +
"_BAK0";
21432 MString surnameBAK1 = surname +
"_BAK1";
21433 MString surnameBAK2 = surname +
"_BAK2";
21434 rename(surnameBAK1.c_str(), surnameBAK2.c_str());
21435 rename(surnameBAK0.c_str(), surnameBAK1.c_str());
21436 rename(surnameBAK.c_str(), surnameBAK0.c_str());
21437 rename(surname.c_str(), surnameBAK.c_str());
21438 ofl.open(surname.c_str(), ios_base::out | ios_base::trunc);
21439 ofl <<
"# Header valid for nDim = 3" << endl;
21440 ofl <<
"#1:ts 2:tf 3:t 4-6:forceCoeffs 7-9:momentCoeffs 10-12:pressureForceCoeffs";
21443 ofl.open(surname.c_str(), ios_base::out | ios_base::app);
21445 if(ofl.is_open() && ofl.good()) {
21446 ofl << setprecision(8) <<
globalTimeStep <<
" " << m_physicalTime <<
" " << m_time <<
" ";
21447 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
21448 ofl << forceCoeffs[spaceId] <<
" ";
21450 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
21451 ofl << momentCoeffs[spaceId] <<
" ";
21453 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
21454 ofl << pressureForceCoeffs[spaceId] <<
" ";
21462template <MInt nDim,
class SysEqn>
21468 if(!m_multipleFvSolver) {
21469 surname =
"bodyPosition";
21471 surname =
"bodyPosition_s" + to_string(solverId());
21474 if(domainId() == 0) {
21476 MString surnameBAK = surname +
"_BAK";
21477 MString surnameBAK0 = surname +
"_BAK0";
21478 MString surnameBAK1 = surname +
"_BAK1";
21479 MString surnameBAK2 = surname +
"_BAK2";
21480 rename(surnameBAK1.c_str(), surnameBAK2.c_str());
21481 rename(surnameBAK0.c_str(), surnameBAK1.c_str());
21482 rename(surnameBAK.c_str(), surnameBAK0.c_str());
21483 rename(surname.c_str(), surnameBAK.c_str());
21484 ofl.open(surname.c_str(), ios_base::out | ios_base::trunc);
21485 ofl <<
"# 1:ts 2:tf 3:t 4-6:bodyCenter 7-9:bodyVelocity 10-12:bodyOrientation 13-15: bodyAngularVelocity";
21487 ofl <<
"# For more than 2 bodies, the output is performed for the first two bodies" << endl;
21488 ofl <<
"# (>2bodies) 16-18:bodyCenter 19-21:bodyVelocity 22-24:bodyOrientation 25-27: bodyAngularVelocity";
21491 ofl.open(surname.c_str(), ios_base::out | ios_base::app);
21493 if(ofl.is_open() && ofl.good()) {
21494 ofl << setprecision(8) <<
globalTimeStep <<
" " << m_physicalTime <<
" " << m_time <<
" ";
21496 MFloat tmp[3] = {F0, F0, F1};
21498 for(
MInt k = 0; k <
mMin(2, m_noEmbeddedBodies); k++) {
21499 computeRotationMatrix(R, &(m_bodyQuaternion[4 * k]));
21500 matrixVectorProductTranspose(zHat, R, tmp);
21501 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
21502 ofl << m_bodyCenter[k * nDim + spaceId] <<
" ";
21504 for(
MInt spaceId = 0; spaceId < nDim; spaceId++) {
21505 ofl << m_bodyVelocity[k * nDim + spaceId] <<
" ";
21507 for(
MInt spaceId = 0; spaceId < 3; spaceId++) {
21508 ofl << zHat[spaceId] <<
" ";
21510 for(
MInt spaceId = 0; spaceId < 3; spaceId++) {
21511 ofl << m_bodyAngularVelocity[k * 3 + spaceId] <<
" ";
21525template <MInt nDim,
class SysEqn>
21528 NEW_TIMER_GROUP(t_statistics,
"statistics");
21529 NEW_TIMER(t_timertotal,
"statistics", t_statistics);
21530 NEW_SUB_TIMER(t_slip,
"slip", t_timertotal);
21531 NEW_SUB_TIMER(t_states,
"states", t_timertotal);
21532 NEW_SUB_TIMER(t_odf,
"odf", t_timertotal);
21533 NEW_SUB_TIMER(t_pdf,
"pdf", t_timertotal);
21534 NEW_SUB_TIMER(t_near,
"near", t_timertotal);
21535 NEW_SUB_TIMER(t_near_bodydat,
"near_bodydat", t_near);
21536 NEW_SUB_TIMER(t_near_bodydat2,
"near_bodydat2", t_near);
21537 NEW_SUB_TIMER(t_near_output,
"near_output", t_near);
21538 NEW_SUB_TIMER(t_fft,
"fft", t_timertotal);
21540 TERMM_IF_COND(m_reConstSVDWeightMode == 3 || m_reConstSVDWeightMode == 4,
"Not yet implemented!");
21543 auto getIntProp = [&](
const char* name,
const MInt defaultValue) {
21544 return (
Context::propertyExists(name, 0)) ? Context::getSolverProperty<MInt>(name, m_solverId, AT_) : defaultValue;
21548 const MInt statsInterval = getIntProp(
"statsInterval", m_dragOutputInterval);
21549 const MInt pdfInterval = getIntProp(
"pdfInterval", 0);
21550 const MInt angleInterval = getIntProp(
"angleInterval", 0);
21551 const MInt nearBodyInterval = getIntProp(
"nearBodyInterval", 0);
21552 const MInt scatterInterval = getIntProp(
"scatterInterval", 0);
21553 const MInt fftInterval = getIntProp(
"fftInterval", 0);
21558 MBool outputSlipStats = (m_saveSlipInterval > 0 &&
globalTimeStep % m_saveSlipInterval == 0);
21561 MBool computeNearBody = (nearBodyInterval > 0 &&
globalTimeStep % nearBodyInterval == 0);
21566 MBool forceOutput =
false;
21569 for(
MInt k = 0; k < cnt; k++) {
21570 MInt ts = Context::getSolverProperty<MInt>(
"forceFVMBStatistics", m_solverId, AT_, k);
21571 m_forceFVMBStatistics.push_back(ts);
21574 for(
MUint i = 0; i < m_forceFVMBStatistics.size(); i++) {
21575 if(
globalTimeStep == m_forceFVMBStatistics[i]) forceOutput =
true;
21578 if(forceOutput ==
true) {
21579 computeStats = (statsInterval > 0);
21580 computeSlipStats = (m_slipInterval > 0);
21581 outputSlipStats = (m_saveSlipInterval > 0);
21582 computePdf = (pdfInterval > 0);
21583 computeAngles = (angleInterval > 0);
21584 computeNearBody = (nearBodyInterval > 0);
21585 computeScatter = (scatterInterval > 0);
21586 computeFFT = (fftInterval > 0);
21590 if(computePdf || computeSlipStats || computeAngles || computeNearBody || computeScatter || computeFFT || force)
21591 computeStats =
true;
21593 if(!computeStats)
return;
21595 if(domainId() == 0) {
21597 <<
"computeStats " << computeStats <<
" "
21598 <<
"computeSlipStats " << computeSlipStats <<
" "
21599 <<
"outputSlipStats " << outputSlipStats <<
" "
21600 <<
"computePdf " << computePdf <<
" "
21601 <<
"computeAngles " << computeAngles <<
" "
21602 <<
"computeNearBody " << computeNearBody <<
" "
21603 <<
"computeScatter " << computeScatter <<
" "
21604 <<
"computeFFT " << computeFFT << endl;
21607 RECORD_TIMER_START(t_timertotal);
21608 leastSquaresReconstruction();
21609 RECORD_TIMER_START(t_slip);
21610 MInt noParticles = 0;
21611 if(m_noPointParticles > 0)
21612 noParticles = m_noPointParticlesLocal;
21613 else if(m_noEmbeddedBodies > 0)
21614 noParticles = m_noEmbeddedBodies;
21615 const MBool computeBodyVol =
true;
21619 MFloat* velGradient =
nullptr;
21620 MFloat* quats =
nullptr;
21622 MFloat* pvelDt1 =
nullptr;
21623 MFloat* protVelHat =
nullptr;
21624 MFloat* protVelHatDt1 =
nullptr;
21625 MFloat* nearBodyState =
nullptr;
21626 MFloat* pRadii =
nullptr;
21627 MFloat* pTemperature =
nullptr;
21628 const MInt noNearBodyState = 5;
21636 MFloatScratchSpace particleFluidRotation(
mMax(1, m_noEmbeddedBodies), nDim, AT_,
"particleFluidRotation");
21639 MIntScratchSpace nearestBodies((m_noPointParticles > 0 ? 1 : m_maxNearestBodies * a_noCells()), AT_,
"nearestBodies");
21640 MFloatScratchSpace nearestDist((m_noPointParticles > 0 ? 1 : m_maxNearestBodies * a_noCells()), AT_,
"nearestDist");
21641 MFloatScratchSpace nearestFac((m_noPointParticles > 0 ? 1 : m_maxNearestBodies * a_noCells()), AT_,
"nearestFac");
21642 const MFloat maxDistConstruct = (m_noEmbeddedBodies <= 0 ? -1 : 5.0 * m_bodyDiameter[0]);
21644 skipParticle.
fill(0);
21645 if(m_noPointParticles > 0) {
21646 setParticleFluidVelocities(&(particleFluidPressure[0]));
21647 vel = &(m_particleVelocityFluid[0]);
21648 velGradient = &(m_particleVelocityGradientFluid[0]);
21649 quats = &(m_particleQuaternions[0]);
21650 pvel = &(m_particleVelocity[0]);
21651 pvelDt1 = &(m_particleVelocityDt1[0]);
21652 protVelHat = &(m_particleAngularVelocity[0]);
21653 protVelHatDt1 = &(m_particleAngularVelocityDt1[0]);
21654 pRadii = &(m_particleRadii[0]);
21655 pTemperature = &(m_particleTemperature[0]);
21656 }
else if(m_noEmbeddedBodies > 0) {
21657 MInt maxBodyCnt = 0;
21658 nearestBodies.
fill(-1);
21659 nearestDist.
fill(numeric_limits<MFloat>::max());
21660 maxBodyCnt = constructDistance(maxDistConstruct, nearestBodies, nearestDist);
21661 if(maxBodyCnt > m_maxNearestBodies) {
21662 cerr <<
"constructDistance: maxBodyCnt " << maxBodyCnt <<
" exceeds m_maxNearestBodies " << m_maxNearestBodies
21663 <<
" computeNearBodyFluidVelocity will be affected in the statistics on domainId " << domainId() << endl;
21665 const MFloat minDist = 2.0;
21666 const MFloat maxDist = minDist + 1.0;
21667 constexpr MFloat maxAngleVel = 0.0;
21668 constexpr MFloat maxAngleRot = 0.0;
21669 vector<MFloat> setup = {minDist, maxDist, maxAngleVel, maxAngleRot};
21670 if(computePdf || computeNearBody) {
21671 computeNearBodyFluidVelocity(nearestBodies, nearestDist, &velMem[0], &velGradMem[0], &particleFluidRotation[0],
21672 setup, &skipParticle[0], &nbStateMem[0], &particleFluidPressure[0], &nearestFac[0]);
21674 computeNearBodyFluidVelocity(nearestBodies, nearestDist, &velMem[0], &velGradMem[0], &particleFluidRotation[0],
21675 setup, &skipParticle[0]);
21677 quats = &(m_bodyQuaternion[0]);
21678 pvel = &(m_bodyVelocity[0]);
21679 pvelDt1 = &(m_bodyVelocityDt1[0]);
21680 protVelHat = &(protVelHatMem[0]);
21681 protVelHatDt1 = &(protVelHatMemDt1[0]);
21683 velGradient = &velGradMem[0];
21685 nearBodyState = &nbStateMem[0];
21686 pRadii = &(m_bodyRadii[0]);
21687 pTemperature = &(m_bodyTemperature[0]);
21691 if(m_noEmbeddedBodies > 0) {
21692 for(
MInt p = 0; p < noParticles; p++) {
21701 for(
MInt i = 0; i < nDim; i++) {
21702 MInt id0 = (i + 1) % 3;
21703 MInt id1 = (id0 + 1) % 3;
21704 qiRotFluid[i] = F1B2 * (velGradient[9 * p + 3 * id1 + id0] - velGradient[9 * p + 3 * id0 + id1]);
21705 qiShear[i] = F1B2 * (velGradient[9 * p + 3 * id1 + id0] + velGradient[9 * p + 3 * id0 + id1]);
21706 qiRotvel[i] = m_bodyAngularVelocity[3 * p + i];
21707 qiRotvelDt1[i] = m_bodyAngularVelocityDt1[3 * p + i];
21710 computeRotationMatrix(R, &(quats[4 * p]));
21711 matrixVectorProduct(qbRot, R, qiRotFluid);
21712 matrixVectorProduct(qbShear, R, qiShear);
21713 matrixVectorProduct(qbRotvel, R, qiRotvel);
21714 matrixVectorProduct(qbRotvelDt1, R, qiRotvelDt1);
21715 for(
MInt i = 0; i < nDim; i++) {
21716 pOmegaHat[p * nDim + i] = qbRot[i];
21717 velShearHat[p * nDim + i] = qbShear[i];
21718 protVelHat[p * nDim + i] = qbRotvel[i];
21719 protVelHatDt1[p * nDim + i] = qbRotvelDt1[i];
21723 for(
MInt p = 0; p < noParticles; p++) {
21724 for(
MInt i = 0; i < nDim; i++) {
21725 MInt id0 = (i + 1) % 3;
21726 MInt id1 = (id0 + 1) % 3;
21727 pOmegaHat[p * nDim + i] = F1B2 * (velGradient[9 * p + 3 * id1 + id0] - velGradient[9 * p + 3 * id0 + id1]);
21728 velShearHat[p * nDim + i] = F1B2 * (velGradient[9 * p + 3 * id1 + id0] + velGradient[9 * p + 3 * id0 + id1]);
21733 if(computeSlipStats) computeSlipStatistics(nearestBodies, nearestDist, maxDistConstruct);
21734 if(outputSlipStats) saveParticleSlipData();
21735 RECORD_TIMER_STOP(t_slip);
21737 const MFloat DX = (m_bbox[3] - m_bbox[0]);
21739 if(m_noEmbeddedBodies > 0) {
21740 if(computeBodyVol) {
21741 computeBodyVolume(partVol);
21743 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
21744 partVol[
b] = m_bodyVolume[
b];
21748 for(
MInt p = 0; p < m_noPointParticlesLocal; p++) {
21749 partVol[p] = F4B3 * PI * m_particleRadii[3 * p] * m_particleRadii[3 * p + 1] * m_particleRadii[3 * p + 2];
21753 MInt noLeafCells = 0;
21754 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
21755 if(a_isBndryGhostCell(cellId))
continue;
21756 if(a_isHalo(cellId))
continue;
21757 if(a_isPeriodic(cellId))
continue;
21758 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
21759 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
21760 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
21761 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && a_hasProperty(cellId, SolverCell::IsInactive))
continue;
21762 if(a_bndryId(cellId) < 0 && a_levelSetValuesMb(cellId, 0) < F0) cerr <<
"warn: neg LS " << endl;
21763 leafCells(noLeafCells++) = cellId;
21765 RECORD_TIMER_START(t_states);
21766 vector<MFloat> eKinFlowDataMean(17, F0);
21768 for(
MInt stat = 0; stat < m_noMeanStatistics; stat++) {
21769 const MFloat refRadius = (noParticles > 0 ? pow(pRadii[0] * pRadii[1] * pRadii[2], F1B3) : 0);
21771 for(
MInt c = 0; c < noLeafCells; c++) {
21772 MInt cellId = leafCells(c);
21773 MFloat volume = a_cellVolume(cellId);
21774 if(volume < 1e-14)
continue;
21775 if(stat > 0 && a_levelSetValuesMb(cellId, 0) < m_distThresholdStat[stat] * refRadius)
continue;
21780 for(
MInt i = 0; i < nDim; i++) {
21781 U2 +=
POW2(a_variable(cellId, CV->RHO_VV[i]) / a_variable(cellId, CV->RHO));
21782 U20 +=
POW2(a_oldVariable(cellId, CV->RHO_VV[i]) / a_oldVariable(cellId, CV->RHO));
21783 w2 +=
POW2(a_slope(cellId, PV->VV[(i + 1) % nDim], (i + 2) % nDim)
21784 - a_slope(cellId, PV->VV[(i + 2) % nDim], (i + 1) % nDim));
21785 s2 +=
POW2(a_slope(cellId, PV->VV[(i + 1) % nDim], (i + 2) % nDim)
21786 + a_slope(cellId, PV->VV[(i + 2) % nDim], (i + 1) % nDim));
21788 MFloat T = sysEqn().temperature_ES(a_pvariable(cellId, PV->RHO), a_pvariable(cellId, PV->P));
21789 MFloat mue = SUTHERLANDLAW(T) / sysEqn().m_Re0;
21792 for(
MInt i = 0; i < nDim; i++) {
21793 div += a_slope(cellId, PV->VV[i], i);
21795 eKinFlowDataMean[0] += F1B2 * volume * U2;
21796 eKinFlowDataMean[1] += F1B2 * volume * a_variable(cellId, CV->RHO) * U2;
21797 eKinFlowDataMean[2] += F1B2 * m_cellVolumesDt1[cellId] * U20;
21798 eKinFlowDataMean[3] += F1B2 * m_cellVolumesDt1[cellId] * a_oldVariable(cellId, CV->RHO) * U20;
21799 eKinFlowDataMean[4] += volume * fabs(div);
21800 eKinFlowDataMean[5] += volume * w2;
21801 for(
MInt i = 0; i < nDim; i++) {
21802 for(
MInt j = 0; j < nDim; j++) {
21803 eKinFlowDataMean[6] += volume * mue * (a_slope(cellId, PV->VV[i], j) + a_slope(cellId, PV->VV[j], i))
21804 * a_slope(cellId, PV->VV[i], j);
21805 eKinFlowDataMean[7] +=
21806 volume * F1B2 * mue *
POW2(a_slope(cellId, PV->VV[i], j) + a_slope(cellId, PV->VV[j], i));
21807 eKinFlowDataMean[8] += volume * mue * a_slope(cellId, PV->VV[i], j) * a_slope(cellId, PV->VV[i], j);
21809 eKinFlowDataMean[9] += volume *
POW2(a_slope(cellId, PV->VV[i], i));
21810 eKinFlowDataMean[10] += volume *
POW3(a_slope(cellId, PV->VV[i], i));
21812 eKinFlowDataMean[11] += volume * mue;
21813 eKinFlowDataMean[12] += volume * a_variable(cellId, CV->RHO);
21814 eKinFlowDataMean[13] += T * volume;
21815 eKinFlowDataMean[14] += volume;
21816 eKinFlowDataMean[15] += volume *
POW2(div);
21817 eKinFlowDataMean[16] += volume *
POW2(a_variable(cellId, CV->RHO));
21819 MPI_Allreduce(MPI_IN_PLACE, eKinFlowDataMean.data(), eKinFlowDataMean.size(), MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
21820 "MPI_IN_PLACE",
"eKinFlowDataMean[0]");
21823 vector<MFloat> eKinPartDataMean(25, F0);
21824 for(
MInt p = 0; p < noParticles; p++) {
21825 eKinPartDataMean[0] += F1;
21826 eKinPartDataMean[1] += partVol[p];
21827 eKinPartDataMean[2] += pvel[p * nDim];
21828 eKinPartDataMean[3] += pvel[p * nDim + 1];
21829 eKinPartDataMean[4] += pvel[p * nDim + 2];
21830 eKinPartDataMean[5] +=
POW2(pvel[p * nDim]);
21831 eKinPartDataMean[6] +=
POW2(pvel[p * nDim + 1]);
21832 eKinPartDataMean[7] +=
POW2(pvel[p * nDim + 2]);
21833 eKinPartDataMean[8] += protVelHat[p * nDim + 0];
21834 eKinPartDataMean[9] += protVelHat[p * nDim + 1];
21835 eKinPartDataMean[10] += protVelHat[p * nDim + 2];
21836 eKinPartDataMean[11] +=
POW2(protVelHat[p * nDim + 0]);
21837 eKinPartDataMean[12] +=
POW2(protVelHat[p * nDim + 1]);
21838 eKinPartDataMean[13] +=
POW2(protVelHat[p * nDim + 2]);
21840 computeRotationMatrix(R, &(quats[4 * p]));
21843 MFloat tmp[3] = {F1, F0, F0};
21845 matrixVectorProductTranspose(zHat, R, tmp);
21846 for(
MInt i = 0; i < nDim; i++) {
21847 zHat[i] /=
mMax(1e-12, sqrt(zHat[0] * zHat[0] + zHat[1] * zHat[1] + zHat[2] * zHat[2]));
21849 eKinPartDataMean[14] += fabs(zHat[2]);
21850 MFloat diameter = F2 * pow(pRadii[3 * p] * pRadii[3 * p + 1] * pRadii[3 * p + 2], F1B3);
21852 for(
MInt i = 0; i < nDim; i++) {
21853 Rep +=
POW2(vel[3 * p + i] - pvel[3 * p + i]);
21855 Rep = sqrt(Rep) * diameter * m_rhoInfinity * sysEqn().m_Re0 / sysEqn().m_muInfinity;
21856 eKinPartDataMean[15] += Rep;
21857 eKinPartDataMean[16] +=
POW2(Rep);
21858 MFloat pmass = partVol[p] * m_densityRatio * m_rhoInfinity;
21859 eKinPartDataMean[17] += pmass;
21860 MFloat momI[3] = {F0, F0, F0};
21861 momI[0] = F1B5 * (
POW2(pRadii[3 * p + 1]) +
POW2(pRadii[3 * p + 2]));
21862 momI[1] = F1B5 * (
POW2(pRadii[3 * p + 0]) +
POW2(pRadii[3 * p + 2]));
21863 momI[2] = F1B5 * (
POW2(pRadii[3 * p + 0]) +
POW2(pRadii[3 * p + 1]));
21864 for(
MInt i = 0; i < nDim; i++) {
21865 eKinPartDataMean[18] += partVol[p] * F1B2 *
POW2(pvel[p * nDim + i]);
21866 eKinPartDataMean[19] += partVol[p] * F1B2 * momI[i] *
POW2(protVelHat[p * nDim + i]);
21867 eKinPartDataMean[20] += partVol[p] * F1B2 *
POW2(pvelDt1[p * nDim + i]);
21868 eKinPartDataMean[21] += partVol[p] * F1B2 * momI[i] *
POW2(protVelHatDt1[p * nDim + i]);
21870 MFloat vrel[3] = {F0, F0, F0};
21871 MFloat omegaRel[3] = {F0, F0, F0};
21872 for(
MInt i = 0; i < nDim; i++) {
21873 vrel[i] = vel[nDim * p + i] - pvel[nDim * p + i];
21874 omegaRel[i] = pOmegaHat[i] - protVelHat[p * 3 + i];
21876 if(m_noEmbeddedBodies > 0) {
21877 eKinPartDataMean[22] += (m_hydroForce[nDim * p + 0] * vrel[0] + m_hydroForce[nDim * p + 1] * vrel[1]
21878 + m_hydroForce[nDim * p + 2] * vrel[2]);
21879 eKinPartDataMean[23] += (m_bodyTorque[nDim * p + 0] * omegaRel[0] + m_bodyTorque[nDim * p + 1] * omegaRel[1]
21880 + m_bodyTorque[nDim * p + 2] * omegaRel[2]);
21882 eKinPartDataMean[22] +=
21884 * (m_particleAcceleration[nDim * p + 0] * vrel[0] + m_particleAcceleration[nDim * p + 1] * vrel[1]
21885 + m_particleAcceleration[nDim * p + 2] * vrel[2]);
21886 eKinPartDataMean[23] += F0;
21888 eKinPartDataMean[24] += pTemperature[p];
21890 if(m_noPointParticles > 0) {
21891 if(domainId() == 0) {
21892 MPI_Reduce(MPI_IN_PLACE, eKinPartDataMean.data(), eKinPartDataMean.size(), MPI_DOUBLE, MPI_SUM, 0, mpiComm(),
21893 AT_,
"MPI_IN_PLACE",
"eKinPartDataMean");
21895 MPI_Reduce(eKinPartDataMean.data(), eKinPartDataMean.data(), eKinPartDataMean.size(), MPI_DOUBLE, MPI_SUM, 0,
21896 mpiComm(), AT_,
"MPI_IN_PLACE",
"eKinPartDataMean");
21900 const MFloat volF = eKinFlowDataMean[14];
21901 const MFloat fluidMass = eKinFlowDataMean[12];
21902 const MFloat volP = eKinPartDataMean[1];
21903 const MFloat totalMass = fluidMass + eKinPartDataMean[17];
21904 const MInt cnt = eKinPartDataMean[0];
21905 const MFloat partLinDiss = eKinPartDataMean[22] /
POW3(DX);
21906 const MFloat partRotDiss = eKinPartDataMean[23] /
POW3(DX);
21907 if(cnt != noParticles) {
21908 cerr <<
"Number of particles in statistics is wrong " << cnt <<
" " << m_noEmbeddedBodies <<
" "
21909 << m_noPointParticles <<
" " << noParticles << endl;
21912 MFloat EkT = eKinFlowDataMean[1] + (eKinPartDataMean[18] + eKinPartDataMean[19]) * m_densityRatio * m_rhoInfinity;
21913 MFloat EkB = (eKinPartDataMean[18] + eKinPartDataMean[19]) / volP;
21915 for(
MUint i = 0; i < eKinFlowDataMean.size(); i++) {
21916 eKinFlowDataMean[i] /= volF;
21918 for(
MUint i = 0; i < eKinPartDataMean.size(); i++) {
21919 eKinPartDataMean[i] /= cnt;
21924 meanState(0) = eKinFlowDataMean[0];
21925 meanState(1) = EkT / totalMass;
21926 meanState(2) = EkB;
21927 meanState(3) = (5.0 * (sysEqn().m_muInfinity / sysEqn().m_Re0) * (eKinFlowDataMean[9] / F3));
21930 m_oldMeanState[stat][0] = meanState(0);
21931 m_oldMeanState[stat][1] = meanState(1);
21932 m_oldMeanState[stat][2] = meanState(2);
21933 m_oldMeanState[stat][3] = meanState(3);
21935 if(domainId() == 0) {
21936 MFloat mue = eKinFlowDataMean[11];
21937 MFloat dudx = eKinFlowDataMean[9];
21938 MFloat eps4 = F5 * mue * dudx;
21939 MFloat skewness = (eKinFlowDataMean[10] / F3) / pow(dudx / F3, F3B2);
21940 MFloat eta = pow(mue, 0.75) / pow(eps4, 0.25);
21941 MFloat lambda = sqrt(F2B3 * eKinFlowDataMean[0]) / sqrt(dudx / F3);
21942 MFloat reLambda = lambda * sqrt(F2B3 * eKinFlowDataMean[0]) * eKinFlowDataMean[12] / mue;
21943 MFloat coupling = m_couplingRate / (volF + volP);
21944 MFloat* termVel =
nullptr;
21945 MFloat defaultTermVel[3] = {F0, F0, F0};
21946 if(m_noPointParticles > 0 && m_particleRadii.size() > 0) {
21947 termVel = m_particleTerminalVelocity;
21948 }
else if(m_noEmbeddedBodies > 0) {
21949 termVel = m_bodyTerminalVelocity;
21951 termVel = defaultTermVel;
21953 const MFloat taup = F2 * m_densityRatio *
POW2(refRadius) / (9.0 * sysEqn().m_muInfinity / sysEqn().m_Re0);
21954 const MFloat epsRef = DX / (
POW3(m_UInfinity));
21956 vector<pair<string, double>> eKinOutput;
21958 eKinOutput.push_back(make_pair(
"t", m_time));
21959 eKinOutput.push_back(make_pair(
"tf", m_physicalTime));
21960 eKinOutput.push_back(make_pair(
"Ek", eKinFlowDataMean[0] /
POW2(m_UInfinity)));
21961 eKinOutput.push_back(make_pair(
"EkB", EkB /
POW2(m_UInfinity)));
21962 eKinOutput.push_back(make_pair(
"EkT", EkT / (
POW2(m_UInfinity) * totalMass)));
21963 eKinOutput.push_back(make_pair(
"-d(Ek)dt", -(meanState(0) - m_oldMeanState[stat][0]) * epsRef
21964 / (timeStep() * m_dragOutputInterval)));
21965 eKinOutput.push_back(make_pair(
"-d(EkB)dt", -(meanState(2) - m_oldMeanState[stat][2]) * epsRef
21966 / (timeStep() * m_dragOutputInterval)));
21967 eKinOutput.push_back(make_pair(
"-d(EkT)dt", -(meanState(1) - m_oldMeanState[stat][1]) * epsRef
21968 / (timeStep() * m_dragOutputInterval)));
21969 eKinOutput.push_back(make_pair(
"divergence", eKinFlowDataMean[4] / m_UInfinity));
21970 eKinOutput.push_back(make_pair(
"divergenceRMS", sqrt(eKinFlowDataMean[15]) / m_UInfinity));
21971 eKinOutput.push_back(make_pair(
"enstrophy", eKinFlowDataMean[5]));
21972 eKinOutput.push_back(make_pair(
"eps", eKinFlowDataMean[6] * epsRef));
21973 eKinOutput.push_back(make_pair(
"eps2", eKinFlowDataMean[7] * epsRef));
21974 eKinOutput.push_back(make_pair(
"eps3", eKinFlowDataMean[8] * epsRef));
21975 eKinOutput.push_back(make_pair(
"eps4", eps4 * epsRef));
21976 eKinOutput.push_back(make_pair(
"skewness", -skewness));
21977 eKinOutput.push_back(make_pair(
"volF", volF /
POW3(DX)));
21978 eKinOutput.push_back(make_pair(
"volP", volP /
POW3(DX)));
21979 eKinOutput.push_back(make_pair(
"volDiff", (
POW3(DX) - volF - volP) /
POW3(DX)));
21980 eKinOutput.push_back(make_pair(
"Kolmogorov-scale", eta / DX));
21981 eKinOutput.push_back(make_pair(
"Taylor-scale", lambda / DX));
21982 eKinOutput.push_back(make_pair(
"ReLambda", reLambda));
21983 eKinOutput.push_back(make_pair(
"Interphase-Momentum-Exchange", coupling * epsRef));
21984 eKinOutput.push_back(make_pair(
"uPMean", eKinPartDataMean[2] / m_Ma));
21985 eKinOutput.push_back(make_pair(
"vPMean", eKinPartDataMean[3] / m_Ma));
21986 eKinOutput.push_back(make_pair(
"wPMean", eKinPartDataMean[4] / m_Ma));
21987 eKinOutput.push_back(make_pair(
"uPRMS", sqrt(eKinPartDataMean[5]) / m_Ma));
21988 eKinOutput.push_back(make_pair(
"vPRMS", sqrt(eKinPartDataMean[6]) / m_Ma));
21989 eKinOutput.push_back(make_pair(
"wPRMS", sqrt(eKinPartDataMean[7]) / m_Ma));
21990 eKinOutput.push_back(make_pair(
"OmegaxPMean", eKinPartDataMean[8]));
21991 eKinOutput.push_back(make_pair(
"OmegayPMean", eKinPartDataMean[9]));
21992 eKinOutput.push_back(make_pair(
"OmegazPMean", eKinPartDataMean[10]));
21993 eKinOutput.push_back(make_pair(
"OmegaxPRMS", sqrt(eKinPartDataMean[11])));
21994 eKinOutput.push_back(make_pair(
"OmegayPRMS", sqrt(eKinPartDataMean[12])));
21995 eKinOutput.push_back(make_pair(
"OmegazPRMS", sqrt(eKinPartDataMean[13])));
21996 eKinOutput.push_back(make_pair(
"thetaMean", eKinPartDataMean[14]));
21997 eKinOutput.push_back(make_pair(
"RepMean", eKinPartDataMean[15]));
21998 eKinOutput.push_back(make_pair(
"RepRMS", sqrt(eKinPartDataMean[16])));
21999 eKinOutput.push_back(make_pair(
"Stokes", taup * sqrt(F5 * dudx)));
22000 eKinOutput.push_back(make_pair(
"Froude", taup *
POW2(termVel[2]) / mue));
22001 eKinOutput.push_back(make_pair(
"mueMean", mue / (sysEqn().m_muInfinity / sysEqn().m_Re0)));
22002 eKinOutput.push_back(make_pair(
"rhoMean", eKinFlowDataMean[12] / m_rhoInfinity));
22003 eKinOutput.push_back(make_pair(
"rhoRMS", sqrt(eKinFlowDataMean[16]) / m_rhoInfinity));
22004 eKinOutput.push_back(make_pair(
"TFluid", eKinFlowDataMean[13] / m_TInfinity));
22005 eKinOutput.push_back(make_pair(
"TPart", eKinPartDataMean[24] / m_TInfinity));
22006 eKinOutput.push_back(make_pair(
"part_lin_diss", partLinDiss * epsRef));
22007 eKinOutput.push_back(make_pair(
"part_rot_diss", partRotDiss * epsRef));
22010 MString suffix = (stat > 0) ?
"_D" + to_string(m_distThresholdStat[stat]) :
"";
22011 suffix.erase(suffix.find_last_not_of(
'0') + 1, std::string::npos);
22012 suffix.erase(suffix.find_last_not_of(
'.') + 1, std::string::npos);
22015 rename((
"kineticEnergy" + suffix +
"_BAK1").c_str(), (
"kineticEnergy" + suffix +
"_BAK2").c_str());
22016 rename((
"kineticEnergy" + suffix +
"_BAK0").c_str(), (
"kineticEnergy" + suffix +
"_BAK1").c_str());
22017 rename((
"kineticEnergy" + suffix +
"_BAK").c_str(), (
"kineticEnergy" + suffix +
"_BAK0").c_str());
22018 rename((
"kineticEnergy" + suffix).c_str(), (
"kineticEnergy" + suffix +
"_BAK").c_str());
22019 ofl.open((
"kineticEnergy" + suffix).c_str(), ios_base::out | ios_base::trunc);
22021 for(
MUint i = 0; i < eKinOutput.size(); i++) {
22022 ofl << i + 1 <<
":" << get<0>(eKinOutput[i]) <<
" ";
22026 ofl.open((
"kineticEnergy" + suffix).c_str(), ios_base::out | ios_base::app);
22028 if(ofl.is_open() && ofl.good()) {
22029 for(
MUint i = 0; i < eKinOutput.size(); i++) {
22030 ofl << get<1>(eKinOutput[i]) <<
" ";
22036 m_oldMeanState[stat][0] = meanState(0);
22037 m_oldMeanState[stat][1] = meanState(1);
22038 m_oldMeanState[stat][2] = meanState(2);
22039 m_oldMeanState[stat][3] = meanState(3);
22041 RECORD_TIMER_STOP(t_states);
22045 IF_CONSTEXPR(nDim == 2)
mTerm(1, AT_,
"computePdf not implemented for 2D!");
22046 RECORD_TIMER_START(t_odf);
22047 const MInt noSamples = 1;
22048 const MInt thetaSize = 100;
22050 const MInt noDat = 64;
22062 thetaDensity.
fill(F0);
22063 thetaDensity2.
fill(F0);
22064 thetaBounds(0) = F0;
22065 thetaBounds2(0) = -F1;
22066 for(
MInt i = 0; i < thetaSize; i++) {
22067 MFloat theta0 = thetaBounds(i);
22068 MFloat theta1 = acos(F1 - ((
MFloat)(i + 1)) * deltaRadius);
22069 MFloat theta02 = thetaBounds2(i);
22070 MFloat theta12 = thetaBounds2(0) + ((
MFloat)(i + 1)) * deltaRadius;
22071 thetaPoints(i) = F1B2 * (theta0 + theta1);
22072 thetaPoints2(i) = F1B2 * (theta02 + theta12);
22073 thetaBounds(i + 1) = theta1;
22074 thetaBounds2(i + 1) = theta12;
22076 thetaBounds(thetaSize) = PI;
22077 thetaBounds2(thetaSize) = F1;
22078 for(
MInt p = 0; p < noParticles; p++) {
22079 if(skipParticle(p))
continue;
22080 vector<MFloat> values;
22081 MFloat fdir[3] = {F0, F0, F0};
22082 MFloat wdir[3] = {F0, F0, F0};
22083 MFloat pdir[3] = {F0, F0, F0};
22084 MFloat rdir[3] = {F0, F0, F0};
22085 MFloat reldir[3] = {F0, F0, F0};
22086 for(
MInt i = 0; i < nDim; i++) {
22087 fdir[i] = vel[nDim * p + i];
22088 wdir[i] = pOmegaHat[nDim * p + i];
22089 pdir[i] = pvel[nDim * p + i];
22090 rdir[i] = protVelHat[nDim * p + i];
22091 reldir[i] = vel[nDim * p + i] - pvel[nDim * p + i];
22099 computeRotationMatrix(R, &(quats[4 * p]));
22102 MFloat tmp[3] = {F1, F0, F0};
22103 matrixVectorProductTranspose(q, R, tmp);
22104 const MFloat qabs = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
22105 for(
MInt i = 0; i < nDim; i++) {
22106 fdir[i] /=
mMax(1e-12, ffabs);
22107 wdir[i] /=
mMax(1e-12, wabs);
22108 pdir[i] /=
mMax(1e-12, pabs);
22109 rdir[i] /=
mMax(1e-12, rabs);
22110 reldir[i] /=
mMax(1e-12, relabs);
22111 q[i] /=
mMax(1e-12, qabs);
22113 matrixVectorProduct(tmp, R, fdir);
22114 values.push_back(q[0]);
22115 values.push_back(q[1]);
22116 values.push_back(q[2]);
22117 values.push_back(tmp[2]);
22118 values.push_back(wdir[2]);
22121 for(
MInt i = 0; i < nDim; i++) {
22122 omegaVel += pdir[i] * fdir[i];
22123 omegaVort += rdir[i] * wdir[i];
22125 values.push_back(omegaVel);
22126 values.push_back(omegaVort);
22127 values.push_back(pdir[0] * q[0] + pdir[1] * q[1] + pdir[2] * q[2]);
22128 values.push_back(reldir[0] * q[0] + reldir[1] * q[1] + reldir[2] * q[2]);
22129 if(m_noEmbeddedBodies > 0)
22130 values.push_back(q[0] * rdir[0] + q[1] * rdir[1] + q[2] * rdir[2]);
22132 values.push_back(rdir[2]);
22135 for(
MUint i = 0; i < values.size(); i++) {
22136 for(
MInt j = 0; j < 4; j++) {
22137 angles[cnt] = acos(values[i]);
22138 angles2[cnt++] = values[i];
22142 const MFloat kernelWidth = 0.05;
22143 const MFloat kernelWidth2 = 0.02;
22144 const MFloat fac = F1 / (kernelWidth);
22145 const MFloat fac2 = F1 / (kernelWidth2);
22146 for(
MInt j = 0; j < noDat; j++) {
22147 for(
MInt i = 0; i < thetaSize; i++) {
22150 if(j % 4 > 1 && i >= thetaSize / 2) ii = thetaSize - i - 1;
22151 if(j % 4 > 1 && i < thetaSize / 2) ii2 = thetaSize - i - 1;
22153 if(angles[j] > thetaBounds(i) && angles[j] < thetaBounds(i + 1)) thetaDensity(ii, j) += F1;
22154 if(angles2[j] > thetaBounds2(i) && angles2[j] < thetaBounds2(i + 1))
22155 thetaDensity2(ii2, j) += F1;
22157 MFloat DA = thetaBounds(thetaSize) - thetaBounds(0);
22158 MFloat DA2 = thetaBounds2(thetaSize) - thetaBounds2(0);
22159 MFloat t = fabs(angles[j] - thetaPoints(i)) / kernelWidth;
22160 t =
mMin(t, fabs(angles[j] + DA - thetaPoints(i)) / kernelWidth);
22161 t =
mMin(t, fabs(angles[j] - DA - thetaPoints(i)) / kernelWidth);
22162 MFloat t2 = fabs(angles2[j] - thetaPoints2(i)) / kernelWidth2;
22163 t2 =
mMin(t2, fabs(angles2[j] + DA2 - thetaPoints2(i)) / kernelWidth2);
22164 t2 =
mMin(t2, fabs(angles2[j] - DA2 - thetaPoints2(i)) / kernelWidth2);
22166 thetaDensity(ii, j) += fac * (thetaBounds(i + 1) - thetaBounds(i)) * exp(-F1B2 *
POW2(t)) / sqrt(F2 * PI);
22167 thetaDensity2(ii2, j) +=
22168 fac2 * (thetaBounds2(i + 1) - thetaBounds2(i)) * exp(-F1B2 *
POW2(t2)) / sqrt(F2 * PI);
22173 if(m_noPointParticles > 0) {
22174 MPI_Allreduce(MPI_IN_PLACE, &thetaDensity[0], noDat * thetaSize, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
22175 "MPI_IN_PLACE",
"thetaDensity[0]");
22176 MPI_Allreduce(MPI_IN_PLACE, &thetaDensity2[0], noDat * thetaSize, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
22177 "MPI_IN_PLACE",
"thetaDensity2[0]");
22183 for(
MInt i = 0; i < thetaSize; i++) {
22184 MFloat ang = thetaPoints(i);
22187 for(
MInt j = 0; j < noDat; j++) {
22188 sum[j] += fac * (thetaBounds(i + 1) - thetaBounds(i)) * thetaDensity(i, j);
22189 sum2[j] += fac2 * (thetaBounds2(i + 1) - thetaBounds2(i)) * thetaDensity2(i, j);
22192 for(
MInt i = 0; i < thetaSize; i++) {
22193 for(
MInt j = 0; j < noDat; j++) {
22194 thetaDensity(i, j) /= sum[j];
22195 thetaDensity2(i, j) /= sum2[j];
22199 if(domainId() == 0) {
22202 ofl.open(
"angleDensity_00" + to_string(
globalTimeStep), ios_base::out | ios_base::trunc);
22203 ofl2.open(
"angleDensityCos_00" + to_string(
globalTimeStep), ios_base::out | ios_base::trunc);
22204 if(ofl.is_open() && ofl.good()) {
22205 ofl <<
"# average orientation distribution functions, sampled from time steps " <<
globalTimeStep - noSamples
22206 <<
" to " <<
globalTimeStep <<
" (time level " << m_time - (((
MFloat)noSamples) * timeStep()) <<
" to "
22207 << m_time <<
")" << endl;
22208 ofl2 <<
"# average orientation distribution functions (cosines), sampled from time steps "
22210 << m_time - (((
MFloat)noSamples) * timeStep()) <<
" to " << m_time <<
")" << endl;
22211 ofl <<
"# 1: angle" << endl;
22212 ofl <<
"# 2: bin size" << endl;
22213 ofl <<
"# 3: no samples in bin" << endl;
22214 ofl <<
"# 4-7: alignment of particle symmetry axis with x-axis" << endl;
22215 ofl <<
"# 8-11: alignment of particle symmetry axis with y-axis" << endl;
22216 ofl <<
"# 12-15: alignment of particle symmetry axis with z-axis" << endl;
22217 ofl <<
"# 16-19: alignment of particle symmetry axis with flow direction" << endl;
22218 ofl <<
"# 20-23: alignment of particle symmetry axis with vorticity direction" << endl;
22219 ofl <<
"# 24-27: alignment of particle velocity with flow velocity" << endl;
22220 ofl <<
"# 28-31: alignment of particle angular velocity with fluid vorticity" << endl;
22221 ofl <<
"# 32-35: alignment of particle velocity vector with symmetry axis" << endl;
22222 ofl <<
"# 36-39: alignment of particle rotation vector with symmetry axis" << endl;
22223 ofl <<
"# 40-43: alignment of relative velocity vector with symmetry axis" << endl;
22224 for(
MInt i = 0; i < thetaSize; i++) {
22225 ofl << thetaPoints(i) <<
" " << thetaBounds(i + 1) - thetaBounds(i) <<
" " << F0;
22226 ofl2 << thetaPoints2(i) <<
" " << thetaBounds2(i + 1) - thetaBounds2(i) <<
" " << F0;
22227 for(
MInt j = 0; j < noDat; j++) {
22228 if(j % 4 > 1 && i >= thetaSize / 2)
22231 ofl <<
" " << thetaDensity(i, j);
22232 if(j % 4 > 1 && i < thetaSize / 2)
22235 ofl2 <<
" " << thetaDensity2(i, j);
22245 RECORD_TIMER_STOP(t_odf);
22246 RECORD_TIMER_START(t_pdf);
22248 const MInt noPdfPoints = 100;
22250 const MInt kernelSteps = 5;
22253 const MInt noPdfsPF = 7;
22254 const MInt noPdfsP = 17;
22258 MFloatScratchSpace pdfValuesPFfluid(noPdfsPF, noPdfPoints, AT_,
"pdfValuesPFfluid");
22259 MFloatScratchSpace pdfValuesPFparticle(noPdfsPF, noPdfPoints, AT_,
"pdfValuesPFparticle");
22269 vector<MString> pdfTitle;
22270 dataPointsPF.
fill(F0);
22271 pdfPointsPF.
fill(F0);
22272 pdfBoundsPF.
fill(F0);
22273 pdfValuesPFfluid.
fill(F0);
22274 pdfValuesPFparticle.
fill(F0);
22275 dataPointsP.
fill(F0);
22276 pdfPointsP.
fill(F0);
22277 pdfBoundsP.
fill(F0);
22278 pdfValuesP.
fill(F0);
22279 meanValsPF.
fill(F0);
22280 rmsValsPF.
fill(F0);
22281 meanValsP.
fill(F0);
22283 sumValsPF.
fill(F0);
22287 pdfBoundsPF(0, 0) = 0.0;
22288 pdfBoundsPF(0, noPdfPoints) = 200.0;
22289 pdfTitle.push_back(
"angular-velocity(particle-fluid)");
22290 pdfBoundsPF(1, 0) = 0.0;
22291 pdfBoundsPF(1, noPdfPoints) = 200.0;
22292 pdfTitle.push_back(
"strain-rate(particle-fluid)");
22293 pdfBoundsPF(2, 0) = 0.98;
22294 pdfBoundsPF(2, noPdfPoints) = 1.03;
22295 pdfTitle.push_back(
"pressure(particle-fluid)");
22296 pdfBoundsPF(3, 0) = 0.0;
22297 pdfBoundsPF(3, noPdfPoints) = 3.0;
22298 pdfTitle.push_back(
"velocity(particle-fluid)");
22300 pdfBoundsPF(4, 0) = -1.5;
22301 pdfBoundsPF(4, noPdfPoints) = 1.5;
22302 pdfTitle.push_back(
"velX(particle-fluid)");
22303 pdfBoundsPF(5, 0) = -1.5;
22304 pdfBoundsPF(5, noPdfPoints) = 1.5;
22305 pdfTitle.push_back(
"velY(particle-fluid)");
22306 pdfBoundsPF(6, 0) = -1.5;
22307 pdfBoundsPF(6, noPdfPoints) = 1.5;
22308 pdfTitle.push_back(
"velZ(particle-fluid)");
22310 pdfBoundsP(0, 0) = 0.0;
22311 pdfBoundsP(0, noPdfPoints) = 3.0;
22312 pdfTitle.push_back(
"velocity(particle)");
22313 pdfBoundsP(1, 0) = 0.0;
22314 pdfBoundsP(1, noPdfPoints) = 150.0;
22315 pdfTitle.push_back(
"angular-velocity(particle)");
22316 pdfBoundsP(2, 0) = 0.0;
22317 pdfBoundsP(2, noPdfPoints) = 50.0;
22318 pdfTitle.push_back(
"particle-Reynolds-number");
22319 pdfBoundsP(3, 0) = -10.0;
22320 pdfBoundsP(3, noPdfPoints) = 100.0;
22321 pdfTitle.push_back(
"F_p");
22322 pdfBoundsP(4, 0) = -2.0;
22323 pdfBoundsP(4, noPdfPoints) = 30.0;
22324 pdfTitle.push_back(
"F*(U_p-v_p)");
22325 pdfBoundsP(5, 0) = -8.0;
22326 pdfBoundsP(5, noPdfPoints) = 20.0;
22327 pdfTitle.push_back(
"F*U_p");
22328 pdfBoundsP(6, 0) = -25.0;
22329 pdfBoundsP(6, noPdfPoints) = 2.0;
22330 pdfTitle.push_back(
"F*v_p");
22331 pdfBoundsP(7, 0) = -2.0;
22332 pdfBoundsP(7, noPdfPoints) = 10.0;
22333 pdfTitle.push_back(
"T_p");
22334 pdfBoundsP(8, 0) = -0.3;
22335 pdfBoundsP(8, noPdfPoints) = 0.3;
22336 pdfTitle.push_back(
"T_p*(O_p-w_p)");
22337 pdfBoundsP(9, 0) = -0.2;
22338 pdfBoundsP(9, noPdfPoints) = 0.2;
22339 pdfTitle.push_back(
"T_p*O_p");
22340 pdfBoundsP(10, 0) = -0.3;
22341 pdfBoundsP(10, noPdfPoints) = 0.3;
22342 pdfTitle.push_back(
"T_p*w_p");
22343 pdfBoundsP(11, 0) = -100.0;
22344 pdfBoundsP(11, noPdfPoints) = 100.0;
22345 pdfTitle.push_back(
"wHat_px");
22346 pdfBoundsP(12, 0) = -100.0;
22347 pdfBoundsP(12, noPdfPoints) = 100.0;
22348 pdfTitle.push_back(
"wHat_py");
22349 pdfBoundsP(13, 0) = -100.0;
22350 pdfBoundsP(13, noPdfPoints) = 100.0;
22351 pdfTitle.push_back(
"wHat_pz");
22352 pdfBoundsP(14, 0) = -100.0;
22353 pdfBoundsP(14, noPdfPoints) = 100.0;
22354 pdfTitle.push_back(
"OHat_px");
22355 pdfBoundsP(15, 0) = -100.0;
22356 pdfBoundsP(15, noPdfPoints) = 100.0;
22357 pdfTitle.push_back(
"OHat_py");
22358 pdfBoundsP(16, 0) = -100.0;
22359 pdfBoundsP(16, noPdfPoints) = 100.0;
22360 pdfTitle.push_back(
"OHat_pz");
22362 for(
MInt i = 0; i < noPdfsPF; i++) {
22363 const MFloat DV = (pdfBoundsPF(i, noPdfPoints) - pdfBoundsPF(i, 0)) / ((
MFloat)noPdfPoints);
22364 for(
MInt j = 0; j < noPdfPoints; j++) {
22365 pdfBoundsPF(i, j + 1) = pdfBoundsPF(i, j) + DV;
22366 pdfPointsPF(i, j) = F1B2 * (pdfBoundsPF(i, j + 1) + pdfBoundsPF(i, j));
22369 for(
MInt i = 0; i < noPdfsP; i++) {
22370 const MFloat DV = (pdfBoundsP(i, noPdfPoints) - pdfBoundsP(i, 0)) / ((
MFloat)noPdfPoints);
22371 for(
MInt j = 0; j < noPdfPoints; j++) {
22372 pdfBoundsP(i, j + 1) = pdfBoundsP(i, j) + DV;
22373 pdfPointsP(i, j) = F1B2 * (pdfBoundsP(i, j + 1) + pdfBoundsP(i, j));
22377 for(
MInt c = 0; c < noLeafCells; c++) {
22378 MInt cellId = leafCells(c);
22379 MFloat volume = a_cellVolume(cellId) / grid().gridCellVolume(maxUniformRefinementLevel());
22383 for(
MInt i = 0; i < nDim; i++) {
22384 MInt id0 = (i + 1) % 3;
22385 MInt id1 = (id0 + 1) % 3;
22386 vort +=
POW2(F1B2 * (a_slope(cellId, PV->VV[id1], id0) - a_slope(cellId, PV->VV[id0], id1)));
22387 for(
MInt j = 0; j < nDim; j++) {
22388 strain +=
POW2(F1B2 * (a_slope(cellId, PV->VV[i], j) + a_slope(cellId, PV->VV[j], i)));
22390 velm +=
POW2(a_pvariable(cellId, PV->VV[i]));
22393 strain = sqrt(strain);
22395 MFloat pressure = a_pvariable(cellId, PV->P) / m_PInfinity;
22396 dataPointsPF(0) = vort * DX / m_UInfinity;
22397 dataPointsPF(1) = strain * DX / m_UInfinity;
22398 dataPointsPF(2) = pressure;
22399 dataPointsPF(3) = velm / m_UInfinity;
22400 dataPointsPF(4) = a_pvariable(cellId, PV->VV[0]) / m_UInfinity;
22401 dataPointsPF(5) = a_pvariable(cellId, PV->VV[1]) / m_UInfinity;
22402 dataPointsPF(6) = a_pvariable(cellId, PV->VV[2]) / m_UInfinity;
22403 const MFloat weight = volume;
22404 for(
MInt i = 0; i < noPdfsPF; i++) {
22405 meanValsPF(0, i) += weight * dataPointsPF(i);
22406 rmsValsPF(0, i) += weight *
POW2(dataPointsPF(i));
22408 sumValsPF(0) += weight;
22410 for(
MInt i = 0; i < noPdfsPF; i++) {
22411 const MFloat DV = (pdfBoundsPF(i, noPdfPoints) - pdfBoundsPF(i, 0)) / ((
MFloat)noPdfPoints);
22412 MInt bin = (
MInt)floor((dataPointsPF(i) - pdfBoundsPF(i, 0)) / DV);
22413 const MFloat kernelWidth = DV * ((
MFloat)kernelSteps);
22414 const MFloat fac = F1 / (kernelWidth);
22415 if(kernelSteps == 0) {
22416 if(bin > -1 && bin < noPdfPoints) pdfValuesPFfluid(i, bin) += weight;
22418 for(
MInt j = bin - 5 * kernelSteps; j < bin + 5 * kernelSteps; j++) {
22419 if(j < 0 || j >= noPdfPoints)
continue;
22420 MFloat t = fabs(dataPointsPF(i) - pdfPointsPF(i, j)) / DV;
22421 pdfValuesPFfluid(i, j) += fac * weight * exp(-F1B2 *
POW2(t)) / sqrt(F2 * PI);
22427 for(
MInt p = 0; p < noParticles; p++) {
22428 if(skipParticle(p))
continue;
22433 for(
MInt i = 0; i < nDim; i++) {
22434 velRot +=
POW2(pOmegaHat[p * nDim + i]);
22435 for(
MInt j = 0; j < nDim; j++) {
22436 shear +=
POW2(velShearHat[p * nDim + i]);
22438 velm +=
POW2(vel[3 * p + i]);
22440 dataPointsPF(0) = sqrt(velRot) * DX / m_UInfinity;
22441 dataPointsPF(1) = sqrt(shear) * DX / m_UInfinity;
22442 dataPointsPF(2) = particleFluidPressure[p] / m_PInfinity;
22443 dataPointsPF(3) = sqrt(velm) / m_UInfinity;
22444 dataPointsPF(4) = vel[3 * p + 0] / m_UInfinity;
22445 dataPointsPF(5) = vel[3 * p + 1] / m_UInfinity;
22446 dataPointsPF(6) = vel[3 * p + 2] / m_UInfinity;
22447 for(
MInt i = 0; i < noPdfsPF; i++) {
22448 const MFloat DV = (pdfBoundsPF(i, noPdfPoints) - pdfBoundsPF(i, 0)) / ((
MFloat)noPdfPoints);
22449 MInt bin = (
MInt)floor((dataPointsPF(i) - pdfBoundsPF(i, 0)) / DV);
22450 const MFloat kernelWidth = DV * ((
MFloat)kernelSteps);
22451 const MFloat fac = F1 / (kernelWidth);
22452 if(kernelSteps == 0) {
22453 if(bin > -1 && bin < noPdfPoints) pdfValuesPFparticle(i, bin) += F1;
22455 for(
MInt j = bin - 5 * kernelSteps; j < bin + 5 * kernelSteps; j++) {
22456 if(j < 0 || j >= noPdfPoints)
continue;
22457 MFloat t = fabs(dataPointsPF(i) - pdfPointsPF(i, j)) / DV;
22458 pdfValuesPFparticle(i, j) += fac * exp(-F1B2 *
POW2(t)) / sqrt(F2 * PI);
22462 for(
MInt i = 0; i < noPdfsPF; i++) {
22463 meanValsPF(1, i) += dataPointsPF(i);
22464 rmsValsPF(1, i) +=
POW2(dataPointsPF(i));
22466 sumValsPF(1) += F1;
22470 for(
MInt i = 0; i < nDim; i++) {
22471 partvel +=
POW2(pvel[3 * p + i]);
22472 prot +=
POW2(protVelHat[3 * p + i]);
22474 dataPointsP(0) = sqrt(partvel) / m_UInfinity;
22475 dataPointsP(1) = sqrt(prot) * DX / m_UInfinity;
22477 MFloat diameter = F2 * pow(pRadii[3 * p] * pRadii[3 * p + 1] * pRadii[3 * p + 2], F1B3);
22478 for(
MInt i = 0; i < nDim; i++) {
22479 Rep +=
POW2(vel[nDim * p + i] - pvel[nDim * p + i]);
22481 dataPointsP(2) = sqrt(Rep) * diameter * m_rhoInfinity * sysEqn().m_Re0 / sysEqn().m_muInfinity;
22490 vector<MFloat> pForce(3, F0);
22491 vector<MFloat> pTorqueHat(3, F0);
22494 computeRotationMatrix(R, &(quats[4 * p]));
22495 if(m_noEmbeddedBodies > 0) {
22496 matrixVectorProduct(q, R, &m_bodyTorque[nDim * p]);
22497 for(
MInt i = 0; i < nDim; i++) {
22498 pForce[i] = m_hydroForce[nDim * p + i];
22499 pTorqueHat[i] = q[i];
22502 const MFloat pmass = F4B3 * PI * m_particleRadii[3 * p] * m_particleRadii[3 * p + 1]
22503 * m_particleRadii[3 * p + 2] * m_densityRatio * m_rhoInfinity;
22504 const MFloat Ix = F1B5 * (
POW2(m_particleRadii[3 * p + 1]) +
POW2(m_particleRadii[3 * p + 2])) * pmass;
22505 const MFloat Iy = F1B5 * (
POW2(m_particleRadii[3 * p + 0]) +
POW2(m_particleRadii[3 * p + 2])) * pmass;
22506 const MFloat Iz = F1B5 * (
POW2(m_particleRadii[3 * p + 0]) +
POW2(m_particleRadii[3 * p + 1])) * pmass;
22507 const MFloat momI[3] = {Ix, Iy, Iz};
22508 for(
MInt i = 0; i < nDim; i++) {
22509 pForce[i] = pmass * m_particleAcceleration[nDim * p + i];
22510 pTorqueHat[i] = momI[i] * m_particleAngularAcceleration[3 * p + i];
22511 protVelHat[i] = protVelHat[p * 3 + i];
22514 for(
MInt i = 0; i < nDim; i++) {
22515 pF +=
POW2(pForce[i]);
22516 pFUv += pForce[i] * (vel[nDim * p + i] - pvel[nDim * p + i]);
22517 pFU += pForce[i] * vel[nDim * p + i];
22518 pFv += pForce[i] * pvel[nDim * p + i];
22519 pT +=
POW2(pTorqueHat[i]);
22520 pTOw += pTorqueHat[i] * (pOmegaHat[p * 3 + i] - protVelHat[p * 3 + i]);
22521 pTO += pTorqueHat[i] * pOmegaHat[p * 3 + i];
22522 pTw += pTorqueHat[i] * protVelHat[p * 3 + i];
22524 dataPointsP(3) = sqrt(pF) / (
POW3(m_UInfinity) *
POW2(diameter));
22525 dataPointsP(4) = pFUv / (
POW3(m_UInfinity) *
POW2(diameter));
22526 dataPointsP(5) = pFU / (
POW3(m_UInfinity) *
POW2(diameter));
22527 dataPointsP(6) = pFv / (
POW3(m_UInfinity) *
POW2(diameter));
22528 dataPointsP(7) = sqrt(pT) / (
POW3(m_UInfinity) *
POW2(diameter));
22529 dataPointsP(8) = pTOw / (
POW3(m_UInfinity) *
POW2(diameter));
22530 dataPointsP(9) = pTO / (
POW3(m_UInfinity) *
POW2(diameter));
22531 dataPointsP(10) = pTw / (
POW3(m_UInfinity) *
POW2(diameter));
22533 for(
MInt i = 0; i < nDim; i++) {
22534 dataPointsP(11 + i) = protVelHat[p * nDim + i] * DX / m_UInfinity;
22535 dataPointsP(14 + i) = pOmegaHat[p * nDim + i] * DX / m_UInfinity;
22537 for(
MInt i = 0; i < noPdfsP; i++) {
22538 meanValsP(i) += dataPointsP(i);
22539 rmsValsP(i) +=
POW2(dataPointsP(i));
22543 for(
MInt i = 0; i < noPdfsP; i++) {
22544 const MFloat DV = (pdfBoundsP(i, noPdfPoints) - pdfBoundsP(i, 0)) / ((
MFloat)noPdfPoints);
22545 MInt bin = (
MInt)floor((dataPointsP(i) - pdfBoundsP(i, 0)) / DV);
22546 const MFloat kernelWidth = DV * ((
MFloat)kernelSteps);
22547 const MFloat fac = F1 / (kernelWidth);
22548 if(kernelSteps == 0) {
22549 if(bin > -1 && bin < noPdfPoints) pdfValuesP(i, bin) += F1;
22551 for(
MInt j = bin - 5 * kernelSteps; j < bin + 5 * kernelSteps; j++) {
22552 if(j < 0 || j >= noPdfPoints)
continue;
22553 MFloat t = fabs(dataPointsP(i) - pdfPointsP(i, j)) / DV;
22554 pdfValuesP(i, j) += fac * exp(-F1B2 *
POW2(t)) / sqrt(F2 * PI);
22560 if(domainId() == 0) {
22561 MPI_Reduce(MPI_IN_PLACE, &meanValsPF[0], 2 * noPdfsPF, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22563 MPI_Reduce(MPI_IN_PLACE, &rmsValsPF[0], 2 * noPdfsPF, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22565 MPI_Reduce(MPI_IN_PLACE, &sumValsPF[0], 2, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22568 MPI_Reduce(&meanValsPF[0], &meanValsPF[0], 2 * noPdfsPF, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22570 MPI_Reduce(&meanValsPF[0], &rmsValsPF[0], 2 * noPdfsPF, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22572 MPI_Reduce(&meanValsPF[0], &sumValsPF[0], 2, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22576 if(m_noPointParticles > 0) {
22577 MPI_Reduce(MPI_IN_PLACE, &pdfValuesPFfluid[0], noPdfsPF * noPdfPoints, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
22578 "MPI_IN_PLACE",
"pdfValuesPFfluid[0]");
22579 MPI_Reduce(MPI_IN_PLACE, &pdfValuesPFparticle[0], noPdfsPF * noPdfPoints, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
22580 "MPI_IN_PLACE",
"pdfValuesPFparticle[0]");
22581 MPI_Reduce(MPI_IN_PLACE, &meanValsP[0], noPdfsP, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22583 MPI_Reduce(MPI_IN_PLACE, &rmsValsP[0], noPdfsP, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
22585 MPI_Reduce(MPI_IN_PLACE, &sumValsP, 1, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
"MPI_IN_PLACE",
"sumValsP[0]");
22586 MPI_Reduce(MPI_IN_PLACE, &pdfValuesP[0], noPdfsP * noPdfPoints, MPI_DOUBLE, MPI_SUM, 0, mpiComm(), AT_,
22587 "MPI_IN_PLACE",
"pdfValuesP[0]");
22590 if(domainId() == 0) {
22591 for(
MInt i = 0; i < noPdfsPF; i++) {
22592 meanValsPF(0, i) /= sumValsPF(0);
22593 meanValsPF(1, i) /= sumValsPF(1);
22594 rmsValsPF(0, i) = sqrt(rmsValsPF(0, i) / sumValsPF(0));
22595 rmsValsPF(1, i) = sqrt(rmsValsPF(1, i) / sumValsPF(1));
22597 for(
MInt i = 0; i < noPdfsP; i++) {
22598 meanValsP(i) /= sumValsP;
22599 rmsValsP(i) = sqrt(rmsValsP(i) / sumValsP);
22604 for(
MInt i = 0; i < noPdfsPF; i++) {
22607 for(
MInt j = 0; j < noPdfPoints; j++) {
22608 sumv += (pdfBoundsPF(i, j + 1) - pdfBoundsPF(i, j)) * pdfValuesPFfluid(i, j);
22609 sumv2 += (pdfBoundsPF(i, j + 1) - pdfBoundsPF(i, j)) * pdfValuesPFparticle(i, j);
22611 nfacsPF(i, 0) = sumv;
22612 nfacsPF(i, 1) = sumv2;
22613 for(
MInt j = 0; j < noPdfPoints; j++) {
22614 pdfValuesPFfluid(i, j) /= sumv;
22615 pdfValuesPFparticle(i, j) /= sumv2;
22618 for(
MInt i = 0; i < noPdfsP; i++) {
22620 for(
MInt j = 0; j < noPdfPoints; j++) {
22621 sumv += (pdfBoundsP(i, j + 1) - pdfBoundsP(i, j)) * pdfValuesP(i, j);
22624 for(
MInt j = 0; j < noPdfPoints; j++) {
22625 pdfValuesP(i, j) /= sumv;
22629 ofl.open(
"pdf_00" + to_string(
globalTimeStep), ios_base::out | ios_base::trunc);
22630 if(ofl.is_open() && ofl.good()) {
22632 ofl <<
"# average pdfs, sampled at time step " <<
globalTimeStep <<
" (time level " << m_time <<
")" << endl;
22633 ofl <<
"#particle-fluid meanVals: #fluid #particle-fluid: ";
22634 for(
MInt i = 0; i < noPdfsPF; i++) {
22635 ofl << meanValsPF(0, i) <<
" " << meanValsPF(1, i) <<
" ";
22638 ofl <<
"#particle-fluid rmsVals: #fluid #particle-fluid: ";
22639 for(
MInt i = 0; i < noPdfsPF; i++) {
22640 ofl << rmsValsPF(0, i) <<
" " << rmsValsPF(1, i) <<
" ";
22643 ofl <<
"#particle meanVals: ";
22644 for(
MInt i = 0; i < noPdfsP; i++) {
22645 ofl << meanValsP(i) <<
" ";
22648 ofl <<
"#particle rmsVals: ";
22649 for(
MInt i = 0; i < noPdfsP; i++) {
22650 ofl << rmsValsP(i) <<
" ";
22654 for(
MUint i = 0; i < noPdfsPF; i++) {
22655 ofl <<
"#" << cnt++ <<
":" << pdfTitle[i];
22656 ofl <<
", " << cnt++ <<
": pdf_fluid, ";
22657 ofl << cnt++ <<
": pdf_particleFluid" << endl;
22659 for(
MUint i = noPdfsPF; i < pdfTitle.size(); i++) {
22660 ofl <<
"#" << cnt++ <<
":" << pdfTitle[i];
22661 ofl <<
", " << cnt++ <<
": pdf_particle" << endl;
22664 for(
MInt j = 0; j < noPdfPoints; j++) {
22665 for(
MInt i = 0; i < noPdfsPF; i++) {
22666 ofl << pdfPointsPF(i, j) <<
" " << pdfValuesPFfluid(i, j) <<
" " << pdfValuesPFparticle(i, j) <<
" ";
22668 for(
MInt i = 0; i < noPdfsP; i++) {
22669 ofl << pdfPointsP(i, j) <<
" " << pdfValuesP(i, j) <<
" ";
22671 for(
MInt i = 0; i < noPdfsPF; i++) {
22672 ofl << nfacsPF(i, 0) <<
" " << nfacsPF(i, 1) <<
" ";
22674 for(
MInt i = 0; i < noPdfsP; i++) {
22675 ofl << nfacsP(i) <<
" " << nfacsP(i) <<
" ";
22682 RECORD_TIMER_STOP(t_pdf);
22686 if(computeNearBody && m_noEmbeddedBodies > 0) {
22687 IF_CONSTEXPR(nDim == 2)
mTerm(1, AT_,
"computeNearBody not implemented for 2D!");
22688 RECORD_TIMER_START(t_near);
22691 constexpr MInt noDat2 = 26;
22692 const MInt noReClasses = (m_bodyTypeMb == 3 ? 6 : 1);
22695 MFloatScratchSpace bodyDataScatter(m_noEmbeddedBodies, noDat2, AT_,
"bodyDataScatter");
22697 bodyDataScatter.
fill(F0);
22700 if(m_bodyTypeMb == 3) {
22701 ReClassBounds(0) = 0;
22702 ReClassBounds(1) = 10;
22703 ReClassBounds(2) = 40;
22704 ReClassBounds(3) = 50;
22705 ReClassBounds(4) = 80;
22706 ReClassBounds(5) = 90;
22709 RECORD_TIMER_START(t_near_bodydat2);
22710 for(
MInt p = 0; p < m_noEmbeddedBodies; p++) {
22711 MFloat diameter = F2 * pow(m_bodyRadii[3 * p] * m_bodyRadii[3 * p + 1] * m_bodyRadii[3 * p + 2], F1B3);
22712 MFloat vrel[3] = {F0, F0, F0};
22713 MFloat vdir[3] = {F0, F0, F0};
22714 MFloat vpdir[3] = {F0, F0, F0};
22715 MFloat vfdir[3] = {F0, F0, F0};
22716 MFloat omegaRel[3] = {F0, F0, F0};
22720 for(
MInt i = 0; i < nDim; i++) {
22721 vrel[i] = vel[nDim * p + i] - pvel[nDim * p + i];
22722 vpdir[i] = pvel[nDim * p + i];
22723 vfdir[i] = vel[nDim * p + i];
22724 vrel_mag +=
POW2(vrel[i]);
22725 vp_mag +=
POW2(vpdir[i]);
22726 vf_mag +=
POW2(vfdir[i]);
22728 vrel_mag = sqrt(vrel_mag);
22729 vp_mag = sqrt(vp_mag);
22730 vf_mag = sqrt(vf_mag);
22731 for(
MInt i = 0; i < nDim; i++) {
22732 vdir[i] = vrel[i] /
mMax(1e-12, vrel_mag);
22733 vpdir[i] /=
mMax(1e-12, vp_mag);
22734 vfdir[i] /=
mMax(1e-12, vf_mag);
22738 MFloat tmp[3] = {F1, F0, F0};
22740 computeRotationMatrix(R, &(quats[4 * p]));
22741 matrixVectorProductTranspose(q, R, tmp);
22742 const MFloat qabs = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
22743 for(
MInt i = 0; i < nDim; i++)
22744 q[i] /=
mMax(1e-12, qabs);
22745 MFloat Rep = vrel_mag * diameter * m_rhoInfinity * sysEqn().m_Re0 / sysEqn().m_muInfinity;
22747 if(m_bodyTypeMb == 3) {
22749 for(
MInt i = 0; i < nDim; i++) {
22750 aof += vdir[i] * q[i];
22752 aof = acos(fabs(aof)) * 360.0 / (2.0 * PI);
22753 for(
MInt i = 1; i < noReClasses; i++) {
22754 if(aof >= ReClassBounds(i - 1) && aof < ReClassBounds(i)) {
22759 ReClass(p) = classId;
22761 bodyCnt[classId] += F1;
22764 ReClass(p) = classId;
22766 bodyCnt[classId] += F1;
22771 for(
MInt i = 0; i < nDim; i++) {
22772 eps0 += 5.0 * (sysEqn().m_muInfinity / sysEqn().m_Re0) *
POW2(velGradient[9 * p + 3 * i + i]);
22773 for(
MInt j = 0; j < nDim; j++) {
22774 eps1 += (sysEqn().m_muInfinity / sysEqn().m_Re0)
22775 * (velGradient[9 * p + 3 * i + j] + velGradient[9 * p + 3 * j + i]) * velGradient[9 * p + 3 * i + j];
22778 const MFloat epsRef = diameter / (
POW3(m_UInfinity));
22781 for(
MInt i = 0; i < nDim; i++) {
22782 MInt id0 = (i + 1) % 3;
22783 MInt id1 = (id0 + 1) % 3;
22784 wdir[i] = F1B2 * (velGradient[9 * p + 3 * id1 + id0] - velGradient[9 * p + 3 * id0 + id1]);
22785 pOmega[i] = wdir[i];
22787 for(
MInt i = 0; i < 3; i++) {
22788 omegaRel[i] = wdir[i] - m_bodyAngularVelocity[p * 3 + i];
22791 for(
MInt i = 0; i < nDim; i++) {
22792 wdir[i] /=
mMax(1e-12, wabs);
22797 for(
MInt i = 0; i < nDim; i++) {
22798 tmp2[i] = m_hydroForce[nDim * p + i];
22800 matrixVectorProduct(force_frs, R, tmp2);
22802 for(
MInt i = 0; i < 3; i++) {
22803 tmp2[i] = m_bodyTorque[3 * p + i];
22805 matrixVectorProduct(torque_frs, R, tmp2);
22808 bodyDataScatter(p, cnt++) = Rep;
22809 bodyDataScatter(p, cnt++) = sqrt(
POW2(vrel[0]) +
POW2(vrel[1]) +
POW2(vrel[2])) / m_UInfinity;
22810 bodyDataScatter(p, cnt++) =
22811 sqrt(
POW2(pvel[nDim * p + 0]) +
POW2(pvel[nDim * p + 1]) +
POW2(pvel[nDim * p + 2])) / m_UInfinity;
22812 bodyDataScatter(p, cnt++) =
22813 (pvel[nDim * p + 0] * vdir[0] + pvel[nDim * p + 1] * vdir[1] + pvel[nDim * p + 2] * vdir[2]) / m_UInfinity;
22814 bodyDataScatter(p, cnt++) =
22815 sqrt(
POW2(vel[nDim * p + 0]) +
POW2(vel[nDim * p + 1]) +
POW2(vel[nDim * p + 2])) / m_UInfinity;
22816 bodyDataScatter(p, cnt++) =
22817 (vel[nDim * p + 0] * vdir[0] + vel[nDim * p + 1] * vdir[1] + vel[nDim * p + 2] * vdir[2]) / m_UInfinity;
22818 bodyDataScatter(p, cnt++) = sqrt(
POW2(pOmega[0]) +
POW2(pOmega[1]) +
POW2(pOmega[2])) * diameter / m_UInfinity;
22819 bodyDataScatter(p, cnt++) =
22820 (pOmega[0] * vdir[0] + pOmega[1] * vdir[1] + pOmega[2] * vdir[2]) * diameter / m_UInfinity;
22821 bodyDataScatter(p, cnt++) = (vfdir[0] * vpdir[0] + vfdir[1] * vpdir[1] + vfdir[2] * vpdir[2]);
22822 bodyDataScatter(p, cnt++) = (vdir[0] * vpdir[0] + vdir[1] * vpdir[1] + vdir[2] * vpdir[2]);
22823 bodyDataScatter(p, cnt++) = (particleFluidPressure[p] - m_PInfinity) / (F1B2 * m_rhoInfinity *
POW2(m_UInfinity));
22824 bodyDataScatter(p, cnt++) = eps0 * epsRef;
22825 bodyDataScatter(p, cnt++) = eps1 * epsRef;
22826 bodyDataScatter(p, cnt++) = nearBodyState[noNearBodyState * p + 0] * epsRef;
22827 bodyDataScatter(p, cnt++) = nearBodyState[noNearBodyState * p + 1] * epsRef;
22828 bodyDataScatter(p, cnt++) = nearBodyState[noNearBodyState * p + 2] * epsRef;
22829 bodyDataScatter(p, cnt++) = nearBodyState[noNearBodyState * p + 3] * epsRef;
22830 bodyDataScatter(p, cnt++) = nearBodyState[noNearBodyState * p + 4] * epsRef;
22831 bodyDataScatter(p, cnt++) = (m_hydroForce[nDim * p + 0] * vrel[0] + m_hydroForce[nDim * p + 1] * vrel[1]
22832 + m_hydroForce[nDim * p + 2] * vrel[2])
22833 / (
POW3(m_UInfinity) *
POW2(diameter));
22834 bodyDataScatter(p, cnt++) = (m_bodyTorque[3 * p + 0] * omegaRel[0] + m_bodyTorque[nDim * p + 1] * omegaRel[1]
22835 + m_bodyTorque[nDim * p + 2] * omegaRel[2])
22836 / (
POW3(m_UInfinity) *
POW2(diameter));
22837 bodyDataScatter(p, cnt++) = force_frs[0];
22838 bodyDataScatter(p, cnt++) = force_frs[1];
22839 bodyDataScatter(p, cnt++) = force_frs[2];
22840 bodyDataScatter(p, cnt++) = torque_frs[0];
22841 bodyDataScatter(p, cnt++) = torque_frs[1];
22842 bodyDataScatter(p, cnt++) = torque_frs[2];
22844 if(cnt != noDat2)
mTerm(1, AT_,
"data size mismatch.");
22846 RECORD_TIMER_STOP(t_near_bodydat2);
22848 RECORD_TIMER_START(t_near_bodydat);
22851 const MFloat refRadius = m_maxBodyRadius;
22852 constexpr MInt noDat = 13;
22856 mMin(dxm,
mMax(m_outerBandWidth[
mMin(maxUniformRefinementLevel(), maxRefinementLevel() - 1)] / refRadius, 4.0));
22858 mMax(c_cellLengthAtLevel(maxRefinementLevel()),
mMin(m_minBodyRadius / 4.0, m_maxBodyRadius / 8.0)) / refRadius;
22859 const MInt noPointsX = (
MInt)((deltaX + 0.001 * dx) / dx);
22860 const MFloat deltaY = deltaX;
22861 const MInt noPointsY = noPointsX;
22863 MFloatScratchSpace nearBodyData(noPointsX, noPointsY, noDat * noReClasses, AT_,
"nearBodyData");
22871 const MInt dataSize0 = noPointsX * noPointsY * noReClasses;
22872 const MInt dataSize = noDat * dataSize0;
22873 nearBodyData.
fill(F0);
22876 xBounds(0) = (m_bodyTypeMb == 3) ? -F1B2 * deltaX : 0.0;
22877 for(
MInt i = 0; i < noPointsX; i++) {
22878 xBounds(i + 1) = xBounds(i) + dx;
22879 xPoints(i) = F1B2 * (xBounds(i) + xBounds(i + 1));
22881 yBounds(0) = (m_bodyTypeMb == 3) ? -F1B2 * deltaY : 0.0;
22882 for(
MInt i = 0; i < noPointsY; i++) {
22883 yBounds(i + 1) = yBounds(i) + dy;
22884 yPoints(i) = F1B2 * (yBounds(i) + yBounds(i + 1));
22887 for(
MInt c = 0; c < noLeafCells; c++) {
22888 MInt cellId = leafCells(c);
22890 if(volume < 1e-14)
continue;
22891 if(a_level(cellId) <= maxUniformRefinementLevel())
continue;
22893 for(
MInt set = m_startSet; set < m_noSets; set++) {
22894 if(a_associatedBodyIds(cellId, set) < 0)
continue;
22896 const MInt p = a_associatedBodyIds(cellId, set);
22897 const MInt q = m_internalBodyId[p];
22898 if(q < 0 || q >= m_noEmbeddedBodies) {
22899 cerr <<
"Warning: body id " << endl;
22902 if(skipParticle(q))
continue;
22903 const MInt classId = ReClass(q);
22904 if(classId < 0)
continue;
22905 MFloat diameter = F2 * pow(m_bodyRadii[3 * q] * m_bodyRadii[3 * q + 1] * m_bodyRadii[3 * q + 2], F1B3);
22906 MFloat vrel[3] = {F0, F0, F0};
22907 MFloat vdir[3] = {F0, F0, F0};
22911 MFloat crossp[3] = {F0, F0, F0};
22912 MFloat crossp2[3] = {F0, F0, F0};
22915 MFloat tmp[3] = {F1, F0, F0};
22918 computeRotationMatrix(R, &(quats[4 * q]));
22919 matrixVectorProductTranspose(symm, R, tmp);
22920 for(
MInt i = 0; i < nDim; i++) {
22921 vrel[i] = vel[nDim * q + i] - pvel[nDim * q + i];
22922 vrel_mag +=
POW2(vrel[i]);
22923 vmag +=
POW2(pvel[nDim * q + i]);
22924 scnt +=
POW2(symm[i]);
22927 vrel_mag = sqrt(vrel_mag);
22930 for(
MInt i = 0; i < nDim; i++) {
22931 vdir[i] = vrel[i] /
mMax(1e-14, vrel_mag);
22932 symm[i] = symm[i] /
mMax(1e-14, scnt);
22934 if(m_bodyTypeMb == 3) {
22935 MFloat minRad =
mMin(
mMin(m_bodyRadii[3 * p], m_bodyRadii[3 * p + 1]), m_bodyRadii[3 * p + 2]);
22936 r = (r - minRad) / minRad;
22938 r = (r - m_bodyRadius[p]) / m_bodyRadius[p];
22943 crossProduct(crossp, vdir, symm);
22944 for(
MInt i = 0; i < nDim; i++) {
22945 csm +=
POW2(crossp[i]);
22948 for(
MInt i = 0; i < nDim; i++) {
22949 crossp[i] = crossp[i] /
mMax(1e-14, csm);
22950 trans += crossp[i] * (a_coordinate(cellId, i) - m_bodyCenter[nDim * p + i]);
22952 crossProduct(crossp2, vdir, crossp);
22954 for(
MInt i = 0; i < nDim; i++) {
22955 csm2 +=
POW2(crossp2[i]);
22958 for(
MInt i = 0; i < nDim; i++) {
22959 crossp2[i] = crossp2[i] /
mMax(1e-14, csm2);
22962 if(fabs(trans) >
mMax(F2 * c_cellLengthAtLevel(maxRefinementLevel()), c_cellLengthAtCell(cellId))) {
22970 for(
MInt i = 0; i < nDim; i++) {
22971 aof0 += vdir[i] * symm[i];
22975 for(
MInt i = 0; i < nDim; i++) {
22976 distx += (a_coordinate(cellId, i) - m_bodyCenter[nDim * p + i]) * vdir[i] / refRadius;
22977 disty += (a_coordinate(cellId, i) - m_bodyCenter[nDim * p + i]) * crossp2[i] / refRadius;
22979 if(aof0 < F0) disty *= -F1;
22980 idx = (
MInt)(distx / dx) + noPointsX / 2;
22981 idy = (
MInt)(disty / dy) + noPointsY / 2;
22984 if(idy < 0 || idx < 0 || idy >= noPointsY || idx >= noPointsX) {
22991 for(
MInt i = 0; i < nDim; i++) {
22992 vabs +=
POW2(a_pvariable(cellId, PV->VV[i]) - pvel[nDim * q + i]);
22993 vabs2 +=
POW2(a_pvariable(cellId, PV->VV[i]) - vel[nDim * q + i]);
22996 vabs2 = sqrt(vabs2);
22997 dat(idCnt++) = vabs / m_UInfinity;
22998 dat(idCnt++) = vabs / vmag;
22999 dat(idCnt++) = vabs2 / m_UInfinity;
23000 dat(idCnt++) = vabs2 / vrel_mag;
23001 MFloat cp = (a_pvariable(cellId, PV->P) - particleFluidPressure[q]);
23002 dat(idCnt++) = cp / (F1B2 * m_rhoInfinity *
POW2(m_UInfinity));
23003 dat(idCnt++) = cp / (F1B2 * m_rhoInfinity *
POW2(vrel_mag));
23006 for(
MInt i = 0; i < nDim; i++) {
23007 MInt id0 = (i + 1) % 3;
23008 MInt id1 = (id0 + 1) % 3;
23009 vort[i] = F1B2 * (a_slope(cellId, PV->VV[id1], id0) - a_slope(cellId, PV->VV[id0], id1));
23015 for(
MInt i = 0; i < nDim; i++) {
23016 U2 +=
POW2(a_variable(cellId, CV->RHO_VV[i]) / a_variable(cellId, CV->RHO));
23018 MFloat mue = sysEqn().m_muInfinity / sysEqn().m_Re0;
23020 for(
MInt i = 0; i < nDim; i++) {
23021 eps0 += 5.0 * mue *
POW2(a_slope(cellId, PV->VV[i], i));
23022 for(
MInt j = 0; j < nDim; j++) {
23024 mue * (a_slope(cellId, PV->VV[i], j) + a_slope(cellId, PV->VV[j], i)) * a_slope(cellId, PV->VV[i], j);
23027 const MFloat epsRef = diameter / (
POW3(m_UInfinity));
23028 dat(idCnt++) = Ek /
POW2(m_UInfinity);
23029 dat(idCnt++) = (Ek - meanState(0)) /
POW2(m_UInfinity);
23030 dat(idCnt++) = eps * epsRef;
23031 dat(idCnt++) = eps0 * epsRef;
23032 dat(idCnt++) = (eps - meanState(3)) * epsRef;
23033 dat(idCnt++) = (eps0 - meanState(2)) * epsRef;
23034 dat(idCnt++) = (
POW2(vort[0]) +
POW2(vort[1]) +
POW2(vort[2])) * diameter / m_UInfinity;
23035 if(idCnt != noDat)
mTerm(1, AT_,
"id mismatch.");
23037 for(
MInt i =
mMax(0, idx - 3); i <
mMin(noPointsX, idx + 4); i++) {
23038 for(
MInt j =
mMax(0, idy - 3); j <
mMin(noPointsY, idy + 4); j++) {
23041 exp(-F1B4 *
POW2(
dist)) * a_cellVolume(cellId) / grid().gridCellVolume(maxUniformRefinementLevel());
23042 for(
MInt k = 0; k < noDat; k++) {
23043 nearBodyData(i, j, k) += fac * volume * dat(k);
23045 bodySum(i, j, 0) += fac * volume;
23047 for(
MInt k = 0; k < noDat; k++) {
23048 nearBodyData(i, j, classId * noDat + k) += fac * volume * dat(k);
23050 bodySum(i, j, classId) += fac * volume;
23056 MPI_Allreduce(MPI_IN_PLACE, &nearBodyData[0], dataSize, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23057 "nearBodyData[0]");
23058 MPI_Allreduce(MPI_IN_PLACE, &bodySum[0], dataSize0, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23061 for(
MInt i = 0; i < noPointsX; i++) {
23062 for(
MInt j = 0; j < noPointsY; j++) {
23063 for(
MInt k = 0; k < noDat; k++) {
23064 for(
MInt l = 0; l < noReClasses; l++) {
23065 if(bodySum(i, j, l) > F0) {
23066 nearBodyData(i, j, l * noDat + k) /= bodySum(i, j, l);
23072 RECORD_TIMER_STOP(t_near_bodydat);
23073 RECORD_TIMER_START(t_near_output);
23075 if(domainId() == 0) {
23076 for(
MInt l = 0; l < noReClasses; l++) {
23078 string suffix = (l > 0) ?
"_class" + to_string(l) :
"";
23079 ofl.open((
"nearBodyData" + suffix +
"_00" + to_string(
globalTimeStep)).c_str(),
23080 ios_base::out | ios_base::trunc);
23081 if(ofl.is_open() && ofl.good()) {
23082 ofl <<
"# mean near-body statistics at time step " <<
globalTimeStep <<
", \n";
23083 ofl <<
"# average number of bodies in class: " << bodyCnt[l] <<
"\n";
23084 ofl <<
"# 1: lower bound x" << endl;
23085 ofl <<
"# 2: upper bound x" << endl;
23086 ofl <<
"# 3: x-Coordinate" << endl;
23087 ofl <<
"# 4: lower bound y" << endl;
23088 ofl <<
"# 5: upper bound y" << endl;
23089 ofl <<
"# 6: y-Coordinate" << endl;
23090 ofl <<
"# 7: sample weight" << endl;
23091 ofl <<
"# 8-9: relative velocity abs(u-v_p)" << endl;
23092 ofl <<
"# 12-13: relative velocity abs(u-U_p)" << endl;
23093 ofl <<
"# 14-15: cp" << endl;
23094 ofl <<
"# 16: Ek" << endl;
23095 ofl <<
"# 17: Ek - Ek_mean" << endl;
23096 ofl <<
"# 18: eps (isotropic)" << endl;
23097 ofl <<
"# 19: eps0" << endl;
23098 ofl <<
"# 20: eps - eps_mean (isotropic)" << endl;
23099 ofl <<
"# 21: eps0 - eps0_mean" << endl;
23100 ofl <<
"# 22: vorticity magnitude" << endl;
23102 for(
MInt i = 0; i < noPointsX; i++) {
23103 for(
MInt j = 0; j < noPointsY; j++) {
23104 ofl << xBounds(i) <<
" " << xBounds(i + 1) <<
" " << xPoints(i) <<
" ";
23105 ofl << yBounds(j) <<
" " << yBounds(j + 1) <<
" " << yPoints(j) <<
" ";
23106 ofl << bodySum(i, j, l) <<
" ";
23107 if(bodySum(i, j, l) > F0) {
23108 for(
MInt k = 0; k < noDat; k++) {
23109 ofl << nearBodyData(i, j, l * noDat + k) <<
" ";
23112 for(
MInt k = 0; k < noDat; k++) {
23113 ofl << F0 <<
" " << F0 <<
" ";
23125 if(domainId() == 0) {
23127 ofl.open(
"bodyData_00" + to_string(
globalTimeStep), ios_base::out | ios_base::trunc);
23128 if(ofl.is_open() && ofl.good()) {
23129 ofl <<
"# body statistics at time step " <<
globalTimeStep << endl;
23130 ofl <<
"# 1: Re_p" << endl;
23131 ofl <<
"# 2: vel_rel abs" << endl;
23132 ofl <<
"# 3: vel_part abs" << endl;
23133 ofl <<
"# 4: vel_part inline" << endl;
23134 ofl <<
"# 5: vel_fluid abs" << endl;
23135 ofl <<
"# 6: vel_fluid inline" << endl;
23136 ofl <<
"# 7: vorticity abs" << endl;
23137 ofl <<
"# 8: cosine vorticity times vrel" << endl;
23138 ofl <<
"# 9: cosine vel fluid times vel part " << endl;
23139 ofl <<
"# 10: cosine rel vel times vel part " << endl;
23140 ofl <<
"# 11: c_p" << endl;
23141 ofl <<
"# 12: eps0" << endl;
23142 ofl <<
"# 13: eps1" << endl;
23143 ofl <<
"# 14: near-body eps 0.5 d_p" << endl;
23144 ofl <<
"# 15: near-body eps 1.0 d_p" << endl;
23145 ofl <<
"# 16: near-body eps 1.5 d_p" << endl;
23146 ofl <<
"# 17: near-body eps 2.0 d_p" << endl;
23147 ofl <<
"# 18: near-body eps 2.5 d_p" << endl;
23148 ofl <<
"# 19: F_p * (U_p - v_p)" << endl;
23149 ofl <<
"# 20: T_p * (O_p - o_p)" << endl;
23150 ofl <<
"# 21: FxHat" << endl;
23151 ofl <<
"# 22: FyHat" << endl;
23152 ofl <<
"# 23: FzHat" << endl;
23153 ofl <<
"# 24: TxHat" << endl;
23154 ofl <<
"# 25: TyHat" << endl;
23155 ofl <<
"# 26: TzHat" << endl;
23157 for(
MInt p = 0; p < m_noEmbeddedBodies; p++) {
23158 for(
MInt i = 0; i < noDat2; i++) {
23159 ofl << bodyDataScatter[noDat2 * p + i] <<
" ";
23167 RECORD_TIMER_STOP(t_near_output);
23168 RECORD_TIMER_STOP(t_near);
23172 RECORD_TIMER_START(t_fft);
23175 const MInt fftLevel = maxUniformRefinementLevel();
23176 if(fftLevel > maxUniformRefinementLevel())
mTerm(1, AT_,
"Non-isotropic mesh is not implemented, yet");
23177 if(fftLevel < minLevel())
mTerm(1, AT_,
"Parents missing for fftLevel < minLevel()");
23179 const MFloat dx = c_cellLengthAtLevel(fftLevel);
23180 const MFloat dxeps = 0.1 * dx;
23181 MInt nx = (m_bbox[3] - m_bbox[0] + dxeps) / dx;
23182 MInt ny = (m_bbox[4] - m_bbox[1] + dxeps) / dx;
23183 MInt nz = (m_bbox[5] - m_bbox[2] + dxeps) / dx;
23189 MInt filterLvlLaplace = fftLevel;
23190 filterLvlLaplace = Context::getSolverProperty<MInt>(
"filterLvlLaplace", m_solverId, AT_, &filterLvlLaplace);
23192 MFloat couplingCheck = determineCoupling(coupling);
23193 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23194 for(
MInt i = 0; i < m_noPVars; i++) {
23195 pVariables(cellId, i) = a_pvariable(cellId, i);
23197 for(
MInt i = 0; i < m_noCVars; i++) {
23198 cVariables(cellId, i) = a_variable(cellId, i);
23199 oldVariables(cellId, i) = a_oldVariable(cellId, i);
23202 if(domainId() == 0)
23203 cerr <<
"coupling check " << couplingCheck <<
" " << m_couplingRate <<
" " << couplingCheck / (DX * DX * DX)
23204 <<
" " << m_couplingRate / (DX * DX * DX) <<
" " << DX * m_couplingRate /
POW3(DX * m_UInfinity) << endl;
23207 if(maxRefinementLevel() != fftLevel) {
23208 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23209 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
23210 if(a_isPeriodic(cellId))
continue;
23211 if(a_bndryId(cellId) < -1)
continue;
23212 if(a_isHalo(cellId))
continue;
23213 if(a_level(cellId) != fftLevel)
continue;
23214 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0) {
23215 reduceData(cellId, &coupling(0), nDim,
false);
23216 reduceData(cellId, &(pVariables(0, 0)), m_noPVars);
23217 reduceData(cellId, &(cVariables(0, 0)), m_noCVars);
23218 reduceData(cellId, &(oldVariables(0, 0)), m_noCVars);
23224 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23225 if(a_isHalo(cellId))
continue;
23226 if(a_isBndryGhostCell(cellId))
continue;
23227 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
23228 if(a_level(cellId) != fftLevel)
continue;
23234 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23235 if(a_isHalo(cellId))
continue;
23236 if(a_isBndryGhostCell(cellId))
continue;
23237 if(a_level(cellId) != fftLevel)
continue;
23238 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
23239 MFloat actualCellLength = c_cellLengthAtCell(cellId);
23240 MInt xPos = floor((F1B2 * nx + (a_coordinate(cellId, 0) - F1B2 * (actualCellLength)) / dx) + 0.1);
23241 MInt yPos = floor((F1B2 * ny + (a_coordinate(cellId, 1) - F1B2 * (actualCellLength)) / dx) + 0.1);
23242 MInt zPos = floor((F1B2 * nz + (a_coordinate(cellId, 2) - F1B2 * (actualCellLength)) / dx) + 0.1);
23243 if(xPos > nx - 1 || xPos < 0 || yPos > ny - 1 || yPos < 0 || zPos > nz - 1 || zPos < 0) {
23244 cerr <<
"ERROR: wrong array position!" << endl;
23245 cerr <<
"pos=" << xPos <<
", " << yPos <<
", " << zPos << endl;
23246 cerr <<
"coorda = (" << a_coordinate(cellId, 0) <<
", " << a_coordinate(cellId, 1) <<
", "
23247 << a_coordinate(cellId, 2) <<
")" << endl;
23248 cerr <<
"actuallength=" << actualCellLength << endl;
23249 cerr <<
"minlevel=" << minLevel() <<
", maxLevel=" << maxLevel() << endl;
23250 cerr <<
"lenght on level0=" << c_cellLengthAtLevel(0) << endl;
23251 mTerm(1, AT_,
"Wrong array position");
23253 MInt pos = zPos + nz * (yPos + ny * xPos);
23254 for(
MInt i = 0; i < nDim; i++) {
23255 velDat(noLocDat, i) = pVariables(cellId, PV->VV[i]) / m_UInfinity;
23256 velDat(noLocDat, nDim + i) = coupling(cellId, i) * DX / (grid().gridCellVolume(fftLevel) *
POW2(m_UInfinity));
23257 MFloat u1 = cVariables(cellId, CV->RHO_VV[i]) / cVariables(cellId, CV->RHO);
23258 MFloat u0 = oldVariables(cellId, CV->RHO_VV[i]) / oldVariables(cellId, CV->RHO);
23259 velDat(noLocDat, 2 * nDim + i) = ((u1 - u0) / timeStep()) * DX /
POW2(m_UInfinity);
23261 if(m_noPointParticles > 0 && m_pointParticleTwoWayCoupling > 0) {
23262 for(
MInt i = 0; i < nDim; i++) {
23263 velDat(noLocDat, nDim + i) =
23264 m_coupling[cellId][i] * (DX / (grid().gridCellVolume(fftLevel) *
POW2(m_UInfinity)));
23267 velPos(noLocDat) = pos;
23272 F1 / (sysEqn().m_Re0 * DX * m_UInfinity), mpiComm());
23274 RECORD_TIMER_STOP(t_fft);
23277 m_firstStats =
false;
23279 RECORD_TIMER_STOP(t_timertotal);
23280 DISPLAY_TIMER(t_timertotal);
23284template <MInt nDim,
class SysEqn>
23287 if(m_noEmbeddedBodies > 0) {
23288 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23289 if(a_bndryId(cellId) < -1)
continue;
23290 if(a_isHalo(cellId))
continue;
23291 if(a_isPeriodic(cellId))
continue;
23292 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
23294 if(a_levelSetValuesMb(cellId, 0) < F0 || a_bndryId(cellId) >= m_noOuterBndryCells) {
23295 if(m_associatedBodyIds[IDX_LSSETMB(cellId, 0)] < 0
23296 || m_associatedBodyIds[IDX_LSSETMB(cellId, 0)] > m_noEmbeddedBodies + m_noPeriodicGhostBodies) {
23297 cerr << domainId() <<
": negative body id B " << m_associatedBodyIds[IDX_LSSETMB(cellId, 0)] <<
" "
23298 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" "
23299 << a_hasProperty(cellId, SolverCell::IsSplitChild) << endl;
23302 MInt bodyId = m_internalBodyId[m_associatedBodyIds[IDX_LSSETMB(cellId, 0)]];
23303 MFloat svol = grid().gridCellVolume(a_level(cellId));
23304 if(a_bndryId(cellId) > -1) svol -= a_cellVolume(cellId);
23305 partVol(bodyId) += svol;
23306 if(a_bndryId(cellId) < 0 && a_hasProperty(cellId, SolverCell::IsInactive)) a_cellVolume(cellId) = F0;
23309 MPI_Allreduce(MPI_IN_PLACE, &partVol[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23313 cerr0 <<
"computeBodyVolume skipped since there are no Bodies." << endl;
23326template <MInt nDim,
class SysEqn>
23329 MFloat* rotation,
const vector<MFloat>& setup,
MInt* skipBodies,
MFloat* meanBodyState,
MFloat* pressure,
23333 if(m_noEmbeddedBodies == 0)
return;
23335 const MFloat minDist = (setup.size() >= 1 ? setup[0] : 0.5) * m_bodyDiameter[0];
23336 const MFloat maxDist = (setup.size() >= 2 ? setup[1] : 4.0) * m_bodyDiameter[0];
23337 const MFloat maxAngleVel = (setup.size() >= 3 ? setup[2] : F0);
23338 const MFloat maxAngleRot = (setup.size() >= 4 ? setup[3] : F0);
23339 const MFloat sigma = (setup.size() >= 5 ? setup[2] : (maxDist - minDist) / 6.0);
23340 const MFloat D0 = (setup.size() >= 6 ? setup[3] : (maxDist + minDist) / F2);
23342 if(minDist > maxDist || maxAngleVel < -F1 || maxAngleRot < -F1) {
23343 cerr <<
"computeNearBodyFluidVelocity: wrong setup " << endl;
23347 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23348 for(
MInt i = 0; i < nDim; i++) {
23349 vel[
b * nDim + i] = F0;
23350 rotation[
b * nDim + i] = F0;
23351 for(
MInt j = 0; j < nDim; j++) {
23352 velGrad[
b * nDim * nDim + i * nDim + j] = F0;
23357 if(nearestFac != NULL) {
23358 std::fill_n(nearestFac, m_maxNearestBodies * a_noCells(), F0);
23362 MFloatScratchSpace vel0((velDt || rotationDt || meanBodyState) ? m_noEmbeddedBodies : 1, nDim, AT_,
"vel0");
23366 vector<vector<MInt>> velCells(m_noEmbeddedBodies);
23367 vector<vector<MInt>> rotCells(m_noEmbeddedBodies);
23368 MInt noLeafCells = 0;
23375 for(
MInt bodyId = 0; bodyId < m_noEmbeddedBodies; bodyId++) {
23376 skipBody(bodyId) = 0;
23377 MFloat hydroForceAbs = F0;
23378 for(
MInt i = 0; i < nDim; i++) {
23379 hydroForceAbs +=
POW2(m_hydroForce[bodyId * nDim + i]);
23381 if(hydroForceAbs < 1e-12) {
23382 skipBody(bodyId) = 1;
23385 if(m_bodyInCollision[bodyId] > 0) {
23386 skipBody(bodyId) = 1;
23390 m_log <<
"computeNearBodyFluidVelocities: noBodies skipped (small Body force): " << cnt1 <<
" collision: " << cnt2
23391 <<
" " << minDist / m_bodyDiameter[0] <<
" " << maxDist / m_bodyDiameter[0] <<
" " << maxAngleVel << endl;
23394 MLong smallGradPhi = 0;
23395 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23396 if(a_isBndryGhostCell(cellId))
continue;
23397 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
23398 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
23399 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
23400 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
23401 if(a_hasProperty(cellId, SolverCell::IsSplitChild) ? a_hasProperty(getAssociatedInternalCell(cellId), Cell::IsHalo)
23402 : a_hasProperty(cellId, Cell::IsHalo))
23404 if(a_hasProperty(cellId, SolverCell::IsSplitChild) ? a_isPeriodic(getAssociatedInternalCell(cellId))
23405 : a_isPeriodic(cellId))
23407 leafCells(noLeafCells++) = cellId;
23408 for(
MInt nb = 0; nb < m_maxNearestBodies; nb++) {
23409 const MInt bodyId0 = nearestBodies[m_maxNearestBodies * cellId + nb];
23410 if(bodyId0 < 0)
continue;
23411 const MInt bodyId = m_internalBodyId[bodyId0];
23412 if(skipBody(bodyId))
continue;
23413 const MFloat phi = nearestDist[m_maxNearestBodies * cellId + nb];
23414 if(phi > minDist && phi < maxDist) {
23415 MFloat gradPhi[3] = {F0, F0, F0};
23416 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
23417 cerr <<
"debug state splitChild in CNBFV 1"
23418 <<
" remove this message, if it was reached and everything went fine" << endl;
23419 MInt splitChildBndryId = a_bndryId(cellId);
23420 if(m_bndryCells->a[splitChildBndryId].m_noSrfcs > 1)
23421 cerr <<
"SplitChilds due to collision should not appear here." << endl;
23422 for(
MInt i = 0; i < nDim; i++) {
23423 gradPhi[i] = m_fvBndryCnd->m_bndryCells->a[splitChildBndryId].m_srfcs[0]->m_normalVector[i];
23426 for(
MInt i = 0; i < nDim; i++) {
23427 MInt n0 = (a_hasNeighbor(cellId, 2 * i,
false) > 0) ? c_neighborId(cellId, 2 * i,
false) : cellId;
23428 MInt n1 = (a_hasNeighbor(cellId, 2 * i + 1,
false) > 0) ? c_neighborId(cellId, 2 * i + 1,
false) : cellId;
23429 if(n0 > -1 && n1 > -1) {
23431 for(nb0 = 0; nb0 < m_maxNearestBodies; nb0++) {
23432 if(nearestBodies[m_maxNearestBodies * n0 + nb0] == bodyId0)
break;
23434 for(nb1 = 0; nb1 < m_maxNearestBodies; nb1++) {
23435 if(nearestBodies[m_maxNearestBodies * n1 + nb1] == bodyId0)
break;
23437 if(nb0 < m_maxNearestBodies && nb1 < m_maxNearestBodies) {
23438 gradPhi[i] = (nearestDist[m_maxNearestBodies * n1 + nb1] - nearestDist[m_maxNearestBodies * n0 + nb0])
23439 / (a_coordinate(n1, i) - a_coordinate(n0, i));
23444 MFloat distDotVelGuess = F0;
23446 MFloat hydroForceAbs = F0;
23447 for(
MInt i = 0; i < nDim; i++) {
23448 distDotVelGuess += gradPhi[i] * m_hydroForce[bodyId * nDim + i];
23449 gradPhiAbs +=
POW2(gradPhi[i]);
23450 hydroForceAbs +=
POW2(m_hydroForce[bodyId * nDim + i]);
23452 if(gradPhiAbs < 1e-12) {
23456 MFloat angle = distDotVelGuess / sqrt(gradPhiAbs * hydroForceAbs);
23457 if(angle < maxAngleVel) {
23458 MFloat velWeight = a_cellVolume(cellId);
23459 MFloat distanceBasedWeight = F1 / sqrt(F2 * PI *
POW2(sigma)) * exp(-
POW2(phi - D0) / (F2 *
POW2(sigma)));
23460 velWeight *= distanceBasedWeight;
23461 weights(bodyId) += velWeight;
23462 for(
MInt i = 0; i < nDim; i++) {
23463 vel[bodyId * nDim + i] += velWeight * a_pvariable(cellId, PV->VV[i]);
23465 if(nearestFac != NULL) {
23466 nearestFac[m_maxNearestBodies * cellId + nb] += velWeight;
23468 velCells[bodyId].push_back(cellId);
23469 if(velDt || rotationDt || meanBodyState) {
23470 for(
MInt i = 0; i < nDim; i++) {
23471 vel0(bodyId, i) += velWeight * a_oldVariable(cellId, CV->RHO_VV[i]) / a_oldVariable(cellId, CV->RHO);
23475 if(distDotVelGuess / sqrt(gradPhiAbs * hydroForceAbs) < maxAngleRot) {
23476 rotCells[bodyId].push_back(cellId);
23482 MLong globalSmallGradPhi = 0;
23483 MPI_Reduce(&smallGradPhi, &globalSmallGradPhi, 1, MPI_LONG, MPI_SUM, 0, mpiComm(), AT_,
"smallGradPhi",
23484 "globalSmallGradPhi");
23485 if(globalSmallGradPhi > 0) {
23486 m_log <<
"Skipping cells for nearBodyFluidVelocities (small gradPhi) " << globalSmallGradPhi <<
" "
23487 << minDist / m_bodyDiameter[0] <<
" " << maxDist / m_bodyDiameter[0] <<
" " << maxAngleVel << endl;
23490 MPI_Allreduce(MPI_IN_PLACE, &vel[0], nDim * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23492 MPI_Allreduce(MPI_IN_PLACE, &weights[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23495 if(velDt || rotationDt || meanBodyState) {
23496 MPI_Allreduce(MPI_IN_PLACE, &vel0[0], nDim * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
23497 "MPI_IN_PLACE",
"vel0[0]");
23500 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23501 if((weights(
b) < 1e-10) && !skipBody(
b)) {
23502 if(domainId() == 0)
23503 cerr << setprecision(12) <<
"Warning: near body velocity interpolation " <<
b <<
" " << weights(
b) <<
" "
23504 << minDist / m_bodyDiameter[0] <<
" " << maxDist / m_bodyDiameter[0] <<
" " << maxAngleVel << endl;
23507 for(
MInt i = 0; i < nDim; i++) {
23508 vel[
b * nDim + i] /=
mMax(1e-10, weights(
b));
23509 if(velDt || rotationDt || meanBodyState) vel0(
b, i) /=
mMax(1e-10, weights(
b));
23513 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23514 for(
MInt i = 0; i < nDim; i++) {
23515 velDt[
b * nDim + i] = vel0(
b, i);
23520 if(nearestFac != NULL) {
23521 for(
MInt c = 0; c < noLeafCells; c++) {
23522 MInt cellId = leafCells(c);
23523 for(
MInt nb = 0; nb < m_maxNearestBodies; nb++) {
23524 const MInt bodyId0 = nearestBodies[m_maxNearestBodies * cellId + nb];
23525 if(bodyId0 < 0)
continue;
23526 const MInt bodyId = m_internalBodyId[bodyId0];
23527 nearestFac[m_maxNearestBodies * cellId + nb] /= weights(bodyId);
23533 for(
MInt bodyId = 0; bodyId < m_noEmbeddedBodies; bodyId++) {
23534 for(
auto const& cellId : rotCells[bodyId]) {
23537 for(
MInt nb = 0; nb < m_maxNearestBodies; nb++) {
23538 if(nearestBodies[m_maxNearestBodies * cellId + nb] > -1
23539 && m_internalBodyId[nearestBodies[m_maxNearestBodies * cellId + nb]] == bodyId) {
23540 bodyId0 = nearestBodies[m_maxNearestBodies * cellId + nb];
23541 phi = nearestDist[m_maxNearestBodies * cellId + nb];
23543 cerr <<
"bodyId not found " << bodyId0 <<
" bodyId " << bodyId <<
" domainId() " << domainId() << endl;
23544 MFloat gradPhi[3] = {F0, F0, F0};
23545 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
23546 cerr <<
"debug state splitChild in CNBFV 2"
23547 <<
" remove this message, if it was reached and everything went fine" << endl;
23548 MInt splitChildBndryId = a_bndryId(cellId);
23549 if(m_bndryCells->a[splitChildBndryId].m_noSrfcs > 1)
23550 cerr <<
"SplitChilds due to collision should not appear here." << endl;
23551 for(
MInt i = 0; i < nDim; i++) {
23552 gradPhi[i] = m_fvBndryCnd->m_bndryCells->a[splitChildBndryId].m_srfcs[0]->m_normalVector[i];
23555 for(
MInt i = 0; i < nDim; i++) {
23556 MInt n0 = (a_hasNeighbor(cellId, 2 * i,
false) > 0) ? c_neighborId(cellId, 2 * i,
false) : cellId;
23557 MInt n1 = (a_hasNeighbor(cellId, 2 * i + 1,
false) > 0) ? c_neighborId(cellId, 2 * i + 1,
false) : cellId;
23558 if(n0 == n1) cerr <<
"wrong neighbors" << endl;
23559 if(n0 > -1 && n1 > -1) {
23561 for(nb0 = 0; nb0 < m_maxNearestBodies; nb0++) {
23562 if(nearestBodies[m_maxNearestBodies * n0 + nb0] == bodyId0)
break;
23564 for(nb1 = 0; nb1 < m_maxNearestBodies; nb1++) {
23565 if(nearestBodies[m_maxNearestBodies * n1 + nb1] == bodyId0)
break;
23567 if(nb0 < m_maxNearestBodies && nb1 < m_maxNearestBodies) {
23568 gradPhi[i] = (nearestDist[m_maxNearestBodies * n1 + nb1] - nearestDist[m_maxNearestBodies * n0 + nb0])
23569 / (a_coordinate(n1, i) - a_coordinate(n0, i));
23576 for(
MInt i = 0; i < nDim; i++) {
23577 gradPhiAbs +=
POW2(gradPhi[i]);
23579 if(gradPhiAbs < 1e-12) {
23590 MFloat rotWeight = a_cellVolume(cellId);
23591 MFloat distanceBasedWeight = F1 / sqrt(F2 * PI *
POW2(sigma)) * exp(-
POW2(phi - D0) / (F2 *
POW2(sigma)));
23592 rotWeight *= distanceBasedWeight;
23593 for(
MInt i = 0; i < nDim; i++) {
23594 rad[i] = a_coordinate(cellId, i) - m_bodyCenter[bodyId0 * nDim + i];
23595 vpr[i] = a_pvariable(cellId, PV->VV[i]) - vel[bodyId * nDim + i];
23596 r2 +=
POW2(rad[i]);
23597 for(
MInt j = 0; j < nDim; j++) {
23598 velGrad[bodyId * nDim * nDim + i * nDim + j] += rotWeight * a_slope(cellId, PV->VV[i], j);
23601 crossProduct(rot, rad, vpr);
23602 for(
MInt i = 0; i < nDim; i++) {
23603 rotation[bodyId * nDim + i] += rotWeight * rot[i] / r2;
23605 if(velDt || rotationDt || meanBodyState) {
23606 for(
MInt i = 0; i < nDim; i++) {
23607 rad0[i] = a_coordinate(cellId, i)
23608 - (m_bodyCenter[bodyId0 * nDim + i] + m_bodyCenterDt1[bodyId * nDim + i]
23609 - m_bodyCenter[bodyId * nDim + i]);
23610 vpr0[i] = a_oldVariable(cellId, CV->RHO_VV[i]) / a_oldVariable(cellId, CV->RHO) - vel0(bodyId, i);
23611 r20 +=
POW2(rad0[i]);
23613 crossProduct(rot0, rad0, vpr0);
23616 for(
MInt i = 0; i < nDim; i++) {
23617 rotationDt[bodyId * nDim + i] += rotWeight * (rot0[i] / r20);
23620 weights(bodyId) += rotWeight;
23626 MPI_Allreduce(MPI_IN_PLACE, &weights[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23628 MPI_Allreduce(MPI_IN_PLACE, &velGrad[0], nDim * nDim * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
23629 "MPI_IN_PLACE",
"velGrad[0]");
23630 MPI_Allreduce(MPI_IN_PLACE, &rotation[0], nDim * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
23631 "MPI_IN_PLACE",
"rotation[0]");
23633 MPI_Allreduce(MPI_IN_PLACE, &rotationDt[0], nDim * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
23634 "MPI_IN_PLACE",
"rotationDt[0]");
23636 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23637 if(domainId() == 0 && weights(
b) < 1e-10 && !skipBody(
b)) {
23638 cerr << setprecision(12) <<
"Warning: near body velocity gradient interpolation " <<
b <<
" " << weights(
b) <<
" "
23639 << minDist / m_bodyDiameter[0] <<
" " << maxDist / m_bodyDiameter[0] <<
" " << maxAngleRot << endl;
23641 for(
MInt i = 0; i < nDim; i++) {
23642 rotation[
b * nDim + i] /=
mMax(1e-10, weights(
b));
23643 for(
MInt j = 0; j < nDim; j++) {
23644 velGrad[
b * nDim * nDim + i * nDim + j] /=
mMax(1e-10, weights(
b));
23650 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23651 for(
MInt i = 0; i < nDim; i++) {
23652 rotationDt[
b * nDim + i] /=
mMax(1e-10, weights(
b));
23657 if(meanBodyState && pressure) {
23658 const MInt noNearBodyState = 5;
23660 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23662 for(
MInt i = 0; i < noNearBodyState; i++) {
23663 meanBodyState[noNearBodyState *
b + i] = F0;
23667 for(
MInt c = 0; c < noLeafCells; c++) {
23668 MInt cellId = leafCells(c);
23669 for(
MInt nb = 0; nb < m_maxNearestBodies; nb++) {
23670 const MInt bodyId0 = nearestBodies[m_maxNearestBodies * cellId + nb];
23671 if(bodyId0 < 0)
continue;
23672 const MInt bodyId = m_internalBodyId[bodyId0];
23674 const MFloat phi = nearestDist[m_maxNearestBodies * cellId + nb];
23675 MFloat weight = a_cellVolume(cellId);
23676 MFloat distanceBasedWeight = F1 / sqrt(F2 * PI *
POW2(sigma)) * exp(-
POW2(phi - D0) / (F2 *
POW2(sigma)));
23677 weight *= distanceBasedWeight;
23678 pressure[bodyId] += weight * a_pvariable(cellId, PV->P);
23679 weights(bodyId) += weight;
23681 for(
MInt i = 0; i < nDim; i++) {
23682 for(
MInt j = 0; j < nDim; j++) {
23683 eps1 += F1B2 * (sysEqn().m_muInfinity / sysEqn().m_Re0)
23684 *
POW2(a_slope(cellId, PV->VV[i], j) + a_slope(cellId, PV->VV[j], i));
23688 if(phi < 0.5 * m_bodyDiameter[bodyId]) meanBodyState[noNearBodyState * bodyId] += a_cellVolume(cellId) * eps1;
23689 if(phi < 1.0 * m_bodyDiameter[bodyId])
23690 meanBodyState[noNearBodyState * bodyId + 1] += a_cellVolume(cellId) * eps1;
23691 if(phi < 1.5 * m_bodyDiameter[bodyId])
23692 meanBodyState[noNearBodyState * bodyId + 2] += a_cellVolume(cellId) * eps1;
23693 if(phi < 2.0 * m_bodyDiameter[bodyId])
23694 meanBodyState[noNearBodyState * bodyId + 3] += a_cellVolume(cellId) * eps1;
23695 if(phi < 2.5 * m_bodyDiameter[bodyId])
23696 meanBodyState[noNearBodyState * bodyId + 4] += a_cellVolume(cellId) * eps1;
23700 MPI_Allreduce(MPI_IN_PLACE, &weights[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23702 MPI_Allreduce(MPI_IN_PLACE, &pressure[0], m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
23704 MPI_Allreduce(MPI_IN_PLACE, &meanBodyState[0], noNearBodyState * m_noEmbeddedBodies, MPI_DOUBLE, MPI_SUM, mpiComm(),
23705 AT_,
"MPI_IN_PLACE",
"meanBodyState[0]");
23707 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23708 if(domainId() == 0 && weights(
b) < 1e-10 && !skipBody(
b)) {
23709 cerr <<
"Warning: near body pressure interpolation " <<
b <<
" " << weights(
b) / m_bodyVolume[
b] <<
" "
23710 << minDist / m_bodyDiameter[0] <<
" " << maxDist / m_bodyDiameter[0] <<
" " << maxAngleVel << endl;
23712 pressure[
b] /=
mMax(1e-10, weights(
b));
23718 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
23719 skipBodies[
b] = skipBody(
b);
23720 if(skipBody(
b)) cnt++;
23722 if(domainId() == 0 && cnt > 0 &&
globalTimeStep % m_dragOutputInterval == 0)
23723 m_log <<
"computeNearBodyFluidVelocities: noBodies skipped " << cnt <<
" (" <<
globalTimeStep <<
")" << endl;
23732template <MInt nDim,
class SysEqn>
23734 writeVtkXmlFiles(
"Q_ERR",
"G_ERR", 0, 0);
23742template <MInt nDim,
class SysEqn>
23749 const MBool correctCoords = m_fvBndryCnd->m_cellCoordinatesCorrected;
23750 if(correctCoords) m_fvBndryCnd->recorrectCellCoordinates();
23753 m_haloCellOutput =
true;
23754 m_vtuGeometryOutputExtended =
true;
23755 m_vtuGlobalIdOutput =
true;
23756 m_vtuDomainIdOutput =
true;
23757 m_vtuLevelSetOutput =
false;
23758 m_vtuVelocityGradientOutput =
true;
23760 restoreNeighbourLinks();
23761 IF_CONSTEXPR(nDim == 3) {
23762 if(
true || regularOutput || noDomains() > 24) {
23763 extractPointIdsFromGrid(m_extractedCells, m_gridPoints,
false, m_splitChildToSplitCell, m_vtuLevelThreshold,
23764 m_vtuCoordinatesThreshold);
23765 if(m_vtuLevelThreshold < maxRefinementLevel()) reduceVariables();
23766 deleteNeighbourLinks();
23767 MInt noSolverSpecificVars = (m_vtuLevelSetOutput > 0 ? 1 : 0);
23768 MFloatScratchSpace levelSetOutput((noSolverSpecificVars > 0 ? a_noCells() : 1), AT_,
"levelSetOutput");
23769 if(m_vtuLevelSetOutput) {
23770 noSolverSpecificVars = 1;
23771 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
23772 levelSetOutput(cellId) = a_levelSetValuesMb(cellId, 0);
23777 if(!m_multipleFvSolver) {
23778 fName = m_solutionOutput + fileName +
"_00" + to_string(
globalTimeStep) +
".vtu";
23779 gName = m_solutionOutput + GFileName +
"_00" + to_string(
globalTimeStep) +
".vtp";
23781 fName = m_solutionOutput + fileName +
"_s" + to_string(solverId()) +
"_00" + to_string(
globalTimeStep) +
".vtu";
23783 m_solutionOutput + GFileName +
"_s" + to_string(solverId()) +
"_00" + to_string(
globalTimeStep) +
".vtp";
23785 if(m_solutionDiverged && !m_multipleFvSolver) {
23786 fName = m_solutionOutput + fileName +
"_diverged_00" + to_string(
globalTimeStep) +
".vtu";
23787 gName = m_solutionOutput + GFileName +
"_diverged_00" + to_string(
globalTimeStep) +
".vtp";
23788 }
else if(m_solutionDiverged) {
23789 fName = m_solutionOutput + fileName +
"_s" + to_string(solverId()) +
"_diverged_00" + to_string(
globalTimeStep)
23791 gName = m_solutionOutput + GFileName +
"_s" + to_string(solverId()) +
"_diverged_00" + to_string(
globalTimeStep)
23794 if(domainId() == 0) {
23795 cerr <<
"Writing " << fName <<
" at time step " <<
globalTimeStep <<
"... ";
23800 cerr0 <<
"finished." << endl;
23802 extractPointIdsFromGrid(m_extractedCells, m_gridPoints,
true, m_splitChildToSplitCell);
23803 MString fName = m_solutionOutput + fileName +
"_B" + to_string(domainId());
23804 MString gName = m_solutionOutput + GFileName +
"_B" + to_string(domainId());
23805 if(diverged) fName +=
"_diverged";
23806 if(diverged) gName +=
"_diverged";
23809 cerr << endl <<
"Saving '" << fName <<
"' at time " << setprecision(6) << m_physicalTime <<
"...";
23810 writeVtkXmlOutput(fName.c_str(), (diverged || !regularOutput));
23811 writeGeometryToVtkXmlFile(gName.c_str());
23812 cerr <<
" finished." << endl;
23816 extractPointIdsFromGrid(m_extractedCells, m_gridPoints, m_haloCellOutput, m_splitChildToSplitCell);
23817 deleteNeighbourLinks();
23819 stringstream QName;
23820 QName << m_solutionOutput <<
"solver_data/" << fileName <<
"_B" << domainId();
23822 if(diverged) QName <<
"_diverged";
23825 DEBUG_LOG(
"Rank " << domainId() <<
" saving '" << QName.str() <<
"' at time " << setprecision(6) << m_physicalTime
23827 if(domainId() == 0)
23828 cerr << endl <<
"Saving '" << QName.str() <<
"' at time " << setprecision(6) << m_physicalTime <<
"...";
23830 writeVtkXmlOutput((QName.str()).c_str(), (diverged || !regularOutput));
23832 DEBUG_LOG(
" finished (" << domainId() <<
").");
23833 cerr0 <<
" finished." << endl;
23836 MInt noPolygons = 0;
23839 IF_CONSTEXPR(nDim == 3 && m_vtuWriteGeometryFile) {
23840 stringstream GName;
23841 GName << m_solutionOutput <<
"solver_data/" << GFileName <<
"_B" << domainId();
23843 if(diverged) GName <<
"_diverged";
23846 DEBUG_LOG(
"Rank " << domainId() <<
" saving '" << GName.str() <<
"' at time " << setprecision(6) << m_physicalTime
23849 noPolygons = writeGeometryToVtkXmlFile(GName.str());
23851 DEBUG_LOG(
" .. finished (" << domainId() <<
").");
23853 if(regularOutput) {
23856 for(
MInt c = 0; c < noDomains(); c++) {
23857 noPolysLocal[c] = 0;
23859 noPolysLocal[domainId()] = noPolygons;
23860 MPI_Reduce(noPolysLocal, noPolysGlobal, noDomains(), MPI_INT, MPI_SUM, 0, mpiComm(), AT_,
"noPolysLocal",
23863 noPolysGlobal[0] = noPolygons;
23868 if(noDomains() > 1)
23869 MPI_Gather(&m_noLsMbBndryCells, 1, MPI_INT, &(noLsMbCells[0]), 1, MPI_INT, 0, mpiComm(), AT_,
23870 "m_noLsMbBndryCells",
"(noLsMbCells[0])");
23873 if(domainId() == 0 && regularOutput) {
23877 DEBUG_LOG(
"Writing QOUT.pvd file...");
23879 MBool& firstCall = m_static_writeVtkXmlFiles_firstCall;
23882 rename(
"out/QOUT.pvd",
"out/QOUT_BU.pvd");
23885 remove(
"out/QOUT.pvd.tmp");
23887 ofstream ofile(
"out/QOUT.pvd.tmp", ios_base::out | ios_base::trunc);
23888 if(ofile.is_open() && ofile.good()) {
23889 ofile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
23890 ofile <<
"<Collection>" << endl;
23892 if(m_solutionTimeSteps.empty()) {
23894 for(
MInt p = 0; p < noDomains(); p++) {
23896 tmp <<
"out/solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu";
23898 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" << t <<
"\" file=\""
23899 <<
"./solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu\"/>" << endl;
23904 for(std::set<MInt>::iterator it = m_solutionTimeSteps.begin(); it != m_solutionTimeSteps.end(); it++) {
23906 for(
MInt p = 0; p < noDomains(); p++) {
23908 tmp <<
"out/solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu";
23910 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" << t <<
"\" file=\""
23911 <<
"./solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu\"/>" << endl;
23920 cerr <<
"Error opening file out/QOUT.pvd.tmp" << endl;
23924 ofstream ofile(
"out/QOUT_all.pvd", ios_base::out | ios_base::trunc);
23925 if(ofile.is_open() && ofile.good()) {
23926 ofile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
23927 ofile <<
"<Collection>" << endl;
23928 if(m_solutionTimeSteps.empty()) {
23929 MInt t = m_solutionOffset;
23930 MBool found =
true;
23932 for(
MInt p = 0; p < noDomains(); p++) {
23934 tmp <<
"out/solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu";
23936 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" << t <<
"\" file=\""
23937 <<
"./solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu\"/>" << endl;
23942 t += m_solutionInterval;
23945 std::set<MInt>::iterator it = m_solutionTimeSteps.begin();
23947 MBool found =
true;
23949 for(
MInt p = 0; p < noDomains(); p++) {
23951 tmp <<
"out/solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu";
23953 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" << t <<
"\" file=\""
23954 <<
"./solver_data/" << fileName <<
"_B" << p <<
"_00" << t <<
".vtu\"/>" << endl;
23962 ofile <<
"</Collection>" << endl;
23963 ofile <<
"</VTKFile>" << endl;
23967 cerr <<
"Error opening file out/QOUT_all.pvd" << endl;
23970 ofstream ofile(
"out/QOUT.pvd.tmp", ios_base::out | ios_base::app);
23971 if(ofile.is_open() && ofile.good()) {
23972 for(
MInt p = 0; p < noDomains(); p++) {
23973 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" <<
globalTimeStep <<
"\" file=\""
23974 <<
"./solver_data/" << fileName <<
"_B" << p <<
"_00" <<
globalTimeStep <<
".vtu\"/>" << endl;
23979 cerr <<
"Error opening file out/QOUT.pvd.tmp" << endl;
23983 remove(
"out/QOUT.pvd");
23985 copyFile(
"out/QOUT.pvd.tmp",
"out/QOUT.pvd");
23986 ofstream ofile2(
"out/QOUT.pvd", ios_base::out | ios_base::app);
23987 if(ofile2.is_open() && ofile2.good()) {
23988 ofile2 <<
"</Collection>" << endl;
23989 ofile2 <<
"</VTKFile>" << endl;
23992 cerr <<
"Error opening file out/QOUT.pvd" << endl;
23996 DEBUG_LOG(
"finished.");
24002 IF_CONSTEXPR(nDim == 3 && m_vtuWriteGeometryFile) {
24003 DEBUG_LOG(
"Writing GEOM.pvd file...");
24005 MBool& firstCall2 = m_static_writeVtkXmlFiles_firstCall2;
24008 rename(
"out/GEOM.pvd",
"out/GEOM_BU.pvd");
24011 remove(
"out/GEOM.pvd.tmp");
24013 ofstream ofile(
"out/GEOM.pvd.tmp", ios_base::out | ios_base::trunc);
24014 if(ofile.is_open() && ofile.good()) {
24015 ofile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
24016 ofile <<
"<Collection>" << endl;
24018 if(m_solutionTimeSteps.empty()) {
24021 for(
MInt p = 0; p < noDomains(); p++) {
24023 fn <<
"out/solver_data/" << GFileName <<
"_B" << p <<
"_00" << t;
24025 ofile <<
"<DataSet part=\"" << cnt <<
"\" group=\"\" timestep=\"" << t <<
"\" file=\""
24026 <<
"./solver_data/" << GFileName <<
"_B" << p <<
"_00" << t <<
".vtp\"/>" << endl;
24032 for(std::set<MInt>::iterator it = m_solutionTimeSteps.begin(); it != m_solutionTimeSteps.end(); it++) {
24035 for(
MInt p = 0; p < noDomains(); p++) {
24037 fn <<
"out/solver_data/" << GFileName <<
"_B" << p <<
"_00" << t;
24039 ofile <<
"<DataSet part=\"" << cnt <<
"\" group=\"\" timestep=\"" << t <<
"\" file=\""
24040 <<
"./solver_data/" << GFileName <<
"_B" << p <<
"_00" << t <<
".vtp\"/>" << endl;
24050 cerr <<
"Error opening file out/GEOM.pvd.tmp" << endl;
24054 ofstream ofile(
"out/GEOM_all.pvd", ios_base::out | ios_base::trunc);
24055 if(ofile.is_open() && ofile.good()) {
24056 ofile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
24057 ofile <<
"<Collection>" << endl;
24058 if(m_solutionTimeSteps.empty()) {
24059 MInt t = m_solutionOffset;
24060 MBool found =
true;
24063 for(
MInt p = 0; p < noDomains(); p++) {
24065 fn <<
"out/solver_data/" << GFileName <<
"_B" << p <<
"_00" << t <<
".vtp";
24067 ofile <<
"<DataSet part=\"" << cnt <<
"\" group=\"\" timestep=\"" << t <<
"\" file=\""
24068 <<
"./solver_data/" << GFileName <<
"_B" << p <<
"_00" << t <<
".vtp\"/>" << endl;
24075 t += m_solutionInterval;
24078 std::set<MInt>::iterator it = m_solutionTimeSteps.begin();
24080 MBool found =
true;
24083 for(
MInt p = 0; p < noDomains(); p++) {
24085 fn <<
"out/solver_data/" << GFileName <<
"_B" << p <<
"_00" << t <<
".vtp";
24087 ofile <<
"<DataSet part=\"" << cnt <<
"\" group=\"\" timestep=\"" << t <<
"\" file=\""
24088 <<
"./solver_data/" << GFileName <<
"_B" << p <<
"_00" << t <<
".vtp\"/>" << endl;
24098 ofile <<
"</Collection>" << endl;
24099 ofile <<
"</VTKFile>" << endl;
24103 cerr <<
"Error opening file out/GEOM_all.pvd" << endl;
24106 ofstream ofile(
"out/GEOM.pvd.tmp", ios_base::out | ios_base::app);
24107 if(ofile.is_open() && ofile.good()) {
24109 for(
MInt p = 0; p < noDomains(); p++) {
24110 if(noPolysGlobal[p] > 0) {
24111 ofile <<
"<DataSet part=\"" << cnt <<
"\" group=\"\" timestep=\"" <<
globalTimeStep <<
"\" file=\""
24112 <<
"./solver_data/" << GFileName <<
"_B" << p <<
"_00" <<
globalTimeStep <<
".vtp\"/>" << endl;
24119 cerr <<
"Error opening file out/GEOM.pvd.tmp" << endl;
24123 remove(
"out/GEOM.pvd");
24125 copyFile(
"out/GEOM.pvd.tmp",
"out/GEOM.pvd");
24126 ofstream ofile2(
"out/GEOM.pvd", ios_base::out | ios_base::app);
24127 if(ofile2.is_open() && ofile2.good()) {
24128 ofile2 <<
"</Collection>" << endl;
24129 ofile2 <<
"</VTKFile>" << endl;
24132 cerr <<
"Error opening file out/GEOM.pvd" << endl;
24134 firstCall2 =
false;
24136 DEBUG_LOG(
"finished.");
24141 if(domainId() == 0 && diverged) {
24144 remove(
"out/QOUT_diverged.pvd");
24146 ofstream ofile(
"out/QOUT_diverged.pvd", ios_base::out | ios_base::trunc);
24147 if(ofile.is_open() && ofile.good()) {
24148 ofile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
24149 ofile <<
"<Collection>" << endl;
24150 for(
MInt p = 0; p < noDomains(); p++) {
24152 tmp <<
"out/solver_data/" << fileName <<
"_B" << p <<
"_diverged.vtu";
24154 ofile <<
"<DataSet part=\"" << p <<
"\" timestep=\"" <<
globalTimeStep <<
"\" file=\""
24155 <<
"./solver_data/" << fileName <<
"_B" << p <<
"_diverged.vtu\"/>" << endl;
24158 ofile <<
"</Collection>" << endl;
24159 ofile <<
"</VTKFile>" << endl;
24163 cerr <<
"Error opening file out/QOUT_diverged.pvd" << endl;
24169 remove(
"out/GEOM_diverged.pvd");
24171 ofstream ofile2(
"out/GEOM_diverged.pvd", ios_base::out | ios_base::trunc);
24172 if(ofile2.is_open() && ofile2.good()) {
24173 ofile2 <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
24174 ofile2 <<
"<Collection>" << endl;
24175 for(
MInt p = 0; p < noDomains(); p++) {
24176 if(noLsMbCells(p) > 0) {
24177 ofile2 <<
"<DataSet part=\"" << p <<
"\" timestep=\"" <<
globalTimeStep <<
"\" file=\""
24178 <<
"./solver_data/" << GFileName <<
"_B" << p <<
"_diverged.vtp\"/>" << endl;
24181 ofile2 <<
"</Collection>" << endl;
24182 ofile2 <<
"</VTKFile>" << endl;
24186 cerr <<
"Error opening file out/GEOM_diverged.pvd" << endl;
24191 if(correctCoords) m_fvBndryCnd->rerecorrectCellCoordinates();
24194 if(m_extractedCells) {
24195 delete m_extractedCells;
24196 m_extractedCells =
nullptr;
24199 delete m_gridPoints;
24200 m_gridPoints =
nullptr;
24204 const MInt noBytes = maxNoGridCells() * m_noCVars *
sizeof(
MFloat);
24205 MFloat* RESTRICT cVars = (
MFloat*)(&(a_variable(0, 0)));
24206 MFloat* RESTRICT oCVars = (
MFloat*)(&(a_oldVariable(0, 0)));
24207 memcpy(cVars, oCVars, noBytes);
24208 computePrimitiveVariables();
24209 cerr0 <<
"deactivate m_useNonSpecifiedRestartFile" << endl;
24210 m_useNonSpecifiedRestartFile =
false;
24212 saveRestartFile(
false);
24218 if(m_noPointParticles > 0 && m_noPointParticles < 1000000) {
24225 noPartData(domainId()) = nDim * m_noPointParticlesLocal;
24226 MPI_Allreduce(MPI_IN_PLACE, &noPartData[0], noDomains(), MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
24228 partDataOffsets[0] = 0;
24229 for(
MInt i = 1; i < noDomains(); i++)
24230 partDataOffsets[i] = partDataOffsets[i - 1] + noPartData[i - 1];
24231 MPI_Gatherv(&m_particleCoords[0], noPartData(domainId()), MPI_DOUBLE, &partCoord[0], &noPartData[0],
24232 &partDataOffsets[0], MPI_DOUBLE, 0, mpiComm(), AT_,
"m_particleCoords[0]",
"partCoord[0]");
24233 MPI_Gatherv(&m_particleVelocity[0], noPartData(domainId()), MPI_DOUBLE, &partVel[0], &noPartData[0],
24234 &partDataOffsets[0], MPI_DOUBLE, 0, mpiComm(), AT_,
"m_particleVelocity[0]",
"partVel[0]");
24235 MPI_Gatherv(&m_particleVelocityFluid[0], noPartData(domainId()), MPI_DOUBLE, &partVelFluid[0], &noPartData[0],
24236 &partDataOffsets[0], MPI_DOUBLE, 0, mpiComm(), AT_,
"m_particleVelocityFluid[0]",
"partVelFluid[0]");
24237 MPI_Gatherv(&m_particleRadii[0], noPartData(domainId()), MPI_DOUBLE, &partRadii[0], &noPartData[0],
24238 &partDataOffsets[0], MPI_DOUBLE, 0, mpiComm(), AT_,
"m_particleRadii[0]",
"partRadii[0]");
24240 if(domainId() == 0) {
24241 typedef uint32_t uint_t;
24242 const char*
const uIDataType = (std::is_same<uint_t, uint64_t>::value) ?
"UInt64" :
"UInt32";
24243 const char*
const dataType =
"Float32";
24246 ofl.open(partFileName.c_str(), ios_base::out | ios_base::trunc);
24247 if(ofl.is_open() && ofl.good()) {
24249 ofl <<
"<?xml version=\"1.0\"?>" << endl;
24250 ofl <<
"<VTKFile type=\"PolyData\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">" << endl;
24251 ofl <<
"<PolyData>" << endl;
24254 ofl <<
"<FieldData>" << endl;
24255 ofl <<
"<DataArray type=\"" << uIDataType
24256 <<
"\" Name=\"globalTimeStep\" format=\"ascii\" NumberOfTuples=\"1\" > " <<
globalTimeStep
24257 <<
" </DataArray>" << endl;
24258 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"time\" format=\"ascii\" NumberOfTuples=\"1\" > " << m_time
24259 <<
" </DataArray>" << endl;
24260 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"physicalTime\" format=\"ascii\" NumberOfTuples=\"1\" > "
24261 << m_physicalTime <<
" </DataArray>" << endl;
24262 ofl <<
"</FieldData>" << endl;
24265 ofl <<
"<Piece NumberOfPoints=\"" << m_noPointParticles <<
"\" NumberOfVerts=\"" << m_noPointParticles <<
"\">"
24269 ofl <<
"<Points>" << endl;
24270 ofl << setprecision(12);
24271 ofl <<
"<DataArray type=\"" << dataType <<
"\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
24272 for(
MInt k = 0; k < m_noPointParticles; k++) {
24273 for(
MInt i = 0; i < nDim; i++) {
24274 ofl << partCoord(k, i) <<
" ";
24278 ofl <<
"</DataArray>" << endl;
24279 ofl <<
"</Points>" << endl;
24282 ofl <<
"<Verts>" << endl;
24283 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"connectivity\" format=\"ascii\">" << endl;
24284 for(
MInt k = 0; k < m_noPointParticles; k++) {
24288 ofl <<
"</DataArray>" << endl;
24289 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"offsets\" format=\"ascii\">" << endl;
24290 for(
MInt k = 0; k < m_noPointParticles; k++) {
24291 ofl << k + 1 <<
" ";
24294 ofl <<
"</DataArray>" << endl;
24295 ofl <<
"</Verts>" << endl;
24298 ofl <<
"<PointData Scalars=\"scalars\">" << endl;
24299 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"velocity\" NumberOfComponents=\"3\" format=\"ascii\">"
24301 for(
MInt k = 0; k < m_noPointParticles; k++) {
24302 for(
MInt i = 0; i < nDim; i++) {
24303 ofl << partVel(k, i) <<
" ";
24307 ofl <<
"</DataArray>" << endl;
24308 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Re_p\" NumberOfComponents=\"1\" format=\"ascii\">"
24310 for(
MInt k = 0; k < m_noPointParticles; k++) {
24311 MFloat diameter = F2 * pow(partRadii[3 * k] * partRadii[3 * k + 1] * partRadii[3 * k + 2], F1B3);
24313 for(
MInt i = 0; i < nDim; i++) {
24314 Rep +=
POW2(partVelFluid(k, i) - partVel(k, i));
24316 Rep = sqrt(Rep) * diameter * m_rhoInfinity * sysEqn().m_Re0 / sysEqn().m_muInfinity;
24320 ofl <<
"</DataArray>" << endl;
24321 ofl <<
"</PointData>" << endl;
24323 ofl <<
"</Piece>" << endl;
24324 ofl <<
"</PolyData>" << endl;
24325 ofl <<
"</VTKFile>" << endl;
24329 cerr <<
"ERROR! COULD NOT OPEN FILE " << partFileName <<
" for writing! (1)" << endl;
24340template <MInt nDim,
class SysEqn>
24346 MBool isBinary =
false;
24353 m_noSurfacePointSamples = 0;
24357 stringstream errorMessage;
24358 errorMessage <<
"Error: Unable to find file " << fileName <<
". Quit." << endl;
24359 mTerm(1, AT_, errorMessage.str());
24360 }
else if(isBinary) {
24361 cerr <<
"lacking binary stl code" << endl;
24363 ifile.open(fileName);
24364 if(ifile.is_open()) {
24365 cerr <<
"Reading " << fileName <<
"... ";
24367 getline(ifile, line);
24368 strcpy(cstr, line.c_str());
24369 token = strtok(cstr,
" ");
24370 if(token.compare(0, 5,
"solid", 0, 5) != 0) {
24371 stringstream errorMessage;
24372 errorMessage <<
"Error 1 reading " << fileName <<
". Quit." << endl;
24373 mTerm(1, AT_, errorMessage.str());
24375 while(ifile.good()) {
24376 getline(ifile, line);
24377 if(line ==
"")
continue;
24378 strcpy(cstr, line.c_str());
24379 token = strtok(cstr,
" ");
24380 if(token.compare(0, 5,
"facet", 0, 5) == 0) {
24381 if(noPoints >= m_maxNoSurfacePointSamples) {
24382 mTerm(1, AT_,
"Increase m_maxNoSurfacePointSamples. Quit.");
24386 token = strtok(
nullptr,
" ");
24387 if(token.compare(0, 5,
"normal", 0, 5) != 0) {
24388 stringstream errorMessage;
24389 errorMessage <<
"Error 2 reading " << fileName <<
". Quit." << endl;
24390 mTerm(1, AT_, errorMessage.str());
24393 token = strtok(
nullptr,
" ");
24394 m_sampleNormals[3 * noPoints] = atof(token.c_str());
24395 token = strtok(
nullptr,
" ");
24396 m_sampleNormals[3 * noPoints + 1] = atof(token.c_str());
24397 token = strtok(
nullptr,
" ");
24398 m_sampleNormals[3 * noPoints + 2] = atof(token.c_str());
24402 getline(ifile, line);
24405 getline(ifile, line);
24406 strcpy(cstr, line.c_str());
24407 token = strtok(cstr,
" ");
24408 if(token.compare(0, 6,
"vertex", 0, 6) != 0) {
24409 stringstream errorMessage;
24410 errorMessage <<
"Error 3 reading " << fileName <<
". Quit." << endl;
24411 mTerm(1, AT_, errorMessage.str());
24413 token = strtok(
nullptr,
" ");
24414 a[0] = atof(token.c_str());
24415 token = strtok(
nullptr,
" ");
24416 a[1] = atof(token.c_str());
24417 token = strtok(
nullptr,
" ");
24418 a[2] = atof(token.c_str());
24421 getline(ifile, line);
24422 strcpy(cstr, line.c_str());
24423 token = strtok(cstr,
" ");
24424 if(token.compare(0, 6,
"vertex", 0, 6) != 0) {
24425 stringstream errorMessage;
24426 errorMessage <<
"Error 4 reading " << fileName <<
". Quit." << endl;
24427 mTerm(1, AT_, errorMessage.str());
24429 token = strtok(
nullptr,
" ");
24430 b[0] = atof(token.c_str());
24431 token = strtok(
nullptr,
" ");
24432 b[1] = atof(token.c_str());
24433 token = strtok(
nullptr,
" ");
24434 b[2] = atof(token.c_str());
24437 getline(ifile, line);
24438 strcpy(cstr, line.c_str());
24439 token = strtok(cstr,
" ");
24440 if(token.compare(0, 6,
"vertex", 0, 6) != 0) {
24441 stringstream errorMessage;
24442 errorMessage <<
"Error 5 reading " << fileName <<
". Quit." << endl;
24443 mTerm(1, AT_, errorMessage.str());
24445 token = strtok(
nullptr,
" ");
24446 c[0] = atof(token.c_str());
24447 token = strtok(
nullptr,
" ");
24448 c[1] = atof(token.c_str());
24449 token = strtok(
nullptr,
" ");
24450 c[2] = atof(token.c_str());
24452 m_sampleCoordinates[3 * noPoints] = F1B3 * (
a[0] +
b[0] + c[0]);
24453 m_sampleCoordinates[3 * noPoints + 1] = F1B3 * (
a[1] +
b[1] + c[1]);
24454 m_sampleCoordinates[3 * noPoints + 2] = F1B3 * (
a[2] +
b[2] + c[2]);
24457 for(
MInt i = 0; i < 3; i++) {
24458 b[i] =
b[i] -
a[i];
24459 a[i] = c[i] -
a[i];
24461 crossProduct(c,
b,
a);
24464 m_sampleNormals[3 * noPoints] = c[0] * tmp;
24465 m_sampleNormals[3 * noPoints + 1] = c[1] * tmp;
24466 m_sampleNormals[3 * noPoints + 2] = c[2] * tmp;
24470 getline(ifile, line);
24473 getline(ifile, line);
24476 }
else if(token.compare(0, 8,
"endsolid", 0, 8) == 0) {
24477 cerr <<
"finished ";
24480 stringstream errorMessage;
24481 errorMessage <<
"Error 6 reading " << fileName <<
". Quit." << endl;
24482 mTerm(1, AT_, errorMessage.str());
24489 m_noSurfacePointSamples = noPoints;
24491 cerr <<
"(read " << m_noSurfacePointSamples <<
" samples)." << endl;
24492 cerr <<
"establishing sample neighborhood...";
24494 const MInt noNghbrs = m_maxNoSampleNghbrs;
24497 ASSERT(noNghbrs <= 10,
"");
24499 for(
MInt p = 0; p < noPoints; p++) {
24500 for(
MInt i = 0; i < noNghbrs; i++) {
24501 dist[i] =
POW2(c_cellLengthAtLevel(0));
24504 for(
MInt q = 0; q < noPoints; q++) {
24505 if(p == q)
continue;
24506 MFloat tmpDist =
POW2(m_sampleCoordinates[3 * p] - m_sampleCoordinates[3 * q])
24507 +
POW2(m_sampleCoordinates[3 * p + 1] - m_sampleCoordinates[3 * q + 1])
24508 +
POW2(m_sampleCoordinates[3 * p + 2] - m_sampleCoordinates[3 * q + 2]);
24509 for(
MInt i = 0; i < noNghbrs; i++) {
24510 if(tmpDist <
dist[i]) {
24511 for(
MInt j = noNghbrs - 1; j > i; j--) {
24512 if(nghbrs[j - 1] > -1) {
24513 nghbrs[j] = nghbrs[j - 1];
24523 for(
MInt i = 0; i < noNghbrs; i++) {
24524 m_sampleNghbrs[offset + i] = nghbrs[i];
24526 offset += noNghbrs;
24527 m_sampleNghbrOffsets[p] = offset;
24530 cerr <<
"finished." << endl;
24539template <MInt nDim,
class SysEqn>
24543 writeGridRestart =
false;
24546 writeRestart =
true;
24548 if(isActive() && m_deleteNeighbour) {
24549 restoreNeighbourLinks();
24552 if(m_onlineRestartInterval > 0) {
24555 if(
globalTimeStep % m_onlineRestartInterval == 0) m_adaptationSinceLastRestart =
true;
24558 if(m_forceRestartGrid) {
24559 m_adaptationSinceLastRestart =
true;
24560 if(isActive() && m_recalcIds ==
nullptr)
mAlloc(m_recalcIds, maxNoGridCells(),
"m_recalcIds", -1, AT_);
24563 if(m_adaptationSinceLastRestartBackup || m_adaptationSinceLastRestart) {
24564 writeGridRestart =
true;
24568 if(grid().newMinLevel() > 0) {
24569 writeGridRestart =
true;
24574 if(isActive() && m_useNonSpecifiedRestartFile && writeRestart) {
24575 if(domainId() == 0) {
24576 if(m_adaptationSinceLastRestart) {
24577 MString fileName = outputDir() +
"restartGrid";
24578 fileName +=
".Netcdf";
24579 MString fileNameBak = fileName +
".BAK";
24581 cerr <<
"rename " << fileName <<
" " << fileNameBak << endl;
24583 rename(fileName.c_str(), fileNameBak.c_str());
24586 MString fileName = outputDir() +
"restartVariables";
24587 fileName +=
".Netcdf";
24588 MString fileNameBak = fileName +
".BAK";
24590 cerr <<
"rename " << fileName <<
" " << fileNameBak << endl;
24592 rename(fileName.c_str(), fileNameBak.c_str());
24595 MString fileName = outputDir() +
"restartBodyData";
24596 fileName +=
".Netcdf";
24597 MString fileNameBak = fileName +
".BAK";
24599 cerr <<
"rename " << fileName <<
" " << fileNameBak << endl;
24601 rename(fileName.c_str(), fileNameBak.c_str());
24607 if(isActive() && m_levelSetMb && writeRestart) {
24608 if(maxLevel() > minLevel()) {
24609 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
24610 if(a_isBndryGhostCell(cellId))
continue;
24611 if(a_isHalo(cellId))
continue;
24612 if(a_level(cellId) != minLevel())
continue;
24613 reduceData(cellId, &a_pvariable(0, 0), PV->noVariables);
24614 if(grid().azimuthalPeriodicity()) {
24618 reduceData(cellId, &a_variable(0, 0), CV->noVariables);
24624#if defined _MB_DEBUG_ || !defined NDEBUG
24625 if(isActive() && writeRestart) {
24626 if(domainId() == 0) {
24627 cerr <<
"Checking cells before writing restart-file... ";
24629 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
24630 for(
MInt v = 0; v < CV->noVariables; v++) {
24631 if(std::isnan(a_variable(cellId, v)) && a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
24632 cerr <<
"Nan in variable when writing restart-File: " << cellId <<
" "
24633 << a_hasProperty(cellId, SolverCell::IsInactive) << endl;
24637 cerr0 <<
"finished. " << endl;
24641 return writeRestart;
24650template <MInt nDim,
class SysEqn>
24655 m_adaptationSinceLastRestart =
false;
24656 m_adaptationSinceLastRestartBackup =
false;
24658 deleteNeighbourLinks();
24669template <MInt nDim,
class SysEqn>
24673 const MInt noCellsGrid = grid().raw().treeb().size();
24674 const MInt offset = noCellsGrid * solverId();
24676 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
24677 if(a_isBndryGhostCell(cellId))
continue;
24678 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
24679 if(a_hasProperty(cellId, SolverCell::IsSplitClone))
continue;
24680 assertValidGridCellId(cellId);
24681 const MInt gridCellId = grid().tree().solver2grid(cellId);
24682 const MInt id = gridCellId + offset;
24683 if(a_isHalo(cellId))
continue;
24684 if(c_noChildren(cellId) > 0) {
24685 solverCellWeight[
id] = m_weightBaseCell * m_weightMulitSolverFactor;
24688 if(a_hasProperty(cellId, SolverCell::IsInactive)) {
24689 solverCellWeight[
id] = m_weightLeafCell * m_weightMulitSolverFactor;
24691 solverCellWeight[
id] = m_weightActiveCell * m_weightMulitSolverFactor;
24694 MFloat dist = fabs(a_levelSetValuesMb(cellId, 0));
24695 if(
dist < 2 * grid().cellLengthAtLevel(maxRefinementLevel())) {
24696 solverCellWeight[
id] += m_weightNearBndryCell * m_weightMulitSolverFactor;
24698 if(a_bndryId(cellId) > -1 && c_isLeafCell(cellId)) {
24699 solverCellWeight[
id] += m_weightBndryCell * m_weightMulitSolverFactor;
24710template <MInt nDim,
class SysEqn>
24716 if(m_noEmbeddedBodies > 0) {
24717 saveBodyRestartFile(writeBackup);
24728template <MInt nDim,
class SysEqn>
24733 m_physicalTimeDt1 = m_physicalTime;
24735 updateInfinityVariables();
24737 m_log <<
"ok" << endl;
24738 m_log <<
"computing conservative variables... ";
24739 computeConservativeVariables();
24740 m_log <<
"ok" << endl;
24741 m_log <<
"restart at time step: " <<
globalTimeStep <<
" - solution time: " << m_time << endl;
24742 m_log << m_noSamples <<
" samples read" << endl;
24752template <MInt nDim,
class SysEqn>
24757 cerr0 <<
"Not saving body-restart-data, as the cell volume might not have been created yet!" << endl;
24762 if(!m_trackBodySurfaceData) computeBodySurfaceData();
24764 cerr0 <<
"writing body-restart-data for the fv-mb-solver... ";
24766 int64_t noMbCells = 0;
24767 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
24768 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
24769 if(a_isHalo(cellId))
continue;
24770 if(a_isPeriodic(cellId))
continue;
24771 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
24775 int64_t noMbCellsGlobal = noMbCells;
24779 if(noDomains() > 1) {
24780 volOffsets(domainId() + 1) = (MPI_Offset)noMbCells;
24781 MPI_Allgather(&noMbCells, 1, MPI_INT64_T, &volOffsets[1], 1, MPI_INT64_T, mpiComm(), AT_,
"noMbCells",
24783 for(
MInt d = 0; d < noDomains(); d++) {
24784 volOffsets(d + 1) += volOffsets(d);
24786 noMbCellsGlobal = noMbCells;
24787 MPI_Allreduce(MPI_IN_PLACE, &noMbCellsGlobal, 1, MPI_INT64_T, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
24788 "noMbCellsGlobal");
24789 if(noMbCellsGlobal != volOffsets(noDomains()))
mTerm(1, AT_,
"Dimension mismatch.");
24791 volOffsets(noDomains()) = (MPI_Offset)noMbCellsGlobal;
24794 int64_t noAzimuthalMbCells = 0;
24795 int64_t noAzimuthalMbCellsGlobal = 0;
24797 "volOffsetsAzimuthal");
24798 if(grid().azimuthalPeriodicity()) {
24799 storeAzimuthalPeriodicData();
24800 noAzimuthalMbCells = m_azimuthalNearBoundaryBackup.size();
24801 noAzimuthalMbCellsGlobal = noAzimuthalMbCells;
24802 volOffsetsAzimuthal(0) = 0;
24803 if(noDomains() > 1) {
24804 volOffsetsAzimuthal(domainId() + 1) = (MPI_Offset)noAzimuthalMbCells;
24805 MPI_Allgather(&noAzimuthalMbCells, 1, MPI_INT64_T, &volOffsetsAzimuthal[1], 1, MPI_INT64_T, mpiComm(), AT_,
24806 "noAzimuthalMbCells",
"volOffsetsAzimuthal[1]");
24807 for(
MInt d = 0; d < noDomains(); d++) {
24808 volOffsetsAzimuthal(d + 1) += volOffsetsAzimuthal(d);
24810 noAzimuthalMbCellsGlobal = noAzimuthalMbCells;
24811 MPI_Allreduce(MPI_IN_PLACE, &noAzimuthalMbCellsGlobal, 1, MPI_INT64_T, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
24812 "noAzimuthalMbCellsGlobal");
24813 if(noAzimuthalMbCellsGlobal != volOffsetsAzimuthal(noDomains()))
mTerm(1, AT_,
"Dimension mismatch.");
24815 volOffsetsAzimuthal(noDomains()) = (MPI_Offset)noAzimuthalMbCellsGlobal;
24818 const MLong DOF = m_noEmbeddedBodies;
24819 const MLong DOF_TRANS = nDim * m_noEmbeddedBodies;
24820 const MLong DOF_ROT = 3 * m_noEmbeddedBodies;
24821 const MLong DOF_QUAT = 4 * m_noEmbeddedBodies;
24822 const MLong DOF_VOL = (
MLong)noMbCellsGlobal;
24823 const MLong DOF_VOL_AZIMUTHAL = (
MLong)noAzimuthalMbCellsGlobal;
24828 fn << outputDir() <<
"restartBodyDataBackup_" << getIdentifier(m_multipleFvSolver) <<
globalTimeStep;
24830 if(m_useNonSpecifiedRestartFile) {
24831 fn << outputDir() <<
"restartBodyData" << getIdentifier(m_multipleFvSolver,
"_",
"");
24833 fn << outputDir() <<
"restartBodyData_" << getIdentifier(m_multipleFvSolver) <<
globalTimeStep;
24836 fn << ParallelIo::fileExt();
24843 if(grid().newMinLevel() < 0) {
24844 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
24845 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
24846 if(a_isHalo(cellId))
continue;
24847 if(a_isPeriodic(cellId))
continue;
24848 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
24849 ASSERT(c_globalId(cellId) >= domainOffset(domainId())
24850 && c_globalId(cellId) < domainOffset(domainId()) + noInternalCells(),
24852 bndryCellVolumesIds[cnt] = c_globalId(cellId);
24853 bndryCellVolumes[cnt] = a_cellVolume(cellId);
24854 if(bndryCellVolumesIds[cnt] >= domainOffset(noDomains())) {
24855 cerr << domainId() <<
": index out of range " << bndryCellVolumes[cnt] <<
" " << domainOffset(noDomains())
24856 <<
" " << grid().noCellsGlobal() <<
" " << grid().bitOffset() << endl;
24861 vector<MInt> reOrderedCells;
24862 vector<MLong> newGlobalIds;
24863 cerr0 <<
"Updating globalIds for bodyRestartFile!" << endl;
24864 this->reOrderCellIds(reOrderedCells);
24866 this->recomputeGlobalIds(reOrderedCells, newGlobalIds);
24869 for(
MUint id = 0;
id < reOrderedCells.size();
id++) {
24870 const MInt cellId = reOrderedCells[
id];
24871 if(a_isHalo(cellId))
continue;
24872 if(a_isPeriodic(cellId))
continue;
24873 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
24874 const MInt bndryId = a_bndryId(cellId);
24875 if(bndryId < m_noOuterBndryCells)
continue;
24876 bndryCellVolumesIds[cnt] = newGlobalIds[
id];
24877 bndryCellVolumes[cnt] = a_cellVolume(cellId);
24880 ASSERT(cnt == noMbCells,
"");
24884 "azimuthalndryCellVolumesIds");
24885 MFloatScratchSpace azimuthalBndryCellVolumes(
mMax(noAzimuthalMbCells, (int64_t)1), AT_,
"azimuthalndryCellVolumes");
24887 "azimuthalndryCellCoordinates");
24888 if(grid().azimuthalPeriodicity()) {
24890 for(
auto it = m_azimuthalNearBoundaryBackup.begin(); it != m_azimuthalNearBoundaryBackup.end(); ++it) {
24891 MInt cellId = it->first;
24892 azimuthalBndryCellVolumesIds[cnt] = c_globalId(cellId);
24893 azimuthalBndryCellVolumes[cnt] = (it->second).first[nDim];
24894 for(
MInt d = 0; d < nDim; d++) {
24895 azimuthalBndryCellCoordinates[cnt * nDim + d] = (it->second).first[d];
24902 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
24903 getBodyRotation(k, &bodyRotation[3 * k]);
24907 map<MLong, MFloat> tmpVol;
24908 for(
MInt i = 0; i < noMbCells; i++) {
24909 tmpVol.insert(make_pair(bndryCellVolumesIds[i], bndryCellVolumes[i]));
24912 for(map<MLong, MFloat>::iterator it = tmpVol.begin(); it != tmpVol.end(); it++) {
24913 bndryCellVolumesIds[cnt] = it->first;
24914 bndryCellVolumes[cnt] = it->second;
24918 if(grid().azimuthalPeriodicity()) {
24919 multimap<MLong, vector<MFloat>> tmpVolAzimuthal;
24920 for(
MInt i = 0; i < noAzimuthalMbCells; i++) {
24921 vector<MFloat> tmpFloats(nDim + 1);
24922 for(
MInt d = 0; d < nDim; d++) {
24923 tmpFloats[d] = azimuthalBndryCellCoordinates[i * nDim + d];
24925 tmpFloats[nDim] = azimuthalBndryCellVolumes[i];
24926 tmpVolAzimuthal.insert(make_pair(azimuthalBndryCellVolumesIds[i], tmpFloats));
24929 for(multimap<
MLong, vector<MFloat>>::iterator it = tmpVolAzimuthal.begin(); it != tmpVolAzimuthal.end(); it++) {
24930 azimuthalBndryCellVolumesIds[cnt] = it->first;
24931 for(
MInt d = 0; d < nDim; d++) {
24932 azimuthalBndryCellCoordinates[cnt * nDim + d] = (it->second)[d];
24934 azimuthalBndryCellVolumes[cnt] = (it->second)[nDim];
24939 ParallelIo::size_type start = 0;
24940 ParallelIo::size_type count = 0;
24943 ParallelIo parallelIo(fileName, PIO_REPLACE, mpiComm());
24946 parallelIo.defineScalar(PIO_INT,
"DOF");
24949 parallelIo.defineArray(PIO_FLOAT,
"bodyTemperature", count);
24952 parallelIo.defineArray(PIO_FLOAT,
"bodyCenter", count);
24953 parallelIo.defineArray(PIO_FLOAT,
"bodyVelocity", count);
24954 parallelIo.defineArray(PIO_FLOAT,
"bodyAcceleration", count);
24955 parallelIo.defineArray(PIO_FLOAT,
"bodyForce", count);
24958 parallelIo.defineArray(PIO_FLOAT,
"bodyRotation", count);
24959 parallelIo.defineArray(PIO_FLOAT,
"bodyAngularVelocity", count);
24960 parallelIo.defineArray(PIO_FLOAT,
"bodyAngularAcceleration", count);
24961 parallelIo.defineArray(PIO_FLOAT,
"bodyTorque", count);
24964 parallelIo.defineArray(PIO_FLOAT,
"bodyQuaternion", count);
24967 parallelIo.defineArray(PIO_LONG,
"bndryCellVolumesIds", count);
24968 parallelIo.defineArray(PIO_FLOAT,
"bndryCellVolumes", count);
24970 if(grid().azimuthalPeriodicity()) {
24971 count = DOF_VOL_AZIMUTHAL;
24972 parallelIo.defineArray(PIO_LONG,
"azimuthalBndryCellVolumesIds", count);
24973 parallelIo.defineArray(PIO_FLOAT,
"azimuthalBndryCellVolumes", count);
24975 parallelIo.defineArray(PIO_FLOAT,
"azimuthalBndryCellCoordinates", count);
24978 parallelIo.writeScalar(DOF,
"DOF");
24983 parallelIo.setOffset(count, start);
24984 parallelIo.writeArray(m_bodyTemperature,
"bodyTemperature");
24987 parallelIo.setOffset(count, start);
24988 parallelIo.writeArray(m_bodyCenter,
"bodyCenter");
24989 parallelIo.writeArray(m_bodyVelocity,
"bodyVelocity");
24990 parallelIo.writeArray(m_bodyAcceleration,
"bodyAcceleration");
24991 parallelIo.writeArray(m_bodyForce,
"bodyForce");
24994 parallelIo.setOffset(count, start);
24995 parallelIo.writeArray(&bodyRotation[0],
"bodyRotation");
24997 if(m_LsRotate && !m_constructGField) {
25001 MInt validRoot = -1;
25002 if(std::isnan(m_bodyAngularVelocity[0])) invalid[domainId()] = 1;
25003 MPI_Allreduce(MPI_IN_PLACE, invalid.getPointer(), noDomains(), MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
25005 for(
MInt d = 0; d < noDomains(); d++) {
25006 if(invalid[d] < 0) validRoot = d;
25008 MPI_Bcast(&m_bodyAngularVelocity[0], m_noEmbeddedBodies * nDim, MPI_DOUBLE, validRoot, mpiComm(), AT_,
25009 "m_bodyAngularVelocity");
25010 MPI_Bcast(&m_bodyAngularAcceleration[0], m_noEmbeddedBodies * nDim, MPI_DOUBLE, validRoot, mpiComm(), AT_,
25011 "m_bodyAngularAcceleration");
25014 parallelIo.writeArray(m_bodyAngularVelocity,
"bodyAngularVelocity");
25015 parallelIo.writeArray(m_bodyAngularAcceleration,
"bodyAngularAcceleration");
25016 parallelIo.writeArray(m_bodyTorque,
"bodyTorque");
25019 parallelIo.setOffset(count, start);
25020 parallelIo.writeArray(m_bodyQuaternion,
"bodyQuaternion");
25022 start = volOffsets(domainId());
25024 parallelIo.setOffset(count, start);
25025 parallelIo.writeArray(bndryCellVolumesIds.
begin(),
"bndryCellVolumesIds");
25026 parallelIo.writeArray(bndryCellVolumes.
begin(),
"bndryCellVolumes");
25028 if(grid().azimuthalPeriodicity()) {
25029 start = volOffsetsAzimuthal(domainId());
25030 count = noAzimuthalMbCells;
25031 parallelIo.setOffset(count, start);
25032 parallelIo.writeArray(azimuthalBndryCellVolumesIds.
begin(),
"azimuthalBndryCellVolumesIds");
25033 parallelIo.writeArray(azimuthalBndryCellVolumes.
begin(),
"azimuthalBndryCellVolumes");
25034 start = volOffsetsAzimuthal(domainId()) * nDim;
25035 count = noAzimuthalMbCells * nDim;
25036 parallelIo.setOffset(count, start);
25037 parallelIo.writeArray(azimuthalBndryCellCoordinates.
begin(),
"azimuthalBndryCellCoordinates");
25041 if(domainId() == 0) cerr <<
"ok" << endl;
25055template <MInt nDim,
class SysEqn>
25059 if(m_noEmbeddedBodies == 0)
return;
25063 if(m_useNonSpecifiedRestartFile) {
25064 if(!m_multipleFvSolver) {
25065 fn << restartDir() <<
"restartBodyData";
25067 fn << restartDir() <<
"restartBodyData_" << solverId();
25070 if(!m_multipleFvSolver) {
25071 fn << restartDir() <<
"restartBodyData_" << m_restartTimeStep;
25073 fn << restartDir() <<
"restartBodyData_" << solverId() <<
"_" << m_restartTimeStep;
25076 fn << ParallelIo::fileExt();
25084 const MLong DOF = m_noEmbeddedBodies;
25085 const MLong DOF_TRANS = nDim * m_noEmbeddedBodies;
25086 const MLong DOF_ROT = 3 * m_noEmbeddedBodies;
25087 const MLong DOF_QUAT = 4 * m_noEmbeddedBodies;
25089 if(domainId() == 0) {
25090 cerr <<
"loading body restart file " << fn.str() <<
" at " <<
globalTimeStep <<
"...";
25093 int64_t noMbCells = 0;
25094 int64_t domainOffset0 = (int64_t)domainOffset(domainId() + 1);
25095 int64_t domainOffset1 = (int64_t)domainOffset(domainId());
25099 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25100 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25101 if(a_isHalo(cellId))
continue;
25102 if(a_isPeriodic(cellId))
continue;
25103 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
25104 domainOffset0 =
mMin(domainOffset0, (int64_t)c_globalId(cellId));
25105 domainOffset1 =
mMax(domainOffset1, (int64_t)c_globalId(cellId));
25109 domainOffset0 =
mMax(domainOffset0, (int64_t)domainOffset(domainId()));
25110 domainOffset1 =
mMin(domainOffset1, (int64_t)domainOffset(domainId() + 1));
25112 if(noMbCells == 0) {
25113 domainOffset0 = (int64_t)domainOffset(domainId());
25115 domainOffset1 = domainOffset0 + 1;
25116 if(readMode == 2) {
25117 domainOffset1 = (int64_t)domainOffset(domainId() + 1);
25120 if(domainOffset0 > domainOffset1 || m_bodyTypeMb == 3) {
25121 domainOffset0 = (int64_t)domainOffset(domainId());
25122 domainOffset1 = (int64_t)domainOffset(domainId() + 1);
25124 int64_t noMbCellsGlobal = noMbCells;
25126 if(noDomains() > 1) {
25127 noMbCellsGlobal = noMbCells;
25128 MPI_Allreduce(MPI_IN_PLACE, &noMbCellsGlobal, 1, MPI_INT64_T, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
25129 "noMbCellsGlobal");
25133 ParallelIo parallelIo(fileName, PIO_READ, mpiComm());
25135 ParallelIo::size_type size = 0;
25136 ParallelIo::size_type start = 0;
25137 ParallelIo::size_type count = 0;
25139 if(parallelIo.hasDataset(
"DOF")) {
25140 parallelIo.readScalar(&size,
"DOF");
25142 size = parallelIo.getArraySize(
"bodyTemperature");
25147 "No embedded bodies mismatch in loadBodyRestartFile(): " + to_string(m_noEmbeddedBodies)
25148 +
" != " + to_string(size) +
".");
25151 size = parallelIo.getArraySize(
"bndryCellVolumesIds");
25153 if(noMbCellsGlobal > 0 && size != (MPI_Offset)noMbCellsGlobal && m_geometryChange ==
nullptr) {
25154 if(domainId() == 0) {
25155 cerr <<
"Warning: No boundary cells mismatch in loadBodyRestartFile(): " + to_string(noMbCellsGlobal)
25156 +
" != " + to_string(size) +
". Might be due to non-converged to fluid-structure iterations."
25160 const MLong DOF_VOL = size;
25164 parallelIo.setOffset(count, start);
25165 parallelIo.readArray(m_bodyTemperature,
"bodyTemperature");
25168 parallelIo.setOffset(count, start);
25169 parallelIo.readArray(m_bodyCenter,
"bodyCenter");
25170 parallelIo.readArray(m_bodyVelocity,
"bodyVelocity");
25171 parallelIo.readArray(m_bodyAcceleration,
"bodyAcceleration");
25172 parallelIo.readArray(m_bodyForce,
"bodyForce");
25175 parallelIo.setOffset(count, start);
25176 parallelIo.readArray(m_bodyAngularVelocity,
"bodyAngularVelocity");
25177 parallelIo.readArray(m_bodyAngularAcceleration,
"bodyAngularAcceleration");
25178 parallelIo.readArray(m_bodyTorque,
"bodyTorque");
25181 parallelIo.setOffset(count, start);
25182 parallelIo.readArray(m_bodyQuaternion,
"bodyQuaternion");
25184 if(readMode == 2) {
25185 ASSERT(m_geometryChange !=
nullptr,
"");
25186 if(domainId() == 0) {
25187 cerr <<
"Storing old bndryCell volume for geometryChange!" << endl;
25189 m_oldGeomBndryCells.clear();
25192 MInt mismatchCnt = 0;
25193 if(readMode > 0 && DOF_VOL > 0 && DOF_VOL < domainOffset(noDomains())) {
25194 MBool readVolStrided =
false;
25195 if((readVolStrided || DOF_VOL <= noDomains()) && readMode != 2) {
25198 if(readVolStrided) {
25199 MPI_Offset noSamples = (MPI_Offset)max(2, min((
MInt)DOF_VOL, noDomains() / 2));
25200 MPI_Offset sampleWidth = ((MPI_Offset)(DOF_VOL - 1)) / (noSamples - 1);
25204 parallelIo.setOffset(count, start);
25205 parallelIo.readArray(&sampledIds[0],
"bndryCellVolumesIds", -1, sampleWidth);
25208 MPI_Offset end = DOF_VOL;
25209 for(MPI_Offset i = 0; i < noSamples; i++) {
25210 if(domainOffset0 >= sampledIds[i])
25211 start = i * sampleWidth;
25215 for(MPI_Offset i = noSamples - 1; i >= 0; i--) {
25216 if(domainOffset1 < sampledIds[i])
25217 end = i * sampleWidth;
25221 MInt diff = end - start;
25222 count = (diff > 0) ? (MPI_Offset)diff : 0;
25227 parallelIo.setOffset(count, start);
25228 parallelIo.readArray(&bndryCellVolumesIds[0],
"bndryCellVolumesIds");
25229 parallelIo.readArray(&bndryCellVolumes[0],
"bndryCellVolumes");
25231 MIntScratchSpace bndCells(domainOffset1 - domainOffset0 + 1, AT_,
"bndCells");
25233 for(
MInt i = 0; i < count; i++) {
25234 if(bndryCellVolumesIds[i] < domainOffset0 || bndryCellVolumesIds[i] >= domainOffset1) {
25237 bndCells[bndryCellVolumesIds[i] - domainOffset0] = i;
25240 cerr << domainId() <<
": read " << bndCells.
size() <<
" of " << DOF_VOL
25241 <<
" volume entries within domain offsets " << domainOffset0 <<
"-" << domainOffset1 << endl;
25246 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25247 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25248 if(a_isHalo(cellId))
continue;
25250 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
25251 if(c_globalId(cellId) < domainOffset0 || c_globalId(cellId) >= domainOffset1)
continue;
25252 if(bndCells[c_globalId(cellId) - domainOffset0] > -1) {
25254 MInt i = bndCells[c_globalId(cellId) - domainOffset0];
25255 a_cellVolume(cellId) = bndryCellVolumes[i];
25256 m_cellVolumesDt1[cellId] = bndryCellVolumes[i];
25257 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = bndryCellVolumes[i];
25258 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25259 m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume = bndryCellVolumes[i];
25262 if(a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) < F0
25263 || a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) > F1) {
25264 cerr << domainId() <<
": warning volume fraction in loadBodyRestartFile() "
25265 << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) <<
" for cell " << cellId << endl;
25270 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
25271 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
25272 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
25273 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25276 cerr << domainId() <<
": Corresponding boundary id not found. "
25277 <<
"Might be due to non-converged to fluid-structure iterations: /g " << c_globalId(cellId) <<
" /c "
25278 << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" " << a_coordinate(cellId, 2)
25279 <<
" /ls " << a_levelSetValuesMb(cellId, 0) / c_cellLengthAtCell(cellId) <<
" /v "
25280 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume / grid().gridCellVolume(a_level(cellId)) <<
" "
25281 << domainOffset0 <<
" " << domainOffset1 << endl;
25284 cerr << domainId() <<
": Exceeding 20, not reporting any more." << endl;
25290 MPI_Allreduce(MPI_IN_PLACE, &mismatchCnt, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"mismatchCnt");
25291 if(domainId() == 0) {
25292 cerr <<
"mismatch cnt: " << mismatchCnt <<
" out of " << DOF_VOL << endl;
25296 start = (DOF_VOL / noDomains()) * domainId();
25297 count = (domainId() == noDomains() - 1) ? DOF_VOL - start : (DOF_VOL / noDomains());
25299 MLongScratchSpace bndryCellVolumesIdsTmp(count, AT_,
"bndryCellVolumesIdsTmp");
25302 parallelIo.setOffset(count, start);
25303 parallelIo.readArray(&bndryCellVolumesIdsTmp[0],
"bndryCellVolumesIds");
25304 parallelIo.readArray(&bndryCellVolumesTmp[0],
"bndryCellVolumes");
25312 recvOffsets.
fill(0);
25313 sendOffsets.
fill(-1);
25314 MInt nbDom = noDomains() / 2;
25315 MLong minId = std::numeric_limits<MLong>::max();
25316 MLong bitOffsetBuf = 0;
25317 for(
MInt i = 0; i < count; i++) {
25318 minId =
mMin(minId, bndryCellVolumesIdsTmp[i]);
25320 if(minId < grid().bitOffset()) {
25321 bitOffsetBuf = grid().bitOffset();
25326 for(
MInt i = 0; i < count; i++) {
25327 bndryCellVolumesIdsTmp[i] += bitOffsetBuf;
25329 for(
MInt i = 0; i < count; i++) {
25330 if(bndryCellVolumesIdsTmp(i) >= domainOffset(noDomains())) {
25331 cerr << domainId() <<
": index out of range " << bndryCellVolumesIdsTmp(i) <<
" " << domainOffset(noDomains())
25332 <<
" " << grid().noCellsGlobal() <<
" " << grid().bitOffset() <<
" " << bitOffsetBuf << endl;
25335 while(bndryCellVolumesIdsTmp(i) < domainOffset(nbDom) || bndryCellVolumesIdsTmp(i) >= domainOffset(nbDom + 1)) {
25336 if(bndryCellVolumesIdsTmp(i) < domainOffset(nbDom)) nbDom--;
25337 if(bndryCellVolumesIdsTmp(i) >= domainOffset(nbDom + 1)) nbDom++;
25339 if(sendCnt(nbDom) == 0) sendOffsets[nbDom] = i;
25342 for(
MInt i = 0; i < noDomains(); i++) {
25343 if(sendCnt(i) > 0 && sendOffsets[i] < 0) {
25344 cerr << domainId() <<
": Warning send offset not set: " << i << endl;
25347 MPI_Alltoall(&sendCnt[0], 1, MPI_INT, &recvCnt[0], 1, MPI_INT, mpiComm(), AT_,
"sendCnt[0]",
"recvCnt[0]");
25348 MInt totalNoRecv = 0;
25349 recvOffsets[0] = 0;
25350 for(
MInt i = 0; i < noDomains(); i++) {
25351 totalNoRecv += recvCnt(i);
25352 recvOffsets[i + 1] = recvOffsets[i] + recvCnt(i);
25357 sendReq.
fill(MPI_REQUEST_NULL);
25359 for(
MInt i = 0; i < noDomains(); i++) {
25360 if(sendCnt[i] == 0)
continue;
25361 MPI_Issend(&(bndryCellVolumesIdsTmp[sendOffsets[i]]), sendCnt[i], MPI_LONG, i, 432, mpiComm(), &sendReq[scnt],
25362 AT_,
"(bndryCellVolumesIdsTmp[sendOffsets[i]])");
25365 for(
MInt i = 0; i < noDomains(); i++) {
25366 if(recvCnt[i] == 0)
continue;
25367 MPI_Recv(&(bndryCellVolumesIds[recvOffsets[i]]), recvCnt[i], MPI_LONG, i, 432, mpiComm(), MPI_STATUS_IGNORE,
25368 AT_,
"(bndryCellVolumesIds[recvOffsets[i]])");
25370 if(scnt > 0)
MPI_Waitall(scnt, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
25371 sendReq.
fill(MPI_REQUEST_NULL);
25373 for(
MInt i = 0; i < noDomains(); i++) {
25374 if(sendCnt[i] == 0)
continue;
25375 MPI_Issend(&(bndryCellVolumesTmp[sendOffsets[i]]), sendCnt[i], MPI_DOUBLE, i, 433, mpiComm(), &sendReq[scnt],
25376 AT_,
"(bndryCellVolumesTmp[sendOffsets[i]])");
25379 for(
MInt i = 0; i < noDomains(); i++) {
25380 if(recvCnt[i] == 0)
continue;
25381 MPI_Recv(&(bndryCellVolumes[recvOffsets[i]]), recvCnt[i], MPI_DOUBLE, i, 433, mpiComm(), MPI_STATUS_IGNORE, AT_,
25382 "(bndryCellVolumes[recvOffsets[i]])");
25384 if(scnt > 0)
MPI_Waitall(scnt, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
25386 MIntScratchSpace bndCells(domainOffset1 - domainOffset0 + 1, AT_,
"bndCells");
25388 for(
MInt i = 0; i < totalNoRecv; i++) {
25389 if(bndryCellVolumesIds[i] < domainOffset0 || bndryCellVolumesIds[i] >= domainOffset1) {
25392 bndCells[bndryCellVolumesIds[i] - domainOffset0] = i;
25397 if(readMode == 1) {
25398 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25399 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25400 if(a_isHalo(cellId))
continue;
25401 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
25402 if(c_globalId(cellId) < domainOffset0 || c_globalId(cellId) >= domainOffset1)
continue;
25403 const MInt i = bndCells[c_globalId(cellId) - domainOffset0];
25405 a_cellVolume(cellId) = bndryCellVolumes[i];
25406 m_cellVolumesDt1[cellId] = bndryCellVolumes[i];
25407 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = bndryCellVolumes[i];
25408 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25409 m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume = bndryCellVolumes[i];
25411 if(a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) < F0
25412 || a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) > F1) {
25413 cerr << domainId() <<
": warning volume fraction in loadBodyRestartFile() "
25414 << a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId)) <<
" for cell " << cellId <<
" "
25415 << c_globalId(cellId) << endl;
25420 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
25421 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
25422 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
25423 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25426 if(mismatchCnt < 20) {
25428 <<
": Corresponding boundary id not found. Might be due to non-converged to fluid-structure "
25430 << c_globalId(cellId) <<
" /c " << a_coordinate(cellId, 0) <<
" " << a_coordinate(cellId, 1) <<
" "
25431 << a_coordinate(cellId, 2) <<
" /v "
25432 << m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume / grid().gridCellVolume(a_level(cellId)) <<
" "
25433 << domainOffset0 <<
" " << domainOffset1 << endl;
25436 cerr << domainId() <<
": Exceeding 20, not reporting any more." << endl;
25443 MPI_Allreduce(MPI_IN_PLACE, &mismatchCnt, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"mismatchCnt");
25445 if(domainId() == 0) {
25446 cerr <<
"mismatch cnt: " << mismatchCnt <<
" out of " << DOF_VOL << endl;
25450 if(mismatchCnt > 0.5 * DOF_VOL) {
25451 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25452 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25453 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
25454 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
25455 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
25456 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25465 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
25466 const MInt i = bndCells[cellId];
25468 const MFloat volume = bndryCellVolumes[i];
25469 m_oldGeomBndryCells.insert(make_pair(cellId, volume));
25477 exchangeData(&a_cellVolume(0), 1);
25480 if(grid().azimuthalPeriodicity() && readMode == 1) {
25481 size = parallelIo.getArraySize(
"azimuthalBndryCellVolumesIds");
25482 const MLong DOF_VOL_AZIMUTHAL = size;
25483 start = (DOF_VOL_AZIMUTHAL / noDomains()) * domainId();
25484 count = (domainId() == noDomains() - 1) ? DOF_VOL_AZIMUTHAL - start : (DOF_VOL_AZIMUTHAL / noDomains());
25486 MLongScratchSpace azimuthalBndryCellVolumesIdsTmp(count, AT_,
"azimuthalBndryCellVolumesIdsTmp");
25487 MFloatScratchSpace azimuthalBndryCellVolumesTmp(count, AT_,
"azimuthalBndryCellVolumesTmp");
25488 MFloatScratchSpace azimuthalBndryCellCoordinatesTmp(count * nDim, AT_,
"azimuthalBndryCellCoordinatesTmp");
25490 parallelIo.setOffset(count, start);
25491 parallelIo.readArray(&azimuthalBndryCellVolumesIdsTmp[0],
"azimuthalBndryCellVolumesIds");
25492 parallelIo.readArray(&azimuthalBndryCellVolumesTmp[0],
"azimuthalBndryCellVolumes");
25493 parallelIo.setOffset(count * nDim, start * nDim);
25494 parallelIo.readArray(&azimuthalBndryCellCoordinatesTmp[0],
"azimuthalBndryCellCoordinates");
25498 MIntScratchSpace recvOffsetsAzimuthal(noDomains() + 1, AT_,
"recvOffsetsAzimuthal");
25499 MIntScratchSpace sendOffsetsAzimuthal(noDomains(), AT_,
"sendOffsetsAzimuthal");
25500 sendCntAzimuthal.
fill(0);
25501 recvCntAzimuthal.
fill(0);
25502 recvOffsetsAzimuthal.
fill(0);
25503 sendOffsetsAzimuthal.
fill(-1);
25504 MInt nbDom = noDomains() / 2;
25505 MLong minId = std::numeric_limits<MLong>::max();
25506 MLong bitOffsetBuf = 0;
25507 for(
MInt i = 0; i < count; i++) {
25508 minId =
mMin(minId, azimuthalBndryCellVolumesIdsTmp[i]);
25510 if(minId < grid().bitOffset()) {
25511 bitOffsetBuf = grid().bitOffset();
25516 for(
MInt i = 0; i < count; i++) {
25517 azimuthalBndryCellVolumesIdsTmp[i] += bitOffsetBuf;
25519 for(
MInt i = 0; i < count; i++) {
25520 if(azimuthalBndryCellVolumesIdsTmp(i) >= domainOffset(noDomains())) {
25521 cerr << domainId() <<
": index out of range " << azimuthalBndryCellVolumesIdsTmp(i) <<
" "
25522 << domainOffset(noDomains()) <<
" " << grid().noCellsGlobal() <<
" " << grid().bitOffset() <<
" "
25523 << bitOffsetBuf << endl;
25526 while(azimuthalBndryCellVolumesIdsTmp(i) < domainOffset(nbDom)
25527 || azimuthalBndryCellVolumesIdsTmp(i) >= domainOffset(nbDom + 1)) {
25528 if(azimuthalBndryCellVolumesIdsTmp(i) < domainOffset(nbDom)) nbDom--;
25529 if(azimuthalBndryCellVolumesIdsTmp(i) >= domainOffset(nbDom + 1)) nbDom++;
25531 if(sendCntAzimuthal(nbDom) == 0) sendOffsetsAzimuthal[nbDom] = i;
25532 sendCntAzimuthal(nbDom)++;
25534 for(
MInt i = 0; i < noDomains(); i++) {
25535 if(sendCntAzimuthal(i) > 0 && sendOffsetsAzimuthal[i] < 0) {
25536 cerr << domainId() <<
": Warning send offset not set: " << i << endl;
25539 MPI_Alltoall(&sendCntAzimuthal[0], 1, MPI_INT, &recvCntAzimuthal[0], 1, MPI_INT, mpiComm(), AT_,
25540 "sendCntAzimuthal[0]",
"recvCntAzimuthal[0]");
25541 MInt totalNoRecv = 0;
25542 recvOffsetsAzimuthal[0] = 0;
25543 for(
MInt i = 0; i < noDomains(); i++) {
25544 totalNoRecv += recvCntAzimuthal(i);
25545 recvOffsetsAzimuthal[i + 1] = recvOffsetsAzimuthal[i] + recvCntAzimuthal(i);
25547 MLongScratchSpace azimuthalBndryCellVolumesIds(
mMax(1, totalNoRecv), AT_,
"azimuthalBndryCellVolumesIds");
25549 MFloatScratchSpace azimuthalBndryCellCoordinates(
mMax(1, nDim * totalNoRecv), AT_,
"azimuthalBndryCellCoordinates");
25551 sendReqAzimuthal.
fill(MPI_REQUEST_NULL);
25553 for(
MInt i = 0; i < noDomains(); i++) {
25554 if(sendCntAzimuthal[i] == 0)
continue;
25555 MPI_Issend(&(azimuthalBndryCellVolumesIdsTmp[sendOffsetsAzimuthal[i]]), sendCntAzimuthal[i], MPI_LONG, i, 432,
25556 mpiComm(), &sendReqAzimuthal[scnt], AT_,
"(azimuthalBndryCellVolumesIdsTmp[sendOffsetsAzimuthal[i]])");
25559 for(
MInt i = 0; i < noDomains(); i++) {
25560 if(recvCntAzimuthal[i] == 0)
continue;
25561 MPI_Recv(&(azimuthalBndryCellVolumesIds[recvOffsetsAzimuthal[i]]), recvCntAzimuthal[i], MPI_LONG, i, 432,
25562 mpiComm(), MPI_STATUS_IGNORE, AT_,
"(azimuthalBndryCellVolumesIds[recvOffsets[i]])");
25564 if(scnt > 0)
MPI_Waitall(scnt, &sendReqAzimuthal[0], MPI_STATUSES_IGNORE, AT_);
25565 sendReqAzimuthal.
fill(MPI_REQUEST_NULL);
25567 for(
MInt i = 0; i < noDomains(); i++) {
25568 if(sendCntAzimuthal[i] == 0)
continue;
25569 MPI_Issend(&(azimuthalBndryCellVolumesTmp[sendOffsetsAzimuthal[i]]), sendCntAzimuthal[i], MPI_DOUBLE, i, 433,
25570 mpiComm(), &sendReqAzimuthal[scnt], AT_,
"(azimuthalBndryCellVolumesTmp[sendOffsetsAzimuthal[i]])");
25573 for(
MInt i = 0; i < noDomains(); i++) {
25574 if(recvCntAzimuthal[i] == 0)
continue;
25575 MPI_Recv(&(azimuthalBndryCellVolumes[recvOffsetsAzimuthal[i]]), recvCntAzimuthal[i], MPI_DOUBLE, i, 433,
25576 mpiComm(), MPI_STATUS_IGNORE, AT_,
"(azimuthalBndryCellVolumes[recvOffsetsAzimuthal[i]])");
25578 if(scnt > 0)
MPI_Waitall(scnt, &sendReqAzimuthal[0], MPI_STATUSES_IGNORE, AT_);
25579 sendReqAzimuthal.
fill(MPI_REQUEST_NULL);
25581 for(
MInt i = 0; i < noDomains(); i++) {
25582 if(sendCntAzimuthal[i] == 0)
continue;
25583 MPI_Issend(&(azimuthalBndryCellCoordinatesTmp[nDim * sendOffsetsAzimuthal[i]]), nDim * sendCntAzimuthal[i],
25584 MPI_DOUBLE, i, 434, mpiComm(), &sendReqAzimuthal[scnt], AT_,
25585 "(azimuthalBndryCellCoordinatesTmp[nDim*sendOffsetsAzimuthal[i]])");
25588 for(
MInt i = 0; i < noDomains(); i++) {
25589 if(recvCntAzimuthal[i] == 0)
continue;
25590 MPI_Recv(&(azimuthalBndryCellCoordinates[nDim * recvOffsetsAzimuthal[i]]), nDim * recvCntAzimuthal[i], MPI_DOUBLE,
25591 i, 434, mpiComm(), MPI_STATUS_IGNORE, AT_,
25592 "(azimuthalBndryCellCoordinates[nDim*recvOffsetsAzimuthal[i]])");
25594 if(scnt > 0)
MPI_Waitall(scnt, &sendReqAzimuthal[0], MPI_STATUSES_IGNORE, AT_);
25596 multimap<MLong, vector<MFloat>> tmpVolAzimuthal;
25597 for(
MInt i = 0; i < totalNoRecv; i++) {
25598 MLong cellId = azimuthalBndryCellVolumesIds[i];
25599 if(cellId >= domainOffset(domainId()) && cellId < domainOffset(domainId() + 1)) {
25600 vector<MFloat> tmpFloats(nDim + 1);
25601 for(
MInt d = 0; d < nDim; d++) {
25602 tmpFloats[d] = azimuthalBndryCellCoordinates[i * nDim + d];
25604 tmpFloats[nDim] = azimuthalBndryCellVolumes[i];
25605 tmpVolAzimuthal.insert(make_pair(cellId, tmpFloats));
25607 cerr <<
"ERROR:" << domainId() <<
" " << cellId <<
" " << domainOffset(noDomains()) <<
" "
25608 << domainOffset(noDomains() + 1) << endl;
25609 mTerm(1, AT_,
": azimuthal data is broken.");
25613 MInt noFloatData = 3;
25614 MInt noIntData = 2;
25615 for(
MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
25616 for(
MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
25617 MInt cellId = grid().azimuthalWindowCell(i, j);
25618 if(tmpVolAzimuthal.count(c_globalId(cellId)) != 0) {
25619 MFloat cellLength = c_cellLengthAtCell(cellId);
25620 auto range = tmpVolAzimuthal.equal_range(c_globalId(cellId));
25621 for(
auto it = range.first; it != range.second; ++it) {
25622 MBool isEqual =
true;
25623 for(
MInt d = 0; d < nDim; d++) {
25624 if(!
approx((it->second)[d], this->m_azimuthalCartRecCoord[cnt * nDim + d],
25625 m_azimuthalCornerEps * cellLength)) {
25630 vector<MFloat> tmpF(noFloatData + nDim);
25631 vector<MUlong> tmpI(noIntData);
25632 tmpF[0] = this->m_azimuthalCartRecCoord[cnt * nDim];
25633 tmpF[1] = this->m_azimuthalCartRecCoord[cnt * nDim + 1];
25635 tmpF[2] = this->m_azimuthalCartRecCoord[cnt * nDim + 2];
25637 tmpF[nDim] = (it->second)[nDim];
25638 tmpF[nDim + 1] = (it->second)[nDim];
25639 tmpF[nDim + 2] = 0;
25645 tmpI[1] = props.to_ulong();
25646 m_azimuthalNearBoundaryBackup.insert(make_pair(cellId, make_pair(tmpF, tmpI)));
25655 commAzimuthalPeriodicData();
25658 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25659 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25660 if(a_isHalo(cellId)) {
25661 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
25662 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
25663 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25664 if(mismatchCnt < 0.5 * DOF_VOL) {
25665 m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume = a_cellVolume(cellId);
25670 cerr0 <<
"done" << endl;
25680template <MInt nDim,
class SysEqn>
25685 oldVolumes.
fill(-1);
25687 for(
auto it = m_oldGeomBndryCells.begin(); it != m_oldGeomBndryCells.end(); it++) {
25688 const MInt cellId = it->first;
25689 const MFloat vol = it->second;
25690 oldVolumes(cellId, 0) = vol;
25693 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
25694 oldVolumes(cellId, 1) = a_cellVolume(cellId);
25697 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25698 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25699 if(a_isHalo(cellId))
continue;
25700 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
25701 auto it0 = m_oldGeomBndryCells.find(cellId);
25702 if(it0 != m_oldGeomBndryCells.end()) {
25703 const MFloat vol = it0->second;
25704 m_oldGeomBndryCells.erase(it0);
25706 const MFloat volDif = fabs(a_cellVolume(cellId) - vol);
25707 if(volDif > 0.0001 * vol) {
25708 m_oldGeomBndryCells.insert(make_pair(cellId, -1));
25710 a_cellVolume(cellId) = vol;
25711 m_cellVolumesDt1[cellId] = vol;
25712 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = vol;
25713 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25714 m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume = vol;
25720 exchangeData(&a_cellVolume(0), 1);
25721 exchangeData(&oldVolumes[0], 2);
25723 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
25724 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
25725 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
25726 if(!a_isHalo(cellId))
continue;
25727 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
25728 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
25729 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
25731 if(oldVolumes(cellId, 0) > 0) {
25733 auto it0 = m_oldGeomBndryCells.find(cellId);
25734 if(it0 != m_oldGeomBndryCells.end()) m_oldGeomBndryCells.erase(it0);
25736 const MFloat volDif = fabs(oldVolumes(cellId, 1) - oldVolumes(cellId, 0));
25737 if(volDif > 0.0001 * oldVolumes(cellId, 0)) {
25739 m_oldGeomBndryCells.insert(make_pair(cellId, -1));
25741 m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume = oldVolumes(cellId, 0);
25753template <MInt nDim,
class SysEqn>
25757 if(m_noEmbeddedBodies == 0)
return;
25759 const MInt noNearBodyState = 5;
25760 MFloatScratchSpace particleFluidVel(m_noEmbeddedBodies, nDim, AT_,
"particleFluidVel");
25761 MFloatScratchSpace particleFluidVelDt(m_noEmbeddedBodies, nDim, AT_,
"particleFluidVelDt");
25762 MFloatScratchSpace particleFluidVelGrad(m_noEmbeddedBodies, nDim * nDim, AT_,
"particleFluidVelGrad");
25763 MFloatScratchSpace particleFluidPressure(m_noEmbeddedBodies, AT_,
"particleFluidPressure");
25764 MFloatScratchSpace particleFluidRotation(m_noEmbeddedBodies, nDim, AT_,
"particleFluidRotation");
25765 MFloatScratchSpace particleFluidRotationDt(m_noEmbeddedBodies, nDim, AT_,
"particleFluidRotationDt");
25766 MFloatScratchSpace particleFluidState(m_noEmbeddedBodies, noNearBodyState, AT_,
"particleFluidState");
25768 for(
MInt k = 0; k < m_noEmbeddedBodies; k++) {
25769 getBodyRotation(k, &bodyRotation[3 * k]);
25771 MFloat* vel = &(particleFluidVel[0]);
25772 MFloat* velDt = &(particleFluidVelDt[0]);
25773 MFloat* velGradient = &(particleFluidVelGrad[0]);
25774 MFloat* pressure = &(particleFluidPressure[0]);
25775 MFloat* rotation = &(particleFluidRotation[0]);
25776 MFloat* rotationDt = &(particleFluidRotationDt[0]);
25777 MFloat* state = &(particleFluidState[0]);
25779 MIntScratchSpace nearestBodies(m_maxNearestBodies * a_noCells(), AT_,
"nearestBodies");
25780 MFloatScratchSpace nearestDist(m_maxNearestBodies * a_noCells(), AT_,
"nearestDist");
25781 nearestBodies.
fill(-1);
25782 nearestDist.
fill(numeric_limits<MFloat>::max());
25783 const MFloat maxDist = 5.0 * m_bodyDiameter[0];
25784 MInt maxBodyCnt = constructDistance(maxDist, nearestBodies, nearestDist);
25785 if(maxBodyCnt > m_maxNearestBodies && domainId() == 0) {
25786 cerr <<
"constructDistance: maxBodyCnt " << maxBodyCnt <<
" exceeds m_maxNearestBodies " << m_maxNearestBodies
25787 <<
". Retry with higher value." << endl;
25790 computeNearBodyFluidVelocity(nearestBodies, nearestDist, vel, velGradient, rotation, vector<MFloat>(),
nullptr, state,
25791 pressure, velDt, rotationDt);
25793 const MLong DOF = m_noEmbeddedBodies;
25794 const MLong DOF_TRANS = nDim * m_noEmbeddedBodies;
25795 const MLong DOF_ROT = 3 * m_noEmbeddedBodies;
25796 const MLong DOF_QUAT = 4 * m_noEmbeddedBodies;
25797 const MLong DOF_GRAD = nDim * nDim * m_noEmbeddedBodies;
25800 MString fileName = outputDir() +
"bodySamples_00" + to_string(
globalTimeStep) + ParallelIo::fileExt();
25802 if(domainId() == 0) {
25803 ParallelIo::size_type count = 0;
25842 parallelIo.writeScalar(DOF,
"DOF");
25843 parallelIo.writeScalar(m_bodyDiameter[0],
"bodyDiameter");
25846 parallelIo.setOffset(count, 0);
25847 parallelIo.writeArray(m_bodyTemperature,
"bodyTemperature");
25848 parallelIo.writeArray(&(pressure[0]),
"fluidPressure");
25851 parallelIo.setOffset(count, 0);
25852 parallelIo.writeArray(m_bodyCenter,
"bodyCenter");
25853 parallelIo.writeArray(m_bodyCenterDt1,
"bodyCenterDt1");
25854 parallelIo.writeArray(&(m_bodyVelocity[0]),
"bodyVelocity");
25855 parallelIo.writeArray(&(m_bodyVelocityDt1[0]),
"bodyVelocityDt1");
25856 parallelIo.writeArray(&(m_bodyAcceleration[0]),
"bodyAcceleration");
25857 parallelIo.writeArray(&(m_bodyForce[0]),
"bodyForce");
25858 parallelIo.writeArray(&(vel[0]),
"fluidVelocity");
25859 parallelIo.writeArray(&(velDt[0]),
"fluidVelocityDt1");
25862 parallelIo.setOffset(count, 0);
25863 parallelIo.writeArray(&(bodyRotation[0]),
"bodyRotation");
25864 parallelIo.writeArray(&(m_bodyAngularVelocity[0]),
"bodyAngularVelocity");
25865 parallelIo.writeArray(&(m_bodyAngularVelocityDt1[0]),
"bodyAngularVelocityDt1");
25866 parallelIo.writeArray(&(m_bodyAngularAcceleration[0]),
"bodyAngularAcceleration");
25867 parallelIo.writeArray(&(m_bodyTorque[0]),
"bodyTorque");
25868 parallelIo.writeArray(&(rotation[0]),
"fluidRotation");
25869 parallelIo.writeArray(&(rotationDt[0]),
"fluidRotationDt1");
25872 parallelIo.setOffset(count, 0);
25873 parallelIo.writeArray(&(m_bodyQuaternion[0]),
"bodyQuaternion");
25876 parallelIo.setOffset(count, 0);
25877 parallelIo.writeArray(&(velGradient[0]),
"velocityGradient");
25880 parallelIo.setOffset(count, 0);
25881 parallelIo.writeArray(&(state[0]),
"bodyState");
25891template <MInt nDim,
class SysEqn>
25895 if(m_noPointParticles == 0)
return;
25898 partOffsets(0) = 0;
25899 partOffsets(domainId() + 1) = m_noPointParticlesLocal;
25900 MPI_Allgather(&m_noPointParticlesLocal, 1, MPI_INT, &partOffsets[1], 1, MPI_INT, mpiComm(), AT_,
25901 "m_noPointParticlesLocal",
"partOffsets[1]");
25902 for(
MInt d = 0; d < noDomains(); d++)
25903 partOffsets(d + 1) += partOffsets(d);
25905 MFloatScratchSpace particleFluidPressure(m_noPointParticles, AT_,
"particleFluidPressure");
25906 setParticleFluidVelocities(&(particleFluidPressure[0]));
25908 const MLong DOF = m_noPointParticles;
25909 const MLong DOF_LOC = m_noPointParticlesLocal;
25910 const MLong DOF_TRANS = nDim * m_noPointParticles;
25911 const MLong DOF_TRANS_LOC = nDim * m_noPointParticlesLocal;
25912 const MLong DOF_ROT = 3 * m_noPointParticles;
25913 const MLong DOF_ROT_LOC = 3 * m_noPointParticlesLocal;
25914 const MLong DOF_QUAT = 4 * m_noPointParticles;
25915 const MLong DOF_QUAT_LOC = 4 * m_noPointParticlesLocal;
25916 const MLong DOF_GRAD = nDim * nDim * m_noPointParticles;
25917 const MLong DOF_GRAD_LOC = nDim * nDim * m_noPointParticlesLocal;
25919 MString fileName = outputDir() +
"partSamples_00" + to_string(
globalTimeStep) + ParallelIo::fileExt();
25921 ParallelIo::size_type start = 0;
25922 ParallelIo::size_type count = 0;
25925 ParallelIo parallelIo(fileName, PIO_REPLACE, mpiComm());
25928 parallelIo.defineScalar(PIO_INT,
"DOF");
25931 parallelIo.defineArray(PIO_FLOAT,
"partFluidPressure", count);
25934 parallelIo.defineArray(PIO_FLOAT,
"partCenter", count);
25935 parallelIo.defineArray(PIO_FLOAT,
"partVelocity", count);
25936 parallelIo.defineArray(PIO_FLOAT,
"partAcceleration", count);
25937 parallelIo.defineArray(PIO_FLOAT,
"partVelocityFluid", count);
25940 parallelIo.defineArray(PIO_FLOAT,
"partAngularVelocity", count);
25941 parallelIo.defineArray(PIO_FLOAT,
"partAngularAcceleration", count);
25944 parallelIo.defineArray(PIO_FLOAT,
"partQuaternion", count);
25947 parallelIo.defineArray(PIO_FLOAT,
"partVelocityGradientFluid", count);
25949 parallelIo.writeScalar(DOF,
"DOF");
25951 start = (ParallelIo::size_type)(partOffsets(domainId()));
25952 count = (ParallelIo::size_type)DOF_LOC;
25953 parallelIo.setOffset(count, start);
25954 parallelIo.writeArray(&(particleFluidPressure[0]),
"partFluidPressure");
25956 start = (ParallelIo::size_type)(nDim * partOffsets(domainId()));
25957 count = (ParallelIo::size_type)DOF_TRANS_LOC;
25958 parallelIo.setOffset(count, start);
25959 parallelIo.writeArray(m_particleCoords.data(),
"partCenter");
25960 parallelIo.writeArray(m_particleVelocity.data(),
"partVelocity");
25961 parallelIo.writeArray(m_particleAcceleration.data(),
"partAcceleration");
25962 parallelIo.writeArray(m_particleVelocityFluid.data(),
"partVelocityFluid");
25964 start = (ParallelIo::size_type)(3 * partOffsets(domainId()));
25965 count = (ParallelIo::size_type)DOF_ROT_LOC;
25966 parallelIo.setOffset(count, start);
25967 parallelIo.writeArray(m_particleAngularVelocity.data(),
"partAngularVelocity");
25968 parallelIo.writeArray(m_particleAngularAcceleration.data(),
"partAngularAcceleration");
25970 start = (ParallelIo::size_type)(4 * partOffsets(domainId()));
25971 count = (ParallelIo::size_type)DOF_QUAT_LOC;
25972 parallelIo.setOffset(count, start);
25973 parallelIo.writeArray(m_particleQuaternions.data(),
"partQuaternion");
25975 start = (ParallelIo::size_type)(nDim * nDim * partOffsets(domainId()));
25976 count = (ParallelIo::size_type)DOF_GRAD_LOC;
25977 parallelIo.setOffset(count, start);
25978 parallelIo.writeArray(m_particleVelocityGradientFluid.data(),
"partVelocityGradientFluid");
25986template <MInt nDim,
class SysEqn>
25991 if(rem > 86400.0) {
25992 const MFloat div = floor(rem / 86400.0);
25993 time << ((
MInt)div) <<
" days, ";
25994 rem -= div * 86400.0;
25997 const MFloat div = floor(rem / 3600.0);
25998 time << ((
MInt)div) <<
" hours, ";
25999 rem -= div * 3600.0;
26002 const MFloat div = floor(rem / 60.0);
26003 time << ((
MInt)div) <<
" mins, ";
26006 time << rem <<
" secs";
26007 const MString ret = time.str();
26021template <MInt nDim,
class SysEqn>
26025 MInt cellId, bndryId, masterCellId;
26026 MInt noSurfaces = a_noSurfaces();
26027 MInt otherId[2] = {1, 0};
26029 for(
MInt srfcId = 0; srfcId < noSurfaces; srfcId++) {
26030 for(
MInt nghbrId = 0; nghbrId < 2; nghbrId++) {
26031 cellId = a_surfaceNghbrCellId(srfcId, nghbrId);
26032 if(a_bndryId(cellId) < 0)
continue;
26034 bndryId = a_bndryId(cellId);
26036 if(m_bndryCells->a[bndryId].m_linkedCellId == -1)
continue;
26038 masterCellId = m_bndryCells->a[bndryId].m_linkedCellId;
26042 if(a_surfaceNghbrCellId(srfcId, otherId[nghbrId]) == masterCellId) {
26045 a_surfaceNghbrCellId(srfcId, nghbrId) = masterCellId;
26060template <MInt nDim,
class SysEqn>
26064 for(
MInt cnd = 0; cnd < m_noBndryCandidates; cnd++) {
26065 MInt cellId = m_bndryCandidates[cnd];
26067 MBool isGapCell =
false;
26068 if(m_levelSet && m_closeGaps) {
26069 isGapCell = (a_hasProperty(cellId, SolverCell::IsGapCell));
26073 if(m_complexBoundary && m_noLevelSetsUsedForMb > 1 && (!isGapCell)) {
26075 endSet = m_noLevelSetsUsedForMb;
26077 if(a_hasProperty(cellId, SolverCell::IsInactive) ==
false) {
26079 for(
MInt node = 0; node < m_noCellNodes; node++) {
26080 if(m_candidateNodeValues[IDX_LSSETNODES(cnd, node, 0)] > 0) minus =
false;
26083 a_hasProperty(cellId, SolverCell::IsInactive) =
true;
26084 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
false;
26085 removeSurfaces(cellId);
26089 for(
MInt node = 0; node < m_noCellNodes; node++) {
26090 for(
MInt set = startSet; set < endSet; set++)
26091 if(m_candidateNodeValues[IDX_LSSETNODES(cnd, node, set)] <= 0) plus =
false;
26093 if(plus && c_isLeafCell(cellId)) {
26094 a_hasProperty(cellId, SolverCell::IsInactive) =
false;
26095 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
true;
26096 restoreSurfaces(cellId);
26107template <MInt nDim,
class SysEqn>
26109 struct stat buffer;
26110 return (stat(fileName, &buffer) == 0);
26118template <MInt nDim,
class SysEqn>
26121 cerr <<
"Could not copy file " << fromName <<
"." << endl;
26127 ifstream src(fromName);
26128 ofstream dst(toName);
26129 if(src.good() && dst.good()) {
26130 dst << src.rdbuf();
26136 cerr <<
"Could not copy file " << fromName <<
" (2)." << endl;
26147template <MInt nDim,
class SysEqn>
26151#ifdef DOUBLE_PRECISION_OUTPUT
26152 const char*
const dataType =
"Float64";
26154 const char*
const dataType =
"Float32";
26156 const char*
const iDataType =
"Int32";
26157 const char*
const uIDataType =
"UInt32";
26159 const MString fileName =
"stencil_b" + to_string(bndryId) +
"_D" + to_string(domainId()) +
".vtp";
26160 const MUint noPoints = m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size();
26161 const MUint noLines = noPoints - 1;
26162 const MUint noSrfcs = m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs;
26163 const MUint noRecNghbrs = m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size();
26164 for(
MInt srfc = 0; srfc <
mMin((
signed)noRecNghbrs, (
signed)noSrfcs); srfc++) {
26165 for(
MInt v = 0; v < m_noPVars; v++) {
26166 a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[srfc], v) =
26167 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[v];
26172 ofl.open(fileName.c_str(), ios_base::out | ios_base::trunc);
26174 if(ofl.is_open() && ofl.good()) {
26176 ofl <<
"<?xml version=\"1.0\"?>" << endl;
26177 ofl <<
"<VTKFile type=\"PolyData\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
26178 ofl <<
"<PolyData>" << endl;
26181 ofl <<
"<Piece NumberOfPoints=\"" << noPoints <<
"\" NumberOfVerts=\"" << 1 <<
"\" NumberOfLines=\"" << noLines
26185 ofl <<
"<Points>" << endl;
26186 ofl <<
"<DataArray type=\"" << dataType <<
"\" NumberOfComponents=\"3\" format=\"ascii\">" << endl;
26187 for(
MInt i = 0; i < nDim; i++) {
26188 ofl << a_coordinate(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[noSrfcs], i) <<
" ";
26190 IF_CONSTEXPR(nDim == 2) ofl <<
"0.0 ";
26192 for(
MUint srfc = 0; srfc < noSrfcs; srfc++) {
26193 for(
MInt i = 0; i < nDim; i++) {
26194 ofl << a_coordinate(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId, i) <<
" ";
26196 IF_CONSTEXPR(nDim == 2) ofl <<
"0.0 ";
26199 for(
MUint n = noSrfcs + 1; n < noPoints; n++) {
26200 MInt nghbrId = m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n];
26201 for(
MInt i = 0; i < nDim; i++) {
26202 ofl << a_coordinate(nghbrId, i) <<
" ";
26204 IF_CONSTEXPR(nDim == 2) ofl <<
"0.0 ";
26207 ofl <<
"</DataArray>" << endl;
26208 ofl <<
"</Points>" << endl;
26211 ofl <<
"<Verts>" << endl;
26212 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"connectivity\" format=\"ascii\">" << endl;
26213 ofl <<
"0" << endl;
26214 ofl <<
"</DataArray>" << endl;
26215 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"offsets\" format=\"ascii\">" << endl;
26216 ofl <<
"1" << endl;
26217 ofl <<
"</DataArray>" << endl;
26218 ofl <<
"</Verts>" << endl;
26221 ofl <<
"<Lines>" << endl;
26222 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"connectivity\" format=\"ascii\">" << endl;
26223 for(
MUint n = 0; n < noLines; n++) {
26224 ofl <<
"0 " << n + 1 <<
" ";
26227 ofl <<
"</DataArray>" << endl;
26228 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"offsets\" format=\"ascii\">" << endl;
26229 for(
MUint n = 0; n < noLines; n++) {
26230 ofl << 2 * (n + 1) <<
" ";
26233 ofl <<
"</DataArray>" << endl;
26234 ofl <<
"</Lines>" << endl;
26237 ofl <<
"<CellData Scalars=\"scalars\">" << endl;
26239 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"weights0\" format=\"ascii\">" << endl;
26240 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst[
IPOW2(noSrfcs) * noSrfcs] <<
" ";
26241 for(
MUint srfc = 0; srfc < noSrfcs; srfc++)
26242 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst[
IPOW2(noSrfcs) * srfc] <<
" ";
26243 for(
MUint n = noSrfcs + 1; n < noPoints; n++)
26244 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst[
IPOW2(noSrfcs) * n] <<
" ";
26246 ofl <<
"</DataArray>" << endl;
26248 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"weights1\" format=\"ascii\">" << endl;
26249 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst[
IPOW2(noSrfcs) * noSrfcs +
IPOW2(noSrfcs) - 1] <<
" ";
26250 for(
MUint srfc = 0; srfc < noSrfcs; srfc++)
26251 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst[
IPOW2(noSrfcs) * srfc +
IPOW2(noSrfcs) - 1] <<
" ";
26252 for(
MUint n = noSrfcs + 1; n < noPoints; n++)
26253 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_cellVarsRecConst[
IPOW2(noSrfcs) * n +
IPOW2(noSrfcs) - 1] <<
" ";
26255 ofl <<
"</DataArray>" << endl;
26257 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"weights\" format=\"ascii\">" << endl;
26258 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_imagePointRecConst[noSrfcs] <<
" ";
26259 for(
MUint n = 0; n < noSrfcs; n++)
26260 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_imagePointRecConst[n] <<
" ";
26261 for(
MUint n = noSrfcs + 1; n < noPoints; n++)
26262 ofl << m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_imagePointRecConst[n] <<
" ";
26264 ofl <<
"</DataArray>" << endl;
26266 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"u\" format=\"ascii\">" << endl;
26267 ofl << a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[noSrfcs], PV->U) <<
" ";
26268 for(
MUint n = 0; n < noSrfcs; n++)
26269 ofl << a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n], PV->U) <<
" ";
26270 for(
MUint n = noSrfcs + 1; n < noPoints; n++)
26271 ofl << a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n], PV->U) <<
" ";
26273 ofl <<
"</DataArray>" << endl;
26275 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"v\" format=\"ascii\">" << endl;
26276 ofl << a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[noSrfcs], PV->V) <<
" ";
26277 for(
MUint n = 0; n < noSrfcs; n++)
26278 ofl << a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n], PV->V) <<
" ";
26279 for(
MUint n = noSrfcs + 1; n < noPoints; n++)
26280 ofl << a_pvariable(m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n], PV->V) <<
" ";
26282 ofl <<
"</DataArray>" << endl;
26284 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"id\" format=\"ascii\">" << endl;
26285 ofl << noSrfcs <<
" ";
26286 for(
MUint n = 0; n < noSrfcs; n++)
26288 for(
MUint n = noSrfcs + 1; n < noPoints; n++)
26291 ofl <<
"</DataArray>" << endl;
26292 ofl <<
"</CellData>" << endl;
26294 ofl <<
"</Piece>" << endl;
26295 ofl <<
"</PolyData>" << endl;
26297 ofl <<
"</VTKFile>" << endl;
26301 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (3)" << endl;
26308template <MInt nDim,
class SysEqn>
26310#if defined _MB_DEBUG_ || !defined NDEBUG
26312 MInt solutionDiverged = 0;
26315 for(
MInt i = a_noCells(); i--;) {
26316 if(cnt >= 100)
break;
26317 if(!a_hasProperty(i, SolverCell::IsActive))
continue;
26318 if(!a_hasProperty(i, SolverCell::IsOnCurrentMGLevel))
continue;
26319 if(a_isHalo(i))
continue;
26320 if(a_isBndryGhostCell(i))
continue;
26322 for(
MInt v = 0; v < noVariables(); v++) {
26323 if(!(a_variable(i, v) >= F0 || a_variable(i, v) < F0) || std::isnan(a_variable(i, v))) {
26324 cerr << domainId() <<
": LHSB " << c_globalId(i) <<
" " << a_bndryId(i) <<
" " << a_level(i) <<
" " << v <<
" "
26325 << a_variable(i, v) <<
" "
26326 <<
"cells[i].b_properties.to_string()"
26327 <<
" /v " << a_cellVolume(i) / grid().gridCellVolume(c_level(i)) <<
" "
26328 << m_cellVolumesDt1[i] / grid().gridCellVolume(c_level(i)) <<
" "
26329 << a_hasProperty(i, SolverCell::IsSplitCell) <<
" " << a_hasProperty(i, SolverCell::IsSplitChild) <<
" "
26330 << a_isPeriodic(i) <<
" " << a_coordinate(i, 0) <<
" " << a_coordinate(i, 1) <<
" "
26331 << a_coordinate(i,
mMin(nDim - 1, 2)) <<
" " << a_levelSetValuesMb(i, 0) <<
" /v "
26332 << a_cellVolume(i) * a_FcellVolume(i) <<
" " << m_cellVolumesDt1[i] * a_FcellVolume(i) << endl;
26333 solutionDiverged = 1;
26339 if(a_cellVolume(i) / grid().gridCellVolume(a_level(i)) > m_fvBndryCnd->m_volumeLimitWall) {
26342 cerr << domainId() <<
": LHSB(2) " << i <<
" " << c_globalId(i) <<
" " << a_bndryId(i) <<
" " << a_level(i)
26345 << a_cellVolume(i) / grid().gridCellVolume(c_level(i)) <<
" "
26346 << m_cellVolumesDt1[i] / grid().gridCellVolume(c_level(i)) <<
" "
26347 <<
"cells[i].b_properties.to_string()"
26348 <<
" " << a_hasProperty(i, SolverCell::IsSplitCell) <<
" " << a_hasProperty(i, SolverCell::IsSplitChild)
26349 <<
" " << a_isPeriodic(i) <<
" " << a_coordinate(i, 0) <<
" " << a_coordinate(i, 1) <<
" "
26350 << a_coordinate(i,
mMin(nDim - 1, 2)) <<
" /v " << a_cellVolume(i) * a_FcellVolume(i) <<
" "
26351 << m_cellVolumesDt1[i] * a_FcellVolume(i) << endl;
26352 solutionDiverged = 1;
26358 if(cnt >= 10) cerr <<
"More than 10 errors. Not reporting any more." << endl;
26359 if(solutionDiverged == 1) {
26360 cerr <<
"Solution diverged (LHSB) at solver " << domainId() <<
" " <<
globalTimeStep <<
" " << m_RKStep << endl;
26364 MPI_Allreduce(MPI_IN_PLACE, &solutionDiverged, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
26365 "solutionDiverged");
26366 if(solutionDiverged == 1) {
26367 writeVtkXmlFiles(
"QOUT",
"GEOM",
false,
true);
26369 mTerm(1,
"Solution diverged after LHSB handling.");
26380template <MInt nDim,
class SysEqn>
26385 const MInt noBCells = m_fvBndryCnd->m_bndryCells->size();
26386 MFloat couplingCheck = F0;
26388 for(
MInt bndryId = m_noOuterBndryCells; bndryId < noBCells; bndryId++) {
26389 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
26391 if(a_isHalo(cellId))
continue;
26392 if(a_isBndryGhostCell(cellId))
continue;
26393 if(!a_hasProperty(cellId, SolverCell::IsSplitChild) && c_noChildren(cellId) > 0)
continue;
26394 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
26396 MFloatScratchSpace dummyPvariables(m_bndryCells->a[bndryId].m_noSrfcs, PV->noVariables, AT_,
"dummyPvariables");
26397 for(
MInt srfc = 0; srfc < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
26398 if(m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area < 1e-14)
continue;
26401 for(
MInt s = 0; s <
mMin((
signed)m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size(),
26402 m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs);
26404 dummyPvariables(s, PV->P) = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[s]->m_primVars[PV->P];
26405 dummyPvariables(s, PV->RHO) = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[s]->m_primVars[PV->RHO];
26407 for(
MInt n = 0; n < (signed)m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds.size(); n++) {
26408 const MInt nghbrId = m_fvBndryCnd->m_bndryCell[bndryId].m_recNghbrIds[n];
26409 const MFloat nghbrPvariableP = (n < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs)
26410 ? dummyPvariables(n, PV->P)
26411 : a_pvariable(nghbrId, PV->P);
26412 const MFloat nghbrPvariableRho = (n < m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs)
26413 ? dummyPvariables(n, PV->RHO)
26414 : a_pvariable(nghbrId, PV->RHO);
26416 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_imagePointRecConst[n] * nghbrPvariableRho;
26417 pSurface += m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_imagePointRecConst[n] * nghbrPvariableP;
26419 MFloat normal0[3] = {F0, F0, F0};
26420 for(
MInt i = 0; i < nDim; i++) {
26421 normal0[i] = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
26423 MFloat T = sysEqn().temperature_ES(rhoSurface, pSurface);
26424 MFloat mue = SUTHERLANDLAW(T);
26425 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
26426 for(
MInt i = 0; i < nDim; i++) {
26427 const MFloat dp0 = -pSurface * normal0[i] * area;
26428 MFloat grad = m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[i]];
26429 for(
MInt j = 0; j < nDim; j++)
26430 grad += F1B3 * normal0[i] * normal0[j]
26431 * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_normalDeriv[PV->VV[j]];
26432 MFloat ds0 = mue * grad * area / sysEqn().m_Re0;
26433 coupling(cellId, i) -= (dp0 + ds0);
26434 couplingCheck -= (dp0 + ds0) * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]];
26438 exchangeDataFV(&coupling[0], nDim,
false);
26440 MPI_Allreduce(MPI_IN_PLACE, &couplingCheck, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"couplingCheck");
26441 return couplingCheck;
26449template <MInt nDim,
class SysEqn>
26452 const MFloat maxDistConstructed) {
26455 MInt noParticlesGlobal =
mMax(m_noPointParticles, m_noEmbeddedBodies);
26456 if(noParticlesGlobal == 0)
return;
26457 const MFloat DX = (m_bbox[nDim] - m_bbox[0]);
26458 const MFloat epsRef = DX / (
POW3(m_UInfinity));
26459 MInt noParticles =
mMax(m_noPointParticlesLocal, m_noEmbeddedBodies);
26460 MIntScratchSpace particleOffsets(noDomains() + 1, AT_,
"particleOffsets");
26461 particleOffsets(0) = 0;
26463 for(
MLong dom = 0; dom < noDomains(); dom++) {
26464 MLong tmpv = (((
MLong)noParticlesGlobal) * (dom + 1)) / ((
MLong)noDomains());
26465 if(tmpv > numeric_limits<MInt>::max())
mTerm(1,
"MInt overflow");
26466 particleOffsets(dom + 1) = (
MInt)tmpv;
26468 if(m_noEmbeddedBodies > 0) noParticles = particleOffsets(domainId() + 1) - particleOffsets(domainId());
26473 MFloatScratchSpace particleFluidRotationMem(
mMax(1, m_noEmbeddedBodies), nDim, AT_,
"particleFluidRotationMem");
26474 MIntScratchSpace skipBodies((m_noPointParticles > 0 ? 1 : m_noEmbeddedBodies), AT_,
"skipBodies");
26476 MFloatScratchSpace pointParticleForceMem(
mMax(1, (m_noPointParticles > 0 ? noParticles : -1)), nDim, AT_,
26477 "pointParticleForceMem");
26478 MFloatScratchSpace pointParticleTorqueMem(
mMax(1, (m_noPointParticles > 0 ? noParticles : -1)), nDim, AT_,
26479 "pointParticleTorqueMem");
26480 const MFloat distWidth = F1;
26481 const MFloat minDistBound = 0.5;
26482 const MFloat maxDistBound = 2.5;
26483 const MFloat correctionBuffer = 1.0;
26484 const MFloat maxAngleBound = 0.5 + correctionBuffer;
26485 const MFloat minAngleBound = -0.5 + correctionBuffer;
26486 const MInt noAngleSetups = (m_noPointParticles > 0 ? 1 : 3);
26487 const MInt noDistSetups = (m_noPointParticles > 0 ? 1 : 3);
26492 for(
MInt i = 0; i < noAngleSetups; i++) {
26493 MFloat maxAngle = (maxAngleBound - minAngleBound) /
mMax((
MFloat)noAngleSetups - 1, F1) * i + minAngleBound;
26494 maxAngle -= correctionBuffer;
26495 if(m_noPointParticles > 0) maxAngle = 1.0;
26496 for(
MInt j = 0; j < noDistSetups; j++) {
26497 MFloat* fluidVel =
nullptr;
26498 MFloat* fluidVelGrad =
nullptr;
26499 MFloat* fluidRotation =
nullptr;
26500 MFloat* particleVelocity =
nullptr;
26501 MFloat* particleAngularVelocity =
nullptr;
26502 MFloat* particleQuaternion =
nullptr;
26503 MFloat* particleForce =
nullptr;
26504 MFloat* particleTorque =
nullptr;
26507 if(m_noEmbeddedBodies > 0) {
26508 minDist = (maxDistBound - minDistBound) /
mMax((
MFloat)noDistSetups - 1, F1) * j
26510 maxDist = minDist + distWidth;
26511 if(maxDist * m_bodyDiameter[0] > maxDistConstructed && domainId() == 0)
26512 cerr <<
"Warning slip statistics: maxDist " << maxDist <<
" exceeds maxDistConstructed " << maxDistConstructed
26514 vector<MFloat> setup = {minDist, maxDist, maxAngle, maxAngle};
26515 fluidVel = &velMem[0];
26516 fluidVelGrad = &velGradMem[0];
26517 fluidRotation = &particleFluidRotationMem[0];
26518 particleVelocity = &m_bodyVelocity[0];
26519 particleAngularVelocity = &m_bodyAngularVelocity[0];
26520 particleQuaternion = &m_bodyQuaternion[0];
26521 particleForce = &m_hydroForce[0];
26522 particleTorque = &m_bodyTorque[0];
26523 computeNearBodyFluidVelocity(nearestBodies, nearestDist, &fluidVel[0], &fluidVelGrad[0], &fluidRotation[0],
26524 setup, &skipBodies[0]);
26525 }
else if(m_noPointParticles > 0) {
26526 setParticleFluidVelocities();
26527 fluidVel = &(m_particleVelocityFluid[0]);
26528 fluidVelGrad = &(m_particleVelocityGradientFluid[0]);
26529 particleVelocity = &m_particleVelocity[0];
26530 particleAngularVelocity = &m_particleAngularVelocity[0];
26531 particleQuaternion = &m_particleQuaternions[0];
26532 for(
MInt p = 0; p < noParticles; p++) {
26533 const MFloat pmass = F4B3 * PI * m_particleRadii[3 * p] * m_particleRadii[3 * p + 1]
26534 * m_particleRadii[3 * p + 2] * m_densityRatio * m_rhoInfinity;
26535 const MFloat Ix = F1B5 * (
POW2(m_particleRadii[3 * p + 1]) +
POW2(m_particleRadii[3 * p + 2])) * pmass;
26536 const MFloat Iy = F1B5 * (
POW2(m_particleRadii[3 * p + 0]) +
POW2(m_particleRadii[3 * p + 2])) * pmass;
26537 const MFloat Iz = F1B5 * (
POW2(m_particleRadii[3 * p + 0]) +
POW2(m_particleRadii[3 * p + 1])) * pmass;
26538 const MFloat momI[3] = {Ix, Iy, Iz};
26539 for(
MInt dim = 0; dim < nDim; dim++) {
26540 MInt id0 = (dim + 1) % 3;
26541 MInt id1 = (id0 + 1) % 3;
26542 pointParticleForceMem[nDim * p + dim] = pmass * m_particleAcceleration[nDim * p + dim];
26543 pointParticleTorqueMem[nDim * p + dim] = momI[dim] * m_particleAngularAcceleration[3 * p + dim];
26544 particleFluidRotationMem[nDim * p + dim] =
26545 F1B2 * (fluidVelGrad[9 * p + 3 * id1 + id0] - fluidVelGrad[9 * p + 3 * id0 + id1]);
26548 particleForce = &pointParticleForceMem[0];
26549 particleTorque = &pointParticleTorqueMem[0];
26550 fluidRotation = &particleFluidRotationMem[0];
26555 MFloat meanPartVel = F0;
26556 MFloat meanPartAngularVel = F0;
26561 gradRot nearParticleRot;
26564 gradRot meanOmegaRel;
26567 for(
MInt p = 0; p < noParticles; p++) {
26568 if(m_noEmbeddedBodies > 0) {
26569 p += particleOffsets(domainId());
26570 if(skipBodies[p])
continue;
26573 (m_noPointParticles > 0
26574 ? pow(m_particleRadii[3 * p + 0] * m_particleRadii[3 * p + 1] * m_particleRadii[3 * p + 2], F1B3)
26575 : pow(m_bodyRadii[nDim * p + 0] * m_bodyRadii[nDim * p + 1] * m_bodyRadii[nDim * p + 2], F1B3));
26576 const MFloat diameter = F2 * refRad;
26578 MFloat partAngularVel = F0;
26580 MFloat omegaRotation = F0;
26581 MFloat omegaRelGrad = F0;
26582 MFloat meanOmegaRelRotation = F0;
26584 vector<MFloat> vrel(nDim);
26585 vector<gradRot> omegaRel(nDim);
26586 for(
MInt dim = 0; dim < nDim; dim++) {
26587 vrel[dim] = fluidVel[nDim * p + dim] - particleVelocity[nDim * p + dim];
26588 vrelAbs +=
POW2(vrel[dim]);
26589 lin_diss += particleForce[nDim * p + dim] * vrel[dim];
26590 partVel +=
POW2(particleVelocity[nDim * p + dim]);
26591 FUf += particleForce[p * nDim + dim] * fluidVel[nDim * p + dim];
26592 FVp += particleForce[p * nDim + dim] * particleVelocity[nDim * p + dim];
26595 MInt id0 = (dim + 1) % nDim;
26596 MInt id1 = (id0 + 1) % nDim;
26597 nearParticleRot.grad =
26599 * (fluidVelGrad[
POW2(nDim) * p + nDim * id1 + id0] - fluidVelGrad[
POW2(nDim) * p + nDim * id0 + id1]);
26600 nearParticleRot.rotation = fluidRotation[p * nDim + dim];
26601 omegaRel[dim].grad = nearParticleRot.grad - particleAngularVelocity[p * nDim + dim];
26602 omegaRel[dim].rotation = nearParticleRot.rotation - particleAngularVelocity[p * nDim + dim];
26603 rot_diss.grad += particleTorque[nDim * p + dim] * omegaRel[dim].grad;
26604 rot_diss.rotation += particleTorque[nDim * p + dim] * omegaRel[dim].rotation;
26605 omegaGrad +=
POW2(nearParticleRot.grad);
26606 omegaRotation +=
POW2(nearParticleRot.rotation);
26607 omegaRelGrad +=
POW2(omegaRel[dim].grad);
26608 meanOmegaRelRotation +=
POW2(omegaRel[dim].rotation);
26609 partAngularVel +=
POW2(particleAngularVelocity[p * nDim + dim]);
26610 TOmegaF.grad += particleTorque[nDim * p + dim] * nearParticleRot.grad;
26611 TOmegaF.rotation += particleTorque[nDim * p + dim] * nearParticleRot.rotation;
26612 TOmegaP += particleTorque[nDim * p + dim] * particleAngularVelocity[p * nDim + dim];
26614 meanPartVel += sqrt(partVel);
26615 meanPartAngularVel += sqrt(partAngularVel);
26616 meanOmega.grad += sqrt(omegaGrad);
26617 meanOmega.rotation += sqrt(omegaRotation);
26618 meanOmegaRel.grad += sqrt(omegaRelGrad);
26619 meanOmegaRel.rotation += sqrt(meanOmegaRelRotation);
26620 Rep += sqrt(vrelAbs) * diameter * m_rhoInfinity * sysEqn().m_Re0 / sysEqn().m_muInfinity;
26624 vector<MFloat> communicateData = {lin_diss,
26632 meanOmega.rotation,
26634 meanOmegaRel.rotation,
26635 meanPartAngularVel,
26639 MPI_Allreduce(MPI_IN_PLACE, &cnt, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"cnt");
26640 MPI_Allreduce(MPI_IN_PLACE, communicateData.data(), communicateData.size(), MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
26641 "MPI_IN_PLACE",
"communicateData.data()");
26643 lin_diss = (epsRef /
POW3(DX)) * communicateData[
id++];
26644 FUf = (epsRef /
POW3(DX)) * communicateData[
id++];
26645 FVp = (epsRef /
POW3(DX)) * communicateData[
id++];
26646 rot_diss.grad = (epsRef /
POW3(DX)) * communicateData[
id++];
26647 rot_diss.rotation = (epsRef /
POW3(DX)) * communicateData[
id++];
26648 meanPartVel = communicateData[
id++] / (m_UInfinity * cnt);
26649 Rep = communicateData[
id++];
26650 meanOmega.grad = (DX / (m_UInfinity * cnt)) * communicateData[
id++];
26651 meanOmega.rotation = (DX / (m_UInfinity * cnt)) * communicateData[
id++];
26652 meanOmegaRel.grad = (DX / (m_UInfinity * cnt)) * communicateData[
id++];
26653 meanOmegaRel.rotation = (DX / (m_UInfinity * cnt)) * communicateData[
id++];
26654 meanPartAngularVel = (DX / (m_UInfinity * cnt)) * communicateData[
id++];
26655 TOmegaF.grad = (epsRef /
POW3(DX)) * communicateData[
id++];
26656 TOmegaF.rotation = (epsRef /
POW3(DX)) * communicateData[
id++];
26657 TOmegaP = (epsRef /
POW3(DX)) * communicateData[
id++];
26659 if(
id != communicateData.size())
mTerm(1, AT_,
"Communication messed up in slipStatistics;");
26660 if(domainId() == 0) {
26662 ofl.open(
"slipStatistics_angle_" + to_string(maxAngle) +
"_minDist_" + to_string(minDist),
26663 ios_base::out | ios_base::app);
26665 if(ofl.is_open() && ofl.good()) {
26666 if(!m_restart && m_printHeaderSlip) {
26667 ofl <<
"# 1:ts 2:time 3:physicalTime "
26668 <<
" 4:maxAngle 5:minDist 6:maxDist 7:noBodies "
26671 <<
" 10:rotDiss(G) 11:rotDiss(R)"
26672 <<
" 12:meanOmega(G) 13:meanOmega(R)"
26673 <<
" 14:meanOmegaRel(G) 15:meanOmega(R)"
26674 <<
" 16:meanPartVel 17:meanPartAngularVal "
26675 <<
" 18:F*U_f(m) 19:F*v_P "
26676 <<
" 20:T*O_f(G) 21:T*O_f(R) 22:T*O_p "
26678 m_printHeaderSlip =
false;
26680 ofl <<
globalTimeStep <<
" " << m_time <<
" " << m_physicalTime << seperator <<
" " << maxAngle <<
" "
26681 << minDist <<
" " << maxDist <<
" " << cnt << seperator <<
" " << Rep /
MFloat(cnt) <<
" " << lin_diss
26682 <<
" " << rot_diss.grad <<
" " << rot_diss.rotation <<
" " << meanOmega.grad <<
" " << meanOmega.rotation
26683 <<
" " << meanOmegaRel.grad <<
" " << meanOmegaRel.rotation <<
" " << meanPartVel <<
" "
26684 << meanPartAngularVel <<
" " << FUf <<
" " << FVp <<
" " << TOmegaF.grad <<
" " << TOmegaF.rotation <<
" "
26685 << TOmegaP << endl;
26690 if(m_saveSlipInterval > 0) {
26691 MInt noTimeStepsSaved = m_slipDataTimeSteps.size();
26692 for(
MInt p = 0; p < noParticles; p++) {
26693 MInt globalPId = p + particleOffsets(domainId());
26694 if(i == 0 && j == 0) {
26695 for(
MInt dim = 0; dim < nDim; dim++) {
26696 m_slipDataParticleVel[nDim * noParticles * noTimeStepsSaved + p * nDim + dim] =
26697 (!(skipBodies[globalPId] == 1) ? particleVelocity[globalPId * nDim + dim] : -1234);
26698 m_slipDataParticleForce[nDim * noParticles * noTimeStepsSaved + p * nDim + dim] =
26699 (!(skipBodies[globalPId] == 1) ? particleForce[globalPId * nDim + dim] : -1234);
26700 m_slipDataParticlePosition[nDim * noParticles * noTimeStepsSaved + p * nDim + dim] =
26701 m_bodyCenter[globalPId * nDim + dim];
26703 for(
MInt dim = 0; dim < 4; dim++) {
26704 m_slipDataParticleQuaternion[4 * noParticles * noTimeStepsSaved + p * 4 + dim] =
26705 (!(skipBodies[globalPId] == 1) ? particleQuaternion[globalPId * 4 + dim] : -1234);
26707 for(
MInt dim = 0; dim < nDim; dim++) {
26708 m_slipDataParticleAngularVel[nDim * noParticles * noTimeStepsSaved + p * nDim + dim] =
26709 (!(skipBodies[globalPId] == 1) ? particleAngularVelocity[globalPId * nDim + dim] : -1234);
26710 m_slipDataParticleTorque[nDim * noParticles * noTimeStepsSaved + p * nDim + dim] =
26711 (!(skipBodies[globalPId] == 1) ? particleTorque[globalPId * nDim + dim] : -1234);
26714 for(
MInt dim = 0; dim < nDim; dim++) {
26715 m_slipDataParticleFluidVel[noTimeStepsSaved * noParticles * nDim * m_noDistSetups * m_noAngleSetups
26716 + p * m_noDistSetups * m_noAngleSetups * nDim + i * nDim * m_noDistSetups
26717 + j * nDim + dim] =
26718 (!(skipBodies[globalPId] == 1) ? fluidVel[globalPId * nDim + dim] : -1234);
26719 m_slipDataParticleFluidVelRot[noTimeStepsSaved * noParticles * nDim * m_noDistSetups * m_noAngleSetups
26720 + p * m_noDistSetups * m_noAngleSetups * nDim + i * nDim * m_noDistSetups
26721 + j * nDim + dim] =
26722 (!(skipBodies[globalPId] == 1) ? fluidRotation[globalPId * nDim + dim] : -1234);
26724 for(
MInt dim = 0; dim <
POW2(nDim); dim++) {
26725 m_slipDataParticleFluidVelGrad[noTimeStepsSaved * noParticles *
POW2(nDim) * m_noDistSetups
26727 + p * m_noDistSetups * m_noAngleSetups *
POW2(nDim)
26728 + i *
POW2(nDim) * m_noDistSetups + j *
POW2(nDim) + dim] =
26729 (!(skipBodies[globalPId] == 1) ? fluidVelGrad[globalPId *
POW2(nDim) + dim] : -1234);
26735 if(m_saveSlipInterval > 0) {
26745template <MInt nDim,
class SysEqn>
26749 MInt noTimeStepsSaved = m_slipDataTimeSteps.size();
26750 if(noTimeStepsSaved == 0)
return;
26751 MInt noLocalParticles = m_particleOffsets[domainId() + 1] - m_particleOffsets[domainId()];
26752 MInt noGlobalParticles = m_noEmbeddedBodies;
26753 MInt noSetups = m_noAngleSetups * m_noDistSetups;
26754 MFloatScratchSpace outputParticleVel(
mMax(1, noLocalParticles) * nDim * noTimeStepsSaved, AT_,
"outputParticleVel");
26756 "outputParticleAngularVel");
26758 "outputParticleQuaternion");
26759 MFloatScratchSpace outputVel(
mMax(1, noLocalParticles) * nDim * noTimeStepsSaved * noSetups, AT_,
"outputVel");
26762 MFloatScratchSpace outputParticleFluidRotation(
mMax(1, noLocalParticles) * nDim * noTimeStepsSaved * noSetups, AT_,
26763 "outputParticleFluidRotation");
26765 "outputParticleForce");
26767 "outputParticleTorque");
26769 "outputParticlePosition");
26770 MIntScratchSpace outputCollision(
mMax(1, noLocalParticles) * noTimeStepsSaved, AT_,
"outputCollision");
26771 outputParticleVel.
fill(F0);
26772 outputParticleAngularVel.
fill(F0);
26773 outputParticleQuaternion.
fill(-F1);
26774 outputVel.
fill(F0);
26775 outputVelGrad.
fill(F0);
26776 outputParticleFluidRotation.
fill(F0);
26777 outputParticleForce.
fill(F0);
26778 outputParticlePosition.
fill(F0);
26779 outputParticleTorque.
fill(F0);
26780 outputCollision.
fill(0);
26782 MIntScratchSpace localToGlobal(
mMax(1, noLocalParticles) * noTimeStepsSaved, AT_,
"localToGlobal");
26784 for(
MInt p = 0; p < noLocalParticles; p++) {
26785 particleGlobalId(p) = p + m_particleOffsets[domainId()];
26787 for(
MInt ts = 0; ts < noTimeStepsSaved; ts++) {
26788 for(
MInt p = 0; p < noLocalParticles; p++) {
26789 localToGlobal(ts * noLocalParticles + p) = ts * noGlobalParticles + particleGlobalId(p);
26793 for(
MLong dom = 0; dom < noDomains() + 1; dom++) {
26794 dataOffsets(dom) = noTimeStepsSaved * m_particleOffsets[dom];
26798 noGlobalParticles * noTimeStepsSaved, 1, nDim, noDomains(), domainId(),
26799 mpiComm(), localToGlobal, dataOffsets, outputParticleVel);
26801 noGlobalParticles * noTimeStepsSaved, 1, nDim, noDomains(), domainId(),
26802 mpiComm(), localToGlobal, dataOffsets, outputParticleAngularVel);
26804 noGlobalParticles * noTimeStepsSaved, 1, 4, noDomains(), domainId(),
26805 mpiComm(), localToGlobal, dataOffsets, outputParticleQuaternion);
26807 noGlobalParticles * noTimeStepsSaved, 1, nDim * noSetups, noDomains(),
26808 domainId(), mpiComm(), localToGlobal, dataOffsets, outputVel);
26810 noGlobalParticles * noTimeStepsSaved, 1,
POW2(nDim) * noSetups, noDomains(),
26811 domainId(), mpiComm(), localToGlobal, dataOffsets, outputVelGrad);
26813 &m_slipDataParticleFluidVelRot[0], noLocalParticles * noTimeStepsSaved, noGlobalParticles * noTimeStepsSaved, 1,
26814 nDim * noSetups, noDomains(), domainId(), mpiComm(), localToGlobal, dataOffsets, outputParticleFluidRotation);
26816 noGlobalParticles * noTimeStepsSaved, 1, nDim, noDomains(), domainId(),
26817 mpiComm(), localToGlobal, dataOffsets, outputParticleForce);
26819 noGlobalParticles * noTimeStepsSaved, 1, nDim, noDomains(), domainId(),
26820 mpiComm(), localToGlobal, dataOffsets, outputParticlePosition);
26822 noGlobalParticles * noTimeStepsSaved, 1, nDim, noDomains(), domainId(),
26823 mpiComm(), localToGlobal, dataOffsets, outputParticleTorque);
26825 noGlobalParticles * noTimeStepsSaved, 1, 1, noDomains(), domainId(),
26826 mpiComm(), localToGlobal, dataOffsets, outputCollision);
26828 MLongScratchSpace totalOffsetsDOF(noDomains() + 1, AT_,
"totalOffsetsDOF_TRANS");
26829 MLongScratchSpace totalOffsetsDOF_TRANS(noDomains() + 1, AT_,
"totalOffsetsDOF_TRANS");
26830 MLongScratchSpace totalOffsetsDOF_QUAT(noDomains() + 1, AT_,
"totalOffsetsDOF_QUAT");
26831 MLongScratchSpace totalOffsetsDOF_ROT(noDomains() + 1, AT_,
"totalOffsetsDOF_ROT");
26832 MLongScratchSpace totalOffsetsDOF_GRAD_Fluid(noDomains() + 1, AT_,
"totalOffsetsDOF_GRAD_Fluid");
26833 MLongScratchSpace totalOffsetsDOF_TRANS_Fluid(noDomains() + 1, AT_,
"totalOffsetsDOF_TRANS_Fluid");
26834 MLongScratchSpace totalOffsetsDOF_ROT_Fluid(noDomains() + 1, AT_,
"totalOffsetsDOF_ROT_Fluid");
26835 for(
MLong dom = 0; dom < noDomains() + 1; dom++) {
26836 totalOffsetsDOF(dom) = dataOffsets(dom);
26837 totalOffsetsDOF_QUAT(dom) = dataOffsets(dom) * 4;
26838 totalOffsetsDOF_TRANS(dom) = dataOffsets(dom) * nDim;
26839 totalOffsetsDOF_ROT(dom) = dataOffsets(dom) * nDim;
26840 totalOffsetsDOF_TRANS_Fluid(dom) = dataOffsets(dom) * nDim * noSetups;
26841 totalOffsetsDOF_ROT_Fluid(dom) = dataOffsets(dom) * nDim * noSetups;
26842 totalOffsetsDOF_GRAD_Fluid(dom) = dataOffsets(dom) *
POW2(nDim) * noSetups;
26844 const ParallelIo::size_type DOF = totalOffsetsDOF(domainId() + 1) - totalOffsetsDOF(domainId());
26845 const ParallelIo::size_type DOF_start = totalOffsetsDOF(domainId());
26846 const ParallelIo::size_type DOF_QUAT = totalOffsetsDOF_QUAT(domainId() + 1) - totalOffsetsDOF_QUAT(domainId());
26847 const ParallelIo::size_type DOF_QUAT_start = totalOffsetsDOF_QUAT(domainId());
26848 const ParallelIo::size_type DOF_TRANS = totalOffsetsDOF_TRANS(domainId() + 1) - totalOffsetsDOF_TRANS(domainId());
26849 const ParallelIo::size_type DOF_TRANS_start = totalOffsetsDOF_TRANS(domainId());
26850 const ParallelIo::size_type DOF_ROT = totalOffsetsDOF_ROT(domainId() + 1) - totalOffsetsDOF_ROT(domainId());
26851 const ParallelIo::size_type DOF_ROT_start = totalOffsetsDOF_ROT(domainId());
26852 const ParallelIo::size_type DOF_TRANS_Fluid =
26853 totalOffsetsDOF_TRANS_Fluid(domainId() + 1) - totalOffsetsDOF_TRANS_Fluid(domainId());
26854 const ParallelIo::size_type DOF_TRANS_Fluid_start = totalOffsetsDOF_TRANS_Fluid(domainId());
26855 const ParallelIo::size_type DOF_ROT_Fluid =
26856 totalOffsetsDOF_ROT_Fluid(domainId() + 1) - totalOffsetsDOF_ROT_Fluid(domainId());
26857 const ParallelIo::size_type DOF_ROT_Fluid_start = totalOffsetsDOF_ROT_Fluid(domainId());
26858 const ParallelIo::size_type DOF_GRAD_Fluid =
26859 totalOffsetsDOF_GRAD_Fluid(domainId() + 1) - totalOffsetsDOF_GRAD_Fluid(domainId());
26860 const ParallelIo::size_type DOF_GRAD_Fluid_start = totalOffsetsDOF_GRAD_Fluid(domainId());
26863 fn << outputDir() <<
"correlationData_" << to_string(
globalTimeStep);
26864 fn << ParallelIo::fileExt();
26866 ParallelIo::size_type start = 0;
26867 ParallelIo::size_type count = 0;
26868 if(ParallelIo::fileExists(fileName, mpiComm()) && domainId() == 0) {
26870 fn2 << outputDir() <<
"correlationData_" << to_string(
globalTimeStep);
26871 fn2 << ParallelIo::fileExt();
26872 time_t now = std::time(0);
26873 tm* ltm = localtime(&now);
26874 fn2 <<
"_" << ltm->tm_year <<
"_" << ltm->tm_mon <<
"_" << ltm->tm_mday <<
"_" << ltm->tm_hour <<
"_" << ltm->tm_min
26875 <<
"_" << ltm->tm_sec;
26876 MString fileName2 = fn2.str();
26877 rename(fileName.c_str(), fileName2.c_str());
26881 ParallelIo parallelIo(fileName, PIO_REPLACE, mpiComm());
26883 count = m_slipDataTimeSteps.size();
26884 parallelIo.defineArray(PIO_INT,
"slipDataTimeSteps", count);
26886 count = totalOffsetsDOF(noDomains());
26887 parallelIo.defineArray(PIO_INT,
"bodyInCollision", count);
26889 count = totalOffsetsDOF_TRANS(noDomains());
26890 parallelIo.defineArray(PIO_FLOAT,
"particleVelocity", count);
26891 parallelIo.defineArray(PIO_FLOAT,
"particleForce", count);
26892 parallelIo.defineArray(PIO_FLOAT,
"particlePosition", count);
26894 count = totalOffsetsDOF_ROT(noDomains());
26895 parallelIo.defineArray(PIO_FLOAT,
"particleAngularVelocity", count);
26896 parallelIo.defineArray(PIO_FLOAT,
"particleTorque", count);
26898 count = totalOffsetsDOF_QUAT(noDomains());
26899 parallelIo.defineArray(PIO_FLOAT,
"particleQuaternion", count);
26901 count = totalOffsetsDOF_TRANS_Fluid(noDomains());
26902 parallelIo.defineArray(PIO_FLOAT,
"particleFluidVel", count);
26904 count = totalOffsetsDOF_ROT_Fluid(noDomains());
26905 parallelIo.defineArray(PIO_FLOAT,
"particleFluidVelRot", count);
26907 count = totalOffsetsDOF_GRAD_Fluid(noDomains());
26908 parallelIo.defineArray(PIO_FLOAT,
"particleFluidVelGrad", count);
26911 count = m_slipDataTimeSteps.size();
26912 parallelIo.setOffset(count, start);
26913 parallelIo.writeArray(&m_slipDataTimeSteps[0],
"slipDataTimeSteps");
26917 parallelIo.setOffset(count, start);
26918 parallelIo.writeArray(&outputCollision[0],
"bodyInCollision");
26920 start = DOF_TRANS_start;
26922 parallelIo.setOffset(count, start);
26923 parallelIo.writeArray(&outputParticleVel[0],
"particleVelocity");
26924 parallelIo.writeArray(&outputParticleForce[0],
"particleForce");
26925 parallelIo.writeArray(&outputParticlePosition[0],
"particlePosition");
26927 start = DOF_ROT_start;
26929 parallelIo.setOffset(count, start);
26930 parallelIo.writeArray(&outputParticleAngularVel[0],
"particleAngularVelocity");
26931 parallelIo.writeArray(&outputParticleTorque[0],
"particleTorque");
26933 start = DOF_QUAT_start;
26935 parallelIo.setOffset(count, start);
26936 parallelIo.writeArray(&outputParticleQuaternion[0],
"particleQuaternion");
26938 start = DOF_TRANS_Fluid_start;
26939 count = DOF_TRANS_Fluid;
26940 parallelIo.setOffset(count, start);
26941 parallelIo.writeArray(&outputVel[0],
"particleFluidVel");
26943 start = DOF_ROT_Fluid_start;
26944 count = DOF_ROT_Fluid;
26945 parallelIo.setOffset(count, start);
26946 parallelIo.writeArray(&outputParticleFluidRotation[0],
"particleFluidVelRot");
26948 start = DOF_GRAD_Fluid_start;
26949 count = DOF_GRAD_Fluid;
26950 parallelIo.setOffset(count, start);
26951 parallelIo.writeArray(&outputVelGrad[0],
"particleFluidVelGrad");
26953 m_slipDataTimeSteps.clear();
26955 for(
MInt i = 0; i < dim * m_noSlipDataOutputs; i++) {
26956 m_slipDataParticleCollision[i] = -5;
26959 for(
MInt i = 0; i < dim * m_noSlipDataOutputs; i++) {
26960 m_slipDataParticleQuaternion[i] = -F1;
26963 for(
MInt i = 0; i < dim * m_noSlipDataOutputs; i++) {
26964 m_slipDataParticleAngularVel[i] = -F1;
26965 m_slipDataParticleTorque[i] = -F1;
26967 for(
MInt i = 0; i < dim * m_noSlipDataOutputs * noSetups; i++) {
26968 m_slipDataParticleFluidVelRot[i] = -F1;
26971 for(
MInt i = 0; i < dim * m_noSlipDataOutputs; i++) {
26972 m_slipDataParticleVel[i] = -F1;
26973 m_slipDataParticleForce[i] = -F1;
26974 m_slipDataParticlePosition[i] = -F1;
26976 for(
MInt i = 0; i < dim * m_noSlipDataOutputs * noSetups; i++) {
26977 m_slipDataParticleFluidVel[i] = -F1;
26980 for(
MInt i = 0; i < dim * m_noSlipDataOutputs * noSetups; i++) {
26981 m_slipDataParticleFluidVelGrad[i] = -F1;
26990template <MInt nDim,
class SysEqn>
26994 ASSERT(m_levelSetMb,
"Wrong Function call, only for m_levelSetMb! Otherwise use preTimeStep in fvsolver.cpp");
26996 RECORD_TIMER_START(m_timers[Timers::PreTime]);
26998 reInitSolutionStep(mode);
26999 writeListOfActiveFlowCells();
27001 RECORD_TIMER_STOP(m_timers[Timers::PreTime]);
27009template <MInt nDim,
class SysEqn>
27013 RECORD_TIMER_START(m_timers[Timers::PostTime]);
27014 RECORD_TIMER_START(m_timers[Timers::PostSolu]);
27016 MBool convergence =
false;
27019 RECORD_TIMER_START(m_timers[Timers::ResidualMb]);
27020 convergence = this->maxResidual();
27021 RECORD_TIMER_STOP(m_timers[Timers::ResidualMb]);
27024 RECORD_TIMER_START(m_timers[Timers::SurfaceForces]);
27025 this->computeBoundarySurfaceForces();
27026 RECORD_TIMER_STOP(m_timers[Timers::SurfaceForces]);
27031 RECORD_TIMER_START(m_timers[Timers::LevelSetCorr]);
27032 convergence =
mMin(convergence, constructGFieldCorrector());
27033 RECORD_TIMER_STOP(m_timers[Timers::LevelSetCorr]);
27036 RECORD_TIMER_STOP(m_timers[Timers::PostSolu]);
27037 RECORD_TIMER_STOP(m_timers[Timers::PostTime]);
27039 return convergence;
27053template <MInt nDim,
class SysEqn>
27057 const MFloat eps0 = 1e-12;
27058 const MInt noChecks = 11;
27060 cellCheck.
fill(std::numeric_limits<MFloat>::max());
27062 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
27063 cellCheck(cellId, 0) = F1;
27064 cellCheck(cellId, 1) = a_cellVolume(cellId);
27065 cellCheck(cellId, 2) = m_cellVolumesDt1[cellId];
27066 cellCheck(cellId, 3) = (
MFloat)a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel);
27067 cellCheck(cellId, 4) = (
MFloat)a_hasProperty(cellId, SolverCell::IsInactive);
27068 cellCheck(cellId, 5) = a_levelSetValuesMb(cellId, 0);
27069 cellCheck(cellId, 6) = (
MFloat)a_isGapCell(cellId);
27070 cellCheck(cellId, 7) = (
MFloat)a_wasGapCell(cellId);
27071 cellCheck(cellId, 8) = (
MFloat)a_hasProperty(cellId, SolverCell::NearWall);
27072 cellCheck(cellId, 9) = (
MFloat)a_bndryId(cellId) > -1 ? 1 : -1;
27073 cellCheck(cellId, 10) = (
MFloat)a_hasProperty(cellId, SolverCell::WasInactive);
27076 exchangeData(&cellCheck(0), noChecks);
27078 for(
MInt cellId = noInternalCells(); cellId < a_noCells(); cellId++) {
27079 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
27080 if(a_isBndryGhostCell(cellId))
continue;
27082 if(grid().azimuthalPeriodicity() && a_isPeriodic(cellId))
continue;
27084 ASSERT((
MInt)cellCheck(cellId, 0) == 1, to_string(a_isHalo(cellId)));
27087 if((
MInt)cellCheck(cellId, 6) != a_isGapCell(cellId)) {
27088 cerr << domainId() <<
": ERR7 checkHaloCells " <<
globalTimeStep <<
" " << c_globalId(cellId) << endl;
27091 if((
MInt)cellCheck(cellId, 7) != a_wasGapCell(cellId)) {
27092 cerr << domainId() <<
": ERR7 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27098 if(fabs(cellCheck(cellId, 1) - a_cellVolume(cellId)) > eps0) {
27099 cerr << domainId() <<
": ERR1 checkHaloCells " << cellId <<
" " << c_globalId(cellId) <<
" "
27100 << a_hasProperty(cellId, SolverCell::IsSplitCell) <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild)
27101 <<
" " << a_isHalo(cellId) <<
" " << a_isWindow(cellId) <<
" " << a_level(cellId) <<
" "
27102 << a_cellVolume(cellId) <<
" " << cellCheck(cellId, 1) <<
" "
27103 << (cellCheck(cellId, 1) - grid().gridCellVolume(a_level(cellId))) / grid().gridCellVolume(a_level(cellId))
27105 << (a_cellVolume(cellId) - grid().gridCellVolume(a_level(cellId))) / grid().gridCellVolume(a_level(cellId))
27106 <<
" " << fabs(cellCheck(cellId, 1) - a_cellVolume(cellId)) / grid().gridCellVolume(a_level(cellId)) << endl;
27108 if(fabs(cellCheck(cellId, 2) - m_cellVolumesDt1[cellId]) > eps0 && mode != 3) {
27109 cerr << domainId() <<
": ERR2 checkHaloCells " <<
globalTimeStep <<
" " << c_globalId(cellId) <<
" "
27110 << m_cellVolumesDt1[cellId] <<
" " << cellCheck(cellId, 2) <<
" " << c_isLeafCell(cellId) << endl;
27112 if((
MInt)cellCheck(cellId, 3) != a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
27113 cerr << domainId() <<
": ERR3 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27116 if(fabs(cellCheck(cellId, 5) - a_levelSetValuesMb(cellId, 0)) > eps0) {
27117 cerr << domainId() <<
": ERR5 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27120 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
27123 if((
MInt)cellCheck(cellId, 4) != a_hasProperty(cellId, SolverCell::IsInactive)) {
27124 cerr << domainId() <<
": ERR4 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27128 if((
MInt)cellCheck(cellId, 6) != a_isGapCell(cellId)) {
27129 cerr << domainId() <<
": ERR6 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27132 if((
MInt)cellCheck(cellId, 7) != a_wasGapCell(cellId)) {
27133 cerr << domainId() <<
": ERR7 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27135 if((
MInt)cellCheck(cellId, 8) != a_hasProperty(cellId, SolverCell::NearWall)) {
27136 cerr << domainId() <<
": ERR8 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27138 const MInt isbndry = a_bndryId(cellId) > -1 ? 1 : -1;
27139 if((
MInt)cellCheck(cellId, 9) != isbndry) {
27140 cerr << domainId() <<
": ERR9 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27144 if((
MInt)cellCheck(cellId, 10) != a_hasProperty(cellId, SolverCell::WasInactive)) {
27145 cerr << domainId() <<
": ERR10 checkHaloCells " <<
globalTimeStep <<
" " << cellId << endl;
27160template <MInt nDim,
class SysEqn>
27164 ASSERT(m_gapInitMethod == 0,
"");
27165 if(!m_closeGaps)
return;
27169 ASSERT(!m_gapOpened,
"");
27170 ASSERT(m_levelSet,
"");
27173 const MFloat eps = sqrt(nDim) * c_cellLengthAtLevel(m_lsCutCellBaseLevel);
27175 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
27176 if(a_isBndryGhostCell(cellId))
continue;
27178 if(!a_hasProperty(cellId, SolverCell::WasGapCell))
continue;
27179 if(a_level(cellId) != maxRefinementLevel())
continue;
27180 if(!a_hasProperty(cellId, SolverCell::WasInactive))
continue;
27181 if(a_hasProperty(cellId, SolverCell::IsGapCell))
continue;
27183 if(a_levelSetValuesMb(cellId, 0) < -eps)
continue;
27189 a_variable(cellId, CV->RHO) = m_rhoInfinity;
27190 a_variable(cellId, CV->RHO_E) = m_rhoEInfinity;
27191 a_variable(cellId, CV->RHO_VV[0]) = F0;
27192 a_variable(cellId, CV->RHO_VV[1]) = F0;
27193 IF_CONSTEXPR(nDim == 3) a_variable(cellId, CV->RHO_VV[2]) = F0;
27194 a_pvariable(cellId, PV->RHO) = m_rhoInfinity;
27195 a_pvariable(cellId, PV->U) = F0;
27196 a_pvariable(cellId, PV->V) = F0;
27197 IF_CONSTEXPR(nDim == 3) a_pvariable(cellId, PV->W) = F0;
27198 a_pvariable(cellId, PV->P) = m_PInfinity;
27200 cerr << domainId() <<
": old gap cell activated at timeStep " <<
globalTimeStep <<
": cellId " << cellId <<
" "
27201 << c_globalId(cellId) <<
" lvsVal: " << a_levelSetValuesMb(cellId, 0)
27202 <<
" inactive: " << a_hasProperty(cellId, SolverCell::IsInactive) << endl;
27204 m_gapOpened =
true;
27207 MInt gapOpened = (
MInt)m_gapOpened;
27208 MPI_Allreduce(MPI_IN_PLACE, &gapOpened, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
"gapOpened");
27209 m_gapOpened = (
MBool)gapOpened;
27211 if(domainId() == 0 && m_gapOpened) {
27212 cerr <<
"Gap Opening Initialized at timestep " <<
globalTimeStep << endl;
27223template <MInt nDim,
class SysEqn>
27227 ASSERT(m_levelSet && m_closeGaps,
"");
27228 ASSERT(m_gapInitMethod > 0,
"");
27230 m_gapCellExchangeInit =
false;
27232 m_gapCellId.clear();
27233 m_gapCellId.resize(a_noCells());
27234 for(
MInt i = 0; i < a_noCells(); i++)
27235 m_gapCellId[i] = -1;
27238 if(m_noneGapRegions)
return;
27240 ASSERT(m_initGapCell,
"");
27243 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27244 const MInt cellId = m_gapCells[it].cellId;
27245 m_gapCellId[cellId] = (
MInt)it;
27249 MBool anyGapOpening =
false;
27250 for(
MInt region = 0; region < m_noGapRegions; region++) {
27251 if(m_gapState[region] == 2) anyGapOpening =
true;
27278 for(
MInt region = 0; region < m_noGapRegions; region++) {
27279 if(m_gapState[region] != -2)
continue;
27280 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27281 MInt regionId = m_gapCells[it].region;
27282 if(regionId != region)
continue;
27283 MInt cellId = m_gapCells[it].cellId;
27287 if(a_level(cellId) < m_lsCutCellMinLevel || !c_isLeafCell(cellId))
continue;
27289 ASSERT(!a_wasGapCell(cellId),
"");
27290 ASSERT(m_gapCells[it].status == 0,
"");
27291 MInt flowCornerBodySet = 0;
27292 MInt flowCorner = 0;
27293 MInt bodyId = a_associatedBodyIds(cellId, 0);
27294 MInt bodySet = m_bodyToSetTable[bodyId];
27296 MInt cndId = m_bndryCandidateIds[cellId];
27300 if(a_levelSetValuesMb(cellId, bodySet) > F0) {
27301 flowCornerBodySet = m_noCellNodes;
27303 flowCornerBodySet = 0;
27305 if(a_levelSetValuesMb(cellId, 0) > F0) {
27306 flowCorner = m_noCellNodes;
27311 for(
MInt node = 0; node < m_noCellNodes; node++) {
27312 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, bodySet)] > F0) flowCornerBodySet++;
27313 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, 0)] > F0) flowCorner++;
27318 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
27321 if(flowCorner == m_noCellNodes) {
27322 cerr <<
"UnExpected GapCell (1) at initGapClosure! " << c_globalId(cellId) <<
" " << a_isBndryCell(cellId)
27323 <<
" " << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << cndId << endl;
27324 }
else if(flowCorner > 0 && flowCorner < m_noCellNodes) {
27326 m_gapCells[it].status = 99;
27329 m_gapCells[it].status = 2;
27333 if(flowCorner == m_noCellNodes) {
27334 auto it1 = m_oldBndryCells.find(cellId);
27335 if(it1 != m_oldBndryCells.end()) {
27337 m_gapCells[it].status = 9;
27340 m_gapCells[it].status = 8;
27344 }
else if(flowCorner > 0 && flowCorner < m_noCellNodes) {
27345 if(flowCornerBodySet == 0) {
27347 m_gapCells[it].status = 6;
27348 }
else if(flowCornerBodySet == m_noCellNodes) {
27350 m_gapCells[it].status = 7;
27353 m_gapCells[it].status = 5;
27359 auto it1 = m_oldBndryCells.find(cellId);
27360 if(it1 != m_oldBndryCells.end()) {
27362 m_gapCells[it].status = 4;
27364 cerr <<
"--> Deleting oldBndryCells shadowed by the Gap in region " << regionId << endl;
27367 removeSurfaces(cellId);
27368 m_oldBndryCells.erase(it1);
27369 a_cellVolume(cellId) = grid().gridCellVolume(a_level(cellId));
27370 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
27371 m_cellVolumesDt1[cellId] = grid().gridCellVolume(a_level(cellId));
27372 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = grid().gridCellVolume(a_level(cellId));
27373 for(
MInt v = 0; v < m_noFVars; v++) {
27374 a_rightHandSide(cellId, v) = F0;
27375 m_rhs0[cellId][v] = F0;
27380 m_gapCells[it].status = 3;
27382 cerr <<
"--> Deleting Gap-Shadowed Cells in region " << regionId << endl;
27385 removeSurfaces(cellId);
27386 ASSERT(fabs(grid().gridCellVolume(a_level(cellId)) - a_cellVolume(cellId)) < 0.00001,
"");
27387 for(
MInt v = 0; v < m_noFVars; v++) {
27388 a_rightHandSide(cellId, v) = F0;
27389 m_rhs0[cellId][v] = F0;
27404 for(
MInt region = 0; region < m_noGapRegions; region++) {
27405 if(m_gapState[region] != -1)
continue;
27406 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27407 const MInt regionId = m_gapCells[it].region;
27408 if(regionId != region)
continue;
27409 const MInt cellId = m_gapCells[it].cellId;
27410 const MInt status = m_gapCells[it].status;
27437 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
27438 if(a_isBndryGhostCell(cellId))
continue;
27441 if(a_level(cellId) < m_lsCutCellMinLevel || !c_isLeafCell(cellId))
continue;
27443 MInt flowCornerBodySet = 0;
27444 MInt flowCorner = 0;
27445 MInt bodyId = a_associatedBodyIds(cellId, 0);
27446 MInt bodySet = m_bodyToSetTable[bodyId];
27448 MInt cndId = m_bndryCandidateIds[cellId];
27452 if(a_levelSetValuesMb(cellId, bodySet) > F0) {
27453 flowCornerBodySet = m_noCellNodes;
27455 flowCornerBodySet = 0;
27457 if(a_levelSetValuesMb(cellId, 0) > F0) {
27458 flowCorner = m_noCellNodes;
27463 for(
MInt node = 0; node < m_noCellNodes; node++) {
27464 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, bodySet)] > F0) flowCornerBodySet++;
27465 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, 0)] > F0) flowCorner++;
27469 if(flowCorner == m_noCellNodes) {
27471 m_gapCells[it].status = 30;
27474 }
else if(flowCorner == 0) {
27476 m_gapCells[it].status = 31;
27480 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
27483 if(flowCornerBodySet == 8) {
27507 vector<MInt> partialGapOpened;
27508 vector<MInt> fullyGapOpened;
27509 vector<MInt> fullyGapBndry;
27510 for(
MInt region = 0; region < m_noGapRegions; region++) {
27511 partialGapOpened.push_back(0);
27512 fullyGapOpened.push_back(0);
27513 fullyGapBndry.push_back(0);
27514 if(m_gapState[region] != 3)
continue;
27515 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27516 MInt regionId = m_gapCells[it].region;
27517 if(regionId != region)
continue;
27518 MInt cellId = m_gapCells[it].cellId;
27520 MInt status = m_gapCells[it].status;
27553 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
27554 if(a_isBndryGhostCell(cellId))
continue;
27556 if(a_level(cellId) < m_lsCutCellMinLevel || !c_isLeafCell(cellId))
continue;
27558 MInt flowCornerBodySet = 0;
27559 MInt flowCorner = 0;
27560 MInt bodyId = a_associatedBodyIds(cellId, 0);
27561 MInt bodySet = m_bodyToSetTable[bodyId];
27563 MInt cndId = m_bndryCandidateIds[cellId];
27567 if(a_levelSetValuesMb(cellId, bodySet) > F0) {
27568 flowCornerBodySet = m_noCellNodes;
27570 flowCornerBodySet = 0;
27572 if(a_levelSetValuesMb(cellId, 0) > F0) {
27573 flowCorner = m_noCellNodes;
27578 for(
MInt node = 0; node < m_noCellNodes; node++) {
27579 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, bodySet)] > F0) flowCornerBodySet++;
27580 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, 0)] > F0) flowCorner++;
27585 if(flowCorner == m_noCellNodes) {
27589 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
27595 cerr <<
"Incorrect status " << c_globalId(cellId) << a_hasProperty(cellId, SolverCell::WasInactive) <<
" "
27596 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << a_isGapCell(cellId) <<
" "
27597 << a_wasGapCell(cellId) << endl;
27599 m_gapCells[it].status = 21;
27600 fullyGapOpened[region]++;
27604 m_gapCells[it].status = 10;
27608 }
else if(flowCorner == 0) {
27611 ASSERT(a_hasProperty(cellId, SolverCell::IsInactive),
"");
27612 m_gapCells[it].status = 11;
27613 if(status == 1) ASSERT(flowCornerBodySet == 0,
"");
27618 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
27622 m_gapCells[it].status = 22;
27623 fullyGapBndry[region]++;
27625 m_gapCells[it].status = 13;
27628 MInt masterId = -1;
27629 MFloat maxVolActive = F0;
27630 MInt noInternalNghbrs = 0;
27631 const MInt rootId = cellId;
27632 for(
MInt dir = 0; dir < m_noDirs; dir++) {
27633 if(!checkNeighborActive(rootId, dir) || a_hasNeighbor(rootId, dir) == 0)
continue;
27634 const MInt nghbrId = c_neighborId(rootId, dir);
27635 if(nghbrId < 0)
continue;
27636 if(!a_isHalo(nghbrId)) noInternalNghbrs++;
27637 if(a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
27638 if(a_hasProperty(nghbrId, SolverCell::IsSplitCell))
continue;
27639 if(a_hasProperty(nghbrId, SolverCell::IsSplitChild))
continue;
27640 if(a_cellVolume(nghbrId) > maxVolActive) {
27641 masterId = nghbrId;
27642 maxVolActive = a_cellVolume(nghbrId);
27645 if(masterId > -1)
continue;
27646 if(a_isHalo(cellId) && noInternalNghbrs == 0)
continue;
27647 if(a_isHalo(cellId) && a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
27649 m_gapCells[it].status = 16;
27650 partialGapOpened[region]++;
27655 auto it1 = m_oldBndryCells.find(cellId);
27656 if(it1 != m_oldBndryCells.end()) {
27658 m_gapCells[it].status = 14;
27661 m_gapCells[it].status = 15;
27672 MPI_Allreduce(MPI_IN_PLACE, &partialGapOpened[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
27673 "partialGapOpened[0]");
27674 MPI_Allreduce(MPI_IN_PLACE, &fullyGapOpened[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
27675 "fullyGapOpened[0]");
27676 MPI_Allreduce(MPI_IN_PLACE, &fullyGapBndry[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
27677 "fullyGapBndry[0]");
27679 MBool anyPartialGapOpened =
false;
27680 for(
MInt region = 0; region < m_noGapRegions; region++) {
27681 if(partialGapOpened[region] > 0) {
27682 anyPartialGapOpened =
true;
27687 MBool anyFullyGapOpened =
false;
27688 for(
MInt region = 0; region < m_noGapRegions; region++) {
27689 if(fullyGapOpened[region] > 0) {
27690 anyFullyGapOpened =
true;
27695 if(anyPartialGapOpened) {
27696 for(
MInt region = 0; region < m_noGapRegions; region++) {
27697 if(domainId() == 0 && partialGapOpened[region] && !fullyGapOpened[region]) {
27698 cerr <<
"Partial Gap Opening at region " << region <<
" with " << partialGapOpened[region] <<
" Cells." << endl;
27702 initGapCellExchange();
27704 for(
MInt region = 0; region < m_noGapRegions; region++) {
27705 if(!partialGapOpened[region])
continue;
27706 if(fullyGapOpened[region])
continue;
27707 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27708 const MInt regionId = m_gapCells[it].region;
27709 if(regionId != region)
continue;
27710 const MInt cellId = m_gapCells[it].cellId;
27711 const MInt status = m_gapCells[it].status;
27713 if(status != 16)
continue;
27715 MInt largestNeighbor = checkNeighborActivity(cellId);
27717 if(largestNeighbor >= 0) {
27718 MInt largestNeighborGapCellId = m_gapCellId[largestNeighbor];
27719 m_gapCells[largestNeighborGapCellId].status = 17;
27721 if(a_isHalo(largestNeighbor)) {
27722 m_gapCells[largestNeighborGapCellId].status = -99;
27728 gapCellExchange(1);
27756 vector<MInt> noArisingGapCells;
27757 vector<MInt> noArisingGapCellsHalo;
27758 vector<MInt> noNewBndryCells;
27759 vector<MInt> noNewBndryCellsHalo;
27761 vector<MInt> interpolationCells;
27763 for(
MInt region = 0; region < m_noGapRegions; region++) {
27764 noArisingGapCells.push_back(0);
27765 noArisingGapCellsHalo.push_back(0);
27766 noNewBndryCells.push_back(0);
27767 noNewBndryCellsHalo.push_back(0);
27768 if(m_gapState[region] != 2)
continue;
27769 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27770 const MInt regionId = m_gapCells[it].region;
27771 if(regionId != region)
continue;
27772 const MInt cellId = m_gapCells[it].cellId;
27776 if(a_isBndryGhostCell(cellId))
continue;
27777 ASSERT(a_level(cellId) == maxRefinementLevel(),
"");
27779 if(a_level(cellId) != maxRefinementLevel())
continue;
27781 ASSERT(!a_isGapCell(cellId),
"");
27782 ASSERT(m_gapCells[it].status == 1,
"");
27785 MInt flowCorner = 0;
27786 MInt bodyId = a_associatedBodyIds(cellId, 0);
27787 MInt bodySet = m_bodyToSetTable[bodyId];
27789 MInt cndId = m_bndryCandidateIds[cellId];
27792 if(a_levelSetValuesMb(cellId, bodySet) > F0) {
27793 flowCorner = m_noCellNodes;
27798 for(
MInt node = 0; node < m_noCellNodes; node++) {
27799 if(m_candidateNodeValues[IDX_LSSETNODES(cndId, node, bodySet)] > F0) flowCorner++;
27803 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
27804 if(flowCorner == m_noCellNodes) {
27806 m_gapCells[it].status = 21;
27807 if(a_isHalo(cellId)) {
27808 noArisingGapCellsHalo[region]++;
27810 noArisingGapCells[region]++;
27813 }
else if(flowCorner == 0) {
27815 m_gapCells[it].status = 26;
27819 if(a_isHalo(cellId)) {
27820 noNewBndryCellsHalo[region]++;
27822 noNewBndryCells[region]++;
27824 m_gapCells[it].status = 22;
27830 auto it1 = m_oldBndryCells.find(cellId);
27831 if(it1 != m_oldBndryCells.end()) {
27832 if(flowCorner == m_noCellNodes) {
27835 m_gapCells[it].status = 23;
27840 for(
MInt v = 0; v < m_noFVars; v++) {
27841 a_rightHandSide(cellId, v) = F0;
27842 m_rhs0[cellId][v] = F0;
27845 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = grid().gridCellVolume(a_level(cellId));
27846 a_cellVolume(cellId) = grid().gridCellVolume(a_level(cellId));
27847 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
27848 m_cellVolumesDt1[cellId] = grid().gridCellVolume(a_level(cellId));
27849 m_oldBndryCells.erase(it1);
27851 }
else if(flowCorner == 0) {
27854 m_gapCells[it].status = 99;
27859 for(
MInt v = 0; v < m_noFVars; v++) {
27860 a_rightHandSide(cellId, v) = F0;
27861 m_rhs0[cellId][v] = F0;
27863 removeSurfaces(cellId);
27865 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = grid().gridCellVolume(a_level(cellId));
27866 a_cellVolume(cellId) = grid().gridCellVolume(a_level(cellId));
27867 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
27868 m_cellVolumesDt1[cellId] = grid().gridCellVolume(a_level(cellId));
27869 m_oldBndryCells.erase(it1);
27874 m_gapCells[it].status = 24;
27881 if(flowCorner == m_noCellNodes) {
27884 m_gapCells[it].status = 25;
27886 }
else if(flowCorner == 0) {
27887 cerr <<
"UnExpected GapCell (2) at initGapOpening! " << c_globalId(cellId) << endl;
27892 m_gapCells[it].status = 27;
27899 MPI_Allreduce(MPI_IN_PLACE, &noArisingGapCells[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
27900 "noArisingGapCells[0]");
27901 MPI_Allreduce(MPI_IN_PLACE, &noNewBndryCells[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
27902 "noNewBndryCells[0]");
27903 MPI_Allreduce(MPI_IN_PLACE, &noArisingGapCellsHalo[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
27904 "MPI_IN_PLACE",
"noArisingGapCellsHalo[0]");
27905 MPI_Allreduce(MPI_IN_PLACE, &noNewBndryCellsHalo[0], m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
27906 "noNewBndryCellsHalo[0]");
27910 if(anyGapOpening || anyFullyGapOpened) {
27911 for(
MInt region = 0; region < m_noGapRegions; region++) {
27912 if(m_gapState[region] == 2 && domainId() == 0) {
27913 cerr <<
"Number of Arising-Gap-Cells " << noArisingGapCells[region] <<
" in region " << region << endl;
27914 cerr <<
"Number of new-Bndry-Cells " << noNewBndryCells[region] <<
" in region " << region << endl;
27915 }
else if(domainId() == 0 && m_gapState[region] == 3) {
27916 cerr <<
"Number of Fully arising-Gap-Cells " << fullyGapOpened[region] <<
" in region " << region << endl;
27917 cerr <<
"Number of new-Bndry-Cells " << fullyGapBndry[region] <<
" in region " << region << endl;
27921 initGapCellExchange();
27924 for(
MInt region = 0; region < m_noGapRegions; region++) {
27925 if(m_gapState[region] != 2 && !fullyGapOpened[region])
continue;
27926 for(
MUint it = 0; it < m_gapCells.size(); it++) {
27927 const MInt regionId = m_gapCells[it].region;
27928 if(regionId != region)
continue;
27929 const MInt cellId = m_gapCells[it].cellId;
27930 const MInt status = m_gapCells[it].status;
27933 if(!a_isHalo(cellId)) {
27934 interpolationCells.push_back(cellId);
27940 ASSERT(!a_hasProperty(cellId, SolverCell::IsInactive),
"");
27943 restoreSurfaces(cellId);
27947 a_pvariable(cellId, PV->RHO) = m_rhoInfinity;
27948 a_pvariable(cellId, PV->U) = F0;
27949 a_pvariable(cellId, PV->V) = F0;
27950 IF_CONSTEXPR(nDim == 3) a_pvariable(cellId, PV->W) = F0;
27951 a_pvariable(cellId, PV->P) = m_PInfinity;
27954 a_cellVolume(cellId) = grid().gridCellVolume(a_level(cellId));
27955 m_cellVolumesDt1[cellId] = grid().gridCellVolume(a_level(cellId));
27956 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
27959 for(
MInt v = 0; v < m_noFVars; v++) {
27960 a_rightHandSide(cellId, v) = F0;
27961 m_rhs0[cellId][v] = F0;
27968 ASSERT(a_hasProperty(cellId, SolverCell::WasInactive),
"");
27969 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
27971 }
else if(status == 22) {
27972 if(!a_isHalo(cellId)) {
27973 interpolationCells.push_back(cellId);
27976 ASSERT(!a_hasProperty(cellId, SolverCell::IsInactive),
"");
27979 a_pvariable(cellId, PV->RHO) = m_rhoInfinity;
27980 a_pvariable(cellId, PV->U) = F0;
27981 a_pvariable(cellId, PV->V) = F0;
27982 IF_CONSTEXPR(nDim == 3) a_pvariable(cellId, PV->W) = F0;
27983 a_pvariable(cellId, PV->P) = m_PInfinity;
27986 for(
MInt v = 0; v < m_noFVars; v++) {
27987 a_rightHandSide(cellId, v) = F0;
27988 m_rhs0[cellId][v] = F0;
27995 gapCellExchange(1);
27999 vector<MInt> noIterations;
28000 for(
MInt region = 0; region < m_noGapRegions; region++) {
28001 noIterations.push_back(0);
28002 noIterations[region] = noArisingGapCells[region] + (
MInt)(noNewBndryCells[region] /
IPOW2(nDim))
28003 + fullyGapOpened[region] + fullyGapBndry[region];
28004 noIterations[region] =
mMax(noIterations[region], 100);
28007 MPI_Allreduce(MPI_IN_PLACE, &noIterations[0], m_noGapRegions, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
28008 "noIterations[0]");
28010 for(
MInt region = 0; region < m_noGapRegions; region++) {
28011 if(m_gapState[region] != 2 && !fullyGapOpened[region])
continue;
28012#if defined _MB_DEBUG_ || !defined NDEBUG
28013 if(domainId() == 0) {
28014 cerr <<
"Starting to iterate for region: " << region <<
" with " << noIterations[region] <<
" Iterations! "
28019 for(
MInt loop = 0; loop < noIterations[region]; loop++) {
28020 for(
MUint i = 0; i < interpolationCells.size(); i++) {
28021 const MInt cellId = interpolationCells[i];
28022 const MInt it = m_gapCellId[cellId];
28023 ASSERT(it >= 0,
"");
28024 const MInt regionId = m_gapCells[it].region;
28025 if(regionId != region)
continue;
28026 const MInt status = m_gapCells[it].status;
28028 ASSERT(status == 21 || status == 22,
"");
28029 ASSERT(!a_isHalo(cellId),
"");
28033 MFloat pVariables[5] = {F0, F0, F0, F0, F0};
28035 for(
MInt dir = 0; dir < m_noDirs; dir++) {
28036 if(!checkNeighborActive(cellId, dir) || a_hasNeighbor(cellId, dir) == 0)
continue;
28037 MInt nghbrId = c_neighborId(cellId, dir);
28038 if(nghbrId < 0)
continue;
28039 ASSERT(!a_hasProperty(nghbrId, SolverCell::IsInactive),
"");
28040 if(!a_wasGapCell(nghbrId) && a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
28059 MInt nghbrGapId = m_gapCellId[nghbrId];
28060 if(nghbrGapId >= 0) {
28063 MInt nghbrStatus = m_gapCells[nghbrGapId].status;
28065 if(nghbrStatus == 26)
continue;
28068 if(nghbrStatus == 23 || nghbrStatus == 24) {
28071 if(!checkNeighborActive(nghbrId, dir) || a_hasNeighbor(nghbrId, dir) == 0)
continue;
28072 nghbrId = c_neighborId(nghbrId, dir);
28073 if(nghbrId < 0)
continue;
28074 nghbrGapId = m_gapCellId[nghbrId];
28075 nghbrStatus = m_gapCells[nghbrGapId].status;
28077 if(nghbrStatus == 23) {
28079 if(!checkNeighborActive(nghbrId, dir) || a_hasNeighbor(nghbrId, dir) == 0)
continue;
28080 nghbrId = c_neighborId(nghbrId, dir);
28081 if(nghbrId < 0)
continue;
28082 nghbrGapId = m_gapCellId[nghbrId];
28083 nghbrStatus = m_gapCells[nghbrGapId].status;
28088 if(nghbrStatus == 10 || nghbrStatus == 14) {
28091 if(!checkNeighborActive(nghbrId, dir) || a_hasNeighbor(nghbrId, dir) == 0)
continue;
28092 nghbrId = c_neighborId(nghbrId, dir);
28093 if(nghbrId < 0)
continue;
28094 nghbrGapId = m_gapCellId[nghbrId];
28095 nghbrStatus = m_gapCells[nghbrGapId].status;
28097 if(nghbrStatus == 10) {
28099 if(!checkNeighborActive(nghbrId, dir) || a_hasNeighbor(nghbrId, dir) == 0)
continue;
28100 nghbrId = c_neighborId(nghbrId, dir);
28101 if(nghbrId < 0)
continue;
28102 nghbrGapId = m_gapCellId[nghbrId];
28103 nghbrStatus = m_gapCells[nghbrGapId].status;
28106 if(nghbrStatus == 26)
continue;
28108 if(m_gapState[region] == 2 && a_wasGapCell(nghbrId) && nghbrStatus != 25 && nghbrStatus != 21
28109 && nghbrStatus != 23 && nghbrStatus != 22 && nghbrStatus != 24) {
28110 cerr <<
"Caution: using strange neighbor for interpolation: " << c_globalId(cellId) <<
" " << status
28111 <<
" " << c_globalId(nghbrId) <<
" " << a_wasGapCell(nghbrId) <<
" "
28112 << a_hasProperty(nghbrId, SolverCell::WasInactive) <<
" " << nghbrStatus << endl;
28113 }
else if(m_gapState[region] == 3 && a_wasGapCell(nghbrId) && nghbrStatus != 21 && nghbrStatus != 22
28114 && nghbrStatus != 10 && nghbrStatus != 14) {
28115 cerr <<
"Caution: using strange neighbor for interpolation: " << c_globalId(cellId) <<
" " << status
28116 <<
" " << c_globalId(nghbrId) <<
" " << a_wasGapCell(nghbrId) <<
" "
28117 << a_hasProperty(nghbrId, SolverCell::WasInactive) <<
" " << nghbrStatus << endl;
28121 if(a_hasProperty(nghbrId, SolverCell::IsInactive))
continue;
28123 ASSERT(!a_hasProperty(nghbrId, SolverCell::IsInactive),
"");
28124 if(!a_wasGapCell(nghbrId) && a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
28127 auto it1 = m_oldBndryCells.find(nghbrId);
28128 if(it1 != m_oldBndryCells.end())
continue;
28132 pVariables[0] += a_pvariable(nghbrId, PV->RHO);
28133 pVariables[1] += a_pvariable(nghbrId, PV->P);
28134 pVariables[2] += a_pvariable(nghbrId, PV->U);
28135 pVariables[3] += a_pvariable(nghbrId, PV->V);
28136 IF_CONSTEXPR(nDim == 3) pVariables[4] += a_pvariable(nghbrId, PV->W);
28143 a_pvariable(cellId, PV->RHO) = pVariables[0] / noNghbrs;
28144 a_pvariable(cellId, PV->P) = pVariables[1] / noNghbrs;
28145 a_pvariable(cellId, PV->U) = pVariables[2] / noNghbrs;
28146 a_pvariable(cellId, PV->V) = pVariables[3] / noNghbrs;
28147 IF_CONSTEXPR(nDim == 3) a_pvariable(cellId, PV->W) = pVariables[4] / noNghbrs;
28151 gapCellExchange(0);
28160 for(
MInt region = 0; region < m_noGapRegions; region++) {
28161 if(m_gapState[region] != 2)
continue;
28162 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28163 MInt regionId = m_gapCells[it].region;
28164 if(regionId != region)
continue;
28165 MInt cellId = m_gapCells[it].cellId;
28166 MInt status = m_gapCells[it].status;
28168 if(status != 22)
continue;
28170 if(m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_volume / grid().gridCellVolume(a_level(cellId)) > 0.5) {
28171 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
28172 m_oldBndryCells.insert(make_pair(cellId, F0));
28173 m_gapCells[it].status = 29;
28175 if(noArisingGapCells[region] == 0 && fullyGapOpened[region] == 0) {
28177 if(m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_volume / grid().gridCellVolume(a_level(cellId))
28179 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
28180 m_oldBndryCells.insert(make_pair(cellId, F0));
28181 m_gapCells[it].status = 29;
28190 for(
MInt region = 0; region < m_noGapRegions; region++) {
28191 if(m_gapState[region] != 2)
continue;
28192 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28193 MInt regionId = m_gapCells[it].region;
28194 if(regionId != region)
continue;
28195 MInt cellId = m_gapCells[it].cellId;
28196 MInt status = m_gapCells[it].status;
28198 if(status != 21 && status != 22 && status != 29)
continue;
28200 setConservativeVariables(cellId);
28203 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
28204 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
28211 MInt largestNeighbor = checkNeighborActivity(cellId);
28212 if(largestNeighbor > 0) {
28213 MInt largestNeighborGapCellId = m_gapCellId[largestNeighbor];
28214 m_gapCells[largestNeighborGapCellId].status = 28;
28215 if(a_isHalo(largestNeighbor)) {
28216 m_gapCells[largestNeighborGapCellId].status = -99;
28223 gapCellExchange(1);
28277 MInt noGapSplitChild = 0;
28278 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
28279 const MInt cellId = m_splitCells[sc];
28280 if(m_gapCellId[cellId] < 0)
continue;
28281 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
28282 const MInt splitChildId = m_splitChilds[sc][ssc];
28283 a_isGapCell(splitChildId) = a_isGapCell(cellId);
28284 a_wasGapCell(splitChildId) = a_wasGapCell(cellId);
28285 if(a_isGapCell(splitChildId) || a_wasGapCell(splitChildId)) {
28287 const MInt region = m_gapCells[m_gapCellId[cellId]].region;
28288 const MInt status = m_gapCells[m_gapCellId[cellId]].status;
28289 const MInt body1 = m_gapCells[m_gapCellId[cellId]].bodyIds[0];
28290 const MInt body2 = m_gapCells[m_gapCellId[cellId]].bodyIds[1];
28291 const MInt gapId = m_gapCells.size();
28292 m_gapCells.emplace_back(splitChildId, region, status, body1, body2);
28293 m_gapCellId[splitChildId] = gapId;
28294 a_hasProperty(splitChildId, SolverCell::WasInactive) = a_hasProperty(cellId, SolverCell::WasInactive);
28296 if(region > m_noGapRegions)
continue;
28298 if(m_gapState[region] == 2) {
28299 for(
MInt var = 0; var < m_noCVars; var++) {
28300 a_variable(splitChildId, var) = a_variable(cellId, var);
28301 a_oldVariable(splitChildId, var) = a_variable(cellId, var);
28303 for(
MInt var = 0; var < m_noPVars; var++) {
28304 a_pvariable(splitChildId, var) = a_pvariable(cellId, var);
28306 for(
MInt var = 0; var < m_noFVars; var++) {
28307 a_rightHandSide(splitChildId, var) = a_rightHandSide(cellId, var);
28308 m_rhs0[splitChildId][var] = m_rhs0[cellId][var];
28310 }
else if(m_gapState[region] == -2) {
28312 a_hasProperty(splitChildId, SolverCell::IsInactive) = a_hasProperty(cellId, SolverCell::IsInactive);
28313 for(
MInt v = 0; v < m_noFVars; v++) {
28314 a_rightHandSide(splitChildId, v) = a_rightHandSide(cellId, v);
28315 m_rhs0[splitChildId][v] = m_rhs0[cellId][v];
28317 if(!a_hasProperty(splitChildId, SolverCell::WasInactive)
28318 && a_hasProperty(splitChildId, SolverCell::IsInactive)) {
28319 removeSurfaces(cellId);
28325 MPI_Allreduce(MPI_IN_PLACE, &noGapSplitChild, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"noGapSplitChild");
28327#if defined _MB_DEBUG_ || !defined NDEBUG
28328 if(domainId() == 0 && anyGapOpening) cerr <<
" Finished gap-Handling" << endl;
28331 if(noGapSplitChild > 0) {
28332 initGapCellExchange();
28333 gapCellExchange(1);
28335#if defined _MB_DEBUG_ || !defined NDEBUG
28336 if(domainId() == 0) {
28337 cerr <<
"Number of Gap-Split-Childs " << noGapSplitChild << endl;
28348template <MInt nDim,
class SysEqn>
28352 ASSERT(m_levelSet && m_closeGaps,
"");
28353 ASSERT(m_gapInitMethod > 0,
"");
28358 for(
MInt region = 0; region < m_noGapRegions; region++) {
28359 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28360 const MInt regionId = m_gapCells[it].region;
28361 if(regionId != region)
continue;
28362 const MInt cellId = m_gapCells[it].cellId;
28363 const MInt status = m_gapCells[it].status;
28365 ASSERT(a_cellVolume(cellId) > 0,
"");
28367 if(a_cellVolume(cellId) > grid().gridCellVolume(a_level(cellId))) {
28368 const MInt globalId = cellId < c_noCells() ? c_globalId(cellId) : -1;
28369 cerr <<
"Large Volume " << globalId <<
" " << status << endl;
28373 if(m_cellVolumesDt1[cellId] < 0) {
28374 const MInt globalId = cellId < c_noCells() ? c_globalId(cellId) : -1;
28375 cerr <<
"Negative Dt-Volume " << globalId <<
" " << status <<
" "
28376 << m_cellVolumesDt1[cellId] / grid().gridCellVolume(a_level(cellId)) << endl;
28379 if(m_cellVolumesDt1[cellId] > grid().gridCellVolume(a_level(cellId))) {
28380 const MInt globalId = cellId < c_noCells() ? c_globalId(cellId) : -1;
28381 cerr <<
"Large Dt-Volume " << globalId <<
" " << status <<
" "
28382 << m_cellVolumesDt1[cellId] / grid().gridCellVolume(a_level(cellId)) << endl;
28390 for(
MInt region = 0; region < m_noGapRegions; region++) {
28391 if(m_gapState[region] != -2)
continue;
28392 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28393 const MInt regionId = m_gapCells[it].region;
28394 if(regionId != region)
continue;
28395 const MInt cellId = m_gapCells[it].cellId;
28396 const MInt status = m_gapCells[it].status;
28397 if(status == 3 || status == 4) {
28398 ASSERT(a_hasProperty(cellId, SolverCell::IsInactive),
"");
28399 for(
MInt dir = 0; dir < m_noDirs; dir++) {
28400 ASSERT(m_cellSurfaceMapping[cellId][dir] == -1,
"");
28402 auto it1 = m_oldBndryCells.find(cellId);
28403 ASSERT(it1 == m_oldBndryCells.end(),
"");
28404 }
else if(status == 5 || status == 6 || status == 7) {
28405 ASSERT(a_isBndryCell(cellId),
"");
28407 }
else if(status == 8 || status == 9) {
28408 ASSERT(!a_hasProperty(cellId, SolverCell::IsInactive),
"");
28409 ASSERT(!a_isBndryCell(cellId),
"");
28410 ASSERT(abs(a_cellVolume(cellId) - grid().gridCellVolume(a_level(cellId))) < 0.000001,
"");
28411 }
else if(status == 2) {
28412 ASSERT(a_hasProperty(cellId, SolverCell::IsInactive),
"");
28418 for(
MInt region = 0; region < m_noGapRegions; region++) {
28419 if(m_gapState[region] != 3)
continue;
28420 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28421 const MInt regionId = m_gapCells[it].region;
28422 if(regionId != region)
continue;
28423 const MInt cellId = m_gapCells[it].cellId;
28424 const MInt status = m_gapCells[it].status;
28426 ASSERT((status >= 10 && status < 18) || (status == 0 )
28427 || (status == 21 || status == 22 || status == 28 || status == 29),
28428 to_string(status));
28431 if(!a_hasProperty(cellId, SolverCell::IsInactive) && !a_isBndryCell(cellId)) {
28432 ASSERT(!a_hasProperty(cellId, SolverCell::WasInactive),
"");
28436 ASSERT(a_cellVolume(cellId) - grid().gridCellVolume(a_level(cellId)) < 0.00001, to_string(c_globalId(cellId)));
28439 if(a_cellVolume(cellId) < 0 || m_cellVolumesDt1[cellId] < 0) {
28440 cerr <<
"Volume-Error in gap-Cell " << c_globalId(cellId) <<
" " << status <<
" "
28441 << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << a_isHalo(cellId) << endl;
28445 if(status == 12 || status == 13) {
28446 if(a_isHalo(cellId)) {
28457 }
else if(!a_hasProperty(cellId, SolverCell::IsSplitChild)) {
28458 if(!a_hasProperty(cellId, SolverCell::IsTempLinked)) {
28459 cerr <<
"CAUTION: unable to link gap BndryCell during Gap-Widening " << c_globalId(cellId) <<
" " << status
28460 <<
" " << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << a_isBndryCell(cellId) <<
" "
28461 << a_hasProperty(cellId, SolverCell::WasInactive) <<
" " << a_isHalo(cellId) << endl;
28465 }
else if(status == 14 || status == 15) {
28466 if(a_cellVolume(cellId) < 0 || a_cellVolume(cellId) > grid().gridCellVolume(a_level(cellId))) {
28477 for(
MInt region = 0; region < m_noGapRegions; region++) {
28478 if(m_gapState[region] != 2)
continue;
28479 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28480 const MInt regionId = m_gapCells[it].region;
28481 if(regionId != region)
continue;
28482 const MInt cellId = m_gapCells[it].cellId;
28483 const MInt status = m_gapCells[it].status;
28485 ASSERT(((status > 20 && status <= 29) || status == 99 || status == 98), to_string(status));
28488 if(a_cellVolume(cellId) > grid().gridCellVolume(a_level(cellId))
28489 || a_cellVolume(cellId) < grid().gridCellVolume(a_level(cellId))) {
28490 cerr <<
"Incorrect Cell-Volume of arising Gap-Cell" << c_globalId(cellId) <<
" " << a_cellVolume(cellId)
28491 <<
" " << grid().gridCellVolume(a_level(cellId)) << endl;
28495 ASSERT(!a_hasProperty(cellId, SolverCell::IsInactive),
"");
28497 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
28498 for(
MInt dir = 0; dir < m_noDirs; dir++) {
28499 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
28500 MInt nghbrId = c_neighborId(cellId, dir);
28501 if(nghbrId < 0)
continue;
28502 if(a_isHalo(cellId) && a_isHalo(nghbrId))
continue;
28504 cerr <<
"CAUTION: Arising-Gap-Cell is missing surfaces " << c_globalId(cellId) <<
" " << dir <<
" "
28505 << a_levelSetValuesMb(cellId, 0) <<
" " << a_isHalo(cellId) <<
" "
28506 << a_hasProperty(cellId, SolverCell::IsNotGradient) << endl;
28509 }
else if(status == 22 &&
false) {
28510 if(!a_isHalo(cellId)) {
28511 if(!a_hasProperty(cellId, SolverCell::IsTempLinked)) {
28512 cerr <<
"CAUTION: unable to link gap BndryCell during initGapOpening " << c_globalId(cellId) <<
" "
28513 << status <<
" " << a_hasProperty(cellId, SolverCell::IsInactive) <<
" " << a_isBndryCell(cellId)
28514 <<
" " << a_hasProperty(cellId, SolverCell::WasInactive) <<
" " << a_isHalo(cellId) << endl;
28522 for(
MInt region = 0; region < m_noGapRegions; region++) {
28523 if(m_gapState[region] != -1)
continue;
28524 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28525 MInt regionId = m_gapCells[it].region;
28526 if(regionId != region)
continue;
28527 MInt cellId = m_gapCells[it].cellId;
28529 if(!a_isBndryCell(cellId))
continue;
28530 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
28531 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
28533 if(a_wasGapCell(cellId) && !a_isGapCell(cellId))
continue;
28535 MInt bndryId = a_bndryId(cellId);
28536 if(bndryId < -1)
continue;
28537 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28538 for(
MInt i = 0; i < nDim; i++) {
28539 ASSERT(abs(m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]]) < 0.00000001,
"");
28541 MInt ghostCellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_ghostCellId;
28542 if(ghostCellId < 0)
continue;
28548 const MInt noChecks = 4;
28550 cellCheck.
fill(std::numeric_limits<MFloat>::max());
28552 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
28553 cellCheck(cellId, 0) = (
MFloat)a_isGapCell(cellId);
28554 cellCheck(cellId, 1) = (
MFloat)a_wasGapCell(cellId);
28555 cellCheck(cellId, 2) = -F1;
28556 cellCheck(cellId, 3) = -F1;
28557 if(a_isGapCell(cellId) || a_wasGapCell(cellId)) {
28558 const MInt region = m_gapCells[m_gapCellId[cellId]].region;
28559 const MInt status = m_gapCells[m_gapCellId[cellId]].status;
28560 cellCheck(cellId, 2) = (
MFloat)region;
28561 cellCheck(cellId, 3) = (
MFloat)status;
28565 exchangeDataFV(&cellCheck(0), noChecks);
28567 for(
MInt cellId = noInternalCells(); cellId < a_noCells(); cellId++) {
28568 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
28569 if((
MInt)cellCheck(cellId, 0) != a_isGapCell(cellId)) {
28570 cerr << domainId() <<
": ERR0 checkGapHaloCells " <<
globalTimeStep <<
" " << c_globalId(cellId) << endl;
28572 if((
MInt)cellCheck(cellId, 1) != a_wasGapCell(cellId)) {
28573 cerr << domainId() <<
": ERR1 checkGapHaloCells " <<
globalTimeStep <<
" " << c_globalId(cellId) << endl;
28577 if(a_isGapCell(cellId) || a_wasGapCell(cellId)) {
28578 region = m_gapCells[m_gapCellId[cellId]].region;
28579 status = m_gapCells[m_gapCellId[cellId]].status;
28582 if((
MInt)cellCheck(cellId, 2) != region) {
28583 cerr << domainId() <<
": ERR2 checkGapHaloCells " <<
globalTimeStep <<
" " << c_globalId(cellId) << endl;
28585 if((
MInt)cellCheck(cellId, 3) != status) {
28586 cerr << domainId() <<
": ERR3 checkGapHaloCells " <<
globalTimeStep <<
" " << c_globalId(cellId) << endl;
28597template <MInt nDim,
class SysEqn>
28601 ASSERT(m_gapInitMethod == 0,
"");
28603 m_gapCellId.clear();
28604 m_gapCellId.resize(a_noCells());
28605 for(
MInt i = 0; i < a_noCells(); i++)
28606 m_gapCellId[i] = -1;
28608 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28609 const MInt cellId = m_gapCells[it].cellId;
28610 m_gapCellId[cellId] = (
MInt)it;
28613 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
28614 const MInt cellId = m_splitCells[sc];
28615 if(m_gapCellId[cellId] < 0)
continue;
28616 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
28617 const MInt splitChildId = m_splitChilds[sc][ssc];
28618 if(a_isGapCell(splitChildId) || a_wasGapCell(splitChildId)) {
28619 const MInt gapId = m_gapCells.size();
28620 const MInt region = m_gapCells[m_gapCellId[cellId]].region;
28621 const MInt status = m_gapCells[m_gapCellId[cellId]].status;
28622 const MInt body1 = m_gapCells[m_gapCellId[cellId]].bodyIds[0];
28623 const MInt body2 = m_gapCells[m_gapCellId[cellId]].bodyIds[1];
28624 m_gapCells.emplace_back(splitChildId, region, status, body1, body2);
28625 m_gapCellId[splitChildId] = gapId;
28640template <MInt nDim,
class SysEqn>
28644 ASSERT(m_levelSet && m_closeGaps,
"");
28645 ASSERT(m_gapInitMethod > 0,
"");
28648 for(
MInt region = 0; region < m_noGapRegions; region++) {
28649 if(m_gapState[region] != -2)
continue;
28656 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
28657 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
28658 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
28659 const MInt gapCellId = m_gapCellId[cellId];
28660 if(gapCellId < 0)
continue;
28661 const MInt regionId = m_gapCells[gapCellId].region;
28662 if(regionId != region)
continue;
28664 const MInt status = m_gapCells[gapCellId].status;
28667 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
28668 for(
MInt v = 0; v < m_noFVars; v++) {
28669 a_rightHandSide(cellId, v) = F0;
28670 m_rhs0[cellId][v] = F0;
28672 m_sweptVolumeDt1[bndryId] = 0;
28673 m_sweptVolume[bndryId] = 0;
28674 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28675 for(
MInt i = 0; i < nDim; i++) {
28676 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] = 0;
28682 if(status != 5 && status != 6 && status != 7 && status != 99) {
28683 cerr <<
"UnExpected Bndry-Cell-Status (1) " << c_globalId(cellId) <<
" " << status << endl;
28687 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
28688 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
28689 m_sweptVolumeDt1[bndryId] = 0;
28690 m_sweptVolume[bndryId] = 0;
28691 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28692 for(
MInt i = 0; i < nDim; i++) {
28693 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] = 0;
28696 for(
MInt v = 0; v < m_noFVars; v++) {
28697 a_rightHandSide(cellId, v) = F0;
28698 m_rhs0[cellId][v] = F0;
28704 for(
MInt region = 0; region < m_noGapRegions; region++) {
28705 if(m_gapState[region] != 3 && m_gapState[region] != -1)
continue;
28712 for(
MUint it = 0; it < m_gapCells.size(); it++) {
28713 const MInt regionId = m_gapCells[it].region;
28714 if(regionId != region)
continue;
28715 const MInt cellId = m_gapCells[it].cellId;
28716 const MInt status = m_gapCells[it].status;
28718 if(!a_isBndryCell(cellId))
continue;
28719 if(!a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel))
continue;
28720 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
28722 if(a_wasGapCell(cellId) && !a_isGapCell(cellId))
continue;
28727 MInt bndryId = a_bndryId(cellId);
28728 if(bndryId < -1)
continue;
28731 if(a_hasProperty(cellId, SolverCell::IsSplitChild)) {
28732 for(
MInt v = 0; v < m_noFVars; v++) {
28733 a_rightHandSide(cellId, v) = F0;
28734 m_rhs0[cellId][v] = F0;
28736 m_sweptVolumeDt1[bndryId] = 0;
28737 m_sweptVolume[bndryId] = 0;
28738 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28739 for(
MInt i = 0; i < nDim; i++) {
28740 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] = 0;
28746 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
28747 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
28748 m_sweptVolumeDt1[bndryId] = 0;
28749 m_sweptVolume[bndryId] = 0;
28750 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28751 for(
MInt i = 0; i < nDim; i++) {
28752 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] = 0;
28760 MFloat dt = timeStep(
true);
28762 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28763 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
28764 for(
MInt i = 0; i < nDim; i++) {
28765 MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
28766 dV -= dt * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] * nml * area;
28770 MFloat cellVolume = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
28772 if(dV > cellVolume) {
28777 m_sweptVolume[bndryId] = dV;
28778 m_sweptVolumeDt1[bndryId] = dV;
28782 for(
MInt i = 0; i < nDim; i++) {
28783 a_pvariable(cellId, PV->VV[i]) =
28784 delta * a_pvariable(cellId, PV->VV[i])
28785 + (F1 - delta) * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->VV[i]];
28787 setConservativeVariables(cellId);
28788 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
28789 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
28841 for(
MInt region = 0; region < m_noGapRegions; region++) {
28842 if(m_gapState[region] != 2)
continue;
28846 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
28847 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
28848 MInt gapCellId = m_gapCellId[cellId];
28849 if(gapCellId < 0)
continue;
28851 const MInt regionId = m_gapCells[gapCellId].region;
28852 if(regionId != region)
continue;
28854 ASSERT(a_wasGapCell(cellId),
"");
28857 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
28859 MInt status = m_gapCells[gapCellId].status;
28867 if(status != 22 && status != 24 && status != 28 && status != 29) {
28868 cerr <<
"UnExpected Bndry-Cell-Status (2) " << c_globalId(cellId) <<
" " << status << endl;
28872 MFloat dt = timeStep(
true);
28874 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28875 MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
28876 for(
MInt i = 0; i < nDim; i++) {
28877 MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
28878 dV -= dt * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] * nml * area;
28882 MFloat cellVolume = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
28884 if(dV > cellVolume) {
28887 m_gapCells[gapCellId].status = 98;
28890 m_sweptVolume[bndryId] = dV;
28891 m_sweptVolumeDt1[bndryId] = dV;
28894 if(status == 22 || status == 28 || status == 29) {
28899 for(
MInt i = 0; i < nDim; i++) {
28900 a_pvariable(cellId, PV->VV[i]) =
28901 delta * a_pvariable(cellId, PV->VV[i])
28902 + (F1 - delta) * m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[PV->VV[i]];
28904 setConservativeVariables(cellId);
28905 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
28906 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
28911 gapCellExchange(1);
28981 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
28982 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
28983 MInt gapCellId = m_gapCellId[cellId];
28984 if(gapCellId < 0)
continue;
28986 const MInt regionId = m_gapCells[gapCellId].region;
28987 if(regionId != m_noGapRegions)
continue;
28990 for(
MInt i = 0; i < nDim; i++) {
28991 vel[i] = m_gapCells[gapCellId].surfaceVelocity[i];
28995 const MFloat dt = timeStep(
true);
28996 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
28997 const MFloat area = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area;
28998 for(
MInt i = 0; i < nDim; i++) {
28999 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[PV->VV[i]] = vel[i];
29001 const MFloat nml = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
29002 dV -= dt * vel[i] * nml * area;
29005 if(dV * 100 / 5 > grid().gridCellVolume(a_level(cellId))) {
29006 cerr <<
"Large Volume change in G0-region cell! " << dV <<
" " << dV / m_cellVolumesDt1[cellId] << endl;
29012 for(
MUint sc = 0; sc < m_splitCells.size(); sc++) {
29013 const MInt cellId = m_splitCells[sc];
29014 if(m_gapCellId[cellId] > -1)
continue;
29016 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
29017 const MInt splitChildId = m_splitChilds[sc][ssc];
29018 MFloat vol = m_fvBndryCnd->m_bndryCells->a[a_bndryId(splitChildId)].m_volume;
29020 a_cellVolume(splitChildId) = vol * a_cellVolume(cellId);
29021 m_cellVolumesDt1[splitChildId] = vol * m_cellVolumesDt1[cellId];
29023 cvol =
mMax(1e-15, cvol);
29024 for(
MUint ssc = 0; ssc < m_splitChilds[sc].size(); ssc++) {
29025 const MInt splitChildId = m_splitChilds[sc][ssc];
29026 a_cellVolume(splitChildId) /= cvol;
29027 m_cellVolumesDt1[splitChildId] /= cvol;
29037template <MInt nDim,
class SysEqn>
29041 if(!m_levelSetMb)
return;
29043 ASSERT(m_temporarilyLinkedCells.size() < 1,
"");
29045 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
29046 a_hasProperty(cellId, SolverCell::IsTempLinked) =
false;
29049 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
29050 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
29051 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
29052 if(!a_hasProperty(cellId, SolverCell::WasInactive))
continue;
29057 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
29060 if(a_hasProperty(cellId, SolverCell::IsTempLinked))
continue;
29063 for(
MInt v = 0; v < m_noCVars; v++) {
29064 a_oldVariable(cellId, v) = F0;
29068 if(m_levelSet && m_closeGaps && m_gapInitMethod == 0 && a_hasProperty(cellId, SolverCell::WasGapCell)
29069 && !a_hasProperty(cellId, SolverCell::IsGapCell)) {
29076 if(grid().azimuthalPeriodicity() && a_isPeriodic(cellId))
continue;
29079 MInt masterId = -1;
29080 MInt tripleLink = -1;
29082 MInt noInternalNghbrs = 0;
29083 MInt noWasActiveNghbrs = 0;
29084 const MInt rootId = cellId;
29085 for(
MInt dir = 0; dir < m_noDirs; dir++) {
29086 if(!checkNeighborActive(rootId, dir) || a_hasNeighbor(rootId, dir) == 0)
continue;
29087 const MInt nghbrId = c_neighborId(rootId, dir);
29088 if(nghbrId < 0)
continue;
29089 if(!a_isHalo(nghbrId)) noInternalNghbrs++;
29090 if(a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
29091 noWasActiveNghbrs++;
29092 if(a_hasProperty(nghbrId, SolverCell::IsSplitCell))
continue;
29093 if(a_hasProperty(nghbrId, SolverCell::IsSplitChild))
continue;
29094 if(a_cellVolume(nghbrId) > maxVol) {
29095 masterId = nghbrId;
29096 maxVol = a_cellVolume(nghbrId);
29101 if(a_isHalo(cellId) && noInternalNghbrs == 0)
continue;
29102 if(masterId > -1 && a_isHalo(cellId) && a_isHalo(masterId))
continue;
29106 if(masterId > -1) {
29107 m_temporarilyLinkedCells.push_back(make_tuple(cellId, masterId, tripleLink));
29108 a_hasProperty(cellId, SolverCell::IsTempLinked) =
true;
29109 for(
MInt v = 0; v < m_noCVars; v++) {
29110 a_variable(cellId, v) = a_variable(masterId, v);
29111 a_oldVariable(cellId, v) = a_oldVariable(masterId, v);
29113 for(
MInt v = 0; v < m_noPVars; v++) {
29114 a_pvariable(cellId, v) = a_pvariable(masterId, v);
29379 cerr << domainId() <<
" Still no temporary master found for emerged cell " << cellId <<
" "
29380 << c_globalId(cellId) <<
" " << a_isHalo(cellId) <<
" " << a_isWindow(cellId) <<
" "
29381 << a_hasProperty(cellId, SolverCell::IsNotGradient) <<
" " << noInternalNghbrs <<
" " << noWasActiveNghbrs
29382 <<
" " << a_hasProperty(cellId, SolverCell::IsSplitChild) <<
" " << a_levelSetValuesMb(cellId, 0) <<
" "
29383 << a_hasProperty(cellId, SolverCell::IsGapCell) <<
" " << a_hasProperty(cellId, SolverCell::WasGapCell)
29385 << m_fvBndryCnd->m_bndryCells->a[a_bndryId(cellId)].m_volume / grid().gridCellVolume(a_level(cellId))
29386 <<
" " << a_hasProperty(cellId, SolverCell::IsInactive) << endl;
29387 if(m_closeGaps && m_gapCellId[cellId] > 0)
29388 cerr << m_gapCellId[cellId] <<
" " << m_gapCells[m_gapCellId[cellId]].status << endl;
29394 ASSERT(a_isHalo(cellId),
"");
29395 ASSERT(a_hasProperty(cellId, SolverCell::IsNotGradient),
"");
29400 if(grid().azimuthalPeriodicity() && a_isPeriodic(masterId)) {
29401 if(tripleLink >= 0) {
29402 mTerm(1, AT_,
"Triple link with azimuthalPeriodicity");
29410 if(tripleLink < 0 && masterId > -1 && a_isHalo(cellId) != a_isHalo(masterId)) {
29411 if(c_globalId(cellId) < 0 || c_globalId(masterId) < 0) {
29412 cerr << domainId() <<
": GID " << cellId <<
" " << masterId <<
" " << c_globalId(cellId) <<
" "
29413 << c_globalId(masterId) <<
" " << a_isPeriodic(cellId) <<
" " << a_isPeriodic(masterId) << endl;
29415 ASSERT(c_globalId(cellId) > -1 && c_globalId(masterId) > -1,
"");
29416 if(a_isHalo(cellId)) {
29417 ASSERT(a_isWindow(masterId),
"");
29418 MInt ndom = grid().findNeighborDomainId(c_globalId(cellId));
29419 MInt idx = grid().domainIndex(ndom);
29420 ASSERT(neighborDomain(idx) == ndom,
"");
29421 m_linkedHaloCells[idx].push_back(cellId);
29422 m_linkedWindowCells[idx].push_back(masterId);
29425 ASSERT(a_isHalo(masterId),
"");
29426 ASSERT(a_isWindow(cellId),
"");
29427 MInt ndom = grid().findNeighborDomainId(c_globalId(masterId));
29428 MInt idx = grid().domainIndex(ndom);
29429 ASSERT(neighborDomain(idx) == ndom,
"");
29430 m_linkedHaloCells[idx].push_back(masterId);
29431 m_linkedWindowCells[idx].push_back(cellId);
29435 else if(tripleLink > -1 && masterId > -1
29436 && (a_isHalo(cellId) != a_isHalo(tripleLink) || a_isHalo(tripleLink) != a_isHalo(masterId))) {
29440 ASSERT(c_globalId(cellId) > -1 && c_globalId(masterId) > -1 && c_globalId(tripleLink),
"");
29445 MInt ndom11 = grid().findNeighborDomainId(c_globalId(tripleLink));
29446 MInt ndom22 = grid().findNeighborDomainId(c_globalId(cellId));
29447 MInt ndom33 = grid().findNeighborDomainId(c_globalId(masterId));
29449 cerr << domainId() <<
"Parallel Triple-Link Halo-Cells: " << c_globalId(cellId) <<
" " << c_globalId(tripleLink)
29450 <<
" " << c_globalId(masterId) <<
" " << a_isHalo(cellId) <<
" " << a_isHalo(tripleLink) <<
" "
29451 << a_isHalo(masterId) <<
" Domains " << ndom22 <<
" " << ndom11 <<
" " << ndom33 << endl;
29454 if(a_isHalo(tripleLink) && !a_isHalo(masterId)) {
29455 ASSERT(a_isWindow(masterId),
"");
29456 MInt ndom = grid().findNeighborDomainId(c_globalId(tripleLink));
29457 MInt idx = grid().domainIndex(ndom);
29458 ASSERT(neighborDomain(idx) == ndom,
"");
29459 m_linkedHaloCells[idx].push_back(tripleLink);
29460 m_linkedWindowCells[idx].push_back(masterId);
29462 }
else if(a_isHalo(masterId) && !a_isHalo(tripleLink)) {
29463 ASSERT(a_isWindow(tripleLink),
"");
29464 MInt ndom = grid().findNeighborDomainId(c_globalId(masterId));
29465 MInt idx = grid().domainIndex(ndom);
29466 ASSERT(neighborDomain(idx) == ndom,
"");
29467 m_linkedHaloCells[idx].push_back(masterId);
29468 m_linkedWindowCells[idx].push_back(tripleLink);
29471 if(a_isHalo(tripleLink) && !a_isHalo(cellId)) {
29472 ASSERT(a_isWindow(cellId),
"");
29473 MInt ndom = grid().findNeighborDomainId(c_globalId(tripleLink));
29474 MInt idx = grid().domainIndex(ndom);
29475 ASSERT(neighborDomain(idx) == ndom,
"");
29476 m_linkedHaloCells[idx].push_back(tripleLink);
29477 m_linkedWindowCells[idx].push_back(cellId);
29479 }
else if(!a_isHalo(tripleLink) && a_isHalo(cellId)) {
29480 ASSERT(a_isWindow(tripleLink),
"");
29481 MInt ndom = grid().findNeighborDomainId(c_globalId(cellId));
29482 MInt idx = grid().domainIndex(ndom);
29483 ASSERT(neighborDomain(idx) == ndom,
"");
29484 m_linkedHaloCells[idx].push_back(cellId);
29485 m_linkedWindowCells[idx].push_back(tripleLink);
29488 if(a_isHalo(masterId) && !a_isHalo(cellId)) {
29489 }
else if(!a_isHalo(masterId) && a_isHalo(cellId)) {
29495 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29496 sort(m_linkedHaloCells[i].begin(), m_linkedHaloCells[i].end(),
29497 [
this](
const MInt&
a,
const MInt&
b) {
return c_globalId(
a) < c_globalId(
b); });
29498 sort(m_linkedWindowCells[i].begin(), m_linkedWindowCells[i].end(),
29499 [
this](
const MInt&
a,
const MInt&
b) {
return c_globalId(
a) < c_globalId(
b); });
29511template <MInt nDim,
class SysEqn>
29515 ASSERT(cellId >= 0,
"");
29517 if(!a_hasProperty(cellId, SolverCell::WasInactive))
return -1;
29518 if(a_hasProperty(cellId, SolverCell::IsInactive))
return -2;
29520 MInt masterId = -1;
29521 MInt largestNeighbor = -1;
29523 MFloat maxVolActive = F0;
29524 MInt noInternalNghbrs = 0;
29525 for(
MInt dir = 0; dir < m_noDirs; dir++) {
29526 if(!checkNeighborActive(cellId, dir) || a_hasNeighbor(cellId, dir) == 0)
continue;
29527 const MInt nghbrId = c_neighborId(cellId, dir);
29528 if(nghbrId < 0)
continue;
29529 if(a_hasProperty(nghbrId, SolverCell::IsSplitCell))
continue;
29530 if(a_hasProperty(nghbrId, SolverCell::IsSplitChild))
continue;
29531 if(a_cellVolume(nghbrId) > maxVolActive && !a_hasProperty(nghbrId, SolverCell::WasInactive)) {
29532 masterId = nghbrId;
29533 maxVolActive = a_cellVolume(nghbrId);
29535 if(a_cellVolume(nghbrId) > maxVol) {
29536 largestNeighbor = nghbrId;
29537 maxVol = a_cellVolume(nghbrId);
29541 if(masterId > -1)
return -1;
29542 if(a_isHalo(cellId) && noInternalNghbrs == 0)
return -1;
29544 ASSERT(a_hasProperty(largestNeighbor, SolverCell::WasInactive),
"");
29545 ASSERT(largestNeighbor > 0,
"");
29548 if(a_cellVolume(largestNeighbor) < a_cellVolume(cellId)) {
29549 MInt backup = cellId;
29550 cellId = largestNeighbor;
29551 largestNeighbor = backup;
29570 ASSERT(a_wasGapCell(largestNeighbor) || a_isGapCell(largestNeighbor),
"");
29574 const MInt region = m_gapCells[m_gapCellId[cellId]].region;
29575 ASSERT(region > -1 && region < m_noGapRegions,
"");
29576 if(m_gapState[region] != 2) {
29588 if(a_isHalo(largestNeighbor) && a_hasProperty(largestNeighbor, SolverCell::IsNotGradient)) {
29593 for(
MInt dir = 0; dir < m_noDirs; dir++) {
29594 if(!checkNeighborActive(largestNeighbor, dir) || a_hasNeighbor(largestNeighbor, dir) == 0)
continue;
29595 MInt nghbrId = c_neighborId(largestNeighbor, dir);
29596 if(nghbrId < 0)
continue;
29597 if(a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
29598 if(a_cellVolume(nghbrId) > maxVol) {
29599 masterId = nghbrId;
29600 maxVol = a_cellVolume(nghbrId);
29604 if(masterId > -1) {
29605 for(
MInt v = 0; v < m_noCVars; v++) {
29606 a_variable(largestNeighbor, v) = a_variable(masterId, v);
29607 a_oldVariable(largestNeighbor, v) = a_oldVariable(masterId, v);
29609 for(
MInt v = 0; v < m_noPVars; v++) {
29610 a_pvariable(largestNeighbor, v) = a_pvariable(masterId, v);
29612 for(
MInt v = 0; v < m_noFVars; v++) {
29613 a_rightHandSide(largestNeighbor, v) = F0;
29614 m_rhs0[largestNeighbor][v] = F0;
29623 cerr << a_isHalo(largestNeighbor) <<
" " << a_isHalo(cellId) << endl;
29624 mTerm(1, AT_,
"Even the largest neighbor is inactive!");
29629 if(a_isHalo(largestNeighbor)) {
29630 cerr <<
"Caution changing cell-property of a Halo-Cell! " << endl;
29634 a_hasProperty(largestNeighbor, SolverCell::WasInactive) =
false;
29635 m_oldBndryCells.insert(make_pair(largestNeighbor, F0));
29638 return largestNeighbor;
29647template <MInt nDim,
class SysEqn>
29651#if defined _MB_DEBUG_ || !defined NDEBUG
29656 if(m_gapCellExchangeInit)
return;
29657 m_gapCellExchangeInit =
true;
29659 if(noNeighborDomains() == 0)
return;
29661 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29662 m_gapWindowCells[i].clear();
29663 m_gapHaloCells[i].clear();
29673 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29674 ASSERT(m_gapHaloCells[i].size() == 0,
"");
29675 for(
MInt j = 0; j < noHaloCells(i); j++) {
29676 MInt cellId = haloCellId(i, j);
29677 if(a_wasGapCell(cellId) || a_isGapCell(cellId)) {
29678 m_gapHaloCells[i].push_back(cellId);
29687 &isGap[0], &recvBuffer[0]);
29691 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29692 ASSERT(m_gapWindowCells[i].size() == 0,
"");
29693 for(
MInt j = 0; j < noWindowCells(i); j++) {
29694 MInt cellId = windowCellId(i, j);
29695 if(recvBuffer[recvSize]) {
29696 ASSERT(a_isGapCell(cellId) || a_wasGapCell(cellId),
"");
29697 m_gapWindowCells[i].push_back(cellId);
29704#if defined _MB_DEBUG_ || !defined NDEBUG
29706 MPI_Status statusMpi;
29710 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
29712 if(a_isGapCell(cellId)) check[cellId] = 2;
29713 if(a_wasGapCell(cellId)) check[cellId] = 3;
29714 if(a_isGapCell(cellId) && a_wasGapCell(cellId)) check[cellId] = 4;
29718 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29719 if(m_gapWindowCells[i].empty())
continue;
29720 MInt sendBufferCounter = 0;
29721 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
29722 MInt cellId = m_gapWindowCells[i][j];
29723 m_sendBuffers[i][sendBufferCounter] = (
MFloat)check[cellId];
29724 sendBufferCounter++;
29730 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29731 if(m_gapWindowCells[i].empty())
continue;
29732 MInt bufSize = m_gapWindowCells[i].
size();
29733 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
29734 "m_sendBuffers[i]");
29738 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29739 if(m_gapHaloCells[i].empty())
continue;
29740 MInt bufSize = m_gapHaloCells[i].size();
29741 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
29742 "m_receiveBuffers[i]");
29744 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29745 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
29749 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29750 if(m_gapHaloCells[i].empty())
continue;
29751 MInt receiveBufferCounter = 0;
29752 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
29753 MInt cellId = m_gapHaloCells[i][j];
29754 check[cellId] = (
MInt)m_receiveBuffers[i][receiveBufferCounter];
29755 receiveBufferCounter++;
29759 for(
MInt cellId = noInternalCells(); cellId < a_noCells(); cellId++) {
29760 if(a_hasProperty(cellId, SolverCell::IsSplitChild))
continue;
29761 if(a_isGapCell(cellId) && !a_wasGapCell(cellId))
29762 ASSERT(check[cellId] == 2,
"");
29763 else if(a_wasGapCell(cellId) && !a_isGapCell(cellId))
29764 ASSERT(check[cellId] == 3,
"");
29765 else if(a_isGapCell(cellId) && a_wasGapCell(cellId))
29766 ASSERT(check[cellId] == 4,
"");
29768 ASSERT(check[cellId] == 0,
"");
29785template <MInt nDim,
class SysEqn>
29789 ASSERT(m_gapCellExchangeInit,
"");
29790 if(noNeighborDomains() == 0)
return;
29792 MPI_Status statusMpi;
29797 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29798 if(m_gapWindowCells[i].empty())
continue;
29799 MInt sendBufferCounter = 0;
29800 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
29801 MInt cellId = m_gapWindowCells[i][j];
29802 memcpy((
void*)&m_sendBuffers[i][sendBufferCounter], (
void*)&a_pvariable(cellId, 0),
29803 m_dataBlockSize *
sizeof(
MFloat));
29804 sendBufferCounter += m_dataBlockSize;
29809 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29810 if(m_gapWindowCells[i].empty())
continue;
29811 MInt bufSize = m_gapWindowCells[i].size() * m_dataBlockSize;
29812 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
29813 "m_sendBuffers[i]");
29817 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29818 if(m_gapHaloCells[i].empty())
continue;
29819 MInt bufSize = m_gapHaloCells[i].size() * m_dataBlockSize;
29820 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
29821 "m_receiveBuffers[i]");
29823 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29824 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
29828 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29829 if(m_gapHaloCells[i].empty())
continue;
29830 MInt receiveBufferCounter = 0;
29831 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
29832 MInt cellId = m_gapHaloCells[i][j];
29833 memcpy((
void*)&a_pvariable(cellId, 0), (
void*)&m_receiveBuffers[i][receiveBufferCounter],
29834 m_dataBlockSize *
sizeof(
MFloat));
29835 receiveBufferCounter += m_dataBlockSize;
29843 MInt reverseExchange = 0;
29852 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29853 if(m_gapWindowCells[i].empty())
continue;
29854 MInt sendBufferCounter = 0;
29855 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
29856 MInt cellId = m_gapWindowCells[i][j];
29857 m_sendBuffers[i][sendBufferCounter] = -F1;
29858 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
29859 m_sendBuffers[i][sendBufferCounter] = F1;
29861 sendBufferCounter++;
29867 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29868 if(m_gapWindowCells[i].empty())
continue;
29869 MInt bufSize = m_gapWindowCells[i].size();
29870 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
29871 "m_sendBuffers[i]");
29875 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29876 if(m_gapHaloCells[i].empty())
continue;
29877 MInt bufSize = m_gapHaloCells[i].size();
29878 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
29879 "m_receiveBuffers[i]");
29881 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29882 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
29886 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29887 if(m_gapHaloCells[i].empty())
continue;
29888 MInt receiveBufferCounter = 0;
29889 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
29890 const MInt cellId = m_gapHaloCells[i][j];
29891 const MInt status = m_gapCells[m_gapCellId[cellId]].status;
29892 if(status == -99) {
29893 reverseExchange = 1;
29894 receiveBufferCounter++;
29897 if(m_receiveBuffers[i][receiveBufferCounter] > 0) {
29898 a_hasProperty(cellId, SolverCell::WasInactive) =
true;
29900 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
29902 receiveBufferCounter++;
29906 MPI_Allreduce(MPI_IN_PLACE, &reverseExchange, 1, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
29907 "reverseExchange");
29909 if(reverseExchange > 0) {
29912 vector<MInt> updatedWindowCells;
29915 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29916 if(m_gapHaloCells[i].empty())
continue;
29917 MInt sendBufferCounter = 0;
29918 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
29919 MInt cellId = m_gapHaloCells[i][j];
29920 m_sendBuffers[i][sendBufferCounter] = -1.0;
29921 if(m_gapCells[m_gapCellId[cellId]].status == -99) {
29922 ASSERT(a_hasProperty(cellId, SolverCell::WasInactive) ==
false,
"");
29923 m_sendBuffers[i][sendBufferCounter] = 2.0;
29925 sendBufferCounter++;
29930 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29931 if(m_gapHaloCells[i].empty())
continue;
29932 MInt bufSize = m_gapHaloCells[i].size();
29933 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
29934 "m_sendBuffers[i]");
29938 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29939 if(m_gapWindowCells[i].empty())
continue;
29940 MInt bufSize = m_gapWindowCells[i].size();
29941 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
29942 "m_receiveBuffers[i]");
29944 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29945 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
29949 for(
MInt i = 0; i < noNeighborDomains(); i++) {
29950 if(m_gapWindowCells[i].empty())
continue;
29951 MInt receiveBufferCounter = 0;
29952 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
29953 MInt cellId = m_gapWindowCells[i][j];
29954 if(m_receiveBuffers[i][receiveBufferCounter] > 1) {
29955 updatedWindowCells.push_back(cellId);
29957 receiveBufferCounter++;
29962 for(
MUint i = 0; i < updatedWindowCells.size(); i++) {
29963 MInt cellId = updatedWindowCells[i];
29964 cerr <<
"Updating Window-Cell " << c_globalId(cellId) << endl;
29965 MInt masterId = -1;
29967 const MInt rootId = cellId;
29968 for(
MInt dir = 0; dir < m_noDirs; dir++) {
29969 if(!checkNeighborActive(rootId, dir) || a_hasNeighbor(rootId, dir) == 0)
continue;
29970 const MInt nghbrId = c_neighborId(rootId, dir);
29971 if(nghbrId < 0)
continue;
29972 if(a_hasProperty(nghbrId, SolverCell::WasInactive))
continue;
29973 if(a_hasProperty(nghbrId, SolverCell::IsSplitCell))
continue;
29974 if(a_hasProperty(nghbrId, SolverCell::IsSplitChild))
continue;
29975 if(a_cellVolume(nghbrId) > maxVol) {
29976 masterId = nghbrId;
29977 maxVol = a_cellVolume(nghbrId);
29980 if(masterId > -1) {
29984 for(
MInt v = 0; v < m_noCVars; v++) {
29985 a_variable(cellId, v) = a_variable(masterId, v);
29986 a_oldVariable(cellId, v) = a_oldVariable(masterId, v);
29988 for(
MInt v = 0; v < m_noPVars; v++) {
29989 a_pvariable(cellId, v) = a_pvariable(masterId, v);
29992 for(
MInt v = 0; v < m_noFVars; v++) {
29993 a_rightHandSide(cellId, v) = F0;
29994 m_rhs0[cellId][v] = F0;
29996 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
29997 MInt gapCellId = m_gapCellId[cellId];
29998 MInt region = m_gapCells[gapCellId].region;
29999 ASSERT(region > -1 && region < m_noGapRegions,
" ");
30000 if(m_gapState[region] == 3) {
30001 m_gapCells[gapCellId].status = 17;
30003 m_gapCells[gapCellId].status = 28;
30012 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30013 if(m_gapWindowCells[i].empty())
continue;
30014 MInt sendBufferCounter = 0;
30015 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
30016 MInt cellId = m_gapWindowCells[i][j];
30017 m_sendBuffers[i][sendBufferCounter] = -F1;
30018 if(a_hasProperty(cellId, SolverCell::WasInactive)) {
30019 m_sendBuffers[i][sendBufferCounter] = F1;
30021 sendBufferCounter++;
30027 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30028 if(m_gapWindowCells[i].empty())
continue;
30029 MInt bufSize = m_gapWindowCells[i].size();
30030 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
30031 "m_sendBuffers[i]");
30035 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30036 if(m_gapHaloCells[i].empty())
continue;
30037 MInt bufSize = m_gapHaloCells[i].size();
30038 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
30039 "m_receiveBuffers[i]");
30041 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30042 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
30046 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30047 if(m_gapHaloCells[i].empty())
continue;
30048 MInt receiveBufferCounter = 0;
30049 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
30050 MInt cellId = m_gapHaloCells[i][j];
30051 if(m_receiveBuffers[i][receiveBufferCounter] > 0) {
30052 a_hasProperty(cellId, SolverCell::WasInactive) =
true;
30054 a_hasProperty(cellId, SolverCell::WasInactive) =
false;
30056 receiveBufferCounter++;
30064 gapCellExchange(0);
30069 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30070 if(m_gapWindowCells[i].empty())
continue;
30071 MInt sendBufferCounter = 0;
30072 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
30073 MInt cellId = m_gapWindowCells[i][j];
30074 memcpy((
void*)&m_sendBuffers[i][sendBufferCounter], (
void*)&a_oldVariable(cellId, 0),
30075 m_dataBlockSize *
sizeof(
MFloat));
30076 sendBufferCounter += m_dataBlockSize;
30081 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30082 if(m_gapWindowCells[i].empty())
continue;
30083 MInt bufSize = m_gapWindowCells[i].size() * m_dataBlockSize;
30084 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
30085 "m_sendBuffers[i]");
30089 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30090 if(m_gapHaloCells[i].empty())
continue;
30091 MInt bufSize = m_gapHaloCells[i].size() * m_dataBlockSize;
30092 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
30093 "m_receiveBuffers[i]");
30095 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30096 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
30100 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30101 if(m_gapHaloCells[i].empty())
continue;
30102 MInt receiveBufferCounter = 0;
30103 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
30104 MInt cellId = m_gapHaloCells[i][j];
30105 memcpy((
void*)&a_oldVariable(cellId, 0), (
void*)&m_receiveBuffers[i][receiveBufferCounter],
30106 m_dataBlockSize *
sizeof(
MFloat));
30107 receiveBufferCounter += m_dataBlockSize;
30114 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30115 if(m_gapWindowCells[i].empty())
continue;
30116 MInt sendBufferCounter = 0;
30117 for(
MInt j = 0; j < (signed)m_gapWindowCells[i].size(); j++) {
30118 MInt cellId = m_gapWindowCells[i][j];
30119 MInt gapCellId = m_gapCellId[cellId];
30120 m_sendBuffers[i][sendBufferCounter] = (
MFloat)m_gapCells[gapCellId].status;
30121 sendBufferCounter++;
30127 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30128 if(m_gapWindowCells[i].empty())
continue;
30129 MInt bufSize = m_gapWindowCells[i].size();
30130 MPI_Issend(m_sendBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &g_mpiRequestMb[i], AT_,
30131 "m_sendBuffers[i]");
30135 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30136 if(m_gapHaloCells[i].empty())
continue;
30137 MInt bufSize = m_gapHaloCells[i].size();
30138 MPI_Recv(m_receiveBuffers[i], bufSize, MPI_DOUBLE, neighborDomain(i), 0, mpiComm(), &statusMpi, AT_,
30139 "m_receiveBuffers[i]");
30141 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30142 MPI_Wait(&g_mpiRequestMb[i], &statusMpi, AT_);
30146 for(
MInt i = 0; i < noNeighborDomains(); i++) {
30147 if(m_gapHaloCells[i].empty())
continue;
30148 MInt receiveBufferCounter = 0;
30149 for(
MInt j = 0; j < (signed)m_gapHaloCells[i].size(); j++) {
30150 MInt cellId = m_gapHaloCells[i][j];
30151 MInt gapCellId = m_gapCellId[cellId];
30152 m_gapCells[gapCellId].status = (
MInt)m_receiveBuffers[i][receiveBufferCounter];
30153 receiveBufferCounter++;
30165template <MInt nDim,
class SysEqn>
30169 NEW_TIMER_GROUP_STATIC(tg_solutionStep,
"solution step");
30170 NEW_TIMER_STATIC(t_solutionStep,
"time integration", tg_solutionStep);
30171 NEW_SUB_TIMER_STATIC(t_timeIntegration,
"time integration", t_solutionStep);
30172 NEW_SUB_TIMER_STATIC(t_lhs,
"lhs", t_timeIntegration);
30173 NEW_SUB_TIMER_STATIC(t_lhsBnd,
"lhsBnd", t_timeIntegration);
30174 NEW_SUB_TIMER_STATIC(t_rhs,
"rhs", t_timeIntegration);
30175 NEW_SUB_TIMER_STATIC(t_rhsBnd,
"rhsBnd", t_timeIntegration);
30177 RECORD_TIMER_START(t_solutionStep);
30178 RECORD_TIMER_START(t_timeIntegration);
30182 RECORD_TIMER_START(t_lhsBnd);
30183 this->lhsBndFinish();
30184 RECORD_TIMER_STOP(t_lhsBnd);
30186 RECORD_TIMER_START(t_rhs);
30188 RECORD_TIMER_STOP(t_rhs);
30190 RECORD_TIMER_START(t_rhsBnd);
30192 RECORD_TIMER_STOP(t_rhsBnd);
30195 m_splitMpiCommRecv =
true;
30199 RECORD_TIMER_START(t_lhs);
30200 MBool timeStepCompleted = this->solverStep();
30201 RECORD_TIMER_STOP(t_lhs);
30204 RECORD_TIMER_START(t_lhsBnd);
30206 RECORD_TIMER_STOP(t_lhsBnd);
30210 RECORD_TIMER_START(t_rhs);
30212 RECORD_TIMER_STOP(t_rhs);
30215 RECORD_TIMER_START(t_rhsBnd);
30217 RECORD_TIMER_STOP(t_rhsBnd);
30220 RECORD_TIMER_STOP(t_timeIntegration);
30221 RECORD_TIMER_STOP(t_solutionStep);
30223 return timeStepCompleted;
30231template <MInt nDim,
class SysEqn>
30235 RECORD_TIMER_START(m_timers[Timers::PreTime]);
30237 if(!grid().wasAdapted()) {
30242 if(m_constructGField) {
30243 constructGFieldPredictor();
30244 }
else if(!m_LsMovement) {
30245 updateBodyProperties();
30250 RECORD_TIMER_STOP(m_timers[Timers::PreTime]);
30251 if(grid().wasAdapted()) {
30252 if(!isMultilevel() || isMultilevelPrimary()) {
30253 preSolutionStep(0);
30258 RECORD_TIMER_START(m_timers[Timers::PreTime]);
30261 const MInt interval = !m_multilevel ? 500 : 100;
30263 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30264 if(!m_fvBndryCnd->m_smallCellRHSCorrection) {
30266 a_localTimeStep(cellId) = timeStep() *
IPOW2(maxLevel() - a_level(cellId));
30268 a_localTimeStep(cellId) = computeTimeStepEulerDirectional(cellId);
30275 if(grid().wasAdapted() || grid().wasBalanced()) {
30276 initCutOffBoundaryCondition();
30279 constexpr MBool dbg =
false;
30280 if constexpr(dbg) {
30283 const MInt noVolSteps = 20;
30286 const MFloat deltaVol = F1 / noVolSteps;
30289 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30290 if(a_isHalo(cellId))
continue;
30291 if(a_isBndryGhostCell(cellId))
continue;
30292 if(a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
30293 if(!a_isBndryCell(cellId))
continue;
30295 const MFloat vFrac = a_cellVolume(cellId) / grid().gridCellVolume(a_level(cellId));
30296 const MInt pos = floor(vFrac / deltaVol);
30302 MPI_Allreduce(MPI_IN_PLACE, &volumes(0), noVolSteps, MPI_INT, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"volumes");
30305 if(domainId() == 0) {
30307 struct stat buffer;
30308 std::string name =
"Volumes_" + to_string(solverId());
30309 const char* cstr = name.c_str();
30310 if(stat(cstr, &buffer) == 0) {
30311 rename(cstr,
"Volumes_BAK");
30313 datei = fopen(cstr,
"w");
30314 fprintf(datei,
"%s",
"# 1:volLower 2:volUpper 3:count \n");
30315 for(
MInt i = 0; i < noVolSteps; i++) {
30316 const MFloat volLimit1 = i * deltaVol;
30317 const MFloat volLimit2 = i * deltaVol + deltaVol;
30318 fprintf(datei,
"%.8g", volLimit1);
30319 fprintf(datei,
" %.8g", volLimit2);
30320 fprintf(datei,
" %d", volumes(i));
30321 fprintf(datei,
"\n");
30328 m_splitMpiCommRecv =
false;
30332 RECORD_TIMER_STOP(m_timers[Timers::PreTime]);
30340template <MInt nDim,
class SysEqn>
30344 RECORD_TIMER_START(m_timers[Timers::PostTime]);
30348 this->lhsBndFinish();
30349 m_splitMpiCommRecv =
false;
30358 if(m_maxIterations == 1) {
30359 RECORD_TIMER_STOP(m_timers[Timers::PostTime]);
30360 postSolutionStep();
30361 RECORD_TIMER_START(m_timers[Timers::PostTime]);
30364 m_forceAdaptation = adaptationTrigger();
30367 if(isMultilevelLowestSecondary()) {
30368 prepareNextTimeStep();
30371 RECORD_TIMER_STOP(m_timers[Timers::PostTime]);
30379template <MInt nDim,
class SysEqn>
30383 ASSERT(m_constructGField,
"Wrong function to call for m_constructGField = false!");
30385 m_complexBoundary = Context::getSolverProperty<MBool>(
"complexBoundaryForMb", m_solverId, AT_, &m_complexBoundary);
30387 m_buildCollectedLevelSetFunction = Context::getSolverProperty<MBool>(
"buildCollectedLevelSetFunction", m_solverId,
30388 AT_, &m_buildCollectedLevelSetFunction);
30392 MInt noPeriodicDirs = 0;
30393 for(
MInt dir = 0; dir < nDim; dir++) {
30394 if(grid().periodicCartesianDir(dir)) noPeriodicDirs++;
30397 if(m_complexBoundary) {
30398 mAlloc(m_bodyToSetTable, m_noEmbeddedBodies,
"m_bodyToSetTable", 0, AT_);
30399 mAlloc(m_noBodiesInSet, m_noLevelSetsUsedForMb,
"m_noBodiesInSet", 0, AT_);
30400 mAlloc(m_setToBodiesTable, m_noLevelSetsUsedForMb, m_noEmbeddedBodies,
"m_setToBodiesTable", 0, AT_);
30402 if(!m_buildCollectedLevelSetFunction) {
30405 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30406 m_bodyToSetTable[i] = 0;
30407 m_setToBodiesTable[0][m_noBodiesInSet[0]] = i;
30408 m_noBodiesInSet[0]++;
30410 }
else if(m_buildCollectedLevelSetFunction) {
30412 m_noSets =
mMin(m_noLevelSetsUsedForMb, m_noEmbeddedBodies + m_startSet);
30413 if(m_noSets > m_noLevelSetsUsedForMb)
30414 mTerm(1, AT_,
"Too many bodies for mode 1, m_noSets would be higher than m_noLevelSetsUsedForMb!");
30415 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30416 MInt id = m_startSet + i % (m_noLevelSetsUsedForMb - 1);
30417 m_bodyToSetTable[i] =
id;
30418 m_setToBodiesTable[
id][m_noBodiesInSet[
id]] = i;
30419 m_noBodiesInSet[
id]++;
30421 m_noBodiesInSet[0] = 0;
30422 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30423 m_setToBodiesTable[0][m_noBodiesInSet[0]] = i;
30424 m_noBodiesInSet[0]++;
30428 if((m_maxNoEmbeddedBodiesPeriodic > m_noEmbeddedBodies) ) {
30429 if(!m_buildCollectedLevelSetFunction)
mTerm(1, AT_,
"This case is unknown.");
30433 mAlloc(m_bodyToSetTable, m_maxNoEmbeddedBodiesPeriodic,
"m_bodyToSetTable", 0, AT_);
30434 mAlloc(m_noBodiesInSet, m_noLevelSetsUsedForMb,
"m_noBodiesInSet", 0, AT_);
30435 mAlloc(m_setToBodiesTable, m_noLevelSetsUsedForMb, m_maxNoEmbeddedBodiesPeriodic,
"m_setToBodiesTable", 0, AT_);
30437 for(
MInt i = 0; i < m_noLevelSetsUsedForMb; i++) {
30438 for(
MInt j = 0; j < m_maxNoEmbeddedBodiesPeriodic; j++)
30439 m_setToBodiesTable[i][j] = 0;
30440 m_noBodiesInSet[i] = 0;
30442 m_noBodiesInSet[0] = 0;
30443 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30444 m_setToBodiesTable[0][m_noBodiesInSet[0]] = i;
30445 m_bodyToSetTable[i] = 0;
30446 m_noBodiesInSet[0]++;
30449 m_noSets =
mMin(m_noLevelSetsUsedForMb, m_noEmbeddedBodies + m_startSet);
30450 if(m_noSets > m_noLevelSetsUsedForMb)
30451 mTerm(1, AT_,
"Too many bodies for mode 0, m_noSets would be higher than m_noLevelSetsUsedForMb!");
30452 for(
MInt i = 0; i < m_noLevelSetsUsedForMb; i++) {
30453 for(
MInt j = 0; j < m_maxNoEmbeddedBodiesPeriodic; j++)
30454 m_setToBodiesTable[i][j] = 0;
30455 m_noBodiesInSet[i] = 0;
30457 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30458 MInt id = m_startSet + i % (m_noLevelSetsUsedForMb - 1);
30459 m_bodyToSetTable[i] =
id;
30460 m_setToBodiesTable[
id][m_noBodiesInSet[
id]] = i;
30461 m_noBodiesInSet[
id]++;
30463 m_noBodiesInSet[0] = 0;
30464 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30465 m_setToBodiesTable[0][m_noBodiesInSet[0]] = i;
30466 m_noBodiesInSet[0]++;
30470 if(m_bodyToSetTable ==
nullptr)
mAlloc(m_bodyToSetTable, m_maxNoEmbeddedBodiesPeriodic,
"m_bodyToSetTable", 0, AT_);
30471 if(m_noBodiesInSet ==
nullptr)
mAlloc(m_noBodiesInSet, m_noLevelSetsUsedForMb,
"m_noBodiesInSet", 0, AT_);
30472 if(m_setToBodiesTable ==
nullptr)
30473 mAlloc(m_setToBodiesTable, m_noLevelSetsUsedForMb, m_maxNoEmbeddedBodiesPeriodic,
"m_noBodiesInSet", 0, AT_);
30476 for(
MInt i = 0; i < m_noLevelSetsUsedForMb; i++) {
30477 for(
MInt j = 0; j < m_maxNoEmbeddedBodiesPeriodic; j++)
30478 m_setToBodiesTable[i][j] = 0;
30479 m_noBodiesInSet[i] = 0;
30481 m_noBodiesInSet[0] = 0;
30482 for(
MInt i = 0; i < m_noEmbeddedBodies; i++) {
30483 m_setToBodiesTable[0][m_noBodiesInSet[0]] = i;
30484 m_bodyToSetTable[i] = 0;
30485 m_noBodiesInSet[0]++;
30489 if(m_noSets > 0 && domainId() == 0) {
30490 m_log <<
" m_noSets: " << m_noSets << endl;
30491 m_log <<
" start set: " << m_startSet << endl;
30492 m_log <<
" m_bodyToSetTable: ";
30493 for(
MInt i = 0; i <
mMin(m_noEmbeddedBodies, 10); i++)
30494 m_log <<
" " << m_bodyToSetTable[i];
30496 m_log <<
" m_noBodiesInSet: ";
30497 for(
MInt i = 0; i < m_noLevelSetsUsedForMb; i++)
30498 m_log <<
" " << m_noBodiesInSet[i];
30500 m_log <<
" m_setToBodiesTable: ";
30501 for(
MInt i = 0; i < m_noLevelSetsUsedForMb; i++) {
30502 m_log <<
" s" << i <<
": ";
30503 for(
MInt j = 0; j < m_noBodiesInSet[i]; j++)
30504 m_log <<
" " << m_setToBodiesTable[i][j];
30514template <MInt nDim,
class SysEqn>
30518 m_geometryIntersection->m_noEmbeddedBodies = m_noEmbeddedBodies;
30519 m_geometryIntersection->m_noLevelSetsUsedForMb = m_noLevelSetsUsedForMb;
30520 m_geometryIntersection->m_bodyToSetTable = m_bodyToSetTable;
30521 m_geometryIntersection->m_setToBodiesTable = m_setToBodiesTable;
30522 m_geometryIntersection->m_noBodiesInSet = m_noBodiesInSet;
30529template <MInt nDim,
class SysEqn>
30547template <MInt nDim,
class SysEqn>
30551 NEW_TIMER_GROUP(t_initTimer,
"initSolutionStep");
30552 NEW_TIMER(t_timertotal,
"initSolutionStep", t_initTimer);
30553 NEW_SUB_TIMER(t_init,
"init", t_timertotal);
30554 NEW_SUB_TIMER(t_createBnd,
"createBoundaryCells", t_timertotal);
30555 NEW_SUB_TIMER(t_initBnd,
"initBoundaryCells", t_timertotal);
30556 NEW_SUB_TIMER(t_stencil,
"buildStencil", t_timertotal);
30557 NEW_SUB_TIMER(t_surfaces,
"createSurfaces", t_timertotal);
30558 NEW_SUB_TIMER(t_initSurfaces,
"initSurfaces", t_timertotal);
30559 NEW_SUB_TIMER(t_finalize,
"finalize", t_timertotal);
30560 RECORD_TIMER_START(t_timertotal);
30561 RECORD_TIMER_START(t_init);
30563 grid().updateGridInfo();
30564 if(m_fvBndryCnd->m_cellCoordinatesCorrected) m_fvBndryCnd->recorrectCellCoordinates();
30566 MBool& frstrn = m_static_initSolutionStep_frstrn;
30569 ASSERT(frstrn,
"");
30570 ASSERT(!m_onlineRestart,
"");
30571 }
else if(mode == 1) {
30572 ASSERT(m_onlineRestart,
"");
30574 ASSERT(!m_onlineRestart,
"");
30578 if(!m_restart && mode < 1) {
30579 if(m_constructGField && m_bodyTypeMb) {
30582 m_bndryGhostCellsOffset = a_noCells();
30585 exchangeLevelSetData();
30586 setCellProperties();
30588 RECORD_TIMER_STOP(t_init);
30589 RECORD_TIMER_START(t_createBnd);
30591 setLevelSetMbCellProperties();
30593 IF_CONSTEXPR(nDim == 3) {
30594 if(m_noPointParticles > 0) {
30595 initBodyProperties();
30602 computeCellVolumes();
30606 generateBndryCells();
30607 m_noOuterBndryCells = m_fvBndryCnd->m_bndryCells->size();
30608 IF_CONSTEXPR(nDim == 3) { checkCells(); }
30610 for(
MInt bndryId = 0; bndryId < m_noOuterBndryCells; bndryId++) {
30611 const MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
30612 a_cellVolume(cellId) = m_fvBndryCnd->m_bndryCells->a[bndryId].m_volume;
30613 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
30614 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
30615 a_FcellVolume(cellId) = F1 /
mMax(m_volumeThreshold, a_cellVolume(cellId));
30616 m_sweptVolume[bndryId] = F0;
30617 m_sweptVolumeDt1[bndryId] = F0;
30622 if(m_dualTimeStepping) {
30623 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30624 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
30625 a_dt2Variable(cellId, varId) = a_variable(cellId, varId);
30626 a_dt1Variable(cellId, varId) = a_variable(cellId, varId);
30630 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30631 for(
MInt varId = 0; varId < CV->noVariables; varId++) {
30632 a_oldVariable(cellId, varId) = a_variable(cellId, varId);
30639 m_fvBndryCnd->correctCellCoordinates();
30644 m_fvBndryCnd->correctCoarseBndryCells();
30645 m_fvBndryCnd->m_smallBndryCells->setSize(0);
30647 RECORD_TIMER_STOP(t_createBnd);
30648 RECORD_TIMER_START(t_initBnd);
30650 if(m_fvBndryCnd->m_cellMerging) {
30653 m_fvBndryCnd->detectSmallBndryCells();
30654 m_log <<
"Connecting master and slave cells...";
30655 m_fvBndryCnd->mergeCells();
30656 m_log <<
"ok" << endl;
30658 m_fvBndryCnd->setBCTypes();
30659 m_fvBndryCnd->setNearBoundaryRecNghbrs();
30660 m_fvBndryCnd->computeImagePointRecConst();
30661 if(m_fvBndryCnd->m_smallCellRHSCorrection) {
30662 m_fvBndryCnd->initSmallCellRHSCorrection();
30664 m_fvBndryCnd->initSmallCellCorrection();
30670 if(m_writeOutData) {
30671 cerr <<
"Writing out center line data" << endl;
30672 stringstream fileNameCL;
30673 fileNameCL <<
"centerlineData";
30674 fileNameCL <<
"_" << domainId();
30675 writeCenterLineVel((fileNameCL.str()).c_str());
30679 RECORD_TIMER_STOP(t_initBnd);
30681 RECORD_TIMER_START(t_surfaces);
30682 m_log <<
"create initial surfaces...";
30683 createInitialSrfcs();
30684 m_initialSurfacesOffset = a_noSurfaces();
30685 m_log <<
"ok" << endl;
30686 RECORD_TIMER_STOP(t_surfaces);
30688 RECORD_TIMER_START(t_stencil);
30689 setOuterBoundaryGhostCells();
30690 setOuterBoundarySurfaces();
30691 m_noOuterBoundarySurfaces = m_fvBndryCnd->m_noBoundarySurfaces;
30693 m_log <<
"Tagging cells needed for the surface flux computation...";
30694 tagCellsNeededForSurfaceFlux();
30695 m_log <<
"ok" << endl;
30700 IF_CONSTEXPR(nDim == 2) {
30701 m_log <<
"Setting upwind coefficient...";
30702 setUpwindCoefficient();
30703 m_log <<
"ok" << endl;
30706 m_log <<
"Computing plane vectors...";
30707 m_fvBndryCnd->computePlaneVectors();
30708 m_log <<
"ok" << endl;
30710 setCellProperties();
30711 if(m_useCentralDifferencingSlopes) {
30712 determineStructuredCells();
30715 m_log <<
"Initializing the least-squares reconstruction...";
30717 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30718 a_hasProperty(cellId, SolverCell::IsActive) =
true;
30720 if(m_fvBndryCnd->m_cellMerging) {
30723 buildLeastSquaresStencilSimple();
30727 m_log <<
"ok" << endl;
30730 IF_CONSTEXPR(nDim == 3) {
30731 if(m_extractedCells !=
nullptr) {
30732 delete m_extractedCells;
30733 m_extractedCells =
nullptr;
30734 }
else if(m_gridPoints !=
nullptr) {
30735 delete m_gridPoints;
30736 m_gridPoints =
nullptr;
30740 m_log <<
"Initializing the viscous flux computation...";
30741 initViscousFluxComputation();
30742 m_log <<
"ok" << endl;
30745 if(m_fvBndryCnd->m_cellMerging) {
30746 m_log <<
"Initializing boundary conditions...";
30748 m_fvBndryCnd->initBndryCnds();
30751 m_log <<
"ok" << endl;
30753 m_fvBndryCnd->setBCTypes();
30763 m_log <<
"Computing reconstruction constants...";
30765 computeReconstructionConstants();
30766 m_log <<
"ok" << endl;
30767 RECORD_TIMER_STOP(t_stencil);
30769 if(grid().azimuthalPeriodicity()) {
30770 initAzimuthalReconstruction();
30771 computeAzimuthalReconstructionConstants();
30773 m_azimuthalWasNearBndryIds.clear();
30774 m_azimuthalWasNearBndryIds.assign(noWindows, -1);
30775 if(mode == 1) cutOffBoundaryCondition();
30777 RECORD_TIMER_START(t_initSurfaces);
30778 initializeMaxLevelExchange();
30780#if defined _MB_DEBUG_ || !defined NDEBUG
30786 if(grid().azimuthalPeriodicity()) {
30788 for(
MInt cellId = 0; cellId < noInternalCells(); cellId++) {
30790 for(
MInt v = 0; v < PV->noVariables; v++) {
30791 if(!(a_pvariable(cellId, v) >= F0 || a_pvariable(cellId, v) < F0) || std::isnan(a_pvariable(cellId, v))) {
30792 if(a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel)) {
30793 mTerm(1,
"This should only occur for non-leaf cells!");
30795 a_pvariable(cellId, v) = F0;
30805 computeCellSurfaceDistanceVectors();
30808 m_bndryCandidateIds.clear();
30809 for(
MInt i = 0; i < m_bndryGhostCellsOffset; i++) {
30810 m_bndryCandidateIds.push_back(-1);
30812 m_bndryCandidates.clear();
30813 m_noBndryCandidates = 0;
30815 MBool found =
false;
30816 for(
MInt bc = 0; bc < m_fvBndryCnd->m_noBndryCndIds; bc++) {
30817 if(m_fvBndryCnd->m_bndryCndIds[bc] == m_movingBndryCndId) found =
true;
30820 m_fvBndryCnd->m_bndryCndIds[m_fvBndryCnd->m_noBndryCndIds] = m_movingBndryCndId;
30821 m_fvBndryCnd->m_noBndryCndIds++;
30822 m_vtuGeometryOutput.insert(m_movingBndryCndId);
30823 m_log <<
"Added moving boundary condition " << m_movingBndryCndId << endl;
30825 m_fvBndryCnd->createBndryCndHandler();
30827 for(
MInt i = 0; i < a_noCells(); i++) {
30828 a_hasProperty(i, SolverCell::NearWall) =
false;
30832 IF_CONSTEXPR(nDim == 2) {
30833 m_fvBndryCnd->recorrectCellCoordinates();
30834 const MFloat signStencil[4][2] = {{-F1, -F1}, {F1, -F1}, {-F1, F1}, {F1, F1}};
30836 for(
MInt bndryId = 0; bndryId < m_bndryCells->size(); bndryId++) {
30837 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
30838 for(
MInt p = 0; p < m_noCellNodes; p++) {
30839 for(
MInt i = 0; i < nDim; i++) {
30840 tmpPoint[i] = a_coordinate(cellId, i) + signStencil[p][i] * F1B2 * c_cellLengthAtLevel(a_level(cellId));
30842 m_pointIsInside[bndryId][IDX_LSSETMB(p, 0)] = m_geometry->pointIsInside(tmpPoint);
30845 m_fvBndryCnd->rerecorrectCellCoordinates();
30848 MBool& firstRun = m_static_initSolutionStep_firstRun;
30849 if(m_restart) firstRun =
true;
30851 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30852 m_cellVolumesDt1[cellId] = a_cellVolume(cellId);
30853 if(m_dualTimeStepping) m_cellVolumesDt2[cellId] = a_cellVolume(cellId);
30858 RECORD_TIMER_STOP(t_initSurfaces);
30859 RECORD_TIMER_START(t_finalize);
30862 m_log <<
"_________________________________________________________________" << endl << endl;
30863 m_log <<
"Grid summary after clean initialization:" << endl;
30864 m_log <<
"_________________________________________________________________" << endl << endl;
30865 m_log << setfill(
' ');
30866 m_log <<
"number of cells " << setw(7) << a_noCells() << endl;
30867 m_log <<
"number of surfaces " << setw(7) << a_noSurfaces() << endl;
30868 m_log <<
"number of small cells " << setw(7) << m_fvBndryCnd->m_smallBndryCells->size() << endl;
30869 m_log <<
"minimum grid level " << setw(7) << minLevel() << endl;
30870 m_log <<
"maximum grid level " << setw(7) << maxLevel() << endl << endl;
30871 m_log <<
"level | total no cells | no of leaf cells | ghost cells" << endl;
30873 MInt total = 0, leaf = 0, ghost = 0;
30874 for(
MInt level = maxLevel(); level >= minLevel(); level--) {
30878 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
30879 if(a_isBndryGhostCell(cellId)) {
30880 if(a_level(cellId) == level) {
30885 }
else if(a_level(cellId) == level) {
30887 if(c_isLeafCell(cellId)) {
30892 m_log << setfill(
' ');
30893 m_log << setw(3) << level <<
" " << setw(12) << total <<
" " << setw(16) << leaf <<
" " << setw(14) << ghost
30898 MInt noCells = noInternalCells();
30899 MFloat cellLength = NAN;
30900 MFloat maxC[3] = {-10000.0, -10000.0, -10000.0};
30901 MFloat minC[3] = {10000.0, 10000.0, 10000.0};
30902 for(
MInt c = 0; c < noCells; c++) {
30903 if(!a_hasProperty(c, SolverCell::IsOnCurrentMGLevel))
continue;
30904 if(a_isHalo(c))
continue;
30905 if(a_isPeriodic(c))
continue;
30906 cellLength = c_cellLengthAtCell(c);
30907 for(
MInt i = 0; i < nDim; i++) {
30908 maxC[i] =
mMax(maxC[i], a_coordinate(c, i) + F1B2 * cellLength);
30909 minC[i] =
mMin(minC[i], a_coordinate(c, i) - F1B2 * cellLength);
30912 m_log <<
"_________________________________________________________________" << endl << endl;
30914 m_log <<
"Physical domain boundaries: " << endl;
30915 m_log <<
"min (x,y" << (nDim == 3 ?
",z): (" :
"): (") << minC[0] <<
"," << minC[1];
30916 IF_CONSTEXPR(nDim == 3)
m_log <<
"," << minC[2];
30917 m_log <<
")" << endl;
30918 m_log <<
"max (x,y" << (nDim == 3 ?
",z): (" :
"): (") << maxC[0] <<
"," << maxC[1];
30919 IF_CONSTEXPR(nDim == 3)
m_log <<
"," << maxC[2];
30920 m_log <<
")" << endl;
30922 m_log <<
"_________________________________________________________________" << endl << endl;
30925 m_log <<
"Process " << domainId() <<
" finished FV-MB initialization at time step " <<
globalTimeStep << endl;
30927 if(domainId() == 0 || domainId() == noDomains() - 1)
30928 cerr <<
"Process " << domainId() <<
" finished FV-MB initialization at time step " <<
globalTimeStep << endl;
30930 m_log << endl << endl;
30932 RECORD_TIMER_STOP(t_finalize);
30933 RECORD_TIMER_STOP(t_timertotal);
30934 DISPLAY_TIMER(t_timertotal);
30942template <MInt nDim,
class SysEqn>
30946 const MInt noSrfcs = a_noSurfaces();
30947 const MInt surfaceVarMemory = m_surfaceVarMemory;
30948 const MInt slopeMemory = m_slopeMemory;
30949 auto* surfaceVar = (
MFloat*)(&(a_surfaceVariable(0, 0, 0)));
30950 auto* cellSlopes = (
MFloat*)(&(a_slope(0, 0, 0)));
30951 auto* dx = (
MFloat*)(&(a_surfaceDeltaX(0, 0)));
30958 MInt va0 = surfaceVarMemory * noSrfcs;
30959 MInt va1 = va0 + m_noPVars;
30960 MInt i = 2 * nDim * noSrfcs;
30961 for(
MInt srfcId = noSrfcs; srfcId--;) {
30962 va0 -= surfaceVarMemory;
30963 va1 -= surfaceVarMemory;
30967 MInt nghbr0 = a_surfaceNghbrCellId(srfcId, 0);
30968 MInt nghbr1 = a_surfaceNghbrCellId(srfcId, 1);
30970 MInt sl0 = nghbr0 * slopeMemory;
30971 MInt sl1 = nghbr1 * slopeMemory;
30973 for(
MInt varId = 0; varId < m_noPVars; varId++) {
30975#ifdef _MINMOD_LIMITER_
30976 IF_CONSTEXPR(nDim == 2) {
30977 mTerm(1,
"This part has never been used in 2D. If you know it is working properly remove this!");
30985 if(a_surfaceBndryCndId(srfcId) < 0) {
30986 for(
MInt dir = 0; dir < m_noDirs; dir++) {
30987 if(a_hasNeighbor(nghbr0, dir) > 0) {
30988 MInt nghbrId = c_neighborId(nghbr0, dir);
30989 if(!a_hasProperty(nghbrId, SolverCell::IsOnCurrentMGLevel))
continue;
30991 vmax0 =
mMax(vmax0, a_pvariable(nghbrId, varId));
30993 if(a_hasNeighbor(nghbr1, dir) > 0) {
30994 MInt nghbrId = c_neighborId(nghbr1, dir);
30995 if(!a_hasProperty(nghbrId, SolverCell::IsOnCurrentMGLevel))
continue;
30996 vmin1 =
mMin(vmin1, a_pvariable(nghbrId, varId));
30997 vmax1 =
mMax(vmax1, a_pvariable(nghbrId, varId));
31000 for(
MInt dir = 0; dir < m_noDirs; dir++) {
31001 if(a_hasNeighbor(nghbr0, dir) > 0) {
31002 MInt nghbrId = c_neighborId(nghbr0, dir);
31003 if(!a_hasProperty(nghbrId, SolverCell::IsOnCurrentMGLevel))
continue;
31005 for(
MInt j = 0; j < nDim; j++) {
31006 dv += (a_coordinate(nghbrId, j) - a_coordinate(nghbr0, j)) * a_slope(nghbr0, varId, j);
31008 if(a_pvariable(nghbr0, varId) + dv < vmin0 || a_pvariable(nghbr0, varId) + dv > vmax0) {
31009 phi0 =
mMin(phi0,
mMax(F0, (a_pvariable(nghbrId, varId) - a_pvariable(nghbr0, varId)) / dv));
31012 if(a_hasNeighbor(nghbr1, dir) > 0) {
31013 MInt nghbrId = c_neighborId(nghbr1, dir);
31014 if(!a_hasProperty(nghbrId, SolverCell::IsOnCurrentMGLevel))
continue;
31016 for(
MInt j = 0; j < nDim; j++) {
31017 dv += (a_coordinate(nghbrId, j) - a_coordinate(nghbr1, j)) * a_slope(nghbr1, varId, j);
31019 if(a_pvariable(nghbr1, varId) + dv < vmin1 || a_pvariable(nghbr1, varId) + dv > vmax1) {
31020 phi1 =
mMin(phi1,
mMax(F0, (a_pvariable(nghbrId, varId) - a_pvariable(nghbr1, varId)) / dv));
31025 surfaceVar[va0 + varId] = a_pvariable(nghbr0, varId);
31026 surfaceVar[va0 + varId] += phi0 * std::inner_product(&cellSlopes[sl0], &cellSlopes[sl0] + nDim, &dx[i], 0);
31027 surfaceVar[va1 + varId] = a_pvariable(nghbr1, varId);
31028 surfaceVar[va1 + varId] +=
31029 phi1 * std::inner_product(&cellSlopes[sl1], &cellSlopes[sl1] + nDim, &dx[i + nDim], 0);
31032 surfaceVar[va0 + varId] =
31033 std::inner_product(&cellSlopes[sl0], &cellSlopes[sl0] + nDim, &dx[i], a_pvariable(nghbr0, varId));
31034 surfaceVar[va1 + varId] =
31035 std::inner_product(&cellSlopes[sl1], &cellSlopes[sl1] + nDim, &dx[i + nDim], a_pvariable(nghbr1, varId));
31039 if(blk > -1 && domainId() == blk && srfcId == sfc) {
31040 cerr <<
"svalues @" <<
globalTimeStep <<
"/" << m_RKStep <<
" /s " << srfcId <<
" /n " << nghbr0 <<
" "
31041 << nghbr1 <<
" /var " << varId <<
" " << surfaceVar[va0 + varId] <<
" " << surfaceVar[va1 + varId]
31042 <<
" /cvar " << a_pvariable(nghbr0, varId) <<
" " << a_pvariable(nghbr1, varId) <<
" /sl0 "
31043 << cellSlopes[sl0] <<
" " << cellSlopes[sl0 + 1] <<
" " << cellSlopes[sl0 + 2] <<
" /sl1 "
31044 << cellSlopes[sl1] <<
" " << cellSlopes[sl1 + 1] <<
" " << cellSlopes[sl1 + 2] <<
" /dx0 " << dx[i]
31045 <<
" " << dx[i + 1] <<
" " << dx[i + 2] <<
" /dx1 " << dx[i + 3] <<
" " << dx[i + 4] <<
" " << dx[i + 5]
31054 if((surfaceVar[va0 + PV->P] < F0) || (surfaceVar[va1 + PV->P] < F0)) {
31055 m_log <<
globalTimeStep <<
"/" << m_RKStep <<
" negative pressure: " << srfcId <<
" " << nghbr0 <<
" " << nghbr1
31056 <<
" / " << surfaceVar[va0 + PV->P] <<
" " << surfaceVar[va1 + PV->P] <<
" " << a_pvariable(nghbr0, PV->P)
31057 <<
" " << a_pvariable(nghbr1, PV->P) <<
" / " << a_isHalo(nghbr0) <<
" " << a_isHalo(nghbr1) <<
" / "
31058 << a_level(nghbr0) <<
" " << a_level(nghbr1) << endl;
31059 const MInt offset0 = nDim * m_cells.noRecNghbrs() * nghbr0;
31060 for(
MInt n = a_noReconstructionNeighbors(nghbr0); n--;) {
31061 m_log << srfcId <<
" recvals0: " << n <<
":" << a_reconstructionNeighborId(nghbr0, n) <<
"("
31062 << m_reconstructionConstants[offset0 + n * nDim + 0] <<
"/"
31063 << m_reconstructionConstants[offset0 + n * nDim + 1] <<
"/"
31064 << m_reconstructionConstants[offset0 + n * nDim + 2] <<
"#"
31065 << a_pvariable(a_reconstructionNeighborId(nghbr0, n), PV->P) <<
"="
31066 << a_isHalo(a_reconstructionNeighborId(nghbr0, n)) <<
") " << endl;
31068 const MInt offset1 = nDim * m_cells.noRecNghbrs() * nghbr1;
31069 for(
MInt n = a_noReconstructionNeighbors(nghbr1); n--;) {
31070 m_log << srfcId <<
" recvals1: " << n <<
":" << a_reconstructionNeighborId(nghbr1, n) <<
"("
31071 << m_reconstructionConstants[offset1 + n * nDim + 0] <<
"/"
31072 << m_reconstructionConstants[offset1 + n * nDim + 1] <<
"/"
31073 << m_reconstructionConstants[offset1 + n * nDim + 2] <<
"#"
31074 << a_pvariable(a_reconstructionNeighborId(nghbr1, n), PV->P) <<
"="
31075 << a_isHalo(a_reconstructionNeighborId(nghbr1, n)) <<
") " << endl;
31082 IF_CONSTEXPR(nDim == 3) {
31083 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
31084 for(
MInt srfc = 0; srfc < m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
31085 for(
MInt k = 0; k < nDim; k++) {
31086 MInt srfcId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcVariables[srfc]->m_srfcId[k];
31087 if(srfcId < 0)
continue;
31088 for(
MInt var = 0; var < m_noPVars; var++) {
31089 a_surfaceVariable(srfcId, 0, var) =
31090 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[var];
31091 a_surfaceVariable(srfcId, 1, var) =
31092 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[var];
31105template <MInt nDim,
class SysEqn>
31109 const MInt noSrfcs = a_noSurfaces();
31110 const MInt surfaceVarMemory = m_surfaceVarMemory;
31111 const MInt slopeMemory = m_slopeMemory;
31112 const MFloat eps = 1e-10 * m_rhoInfinity;
31113 auto* surfaceVar = (
MFloat*)(&(a_surfaceVariable(0, 0, 0)));
31114 auto* cellSlopes = (
MFloat*)(&(a_slope(0, 0, 0)));
31115 auto* dx = (
MFloat*)(&(a_surfaceDeltaX(0, 0)));
31119 for(
MInt j = 0; j < m_noSlopes; j++) {
31120 phi.p[
cellId * m_noSlopes + j] = F0;
31124 if(a_hasProperty(cellId, SolverCell::IsNotGradient))
continue;
31125 if(a_hasProperty(cellId, SolverCell::IsInactive))
continue;
31126 if(a_bndryId(cellId) < -1)
continue;
31128 for(
MInt j = 0; j < nDim; j++) {
31129 if((!checkNeighborActive(cellId, 2 * j) || a_hasNeighbor(cellId, 2 * j) == 0)
31130 || (!checkNeighborActive(cellId, 2 * j + 1) || a_hasNeighbor(cellId, 2 * j + 1) == 0))
31132 MInt n0 = c_neighborId(cellId, 2 * j);
31133 MInt n1 = c_neighborId(cellId, 2 * j + 1);
31134 ASSERT(n0 > -1 && n1 > -1 && n0 < a_noCells() && n1 < a_noCells(),
"");
31135 for(
MInt v = 0; v < m_noPVars; v++) {
31137 (a_pvariable(n1, v) - a_pvariable(cellId, v)) / (a_pvariable(cellId, v) - a_pvariable(n0, v) + m_eps);
31138 phi.p[
cellId * m_noSlopes + v * nDim + j] =
mMax(F0,
mMin(F1, f));
31162 MInt va0 = surfaceVarMemory * noSrfcs;
31163 MInt va1 = va0 + m_noPVars;
31164 MInt i = 2 * nDim * noSrfcs;
31165 for(
MInt srfcId = noSrfcs; srfcId--;) {
31166 va0 -= surfaceVarMemory;
31167 va1 -= surfaceVarMemory;
31172 MInt nghbr0 = a_surfaceNghbrCellId(srfcId, 0);
31173 MInt nghbr1 = a_surfaceNghbrCellId(srfcId, 1);
31175 MInt sl0 = nghbr0 * slopeMemory;
31176 MInt sl1 = nghbr1 * slopeMemory;
31178 for(
MInt varId = 0; varId < m_noPVars; varId++) {
31179 surfaceVar[va0 + varId] = a_pvariable(nghbr0, varId);
31180 for(
MInt dim = 0; dim < nDim; ++dim)
31181 surfaceVar[va0 + varId] +=
31182 phi.p[m_noSlopes * nghbr0 + nDim * varId + dim] * cellSlopes[sl0 + dim] * dx[i + dim];
31184 surfaceVar[va1 + varId] = a_pvariable(nghbr1, varId);
31185 for(
MInt dim = 0; dim < nDim; ++dim)
31186 surfaceVar[va1 + varId] +=
31187 phi.p[m_noSlopes * nghbr1 + nDim * varId + dim] * cellSlopes[sl1 + dim] * dx[i + nDim + dim];
31192 surfaceVar[va0 + PV->RHO] =
mMax(eps, surfaceVar[va0 + PV->RHO]);
31193 surfaceVar[va1 + PV->RHO] =
mMax(eps, surfaceVar[va1 + PV->RHO]);
31194 surfaceVar[va0 + PV->P] =
mMax(eps, surfaceVar[va0 + PV->P]);
31195 surfaceVar[va1 + PV->P] =
mMax(eps, surfaceVar[va1 + PV->P]);
31205template <MInt nDim,
class SysEqn>
31209 for(
MInt bndryId = m_noOuterBndryCells; bndryId < m_fvBndryCnd->m_bndryCells->size(); bndryId++) {
31210 MInt cellId = m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId;
31211 for(
MInt dir = 0; dir < m_noDirs; dir++) {
31212 MInt srfcId = m_cellSurfaceMapping[cellId][dir];
31214 updateCellSurfaceDistanceVector(srfcId);
31234template <MInt nDim,
class SysEqn>
31238 const MUint noPVars = PV->noVariables;
31239 const MUint noFluxVars = FV->noVariables;
31240 const MUint surfaceVarMemory = 2 * noPVars;
31242 MFloat*
const RESTRICT fluxes = ALIGNED_MF(&a_surfaceFlux(0, 0));
31243 const MInt noSurfaces = a_noSurfaces();
31244 const MInt noData = m_surfaceVarMemory;
31245 auto* RESTRICT surfArea = &a_surfaceArea(0);
31246 auto* RESTRICT var = (
MFloat*)(&(a_surfaceVariable(0, 0, 0)));
31248 MFloat*
const RESTRICT surfaceVars = ALIGNED_F(&a_surfaceVariable(0, 0, 0));
31252 if(m_centralizeSurfaceVariables > 0) {
31253 for(
MInt srfcId = 0; srfcId < noSurfaces; srfcId++) {
31254 const MInt orientation = a_surfaceOrientation(srfcId);
31255 const MUint offset = srfcId * surfaceVarMemory;
31256 MFloat*
const RESTRICT leftVars = ALIGNED_F(surfaceVars + offset);
31257 MFloat*
const RESTRICT rightVars = ALIGNED_F(leftVars + noPVars);
31259 MInt levelFac = -1;
31260 if(m_centralizeSurfaceVariables == 5) {
31261 const MInt nghbr0 = a_surfaceNghbrCellId(srfcId, 0);
31262 const MInt nghbr1 = a_surfaceNghbrCellId(srfcId, 1);
31263 const MInt level =
mMax(a_level(nghbr0), a_level(nghbr1));
31264 levelFac = (
MFloat)((maxRefinementLevel() - level) / (maxRefinementLevel() - maxUniformRefinementLevel()));
31266 switch(m_centralizeSurfaceVariables) {
31268 sysEqn().template centralizeSurfaceVariables<1>(leftVars, rightVars, orientation, levelFac);
31272 sysEqn().template centralizeSurfaceVariables<2>(leftVars, rightVars, orientation, levelFac);
31276 sysEqn().template centralizeSurfaceVariables<3>(leftVars, rightVars, orientation, levelFac);
31280 sysEqn().template centralizeSurfaceVariables<4>(leftVars, rightVars, orientation, levelFac);
31284 sysEqn().template centralizeSurfaceVariables<5>(leftVars, rightVars, orientation, levelFac);
31288 mTerm(1, AT_,
"centralizeSurfaceVariables mode not implemented!");
31296 this->m_static_computeSurfaceValuesLimitedSlopesMan_checkedBndryCndIds =
true;
31297 this->m_static_computeSurfaceValuesLimitedSlopesMan_correctWallBndryFluxes =
false;
31303 for(
MInt bs = 0; bs < m_fvBndryCnd->m_noBoundarySurfaces; bs++) {
31304 MInt srfcId = m_fvBndryCnd->m_boundarySurfaces[bs];
31305 if(a_surfaceBndryCndId(srfcId) == 3003) {
31306 const MInt offset = noData * srfcId;
31307 const MInt orientation = a_surfaceOrientation(srfcId);
31308 const MFloat area = surfArea[srfcId];
31309 const MFloat* leftVars = var + offset;
31310 const MFloat* rightVars = leftVars + noPVars;
31311 const MUint fluxOffset = srfcId * noFluxVars;
31312 MFloat*
const RESTRICT flux = fluxes + fluxOffset;
31313 sysEqn().AusmBndryCorrection(orientation, area, leftVars, rightVars, flux);
31317 applyALECorrection();
31325template <MInt nDim,
class SysEqn>
31329 for(
MInt i = 0; i < nDim; i++) {
31330 MFloat diff = a_surfaceCoordinate(srfcId1, i) - a_surfaceCoordinate(srfcId2, i);
31331 xDiff += (diff * diff);
31334 return sqrt(xDiff);
31342template <MInt nDim,
class SysEqn>
31344 return fabs(a_surfaceArea(srfcId1) - a_surfaceArea(srfcId2));
31352template <MInt nDim,
class SysEqn>
31359 (this->normal.dot((polygon->
plane.
normal)) > F0 ? coplanarFront : coplanarBack)->push_back(*polygon);
31367template <MInt nDim,
class SysEqn>
31374 const MInt COPLANAR = 0;
31375 const MInt FRONT = 1;
31376 const MInt BACK = 2;
31377 const MInt SPANNING = 3;
31379 MInt polygonType = 0;
31380 std::vector<MInt> types;
31383 MBool normalsEqual =
false;
31384 IF_CONSTEXPR(
nDim == 3) {
31385 if(abs(abs(this->normal.xx[0]) - abs(polygon->
plane.
normal.
xx[0])) < MFloatEps
31386 && abs(abs(this->normal.xx[1]) - abs(polygon->
plane.
normal.
xx[1])) < MFloatEps
31387 && abs(abs(this->normal.xx[2]) - abs(polygon->
plane.
normal.
xx[2])) < MFloatEps)
31388 normalsEqual =
true;
31391 MBool coplanarVertex =
false;
31392 for(
MInt i = 0; (unsigned)i < polygon->vertices.size(); i++) {
31393 MFloat t = this->normal.dot((polygon->
vertices[i].pos)) - this->w;
31394 MInt type = (t < -
eps) ? BACK : (t >
eps) ? FRONT : COPLANAR;
31395 polygonType |= type;
31396 types.push_back(type);
31397 IF_CONSTEXPR(
nDim == 3) {
31398 if(type == 0) coplanarVertex =
true;
31404 if(normalsEqual && coplanarVertex) polygonType = COPLANAR;
31406 switch(polygonType) {
31408 (this->normal.dot((polygon->
plane.
normal)) > F0 ? coplanarFront : coplanarBack)->push_back(*polygon);
31411 front->push_back(*polygon);
31414 back->push_back(*polygon);
31417 std::vector<CsgVertex> f;
31418 std::vector<CsgVertex>
b;
31419 IF_CONSTEXPR(
nDim == 2) {
31422 MInt ti = types[i], tj = types[j];
31425 if(ti != BACK) f.push_back(vi);
31426 if(ti != FRONT)
b.push_back(ti != BACK ? vi.
clone() : vi);
31427 if((ti | tj) == SPANNING) {
31433 if(tj != BACK) f.push_back(vj);
31434 if(tj != FRONT)
b.push_back(tj != BACK ? vj.
clone() : vj);
31436 else IF_CONSTEXPR(
nDim == 3) {
31437 for(
MInt i = 0; (unsigned)i < polygon->vertices.size(); i++) {
31439 MInt ti = types[i], tj = types[j];
31442 if(ti != BACK) f.push_back(vi);
31443 if(ti != FRONT)
b.push_back(ti != BACK ? vi.
clone() : vi);
31444 if((ti | tj) == SPANNING) {
31452 if(f.size() >=
nDim)
31455 if(
b.size() >=
nDim)
31469template <MInt nDim,
class SysEqn>
31471 if(_polygons.empty())
return;
31472 MInt polygonStartIndex =
nDim == 3 ? 0 : 1;
31474 this->plane = _polygons[0].plane.clone();
31476 IF_CONSTEXPR(
nDim == 3) {
31477 this->polygons.push_back(_polygons[0]);
31478 polygonStartIndex = 1;
31481 std::vector<CsgPolygon> _front;
31482 std::vector<CsgPolygon> _back;
31483 IF_CONSTEXPR(
nDim == 2) { this->plane.insertCoplanarPolygon(&_polygons[0], &this->polygons, &this->polygons); }
31484 for(
MInt i = polygonStartIndex; (unsigned)i < _polygons.size(); i++) {
31485 this->plane.splitPolygon(&_polygons[i], &this->polygons, &this->polygons, &_front, &_back);
31487 if(_front.size() != 0u) {
31490 this->front->build(_front);
31492 if(_back.size() != 0u) {
31493 if(!this->back) this->back =
new CsgNode();
31494 this->back->build(_back);
31504template <MInt nDim,
class SysEqn>
31506 const MInt faceCornerMapping[6][4] = {{2, 6, 4, 0}, {1, 5, 7, 3}, {0, 4, 5, 1},
31507 {3, 7, 6, 2}, {2, 3, 1, 0}, {6, 7, 5, 4}};
31514 MFloat testSum = A * C - B * D;
31515 if(fabs(testSum) <
m_eps)
return true;
31516 return A * testSum >= F0;
31524template <MInt nDim,
class SysEqn>
31525template <
class _, std::enable_if_t<nDim == 2, _*>>
31527 const std::vector<polyVertex>* vertices,
MInt A,
31529 MFloat P1 = F0, Pa = F0, Pb = F0;
31531 for(
MInt i = 0; (unsigned)i < (*cutCell).faces_edges.size(); i++) {
31532 MInt edge = (*cutCell).faces_edges[i];
31533 MInt vertex0, vertex1;
31534 vertex0 = (*edges)[edge].vertices[0];
31535 vertex1 = (*edges)[edge].vertices[1];
31536 MFloat a0 = (*vertices)[vertex0].coordinates[A];
31537 MFloat b0 = (*vertices)[vertex0].coordinates[B];
31538 MFloat a1 = (*vertices)[vertex1].coordinates[A];
31539 MFloat b1 = (*vertices)[vertex1].coordinates[B];
31546 MFloat Ca = a1 * C1 + a0_2;
31547 MFloat Cb = b1 * (b1 + b0) + b0_2;
31553 (*edges)[edge].center[A] = a0 + F1B2 * da;
31554 (*edges)[edge].center[B] = b0 + F1B2 * db;
31555 (*edges)[edge].area = sqrt(da * da + db * db);
31568template <MInt nDim,
class SysEqn>
31569template <
class _, std::enable_if_t<nDim == 2, _*>>
31571 const std::vector<polyVertex>* vertices,
MInt A,
MInt B) {
31577 if(area > 1e3 *
m_eps) {
31579 cutCell->
center[A] = P[1] / area;
31580 cutCell->
center[B] = P[2] / area;
31581 }
else if(area > F0) {
31585 for(
MInt i = 0; (unsigned)i < (*cutCell).faces_edges.size(); i++) {
31586 MInt edge = (*cutCell).faces_edges[i];
31587 MInt vertex0 = (*edges)[edge].vertices[0];
31588 P[1] += (*vertices)[vertex0].coordinates[0];
31589 P[2] += (*vertices)[vertex0].coordinates[1];
31591 P[1] /= (*cutCell).faces_edges.size();
31592 P[2] /= (*cutCell).faces_edges.size();
31593 cutCell->
center[A] = P[1];
31594 cutCell->
center[B] = P[2];
31599 for(
MInt i = 0; (unsigned)i < (*cutCell).faces_edges.size(); i++) {
31600 MInt edge = (*cutCell).faces_edges[i];
31601 MInt vertex0 = (*edges)[edge].vertices[0];
31602 P[1] += (*vertices)[vertex0].coordinates[0];
31603 P[2] += (*vertices)[vertex0].coordinates[1];
31605 P[1] /= (*cutCell).faces_edges.size();
31606 P[2] /= (*cutCell).faces_edges.size();
31607 cutCell->
center[A] = P[1];
31608 cutCell->
center[B] = P[2];
31617template <MInt nDim,
class SysEqn>
31618template <
class _, std::enable_if_t<nDim == 2, _*>>
31620 std::vector<polyEdge2D>* edges,
31621 const std::vector<polyVertex>* vertices) {
31624 for(
MInt cC = 0; (unsigned)cC < cutCells->size(); cC++) {
31636template <MInt nDim,
class SysEqn>
31637template <
class _, std::enable_if_t<nDim == 3, _*>>
31643 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bndryCndId < 0) {
31644 mTerm(1, AT_,
"error in createCutFaceMb(): m_bndryCndId not set: " + to_string(bndryId));
31648 test +=
POW2(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i]);
31650 if(fabs(test - F1) > 0.1) {
31654 <<
", cell " << cellId <<
" " << bndryId <<
" " << srfc <<
" " <<
c_globalId(cellId)
31655 <<
" /p15=" <<
a_isHalo(cellId) <<
" /n "
31656 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[0] <<
" "
31657 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[1] <<
" "
31658 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[2] <<
" /a "
31659 <<
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcs[srfc]->m_area <<
" /v "
31663 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[0] <<
" "
31664 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[1] <<
" "
31665 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_coordinates[2] << endl;
31667 MFloat nablaPhi[3] = {F1, F1, F1};
31676 nablaAbs +=
POW2(nablaPhi[i]);
31678 nablaAbs = sqrt(nablaAbs);
31680 nablaPhi[i] /= nablaAbs;
31681 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i] = nablaPhi[i];
31684 cerr <<
domainId() <<
": corrected " <<
POW2(nablaAbs) <<
" /n "
31685 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[0] <<
" "
31686 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[1] <<
" "
31687 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[2] << endl;
31693 m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i] /= test;
31706template <MInt nDim,
class SysEqn>
31707template <
class _, std::enable_if_t<nDim == 2, _*>>
31713 ASSERT(debugOutput ||
true,
"");
31730 MBool writePointData =
false;
31731 writePointData = Context::getSolverProperty<MBool>(
"writePointData",
solverId(), AT_, &writePointData);
31736 MBool QThresholdOutput =
true;
31737 MBool entropyChangeOutput =
true;
31740 const MInt baseCellType = 8;
31741 const MInt polyCellType = 7;
31743 MInt cellId, ghostCellId, counter;
31746 const string dataType64 =
"Float64";
31747#ifdef DOUBLE_PRECISION_OUTPUT
31748 const string dataType =
"Float64";
31750 const string dataType =
"Float32";
31752 const string iDataType =
"Int32";
31753 const string uIDataType =
"UInt32";
31754 const string uI8DataType =
"UInt8";
31755 const string uI16DataType =
"UInt16";
31758#ifdef DOUBLE_PRECISION_OUTPUT
31766 cerr <<
"extracted";
31772 noCells = noExtractedCells;
31775 const MInt ltable[4][3] = {{2, 3}, {0, 2}, {1, 0}, {3, 1}};
31776 const MInt pointOrder[4] = {0, 1, 3, 2};
31777 const MInt dirOrder[4] = {2, 1, 3, 0};
31778 const MInt reverseDir[4] = {1, 0, 3, 2};
31790 for(
MInt c = 0; c < noExtractedCells; c++) {
31794 if(pid < 0 || pid >= noPoints) {
31796 "Error A in FvMbSolver2D::writeVtkXmlOutput(..). Quit. " + to_string(cellId) +
" " + to_string(k) +
" "
31803 cutPointIds.p[i] = -1;
31807 cerr <<
"prepare...";
31810 reverseMapping.p[c] = -1;
31812 for(
MInt c = 0; c < noExtractedCells; c++) {
31819 for(
MInt c = 0; c < noExtractedCells; c++) {
31821 cellTypes.p[c] = baseCellType;
31823 isPolyCell =
false;
31832 if(nghbrId < 0)
continue;
31835 if(reverseMapping.p[childId] < 0) {
31836 isPolyCell =
false;
31844 cellTypes.p[c] = polyCellType;
31845 polyIds.p[c] = noPolyCells;
31851 MInt eCell, nghbrId;
31852 const MInt maxNoExtraPoints = 8;
31853 const MInt maxNoPolyCells = noPolyCells;
31855 ScratchSpace<MInt> extraPoints(maxNoPolyCells * maxNoExtraPoints, AT_,
"extraPoints");
31858 MInt offset, pointCount;
31860 for(
MInt c = 0; c < noExtractedCells; c++) {
31861 if(cellTypes.p[c] == polyCellType) {
31862 polyCellLink.p[polyIds.p[c]] = c;
31868 for(
MInt pc = 0; pc < noPolyCells; pc++) {
31869 eCell = polyCellLink.p[pc];
31872 noExtraPoints.p[pc] = 0;
31878 noInternalPoints.p[pc] = 0;
31881 MInt p = pointOrder[i];
31882 MInt dir = dirOrder[i];
31886 extraPoints.p[pc * maxNoExtraPoints + noExtraPoints.p[pc]] =
m_extractedCells->
a[eCell].m_pointIds[
p];
31887 noExtraPoints.p[pc]++;
31891 for(
MInt cp = 0; cp <
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints; cp++) {
31892 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutEdge[cp] == dir) {
31893 MInt gridPointId = -1;
31897 if(gridPointId > -1) {
31903 if(gridPointId >= noPoints) {
31904 mTerm(1, AT_,
"Error 0 in FvMbSolver3D::writeVtkXmlOutput(..). Quit.");
31906 if(gridPointId < 0) {
31917 cutPointIds.p[
m_noDirs * bndryId + dir] = gridPointId;
31919 extraPoints.p[pc * maxNoExtraPoints + noExtraPoints.p[pc]] = gridPointId;
31920 noExtraPoints.p[pc]++;
31927 noInternalPoints.p[pc] = 0;
31930 MInt p = pointOrder[i];
31931 MInt dir = dirOrder[i];
31933 extraPoints.p[pc * maxNoExtraPoints + noExtraPoints.p[pc]] =
m_extractedCells->
a[eCell].m_pointIds[
p];
31934 noExtraPoints.p[pc]++;
31936 isPolyFace =
false;
31942 if(!childCode[dir][child])
continue;
31945 isPolyFace =
false;
31947 if(reverseMapping.p[childId] < 0) {
31948 isPolyFace =
false;
31958 cerr <<
"=== VTK XML ERROR LOG === " <<
domainId() << endl;
31962 cerr << endl <<
a_noCells() <<
" " <<
a_noCells() <<
" " << dir <<
" " << ltable[i][0] << endl;
31964 cerr <<
"props: " <<
a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" " <<
a_isHalo(cellId) <<
" "
31988 mTerm(1, AT_,
"Error 1 in FvMbSolver2D::writeVtkXmlOutput(..). Quit.");
31991 extraPoints.p[pc * maxNoExtraPoints + noExtraPoints.p[pc]] = centerId;
31992 noExtraPoints.p[pc]++;
31998 cerr << endl <<
cellId <<
" / ";
32002 mTerm(1, AT_,
"Error 2 in FvMbSolver2D::writeVtkXmlOutput(..). Quit.");
32010 for(
MInt c = 0; c < noExtractedCells; c++) {
32011 MInt pc = polyIds.p[c];
32013 pointCount += noInternalPoints.p[pc];
32014 pointCount += noExtraPoints.p[pc];
32020 MInt qDataSize = 2;
32021 if(QThresholdOutput) qDataSize++;
32024 for(
MInt c = 0; c < noExtractedCells; c++) {
32032 MFloat omega = F1B2 * (gradU[1][0] - gradU[0][1]);
32037 S2 +=
POW2(F1B2 * (gradU[i][j] + gradU[j][i]));
32040 MFloat Q = F1B2 * (omega2 / S2 - F1);
32041 qData(0, cellId) = Q;
32042 qData(1, cellId) = omega;
32043 if(QThresholdOutput) qData(2, cellId) = F1B2 * ((omega2 /
mMax(
m_eps, S2)) - F1);
32049 cerr <<
"gather...";
32054 for(
MInt p = 0;
p < noPoints;
p++) {
32058 points.p[3 *
p + 2] = (flt)F0;
32064 for(
MInt c = 0; c < noExtractedCells; c++) {
32065 MInt pc = polyIds.p[c];
32067 for(
MInt p = 0;
p < noExtraPoints.p[pc];
p++) {
32068 connectivity.p[counter] = (
MUint)extraPoints.p[pc * maxNoExtraPoints + p];
32078 if(counter != pointCount) {
32079 mTerm(1, AT_,
"E1");
32085 for(
MInt c = 0; c < noExtractedCells; c++) {
32086 MInt pc = polyIds.p[c];
32088 counter += noInternalPoints.p[pc] + noExtraPoints.p[pc];
32092 offsets.p[c] = (
MUint)counter;
32097 for(
MInt c = 0; c < noExtractedCells; c++) {
32098 types.p[c] = (
unsigned char)cellTypes.p[c];
32103 for(
MInt c = 0; c < noExtractedCells; c++) {
32111 for(
MInt c = 0; c < noExtractedCells; c++) {
32112 vtkGhostLevels.p[c] = (
unsigned char)0;
32115 vtkGhostLevels.p[c] = (
unsigned char)2;
32123 for(
MInt c = 0; c < noExtractedCells; c++) {
32130 for(
MInt c = 0; c < noExtractedCells; c++) {
32137 for(
MInt c = 0; c < noExtractedCells; c++) {
32143 for(
MInt c = 0; c < noExtractedCells; c++) {
32149 MInt asize = noCells;
32150 if(writePointData) {
32159 const MInt dSSize = entropyChangeOutput ? asize : 1;
32163 const MInt qtSize = QThresholdOutput ? asize : 1;
32169 if(writePointData) {
32170 for(
MInt p = 0;
p < noInternalGridPoints;
p++) {
32196 pressure.p[
p] = (flt)F0;
32197 density.p[
p] = (flt)F0;
32198 vorticity.p[
p] = (flt)F0;
32199 Qcriterion.p[
p] = (flt)F0;
32200 if(entropyChangeOutput) dS.p[
p] = (flt)F0;
32202 velocity.p[3 *
p + i] = (flt)F0;
32204 velocity.p[3 *
p + 2] = (flt)F0;
32206 rhoE.p[
p] = (flt)F0;
32207 if(QThresholdOutput) QThreshold.p[
p] = (flt)F0;
32214 vorticity.p[
p] += (flt)weights[n] * qData(1, cellId);
32216 Qcriterion.p[
p] += (flt)weights[n] * qData(0, cellId);
32219 velocity.p[3 *
p + i] += (flt)weights[n] *
a_pvariable(cellId,
PV->VV[i]);
32222 rhoE.p[
p] += (flt)weights[n] *
a_variable(cellId,
CV->RHO_E);
32223 if(QThresholdOutput) QThreshold.p[
p] += (flt)weights[n] * qData(2, cellId);
32227 for(
MInt p = noInternalGridPoints;
p < noPoints;
p++) {
32234 if(
a_hasProperty(cellId, SolverCell::IsInactive))
continue;
32246 pressure.p[
p] = (flt)F0;
32247 density.p[
p] = (flt)F0;
32248 vorticity.p[
p] = (flt)F0;
32249 Qcriterion.p[
p] = (flt)F0;
32250 if(entropyChangeOutput) dS.p[
p] = (flt)F0;
32252 velocity.p[3 *
p + i] = (flt)F0;
32254 velocity.p[3 *
p + 2] = F0;
32256 rhoE.p[
p] = (flt)F0;
32257 if(QThresholdOutput) QThreshold.p[
p] = (flt)F0;
32261 if(
a_hasProperty(cellId, SolverCell::IsInactive))
continue;
32267 pressure.p[
p] += (flt)weights[n] * pb;
32268 density.p[
p] += (flt)weights[n] * rhob;
32269 vorticity.p[
p] += (flt)weights[n] * qData(1, cellId);
32270 Qcriterion.p[
p] += (flt)weights[n] * qData(0, cellId);
32274 velocity.p[3 *
p + i] +=
32278 rhoE.p[
p] += (flt)weights[n] *
a_variable(cellId,
CV->RHO_E);
32279 if(QThresholdOutput) QThreshold.p[
p] += (flt)weights[n] * qData(2, cellId);
32283 pressure.p[
p] += (flt)weights[n] *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->P];
32284 density.p[p] += (flt)weights[n] *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->RHO];
32285 vorticity.p[
p] += (flt)weights[n] * qData(1, cellId);
32286 Qcriterion.p[
p] += (flt)weights[n] * qData(0, cellId);
32288 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->RHO]);
32291 velocity.p[3 *
p + i] +=
32292 (flt)weights[n] *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->VV[i]];
32295 rhoE.p[
p] += (flt)weights[n] *
a_variable(cellId,
CV->RHO_E);
32296 if(QThresholdOutput) QThreshold.p[
p] += (flt)weights[n] * qData(2, cellId);
32302 for(
MInt c = 0; c < noExtractedCells; c++) {
32306 vorticity.p[c] = (flt)qData(1, cellId);
32307 Qcriterion.p[c] = (flt)qData(0, cellId);
32310 velocity.p[3 * c + i] = (flt)
a_pvariable(cellId,
PV->VV[i]);
32312 velocity.p[3 * c + 2] = (flt)F0;
32315 if(QThresholdOutput) QThreshold.p[c] = (flt)qData(2, cellId);
32322 cerr <<
"write...";
32326 ofl.open(fileName.c_str(), ios_base::out | ios_base::trunc);
32327 if(ofl.is_open() && ofl.good()) {
32331 ofl <<
"<?xml version=\"1.0\"?>" << endl;
32332 ofl <<
"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
32333 ofl <<
"<UnstructuredGrid>" << endl;
32337 ofl <<
"<FieldData>" << endl;
32338 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"time\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32339 <<
m_time <<
"\" RangeMax=\"" <<
m_time <<
"\">" << endl;
32341 ofl <<
"</DataArray>" << endl;
32342 ofl <<
"<DataArray type=\"" << dataType
32343 <<
"\" Name=\"physicalTime\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\"" <<
m_physicalTime
32346 ofl <<
"</DataArray>" << endl;
32347 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"timeStep\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32350 ofl <<
"</DataArray>" << endl;
32351 ofl <<
"<DataArray type=\"" << iDataType
32352 <<
"\" Name=\"globalTimeStep\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\"" <<
globalTimeStep
32355 ofl <<
"</DataArray>" << endl;
32356 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Ma\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32357 <<
m_Ma <<
"\" RangeMax=\"" <<
m_Ma <<
"\">" << endl;
32358 ofl <<
m_Ma << endl;
32359 ofl <<
"</DataArray>" << endl;
32360 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Re\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32361 <<
m_Re <<
"\" RangeMax=\"" <<
m_Re <<
"\">" << endl;
32362 ofl <<
m_Re << endl;
32363 ofl <<
"</DataArray>" << endl;
32364 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Pr\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32365 <<
m_Pr <<
"\" RangeMax=\"" <<
m_Pr <<
"\">" << endl;
32366 ofl <<
m_Pr << endl;
32367 ofl <<
"</DataArray>" << endl;
32368 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"gamma\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32371 ofl <<
"</DataArray>" << endl;
32372 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"CFL\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32373 <<
m_cfl <<
"\" RangeMax=\"" <<
m_cfl <<
"\">" << endl;
32374 ofl <<
m_cfl << endl;
32375 ofl <<
"</DataArray>" << endl;
32376 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"uInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32379 ofl <<
"</DataArray>" << endl;
32380 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"vInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32383 ofl <<
"</DataArray>" << endl;
32384 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"pInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32387 ofl <<
"</DataArray>" << endl;
32388 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"rhoInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
32391 ofl <<
"</DataArray>" << endl;
32392 ofl <<
"</FieldData>" << endl;
32395 ofl <<
"<Piece NumberOfPoints=\"" << noPoints <<
"\" NumberOfCells=\"" << noCells <<
"\">" << endl;
32398 ofl <<
"<Points>" << endl;
32399 ofl <<
"<DataArray type=\"" << dataType <<
"\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
32401 offset += points.m_memsize +
sizeof(
MUint);
32402 ofl <<
"</Points>" << endl;
32405 ofl <<
"<Cells>" << endl;
32406 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
32408 offset += connectivity.m_memsize +
sizeof(
MUint);
32410 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"offsets\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32412 offset += offsets.m_memsize +
sizeof(
MUint);
32414 ofl <<
"<DataArray type=\"" << uI8DataType <<
"\" Name=\"types\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32416 offset += types.m_memsize +
sizeof(
MUint);
32418 ofl <<
"</Cells>" << endl;
32421 ofl <<
"<CellData Scalars=\"scalars\">" << endl;
32423 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"cellIds\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32425 offset += cellIds.m_memsize +
sizeof(
MUint);
32428 ofl <<
"<DataArray type=\"" << uI8DataType <<
"\" Name=\"vtkGhostLevels\" format=\"appended\" offset=\"" << offset
32430 offset += vtkGhostLevels.m_memsize +
sizeof(
MUint);
32435 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"bndryIds\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32437 offset += bndryIds.m_memsize +
sizeof(
MUint);
32439 ofl <<
"<DataArray type=\"" << dataType64 <<
"\" Name=\"drho_dt\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32441 offset += drho_dt.m_memsize +
sizeof(
MUint);
32443 ofl <<
"<DataArray type=\"" << dataType64 <<
"\" Name=\"drhou_dt\" format=\"appended\" offset=\"" << offset
32445 offset += drhou_dt.m_memsize +
sizeof(
MUint);
32447 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"levelSetFunction\" format=\"appended\" offset=\"" << offset
32449 offset += levelSetFunction.m_memsize +
sizeof(
MUint);
32452 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"tauC\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32454 offset += tauC.m_memsize +
sizeof(
MUint);
32455 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"tauE\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32457 offset += tauE.m_memsize +
sizeof(
MUint);
32462 if(writePointData) {
32463 ofl <<
"</CellData>" << endl;
32464 ofl <<
"<PointData Scalars=\"scalars\">" << endl;
32467 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"pressure\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32469 offset += pressure.m_memsize +
sizeof(
MUint);
32471 ofl <<
"<DataArray type=\"" << dataType
32472 <<
"\" Name=\"velocity\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset <<
"\"/>" << endl;
32473 offset += velocity.m_memsize +
sizeof(
MUint);
32475 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"density\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32477 offset += density.m_memsize +
sizeof(
MUint);
32479 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"vorticity\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32481 offset += vorticity.m_memsize +
sizeof(
MUint);
32483 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Qcriterion\" format=\"appended\" offset=\"" << offset
32485 offset += Qcriterion.m_memsize +
sizeof(
MUint);
32487 if(entropyChangeOutput) {
32488 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"dS\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32490 offset += dS.m_memsize +
sizeof(
MUint);
32495 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"rhoE\" format=\"appended\" offset=\"" << offset <<
"\"/>"
32497 offset += rhoE.m_memsize +
sizeof(
MUint);
32499 if(QThresholdOutput) {
32500 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"QThreshold\" format=\"appended\" offset=\"" << offset
32502 offset += QThreshold.m_memsize +
sizeof(
MUint);
32506 if(writePointData) {
32507 ofl <<
"</PointData>" << endl;
32509 ofl <<
"</CellData>" << endl;
32512 ofl <<
"</Piece>" << endl;
32513 ofl <<
"</UnstructuredGrid>" << endl;
32517 ofl <<
"<AppendedData encoding=\"raw\">" << endl;
32522 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (1)" << endl;
32524 ofl.open(fileName.c_str(), ios_base::out | ios_base::app | ios_base::binary);
32525 if(ofl.is_open() && ofl.good()) {
32527 uinumber = (
MUint)points.m_memsize;
32528 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(
MUint));
32529 ofl.write(
reinterpret_cast<const char*
>(points.getPointer()), uinumber);
32532 uinumber = (
MUint)connectivity.m_memsize;
32533 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(
MUint));
32534 ofl.write(
reinterpret_cast<const char*
>(connectivity.getPointer()), uinumber);
32537 uinumber = (
MUint)offsets.m_memsize;
32538 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32539 ofl.write(
reinterpret_cast<const char*
>(offsets.getPointer()), uinumber);
32542 uinumber = (
MUint)types.m_memsize;
32543 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32544 ofl.write(
reinterpret_cast<const char*
>(types.getPointer()), uinumber);
32547 uinumber = (
MUint)cellIds.m_memsize;
32548 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32549 ofl.write(
reinterpret_cast<const char*
>(cellIds.getPointer()), uinumber);
32553 uinumber = (
MUint)vtkGhostLevels.m_memsize;
32554 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32555 ofl.write(
reinterpret_cast<const char*
>(vtkGhostLevels.getPointer()), uinumber);
32561 uinumber = (
MUint)bndryIds.m_memsize;
32562 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32563 ofl.write(
reinterpret_cast<const char*
>(bndryIds.getPointer()), uinumber);
32566 uinumber = (
MUint)drho_dt.m_memsize;
32567 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32568 ofl.write(
reinterpret_cast<const char*
>(drho_dt.getPointer()), uinumber);
32571 uinumber = (
MUint)drhou_dt.m_memsize;
32572 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32573 ofl.write(
reinterpret_cast<const char*
>(drhou_dt.getPointer()), uinumber);
32576 uinumber = (
MUint)levelSetFunction.m_memsize;
32577 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32578 ofl.write(
reinterpret_cast<const char*
>(levelSetFunction.getPointer()), uinumber);
32582 uinumber = (
MUint)tauC.m_memsize;
32583 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32584 ofl.write(
reinterpret_cast<const char*
>(tauC.getPointer()), uinumber);
32585 uinumber = (
MUint)tauE.m_memsize;
32586 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32587 ofl.write(
reinterpret_cast<const char*
>(tauE.getPointer()), uinumber);
32593 uinumber = (
MUint)pressure.m_memsize;
32594 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32595 ofl.write(
reinterpret_cast<const char*
>(pressure.getPointer()), uinumber);
32598 uinumber = (
MUint)velocity.m_memsize;
32599 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32600 ofl.write(
reinterpret_cast<const char*
>(velocity.getPointer()), uinumber);
32603 uinumber = (
MUint)density.m_memsize;
32604 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32605 ofl.write(
reinterpret_cast<const char*
>(density.getPointer()), uinumber);
32608 uinumber = (
MUint)vorticity.m_memsize;
32609 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32610 ofl.write(
reinterpret_cast<const char*
>(vorticity.getPointer()), uinumber);
32613 uinumber = (
MUint)Qcriterion.m_memsize;
32614 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32615 ofl.write(
reinterpret_cast<const char*
>(Qcriterion.getPointer()), uinumber);
32617 if(entropyChangeOutput) {
32619 uinumber = (
MUint)dS.m_memsize;
32620 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32621 ofl.write(
reinterpret_cast<const char*
>(dS.getPointer()), uinumber);
32626 uinumber = (
MUint)rhoE.m_memsize;
32627 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32628 ofl.write(
reinterpret_cast<const char*
>(rhoE.getPointer()), uinumber);
32630 if(QThresholdOutput) {
32632 uinumber = (
MUint)QThreshold.m_memsize;
32633 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
32634 ofl.write(
reinterpret_cast<const char*
>(QThreshold.getPointer()), uinumber);
32642 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (2)" << endl;
32645 ofl.open(fileName.c_str(), ios_base::out | ios_base::app);
32646 if(ofl.is_open() && ofl.good()) {
32648 ofl <<
"</AppendedData>" << endl;
32650 ofl <<
"</VTKFile>" << endl;
32654 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (3)" << endl;
32663template <MInt nDim,
class SysEqn>
32664template <
class _, std::enable_if_t<nDim == 3, _*>>
32672template <MInt nDim,
class SysEqn>
32673template <
class _, std::enable_if_t<nDim == 2, _*>>
32680 MBool writePointData =
false;
32681 writePointData = Context::getSolverProperty<MBool>(
"writePointData",
solverId(), AT_, &writePointData);
32686 MBool QThresholdOutput =
true;
32687 MBool entropyChangeOutput =
true;
32689 const MInt baseCellType = 8;
32690 const MInt polyCellType = 7;
32691 MInt cellId, ghostCellId, counter;
32693 const string dataType64 =
"Float64";
32694#ifdef DOUBLE_PRECISION_OUTPUT
32695 const string dataType =
"Float64";
32697 const string dataType =
"Float32";
32699 const string iDataType =
"Int32";
32700 const string uIDataType =
"UInt32";
32701 const string uI8DataType =
"UInt8";
32702 const string uI16DataType =
"UInt16";
32705#ifdef DOUBLE_PRECISION_OUTPUT
32714 cerr <<
"extracted";
32720 noCells = noExtractedCells;
32723 const MInt ltable[4][3] = {{2, 3}, {0, 2}, {1, 0}, {3, 1}};
32724 const MInt pointOrder[4] = {0, 1, 3, 2};
32725 const MInt dirOrder[4] = {2, 1, 3, 0};
32726 const MInt reverseDir[4] = {1, 0, 3, 2};
32738 for(
MInt c = 0; c < noExtractedCells; c++) {
32742 if(pid < 0 || pid >= noPoints) {
32744 "Error A in FvMbSolver2D::writeVtkXmlOutput_MGC(..). Quit. " + to_string(cellId) +
" " + to_string(k)
32745 +
" " + to_string(pid));
32751 cutPointIds.
p[i] = -1;
32755 cerr <<
"prepare...";
32758 reverseMapping.
p[c] = -1;
32760 for(
MInt c = 0; c < noExtractedCells; c++) {
32767 for(
MInt c = 0; c < noExtractedCells; c++) {
32769 cellTypes.
p[c] = baseCellType;
32771 isPolyCell =
false;
32780 if(nghbrId < 0)
continue;
32783 if(reverseMapping.
p[childId] < 0) {
32784 isPolyCell =
false;
32792 cellTypes.
p[c] = polyCellType;
32793 polyIds.
p[c] = noPolyCells;
32799 MInt eCell, nghbrId;
32800 const MInt maxNoExtraPoints = 8;
32801 const MInt maxNoPolyCells = noPolyCells;
32803 ScratchSpace<MInt> extraPoints(maxNoPolyCells * maxNoExtraPoints, AT_,
"extraPoints");
32806 MInt offset, pointCount;
32808 for(
MInt c = 0; c < noExtractedCells; c++) {
32809 if(cellTypes.
p[c] == polyCellType) {
32810 polyCellLink.
p[polyIds.
p[c]] = c;
32816 const MInt maxPointsXD = 12;
32818 for(
MInt pc = 0; pc < noPolyCells; pc++) {
32819 eCell = polyCellLink.
p[pc];
32822 noExtraPoints.
p[pc] = 0;
32829 noInternalPoints.
p[pc] = 0;
32832 MInt p = pointOrder[i];
32833 MInt dir = dirOrder[i];
32837 extraPoints.
p[pc * maxNoExtraPoints + noExtraPoints.
p[pc]] =
m_extractedCells->
a[eCell].m_pointIds[p];
32838 noExtraPoints.
p[pc]++;
32842 for(
MInt cp = 0; cp <
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints; cp++) {
32843 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutEdge[cp] == dir) {
32844 MInt gridPointId = -1;
32848 if(gridPointId > -1) {
32854 if(gridPointId >= noPoints) {
32855 mTerm(1, AT_,
"Error 0 in FvMbSolver3D::writeVtkXmlOutput(..). Quit.");
32857 if(gridPointId < 0) {
32868 cutPointIds.
p[
m_noDirs * bndryId + dir] = gridPointId;
32870 extraPoints.
p[pc * maxNoExtraPoints + noExtraPoints.
p[pc]] = gridPointId;
32871 noExtraPoints.
p[pc]++;
32877 noInternalPoints.
p[pc] = 0;
32882 extraPoints.
p[pc * maxNoExtraPoints + noExtraPoints.
p[pc]] =
m_extractedCells->
a[eCell].m_pointIds[point];
32883 noExtraPoints.
p[pc]++;
32894 MInt previousCutPoints = -1;
32895 MInt pointFound =
false;
32896 for(
MInt srfc = 0; srfc <
m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
32897 for(
MInt cp = 0; cp <
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_noCutPoints; cp++) {
32898 previousCutPoints++;
32899 if(previousCutPoints == point) {
32908 if(pointFound)
break;
32910 extraPoints.
p[pc * maxNoExtraPoints + noExtraPoints.
p[pc]] = gridPointId;
32911 noExtraPoints.
p[pc]++;
32919 noInternalPoints.
p[pc] = 0;
32922 MInt p = pointOrder[i];
32923 MInt dir = dirOrder[i];
32925 extraPoints.
p[pc * maxNoExtraPoints + noExtraPoints.
p[pc]] =
m_extractedCells->
a[eCell].m_pointIds[p];
32926 noExtraPoints.
p[pc]++;
32928 isPolyFace =
false;
32934 if(!childCode[dir][child])
continue;
32937 isPolyFace =
false;
32939 if(reverseMapping.
p[childId] < 0) {
32940 isPolyFace =
false;
32950 cerr <<
"=== VTK XML ERROR LOG === " <<
domainId() << endl;
32954 cerr << endl <<
a_noCells() <<
" " << dir <<
" " << ltable[i][0] << endl;
32956 cerr <<
"props: " <<
a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) <<
" " <<
a_isHalo(cellId) <<
" "
32980 mTerm(1, AT_,
"Error 1 in FvMbSolver2D::writeVtkXmlOutput_MGC(..). Quit.");
32983 extraPoints.
p[pc * maxNoExtraPoints + noExtraPoints.
p[pc]] = centerId;
32984 noExtraPoints.
p[pc]++;
32990 cerr << endl << cellId <<
" / ";
32994 mTerm(1, AT_,
"Error 2 in FvMbSolver2D::writeVtkXmlOutput_MGC(..). Quit.");
33002 for(
MInt c = 0; c < noExtractedCells; c++) {
33003 MInt pc = polyIds.
p[c];
33005 pointCount += noInternalPoints.
p[pc];
33006 pointCount += noExtraPoints.
p[pc];
33012 MInt qDataSize = 2;
33013 if(QThresholdOutput) qDataSize++;
33016 for(
MInt c = 0; c < noExtractedCells; c++) {
33024 MFloat omega = F1B2 * (gradU[1][0] - gradU[0][1]);
33029 S2 +=
POW2(F1B2 * (gradU[i][j] + gradU[j][i]));
33032 MFloat Q = F1B2 * (omega2 - S2);
33033 qData(0, cellId) = Q;
33034 qData(1, cellId) = omega;
33035 if(QThresholdOutput) qData(2, cellId) = F1B2 * ((omega2 /
mMax(
m_eps, S2)) - F1);
33040 cerr <<
"gather...";
33045 for(
MInt p = 0; p < noPoints; p++) {
33049 points.
p[3 * p + 2] = (flt)F0;
33055 for(
MInt c = 0; c < noExtractedCells; c++) {
33056 MInt pc = polyIds.
p[c];
33058 for(
MInt p = 0; p < noExtraPoints.
p[pc]; p++) {
33059 connectivity.
p[counter] = (
MUint)extraPoints.
p[pc * maxNoExtraPoints + p];
33070 if(counter != pointCount) {
33071 mTerm(1, AT_,
"E1");
33077 for(
MInt c = 0; c < noExtractedCells; c++) {
33078 MInt pc = polyIds.
p[c];
33080 counter += noInternalPoints.
p[pc] + noExtraPoints.
p[pc];
33084 offsets.
p[c] = (
MUint)counter;
33089 for(
MInt c = 0; c < noExtractedCells; c++) {
33090 types.
p[c] = (
unsigned char)cellTypes.
p[c];
33095 for(
MInt c = 0; c < noExtractedCells; c++) {
33103 for(
MInt c = 0; c < noExtractedCells; c++) {
33104 vtkGhostLevels.
p[c] = (
unsigned char)0;
33107 vtkGhostLevels.
p[c] = (
unsigned char)2;
33115 for(
MInt c = 0; c < noExtractedCells; c++) {
33122 for(
MInt c = 0; c < noExtractedCells; c++) {
33129 for(
MInt c = 0; c < noExtractedCells; c++) {
33136 for(
MInt c = 0; c < noExtractedCells; c++) {
33142 for(
MInt c = 0; c < noExtractedCells; c++) {
33149 for(
MInt c = 0; c < noExtractedCells; c++) {
33153 const MInt sensorSize = sensorOutput ? noCells : 1;
33157 for(
MInt c = 0; c < noExtractedCells; c++) {
33165 MInt asize = noCells;
33166 if(writePointData) {
33174 const MInt dSSize = entropyChangeOutput ? asize : 1;
33178 const MInt qtSize = QThresholdOutput ? asize : 1;
33184 if(writePointData) {
33185 for(
MInt p = 0; p < noInternalGridPoints; p++) {
33211 pressure.
p[p] = (flt)F0;
33212 density.
p[p] = (flt)F0;
33213 vorticity.
p[p] = (flt)F0;
33214 Qcriterion.
p[p] = (flt)F0;
33215 if(entropyChangeOutput) dS.
p[p] = (flt)F0;
33217 velocity.
p[3 * p + i] = (flt)F0;
33219 velocity.
p[3 * p + 2] = (flt)F0;
33221 rhoE.
p[p] = (flt)F0;
33222 if(QThresholdOutput) QThreshold.
p[p] = (flt)F0;
33228 vorticity.
p[p] += (flt)weights[n] * qData(1, cellId);
33229 Qcriterion.
p[p] += (flt)weights[n] * qData(0, cellId);
33232 velocity.
p[3 * p + i] += (flt)weights[n] *
a_pvariable(cellId,
PV->VV[i]);
33235 rhoE.
p[p] += (flt)weights[n] *
a_variable(cellId,
CV->RHO_E);
33236 if(QThresholdOutput) QThreshold.
p[p] += (flt)weights[n] * qData(2, cellId);
33240 for(
MInt p = noInternalGridPoints; p < noPoints; p++) {
33247 if(
a_hasProperty(cellId, SolverCell::IsInactive))
continue;
33259 pressure.
p[p] = (flt)F0;
33260 density.
p[p] = (flt)F0;
33261 vorticity.
p[p] = (flt)F0;
33262 Qcriterion.
p[p] = (flt)F0;
33263 if(entropyChangeOutput) dS.
p[p] = (flt)F0;
33265 velocity.
p[3 * p + i] = (flt)F0;
33267 velocity.
p[3 * p + 2] = F0;
33269 rhoE.
p[p] = (flt)F0;
33270 if(QThresholdOutput) QThreshold.
p[p] = (flt)F0;
33274 if(
a_hasProperty(cellId, SolverCell::IsInactive))
continue;
33280 pressure.
p[p] += (flt)weights[n] * pb;
33281 density.
p[p] += (flt)weights[n] * rhob;
33282 vorticity.
p[p] += (flt)weights[n] * qData(1, cellId);
33283 Qcriterion.
p[p] += (flt)weights[n] * qData(0, cellId);
33287 velocity.
p[3 * p + i] +=
33291 rhoE.
p[p] += (flt)weights[n] *
a_variable(cellId,
CV->RHO_E);
33292 if(QThresholdOutput) QThreshold.
p[p] += (flt)weights[n] * qData(2, cellId);
33296 pressure.
p[p] += (flt)weights[n] *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->P];
33297 density.
p[p] += (flt)weights[n] *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->RHO];
33298 vorticity.
p[p] += (flt)weights[n] * qData(1, cellId);
33299 Qcriterion.
p[p] += (flt)weights[n] * qData(0, cellId);
33301 m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->RHO]);
33304 velocity.
p[3 * p + i] +=
33305 (flt)weights[n] *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[0]->m_primVars[
PV->VV[i]];
33308 rhoE.
p[p] += (flt)weights[n] *
a_variable(cellId,
CV->RHO_E);
33309 if(QThresholdOutput) QThreshold.
p[p] += (flt)weights[n] * qData(2, cellId);
33315 for(
MInt c = 0; c < noExtractedCells; c++) {
33319 vorticity.
p[c] = (flt)qData(1, cellId);
33320 Qcriterion.
p[c] = (flt)qData(0, cellId);
33325 velocity.
p[3 * c + 2] = (flt)F0;
33328 if(QThresholdOutput) QThreshold.
p[c] = (flt)qData(2, cellId);
33335 cerr <<
"write...";
33339 ofl.open(fileName.c_str(), ios_base::out | ios_base::trunc);
33340 if(ofl.is_open() && ofl.good()) {
33344 ofl <<
"<?xml version=\"1.0\"?>" << endl;
33345 ofl <<
"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << endl;
33346 ofl <<
"<UnstructuredGrid>" << endl;
33349 ofl <<
"<FieldData>" << endl;
33351 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"time\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33352 <<
m_time <<
"\" RangeMax=\"" <<
m_time <<
"\">" << endl;
33354 ofl <<
"</DataArray>" << endl;
33355 ofl <<
"<DataArray type=\"" << dataType
33356 <<
"\" Name=\"physicalTime\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\"" <<
m_physicalTime
33359 ofl <<
"</DataArray>" << endl;
33360 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"timeStep\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33363 ofl <<
"</DataArray>" << endl;
33364 ofl <<
"<DataArray type=\"" << iDataType
33365 <<
"\" Name=\"globalTimeStep\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\"" <<
globalTimeStep
33368 ofl <<
"</DataArray>" << endl;
33369 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Ma\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33370 <<
m_Ma <<
"\" RangeMax=\"" <<
m_Ma <<
"\">" << endl;
33371 ofl <<
m_Ma << endl;
33372 ofl <<
"</DataArray>" << endl;
33373 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Re\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33374 <<
m_Re <<
"\" RangeMax=\"" <<
m_Re <<
"\">" << endl;
33375 ofl <<
m_Re << endl;
33376 ofl <<
"</DataArray>" << endl;
33377 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Pr\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33378 <<
m_Pr <<
"\" RangeMax=\"" <<
m_Pr <<
"\">" << endl;
33379 ofl <<
m_Pr << endl;
33380 ofl <<
"</DataArray>" << endl;
33381 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"gamma\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33384 ofl <<
"</DataArray>" << endl;
33385 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"CFL\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33386 <<
m_cfl <<
"\" RangeMax=\"" <<
m_cfl <<
"\">" << endl;
33387 ofl <<
m_cfl << endl;
33388 ofl <<
"</DataArray>" << endl;
33389 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"uInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33392 ofl <<
"</DataArray>" << endl;
33393 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"vInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33396 ofl <<
"</DataArray>" << endl;
33397 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"pInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33400 ofl <<
"</DataArray>" << endl;
33401 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"rhoInf\" format=\"ascii\" NumberOfTuples=\"1\" RangeMin=\""
33404 ofl <<
"</DataArray>" << endl;
33405 ofl <<
"</FieldData>" << endl;
33408 ofl <<
"<Piece NumberOfPoints=\"" << noPoints <<
"\" NumberOfCells=\"" << noCells <<
"\">" << endl;
33411 ofl <<
"<Points>" << endl;
33412 ofl <<
"<DataArray type=\"" << dataType <<
"\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset
33415 ofl <<
"</Points>" << endl;
33418 ofl <<
"<Cells>" << endl;
33420 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"connectivity\" format=\"appended\" offset=\"" << offset
33424 ofl <<
"<DataArray type=\"" << uIDataType <<
"\" Name=\"offsets\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33428 ofl <<
"<DataArray type=\"" << uI8DataType <<
"\" Name=\"types\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33432 ofl <<
"</Cells>" << endl;
33435 ofl <<
"<CellData Scalars=\"scalars\">" << endl;
33437 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"cellIds\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33442 ofl <<
"<DataArray type=\"" << uI8DataType <<
"\" Name=\"vtkGhostLevels\" format=\"appended\" offset=\"" << offset
33448 ofl <<
"<DataArray type=\"" << iDataType <<
"\" Name=\"bndryIds\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33452 ofl <<
"<DataArray type=\"" << dataType64 <<
"\" Name=\"drho_dt\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33456 ofl <<
"<DataArray type=\"" << dataType64 <<
"\" Name=\"drhou_dt\" format=\"appended\" offset=\"" << offset
33460 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"levelSetFunction\" format=\"appended\" offset=\"" << offset
33464 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"volume\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33468 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"spongeFactor\" format=\"appended\" offset=\"" << offset
33473 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"tauC\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33476 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"tauE\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33483 if(writePointData) {
33484 ofl <<
"</CellData>" << endl;
33485 ofl <<
"<PointData Scalars=\"scalars\">" << endl;
33488 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"pressure\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33492 ofl <<
"<DataArray type=\"" << dataType
33493 <<
"\" Name=\"velocity\" NumberOfComponents=\"3\" format=\"appended\" offset=\"" << offset <<
"\"/>" << endl;
33496 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"density\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33500 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"vorticity\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33504 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"Qcriterion\" format=\"appended\" offset=\"" << offset
33508 if(entropyChangeOutput) {
33509 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"dS\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33515 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"rhoE\" format=\"appended\" offset=\"" << offset <<
"\"/>"
33519 if(QThresholdOutput) {
33520 ofl <<
"<DataArray type=\"" << dataType <<
"\" Name=\"QThreshold\" format=\"appended\" offset=\"" << offset
33527 if(writePointData) {
33528 ofl <<
"</PointData>" << endl;
33530 ofl <<
"</CellData>" << endl;
33533 ofl <<
"</Piece>" << endl;
33534 ofl <<
"</UnstructuredGrid>" << endl;
33536 ofl <<
"<AppendedData encoding=\"raw\">" << endl;
33541 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (1)" << endl;
33543 ofl.open(fileName.c_str(), ios_base::out | ios_base::app | ios_base::binary);
33545 if(ofl.is_open() && ofl.good()) {
33548 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(
MUint));
33549 ofl.write(
reinterpret_cast<const char*
>(points.
getPointer()), uinumber);
33553 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(
MUint));
33554 ofl.write(
reinterpret_cast<const char*
>(connectivity.
getPointer()), uinumber);
33558 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33559 ofl.write(
reinterpret_cast<const char*
>(offsets.
getPointer()), uinumber);
33563 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33564 ofl.write(
reinterpret_cast<const char*
>(types.
getPointer()), uinumber);
33568 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33569 ofl.write(
reinterpret_cast<const char*
>(cellIds.
getPointer()), uinumber);
33574 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33575 ofl.write(
reinterpret_cast<const char*
>(vtkGhostLevels.
getPointer()), uinumber);
33581 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33582 ofl.write(
reinterpret_cast<const char*
>(bndryIds.
getPointer()), uinumber);
33586 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33587 ofl.write(
reinterpret_cast<const char*
>(drho_dt.
getPointer()), uinumber);
33591 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33592 ofl.write(
reinterpret_cast<const char*
>(drhou_dt.
getPointer()), uinumber);
33596 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33597 ofl.write(
reinterpret_cast<const char*
>(levelSetFunction.
getPointer()), uinumber);
33601 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33602 ofl.write(
reinterpret_cast<const char*
>(volume.
getPointer()), uinumber);
33606 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33607 ofl.write(
reinterpret_cast<const char*
>(spongeFac.
getPointer()), uinumber);
33612 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33613 ofl.write(
reinterpret_cast<const char*
>(tauC.
getPointer()), uinumber);
33615 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33616 ofl.write(
reinterpret_cast<const char*
>(tauE.
getPointer()), uinumber);
33623 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33624 ofl.write(
reinterpret_cast<const char*
>(pressure.
getPointer()), uinumber);
33628 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33629 ofl.write(
reinterpret_cast<const char*
>(velocity.
getPointer()), uinumber);
33633 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33634 ofl.write(
reinterpret_cast<const char*
>(density.
getPointer()), uinumber);
33638 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33639 ofl.write(
reinterpret_cast<const char*
>(vorticity.
getPointer()), uinumber);
33643 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33644 ofl.write(
reinterpret_cast<const char*
>(Qcriterion.
getPointer()), uinumber);
33647 if(entropyChangeOutput) {
33649 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33650 ofl.write(
reinterpret_cast<const char*
>(dS.
getPointer()), uinumber);
33657 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33658 ofl.write(
reinterpret_cast<const char*
>(rhoE.
getPointer()), uinumber);
33660 if(QThresholdOutput) {
33662 ofl.write(
reinterpret_cast<const char*
>(&uinumber),
sizeof(uinumber));
33663 ofl.write(
reinterpret_cast<const char*
>(QThreshold.
getPointer()), uinumber);
33671 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (2)" << endl;
33674 ofl.open(fileName.c_str(), ios_base::out | ios_base::app);
33675 if(ofl.is_open() && ofl.good()) {
33677 ofl <<
"</AppendedData>" << endl;
33679 ofl <<
"</VTKFile>" << endl;
33683 cerr <<
"ERROR! COULD NOT OPEN FILE " << fileName <<
" for writing! (3)" << endl;
33692template <MInt nDim,
class SysEqn>
33693template <
class _, std::enable_if_t<nDim == 2, _*>>
33698 ofl.open(fileName.c_str());
33700 if(ofl.is_open() && ofl.good()) {
33701 ofl <<
"<?xml version=\"1.0\"?>" << endl;
33702 ofl << R
"(<VTKFile type="PolyData" version="0.1")" << endl;
33703 ofl << "<PolyData>" << endl;
33704 ofl <<
"<Piece NumberOfPoints=\"" << 0 <<
"\" NumberOfCells=\"" << 0 <<
"\">" << endl;
33705 ofl <<
"</Piece>" << endl;
33706 ofl <<
"</PolyData>" << endl;
33707 ofl <<
"</VTKFile>" << endl;
33720template <MInt nDim,
class SysEqn>
33721template <
class _, std::enable_if_t<nDim == 3, _*>>
33731template <MInt nDim,
class SysEqn>
33732template <
class _, std::enable_if_t<nDim == 2, _*>>
33734 const std::vector<polyVertex>* vertices,
MInt set) {
33735 const MChar* fileName =
"cell_";
33736 stringstream fileName2;
33737 fileName2 << fileName << cellId <<
"_s" << set <<
"_D" <<
domainId() <<
".vtk";
33739 ofl.open((fileName2.str()).c_str(), ofstream::trunc);
33743 ofl.setf(ios::fixed);
33746 ofl <<
"# vtk DataFile Version 3.0" << endl
33747 <<
"MAIAD cutsurface file" << endl
33750 <<
"DATASET UNSTRUCTURED_GRID" << endl
33753 ofl <<
"POINTS " << (*vertices).size() <<
" float" << endl;
33755 for(
MInt v = 0; (unsigned)v < (*vertices).size(); v++) {
33757 ofl << (*vertices)[v].coordinates[i] <<
" ";
33763 MInt numPoints = 0;
33764 MInt noEdges = (*edges).size();
33765 numPoints += noEdges * 2;
33766 ofl <<
"CELLS " << noEdges <<
" " << noEdges + numPoints << endl;
33769 for(
MInt i = 0; i < noEdges; i++) {
33770 unsigned noVerts = 2;
33771 ofl << noVerts <<
" ";
33772 ofl << (*edges)[i].vertices[0] <<
" ";
33773 ofl << (*edges)[i].vertices[1] <<
" ";
33778 ofl <<
"CELL_TYPES " << noEdges << endl;
33779 for(
MInt i = 0; i < noEdges; i++) {
33792template <MInt nDim,
class SysEqn>
33793template <
class _, std::enable_if_t<nDim == 2, _*>>
33795 const std::vector<polyEdge2D>* edges,
33796 const std::vector<polyVertex>* vertices,
MInt set) {
33797 const MChar* fileName =
"cutCell_";
33798 stringstream fileName2;
33799 fileName2 << fileName << cellId <<
"_s" << set <<
"_D" <<
domainId() <<
".vtk";
33801 ofl.open((fileName2.str()).c_str(), ofstream::trunc);
33805 ofl.setf(ios::fixed);
33808 ofl <<
"# vtk DataFile Version 3.0" << endl
33809 <<
"MAIAD cutsurface file" << endl
33812 <<
"DATASET UNSTRUCTURED_GRID" << endl
33815 ofl <<
"POINTS " << (*vertices).size() <<
" float" << endl;
33817 for(
MInt v = 0; (unsigned)v < (*vertices).size(); v++) {
33819 ofl << (*vertices)[v].coordinates[i] <<
" ";
33825 MInt numPoints = 0;
33827 for(
MInt c = 0; (unsigned)c < (*cutCells).size(); c++) {
33828 MInt noEdgesCC = (*cutCells)[c].faces_edges.size();
33829 numPoints += noEdgesCC * 2;
33830 noEdges += noEdgesCC;
33832 ofl <<
"CELLS " << noEdges <<
" " << noEdges + numPoints << endl;
33835 for(
MInt c = 0; (unsigned)c < (*cutCells).size(); c++) {
33836 for(
MInt i = 0; (unsigned)i < (*cutCells)[c].faces_edges.size(); i++) {
33837 MInt edge = (*cutCells)[c].faces_edges[i];
33838 unsigned noVerts = 2;
33839 ofl << noVerts <<
" ";
33840 ofl << (*edges)[edge].vertices[0] <<
" ";
33841 ofl << (*edges)[edge].vertices[1] <<
" ";
33848 ofl <<
"CELL_TYPES " << noEdges << endl;
33849 for(
MInt i = 0; i < noEdges; i++) {
33854 ofl <<
"CELL_DATA " << noEdges << endl;
33855 ofl <<
"FIELD FieldData " << 2 << endl;
33857 <<
" " << 1 <<
" " << noEdges <<
" "
33859 for(
MInt c = 0; (unsigned)c < (*cutCells).size(); c++) {
33860 for(
MInt f = 0; (unsigned)f < (*cutCells)[c].faces_edges.size(); f++) {
33861 MInt edge = (*cutCells)[c].faces_edges[f];
33862 ofl << (*edges)[edge].cutCell <<
" ";
33867 <<
" " << 1 <<
" " << noEdges <<
" "
33869 for(
MInt c = 0; (unsigned)c < (*cutCells).size(); c++) {
33870 for(
MInt f = 0; (unsigned)f < (*cutCells)[c].faces_edges.size(); f++) {
33871 MInt edge = (*cutCells)[c].faces_edges[f];
33872 ofl << (*edges)[edge].bodyId <<
" ";
33886template <MInt nDim,
class SysEqn>
33887template <
class _, std::enable_if_t<nDim == 2, _*>>
33889 const std::vector<polyEdge2D>* edges,
33890 const std::vector<polyVertex>* vertices,
MInt set) {
33891 const MChar* fileName =
"polyData_";
33892 stringstream fileName2;
33893 fileName2 << fileName << cellId <<
"_s" << set <<
"_D" <<
domainId();
33895 ofl.open((fileName2.str()).c_str(), ofstream::trunc);
33899 ofl.setf(ios::fixed);
33902 ofl <<
"VERTICES:" << endl;
33903 for(
MInt v = 0; (unsigned)v < (*vertices).size(); v++) {
33904 ofl << v <<
": " << endl;
33905 ofl <<
"coordinates: " << (*vertices)[v].coordinates[0] <<
" " << (*vertices)[v].coordinates[1] << endl;
33906 ofl <<
"pointId: " << (*vertices)[v].pointId;
33907 ofl <<
", pointType: " << (*vertices)[v].pointType << endl;
33909 for(
MInt e = 0; (unsigned)e < (*vertices)[v].edges.size(); e++)
33910 ofl << (*vertices)[v].edges[e] <<
" ";
33911 ofl << endl << endl;
33914 ofl << endl <<
"EDGES:" << endl;
33915 for(
MInt e = 0; (unsigned)e < (*edges).size(); e++) {
33916 ofl << e <<
": " << endl;
33917 ofl <<
"vertices: " << (*edges)[e].vertices[0] <<
" " << (*edges)[e].vertices[1] << endl;
33918 ofl <<
"edgeId: " << (*edges)[e].edgeId;
33919 ofl <<
", edgeType: " << (*edges)[e].edgeType;
33920 ofl <<
", bodyId: " << (*edges)[e].bodyId;
33921 ofl <<
", cutCell: " << (*edges)[e].cutCell << endl;
33922 ofl <<
"area: " << (*edges)[e].area << endl;
33923 ofl <<
"center: " << (*edges)[e].center[0] <<
" " << (*edges)[e].center[1] << endl;
33924 ofl <<
"normal: " << (*edges)[e].normal[0] <<
" " << (*edges)[e].normal[1] << endl;
33925 ofl <<
"w: " << (*edges)[e].w << endl;
33926 ofl << endl << endl;
33929 ofl << endl <<
"CUT CELLS:" << endl;
33930 for(
MInt c = 0; (unsigned)c < (*cutCells).size(); c++) {
33931 ofl << c <<
": " << endl;
33932 ofl <<
"volume: " << (*cutCells)[c].volume << endl;
33933 ofl <<
"center: " << (*cutCells)[c].center[0] <<
" " << (*cutCells)[c].center[1] << endl;
33934 ofl <<
"cartesianCell: " << (*cutCells)[c].cartesianCell << endl;
33936 for(
MInt f = 0; (unsigned)f < (*cutCells)[c].faces_edges.size(); f++)
33937 ofl << (*cutCells)[c].faces_edges[f] <<
" ";
33938 ofl << endl << endl;
33950template <MInt nDim,
class SysEqn>
33951template <
class _, std::enable_if_t<nDim == 3, _*>>
33953 const std::vector<polyFace>* faces,
33954 const std::vector<polyEdge3D>* edges,
33955 const std::vector<polyVertex>* vertices,
MInt set) {
33956 const MChar* fileName =
"polyData_";
33957 stringstream fileName2;
33958 fileName2 << fileName << cellId <<
"_s" << set <<
"_D" <<
domainId();
33960 ofl.open((fileName2.str()).c_str(), ofstream::trunc);
33964 ofl.setf(ios::fixed);
33967 ofl <<
"VERTICES:" << endl;
33968 for(
MInt v = 0; (unsigned)v < (*vertices).size(); v++) {
33969 ofl << v <<
": " << endl;
33970 ofl <<
"coordinates: " << (*vertices)[v].coordinates[0] <<
" " << (*vertices)[v].coordinates[1] <<
" "
33971 << (*vertices)[v].coordinates[2] << endl;
33972 ofl <<
"pointId: " << (*vertices)[v].pointId;
33973 ofl <<
", pointType: " << (*vertices)[v].pointType << endl;
33974 ofl <<
"surfaceIdentificators: ";
33975 for(std::set<MInt>::iterator it = (*vertices)[v].surfaceIdentificators.begin();
33976 it != (*vertices)[v].surfaceIdentificators.end();
33981 for(
MInt e = 0; (unsigned)e < (*vertices)[v].edges.size(); e++)
33982 ofl << (*vertices)[v].edges[e] <<
" ";
33983 ofl << endl << endl;
33986 ofl << endl <<
"EDGES:" << endl;
33987 for(
MInt e = 0; (unsigned)e < (*edges).size(); e++) {
33988 ofl << e <<
": " << endl;
33989 ofl <<
"vertices: " << (*edges)[e].vertices[0] <<
" " << (*edges)[e].vertices[1] << endl;
33990 ofl <<
"faces: " << (*edges)[e].face[0] <<
" " << (*edges)[e].face[1] << endl;
33991 ofl <<
"edgeId: " << (*edges)[e].edgeId;
33992 ofl <<
", edgeType: " << (*edges)[e].edgeType << endl;
33993 ofl << endl << endl;
33996 ofl << endl <<
"FACES:" << endl;
33997 for(
MInt f = 0; (unsigned)f < (*faces).size(); f++) {
33998 ofl << f <<
": " << endl;
33999 ofl <<
"area: " << (*faces)[f].area << endl;
34000 ofl <<
"center: " << (*faces)[f].center[0] <<
" " << (*faces)[f].center[1] <<
" " << (*faces)[f].center[2]
34002 ofl <<
"normal: " << (*faces)[f].normal[0] <<
" " << (*faces)[f].normal[1] <<
" " << (*faces)[f].normal[2]
34004 ofl <<
"w: " << (*faces)[f].w << endl;
34005 ofl <<
"faceId: " << (*faces)[f].faceId;
34006 ofl <<
", faceType: " << (*faces)[f].faceType << endl;
34007 ofl <<
"bodyId: " << (*faces)[f].bodyId << endl;
34008 ofl <<
"setIndex: " << (*faces)[f].tmpSetIndex << endl;
34009 ofl <<
"cutCell: " << (*faces)[f].cutCell << endl;
34011 for(
MInt e = 0; (unsigned)e < (*faces)[f].edges.size(); e++)
34012 ofl << (*faces)[f].edges[e].first <<
", dir " << (*faces)[f].edges[e].second <<
" ";
34013 ofl << endl << endl;
34016 ofl << endl <<
"CUT CELLS:" << endl;
34017 for(
MInt c = 0; (unsigned)c < (*cutCells).size(); c++) {
34018 ofl << c <<
": " << endl;
34019 ofl <<
"volume: " << (*cutCells)[c].volume << endl;
34020 ofl <<
"center: " << (*cutCells)[c].center[0] <<
" " << (*cutCells)[c].center[1] <<
" "
34021 << (*cutCells)[c].center[2] << endl;
34022 ofl <<
"cartesianCell: " << (*cutCells)[c].cartesianCell << endl;
34024 for(
MInt f = 0; (unsigned)f < (*cutCells)[c].faces_edges.size(); f++)
34025 ofl << (*cutCells)[c].faces_edges[f] <<
" ";
34026 ofl << endl << endl;
34046template <MInt nDim,
class SysEqn>
34047template <
class _, std::enable_if_t<nDim == 2, _*>>
34055 bodyFaceJoinMode = Context::getSolverProperty<MInt>(
"bodyFaceJoinMode",
solverId(), AT_, &bodyFaceJoinMode);
34056 maxA = Context::getSolverProperty<MFloat>(
"bodyFaceJoinCriterion",
solverId(), AT_, &maxA);
34060 const MInt faceOrder[4] = {2, 1, 3, 0};
34061 const MFloat signStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
34062 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
34063 const MInt edgeCornerCode[4][2] = {{2, 0}, {1, 3}, {0, 1}, {3, 2}};
34065 const MInt maxNoSets = 6;
34071 const MInt maxNoVertices = 25;
34072 const MInt maxNoEdges = 25;
34074 stack<MInt> multiEdgeStack;
34075 std::vector<polyVertex> vertices[maxNoSets];
34076 std::vector<polyEdge2D> edges[maxNoSets];
34077 std::vector<polyCutCell> cutCells;
34079 std::vector<CsgPolygon> csg_polygons;
34080 std::vector<CsgVertex> csg_vertices;
34081 std::vector<Csg> csg;
34082 std::vector<CsgPolygon> result;
34083 std::vector<polyVertex> vertices_result;
34084 stack<MInt> edgeStack;
34085 std::vector<MInt> faceVertices;
34087 MIntScratchSpace multiEdgeConnection(maxNoEdges, AT_,
"multiEdgeConnection");
34088 MIntScratchSpace vertices_renamed(2, maxNoVertices, AT_,
"vertices_renamed");
34090 MFloatScratchSpace normalDotProduct(maxNoEdges, maxNoEdges, AT_,
"normalDotProduct");
34093 MBoolScratchSpace isPartOfBodySurface(maxNoVertices, AT_,
"isPartOfBodySurface");
34095 MIntScratchSpace vertexCutCellPointer(maxNoEdges, AT_,
"vertexCutCellPointer");
34101 ASSERT(cndId > -1,
"");
34107 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints == 0) {
34108 cerr <<
"** fvmbsolver2d ERROR" << endl;
34109 cerr <<
"boundary cell " << bndryId << endl;
34111 cerr <<
" -> number of cut points is zero" << endl;
34115 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints % 2 != 0) {
34116 cerr <<
"** fvmbsolver2d ERROR" << endl;
34117 cerr <<
"boundary cell " << bndryId << endl;
34119 cerr <<
" -> number of cut points uneven" << endl;
34124 const MFloat cellHalfLength = F1B2 * cellLength0;
34128 vertices[s].clear();
34130 cutSetPointers[s] = -1;
34131 noCutPointsFromSet[s] = 0;
34135 MBool isGapCell =
false;
34137 isGapCell = (
a_hasProperty(cellId, SolverCell::IsGapCell));
34151 MInt noCutSets = 0;
34152 MBool isCompletelyOutside =
false;
34153 for(
MInt s = startSet; s < endSet; s++) {
34157 unsigned char outcode = 0;
34160 if(currentOutcode) outcode = outcode | (1 << c);
34162 outcode_set[s] = outcode;
34163 if(outcode == 0) isCompletelyOutside =
true;
34168 "bodyId out of bounds " + to_string(cellId) +
" " + to_string(cutPoint) +
" "
34174 + to_string(cutPoint) +
" " + to_string(set) +
" "
34176 noCutPointsFromSet[set]++;
34178 for(
MInt set = startSet; set < endSet; set++) {
34179 if(noCutPointsFromSet[set] && !isCompletelyOutside) {
34180 cutSetPointers[set] = noCutSets++;
34185 for(
MInt set = startSet; set < endSet; set++) {
34186 MInt setIndex = cutSetPointers[set];
34187 if(setIndex < 0)
continue;
34189 if(bodyId < 0)
continue;
34194 MInt cutPoints[4] = {-1, -1, -1, -1};
34195 MInt cutPointToVertexMap[4] = {-1, -1, -1, -1};
34196 MInt noCutPoints = 0;
34203 cutPointToVertexMap[cutPoint] = vertices[setIndex].size() - 1;
34205 MInt cornerToVertexMap[4] = {-1, -1, -1, -1};
34210 tmp_coords[i] =
a_coordinate(cellId, i) + signStencil[c][i] * cellHalfLength;
34211 vertices[setIndex].push_back(
polyVertex(tmp_coords, c, 0));
34212 cornerToVertexMap[c] = vertices[setIndex].size() - 1;
34221 MInt outcode = outcode_set[set];
34224 MInt currentCase = (
MInt)cases2D[outcode][0];
34225 MInt currentSubCase = (
MInt)cases2D[outcode][1];
34226 MInt subConfig = 0;
34228 if(!caseStates2D[currentCase]) {
34230 if((centerIsFluid && currentSubCase == 1) || (!centerIsFluid && currentCase == 0)) subConfig = 1;
34234 const MInt* tilingPointer =
nullptr;
34235 noLines = noEdges2D[currentCase];
34236 switch(currentCase) {
34241 tilingPointer = tiling1_2D[currentSubCase];
34244 tilingPointer = tiling2_2D[currentSubCase];
34248 tilingPointer = tiling3_A_2D[currentSubCase];
34250 tilingPointer = tiling3_B_2D[currentSubCase];
34254 mTerm(1, AT_,
"invalid MC case, how could this happen? exiting...");
34259 for(
MInt t = 0; t < noLines; t++) {
34262 MInt cutEdge0 = tilingPointer[t * 2 + 0];
34263 MInt cutEdge1 = tilingPointer[t * 2 + 1];
34264 MInt p0 = cutPoints[cutEdge0];
34265 MInt p1 = cutPoints[cutEdge1];
34266 p[0] = cutPointToVertexMap[p0];
34267 p[1] = cutPointToVertexMap[p1];
34268 MInt newEdge = edges[setIndex].size();
34271 edges[setIndex].push_back(
polyEdge2D(p[0], p[1], edgeId, edgeType, bodyId));
34272 vertices[setIndex][p[0]].edges.push_back(newEdge);
34273 vertices[setIndex][p[1]].edges.push_back(newEdge);
34276 computeNormal(vertices[setIndex][p[0]].coordinates, vertices[setIndex][p[1]].coordinates,
34277 edges[setIndex][newEdge].normal, edges[setIndex][newEdge].w);
34282 MInt edge = faceOrder[e];
34285 if(p0Fluid && p1Fluid) {
34286 MInt v0 = cornerToVertexMap[edgeCornerCode[edge][0]];
34287 MInt v1 = cornerToVertexMap[edgeCornerCode[edge][1]];
34288 edges[setIndex].push_back(
polyEdge2D(v0, v1, edge, 0, -1));
34289 vertices[setIndex][v0].edges.push_back(edges[setIndex].size() - 1);
34290 vertices[setIndex][v1].edges.push_back(edges[setIndex].size() - 1);
34291 computeNormal(vertices[setIndex][v0].coordinates, vertices[setIndex][v1].coordinates,
34292 edges[setIndex][edges[setIndex].size() - 1].normal,
34293 edges[setIndex][edges[setIndex].size() - 1].w);
34294 }
else if(p0Fluid) {
34295 MInt v0 = cornerToVertexMap[edgeCornerCode[edge][0]];
34296 MInt v1 = cutPointToVertexMap[cutPoints[edge]];
34297 edges[setIndex].push_back(
polyEdge2D(v0, v1, edge, 1, -1));
34298 vertices[setIndex][v0].edges.push_back(edges[setIndex].size() - 1);
34299 vertices[setIndex][v1].edges.push_back(edges[setIndex].size() - 1);
34300 computeNormal(vertices[setIndex][v0].coordinates, vertices[setIndex][v1].coordinates,
34301 edges[setIndex][edges[setIndex].size() - 1].normal,
34302 edges[setIndex][edges[setIndex].size() - 1].w);
34303 }
else if(p1Fluid) {
34304 MInt v0 = cutPointToVertexMap[cutPoints[edge]];
34305 MInt v1 = cornerToVertexMap[edgeCornerCode[edge][1]];
34306 edges[setIndex].push_back(
polyEdge2D(v0, v1, edge, 1, -1));
34307 vertices[setIndex][v0].edges.push_back(edges[setIndex].size() - 1);
34308 vertices[setIndex][v1].edges.push_back(edges[setIndex].size() - 1);
34309 computeNormal(vertices[setIndex][v0].coordinates, vertices[setIndex][v1].coordinates,
34310 edges[setIndex][edges[setIndex].size() - 1].normal,
34311 edges[setIndex][edges[setIndex].size() - 1].w);
34319 const MInt startSetIndex = 0;
34320 MInt referenceSet = startSet;
34321 for(
MInt set = startSet; set < endSet; set++) {
34322 if(cutSetPointers[set] > -1) {
34323 referenceSet = set;
34327 for(
MInt set = referenceSet + 1; set < endSet; set++) {
34328 MInt setIndex = cutSetPointers[set];
34329 if(setIndex < 0)
continue;
34331 csg_polygons.clear();
34333 for(
MInt e = 0; (unsigned)e < edges[startSetIndex].size(); e++) {
34334 csg_vertices.clear();
34335 MInt vertex0 = edges[startSetIndex][e].vertices[0];
34336 MInt vertex1 = edges[startSetIndex][e].vertices[1];
34337 csg_vertices.push_back(
34338 CsgVertex(
CsgVector(vertices[startSetIndex][vertex0].coordinates), vertex0, startSetIndex));
34339 csg_vertices.push_back(
34340 CsgVertex(
CsgVector(vertices[startSetIndex][vertex1].coordinates), vertex1, startSetIndex));
34341 csg_polygons.push_back(
CsgPolygon(csg_vertices, startSetIndex, edges[startSetIndex][e].edgeId,
34342 edges[startSetIndex][e].edgeType, edges[startSetIndex][e].bodyId));
34344 csg.push_back(
Csg(csg_polygons));
34346 csg_polygons.clear();
34347 for(
MInt e = 0; (unsigned)e < edges[setIndex].size(); e++) {
34348 csg_vertices.clear();
34349 MInt vertex0 = edges[setIndex][e].vertices[0];
34350 MInt vertex1 = edges[setIndex][e].vertices[1];
34351 csg_vertices.push_back(
CsgVertex(
CsgVector(vertices[setIndex][vertex0].coordinates), vertex0, setIndex));
34352 csg_vertices.push_back(
CsgVertex(
CsgVector(vertices[setIndex][vertex1].coordinates), vertex1, setIndex));
34353 csg_polygons.push_back(
CsgPolygon(csg_vertices, setIndex, edges[setIndex][e].edgeId,
34354 edges[setIndex][e].edgeType, edges[setIndex][e].bodyId));
34356 csg.push_back(
Csg(csg_polygons));
34360 result = csg[0].intersect(csg[1]);
34361 vertices_result.clear();
34365 for(
MInt i = 0; i < 2; i++)
34366 for(
MInt j = 0; j < maxNoVertices; j++)
34367 vertices_renamed(i, j) = -1;
34369 MInt noVertices = 0;
34370 for(
MInt p = 0; (unsigned)p < result.size(); p++) {
34371 for(
MInt v = 0; (unsigned)v < result[p].vertices.size(); v++) {
34372 ASSERT(result[p].vertices.size() <= (
unsigned)maxNoVertices,
"");
34373 MInt vertexId = result[p].vertices[v].vertexId;
34374 MInt vertexSetIndex = result[p].vertices[v].setIndex;
34375 if(vertexId > -1) {
34376 if(vertices_renamed(vertexSetIndex, vertexId) == -1) {
34378 MBool vertexFound =
false;
34379 MInt vertexIndex = -1;
34380 for(
MInt i = 0; (unsigned)i < vertices_result.size(); i++) {
34381 if(vertices_result[i].
pointType != 3)
continue;
34383 coord_diff += (result[p].vertices[v].pos.xx[0] - vertices_result[i].coordinates[0])
34384 * (result[p].vertices[v].pos.xx[0] - vertices_result[i].coordinates[0]);
34385 coord_diff += (result[p].vertices[v].pos.xx[1] - vertices_result[i].coordinates[1])
34386 * (result[p].vertices[v].pos.xx[1] - vertices_result[i].coordinates[1]);
34388 if(coord_diff <
m_eps * 10) {
34389 vertexFound =
true;
34395 vertices_renamed(vertexSetIndex, vertexId) = vertexIndex;
34397 vertices_renamed(vertexSetIndex, vertexId) = noVertices;
34398 vertices_result.push_back(
polyVertex(vertices[vertexSetIndex][vertexId].pointId,
34399 vertices[vertexSetIndex][vertexId].
pointType));
34400 vertices_result[noVertices].coordinates[0] = vertices[vertexSetIndex][vertexId].coordinates[0];
34401 vertices_result[noVertices].coordinates[1] = vertices[vertexSetIndex][vertexId].coordinates[1];
34405 result[p].vertices[v].vertexId = vertices_renamed(vertexSetIndex, vertexId);
34406 result[p].vertices[v].setIndex = -1;
34410 for(
MInt p = 0; (unsigned)p < result.size(); p++) {
34411 for(
MInt v = 0; (unsigned)v < result[p].vertices.size(); v++) {
34412 MInt vertexId = result[p].vertices[v].vertexId;
34413 if(vertexId == -1) {
34415 MBool vertexFound =
false;
34416 MInt vertexIndex = -1;
34417 for(
MInt i = 0; (unsigned)i < vertices_result.size(); i++) {
34419 coord_diff += (result[p].vertices[v].pos.xx[0] - vertices_result[i].coordinates[0])
34420 * (result[p].vertices[v].pos.xx[0] - vertices_result[i].coordinates[0]);
34421 coord_diff += (result[p].vertices[v].pos.xx[1] - vertices_result[i].coordinates[1])
34422 * (result[p].vertices[v].pos.xx[1] - vertices_result[i].coordinates[1]);
34424 if(coord_diff <
m_eps * 10) {
34425 vertexFound =
true;
34431 result[p].vertices[v].vertexId = vertexIndex;
34432 result[p].vertices[v].setIndex = -1;
34434 vertices_result.push_back(
polyVertex(-1, 3));
34435 vertices_result[noVertices].coordinates[0] = result[p].vertices[v].pos.xx[0];
34436 vertices_result[noVertices].coordinates[1] = result[p].vertices[v].pos.xx[1];
34437 result[p].vertices[v].vertexId = noVertices;
34438 result[p].vertices[v].setIndex = -1;
34445 vertices[startSetIndex].swap(vertices_result);
34446 vertices_result.clear();
34447 edges[startSetIndex].clear();
34451 for(
MInt p = 0; (unsigned)p < result.size(); p++) {
34452 MInt bId = result[p].bodyId;
34453 MInt eId = result[p].faceId;
34454 MInt eType = result[p].faceType;
34457 for(
MInt v = 0; (unsigned)v < result[p].vertices.size() - 1; v++) {
34458 MInt j = (v + 1) % result[p].vertices.size();
34459 MInt vertexId = result[p].vertices[v].vertexId;
34460 MInt vertexIdNext = result[p].vertices[j].vertexId;
34461 MBool edgeFound =
false;
34462 for(
MInt e = 0; (unsigned)e < edges[startSetIndex].size(); e++) {
34463 MInt v0 = edges[startSetIndex][e].vertices[0];
34464 MInt v1 = edges[startSetIndex][e].vertices[1];
34465 if(vertexId == v0 && vertexIdNext == v1) {
34468 }
else if(vertexId == v1 && vertexIdNext == v0) {
34474 edges[startSetIndex].push_back(
polyEdge2D(vertexId, vertexIdNext, eId, eType, bId));
34475 vertices[startSetIndex][vertexId].edges.push_back(noEdges);
34476 vertices[startSetIndex][vertexIdNext].edges.push_back(noEdges);
34477 edges[startSetIndex][noEdges].normal[0] = result[p].plane.normal.xx[0];
34478 edges[startSetIndex][noEdges].normal[1] = result[p].plane.normal.xx[1];
34479 edges[startSetIndex][noEdges].w = -result[p].plane.w;
34489 for(
MInt v = 0; (unsigned)v < vertices[startSetIndex].size(); v++) {
34490 if(vertices[startSetIndex][v].edges.size() == 2)
continue;
34491 cerr <<
" Error on cell " << cellId <<
". Cell has vertex with not 2 edges... " << v <<
"/"
34492 << vertices[startSetIndex][v].edges.size() << endl;
34493 writeVTKFileOfCell(cellId, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34494 outputPolyData(cellId, &cutCells, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34495 ASSERT(vertices[startSetIndex][v].edges.size() == 2,
"");
34499 if(edges[startSetIndex].size() == 0) {
34502 for(
MInt edgeCounter = 0; (unsigned)edgeCounter < edges[startSetIndex].size(); edgeCounter++) {
34503 if(edges[startSetIndex][edgeCounter].cutCell > -1)
continue;
34504 edgeStack.push(edgeCounter);
34505 MInt currentCutCell = cutCells.size();
34507 edges[startSetIndex][edgeCounter].cutCell = currentCutCell;
34508 cutCells[currentCutCell].faces_edges.push_back(edgeCounter);
34509 while(!edgeStack.empty()) {
34510 MInt currentEdge = edgeStack.top();
34512 MInt vertex = edges[startSetIndex][currentEdge].vertices[1];
34513 MInt otherEdge = vertices[startSetIndex][vertex].edges[0];
34514 if(otherEdge == currentEdge) otherEdge = vertices[startSetIndex][vertex].edges[1];
34515 if(edges[startSetIndex][otherEdge].cutCell == -1) {
34516 cutCells[currentCutCell].faces_edges.push_back(otherEdge);
34517 edges[startSetIndex][otherEdge].cutCell = currentCutCell;
34518 edgeStack.push(otherEdge);
34530 if(cutCells.size() > 1) {
34531 cerr <<
"split cell detected. These are not implemented in MB framework yet. cell " << cellId << endl;
34532 writeVTKFileOfCell(cellId, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34533 outputPolyData(cellId, &cutCells, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34534 mTerm(1, AT_,
"split cell detected. These are not implemented in MB framework yet. exiting...");
34537 MInt noFacesPerCartesianFace[6] = {0, 0, 0, 0};
34538 MInt noBodySurfaces = 0;
34539 for(
MInt e = 0; (unsigned)e < cutCells[0].faces_edges.size(); e++) {
34540 MInt edge = cutCells[0].faces_edges[e];
34541 if(edges[startSetIndex][edge].edgeType == 0 || edges[startSetIndex][edge].edgeType == 1)
34542 noFacesPerCartesianFace[edges[startSetIndex][edge].edgeId]++;
34547 if(noFacesPerCartesianFace[i] > 1) {
34548 cerr <<
"split face detected. These are not implemented in MB framework yet. cell " << cellId <<
", face " << i
34550 writeVTKFileOfCell(cellId, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34551 writeVTKFileOfCutCell(cellId, &cutCells, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34552 outputPolyData(cellId, &cutCells, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34553 mTerm(1, AT_,
" split face detected. These are not implemented in MB framework yet. exiting...");
34558 cerr <<
"more than FvBndryCell<2,SysEqn>::m_maxNoSurfaces cut surfaces detected for a cell. This is not "
34560 "in MB framework yet. cell "
34562 writeVTKFileOfCell(cellId, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34563 writeVTKFileOfCutCell(cellId, &cutCells, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34564 outputPolyData(cellId, &cutCells, &edges[startSetIndex], &vertices[startSetIndex], startSetIndex);
34566 " more than 3 cut surfaces detected for a cell. This is not implemented in MB framework yet. "
34574 if(cutCells[0].faces_edges.size() == 0) {
34576 a_hasProperty(cellId, SolverCell::IsOnCurrentMGLevel) =
false;
34577 cutCells[0].volume = F0;
34582 ASSERT(!(cutCells[0].volume < F0),
"");
34583 ASSERT(!(std::isnan(cutCells[0].volume)),
"");
34584 ASSERT(!(std::isnan(cutCells[0].center[0])),
"");
34585 ASSERT(!(std::isnan(cutCells[0].center[1])),
"");
34586 ASSERT(!(std::isinf(cutCells[0].volume)),
"");
34587 ASSERT(!(std::isinf(cutCells[0].center[0])),
"");
34588 ASSERT(!(std::isinf(cutCells[0].center[1])),
"");
34592 if(noFacesPerCartesianFace[f] == 0) {
34604 MInt nghbrBndryId = -1;
34605 if(nghbrId > -1) nghbrBndryId =
a_bndryId(nghbrId);
34607 if(nghbrBndryId > -1) {
34615 ASSERT(vertices[startSetIndex].size() <= (
unsigned)maxNoVertices,
"");
34616 for(
MInt cp = 0; cp < maxNoVertices; cp++)
34617 newCutPointId[cp] = -1;
34618 for(
MInt i = 0; (unsigned)i < vertices[startSetIndex].size(); i++)
34619 isPartOfBodySurface[i] =
false;
34623 noBodySurfaces = 0;
34624 bndryCell->
m_volume = cutCells[0].volume;
34627 for(
MInt f = 0; (unsigned)f < cutCells[0].faces_edges.size(); f++) {
34628 MInt edge = cutCells[0].faces_edges[f];
34629 ASSERT(!(edges[startSetIndex][edge].area < F0),
"");
34630 ASSERT(!(std::isnan(edges[startSetIndex][edge].area)),
"");
34631 ASSERT(!(std::isnan(edges[startSetIndex][edge].center[0])),
"");
34632 ASSERT(!(std::isnan(edges[startSetIndex][edge].center[1])),
"");
34633 ASSERT(!(std::isinf(edges[startSetIndex][edge].area)),
"");
34634 ASSERT(!(std::isinf(edges[startSetIndex][edge].center[0])),
"");
34635 ASSERT(!(std::isinf(edges[startSetIndex][edge].center[1])),
"");
34637 if(edges[startSetIndex][edge].edgeType > 1) {
34639 bodySurface->
m_area = edges[startSetIndex][edge].area;
34641 bodySurface->
m_coordinates[i] = edges[startSetIndex][edge].center[i];
34642 bodySurface->
m_normalVector[i] = edges[startSetIndex][edge].normal[i];
34646 for(
MInt cp = 0; (unsigned)cp < 2; cp++) {
34647 MInt vertex = edges[startSetIndex][edge].vertices[cp];
34648 isPartOfBodySurface[vertex] =
true;
34649 MInt cutPointId = vertices[startSetIndex][vertex].pointId;
34650 newCutPointId[vertex] = cp;
34651 vertices[startSetIndex][vertex].cartSrfcId = noBodySurfaces;
34653 bodySurface->
m_cutCoordinates[cp][i] = vertices[startSetIndex][vertex].coordinates[i];
34654 if(cutPointId > -1) {
34655 bodySurface->
m_cutEdge[cp] = pointEdgeId[cutPointId];
34656 bodySurface->
m_bodyId[cp] = edges[startSetIndex][edge].bodyId;
34659 bodySurface->
m_bodyId[cp] = edges[startSetIndex][edge].bodyId;
34664 MInt dirId = edges[startSetIndex][edge].edgeId;
34674 m_cutFaceArea[bndryId][dirId] = edges[startSetIndex][edge].area;
34677 MInt nghbrBndryId = -1;
34678 if(nghbrId > -1) nghbrBndryId =
a_bndryId(nghbrId);
34679 if(nghbrBndryId > -1) {
34688 for(
MInt srfc = 0; srfc <
m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs; srfc++) {
34695 const MInt maxPointsXD = 12;
34696 for(
MInt c = 0; (unsigned)c < cutCells.size(); c++) {
34699 for(
MInt f = 0; (unsigned)f < cutCells[c].faces_edges.size(); f++) {
34700 MInt edge = cutCells[c].faces_edges[f];
34701 MInt vertex = edges[startSetIndex][edge].vertices[0];
34702 if(vertices[startSetIndex][vertex].
pointType == 0) {
34704 vertices[startSetIndex][vertex].pointId;
34707 if(!isPartOfBodySurface[vertex])
continue;
34708 MInt numCutPointsPreviousFaces = 0;
34709 for(
MInt srfc = 0; srfc < vertices[startSetIndex][vertex].cartSrfcId; srfc++) {
34710 numCutPointsPreviousFaces +=
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_noCutPoints;
34712 MInt cp = numCutPointsPreviousFaces + newCutPointId[vertex];
34731template <MInt nDim,
class SysEqn>
34733 std::vector<std::bitset<64>>& sensorCellFlag,
34734 std::vector<MFloat>& sensorWeight,
MInt sensorOffset,
MInt sen) {
34736 this->
patchRefinement(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen);
34742 const MFloat duration = 5;
34748 cerr <<
"Setting sensor Patch-refinement for current CA!" << endl;
34751 this->
patchRefinement(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen);
34753 const MInt valveBodyId = 2;
34756 const MInt gridCellId =
grid().tree().solver2grid(cellId);
34757 if(sensors[sensorOffset + sen][gridCellId] > 0) {
34759 if(fabs(valveDist) < 0.06757)
continue;
34760 sensors[sensorOffset + sen][gridCellId] = 0;
34761 sensorCellFlag[gridCellId][sensorOffset + sen] = 0;
34764 sensors[sensorOffset + sen][gridCellId] = 1;
34765 sensorCellFlag[gridCellId][sensorOffset + sen] = 1;
34770 cerr <<
"Surpressing Patch-refinement for current CA!" << endl;
34784template <MInt nDim,
class SysEqn>
34788 vector<MInt> deletedBndryCells;
34789 vector<MInt> bndryChilds;
34790 std::map<MInt, MFloat> childBndryCells;
34791 std::map<MInt, MFloat> haloBndryCells;
34794 MPI_Allreduce(MPI_IN_PLACE, &noRefOldBndryCells, 1, MPI_INT, MPI_SUM,
mpiComm(), AT_,
"MPI_IN_PLACE",
34795 "noRefOldBndryCells");
34797 if(noRefOldBndryCells == 0)
return;
34799 m_log <<
"Correcting newly refined BndryCells after adaptation ...";
34803 noRelevantChilds.
fill(-1);
34805 vector<MInt> refOldBndryCellsNew;
34835 refOldBndryCellsNew.push_back(cellId);
34838 MInt noBndryCellChilds = 0;
34842 if(child == -1)
continue;
34845 ASSERT(noBndryCellChilds > 0,
"");
34846 noRelevantChilds(cellId) = noBndryCellChilds;
34854 m_rhs0[cellId][v] =
m_rhs0[parent][v] / noBndryCellChilds;
34868 MInt noBndryCellChilds = noRelevantChilds(cellId);
34871 m_rhs0[cellId][v] =
m_rhs0[parent][v] / noBndryCellChilds;
34879 for(
MInt it = 0; it < (signed)refOldBndryCellsNew.size(); it++) {
34880 const MInt cellId = refOldBndryCellsNew[it];
34884 m_log <<
" Finished" << endl;
34892template <MInt nDim,
class SysEqn>
34907 MFloat nml =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
34908 dV -= dt *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[
PV->VV[i]] * nml * area;
34931template <MInt nDim,
class SysEqn>
34936 const MInt cellId = *it;
34946 MFloat nml =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_normalVector[i];
34947 dV -= dt *
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcVariables[srfc]->m_primVars[
PV->VV[i]] * nml * area;
34972template <MInt nDim,
class SysEqn>
34973template <
class _, std::enable_if_t<nDim == 3, _*>>
34979 const MInt DOFStencil[12] = {1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 2, 2};
34980 NEW_SUB_TIMER_STATIC(tCutFace_00,
"cutFaceNew_00",
m_tCutGroup);
34981 RECORD_TIMER_START(tCutFace_00);
34984 std::vector<CC> cutCellData;
34986 std::vector<MInt> cutCellIdMapping;
34989 cutCellIdMapping[i] = -1;
34997 const MInt faceCornerMapping[6][4] = {{2, 6, 4, 0}, {1, 5, 7, 3}, {0, 4, 5, 1},
34998 {3, 7, 6, 2}, {2, 3, 1, 0}, {6, 7, 5, 4}};
35001 cutCellData.emplace_back();
35002 cutCellData[cnt].cellId = cellId;
35003 cutCellData[cnt].isGapCell =
false;
35004 cutCellIdMapping[cellId] = cnt;
35006 cutCellData[cnt].isGapCell = (
a_hasProperty(cellId, SolverCell::IsGapCell));
35008 ASSERT(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints <= CC::maxNoCutPoints,
"");
35009 cutCellData[cnt].noCutPoints =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints;
35010 for(
MInt cp = 0; cp <
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_noCutPoints; cp++) {
35011 const MInt cutEdge =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutEdge[cp];
35012 const MInt nonZeroDir = DOFStencil[cutEdge];
35015 MFloat cutCoordinate =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutCoordinates[cp][k];
35019 const MFloat cellHalfLength = F1B2 * cellLength;
35020 cutCoordinate = (cutCoordinate -
a_coordinate(cellId, k)) / cellHalfLength;
35022 if(k != nonZeroDir) {
35024 if(cutCoordinate > F0) {
35025 cutCoordinate = F1;
35027 cutCoordinate = -F1;
35031 if(cutCoordinate > F1 - 20 *
m_eps) cutCoordinate = F1 - 20 *
m_eps;
35032 if(cutCoordinate < -F1 + 20 *
m_eps) cutCoordinate = -F1 + 20 *
m_eps;
35035 cutCellData[cnt].cutPoints[cp][k] = cutCoordinate;
35039 cutCellData[cnt].cutBodyIds[cp] =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_bodyId[cp];
35040 cutCellData[cnt].cutEdges[cp] =
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutEdge[cp];
35043 if(cndId < 0)
mTerm(1, AT_,
"error: cell is not a bndryCandidate!");
35046 for(
MInt k = 0; k < CC::noCorners; k++) {
35048 cutCellData[cnt].cornerIsInsideGeometry[set][k] =
m_pointIsInside[bndryId][IDX_LSSETMB(k, set)];
35050 for(
MInt k = 0; k < CC::noFaces; k++) {
35052 for(
MInt j = 0; j < 4; j++) {
35055 cutCellData[cnt].faceCentroidIsInsideGeometry[set][k] = (phi < F0);
35061 const MUint noCutCells = cutCellData.size();
35065 MBool debugOutput =
false;
35067 MInt cutCellId = 10;
35068 MInt neighborCutCellId = 30;
35069 MInt neighbrId = cutCellData[neighborCutCellId].cellId;
35071 MInt cellId = cutCellData[cutCellId].cellId;
35074 cerr <<
"Found " << cutCellData[cutCellId].noCutPoints <<
" Cut-Points for CellId " << cellId << endl;
35075 cerr <<
"Cut edges are: " << endl;
35076 for(
MInt cp = 0; cp < cutCellData[cutCellId].noCutPoints; cp++) {
35077 cerr <<
" Cut-Point " << cp <<
" " << cutCellData[cutCellId].cutEdges[cp] << endl;
35080 cerr <<
"Corner-values are: " << endl;
35082 for(
MInt k = 0; k < CC::noCorners; k++) {
35088 cerr <<
"Found " << cutCellData[neighborCutCellId].noCutPoints <<
" Cut-Points for neighborCutCellId " << neighbrId
35090 cerr <<
"Cut edges are: " << endl;
35091 for(
MInt cp = 0; cp < cutCellData[neighborCutCellId].noCutPoints; cp++) {
35092 cerr <<
" Cut-Point " << cp <<
" " << cutCellData[neighborCutCellId].cutEdges[cp] << endl;
35097 cerr <<
"Corner-values are: " << endl;
35099 for(
MInt k = 0; k < CC::noCorners; k++) {
35107 for(
MUint cutc = 0; cutc < noCutCells; cutc++) {
35109 if(cutCellData[cutc].noCutPoints <
nDim) {
35110 mTerm(1, AT_,
"CutCell with less than nDim CutPoints");
35123 for(
MInt set = startSet; set < endSet; set++) {
35124 for(
MInt k = 0; k < CC::noCorners; k++) {
35125 if(cutCellData[cutc].cornerIsInsideGeometry[set][k]) {
35129 "ERROR in " + to_string(
domainId()) +
" " + to_string(cutCellData[cutc].cellId) +
" "
35130 + to_string(
c_globalId(cutCellData[cutc].cellId)) +
" " + to_string(k) +
" "
35137 const MInt maxNoVertices = 300;
35141 splitFaceCellIds[c] = -1;
35143 std::vector<cellWithSplitFace> splitFaceCells;
35148 const MFloat signStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
35149 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
35151 const MInt faceCornerCode[6][4] = {{0, 2, 6, 4},
35152 {3, 1, 5, 7}, {1, 0, 4, 5}, {2, 3, 7, 6}, {0, 1, 3, 2}, {5, 4, 6, 7}};
35154 RECORD_TIMER_STOP(tCutFace_00);
35159 debugOutput =
false;
35160 MInt debugTimeStep = -1;
35161 MInt debugDomainId = 302;
35162 MInt debugCellId = 23192;
35163 MInt debugNeighborId = 23160;
35169 MInt debugCutCellId = -1;
35170 MInt debugNeighborCutCellId = -1;
35174 cerr <<
"Debug-Surface-Id is " << debugSrfcId <<
" with " << endl;
35178 if(debugSrfcId > -1) {
35186 for(
MUint cutc = 0; cutc < noCutCells; cutc++) {
35187 if(cutCellData[cutc].cellId == debugNeighborId) {
35188 cerr <<
"Neighbor CutCellId " << cutc << endl;
35189 debugNeighborCutCellId = cutc;
35191 if(cutCellData[cutc].cellId == debugCellId) {
35192 cerr <<
"Cell CutCellId " << cutc << endl;
35193 debugCutCellId = cutc;
35200 cerr <<
"Cell-Set: " << cellSet;
35201 cerr <<
"Neighbor-Set: " << neighborSet;
35203 if(debugCutCellId > -1) {
35204 cerr <<
"Cell-CutCellInfo " << cutCellData[debugCutCellId].cellId <<
" has "
35205 << cutCellData[debugCutCellId].noSplitChilds <<
" SplitChilds and "
35206 << cutCellData[debugCutCellId].noFacesPerCartesianDir[debugDir] <<
" Faces in the debug-Direction!"
35207 <<
"The ls-vales of the face are: " << endl;
35209 for(
MInt corner = 0; corner < 4; corner++) {
35210 cerr << set <<
" " << setprecision(16)
35212 faceCornerCode[debugDir][corner], set)];
35218 if(debugNeighborCutCellId) {
35219 cerr <<
"Neighbor-CutCellInfo " << cutCellData[debugNeighborCutCellId].cellId <<
" has "
35220 << cutCellData[debugNeighborCutCellId].noSplitChilds <<
" SplitChilds and "
35221 << cutCellData[debugNeighborCutCellId].noFacesPerCartesianDir[reverseDir]
35222 <<
" Faces in the reverse-debug-Direction!"
35223 <<
"The ls-vales of the face are: " << endl;
35225 for(
MInt corner = 0; corner < 4; corner++) {
35226 cerr << set <<
" " << setprecision(16)
35228 faceCornerCode[reverseDir][corner], set)];
35240 NEW_SUB_TIMER_STATIC(tCutFace_8,
"cutFaceNew_8",
m_tCutGroup);
35241 NEW_SUB_TIMER_STATIC(tCutFace_9,
"cutFaceNew_9",
m_tCutGroup);
35242 NEW_SUB_TIMER_STATIC(tCutFace_10,
"cutFaceNew_10",
m_tCutGroup);
35244 RECORD_TIMER_START(tCutFace_8);
35247 for(
MUint cutc = 0; cutc < noCutCells; cutc++) {
35248 const MInt cellId = cutCellData[cutc].cellId;
35250 MInt noSplitChildren = cutCellData[cutc].noSplitChilds;
35252 MInt splitCellId = -1;
35253 if(noSplitChildren > 1) {
35256 for(
MInt sc = 0; sc < noSplitChildren; sc++) {
35257 MUint splitcutc = cutCellData[cutc].splitChildIds[sc];
35260 cutCellData[splitcutc].cellId = splitChildId;
35263 splitCellIds(bndryId) = splitCellId;
35268 for(
MUint cutc = 0; cutc < cutCellData.size(); cutc++) {
35269 const MInt cellId = cutCellData[cutc].cellId;
35272 const MFloat cellHalfLength = F1B2 * cellLength;
35274 for(
MInt cpId = 0; cpId < cutCellData[cutc].noCutPoints; cpId++) {
35276 cutCellData[cutc].cutPoints[cpId][i] =
35277 cutCellData[cutc].cutPoints[cpId][i] * cellHalfLength +
a_coordinate(cellId, i);
35279 ASSERT(fabs(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[0]->m_cutCoordinates[cpId][i]
35280 - cutCellData[cutc].cutPoints[cpId][i])
35286 cutCellData[cutc].volume = cutCellData[cutc].volume *
POW3(cellHalfLength);
35287 if(cutCellData[cutc].volume <
m_eps) cutCellData[cutc].volume =
m_eps;
35292 cutCellData[cutc].volumetricCentroid[i] = cutCellData[cutc].volumetricCentroid[i] * cellHalfLength;
35295 for(
MInt bs = 0; bs < cutCellData[cutc].noBoundarySurfaces; bs++) {
35297 cutCellData[cutc].boundarySurfaceCentroid[bs][i] =
35298 cutCellData[cutc].boundarySurfaceCentroid[bs][i] * cellHalfLength +
a_coordinate(cellId, i);
35300 cutCellData[cutc].boundarySurfaceArea[bs] = cutCellData[cutc].boundarySurfaceArea[bs] *
POW2(cellHalfLength);
35302 if(cutCellData[cutc].boundarySurfaceArea[bs] <
m_eps) cutCellData[cutc].boundarySurfaceArea[bs] =
m_eps;
35306 for(
MInt cs = 0; cs < cutCellData[cutc].noCartesianSurfaces; cs++) {
35308 cutCellData[cutc].cartFaceCentroid[cs][i] =
35309 cutCellData[cutc].cartFaceCentroid[cs][i] * cellHalfLength +
a_coordinate(cellId, i);
35311 cutCellData[cutc].cartFaceArea[cs] = cutCellData[cutc].cartFaceArea[cs] *
POW2(cellHalfLength);
35313 if(cutCellData[cutc].cartFaceArea[cs] <
m_eps) cutCellData[cutc].cartFaceArea[cs] =
m_eps;
35316 for(
MInt aId = 0; aId < cutCellData[cutc].noAdditionalVertices; aId++) {
35318 cutCellData[cutc].additionalVertices[aId][i] =
35319 cutCellData[cutc].additionalVertices[aId][i] * cellHalfLength +
a_coordinate(cellId, i);
35327 for(
MUint cutc = 0; cutc < cutCellData.size(); cutc++) {
35329 const MInt cellId = cutCellData[cutc].cellId;
35331 MInt splitParentId = cutCellData[cutc].splitParentId;
35332 MInt noSplitChilds = cutCellData[cutc].noSplitChilds;
35334 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId != cutCellData[cutc].cellId) {
35335 cerr <<
domainId() <<
": diff0 " << cutc <<
" " << noSplitChilds <<
" " << splitParentId <<
" "
35336 <<
m_fvBndryCnd->m_bndryCells->a[bndryId].m_cellId <<
" " << cutCellData[cutc].cellId << endl;
35339 bndryCell->
m_volume = cutCellData[cutc].volume;
35341 bndryCell->
m_coordinates[i] = cutCellData[cutc].volumetricCentroid[i];
35343 MInt noSrfcs = cutCellData[cutc].noBoundarySurfaces;
35345 for(
MInt bs = 0; bs < noSrfcs; bs++) {
35348 bodySurface->
m_coordinates[i] = cutCellData[cutc].boundarySurfaceCentroid[bs][i];
35349 bodySurface->
m_normalVector[i] = cutCellData[cutc].boundarySurfaceNormal[bs][i];
35351 bodySurface->
m_area = cutCellData[cutc].boundarySurfaceArea[bs];
35355 bodySurface->
m_bndryCndId = cutCellData[cutc].boundarySurfaceBndryCndId[bs];
35356 bodySurface->
m_bodyId[0] = cutCellData[cutc].boundarySurfaceBodyId[bs];
35358 for(
MInt f = 0; f < 2 *
nDim; f++) {
35362 m_pointIsInside[bndryId][IDX_LSSETMB(c, 0)] = cutCellData[cutc].cornerIsInsideGeometry[0][c];
35367 for(
MUint cutc = 0; cutc < noCutCells; cutc++) {
35369 const MInt cellId = cutCellData[cutc].cellId;
35373 const MFloat cellHalfLength = F1B2 * cellLength0;
35374 MInt noSplitChildren = cutCellData[cutc].noSplitChilds;
35375 MInt splitCellId = splitCellIds(bndryId);
35384 if(noSplitChildren > 1) {
35385 ASSERT(splitCellId > -1,
"");
35386 for(
MInt sc = 0; sc < noSplitChildren; sc++) {
35387 splitCellList[sc] = cutCellData[cutc].splitChildIds[sc];
35390 noSplitChildren = 1;
35391 splitCellList[0] = cutc;
35398 if(noSplitChildren > 1) {
35407 if(debugOutput &&
globalTimeStep == debugTimeStep &&
domainId() == debugDomainId && srfcId == debugSrfcId) {
35408 cerr <<
"Accesing Debug-surface! Nghbrs are : " << nghbr0 <<
" " << nghbr1 <<
"Due to " << noSplitChildren
35409 <<
"splitChilds at CutCellId " << cellId << endl;
35412 if(nghbr0 == cellId) {
35415 }
else if(nghbr1 == cellId) {
35421 if(nghbr0 < 0 && nghbr1 < 0) {
35434 for(
MInt sc = 0; sc < noSplitChildren; sc++) {
35435 MInt splitChildId = cellId;
35436 MInt scBndryId = bndryId;
35438 if(splitCellId > -1) {
35441 scBndryCell = &
m_fvBndryCnd->m_bndryCells->a[scBndryId];
35443 ASSERT(scBndryId > -1,
" ");
35445 MInt cutCellId = splitCellList[sc];
35446 if(noSplitChildren == 1) ASSERT(cutCellId == (
MInt)cutc,
"");
35447 ASSERT(cutCellData[cutCellId].cellId == splitChildId,
"");
35452 if(cutCellData[cutCellId].noFacesPerCartesianDir[i] > 1) {
35457 MInt id = splitFaceCellIds[scBndryId];
35459 id = splitFaceCells.
size();
35460 splitFaceCells.push_back(cellWithSplitFace(splitChildId));
35461 splitFaceCellIds[scBndryId] =
id;
35463 cellWithSplitFace* scsCell = &splitFaceCells[
id];
35464 scsCell->splitFaces.push_back(splitCartesianFace(i));
35474 if(debugOutput &&
globalTimeStep == debugTimeStep &&
domainId() == debugDomainId && srfcId == debugSrfcId) {
35475 cerr <<
"Accesing Debug-surface! Nghbrs are : " << nghbr0 <<
" " << nghbr1 <<
"with CutCellId"
35476 << cutCellId <<
"due to " << cutCellData[cutCellId].noFacesPerCartesianDir[i]
35477 <<
" faces in direction " << i << endl;
35480 if(nghbr0 == splitChildId) {
35483 }
else if(nghbr1 == splitChildId) {
35487 if(nghbr0 < 0 && nghbr1 < 0) {
35499 if(cutCellData[cutCellId].noCartesianSurfaces == 0 && cutCellData[cutCellId].noBoundarySurfaces == 0) {
35500 a_hasProperty(splitChildId, SolverCell::IsInactive) =
true;
35501 a_hasProperty(splitChildId, SolverCell::IsOnCurrentMGLevel) =
false;
35508 if(cutCellData[cutCellId].noFacesPerCartesianDir[f] == 0) {
35511 if(splitCellId < 0) {
35514 if(debugOutput &&
globalTimeStep == debugTimeStep &&
domainId() == debugDomainId && srfcId == debugSrfcId
35516 cerr <<
"Deleting surface " << srfcId <<
" on accord of " << cellId <<
" with zero faces in direction "
35517 << f <<
" is externalFace instead " << cutCellData[cutCellId].externalFaces[f] << endl;
35519 cerr <<
"Cell is an original SplitCell: " << splitCellId <<
" with "
35520 << cutCellData[cutCellId].noSplitChilds <<
" # of SplitChildren and "
35521 << cutCellData[cutCellId].noCartesianSurfaces <<
" Totalfaces. " << endl;
35532 MInt nghbrBndryId = -1;
35533 if(nghbrId > -1) nghbrBndryId =
a_bndryId(nghbrId);
35534 if(nghbrBndryId > -1) {
35543 for(
MInt srf = 0; srf < cutCellData[cutCellId].noCartesianSurfaces; srf++) {
35544 MInt dirId = cutCellData[cutCellId].cartFaceDir[srf];
35549 if(cutCellData[cutCellId].noFacesPerCartesianDir[dirId] > 1) {
35551 MInt sfCellId = splitFaceCellIds[scBndryId];
35552 cellWithSplitFace* sfCell = &splitFaceCells[sfCellId];
35555 for(
MInt s = 0; (unsigned)s < sfCell->splitFaces.size(); s++) {
35556 MInt sfDir = sfCell->splitFaces[s].direction;
35557 if(sfDir == dirId) {
35562 ASSERT(sf > -1,
"");
35563 ASSERT(srfcId < 0,
"");
35567 MBool createSrfc =
true;
35571 createSrfc =
false;
35574 createSrfc =
false;
35580 sfCell->splitFaces[sf].srfcIds.push_back(srfcId);
35583 }
else if(splitCellId > -1) {
35585 ASSERT(srfcId < 0,
"");
35589 MBool createSrfc =
true;
35594 createSrfc =
false;
35597 createSrfc =
false;
35612 a_surfaceArea(srfcId) = cutCellData[cutCellId].cartFaceArea[srf];
35614 if(cutCellData[cutCellId].noFacesPerCartesianDir[dirId] == 1) {
35627 MBool foundNgbrSrfc =
false;
35629 if(!childCode[dirId][child])
continue;
35631 if(childId < 0)
continue;
35632 if(
a_hasProperty(childId, SolverCell::IsInactive))
continue;
35633 if(
a_hasProperty(childId, SolverCell::IsNotGradient))
continue;
35637 if(cutCellIdMapping[childId] > 0
35638 && cutCellData[cutCellIdMapping[childId]].noFacesPerCartesianDir[
m_revDir[dirId]] > 0) {
35641 foundNgbrSrfc =
true;
35653 foundNgbrSrfc =
true;
35657 if(foundNgbrSrfc)
continue;
35660 if(cutCellData[cutCellId].cartFaceArea[srf] <
m_eps * 10 && !cutCellData[cutCellId].externalFaces[dirId]) {
35662 <<
" has small surface inconsistency which is ignored!" << endl;
35667 if(splitCellId <= -1 && cutCellData[cutCellId].noFacesPerCartesianDir[dirId] == 1) {
35668 cerr <<
"ERROR, Found a Cell which is not a splitCell, has one faces in the current direction, yet the "
35669 "Cell-Surface-Mapping is broken!"
35672 cerr <<
"Debug-Setting: " << endl;
35674 cerr <<
"- debugDomainId = " <<
domainId() << endl;
35675 cerr <<
"- debugCellId = " << cellId << endl;
35676 cerr <<
"- debugNeighborId = " <<
c_neighborId(cellId, dirId) << endl;
35677 cerr <<
"- debugDir = " << dirId << endl;
35679 cerr <<
"Surf-Area is " << cutCellData[cutCellId].cartFaceArea[srf] << endl;
35681 cerr <<
" domain " <<
domainId() <<
" cellId " << cellId <<
" (" <<
c_globalId(cellId) <<
") CutCellId "
35682 << cutCellId <<
" splitchildId " << splitChildId <<
" has no surface in dir " << dirId << endl;
35684 cerr <<
"However the cell has " << cutCellData[cutCellId].noFacesPerCartesianDir[dirId]
35685 <<
" Faces in the current direction! "
35686 <<
" And other Faces: " << cutCellData[cutCellId].noFacesPerCartesianDir[0] <<
" "
35687 << cutCellData[cutCellId].noFacesPerCartesianDir[1] << cutCellData[cutCellId].noFacesPerCartesianDir[2]
35688 <<
" " << cutCellData[cutCellId].noFacesPerCartesianDir[3] <<
" "
35689 << cutCellData[cutCellId].noFacesPerCartesianDir[4] <<
" "
35690 << cutCellData[cutCellId].noFacesPerCartesianDir[5] <<
" " << endl;
35692 cerr <<
"Instead the cell has an external-Face (Solid) in the direction: "
35693 << cutCellData[cutCellId].externalFaces[dirId] << endl;
35695 cerr <<
"Cell is an original SplitCell: " << splitCellId <<
" with " << cutCellData[cutCellId].noSplitChilds
35696 <<
" # of SplitChildren and " << cutCellData[cutCellId].noCartesianSurfaces <<
" Totalfaces. " << endl;
35698 cerr <<
"The corner-ls-values of the considered Cell-Face are: " << endl;
35699 for(
MInt corner = 0; corner < 4; corner++) {
35700 cerr <<
" " << setprecision(16)
35712 cerr <<
" Cell is " <<
a_hasProperty(cellId, SolverCell::IsGapCell) <<
" GapCell and the neighbor is "
35714 cerr <<
"Complete corner ls-values: " << endl;
35715 for(
MInt corner = 0; corner < 8; corner++) {
35716 cerr <<
" " << setprecision(16)
35724 mTerm(1, AT_,
"This was not supposed to happen - where is my surface?!?");
35733 MInt nghbrBndryId = -1;
35734 if(splitCellId < 0 && cutCellData[cutCellId].noFacesPerCartesianDir[dirId] == 1) {
35735 if(nghbrId > -1) nghbrBndryId =
a_bndryId(nghbrId);
35737 if(nghbrBndryId > -1) {
35742 if(nghbrId > -1) nghbrBndryId =
a_bndryId(nghbrId);
35749 MBool needFaceStream =
false;
35750 if(
a_hasProperty(splitChildId, SolverCell::HasSplitFace) || cutCellData[cutCellId].noBoundarySurfaces > 1
35751 || cutCellData[cutCellId].noAdditionalVertices > 0)
35752 needFaceStream =
true;
35754 needFaceStream =
true;
35757 if(needFaceStream) {
35758 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceVertices.clear();
35759 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceStream.resize(cutCellData[cutCellId].noTotalFaces);
35760 MInt vertexMap[maxNoVertices];
35761 fill_n(vertexMap, maxNoVertices, -1);
35763 for(
MInt faceType = 1; faceType >= 0; faceType--) {
35764 for(
MInt f = 0; f < cutCellData[cutCellId].noTotalFaces; f++) {
35765 if((faceType == 0) && (cutCellData[cutCellId].allFacesBodyId[f] > -1))
continue;
35766 if((faceType == 1) && (cutCellData[cutCellId].allFacesBodyId[f] < 0))
continue;
35767 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceStream[fcnt].resize(0);
35768 for(
MInt p = 0; p < cutCellData[cutCellId].allFacesNoPoints[f]; p++) {
35769 MInt pointId = cutCellData[cutCellId].allFacesPointIds[f][p];
35770 ASSERT(pointId > -1 && pointId < maxNoVertices,
"");
35771 if(vertexMap[pointId] < 0) {
35772 vertexMap[pointId] = (signed)
m_fvBndryCnd->m_bndryCell[scBndryId].m_faceVertices.size() /
nDim;
35773 if(pointId < CC::noCorners) {
35775 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceVertices.push_back(
35776 a_coordinate(cellId, i) + signStencil[pointId][i] * cellHalfLength);
35778 }
else if(pointId < CC::noCorners + CC::maxNoCutPoints) {
35779 MInt cpId = pointId - CC::noCorners;
35781 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceVertices.push_back(cutCellData[cutc].cutPoints[cpId][i]);
35784 MInt aId = pointId - CC::noCorners - CC::maxNoCutPoints;
35785 ASSERT(aId < cutCellData[cutCellId].noAdditionalVertices,
"");
35787 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceVertices.push_back(
35788 cutCellData[cutCellId].additionalVertices[aId][i]);
35792 ASSERT(fcnt < cutCellData[cutCellId].noTotalFaces,
"");
35793 m_fvBndryCnd->m_bndryCell[scBndryId].m_faceStream[fcnt].push_back(vertexMap[pointId]);
35804 if(splitCellId > -1) {
35807 if(cutCellData[cutc].noFacesPerCartesianDir[dir] == 0) {
35810 MInt srfcId = cellSurfaceMapping_backup[dir];
35821 RECORD_TIMER_STOP(tCutFace_8);
35822 RECORD_TIMER_START(tCutFace_9);
35829 for(
MInt sc = 0; sc < noSplitCells; sc++) {
35834 if(
m_fvBndryCnd->m_bndryCells->a[scBndryId].m_associatedSrfc[d] > -1)
35835 mTerm(1, AT_,
"splitParent cell has a valid surface attached to its boundary cell...");
35846 if(
m_fvBndryCnd->m_bndryCells->a[splitChildBndryId].m_associatedSrfc[d] != srfcId)
35847 mTerm(1, AT_,
"splitChild cell no consistent surface information...");
35848 if(nghbr0 == splitChildId) {
35849 if(nghbr1 > -1)
mTerm(1, AT_,
"splitChild cell has a surface with a valid neighbor attached to it...");
35850 }
else if(nghbr1 == splitChildId) {
35851 if(nghbr0 > -1)
mTerm(1, AT_,
"splitChild cell has a surface with a valid neighbor attached to it...");
35853 mTerm(1, AT_,
"splitChild cell has a surface attached to it which does not point to the cell itself...");
35855 MBool suspicious =
true;
35856 if(
m_fvBndryCnd->m_bndryCells->a[splitChildBndryId].m_externalFaces[d]) {
35857 suspicious =
false;
35861 suspicious =
false;
35865 if(!suspicious)
continue;
35866 MInt sfId = splitFaceCellIds[splitChildBndryId];
35868 cellWithSplitFace* sfCell = &splitFaceCells[sfId];
35869 for(
MInt sff = 0; (unsigned)sff < sfCell->splitFaces.size(); sff++) {
35870 splitCartesianFace* splitFace = &sfCell->splitFaces[sff];
35871 MInt dir = splitFace->direction;
35873 suspicious =
false;
35880 "split cell child has a fluid side which is not split but has no valid surface attached to it!");
35888 MInt noSplitFaceCells = splitFaceCells.size();
35889 for(
MInt sf = 0; sf < noSplitFaceCells; sf++) {
35890 cellWithSplitFace* sfCell = &splitFaceCells[sf];
35891 MInt sfId = sfCell->cellId;
35893 MInt noSplitFaces = sfCell->splitFaces.size();
35894 for(
MInt sff = 0; sff < noSplitFaces; sff++) {
35895 splitCartesianFace* splitFace = &sfCell->splitFaces[sff];
35896 MInt dir = splitFace->direction;
35898 if(srfcId > -1)
mTerm(1, AT_,
"split face has a valid surface attached to it...");
35899 if(
m_fvBndryCnd->m_bndryCells->a[sfBndryId].m_associatedSrfc[dir] > -1)
35900 mTerm(1, AT_,
"split face has a valid surface attached to its boundary cell...");
35901 for(
MInt srfc = 0; (unsigned)srfc < splitFace->srfcIds.size(); srfc++) {
35902 srfcId = splitFace->srfcIds[srfc];
35903 if(srfcId < 0)
mTerm(1, AT_,
"split face part has no surface attached to it...");
35906 if(nghbr0 == sfId) {
35907 if(nghbr1 > -1)
mTerm(1, AT_,
"splitface has a surface with a valid neighbor attached to it...");
35908 }
else if(nghbr1 == sfId) {
35909 if(nghbr0 > -1)
mTerm(1, AT_,
"splitface has a surface with a valid neighbor attached to it...");
35911 mTerm(1, AT_,
"splitface has a surface attached to it which does not point to the cell itself...");
35917 for(
MInt sf = 0; sf < noSplitFaceCells; sf++) {
35918 cellWithSplitFace* sfCell = &splitFaceCells[sf];
35919 const MInt sfId = sfCell->cellId;
35921 const MInt noSplitFaces = sfCell->splitFaces.size();
35927 for(
MInt sff = 0; sff < noSplitFaces; sff++) {
35928 splitCartesianFace* splitFace = &sfCell->splitFaces[sff];
35929 MInt dir = splitFace->direction;
35930 for(
MInt srfc = 0; (unsigned)srfc < splitFace->srfcIds.size(); srfc++) {
35931 MInt srfcId = splitFace->srfcIds[srfc];
35932 ASSERT(srfcId > -1,
"");
35934 if(srfcNeighbor > -1)
35938 if(cellIsSplitChild) {
35944 ASSERT(nghbrId > -1,
"");
35948 MInt splitChildIdN = nghbrId;
35949 MInt noSubCellsN = 1;
35950 MInt splitCellIdN = -1;
35952 splitCellIdN = splitCellIds[
a_bndryId(nghbrId)];
35955 MFloat minXDiff = std::numeric_limits<float>::max();
35956 MInt bestFitSrfc = -1;
35957 MInt bestFitCell = -1;
35958 MInt* bestFitSplitFacePart = (
MInt*)
nullptr;
35960 for(
MInt count = 0; count < noSubCellsN; count++) {
35961 if(splitCellIdN > -1) {
35966 if(srfcIdNghbr > -1) {
35968 if(xDiff < minXDiff) {
35970 bestFitSrfc = srfcIdNghbr;
35971 bestFitCell = splitChildIdN;
35972 bestFitSplitFacePart = (
MInt*)
nullptr;
35975 MInt splitFaceCellNghbrId = splitFaceCellIds[
a_bndryId(splitChildIdN)];
35976 if(splitFaceCellNghbrId < 0)
continue;
35977 for(
MInt sfn = 0; (unsigned)sfn < splitFaceCells[splitFaceCellNghbrId].splitFaces.size(); sfn++) {
35978 if(
m_revDir[dir] == splitFaceCells[splitFaceCellNghbrId].splitFaces[sfn].direction) {
35979 for(
MInt s = 0; (unsigned)s < splitFaceCells[splitFaceCellNghbrId].splitFaces[sfn].srfcIds.size();
35981 srfcIdNghbr = splitFaceCells[splitFaceCellNghbrId].splitFaces[sfn].srfcIds[s];
35982 ASSERT(srfcIdNghbr > -1,
"");
35984 if(xDiff < minXDiff) {
35986 bestFitSrfc = srfcIdNghbr;
35987 bestFitCell = splitChildIdN;
35988 bestFitSplitFacePart = &splitFaceCells[splitFaceCellNghbrId].splitFaces[sfn].srfcIds[s];
35997 if(bestFitSrfc < 0)
mTerm(1, AT_,
"did not find a matching surface at all...");
35999 if(minXDiff > maxXdiff || aDiff > maxAdiff) {
36000 cerr <<
" [" <<
domainId() <<
"] - split surface connection - "
36001 <<
" sfId: " << sfId <<
" nghbr: " << nghbrId
36004 << noSplitFaceCells <<
" " << noSubCellsN << endl;
36015 mTerm(1, AT_,
"split cell connection failed");
36024 if(bestFitSplitFacePart == (
MInt*)
nullptr) {
36026 ASSERT(
a_bndryId(bestFitCell) > -1,
" ");
36029 *bestFitSplitFacePart = srfcId;
36038 for(
MInt sc = 0; sc < noSplitCells; sc++) {
36051 if(srfcNeighbor > -1)
36055 if(nghbrId < 0)
mTerm(1, AT_,
"split cell has no valid neighbor in direction of cut surface...");
36059 MInt splitChildIdN = nghbrId;
36060 MInt noSubCellsN = 1;
36061 MInt splitCellIdN = -1;
36063 splitCellIdN = splitCellIds[
a_bndryId(nghbrId)];
36066 MFloat minXDiff = std::numeric_limits<float>::max();
36067 MInt bestFitSrfc = -1;
36068 MInt bestFitCell = -1;
36070 for(
MInt count = 0; count < noSubCellsN; count++) {
36071 if(splitCellIdN > -1) {
36075 if(srfcIdNghbr > -1) {
36077 if(xDiff < minXDiff) {
36079 bestFitSrfc = srfcIdNghbr;
36080 bestFitCell = splitChildIdN;
36086 if(bestFitSrfc < 0)
mTerm(1, AT_,
"did not find a matching surface at all...");
36088 if(minXDiff > maxXdiff || aDiff > maxAdiff) {
36089 cerr <<
domainId() <<
": split " << splitChildId <<
" " << splitCellIdN <<
" " << splitChildIdN <<
" "
36092 cerr <<
" [" <<
domainId() <<
"] - split cell connection - "
36093 <<
" splitChildId: " << splitChildId <<
" nghbr: " << splitChildIdN <<
" aDiff: " << aDiff <<
" ("
36094 << maxAdiff <<
") minXDiff: " << minXDiff <<
" (" << maxXdiff <<
")" << endl;
36098 mTerm(1, AT_,
"split cell connection failed (2)");
36117 for(
MInt sc = 0; sc < noSplitCells; sc++) {
36122 mTerm(1, AT_,
"splitParent cell has a valid surface attached to it after split connection...");
36123 if(
m_fvBndryCnd->m_bndryCells->a[scBndryId].m_associatedSrfc[d] > -1)
36124 mTerm(1, AT_,
"splitParent cell has a valid surface attached to its boundary cell after split connection...");
36135 if(
m_fvBndryCnd->m_bndryCells->a[splitChildBndryId].m_associatedSrfc[d] != srfcId)
36136 mTerm(1, AT_,
"splitChild cell no consistent surface information...");
36137 if(nghbr0 == splitChildId) {
36140 "splitChild cell has a surface with no valid neighbor attached to it after split connection...");
36141 }
else if(nghbr1 == splitChildId) {
36144 "splitChild cell has a surface with no valid neighbor attached to it after split connection...");
36147 "splitChild cell has a surface attached to it which does not point to the cell itself after split "
36150 MBool suspicious =
true;
36152 suspicious =
false;
36156 if(!suspicious)
continue;
36157 MInt sfId = splitFaceCellIds[splitChildBndryId];
36159 cellWithSplitFace* sfCell = &splitFaceCells[sfId];
36160 for(
MInt sff = 0; (unsigned)sff < sfCell->splitFaces.size(); sff++) {
36161 splitCartesianFace* splitFace = &sfCell->splitFaces[sff];
36162 MInt dir = splitFace->direction;
36164 suspicious =
false;
36171 "split cell child has a fluid side which is not split but has no valid surface attached to it "
36172 "after split connection!");
36177 for(
MInt sf = 0; sf < noSplitFaceCells; sf++) {
36178 cellWithSplitFace* sfCell = &splitFaceCells[sf];
36179 MInt sfId = sfCell->cellId;
36181 MInt noSplitFaces = sfCell->splitFaces.size();
36182 for(
MInt sff = 0; sff < noSplitFaces; sff++) {
36183 splitCartesianFace* splitFace = &sfCell->splitFaces[sff];
36184 MInt dir = splitFace->direction;
36186 if(srfcId > -1)
mTerm(1, AT_,
"split face has a valid surface attached to it after split connection...");
36187 if(
m_fvBndryCnd->m_bndryCells->a[sfBndryId].m_associatedSrfc[dir] > -1)
36188 mTerm(1, AT_,
"split face has a valid surface attached to its boundary cell after split connection...");
36189 for(
MInt srfc = 0; (unsigned)srfc < splitFace->srfcIds.size(); srfc++) {
36190 srfcId = splitFace->srfcIds[srfc];
36191 if(srfcId < 0)
mTerm(1, AT_,
"split face part has no surface attached to it after split connection...");
36194 if(nghbr0 == sfId) {
36196 mTerm(1, AT_,
"splitface has a surface with no valid neighbor attached to it after split connection...");
36197 }
else if(nghbr1 == sfId) {
36199 mTerm(1, AT_,
"splitface has a surface with a valid neighbor attached to it after split connection...");
36202 "splitface has a surface attached to it which does not point to the cell itself after split "
36208 RECORD_TIMER_STOP(tCutFace_9);
36209 RECORD_TIMER_START(tCutFace_10);
36217 if((nghbr0 < 0 || nghbr1 < 0)) {
36219 mTerm(1,
"active surface has not two neighbors 4...", AT_);
36225 if(
a_hasProperty(cellId, SolverCell::IsSplitCell))
continue;
36227 if(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_bndryCndId < 0) {
36229 "error in createCutFaceMb_MGC(): m_bndryCndId not set: " + to_string(cellId) +
" " + to_string(bndryId)
36230 +
" " + to_string(
m_fvBndryCnd->m_bndryCell[bndryId].m_srfcs[srfc]->m_bndryCndId) +
"/"
36231 + to_string(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_noSrfcs) +
" "
36232 + to_string(
m_fvBndryCnd->m_bndryCells->a[bndryId].m_srfcs[srfc]->m_area));
36239 RECORD_TIMER_STOP(tCutFace_10);
36247template <MInt nDim,
class SysEqn>
36253 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36266 }
else if(mode == 1) {
36267 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36277 MBool rebuild =
false;
36278 for(
MInt nghbr = 0; nghbr < noNghbrIds; nghbr++) {
36299template <MInt nDim,
class SysEqn>
36303 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36308 MBool rebuild =
false;
36309 for(
MInt nghbr = 0; nghbr < noNghbrIds; nghbr++) {
36340template <MInt nDim,
class SysEqn>
36344 if(
grid().noAzimuthalNeighborDomains() == 0)
return;
36348 windowData.
fill(0);
36354 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36371 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36375 recCoord[d] = windowData[rcvCnt++];
36379 grid().rotateCartesianCoordinates(recCoord, (side * angle));
36389 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36390 for(
MInt j = 0; j <
grid().noAzimuthalWindowCells(i); j++) {
36391 MInt cellId =
grid().azimuthalWindowCell(i, j);
36410template <MInt nDim,
class SysEqn>
36417 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36418 for(
MInt j = 0; j <
grid().noAzimuthalWindowCells(i); j++) {
36419 MInt cellId =
grid().azimuthalWindowCell(i, j);
36460template <MInt nDim,
class SysEqn>
36465 if(
grid().noAzimuthalNeighborDomains() > 0) {
36471 windowFData.
fill(-1.0);
36473 windowIData.
fill(0);
36476 haloFData.
fill(-1.0);
36481 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36482 for(
MInt j = 0; j <
grid().noAzimuthalHaloCells(i); j++) {
36483 MInt cellId =
grid().azimuthalHaloCell(i, j);
36486 haloFData[sndCnt * noFloatData] =
a_cellVolume(cellId);
36488 haloFData[sndCnt * noFloatData + 2] = it !=
m_oldBndryCells.end() ? it->second : F0;
36490 for(
MInt v = 0; v <
CV->noVariables; v++) {
36491 haloFData[sndCnt * noFloatData + 3 + v] =
a_variable(cellId, v);
36495 haloIData[sndCnt * noIntData] = (unsigned)
m_oldBndryCells.count(cellId);
36496 haloIData[sndCnt * noIntData + 1] = (
a_properties(cellId)).to_ulong();
36512 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36513 for(
MInt j = 0; j <
grid().noAzimuthalWindowCells(i); j++) {
36514 MInt cellId =
grid().azimuthalWindowCell(i, j);
36515 if(windowIData[rcvCnt * noIntData] > 0 || mode == 1) {
36516 MBool isEqual =
false;
36517 MLong gCellId = cellId;
36523 for(
auto it = range.first; it != range.second; ++it) {
36525 recCoord[d] = (it->second).first[d];
36542 vector<MFloat> tmpF(
mMax(noFloatData +
nDim,
nDim + 3));
36543 vector<MUlong> tmpI(noIntData);
36549 tmpF[
nDim] = windowFData[rcvCnt * noFloatData];
36550 tmpF[
nDim + 1] = windowFData[rcvCnt * noFloatData + 1];
36551 tmpF[
nDim + 2] = windowFData[rcvCnt * noFloatData + 2];
36554 for(
MInt v = 0; v <
CV->noVariables; v++) {
36555 tmpF[
nDim + 3 + v] = windowFData[rcvCnt * noFloatData + 3 + v];
36559 tmpI[0] = windowIData[rcvCnt * noIntData];
36560 tmpI[1] = windowIData[rcvCnt * noIntData + 1];
36572 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36573 for(
MInt j = 0; j <
grid().noAzimuthalWindowCells(i); j++) {
36574 MInt cellId =
grid().azimuthalWindowCell(i, j);
36575 MLong gCellId = cellId;
36582 for(
auto it = range.first; it != range.second; ++it) {
36584 recCoord[d] = (it->second).first[d];
36586 cerr <<
"W:" <<
domainId() <<
" " << cellId <<
"/" <<
c_globalId(cellId) <<
" " << gCellId <<
" "
36588 <<
"/" <<
grid().noAzimuthalWindowCells(i) <<
" " <<
grid().azimuthalNeighborDomain(i) <<
" "
36590 << recCoord[0] <<
" " << recCoord[1] <<
" " << recCoord[
nDim - 1] << endl;
36595 MPI_Allreduce(MPI_IN_PLACE, &cntMax, 1, MPI_INT, MPI_MAX,
mpiComm(), AT_,
"MPI_IN_PLACE",
"cntMax");
36596 if(
domainId() == 0) cerr <<
"cntMax: " << cntMax << endl;
36603template <MInt nDim,
class SysEqn>
36607 if(
grid().noAzimuthalNeighborDomains() == 0)
return;
36614 windowFData.
fill(-1.0);
36616 windowFData.
fill(0);
36619 haloFData.
fill(-1.0);
36624 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36625 for(
MInt j = 0; j <
grid().noAzimuthalWindowCells(i); j++) {
36626 MInt cellId =
grid().azimuthalWindowCell(i, j);
36627 MLong gCellId = cellId;
36637 for(
auto it = range.first; it != range.second; ++it) {
36639 tmp[d] = (it->second).first[d];
36641 MBool isEqual =
true;
36643 if(!
approx(tmp[d], recCoord[d], 0.01 * cellLength)) isEqual =
false;
36646 ASSERT((it->second).second[0] > 0 || mode == 1,
"WRONG!");
36647 windowFData[sndCnt * noFloatData] = (it->second).first[
nDim];
36648 windowFData[sndCnt * noFloatData + 1] = (it->second).first[
nDim + 1];
36649 windowFData[sndCnt * noFloatData + 2] = (it->second).first[
nDim + 2];
36651 for(
MInt v = 0; v <
CV->noVariables; v++) {
36652 windowFData[sndCnt * noFloatData + 3 + v] = (it->second).first[
nDim + 3 + v];
36656 windowIData[sndCnt * noIntData] = (it->second).second[0];
36657 windowIData[sndCnt * noIntData + 1] = (it->second).second[1];
36679 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36680 for(
MInt j = 0; j <
grid().noAzimuthalHaloCells(i); j++) {
36681 MInt cellId =
grid().azimuthalHaloCell(i, j);
36694 if(
m_closeGaps)
mTerm(1, AT_,
"AzimuthalPer adaptation not working with gap closing!");
36697 for(
MInt v = 0; v <
CV->noVariables; v++) {
36698 a_variable(cellId, v) = haloFData[rcvCnt * noFloatData + 3 + v];
36703 if(haloIData[rcvCnt * noIntData] > 0) {
36704 a_cellVolume(cellId) = haloFData[rcvCnt * noFloatData];
36707 m_oldBndryCells.insert(make_pair(cellId, haloFData[rcvCnt * noFloatData + 2]));
36726 tmp[1 + v] = std::numeric_limits<MFloat>::lowest();
36729 tmp[1 +
m_noCVars + v] = std::numeric_limits<MFloat>::lowest();
36742template <MInt nDim,
class SysEqn>
36751 if(
grid().azimuthalPeriodicity()) {
36755 "m_azimuthalNearBoundaryBackupBalFloat", AT_);
36770 MPI_Allreduce(MPI_IN_PLACE, &maxCount, 1, MPI_INT, MPI_MAX,
mpiComm(), AT_,
"MPI_IN_PLACE",
"maxCount");
36777 for(
MInt i = 0; i < noLongData; i++) {
36780 for(
MInt i = 0; i < noFloatData; i++) {
36787 for(
auto it_ = range.first; it_ != range.second; ++it_) {
36804template <MInt nDim,
class SysEqn>
36808 set<MInt> needsExc;
36809 for(
MInt i = 0; i <
grid().noAzimuthalNeighborDomains(); i++) {
36813 for(
MInt nghbr = 0; nghbr < noNghbrIds; nghbr++) {
36816 needsExc.insert(recId);
36835 windowBuff.
fill(0);
36841 if(needsExc.find(
haloCell) != needsExc.end()) {
36842 haloBuff[sndCnt] = 1;
36845 haloBuff[sndCnt] = 0;
36853 MInt rcvOffset = 0;
36854 MInt sndOffset = 0;
36857 AT_,
"windowBuff[rcvOffset]");
36872 if(windowBuff[rcvCnt] > 0) {
36883template <MInt nDim,
class SysEqn>
36889 windowData.
fill(0);
MLong allocatedBytes()
Return the number of allocated bytes.
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
static MInt propertyLength(const MString &name, MInt solverId=m_noSolvers)
Returns the number of elements of a property.
static T getSolverProperty(const MString name, const MInt solverId, const MString &nameOfCallingFunction, const T *default_value, MInt pos=0)
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
std::vector< std::vector< MInt > > m_splitChilds
MBool m_azimuthalRecConstSet
MInt c_level(const MInt cellId) const
Returns the grid level of the cell cellId.
void resetSolver() override
Reset the solver prior to load balancing.
std::vector< std::vector< MInt > > m_azimuthalMaxLevelWindowCells
MInt * m_noMaxLevelWindowCells
virtual void LSReconstructCellCenter()
Dispatch the reconstruction computation to the appropiate loop.
MLong c_neighborId(const MInt cellId, const MInt dir, const MBool assertNeighborState=true) const
Returns the grid neighbor id of the grid cell cellId dir.
MInt a_noSurfaces()
Returns the number of surfaces.
static constexpr const MInt m_noCorners
MInt ** m_maxLevelHaloCells
Collector< FvBndryCell< nDim, SysEqn > > * m_bndryCells
void balance(const MInt *const noCellsToReceiveByDomain, const MInt *const noCellsToSendByDomain, const MInt *const targetDomainsByCell, const MInt oldNoCells) override
Balance the solver.
MLong c_childId(const MInt cellId, const MInt pos) const
Returns the grid child id of the grid cell cellId at position pos.
std::vector< std::vector< MInt > > m_azimuthalRemappedWindowCells
MFloat & a_rightHandSide(const MInt cellId, MInt const varId)
Returns the right hand side of the cell cellId for the variable varId.
MBool m_azimuthalNearBndryInit
MFloat c_cellLengthAtCell(const MInt cellId) const
Returns the length of the cell for level.
MFloat c_cellLengthAtLevel(const MInt level) const
Returns the length of the cell for level.
std::vector< MFloat > m_azimuthalRecConsts
MFloat & a_slope(const MInt cellId, MInt const varId, const MInt dir) override
Returns the slope of the cell cellId for the variable varId in direction dir.
MFloat & a_oldVariable(const MInt cellId, const MInt varId)
Returns oldVariablesv of the cell cellId variables varId.
std::vector< MFloat > m_azimuthalCutRecCoord
MBool a_isBndryCell(const MInt cellId) const override
Returns isBndryCell of the cell cellId.
void finalizeAdaptation() override
void swapCells(const MInt, const MInt) override
SysEqn::PrimitiveVariables * PV
virtual void resetBoundaryCells(const MInt offset=0)
virtual void resetSolverFull()
MBool a_isHalo(const MInt cellId) const
Returns IsHalo of the cell cellId.
void prepareAdaptation() override
maia::fv::cell::BitsetType & a_properties(const MInt cellId)
Returns properties of the cell cellId.
MFloat crankAngle(const MFloat, const MInt)
help-function for engine calculations which returns the crank-angle for a given time mode = 0: return...
MFloat & a_surfaceArea(const MInt srfcId)
Returns the area of surface srfcId.
MInt a_cutCellLevel(const MInt cellId) const
Returns the level for cutCells, this can either be the maxRefinementLevel or the level of the current...
MFloat & a_variable(const MInt cellId, const MInt varId)
Returns conservative variable v of the cell cellId for variables varId.
MInt noInternalCells() const override
MLong c_parentId(const MInt cellId) const
Returns the grid parent id of the cell cellId.
Collector< CartesianGridPoint< nDim > > * m_gridPoints
std::vector< std::vector< MInt > > m_azimuthalMaxLevelHaloCells
MInt m_noLevelSetsUsedForMb
MFloat & a_levelSetValuesMb(const MInt cellId, const MInt set)
Returns the levelSetMb-value for fv-CellId cellId and set.
SysEqn::ConservativeVariables * CV
virtual void saveRestartFile(const MBool)
virtual void viscousFlux()
void finalizeBalance() override
Reinitialize solver after all data structures have been recreated.
MFloat & a_surfaceCoordinate(const MInt srfcId, const MInt dir)
Returns the coordinate of surface srfcId in direction dir.
virtual MBool maxResidual(MInt mode=0)
Computes the global root-mean-square residual. The residual is defined as time derivative of conserva...
virtual void Ausm()
Dispatches the AUSM flux computation for different number of species.
MInt & a_associatedBodyIds(const MInt cellId, const MInt set)
Returns the associatedBodyIds for fv-CellId cellId and set.
MInt a_noCells() const
Returns the number of cells.
void writeCenterLineVel()
MInt ** m_maxLevelWindowCells
const MInt m_maxNoAzimuthalRecConst
static constexpr MInt nDim
MBool a_hasProperty(const MInt cellId, const Cell p) const
Returns grid cell property p of the cell cellId.
void loadRestartFile() override
static constexpr MFloat m_volumeThreshold
std::vector< std::vector< MInt > > m_azimuthalMaxLevelWindowMap
static constexpr const MInt m_noDirs
void setSensors(std::vector< std::vector< MFloat > > &sensors, std::vector< MFloat > &sensorWeight, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MInt > &sensorSolverId) override
set the sensors for the adaptation (i.e. which cell should be refined/removed?)
void preTimeStep() override
virtual void resetSurfaces()
void refineCell(const MInt) override
MInt c_noChildren(const MInt cellId) const
Returns the number of children of the cell cellId.
MFloat c_coordinate(const MInt cellId, const MInt dir) const
Returns the coordinate of the cell from the grid().tree() cellId for dimension dir.
virtual void updateSpongeLayer()
computes the additional rhs of all cells lying inside the sponge layer to dissipate outgoing waves.
void removeChilds(const MInt) override
MFloat & a_coordinate(const MInt cellId, const MInt dir)
Returns the coordinate of the cell from the fvcellcollector cellId for dimension dir.
std::vector< MInt > m_noAzimuthalReconstNghbrs
std::vector< MInt > m_azimuthalBndrySide
virtual void applyInitialCondition()
Initializes the entire flow field.
MLong c_globalId(const MInt cellId) const
Returns the global grid id of the grid cell cellId.
MInt & a_surfaceNghbrCellId(const MInt srfcId, const MInt dir)
Returns the neighbor cell id of surface srfcId in direction dir.
virtual void distributeFluxToCells()
Distributes the surface fluxes to the cell RHS.
MFloat & a_spongeFactor(const MInt cellId)
Returns the spongeFactor of the cell cellId.
std::vector< MInt > m_azimuthalReconstNghbrIds
maia::fv::cell::BitsetType::reference a_wasGapCell(const MInt cellId)
Returns wasGapCell of the cell cellId.
MBool c_isLeafCell(const MInt cellId) const
MFloat & a_cellVolume(const MInt cellId)
Returns the cell volume of the cell from the fvcellcollector cellId.
void setPrimitiveVariables(MInt cellId)
computes primitive from primitive variables for given cell id. This is the version for all SysEqn.
virtual void resetRHSCutOffCells()
MInt ** m_cellSurfaceMapping
virtual void setCellProperties()
virtual MFloat entropy(MInt cellId)
void postAdaptation() override
static constexpr const MInt m_noEdges
Collector< PointBasedCell< nDim > > * m_extractedCells
const MInt m_azimuthalNearBoundaryBackupMaxCount
MInt & a_level(const MInt cellId)
Returns the level of the cell from the fvcellcollector cellId.
MInt a_hasNeighbor(const MInt cellId, const MInt dir, const MBool assertNeighborState=true) const
Returns noNeighborIds of the cell CellId for direction dir.
MFloat timeStep(MBool canSolver=false) noexcept
virtual void updateMultiSolverInformation(MBool fullReset=false)
virtual MBool gridPointIsInside(MInt, MInt)
MInt & a_bndryId(const MInt cellId)
Returns the bndryId of the cell cellId.
std::vector< MInt > m_splitCells
std::vector< MInt > m_azimuthalHaloActive
void rebuildAzimuthalReconstructionConstants(MInt cellId, MInt offset, MFloat *recCoord, MInt mode=0)
std::vector< MInt > m_azimuthalRemappedNeighborDomains
MFloat & a_pvariable(const MInt cellId, const MInt varId)
Returns primitive variable v of the cell cellId for variables varId.
MInt * m_noMaxLevelHaloCells
void balancePre() override
Reinitialize solver for DLB prior to setting solution data.
MBool checkNeighborActive(const MInt cellId, const MInt dir) const
Cecks wether the cell cellId has a valid neighbor in direction dir.
MFloat & a_FcellVolume(const MInt cellId) override
Returns the inverse cell volume of the cell from the fvcellcollector cellId.
const MInt & getAssociatedInternalCell(const MInt &cellId) const
Returns the Id of the split cell, if cellId is a split child.
void build(std::vector< CsgPolygon > _polygons)
void splitPolygon(CsgPolygon *polygon, std::vector< CsgPolygon > *coplanarFront, std::vector< CsgPolygon > *coplanarBack, std::vector< CsgPolygon > *front, std::vector< CsgPolygon > *back) const
void insertCoplanarPolygon(CsgPolygon *polygon, std::vector< CsgPolygon > *coplanarFront, std::vector< CsgPolygon > *coplanarBack) const
std::vector< CsgVertex > vertices
CsgVector minus(const CsgVector &a) const
CsgVertex interpolate(CsgVertex *other, MFloat t) const
void logBoundaryData(const MChar *fileName, MBool forceOutput)
logs several boundary values to the given output file
void resetMbBoundaryCells()
resets all moving boundary cells - STL boundary remains intact
void printDynamicCoefficients(MBool firstRun, MFloat *pressureForce)
void reInitSolutionStep(const MInt mode)
Re-initializes the solver.
MInt returnNoActiveCorners(MInt)
returns the numer of active Corners for an arbitrary cell (the cell is not a bndryCandidate yet and t...
void applyInitialCondition() override
void copyVarsToSmallCells() override
calls m_fvBndryCnd->copyVarsToSmallCells()
void sensorPatch(std::vector< std::vector< MFloat > > &, std::vector< std::bitset< 64 > > &, std::vector< MFloat > &, MInt, MInt) override
MFloat getLevelSetValueNaca00XX(const MFloat *const, const MFloat sign)
void initPointParticleProperties()
MFloat * m_sweptVolumeDt1
void initGField()
initializes the level-set data at startup
static void computeNormal(const MFloat *p0, const MFloat *p1, MFloat *res, MFloat &w)
returns the normal corresponding to the triangle abc and returns the result in res
void leastSquaresReconstruction()
Least squares reconstruction.
MInt getAdjacentGridCells(MInt cellId, MInt *adjacentCells)
retrieves all direct and diagonal fluid cell neighbours of the given cell
void storeAzimuthalPeriodicData(MInt mode=0)
Stored azimuthal periodic data from halo rank on window rank.
void checkCellState()
checks the cell state of the inactive cells based on the nodal ls values if a cell is inactive (level...
MInt broadcastSignal(const MInt sender, const MInt signal)
hijacked function to compute gradients in intial condition 122 for pressure poisson equation
static void matrixProduct(MFloatScratchSpace &C, MFloatScratchSpace &A, MFloatScratchSpace &B)
C=A*B.
MInt writeGeometryToVtkXmlFile(const MString &fileName)
Writes VTK file for the embedded geometry.
void loadRestartFile() override
Loads the restart files.
void computeFlowStatistics(MBool force)
MFloat updateCellVolumeGCL(MInt bndryId)
static void matrixProductTranspose(MFloatScratchSpace &C, MFloatScratchSpace &A, MFloatScratchSpace &B)
C=A*B^t.
MInt ** m_cutFacePointIds
MLong * m_azimuthalNearBoundaryBackupBalLong
std::map< MInt, std::vector< MFloat > > m_nearBoundaryBackup
void initAzimuthalLinkedHaloExc()
Create exchange for all window/halo cells which are used for the azimuthal periodic interpolation.
static void computeRotationMatrix(MFloatScratchSpace &, MFloat *q)
rotation matrix co-rotating(~inertial) frame -> body-fixed frame
void computeSlipStatistics(const MIntScratchSpace &nearestBodies, const MFloatScratchSpace &nearestDist, const MFloat maxDistConstructed)
void exchangeLevelSetData()
void gapCellExchange(MInt)
exchanges variables and wasInactive for gapCells
std::vector< std::vector< MInt > > m_azimuthalLinkedWindowCells
void setBoundaryVelocity()
Sets the boundry velocity at the moving cut-cells. sets: m_primVars[PV->VV[i]] to m_bodyVelocity[i] f...
void buildAdditionalAzimuthalReconstructionStencil(MInt mode=0)
Rebuild azimuthal reconstruction constants for moving boundary cells.
void integrateBodyRotation()
std::vector< MInt > m_refOldBndryCells
void computeBodySurfaceData(MFloat *pressureForce=nullptr)
computes relevant variables at the moving boundary surface and determines the resulting body force
void finalizeAdaptation() override
void recordBodyData(const MBool &firstRun)
void saveRestartFile(const MBool) override
Saves the restart file.
MFloat * m_cellVolumesDt1
void finalizeInitSolver() override
Initializes the solver afer the initialRefinement!
void updateInfinityVariables()
update infinity state for certain testcases with constructed level-set field!
void writeVtkDebug(const MString suffix)
MString getConservativeVarName(MInt i)
returns the name of the conservative variable at the given index i
MFloat filterFloat(MFloat number)
filter nan's
void applyExternalOldSource() override
remove external sources from tho old RHS for new-RungeKutta-scheme for moving boundaries
MInt m_noFloatDataAdaptation
FvMbCartesianSolverXD(MInt, MInt, const MBool *, maia::grid::Proxy< nDim > &gridProxy_, Geometry< nDim > &geometry_, const MPI_Comm comm)
virtual void generateBndryCells()
void resetRHSCutOffCells() override
MFloat * m_azimuthalNearBoundaryBackupBalFloat
void advancePointParticles()
void initSolutionStep(MInt mode) override
Initializes the solver.
MFloat getDistanceSplitSphere(const MInt, const MInt)
determines the level-set value for the given cell provided that the embedded body is spherical
void correctRefinedBndryCell()
correct old-BndryCells which are no-longer leaf-Cells after the adaptation NOTE: mas-conservative upd...
void updateViscousFluxComputation()
corrects the cell-surface distances at the boundary needed for the viscous flux computation
void updateAzimuthalNearBoundaryExchange()
Reset former azimuthal nearBoundaryCells.
void Muscl(MInt timerId=-1) override
Reconstructs the flux on the surfaces.
void setupBoundaryCandidatesAnalytical()
determine all possible fluid boundary cells for a spherical embedded body
void swapCells(const MInt, const MInt) override
MInt getFacingNghbrs(const MInt cellId, const MBool includeAllChilds)
determines the neighbors sharing a face with the given cell
void saveParticleSamples()
void updateGhostCellSlopesViscous()
void computeGhostCellsMb()
creates a ghost cell for all cells near(!) the moving boundary
void saveSolverSolution(const MBool forceOutput=false, const MBool finalTimeStep=false) override
Manages solver-specific output.
std::multimap< MLong, std::pair< std::vector< MFloat >, std::vector< MUlong > > > m_azimuthalNearBoundaryBackup
void initSolver() override
Initializes the solution.
void getBodyRotationDt1(const MInt bodyId, MFloat *bodyRotation)
void setSensors(std::vector< std::vector< MFloat > > &sensors, std::vector< MFloat > &sensorWeight, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MInt > &sensorSolverId) override
MInt inverseGJ()
computes the Gauss Jordan matrix inversion of the first DxD-solver of m_A. The inverse A^-1 is stored...
std::vector< MInt > m_bndryCandidateIds
void linkBndryCells()
Links bndryCells.
void correctSrfcsMb()
correct surfaces intersected by the moving boundary
void correctMasterSlaveSurfaces()
Removes surfaces between master-slave pairs and reassigns slave cell surfaces required in order to ma...
void setParticleFluidVelocities(MFloat *=nullptr)
void restoreNeighbourLinks()
restores previously deleted neighbour information and reactivates cells
void applyDirichletCondition()
void saveBodyRestartFile(const MBool backup)
save restart body file
void initBodyVelocities()
void updateGhostCellSlopesInviscid()
void setAdditionalActiveFlag(MIntScratchSpace &) override
void computeBodyMomentOfInertia()
void generateBndryCellsMb(const MInt mode)
call all routines necessary for the generation of boundary cells mode = -1: default argument,...
std::set< MInt > m_freeSurfaceIndices
const MFloat m_azimuthalCornerEps
void computeAzimuthalReconstructionConstants(MInt mode=0) override
Compute the reconstruction constants for azimuthal periodic exchange using a weighted least squares a...
void preSolutionStep(const MInt=-1) override
step before the solver solution Step
void transferBodyState(MInt k, MInt b)
MBool adaptationTrigger() override
void checkNormalVectors()
void commAzimuthalPeriodicData(MInt mode=0)
Send stored azimuthal periodic data from window to halo.
void removeSurfaces(MInt cellId)
removes the surfaces of the given cell
void applyALECorrection()
void resetRHSNonInternalCells() override
void initializeMb()
called by the constructor 1) read additional fvmb properties 2) allocate fvmb specific memory 3) init...
void updateMultiSolverInformation(MBool fullReset=false) override
void buildAdditionalReconstructionStencil()
correct reconstruction stencil for all cells near moving boundaries
MFloat getDistance(const MFloat *const, const MInt)
void allocateBodyMemory(MInt mode=0)
void exchangeAzimuthalOuterNodalValues(std::vector< CutCandidate< nDim > > &candidates, std::vector< MInt > &candidateIds)
Exchange of nodal values of azimuthal periodic halo cells.
void correctCoarsenedBndryCellVolume()
correct BndryCells volume of bndryCells which were a bndryCell on a coarser level before
void deleteNeighbourLinks()
deletes links to neighbours tagged inactive
void updateSpongeLayer() override
computes the additional rhs of all cells lying inside the sponge layer to dissipate outgoing waves.
void initBndryLayer()
initializes the bndryLayer data and is/was inactive at solver initialisation
GeometryIntersection< nDim > * m_geometryIntersection
void createCutFaceMb_MGC()
determines the geometric cut-cell data
MInt getAdjacentCellsAllLevels(MInt cellId, MInt *adjacentCells)
retrieves all direct and diagonal fluid cell neighbours of the given cell
void moveSurface(const MInt toSrfcId, const MInt fromSrfcId)
void createPeriodicGhostBodies()
void updateBodyProperties()
update properties of the embedded body (mainly forced structural motion)
void initializeRungeKutta() override
This function loads all terms used by Runge Kutta.
void writeListOfActiveFlowCells() override
stores all cells and surfaces needed for the flux computation
void writeVTKFileOfCell(MInt, const std::vector< polyEdge2D > *, const std::vector< polyVertex > *, MInt)
MBool m_static_createCutFaceMb_MGC_first
void computeNearBodyFluidVelocity(const MIntScratchSpace &nearestBodies, const MFloatScratchSpace &nearestDist, MFloat *vel, MFloat *velGrad, MFloat *rotation, const std::vector< MFloat > &setup=std::vector< MFloat >(), MInt *skipBodies=nullptr, MFloat *meanBodyState=nullptr, MFloat *pressure=nullptr, MFloat *velDt=nullptr, MFloat *rotationDt=nullptr, MFloat *nearestFac=nullptr)
Mean parameters: near body data estimated by weighted filtering procedure All parameters after "setup...
void setGapCellId()
set the gapCellId for gapInitMethod = 0, otherwise handeled in gapHandling!
MFloat temperature(MInt cellId)
temperature
void initializeMaxLevelExchange() override
update window/halo cell collectors
FvBndryCndXD< nDim, SysEqn > * m_fvBndryCnd
void compVolumeIntegrals(std::vector< polyCutCell > *, std::vector< polyEdge2D > *, const std::vector< polyVertex > *)
void getBodyRotation(const MInt bodyId, MFloat *bodyRotation)
void writeVtkXmlFiles(const MString fileName, const MString GFileName, MBool regularOutput, MBool diverged) override
write flow variables as XML VTK files
void resetSolver() override
Reset the solver prior to load balancing.
void writeVtkXmlOutput(const MString &fileName, MBool debugOutput=false)
write flow variables as XML VTK
void determineNearBndryCells()
determines cells at the boundary (i.e. boundary cells and their direct neighbors)
MBool rungeKuttaStep() override
calls a Runge Kutta substep
void updateCellSurfaceDistanceVectors()
correct the cell-surface distance vectors for cells near the moving boundary
void balancePre() override
Reinitialize solver for DLB prior to setting solution data.
void readStlFile(const MChar *fileName, MBool readNormals)
read specified STL file
void balancePost() override
Reinitialize solver after setting solution data in DLB.
void computeBodyVolume(MFloatScratchSpace &partVol)
void loadBodyRestartFile(MInt)
load restart body file readMode = 0 : do not read the cellVolume from file (read only bodyData) readM...
void adaptTimeStep()
computes the time step
void createSurfaceSplit(MInt srfcId, MInt cellId, MInt splitChildId, MInt direction)
restores the surfaces of the given cell
void restoreSurfaces(const MInt cellId)
restores the surfaces of the given cell
void applyExternalSource() override
Add external sources to the RHS for new-RungeKutta-scheme for moving boundaries differs from the base...
void checkBoundaryCells()
performs an integrety check of the boundary cells
MBool test_face(MInt, MInt, MInt)
Test a face (MarchingCubes helper routine) receives MAIA face if face>0 return true if the face conta...
static MFloat distancePointEllipseSpecial(const MFloat e[2], const MFloat y[2], MFloat x[2])
MInt getEqualLevelNeighbors(MInt cellId, MInt(&nghbrs)[27])
retrieves all direct and diagonal fluid cell neighbours of the given cell
void checkGapCells()
determines Gap-state, and organises GapCells
void getNormalSphere(const MInt, const MInt, MFloat[])
MBool constructGFieldCorrector()
determine the displacement of the embedded body – corrector step
MFloat ** m_maxBndryLayerDistances
MInt ** m_noCutFacePoints
void initGapCellExchange()
creates the gap-cell exchange communicators based on initializeMaxLevelExchange
void computeBoundarySurfaceForces()
static void setAdditionalCellProperties()
set the properties of cells and determines the state of halo cells
void initEmergingGapCells()
initializes variables of cells which occur in a freshly opened gap (valve gap etc....
void updateSplitParentVariables() override
void localToGlobalIds() override
Change local into global ids.
void advanceBodies()
advances the time and stores the flow variables
void applyNeumannCondition()
void resetSolverFull() override
resets the solver
void initializeEmergedCells()
initializes variables of cells which recently became active and therefore have no up-to-date history ...
void finalizeBalance() override
Reinitialize solver after all data structures have been recreated.
MBool solutionStep() override
Performs the solutionStep of the FVMB solver the loop over the different RK-steps is done in the exec...
void resetSolverMb()
resets the solver to an empty domain without moving boundary
MFloat checkAreaDiff(MInt srfcId1, MInt srfcId2)
MInt m_static_createCutFaceMb_MGC_bodyFaceJoinMode
void setCellWeights(MFloat *) override
set static cell weights for solver cells, which are used for the domain decomposition
void getNormalEllipsoid(const MInt, const MInt, MFloat[])
void setOldGeomBndryCellVolume()
set bndryCell volume from m_oldGeomBndryCells which is read from bodyRestartFile at initSolver and th...
void setGapOpened()
sets the global-Trigger m_gapOpened, to determine if Gap-Cells are opened! old and incorrect version!...
MInt getAdjacentCellsExtended(MInt cellId, MInt *adjacentCells)
retrieves the first two layers of direct and diagonal fluid cell neighbours of the given cell
void computeLocalBoundingBox()
static void crossProduct(MFloat *c, MFloat *a, MFloat *b)
computes the cross product c <- (a x b) for a, b, c in R^3
void checkHaloBndryCells(MBool sweptVol)
void compFaceIntegrals(polyCutCell *, std::vector< polyEdge2D > *, const std::vector< polyVertex > *, MInt, MInt)
void computeNodalLSValues()
compute the level-set values at the mesh vertices
void constructGField(MBool updateBody=true)
manually constructs the level-set field after each time step
MFloat getDistanceEllipsoid(const MFloat *const, const MInt)
void correctRefinedBndryCellVolume()
correct BndryCells volume of bndryCells which were a bndryCell on a coarser level before
void compProjectionIntegrals(polyCutCell *, std::vector< polyEdge2D > *, const std::vector< polyVertex > *, MInt, MInt, MFloat *)
compute various integrations over projection of face
MFloat getDistancePiston(const MFloat *const, const MInt)
void setTimeStep() override
calls sets() and stores the time step for all cells
void advanceExternalSource() override
advance external sources
void addBoundarySurfacesMb()
adds a surface for the ghost-boundary cell intersections
MString getPrimitiveVarName(MInt i)
returns the name of the primitive variable at the given index i
void updateGeometry()
Updates the member-variables in the geometry-intersection class.
MInt createSplitCell(MInt cellId, MInt noSplitChilds)
MLong getNumberOfCells(MInt mode)
mode=0: total mode=1: min mode=2: max mode=3: average
MBool fileExists(const MChar *fileName)
MBool gridPointIsInside(MInt, MInt) override
void getBoundaryDistance(MFloatScratchSpace &) override
ATTRIBUTES1(ATTRIBUTE_HOT) void LSReconstructCellCenter() override
MBool maxResidual(MInt mode=0) override
Computes the maxResiduum for all cells.
static constexpr MInt m_noCellNodes
void writeVtkXmlOutput_MGC(const MString &fileName)
write flow variables as XML VTK
void applyBoundaryCondition() override
dummy, since applyBoundaryCondition() it is placed wrong for moving boundary problems,...
void prepareAdaptation() override
MInt createBndryCellMb(MInt cellId)
creates a moving boundary cell for the given cell
void descendDistance(const MInt cellId, const MInt *const bodyIds, const MInt bodyCnt, MIntScratchSpace &nearestBodies, MFloatScratchSpace &nearestDist)
void computeReconstructionConstants() override
computes the reconstruction constants using inverse distance weighted least squares
MFloat CalculateLSV(MInt, MIntScratchSpace &)
Calculate LevelSetValue with an Approximation of the Neighbours for a grid in the NarrowBand.
MInt constructDistance(const MFloat deltaMax, MIntScratchSpace &nearestBodies, MFloatScratchSpace &nearestDist)
void crankAngleSolutionOutput()
save a full solutionOutput at timeSteps closesed to a specified crankAngle Interval save a solution s...
void deleteSurface(MInt srfcId)
removes the surfaces of the given cell
std::set< MInt > m_coarseOldBndryCells
void logOutput()
logs several collector sizes
void advanceSolution()
advances the time and stores the flow variables
MFloat interpolateLevelSet(MInt *, MFloat *, MInt)
interpolates levelset function to a given coordinate
MFloat distancePointEllipsoidSpecial(const MFloat e[3], const MFloat y[3], MFloat x[3])
MInt checkNeighborActivity(MInt)
ckecks that a new bndry-Cell has at least one neighbor which was active before if this is not the cas...
void setRungeKuttaFunctionPointer()
This function sets the function pointers for rungeKutta (also used in splitBalance)
void writeVTKFileOfCutCell(MInt, std::vector< polyCutCell > *, const std::vector< polyEdge2D > *, const std::vector< polyVertex > *, MInt)
void getNormal(const MInt, const MInt, MFloat[])
void refineCell(const MInt) override
void computeCutPointsMb_MGC()
Computes cutpoints of zero level-set with grid edges and creates boundary cells for cut-cells.
MFloat getDistanceTetrahedron(const MFloat *const, const MInt)
void checkDiv() override
Check for divergence in case we use MB_DEBUG or debug.
MBool prepareRestart(MBool, MBool &) override
Prepare the solvers for a grid-restart.
void updateCellSurfaceDistanceVector(MInt srfcId)
correct the cell-surface distance vectors for cells near the moving boundary
void updateLinkedCells()
update the temporarly-linked cells
std::vector< std::vector< MInt > > m_azimuthalLinkedHaloCells
void saveParticleSlipData()
static void matrixProductTranspose2(MFloatScratchSpace &C, MFloatScratchSpace &A, MFloatScratchSpace &B)
C=A^t*B.
void constructGFieldPredictor()
determine the displacement of the embedded body – predictor step
void descendLevelSetValue(const MInt cellId, const MInt *const bodyIds, const MInt bodyCnt)
MFloat getDistanceSphere(const MFloat *const, const MInt)
void computeAzimuthalHaloNodalValues()
init exchange of nodal values of azimuthal periodic halo cells
MInt copyFile(const MChar *fromName, const MChar *toName)
void determineBndryCandidates()
determine all possible fluid boundary cells for a generic embedded body
void setLevelSetMbCellProperties()
determines relevant cell properties
std::vector< MFloat > m_candidateNodeValues
void balance(const MInt *const noCellsToReceiveByDomain, const MInt *const noCellsToSendByDomain, const MInt *const targetDomainsByCell, const MInt oldNoCells) override
Balance the solver.
std::map< MInt, MFloat > m_oldBndryCells
void gapHandling()
determines Gap-state, and organises GapCells
MString printTime(const MFloat t)
MFloat determineCoupling(MFloatScratchSpace &coupling)
void reIntAfterRestart(MBool) override
void setOuterBoundaryGhostCells()
void updateGapBoundaryCells()
set the velocity at gap-Boundary-Cells due to the irregular movement of the gap-surface during wideni...
MFloat getDistanceNaca00XX(const MInt, const MInt)
static void matrixVectorProduct(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A*b
void computeForceCoefficients(MFloat *&)
dummy
std::vector< MInt > m_azimuthalWasNearBndryIds
MInt getAdjacentCells(MInt cellId, MInt *adjacentCells)
retrieves all direct and diagonal fluid cell neighbours of the given cell
void rebuildReconstructionConstants(MInt cellId)
computes the reconstruction constants using inverse distance weighted least squares
void setOuterBoundarySurfaces()
MFloat distEllipsoidEllipsoid(const MInt k0, const MInt k1, MFloat *xc0, MFloat *xc1)
Compute the distance between two ellipsoids by iteratively searching the nearest point on the respect...
void setBodyQuaternions(const MInt bodyId, MFloat *bodyRotation)
MInt getNewSurfaceId()
returns a new surface id
void rebuildKDTreeLocal()
void initAnalyticalLevelSet()
This function creats the bodyTree for analytical LevelSets.
void interpolateGapBodyVelocity()
sets the interpolated velocity for a bndryCell NOTE: all neighbors need to be available for levelset-...
void initBodyProperties()
initialize properties of the embedded body at startup
void createSurface(MInt srfcId, MInt nghbrId0, MInt nghbrId1, MInt orientation)
restores the surfaces of the given cell
void applyBoundaryConditionMb()
applies the boundary condition at all boundaries
void resetSurfaces() override
MBool inside(MFloat x, MFloat a, MFloat b)
void writeStencil(const MInt bndryId)
void applyBoundaryConditionSlope()
void updateLevelSetOutsideBand()
computes an approximate level set value for cells outside the level-set computing band
void preTimeStep() override
Performs the preTimeStep of the FVMB solver.
MBool postSolutionStep() override
step after the solver solution Step
MFloat distancePointEllipsoid(const MFloat e[3], const MFloat y[3], MFloat x[3])
void resetSlopes()
does what it says
void prepareNextTimeStep() override
Updates the old Variables, the body positions and the increases the time.
MFloat m_static_createCutFaceMb_MGC_maxA
void checkHaloCells(MInt mode=0)
Checks a couple of important properties and variables of halo-cells.
MFloat checkCentroidDiff(MInt srfcId1, MInt srfcId2)
void writeVtkErrorFile()
write flow variables as XML VTK files
~FvMbCartesianSolverXD() override
void createInitialSrfcs()
computes initial set of internal grid surfaces
MFloat distancePointEllipsoidSpecial2(const MFloat e[3], const MFloat y[3], MFloat x[3])
void postAdaptation() override
void outputPolyData(const MInt, const std::vector< polyCutCell > *, const std::vector< polyEdge2D > *, const std::vector< polyVertex > *, MInt)
void postTimeStep() override
Performs the postTimeStep of the FVMB solver.
void setCellProperties() override
set the properties of cells and determines the state of halo cells
void removeChilds(const MInt) override
void computeVolumeFraction()
computes the volume fraction V/h^d and the level-set value in the volumetric center of all boundary c...
MInt m_noFloatDataBalance
void correctBoundarySurfaceVariablesMb()
sets boundary surface variables to their correct values
std::vector< MInt > m_candidateNodeSet
void exchangeLinkedHaloCellsForAzimuthalReconstruction()
Create exchange for all window/halo cells which are used for the azimuthal periodic interpolation.
void updateAzimuthalMaxLevelRecCoords()
Update reconstruction coordinate for azimuthal halo cells on max level This is done because of moving...
static void matrixVectorProductTranspose(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A^t*b
void computeCutFaces(std::vector< CutCell< nDim > > &cutCellData, const MInt maxNoSurfaces, const MInt tCutGroup)
This class is a ScratchSpace.
T * getPointer() const
Deprecated: use begin() instead!
void fill(T val)
fill the scratch with a given value
pointer p
Deprecated: use [] instead!
virtual MInt domainId() const
Return the domainId (rank)
MPI_Comm mpiComm() const
Return the MPI communicator used by this solver.
MInt solverId() const
Return the solverId.
virtual MInt noDomains() const
void updateDomainInfo(const MInt domainId, const MInt noDomains, const MPI_Comm mpiComm, const MString &loc)
Set new domain information.
MFloat m_Re
the Reynolds number
MFloat m_Ma
the Mach number
void writeVtuOutputParallel(const MString fileName, const MString geomFileName, const MInt noSolverSpecificVars=0, const MFloatScratchSpace &solverSpecificVars=MFloatScratchSpace(1, "writeVtuOutputParallel", "defaultParameter1"), const MInt noUserVars=0, const MFloatScratchSpace &userVars=MFloatScratchSpace(1, "writeVtuOutputParallel", "defaultParameter2"))
constexpr GridProxy & grid() const
std::vector< MFloat > m_azimuthalCartRecCoord
MInt maxRefinementLevel() const
const MInt & windowCell(const MInt domainId, const MInt cellId) const
MBool isActive() const override
const MInt & haloCell(const MInt domainId, const MInt cellId) const
MInt noNeighborDomains() const
MInt neighborDomain(const MInt id) const
void patchRefinement(std::vector< std::vector< MFloat > > &sensors, std::vector< std::bitset< 64 > > &sensorCellFlag, std::vector< MFloat > &sensorWeight, MInt sensorOffset, MInt sen)
MInt maxNoGridCells() const
void exchangeData(T *data, const MInt dataBlockSize=1)
Exchange memory in 'data' assuming a solver size of 'dataBlockSize' per cell.
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
MInt copyFile(const MString &fromName, const MString &toName)
Copies file fromName to file toName.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MBool fileExists(const MString &fileName)
Returns true if the file fileName exists, false otherwise.
constexpr Real POW3(const Real x)
constexpr Real POW2(const Real x)
MBool approx(const T &, const U &, const T)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
void printAllocatedMemory(const MLong oldAllocatedBytes, const MString &solverName, const MPI_Comm comm)
Prints currently allocated memory.
MInt globalDomainId()
Return global domain id.
constexpr MLong IPOW2(MInt x)
constexpr MFloat FPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
std::basic_string< char > MString
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_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgatherv
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_Issend(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_Issend
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
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
int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Reduce
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_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Alltoall
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
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
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
void const MInt const MInt const MInt const MInt maxNoCells
void setBoundaryVelocity(S &src, T &tgt, M &mapping, C conversion)
Setting the boundary velocity from one surface collector to the other.
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.
T cos(const T a, const T b, const T x)
Cosine slope filter.
constexpr std::underlying_type< FvCell >::type p(const FvCell property)
Converts property name to underlying integer value.
std::bitset< p(FvCell::NumProperties)> BitsetType
void matrixVectorProduct(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A*b
void invert(MFloat *A, const MInt m, const MInt n)
void computeRotationMatrix(MFloatScratchSpace &R, MFloat *q)
rotation matrix co-rotating(~inertial) frame -> body-fixed frame
MFloat deltaFun(const MFloat r, const MFloat r0, const MFloat r1)
void computeEnergySpectrum(MFloatScratchSpace &velocity, MIntScratchSpace &indices, const ptrdiff_t howmany, MInt locSize, MInt nx, MInt ny, MInt nz, MFloat viscosity, const MPI_Comm comm)
Compute energy spectrum on unity cube.
MUint getBufferSize(const std::vector< std::vector< MInt > > &exchangeCells)
Generic exchange of data.
void communicateData(const DataType *const data, const MInt noCells, const MInt *const sortedCellId, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MInt *const noCellsToSendByDomain, const MInt *const noCellsToReceiveByDomain, const MInt dataBlockSize, DataType *const buffer)
Assemble given data in send buffer and communicate.
void exchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const, const MInt *const noWindowCells, const MInt **const windowCells, const MPI_Comm comm, const U *const data, U *const haloBuffer, const MInt noDat=1)
Generic exchange of data.
void exchangeBuffer(const MInt noExDomains, const MInt *const exDomainId, const MInt *const recvSize, const MInt *const sendSize, const MPI_Comm comm, U *const receiveBuffer, const U *const sendBuffer, const MInt noDat=1)
Generic exchange of data.
void communicateBitsetData(const std::bitset< N > *const data, const MInt noCells, const MInt *const sortedCellId, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MInt *const noCellsToSendByDomain, const MInt *const noCellsToReceiveByDomain, const MInt dataBlockSize, std::bitset< N > *const buffer)
void reverseExchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const haloCells, const MInt *const noWindowCells, const MInt **const, const MPI_Comm comm, const U *const data, U *const windowBuffer, const MInt noDat=1)
Generic reverse exchange of data.
void exchangeBitset(const std::vector< MInt > &nghbrDomains, const std::vector< std::vector< MInt > > &haloCellVec, const std::vector< std::vector< MInt > > &windowCellVec, const MPI_Comm comm, std::bitset< N > *const data, const MInt noCells, const MInt noDat=1)
Generic exchange of data.
void communicateGlobalyOrderedData(DataType const *const sendData, const MInt noLocIds, const MInt noGlobalIds, const MInt nRows, const MInt nCols, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MIntScratchSpace &localToGlobal, const MIntScratchSpace &dataOffsets, ScratchSpace< DataType > &recvData)
Communicate (optionally) solver-structured data sorted by a global Id.
PARALLELIO_DEFAULT_BACKEND ParallelIo
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
MFloat ** m_cutCoordinates
Static indices for accessing primitive variables in nd spatial dimensions.