34 static const auto model =
NS_SA;
37 template <EulerModel model>
60 using namespace std::literals;
62 auto runningEnvironment = RunningEnvironment();
63 InitializeRunningEnvironment(runningEnvironment);
70 auto hashCoord = mesh->coords.hash();
73 log() <<
"Mesh coord hash is: [" << std::hex << hashCoord << std::dec <<
"]" << std::endl
76 if (config.timeMarchControl.partitionMeshOnly)
80 log() <<
"Mesh Is not altered; partitioning done" << std::endl;
89 mesh->ObtainLocalFactFillOrdering(*eval.symLU, config.linearSolverControl.directPrecControl);
90 mesh->ObtainSymmetricSymbolicFactorization(*eval.symLU, config.linearSolverControl.directPrecControl);
91 if (config.linearSolverControl.jacobiCode == 2)
102 eval.InitializeUDOF(u);
103 if (config.timeAverageControl.enabled)
104 wAveraged.setConstant(0.0);
105 if (config.timeMarchControl.useRestart)
108 if (!config.restartState.lastRestartFile.empty())
111 ReadRestart(config.restartState.lastRestartFile);
113 if (!config.restartState.otherRestartFile.empty())
114 ReadRestartOtherSolver(config.restartState.otherRestartFile, config.restartState.otherRestartStoreDim);
116 OutputPicker outputPicker;
117 eval.InitializeOutputPicker(outputPicker, {u, uRec, betaPP, alphaPP});
118 addOutList = outputPicker.getSubsetList(config.dataIOControl.outCellScalarNames);
124 auto initUDOF = [&](ArrayDOFV<nVarsFixed> &uu)
125 { vfv->BuildUDof(uu, nVars); };
126 auto initUREC = [&](ArrayRECV<nVarsFixed> &uu)
127 { vfv->BuildURec(uu, nVars); };
129#define DNDS_EULER_SOLVER_GET_TEMP_UDOF(name) \
130 auto __p##name = uPool.getAllocInit(initUDOF); \
131 auto &name = *__p##name;
136 tstart = MPI_Wtime();
137 tstartInternal = tstart;
149 ArrayDOFV<nVarsFixed> &crhs,
150 ArrayDOFV<nVarsFixed> &cx,
152 int iter,
real ct,
int uPos,
int reconstructionFlag)
154 cx.trans.startPersistentPull();
155 cx.trans.waitPersistentPull();
156 auto &uRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRec1 : uRec;
157 auto &JSourceC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JSource1 : JSource;
158 auto &uRecIncC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRecInc1 : uRecInc;
159 auto &alphaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? alphaPP1 : alphaPP;
160 auto &betaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? betaPP1 : betaPP;
163 typename TVFV::template TFBoundary<nVarsFixed>
164 FBoundary = [&](
const TU &UL,
const TU &UMean,
index iCell,
index iFace,
int ig,
167 TVec normOutV = normOut(Seq012);
168 Eigen::Matrix<real, dim, dim> normBase = Geom::NormBuildLocalBaseV<dim>(normOutV);
169 bool compressed =
false;
170 TU ULfixed = eval.CompressRecPart(
174 return eval.generateBoundaryValue(ULfixed, UMean, iCell, iFace, ig, normOutV, normBase, pPhy, tSimu + ct * curDtImplicit, bType,
true, 1);
176 typename TVFV::template TFBoundaryDiff<nVarsFixed>
177 FBoundaryDiff = [&](
const TU &UL,
const TU &
dU,
const TU &UMean,
index iCell,
index iFace,
int ig,
180 TVec normOutV = normOut(Seq012);
181 Eigen::Matrix<real, dim, dim> normBase = Geom::NormBuildLocalBaseV<dim>(normOutV);
182 bool compressed =
false;
183 TU ULfixed = eval.CompressRecPart(
187 TU ULfixedPlus = eval.CompressRecPart(
191 return eval.generateBoundaryValue(ULfixedPlus, UMean, iCell, iFace, ig, normOutV, normBase, pPhy, tSimu + ct * curDtImplicit, bType,
true, 1) -
192 eval.generateBoundaryValue(ULfixed, UMean, iCell, iFace, ig, normOutV, normBase, pPhy, tSimu + ct * curDtImplicit, bType,
true, 1);
195 eval.FixUMaxFilter(cx);
196 if ((iter > config.convergenceControl.nAnchorUpdateStart &&
197 (iter - config.convergenceControl.nAnchorUpdateStart - 1) % config.convergenceControl.nAnchorUpdate == 0))
199 eval.updateBCAnchors(cx, uRecC);
200 eval.updateBCProfiles(cx, uRecC);
201 eval.updateBCProfilesPressureRadialEq();
208 if (!reconstructionFlag)
210 betaPPC.setConstant(1.0);
211 alphaPP_tmp.setConstant(1.0);
212 uRecNew.setConstant(0.0);
213 eval.EvaluateRHS(crhs, JSourceC, cx, uRecNew, uRecNew, betaPPC, alphaPP_tmp,
false, tSimu + ct * curDtImplicit,
214 TEval::RHS_Ignore_Viscosity);
222 int nRec = (gradIsZero ? config.implicitReconstructionControl.nRecMultiplyForZeroedGrad : 1) *
223 config.implicitReconstructionControl.nInternalRecStep;
224 if (step <= config.implicitReconstructionControl.zeroRecForSteps ||
225 iter <= config.implicitReconstructionControl.zeroRecForStepsInternal)
228 uRec.setConstant(0.0);
232 if (config.implicitReconstructionControl.storeRecInc)
235 if (config.implicitReconstructionControl.useExplicit)
238 else if (config.implicitReconstructionControl.recLinearScheme == 0)
240 for (
int iRec = 1; iRec <= nRec; iRec++)
245 vfv->DoReconstructionIter(
250 uRecC.trans.startPersistentPull();
251 uRecC.trans.waitPersistentPull();
256 real recInc = uRecNew1.norm2();
260 if (iRec % config.implicitReconstructionControl.nRecConsolCheck == 0)
263 log() << iRec <<
" Rec inc: " << recIncBase <<
" -> " << recInc << std::endl;
265 if (recInc < recIncBase * config.implicitReconstructionControl.recThreshold)
270 else if (config.implicitReconstructionControl.recLinearScheme == 1)
272 Eigen::VectorXd meanScale;
273 if (config.implicitReconstructionControl.gmresRecScale == 1)
275 meanScale = eval.settings.refU;
276 meanScale(Seq123).setConstant(std::sqrt(meanScale(0) * meanScale(I4)));
279 meanScale.setConstant(nVars, 1.0);
283 int nGMRESrestartAll{0};
284 real gmresResidualB = 0;
285 for (
int iRec = 1; iRec <= nRec; iRec++)
287 vfv->DoReconstructionIter(
291 uRecNew.trans.startPersistentPull();
292 uRecNew.trans.waitPersistentPull();
296 gmresResidualB = uRecNew1.norm2();
300 [&](ArrayRECV<nVarsFixed> &
x, ArrayRECV<nVarsFixed> &
Ax)
302 vfv->DoReconstructionIterDiff(uRec,
x,
Ax, cx, FBoundaryDiff);
303 Ax.trans.startPersistentPull();
304 Ax.trans.waitPersistentPull();
306 [&](ArrayRECV<nVarsFixed> &
x, ArrayRECV<nVarsFixed> &MLx)
312 [&](ArrayRECV<nVarsFixed> &a, ArrayRECV<nVarsFixed> &
b) ->
real
314 return (a.dotV(
b).array() * meanScaleInv.transpose().array().square()).sum();
316 uRecNew, uRecNew1, config.implicitReconstructionControl.nGmresIter,
323 (nGMRESrestartAll % config.implicitReconstructionControl.nRecConsolCheck == 0))
325 auto fmt =
log().flags();
326 log() << std::scientific;
327 log() <<
"GMRES for Rec: " << iRec <<
" Restart " << i <<
" " << resB <<
" -> " <<
res << std::endl;
331 return res < gmresResidualB * config.implicitReconstructionControl.recThreshold;
333 uRecC.addTo(uRecNew1, -1);
337 uRecC.trans.startPersistentPull();
338 uRecC.trans.waitPersistentPull();
340 else if (config.implicitReconstructionControl.recLinearScheme == 2)
342 Eigen::Array<real, 1, Eigen::Dynamic> resB;
344 auto &pcgRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? pcgRec1 : pcgRec;
345 auto &uRecBC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRecB1 : uRecB;
348 || pcgRecC->getPHistorySize() >= config.implicitReconstructionControl.fpcgMaxPHistory)
351 vfv->DoReconstructionIter(
353 FBoundary,
true,
true,
true);
356 if (config.implicitReconstructionControl.fpcgResetScheme == 0)
358 Eigen::RowVectorXd bPrevSqr = uRecNew.dotV(uRecNew);
359 uRecNew.addTo(uRecBC, -1.0);
360 Eigen::RowVectorXd bIncSqr = uRecNew.dotV(uRecNew);
361 real maxPortion = (bIncSqr.array() / (bPrevSqr.array() +
smallReal)).sqrt().maxCoeff();
362 if (maxPortion >= config.implicitReconstructionControl.fpcgResetThres)
364 if (
mpi.rank == 0 && config.implicitReconstructionControl.fpcgResetReport > 0)
365 log() <<
"FPCG force reset at portion " << fmt::format(
"{:.4g}", maxPortion) << std::endl;
369 else if (config.implicitReconstructionControl.fpcgResetScheme == 1)
371 else if (config.implicitReconstructionControl.fpcgResetScheme == 2)
377 for (
int iRec = 1; iRec <= nRec; iRec++)
379 bool pcgConverged = pcgRecC->solve(
380 [&](ArrayRECV<nVarsFixed> &
x, ArrayRECV<nVarsFixed> &
Ax)
382 vfv->DoReconstructionIterDiff(uRec,
x,
Ax, cx, FBoundaryDiff);
383 Ax.trans.startPersistentPull();
384 Ax.trans.waitPersistentPull();
385 vfv->MatrixAMult(
Ax,
Ax);
387 [&](ArrayRECV<nVarsFixed> &
x, ArrayRECV<nVarsFixed> &Mx)
389 vfv->MatrixAMult(
x, Mx);
391 [&](ArrayRECV<nVarsFixed> &
x, ArrayRECV<nVarsFixed> &
res)
393 vfv->DoReconstructionIter(
395 FBoundary,
true,
true);
396 res.trans.startPersistentPull();
397 res.trans.waitPersistentPull();
400 [&](ArrayRECV<nVarsFixed> &a, ArrayRECV<nVarsFixed> &
b)
402 return (a.dotV(
b)).array();
404 uRecC, config.implicitReconstructionControl.nGmresIter,
405 [&](uint32_t i,
const Eigen::Array<real, 1, Eigen::Dynamic> &
res,
const Eigen::Array<real, 1, Eigen::Dynamic> &res1) ->
bool
407 if (i == 1 && iRec == 1)
413 (nPCGIterAll % config.implicitReconstructionControl.nRecConsolCheck == 0))
415 auto fmt =
log().flags();
416 log() << std::scientific << std::setprecision(3);
417 log() <<
"PCG for Rec: " << iRec <<
" Restart " << i <<
" [" << resB <<
"] -> [" << res1 <<
"]" << std::endl;
421 return (res1 / resB).maxCoeff() < config.implicitReconstructionControl.recThreshold;
426 uRecC.trans.startPersistentPull();
427 uRecC.trans.waitPersistentPull();
431 if ((model ==
NS_SA || model ==
NS_SA_3D) && eval.settings.ransForce2nd)
433 std::vector<int> mask;
436 vfv->DoReconstruction2nd(uRec, u, FBoundary, 1, mask);
440 std::vector<int> mask;
444 vfv->DoReconstruction2nd(uRec, u, FBoundary, 1, mask);
450 if (config.timeMarchControl.timeMarchIsTwoStage())
460 if (!config.implicitReconstructionControl.useExplicit && config.limiterControl.useLimiter)
465 using tLimitBatch =
typename TVFV::template tLimitBatch<nVarsFixed>;
468 const Eigen::Ref<tLimitBatch> &data) -> tLimitBatch
471 Eigen::Vector<real, I4 + 1> UC = (UL + UR)(Seq01234) * 0.5;
472 Eigen::Matrix<real, dim, dim> normBase = Geom::NormBuildLocalBaseV<dim>(
n(Seq012));
473 UC(Seq123) = normBase.transpose() * UC(Seq123);
475 auto M = Gas::IdealGas_EulerGasLeftEigenVector<dim>(UC, eval.settings.idealGasProperty.gamma);
476 M(EigenAll, Seq123) *= normBase.transpose();
478 Eigen::Matrix<real, nVarsFixed, nVarsFixed> ret(nVars, nVars);
480 ret(Seq01234, Seq01234) = M;
482 return (ret * data.transpose()).transpose();
486 const Eigen::Ref<tLimitBatch> &data) -> tLimitBatch
489 Eigen::Vector<real, I4 + 1> UC = (UL + UR)(Seq01234) * 0.5;
490 Eigen::Matrix<real, dim, dim> normBase = Geom::NormBuildLocalBaseV<dim>(
n(Seq012));
491 UC(Seq123) = normBase.transpose() * UC(Seq123);
493 auto M = Gas::IdealGas_EulerGasRightEigenVector<dim>(UC, eval.settings.idealGasProperty.gamma);
494 M(Seq123, EigenAll) = normBase * M(Seq123, EigenAll);
496 Eigen::Matrix<real, nVarsFixed, nVarsFixed> ret(nVars, nVars);
498 ret(Seq01234, Seq01234) = M;
501 return (ret * data.transpose()).transpose();
504 if (config.limiterControl.smoothIndicatorProcedure == 0)
505 vfv->template DoCalculateSmoothIndicator<nVarsFixed, 2>(
506 ifUseLimiter, (uRecC), (u),
507 std::array<int, 2>{0, I4});
508 else if (config.limiterControl.smoothIndicatorProcedure == 1)
509 vfv->template DoCalculateSmoothIndicatorV1<nVarsFixed>(
510 ifUseLimiter, (uRecC), (u),
512 [&](Eigen::Matrix<real, 1, nVarsFixed> &
v)
516 cons =
v.transpose();
522 Gas::IdealGasThermalConservative2Primitive<dim>(cons, prim, eval.settings.idealGasProperty.gamma);
523 v.setConstant(prim(I4));
531 if (config.limiterControl.limiterProcedure == 1)
532 vfv->template DoLimiterWBAP_C<nVarsFixed>(
538 iter < config.limiterControl.nPartialLimiterStartLocal && step < config.limiterControl.nPartialLimiterStart,
540 else if (config.limiterControl.limiterProcedure == 0)
541 vfv->template DoLimiterWBAP_3<nVarsFixed>(
547 iter < config.limiterControl.nPartialLimiterStartLocal && step < config.limiterControl.nPartialLimiterStart,
557 if (config.implicitReconstructionControl.storeRecInc)
562 if (config.implicitReconstructionControl.storeRecInc && config.implicitReconstructionControl.dampRecIncDTau)
565 ArrayDOFV<1> damper1;
566 vfv->BuildUDof(damper, 1);
567 vfv->BuildUDof(damper1, 1);
570 damper1 += curDtImplicit;
579 if (config.limiterControl.preserveLimited && config.limiterControl.useLimiter)
588 eval.setPassiveDiscardSource(iter <= 0);
591 alphaPPC.setConstant(1.0);
592 alphaPP_tmp.setConstant(1.0);
593 if (!config.implicitReconstructionControl.useExplicit && config.limiterControl.usePPRecLimiter)
598 if (!config.limiterControl.useLimiter)
600 eval.EvaluateURecBeta(cx, uRecLimited, betaPPC, nLimBeta, minBeta,
601 config.limiterControl.ppRecLimiterCompressToMean
602 ? TEval::EvaluateURecBeta_COMPRESS_TO_MEAN
603 : TEval::EvaluateURecBeta_DEFAULT);
606 (config.outputControl.consoleOutputEveryFix == 1 || config.outputControl.consoleOutputEveryFix == 3))
608 log() << std::scientific << std::setprecision(config.outputControl.nPrecisionConsole)
609 <<
"PPRecLimiter: nLimBeta [" << nLimBeta <<
"]"
610 <<
" minBeta[" << minBeta <<
"]" << std::endl;
612 uRecLimited.trans.startPersistentPull();
613 betaPPC.trans.startPersistentPull();
614 uRecLimited.trans.waitPersistentPull();
615 betaPPC.trans.waitPersistentPull();
620 if (config.implicitReconstructionControl.useExplicit)
621 eval.EvaluateRHS(crhs, JSourceC, cx, uRecC , uRecC ,
622 betaPPC , alphaPP_tmp ,
false, tSimu + ct * curDtImplicit,
623 TEval::RHS_Direct_2nd_Rec | (config.limiterControl.useLimiter ? TEval::RHS_Direct_2nd_Rec_use_limiter : TEval::RHS_No_Flags));
624 else if (config.limiterControl.useLimiter || config.limiterControl.usePPRecLimiter)
625 eval.EvaluateRHS(crhs, JSourceC, cx, config.limiterControl.useViscousLimited ? uRecLimited : uRecC, uRecLimited,
626 betaPPC, alphaPP_tmp, false, tSimu + ct * curDtImplicit);
628 eval.EvaluateRHS(crhs, JSourceC, cx, uRecC, uRecC,
629 betaPPC, alphaPP_tmp,
false, tSimu + ct * curDtImplicit);
631 crhs.trans.startPersistentPull();
632 crhs.trans.waitPersistentPull();
633 if (getNVars(model) > (I4 + 1) && iter <= config.others.nFreezePassiveInner)
635 for (
int i = 0; i < crhs.Size(); i++)
636 crhs[i](Eigen::seq(I4 + 1, EigenLast)).setZero();
647 ArrayDOFV<nVarsFixed> &crhs,
648 ArrayDOFV<nVarsFixed> &cx,
650 int iter,
real ct,
int uPos)
652 if (config.timeMarchControl.timeMarchIsTwoStage() && uPos == 2)
655 return eval.EvaluateRHS(crhs, JSource, cx, uRecNew, uRecNew, betaPP, alphaPP_tmp,
false, tSimu + ct * curDtImplicit,
656 TEval::RHS_Direct_2nd_Rec | TEval::RHS_Dont_Record_Bud_Flux | TEval::RHS_Dont_Update_Integration |
657 TEval::RHS_Direct_2nd_Rec_already_have_uGradBufNoLim |
658 (config.limiterControl.useLimiter ? TEval::RHS_Direct_2nd_Rec_use_limiter : TEval::RHS_No_Flags));
671 return frhsOuter(crhs, cx, dTau, iter, ct, uPos, 1);
674 auto fdtau = [&](ArrayDOFV<nVarsFixed> &cx, ArrayDOFV<1> &dTau,
real alphaDiag,
int uPos)
676 eval.FixUMaxFilter(cx);
677 cx.trans.startPersistentPull();
678 cx.trans.waitPersistentPull();
681 auto &uRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRec1 : uRec;
682 eval.EvaluateDt(dTau, cx, uRecC, CFLNow, curDtMin, 1e100, config.implicitCFLControl.useLocalDt, tSimu);
683 for (
int iS = 1; iS <= config.implicitCFLControl.nSmoothDTau; iS++)
687 dTau.trans.startPersistentPull();
688 dTau.trans.waitPersistentPull();
689 eval.MinSmoothDTau(dTau, dTauTmp);
693 dTau *= 1. / alphaDiag;
696 auto fincrement = [&](
697 ArrayDOFV<nVarsFixed> &cx,
698 ArrayDOFV<nVarsFixed> &cxInc,
702 auto &alphaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? alphaPP1 : alphaPP;
703 auto &betaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? betaPP1 : betaPP;
704 auto &uRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRec1 : uRec;
705 auto &JSourceC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JSource1 : JSource;
708 eval.EvaluateCellRHSAlpha(cx, uRecC, betaPPC, cxInc, alphaPP_tmp, nLimInc, alphaMinInc, config.timeMarchControl.incrementPPRelax,
709 2, TEval::EvaluateCellRHSAlpha_DEFAULT);
712 (config.outputControl.consoleOutputEveryFix == 1 || config.outputControl.consoleOutputEveryFix == 2))
715 log() <<
"PPIncrementLimiter: nIncrementRes[" << nLimInc <<
"] minAlpha [" << alphaMinInc <<
"]"
719 auto pUTemp = uPool.getAllocInit(initUDOF);
720 auto &uTemp = *pUTemp;
723 uTemp *= alphaPP_tmp;
729 if (config.implicitCFLControl.RANSRelax != 1)
730 for (
index i = 0; i < uTemp.Size(); i++)
731 uTemp[i]({I4, I4 + 1}) *= config.implicitCFLControl.RANSRelax;
734 eval.AddFixedIncrement(cx, uTemp,
alpha);
735 eval.AssertMeanValuePP(cx,
true);
740 auto fsolve = [&](ArrayDOFV<nVarsFixed> &cx, ArrayDOFV<nVarsFixed> &cres, ArrayDOFV<nVarsFixed> &resOther, ArrayDOFV<1> &dTau,
741 real dt,
real alphaDiag, ArrayDOFV<nVarsFixed> &cxInc,
int iter,
real ct,
int uPos)
747 eval.CentralSmoothResidual(rhsTemp, cres, uTemp);
750 auto &JDC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JD1 : JD;
751 auto &JSourceC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JSource1 : JSource;
752 auto &uRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRec1 : uRec;
753 auto &uRecIncC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRecInc1 : uRecInc;
754 auto &alphaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? alphaPP1 : alphaPP;
755 auto &betaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? betaPP1 : betaPP;
756 bool isTPMGLevel = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 2;
759 if (config.timeMarchControl.rhsFPPMode == 1 || config.timeMarchControl.rhsFPPMode == 11)
765 rhsTemp *= config.timeMarchControl.rhsFPPScale;
767 real alphaMinFRes = 1;
768 eval.EvaluateCellRHSAlpha(cx, uRecC, betaPPC, rhsTemp, alphaPP_tmp, nLimFRes, alphaMinFRes, config.timeMarchControl.rhsFPPRelax,
769 2, config.timeMarchControl.rhsFPPMode == 1 ? TEval::EvaluateCellRHSAlpha_DEFAULT : TEval::EvaluateCellRHSAlpha_MIN_IF_NOT_ONE);
773 log() << std::scientific << std::setprecision(config.outputControl.nPrecisionConsole) << std::setw(3) <<
TermColor::Red;
774 log() <<
"PPFResLimiter: nLimFRes[" << nLimFRes <<
"] minAlpha [" << alphaMinFRes <<
"]" <<
TermColor::Reset << std::endl;
779 else if (config.timeMarchControl.rhsFPPMode == 2)
784 rhsTemp *= config.timeMarchControl.rhsFPPScale;
786 real alphaMinFRes = 1;
787 eval.EvaluateCellRHSAlpha(cx, uRecC, betaPPC, rhsTemp, alphaPP_tmp, nLimFRes, alphaMinFRes, config.timeMarchControl.rhsFPPRelax,
788 2, TEval::EvaluateCellRHSAlpha_DEFAULT);
793 log() <<
"PPFResLimiter: nLimFRes[" << nLimFRes <<
"] minAlpha [" << alphaMinFRes <<
"]" <<
TermColor::Reset << std::endl;
797 dTauTmp *= alphaPP_tmp;
799 auto &dTauC = config.timeMarchControl.rhsFPPMode == 2 ? dTauTmp : dTau;
802 if (config.limiterControl.useLimiter)
803 eval.LUSGSMatrixInit(JDC, JSourceC,
804 dTauC, dt, alphaDiag,
809 eval.LUSGSMatrixInit(JDC, JSourceC,
810 dTauC, dt, alphaDiag,
819 cxInc.setConstant(0.0);
820 this->solveLinear(alphaDiag, tSimu, cres, cx, cxInc, uRecC, uRecIncC,
821 JDC, *gmres, !isTPMGLevel ? 0 : 1);
823 const auto solve_multigrid = [&](TDof &x_upper, TDof &xIncBuf, TDof &rhsBuf,
const TDof &resOther,
int mgLevelInit,
int mgLevelMax)
825 uRecNew.setConstant(0.0);
838 auto solve_multigrid_impl = [&](TDof &x_upper,
const TDof &rhs_upper,
const TDof &resOther_upper,
int mgLevel,
int mgLevelMax,
auto &solve_multigrid_impl_ref) ->
void
840 static const int use_1st_conv = 1;
842 static const int use_1st_conv_ignore_vis =
843#ifdef USE_MG_O1_NO_VISCOUS
849 std::string level_key = std::to_string(mgLevel);
850 DNDS_assert(config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).multiGridNIterPost >= 0);
851 int curMGIter = config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).multiGridNIter +
852 config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).multiGridNIterPost;
854 curMGIter = config.linearSolverControl.multiGridLPInnerNIter;
864 resOtherCurMG = rhs_upper;
865 resOtherCurMG *= alphaDiag;
866 resOtherCurMG += resOther_upper;
870 if (config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).centralSmoothInputResidual > 0)
872 resOtherCurMG.addTo(uMG1, -1. / dt);
874 rhsTemp = resOtherCurMG;
875 eval.CentralSmoothResidual(resOtherCurMG, rhsTemp, rhsTemp1, config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).centralSmoothInputResidual);
876 resOtherCurMG = rhsTemp;
877 resOtherCurMG.addTo(uMG1, 1. / dt);
881 auto call_evaluate_rhs = [&]()
884 eval.EvaluateRHS(rhsTemp, JSourceTmp, uMG1,
885 config.limiterControl.useViscousLimited ? uRecNew : uRec , uRec ,
886 betaPP , alphaPP , false, tSimu + dt * ct,
887 TEval::RHS_Direct_2nd_Rec | TEval::RHS_Dont_Record_Bud_Flux | TEval::RHS_Dont_Update_Integration |
888 TEval::RHS_Direct_2nd_Rec_already_have_uGradBufNoLim |
889 (config.limiterControl.useLimiter ? TEval::RHS_Direct_2nd_Rec_use_limiter : TEval::RHS_No_Flags) |
890 TEval::RHS_Recover_IncFScale);
891 else if (mgLevel == 2)
892 eval.EvaluateRHS(rhsTemp, JSourceTmp, uMG1,
893 config.limiterControl.useViscousLimited ? uRecNew : uRec , uRec ,
894 betaPP , alphaPP , false, tSimu + dt * ct,
895 (TEval::RHS_Direct_2nd_Rec_1st_Conv * use_1st_conv) |
896 TEval::RHS_Direct_2nd_Rec |
897 TEval::RHS_Dont_Record_Bud_Flux |
898 TEval::RHS_Dont_Update_Integration |
899 (TEval::RHS_Ignore_Viscosity * use_1st_conv_ignore_vis) |
900 TEval::RHS_Direct_2nd_Rec_already_have_uGradBufNoLim |
901 (config.limiterControl.useLimiter ? TEval::RHS_Direct_2nd_Rec_use_limiter : TEval::RHS_No_Flags) |
902 TEval::RHS_Recover_IncFScale);
907 for (
int iIterMG = 1; iIterMG <= curMGIter; iIterMG++)
913 fdtau(uMG1, dTauC, alphaDiag, uPos);
915 rhsTemp.trans.startPersistentPull();
916 rhsTemp.trans.waitPersistentPull();
920 resOtherCurMG.addTo(rhsTemp, -alphaDiag);
924 rhsTemp *= alphaDiag;
925 rhsTemp += resOtherCurMG;
926 rhsTemp.addTo(uMG1, -1. / dt);
936 eval.LUSGSMatrixInit(JDTmp, JSourceTmp, dTauC, dt, alphaDiag, uMG1, uRecNew, 0, tSimu);
938 if (iIterMG % config.linearSolverControl.multiGridLPInnerNSee == 0)
941 eval.EvaluateNorm(resNorm, rhsTemp);
943 log() << fmt::format(
"MG Level LP [{}] iter [{}] res [{:.3e}]", mgLevel, iIterMG, resNorm.transpose()) << std::endl;
945 xIncBuf.setConstant(0.0);
946 solveLinear(alphaDiag, tSimu, rhsTemp, uMG1, xIncBuf, uRecNew, uRecNew,
947 JDTmp, *gmres, mgLevel);
948 fincrement(uMG1, xIncBuf, 1.0, uPos);
953 if (mgLevel < mgLevelMax &&
954 iIterMG == config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).multiGridNIter)
957 solve_multigrid_impl_ref(uMG1, rhsTemp, resOtherCurMG, mgLevel + 1, mgLevelMax, solve_multigrid_impl_ref);
966 fdtau(x_upper, dTauC, alphaDiag, uPos);
967 frhs(rhsBuf, x_upper, dTauC, iter, ct, uPos);
968 rhsBuf.trans.startPersistentPull();
969 rhsBuf.trans.waitPersistentPull();
970 solve_multigrid_impl(x_upper, rhsBuf, resOther, mgLevelInit, mgLevelMax, solve_multigrid_impl);
973 if (config.linearSolverControl.multiGridLP >= 1 && iter > config.linearSolverControl.multiGridLPStartIter)
975 DNDS_assert(config.linearSolverControl.multiGridLP <= 2);
979 fincrement(cxTemp, cxInc, 1.0, uPos);
982 solve_multigrid(cxTemp, cxInc, resTemp, resOther, 1, config.linearSolverControl.multiGridLP);
989 if (getNVars(model) > I4 + 1 && iter <= config.others.nFreezePassiveInner)
991 for (
int i = 0; i < cres.Size(); i++)
992 cxInc[i](Eigen::seq(I4 + 1, EigenLast)).setZero();
998 auto fsolveNest = [&](
999 ArrayDOFV<nVarsFixed> &cx,
1000 ArrayDOFV<nVarsFixed> &cx1,
1001 ArrayDOFV<nVarsFixed> &crhs,
1003 const std::vector<real> &Coefs,
1004 real dt,
real alphaDiag, ArrayDOFV<nVarsFixed> &cxInc,
int iter,
int uPos)
1010 crhs.trans.startPersistentPull();
1011 crhs.trans.waitPersistentPull();
1013 eval.CentralSmoothResidual(rhsTemp, crhs, uTemp);
1016 cxInc.setConstant(0.0);
1017 auto &JDC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JD1 : JD;
1018 auto &JSourceC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JSource1 : JSource;
1019 auto &uRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRec1 : uRec;
1021 eval.EvaluateDt(dTau, cx1, uRecC, CFLNow, curDtMin, 1e100, config.implicitCFLControl.useLocalDt, tSimu);
1023 eval.LUSGSMatrixInit(JD1, JSource1,
1024 dTau, dt * Coefs[2], alphaDiag,
1028 eval.EvaluateDt(dTau, cx, uRecC, CFLNow, curDtMin, 1e100, config.implicitCFLControl.useLocalDt, tSimu);
1030 eval.LUSGSMatrixInit(JD, JSource,
1031 dTau, dt * Coefs[3], alphaDiag,
1041 if (config.linearSolverControl.gmresCode == 0 || config.linearSolverControl.gmresCode == 2)
1046 eval.UpdateLUSGSForward(alphaDiag, tSimu, crhs, cx1, cxInc, JD1, cxInc);
1047 cxInc.trans.startPersistentPull();
1048 cxInc.trans.waitPersistentPull();
1049 eval.UpdateLUSGSBackward(alphaDiag, tSimu, crhs, cx1, cxInc, JD1, cxInc);
1050 cxInc.trans.startPersistentPull();
1051 cxInc.trans.waitPersistentPull();
1053 eval.UpdateLUSGSForward(alphaDiag, tSimu, uTemp, cx, cxInc, JD, cxInc);
1054 cxInc.trans.startPersistentPull();
1055 cxInc.trans.waitPersistentPull();
1056 eval.UpdateLUSGSBackward(alphaDiag, tSimu, uTemp, cx, cxInc, JD, cxInc);
1057 cxInc.trans.startPersistentPull();
1058 cxInc.trans.waitPersistentPull();
1059 cxInc *= 1. / (dt * Coefs[1]);
1062 if (config.linearSolverControl.gmresCode != 0)
1068 [&](
decltype(u) &
x,
decltype(u) &
Ax)
1070 eval.LUSGSMatrixVec(alphaDiag, tSimu, cx,
x, JD,
Ax);
1071 Ax.trans.startPersistentPull();
1072 Ax.trans.waitPersistentPull();
1074 eval.LUSGSMatrixVec(alphaDiag, tSimu, cx1, uTemp, JD1,
Ax);
1075 Ax.trans.startPersistentPull();
1076 Ax.trans.waitPersistentPull();
1077 Ax *= dt * Coefs[1];
1078 Ax.addTo(
x, Coefs[0]);
1080 [&](
decltype(u) &
x,
decltype(u) &MLx)
1083 eval.UpdateLUSGSForward(alphaDiag, tSimu,
x, cx1, MLx, JD1, MLx);
1084 MLx.trans.startPersistentPull();
1085 MLx.trans.waitPersistentPull();
1086 eval.UpdateLUSGSBackward(alphaDiag, tSimu,
x, cx1, MLx, JD1, MLx);
1087 MLx.trans.startPersistentPull();
1088 MLx.trans.waitPersistentPull();
1090 eval.UpdateLUSGSForward(alphaDiag, tSimu, uTemp, cx, MLx, JD, MLx);
1091 MLx.trans.startPersistentPull();
1092 MLx.trans.waitPersistentPull();
1093 eval.UpdateLUSGSBackward(alphaDiag, tSimu, uTemp, cx, MLx, JD, MLx);
1094 MLx.trans.startPersistentPull();
1095 MLx.trans.waitPersistentPull();
1096 MLx *= 1. / (dt * Coefs[1]);
1098 [&](
decltype(u) &a,
decltype(u) &
b) ->
real
1102 crhs, cxInc, config.linearSolverControl.nGmresIter,
1118 if (getNVars(model) > I4 + 1 && iter <= config.others.nFreezePassiveInner)
1120 for (
int i = 0; i < crhs.Size(); i++)
1121 cxInc[i](Eigen::seq(I4 + 1, EigenLast)).setZero();
1127 auto falphaLimSource = [&](
1128 ArrayDOFV<nVarsFixed> &
v,
1131 auto &alphaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? alphaPP1 : alphaPP;
1132 for (
index i = 0; i <
v.Size(); i++)
1133 v[i] *= alphaPPC[i](0);
1136 auto fresidualIncPP = [&](
1137 ArrayDOFV<nVarsFixed> &cx,
1138 ArrayDOFV<nVarsFixed> &xPrev,
1139 ArrayDOFV<nVarsFixed> &crhs,
1140 ArrayDOFV<nVarsFixed> &rhsIncPart,
1141 const std::function<void()> &renewRhsIncPart,
1146 auto &alphaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? alphaPP1 : alphaPP;
1147 auto &betaPPC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? betaPP1 : betaPP;
1148 auto &uRecC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? uRec1 : uRec;
1149 auto &JSourceC = config.timeMarchControl.timeMarchIsTwoStage() && uPos == 1 ? JSource1 : JSource;
1153 eval.EvaluateCellRHSAlpha(xPrev, uRecC, betaPPC, rhsIncPart, alphaPP_tmp, nLimAlpha, minAlpha, 1.,
1154 2, TEval::EvaluateCellRHSAlpha_MIN_IF_NOT_ONE);
1155 alphaPP_tmp.trans.startPersistentPull();
1156 alphaPP_tmp.trans.waitPersistentPull();
1158 if (
mpi.rank == 0 &&
1159 (config.outputControl.consoleOutputEveryFix == 1 || config.outputControl.consoleOutputEveryFix == 4))
1161 log() << std::scientific << std::setprecision(config.outputControl.nPrecisionConsole)
1162 <<
"PPResidualLimiter: nLimAlpha [" << nLimAlpha <<
"]"
1163 <<
" minAlpha[" << minAlpha <<
"]" << std::endl;
1165 alphaPPC = alphaPP_tmp;
1166 if (config.limiterControl.useLimiter || config.limiterControl.usePPRecLimiter)
1167 eval.EvaluateRHS(crhs, JSourceC, cx, config.limiterControl.useViscousLimited ? uRecLimited : uRecC, uRecLimited,
1168 betaPPC, alphaPPC, false, tSimu + ct * curDtImplicit);
1170 eval.EvaluateRHS(crhs, JSourceC, cx, uRecC, uRecC,
1171 betaPPC, alphaPPC,
false, tSimu + ct * curDtImplicit);
1173 crhs.trans.startPersistentPull();
1174 crhs.trans.waitPersistentPull();
1182 eval.EvaluateCellRHSAlphaExpansion(xPrev, uRecC, betaPPC, rhsIncPart, alphaPP_tmp, nLimAlpha, minAlpha);
1183 alphaPP_tmp.trans.startPersistentPull();
1184 alphaPP_tmp.trans.waitPersistentPull();
1186 if (
mpi.rank == 0 &&
1187 (config.outputControl.consoleOutputEveryFix == 1 || config.outputControl.consoleOutputEveryFix == 4))
1189 log() << std::scientific << std::setprecision(config.outputControl.nPrecisionConsole)
1190 <<
"PPResidualLimiter - first expand: nLimAlpha [" << nLimAlpha <<
"]"
1191 <<
" minAlpha[" << minAlpha <<
"]" << std::endl;
1193 alphaPPC = alphaPP_tmp;
1194 if (config.limiterControl.useLimiter || config.limiterControl.usePPRecLimiter)
1195 eval.EvaluateRHS(crhs, JSourceC, cx, config.limiterControl.useViscousLimited ? uRecLimited : uRecC, uRecLimited,
1196 betaPPC, alphaPPC, false, tSimu + ct * curDtImplicit);
1198 eval.EvaluateRHS(crhs, JSourceC, cx, uRecC, uRecC,
1199 betaPPC, alphaPPC,
false, tSimu + ct * curDtImplicit);
1200 crhs.trans.startPersistentPull();
1201 crhs.trans.waitPersistentPull();
1206 auto fstop = [&](
int iter, ArrayDOFV<nVarsFixed> &cres,
int iStep) ->
bool
1208 return functor_fstop(iter, cres, iStep, runningEnvironment);
1215 auto fmainloop = [&]() ->
bool
1217 return functor_fmainloop(runningEnvironment);
1229 if (config.outputControl.dataOutAtInit)
1232 config.dataIOControl.outPltName +
"_" + output_stamp +
"_" +
"00000",
1235 { return ode->getLatestRHS()[iCell](0); },
1238 eval.PrintBCProfiles(config.dataIOControl.outPltName +
"_" + output_stamp +
"_" +
"00000",
1241 if (config.outputControl.restartOutAtInit)
1243 PrintRestart(config.dataIOControl.getOutRestartName() +
"_" + output_stamp +
"_" +
"00000");
1246 for (step = 1; step <= config.timeMarchControl.nTimeStep; step++)
1250 real curDtImplicitOld = curDtImplicit;
1251 curDtImplicit = config.timeMarchControl.dtImplicit;
1252 CFLNow = config.implicitCFLControl.CFL;
1253 fdtau(u, dTauTmp, 1., 0);
1254 curDtImplicit = std::min(curDtMin / CFLNow * config.timeMarchControl.dtCFLLimitScale, curDtImplicit);
1256 if (config.timeMarchControl.useDtPPLimit)
1261 dTauTmp.setConstant(curDtImplicit * config.timeMarchControl.dtPPLimitScale);
1262 frhsOuter(rhsTemp, u, dTauTmp, 1, 0.0, 0, 0);
1264 rhsTemp *= curDtImplicit * config.timeMarchControl.dtPPLimitScale;
1267 eval.EvaluateCellRHSAlpha(u, uRec, alphaPP, rhsTemp, alphaPP_tmp, nLim, minLim, config.timeMarchControl.dtPPLimitRelax,
1268 1, TEval::EvaluateCellRHSAlpha_DEFAULT);
1270 curDtImplicit = std::min(curDtImplicit, minLim * curDtImplicit);
1271 if (curDtImplicitHistory.size() && curDtImplicit > curDtImplicitHistory.back() * config.timeMarchControl.dtIncreaseLimit)
1273 curDtImplicit = curDtImplicitHistory.back() * config.timeMarchControl.dtIncreaseLimit;
1275 if (
mpi.rank == 0 && nLim)
1277 log() <<
"##################################################################" << std::endl;
1278 log() << fmt::format(
"At Step [{:d}] t [{:.8g}] Changing dt to [{}], using PP", step, tSimu, curDtImplicit) << std::endl;
1279 log() <<
"##################################################################" << std::endl;
1283 curDtImplicit = std::max(curDtImplicit, config.timeMarchControl.dtImplicitMin);
1286 if (tSimu + curDtImplicit >= nextTout - curDtImplicit *
smallReal)
1289 curDtImplicit = std::max(0.0, nextTout - tSimu);
1292 if (config.timeMarchControl.useImplicitPP)
1294 switch (config.timeMarchControl.odeCode)
1297 std::dynamic_pointer_cast<ODE::ImplicitBDFDualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
ode)
1303 config.convergenceControl.nTimeStepInternal,
1313 auto odeVBDF = std::dynamic_pointer_cast<ODE::ImplicitVBDFDualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
ode);
1314 odeVBDF->LimitDt_StepPPV2(
1315 u, [&](ArrayDOFV<nVarsFixed> &u, ArrayDOFV<nVarsFixed> &uInc) ->
real
1317 eval.EvaluateCellRHSAlpha(u, uRec, alphaPP, uInc, alphaPP_tmp, nLimAlpha, minAlpha, 1.,
1318 1, TEval::EvaluateCellRHSAlpha_MIN_IF_NOT_ONE);
1321 if (curDtImplicit > curDtImplicitOld)
1323 dtIncreaseCounter++;
1324 if (dtIncreaseCounter > config.timeMarchControl.dtIncreaseAfterCount)
1325 curDtImplicit = std::min(curDtImplicitOld * config.timeMarchControl.dtIncreaseLimit, curDtImplicit);
1327 curDtImplicit = curDtImplicitOld;
1331 dtIncreaseCounter = 0;
1336 log() <<
"##################################################################" << std::endl;
1337 log() << fmt::format(
"At Step [{:d}] t [{:.8g}] Changing dt to {}", step, tSimu, curDtImplicit) << std::endl;
1338 log() <<
"##################################################################" << std::endl;
1345 config.convergenceControl.nTimeStepInternal,
1358 else if (config.timeMarchControl.timeMarchIsTwoStage() &&
false)
1359 std::dynamic_pointer_cast<ODE::ImplicitHermite3SimpleJacobianDualStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
ode)
1365 config.convergenceControl.nTimeStepInternal,
1375 config.convergenceControl.nTimeStepInternal,
1378 curDtImplicitHistory.push_back(curDtImplicit);
1386 template <EulerModel model>
1409 TDof &cres, TDof &cx, TDof &cxInc, TRec &uRecC, TRec uRecIncC,
1410 JacobianDiagBlock<nVarsFixed> &JDC, tGMRES_u &gmres,
int gridLevel)
1413 auto &eval = *pEval;
1414 auto initUDOF = [&](ArrayDOFV<nVarsFixed> &uu)
1415 { vfv->BuildUDof(uu, nVars); };
1417 TU sgsRes(nVars), sgsRes0(nVars);
1418 bool inputIsZero{
true}, hasLUDone{
false};
1420 typename TVFV::template TFBoundary<nVarsFixed>
1421 FBoundary = [&](
const TU &UL,
const TU &UMean,
index iCell,
index iFace,
int iG,
1428 DNDS_assert(gridLevel <= config.linearSolverControl.coarseGridLinearSolverControlList.size());
1429 std::string level_key = std::to_string(gridLevel);
1432 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).gmresCode
1433 : config.linearSolverControl.gmresCode;
1434 bool initWithLastURecInc =
1437 : config.linearSolverControl.initWithLastURecInc;
1441 : config.linearSolverControl.sgsWithRec;
1444 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).sgsIter
1445 : config.linearSolverControl.sgsIter;
1446 int nSgsConsoleCheck =
1448 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).nSgsConsoleCheck
1449 : config.linearSolverControl.nSgsConsoleCheck;
1452 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).gmresScale
1453 : config.linearSolverControl.gmresScale;
1456 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).nGmresIter
1457 : config.linearSolverControl.nGmresIter;
1458 int nGmresConsoleCheck =
1460 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).nGmresConsoleCheck
1461 : config.linearSolverControl.nGmresConsoleCheck;
1462 if (gmresCode == 0 || gmresCode == 2)
1466 if (initWithLastURecInc)
1468 DNDS_assert(config.implicitReconstructionControl.storeRecInc);
1469 eval.UpdateSGSWithRec(alphaDiag, t, cres, cx, uRecC, cxInc, uRecIncC, JDC,
true, sgsRes);
1473 cxInc.trans.startPersistentPull();
1474 cxInc.trans.waitPersistentPull();
1475 eval.UpdateSGSWithRec(alphaDiag, t, cres, cx, uRecC, cxInc, uRecIncC, JDC,
false, sgsRes);
1476 cxInc.trans.startPersistentPull();
1477 cxInc.trans.waitPersistentPull();
1482 doPrecondition(alphaDiag, t, cres, cx, cxInc, uTemp, JDC, sgsRes, inputIsZero, hasLUDone, gridLevel);
1485 if (sgsWithRec != 0)
1486 uRecNew.setConstant(0.0);
1487 for (
int iterSGS = 1; iterSGS <= sgsIter; iterSGS++)
1489 if (sgsWithRec != 0)
1491 vfv->DoReconstructionIter(
1492 uRecNew, uRecNew1, cxInc,
1495 uRecNew.trans.startPersistentPull();
1496 uRecNew.trans.waitPersistentPull();
1497 eval.UpdateSGSWithRec(alphaDiag, t, cres, cx, uRecC, cxInc, uRecNew, JDC,
true, sgsRes);
1498 cxInc.trans.startPersistentPull();
1499 cxInc.trans.waitPersistentPull();
1500 eval.UpdateSGSWithRec(alphaDiag, t, cres, cx, uRecC, cxInc, uRecNew, JDC,
false, sgsRes);
1501 cxInc.trans.startPersistentPull();
1502 cxInc.trans.waitPersistentPull();
1507 doPrecondition(alphaDiag, t, cres, cx, cxInc, uTemp, JDC, sgsRes, inputIsZero, hasLUDone, gridLevel);
1512 if (
mpi.rank == 0 && iterSGS % nSgsConsoleCheck == 0)
1513 log() << std::scientific <<
"SGS1 " << std::to_string(iterSGS)
1514 <<
" [" << sgsRes0.transpose() <<
"] ->"
1515 <<
" [" << sgsRes.transpose() <<
"] " << std::endl;
1518 Eigen::VectorXd meanScale;
1519 if (gmresScale == 1)
1521 meanScale = eval.settings.refU;
1522 meanScale(Seq123).setConstant(std::sqrt(meanScale(0) * meanScale(I4)));
1528 else if (gmresScale == 2)
1530 eval.EvaluateNorm(meanScale, cx, 1,
true,
true);
1531 meanScale(Seq123).setConstant(meanScale(Seq123).norm());
1535 meanScale.setOnes(nVars);
1545 [&](TDof &
x, TDof &
Ax)
1547 eval.LUSGSMatrixVec(alphaDiag, t, cx,
x, JDC,
Ax);
1548 Ax.trans.startPersistentPull();
1549 Ax.trans.waitPersistentPull();
1551 [&](TDof &
x, TDof &MLx)
1554 MLx.setConstant(0.0), inputIsZero =
true;
1555 doPrecondition(alphaDiag, t,
x, cx, MLx, uTemp, JDC, sgsRes, inputIsZero, hasLUDone, gridLevel);
1556 for (
int i = 0; i < sgsIter; i++)
1558 doPrecondition(alphaDiag, t,
x, cx, MLx, uTemp, JDC, sgsRes, inputIsZero, hasLUDone, gridLevel);
1561 [&](TDof &a, TDof &
b) ->
real
1563 return a.dot(
b, meanScaleInv.array(), meanScaleInv.array());
1565 cres, cxInc, nGmresIter,
1568 if (i > 0 && i % nGmresConsoleCheck == 0)
1572 log() << std::scientific;
1573 log() <<
"GMRES: " << i <<
" " << resB <<
" -> " <<
res << std::endl;
1583 template <EulerModel model>
1606 TDof &cres, TDof &cx, TDof &cxInc, TDof &uTemp,
1607 JacobianDiagBlock<nVarsFixed> &JDC, TU &sgsRes,
bool &inputIsZero,
bool &hasLUDone,
int gridLevel)
1610 auto &eval = *pEval;
1611 auto initUDOF = [&](ArrayDOFV<nVarsFixed> &uu)
1612 { vfv->BuildUDof(uu, nVars); };
1617 std::string level_key = std::to_string(gridLevel);
1620 ? config.linearSolverControl.coarseGridLinearSolverControlList.at(level_key).jacobiCode
1621 : config.linearSolverControl.jacobiCode;
1623 if (jacobiCode <= 1)
1625 bool useGS = jacobiCode == 1;
1626 eval.UpdateSGS(alphaDiag, t, cres, cx, cxInc, uTemp, JDC,
true, useGS, sgsRes);
1628 cxInc.trans.startPersistentPull();
1629 cxInc.trans.waitPersistentPull();
1630 eval.UpdateSGS(alphaDiag, t, cres, cx, cxInc, uTemp, JDC,
false, useGS, sgsRes);
1632 cxInc.trans.startPersistentPull();
1633 cxInc.trans.waitPersistentPull();
1640 inputIsZero =
false;
1642 else if (jacobiCode == 2)
1645 DNDS_assert_info(config.linearSolverControl.directPrecControl.useDirectPrec,
"need to use config.linearSolverControl.directPrecControl.useDirectPrec first !");
1647 eval.LUSGSMatrixToJacobianLU(alphaDiag, t, cx, JDC, *JLocalLU), hasLUDone =
true;
1648 for (
int iii = 0; iii < 2; iii++)
1650 eval.LUSGSMatrixSolveJacobianLU(alphaDiag, t, cres, cx, cxInc, uTemp, rhsTemp, JDC, *JLocalLU, inputIsZero, sgsRes);
1651 uTemp.SwapDataFatherSon(cxInc);
1653 cxInc.trans.startPersistentPull();
1654 cxInc.trans.waitPersistentPull();
1655 inputIsZero =
false;
1662 template <EulerModel model>
1676 if (config.timeMarchControl.partitionMeshOnly)
1682 runningEnvironment.pEval = pEval;
1688 logErr = LogErrInitialize();
1694 auto buildDOF = [&](ArrayDOFV<nVarsFixed> &data)
1696 vfv->BuildUDof(data, nVars);
1698 auto buildScalar = [&](ArrayDOFV<1> &data)
1700 vfv->BuildUDof(data, 1);
1703 if (config.timeMarchControl.steadyQuit)
1706 log() <<
"Using steady!" << std::endl;
1707 config.timeMarchControl.odeCode = 1;
1708 config.timeMarchControl.nTimeStep = 1;
1709 config.timeMarchControl.dtImplicit = 1e100;
1710 config.timeMarchControl.useDtPPLimit =
false;
1711 config.timeMarchControl.dtCFLLimitScale = 1e110;
1712 config.outputControl.tDataOut = 1e300;
1714 switch (config.timeMarchControl.odeCode)
1718 log() <<
"=== ODE: ESDIRK4 " << std::endl;
1719 ode = std::make_shared<ODE::ImplicitSDIRK4DualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1721 buildDOF, buildScalar,
1726 log() <<
"=== ODE: SSP-SDIRK4 " << std::endl;
1727 ode = std::make_shared<ODE::ImplicitSDIRK4DualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1729 buildDOF, buildScalar,
1736 log() <<
"=== ODE: " + std::vector<std::string>{
"ESDIRK3",
"Trapz",
"ESDIRK2"}.at(config.timeMarchControl.odeCode - 202) << std::endl;
1737 ode = std::make_shared<ODE::ImplicitSDIRK4DualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1739 buildDOF, buildScalar,
1740 config.timeMarchControl.odeCode - 200);
1744 if (
mpi.rank == 0 && config.timeMarchControl.odeCode == 1)
1745 log() <<
"=== ODE: BDF2 " << std::endl;
1746 if (
mpi.rank == 0 && config.timeMarchControl.odeCode == 103)
1747 log() <<
"=== ODE: Backward Euler " << std::endl;
1748 ode = std::make_shared<ODE::ImplicitVBDFDualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1750 buildDOF, buildScalar,
1751 config.timeMarchControl.odeCode == 1 ? 2 : 1);
1755 log() <<
"=== ODE: VBDF2 " << std::endl;
1756 ode = std::make_shared<ODE::ImplicitVBDFDualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1758 buildDOF, buildScalar,
1763 log() <<
"=== ODE: SSPRK4 " << std::endl;
1764 ode = std::make_shared<ODE::ExplicitSSPRK3TimeStepAsImplicitDualTimeStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1766 buildDOF, buildScalar,
1770 DNDS_assert(config.timeMarchControl.timeMarchIsTwoStage());
1772 log() <<
"=== ODE: Hermite3 (simple jacobian) " << std::endl;
1773 ode = std::make_shared<ODE::ImplicitHermite3SimpleJacobianDualStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1775 buildDOF, buildScalar,
1776 config.timeMarchControl.odeSetting1 == 0 ? 0.55 : config.timeMarchControl.odeSetting1,
1777 std::round(config.timeMarchControl.odeSetting2),
1779 config.timeMarchControl.odeSetting3 == 0 ? 0.9146 : config.timeMarchControl.odeSetting3,
1781 std::round(config.timeMarchControl.odeSetting4)
1787 DNDS_assert(config.timeMarchControl.timeMarchIsTwoStage());
1789 log() <<
"=== ODE: Hermite3 (simple jacobian) " + fmt::format(
"Mask {}", config.timeMarchControl.odeCode - 411)
1791 ode = std::make_shared<ODE::ImplicitHermite3SimpleJacobianDualStep<ArrayDOFV<nVarsFixed>, ArrayDOFV<1>>>(
1793 buildDOF, buildScalar,
1794 config.timeMarchControl.odeSetting1 == 0 ? 0.55 : config.timeMarchControl.odeSetting1,
1795 std::round(config.timeMarchControl.odeSetting2),
1797 config.timeMarchControl.odeSetting3 == 0 ? 0.9146 : config.timeMarchControl.odeSetting3,
1798 config.timeMarchControl.odeSetting4 == 0 ? 0.0 : config.timeMarchControl.odeSetting4,
1799 config.timeMarchControl.odeCode - 411
1805 if (config.timeMarchControl.odeSettingsExtra.is_object())
1806 ode->SetExtraParams(config.timeMarchControl.odeSettingsExtra);
1808 if (config.timeMarchControl.useImplicitPP)
1810 DNDS_assert(config.timeMarchControl.odeCode == 1 || config.timeMarchControl.odeCode == 102);
1819 if (config.linearSolverControl.gmresCode == 1 ||
1820 config.linearSolverControl.gmresCode == 2)
1821 gmres = std::make_unique<tGMRES_u>(
1822 config.linearSolverControl.nGmresSpace,
1823 [&](
decltype(u) &data)
1825 vfv->BuildUDof(data, nVars);
1828 if (config.implicitReconstructionControl.recLinearScheme == 1)
1829 gmresRec = std::make_unique<tGMRES_uRec>(
1830 config.implicitReconstructionControl.nGmresSpace,
1831 [&](
decltype(uRec) &data)
1833 vfv->BuildURec(data, nVars);
1836 if (config.implicitReconstructionControl.recLinearScheme == 2)
1837 pcgRec = std::make_unique<tPCG_uRec>(
1838 [&](
decltype(uRec) &data)
1840 vfv->BuildURec(data, nVars);
1843 if (config.implicitReconstructionControl.recLinearScheme == 2 || config.timeMarchControl.timeMarchIsTwoStage())
1844 pcgRec1 = std::make_unique<tPCG_uRec>(
1845 [&](
decltype(uRec) &data)
1847 vfv->BuildURec(data, nVars);
1853 tstart = MPI_Wtime();
1854 tstartInternal = tstart;
1857 resBaseC.resize(nVars);
1858 resBaseCInternal.resize(nVars);
1859 resBaseC.setConstant(config.convergenceControl.res_base);
1863 nextTout = std::min(config.outputControl.tDataOut, config.timeMarchControl.tEnd);
1864 nextStepOut = config.outputControl.nDataOut;
1865 nextStepOutC = config.outputControl.nDataOutC;
1866 nextStepRestart = config.outputControl.nRestartOut;
1867 nextStepRestartC = config.outputControl.nRestartOutC;
1868 nextStepOutAverage = config.outputControl.nTimeAverageOut;
1869 nextStepOutAverageC = config.outputControl.nTimeAverageOutC;
1871 CFLNow = config.implicitCFLControl.CFL;
1874 curDtImplicit = config.timeMarchControl.dtImplicit;
1878 dtIncreaseCounter = 0;
#define DNDS_MAKE_SSP(ssp,...)
Eigen extensions: to_string, an fmt-safe wrapper, and fmt formatter specialisations for dense Eigen m...
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Top-level solver orchestrator for compressible Navier-Stokes / Euler simulations.
#define DNDS_EULERSOLVER_RUNNINGENV_GET_REF_LIST
#define DNDS_EULER_SOLVER_GET_TEMP_UDOF(name)
#define DNDS_FV_EULEREVALUATOR_GET_FIXED_EIGEN_SEQS
Declares compile-time Eigen index sequences for sub-vector access into conservative state vectors.
#define DNDS_MPI_InsertCheck(mpi, info)
Debug helper: barrier + print "CHECK <info> RANK r @ fn @ file:line".
#define DNDS_SWITCH_INTELLISENSE(real, intellisense)
Analytic isentropic-vortex solutions for inviscid accuracy verification.
void RunImplicitEuler()
Run the main implicit time-marching loop.
void solveLinear(real alphaDiag, real t, TDof &cres, TDof &cx, TDof &cxInc, TRec &uRecC, TRec uRecIncC, JacobianDiagBlock< nVarsFixed > &JDC, tGMRES_u &gmres, int gridLevel)
Solve the implicit linear system at a given grid level.
void InitializeRunningEnvironment(RunningEnvironment &env)
Populate a RunningEnvironment with allocated solvers, loggers, and initial state.
void doPrecondition(real alphaDiag, real t, TDof &crhs, TDof &cx, TDof &cxInc, TDof &uTemp, JacobianDiagBlock< nVarsFixed > &JDC, TU &sgsRes, bool &inputIsZero, bool &hasLUDone, int gridLevel)
Apply the preconditioner (SGS sweeps or ILU) to a right-hand side vector.
Eigen::Vector< real, nVarsFlow > TU
Fixed-size 5-component conservative state vector (rho, rhoU, rhoV, rhoW, E).
@ NS_2EQ_3D
NS + 2-equation RANS, 3D geometry (7 vars).
@ NS_SA_3D
NS + Spalart-Allmaras, 3D geometry (6 vars).
@ NS_SA
NS + Spalart-Allmaras, 2D geometry (6 vars).
@ NS_2EQ
NS + 2-equation RANS, 2D geometry (7 vars).
constexpr std::string_view Reset
ANSI escape: reset all attributes.
constexpr std::string_view Red
ANSI escape: bright red foreground.
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
constexpr T sqr(const T &a)
a * a, constexpr. Works for all arithmetic types.
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
DNDS_CONSTANT const real smallReal
Loose lower bound (for iterative-solver tolerances etc.).
std::ostream & log()
Return the current DNDSR log stream (either std::cout or the installed file).
PerformanceTimer & Timer()
Short-hand accessor to the PerformanceTimer singleton.
DNDS_CONSTANT const real veryLargeReal
Catch-all upper bound ("practically infinity") for physical scalars.
Eigen::Matrix wrapper that hides begin/end from fmt.
Eigen::Matrix< real, 5, 1 > v
Eigen::Vector< real, 5 > dU
std::cout<< "[ESDIRK2-sc4] err1="<< std::scientific<< res.err_coarse<< " err2="<< res.err_fine<< " order="<< std::fixed<< res.order<< std::endl;CHECK(res.order > 1.8);CHECK(res.order< 2.5);}TEST_CASE("VBDF k=1: 1st-order on oscillator"){ ODE::ImplicitVBDFDualTimeStep< Vec2, Vec2 > ode(1, v2init, v2init, 1)
Eigen::Vector3d n(1.0, 0.0, 0.0)