17 static const auto model =
NS_SA;
20 template <EulerModel model>, )
50 if (settings.useRoeJacobian)
54#if defined(DNDS_DIST_MT_USE_OMP)
55# pragma omp parallel for schedule(runtime)
57 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
59 auto c2f = mesh->cell2face[iCell];
62 real fpDivisor = 1.0 / dTau[iCell](0) + 1.0 / dt;
63 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
65 index iFace = c2f[ic2f];
66 fpDivisor += (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) * lambdaFace[iFace] / vfv->GetCellVol(iCell);
67 if (!settings.useRoeJacobian)
70 auto f2c = mesh->face2cell[iFace];
71 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
72 rowsize iCellAtFace = f2c[0] == iCell ? 0 : 1;
73 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
74 (iCellAtFace ? -1 : 1);
79 uj = this->generateBoundaryValue(UL, u[iCell], iCell, iFace, -1,
81 Geom::NormBuildLocalBaseV<dim>(unitNorm),
82 vfv->GetFaceQuadraturePPhys(iFace, -1),
84 mesh->GetFaceZone(iFace),
90 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
91 TJacobianU jacII = fluxJacobian0_Right_Times_du_AsMatrix(
93 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
94 mesh->GetFaceZone(iFace),
95 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
96 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
102 JBC.resize(nVars, nVars);
104 for (
int i = 0; i < nVars; i++)
106 TU VE = JBC(EigenAll, i);
107 JBC(EigenAll, i) = this->generateBoundaryValue(VE, u[iCell], iCell, iFace, -1,
109 Geom::NormBuildLocalBaseV<dim>(unitNorm),
110 vfv->GetFaceQuadraturePPhys(iFace, -1),
112 mesh->GetFaceZone(iFace),
115 TJacobianU jacIJ = fluxJacobian0_Right_Times_du_AsMatrix(
117 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
118 mesh->GetFaceZone(iFace),
119 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
120 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
123 JDiag.getBlock(iCell) += (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) * (jacIJ * JBC);
125 JDiag.getBlock(iCell) += (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) * jacII;
130 if (settings.useRoeJacobian)
131 JDiag.getBlock(iCell).diagonal().array() += 1.0 / dTau[iCell](0) + 1.0 / dt;
135 JDiag.getBlock(iCell).diagonal().setConstant(fpDivisor);
137 JDiag.getDiag(iCell).setConstant(fpDivisor);
144 if (!settings.ignoreSourceTerm)
147 JDiag.getBlock(iCell) += alphaDiag * JSource.getBlock(iCell);
149 JDiag.getDiag(iCell) += alphaDiag * JSource.getDiag(iCell);
162 template <EulerModel model>, )
175 void EulerEvaluator<model>::LUSGSMatrixVec(
178 ArrayDOFV<nVarsFixed> &u,
179 ArrayDOFV<nVarsFixed> &uInc,
180 JacobianDiagBlock<nVarsFixed> &JDiag,
181 ArrayDOFV<nVarsFixed> &AuInc)
187 auto cellOp = [&](
index iCell) __attribute__((always_inline)) {
191#if defined(DNDS_DIST_MT_USE_OMP)
192# pragma omp parallel for schedule(static)
194 for (
int iPart = 0; iPart < mesh->NLocalParts(); iPart++)
195 for (
index iScan = mesh->LocalPartStart(iPart); iScan < mesh->LocalPartEnd(iPart); iScan++)
200 auto c2f = mesh->cell2face[iCell];
201 TU uIncNewBuf(cnvars);
202 uIncNewBuf.setZero();
203 auto uINCi = uInc[iCell];
207 std::cout << uINCi << std::endl;
211 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
213 index iFace = c2f[ic2f];
214 auto f2c = mesh->face2cell[iFace];
215 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
216 index iCellAtFace = f2c[0] == iCell ? 0 : 1;
217 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
218 (iCellAtFace ? -1 : 1);
224 TU uINCj = uInc[iCellOther];
225 TU uj = u[iCellOther];
226 this->UFromOtherCell(uINCj, iFace, iCell, iCellOther, iCellAtFace);
227 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
236 fInc = fluxJacobian0_Right_Times_du(
238 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
239 Geom::BC_ID_INTERNAL, uINCj,
240 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
241 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
243 settings.useRoeJacobian);
246 uIncNewBuf -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
248 if (uIncNewBuf.hasNaN() || (!uIncNewBuf.allFinite()))
251 << fInc.transpose() << std::endl
252 << uInc[iCellOther].transpose() << std::endl;
253 DNDS_assert(!(uIncNewBuf.hasNaN() || (!uIncNewBuf.allFinite())));
260 AuInc[iCell] = JDiag.MatVecLeft(iCell, uInc[iCell]) - uIncNewBuf;
262 auto AuIncI = AuInc[iCell];
265 std::cout << AuIncI.transpose() << std::endl
266 << uINCi.transpose() << std::endl
267 << u[iCell].transpose() << std::endl
268 << JDiag.getValue(iCell) << std::endl
269 << iCell << std::endl;
277 template <EulerModel model>, )
290 void EulerEvaluator<model>::LUSGSMatrixToJacobianLU(
292 ArrayDOFV<nVarsFixed> &u,
293 JacobianDiagBlock<nVarsFixed> &JDiag,
294 JacobianLocalLU<nVarsFixed> &jacLU)
300#if defined(DNDS_DIST_MT_USE_OMP)
301# pragma omp parallel for schedule(static)
303 for (
int iPart = 0; iPart < mesh->NLocalParts(); iPart++)
304 for (
index iScan = mesh->LocalPartStart(iPart); iScan < mesh->LocalPartEnd(iPart); iScan++)
307 auto c2f = mesh->cell2face[iCell];
308 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
310 index iFace = c2f[ic2f];
311 auto f2c = mesh->face2cell[iFace];
312 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
313 rowsize iCellAtFace = f2c[0] == iCell ? 0 : 1;
314 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
315 (iCellAtFace ? -1 : 1);
316 if (iCellOther !=
UnInitIndex && iCellOther != iCell &&
317 iCellOther < mesh->LocalPartEnd(iPart) && iCellOther >= mesh->LocalPartStart(iPart))
319 TU uj = u[iCellOther];
320 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
321 int iC2CInLocal = -1;
322 for (
int ic2c = 0; ic2c < mesh->cell2cellFaceVLocalParts[iCell].size(); ic2c++)
323 if (iCellOther == mesh->cell2cellFaceVLocalParts[iCell][ic2c])
328 jacIJ = fluxJacobian0_Right_Times_du_AsMatrix(
330 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
331 Geom::BC_ID_INTERNAL,
332 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
333 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
335 settings.useRoeJacobian);
337 auto faceID = mesh->GetFaceZone(iFace);
338 mesh->CellOtherCellPeriodicHandle(
341 { jacIJ(EigenAll, Seq123) =
342 mesh->periodicInfo.TransVectorBack<dim, nVarsFixed>(
343 jacIJ(EigenAll, Seq123).transpose(), faceID)
346 { jacIJ(EigenAll, Seq123) =
347 mesh->periodicInfo.TransVector<dim, nVarsFixed>(
348 jacIJ(EigenAll, Seq123).transpose(), faceID)
350 jacLU.LDU(iCell, symLU->cell2cellFaceVLocal2FullRowPos[iCell][iC2CInLocal]) =
351 (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) * jacIJ;
354 jacLU.GetDiag(iCell) = JDiag.getValue(iCell);
357 jacLU.InPlaceDecompose();
362 template <EulerModel model>, template <>)
393 index nCellDist = mesh->NumCell();
394 for (
index iScan = 0; iScan < nCellDist; iScan++)
398 auto c2f = mesh->cell2face[iCell];
399 TU uIncNewBuf(nVars);
400 auto RHSI = rhs[iCell];
403 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
405 index iFace = c2f[ic2f];
406 auto f2c = mesh->face2cell[iFace];
407 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
408 index iCellAtFace = f2c[0] == iCell ? 0 : 1;
409 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
410 (iCellAtFace ? -1 : 1);
413 index iScanOther = iCellOther;
414 if (iScanOther < iScan)
416 TU uINCj = uInc[iCellOther];
417 TU uj = u[iCellOther];
418 this->UFromOtherCell(uINCj, iFace, iCell, iCellOther, iCellAtFace);
419 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
421 TU fInc = fluxJacobian0_Right_Times_du(
423 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
424 Geom::BC_ID_INTERNAL, uINCj,
425 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
426 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
427 settings.useRoeJacobian);
429 uIncNewBuf -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
432 if ((!uIncNewBuf.allFinite()))
434 std::cout << RHSI.transpose() << std::endl
435 << fInc.transpose() << std::endl
436 << uINCj.transpose() << std::endl;
442 auto uIncNewI = uIncNew[iCell];
445 if (uIncNewI.hasNaN())
447 std::cout << uIncNewI.transpose() << std::endl
448 << uIncNewBuf.transpose() << std::endl
449 << JDiag.
getValue(iCell) << std::endl
450 << iCell << std::endl;
458 template <EulerModel model>, template <>)
474 ArrayDOFV<nVarsFixed> &rhs,
475 ArrayDOFV<nVarsFixed> &u,
476 ArrayDOFV<nVarsFixed> &uInc,
477 JacobianDiagBlock<nVarsFixed> &JDiag,
478 ArrayDOFV<nVarsFixed> &uIncNew)
485 index nCellDist = mesh->NumCell();
486 for (
index iScan = nCellDist - 1; iScan >= 0; iScan--)
490 auto c2f = mesh->cell2face[iCell];
491 TU uIncNewBuf(cnvars);
492 uIncNewBuf.setZero();
494 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
496 index iFace = c2f[ic2f];
497 auto f2c = mesh->face2cell[iFace];
498 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
499 index iCellAtFace = f2c[0] == iCell ? 0 : 1;
500 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
501 (iCellAtFace ? -1 : 1);
504 index iScanOther = iCellOther;
505 if (iScanOther > iScan)
507 TU uINCj = uInc[iCellOther];
508 TU uj = u[iCellOther];
509 this->UFromOtherCell(uINCj, iFace, iCell, iCellOther, iCellAtFace);
510 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
512 TU fInc = fluxJacobian0_Right_Times_du(
514 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
515 Geom::BC_ID_INTERNAL, uINCj,
516 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
517 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
518 settings.useRoeJacobian);
520 uIncNewBuf -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
525 auto uIncNewI = uIncNew[iCell];
526 uIncNewI += JDiag.MatVecLeftInvert(iCell, uIncNewBuf);
531 template <EulerModel model>
557 bool forward,
bool gsUpdate,
TU &sumInc,
565 const index nCellDist = mesh->NumCell();
566 sumInc.setZero(cnvars);
568#if defined(DNDS_DIST_MT_USE_OMP)
569 auto cellOp = [&](
index iScanStart,
index iScanEnd)
572 const index iScanStart{0}, iScanEnd(nCellDist);
574 for (
index iScan = iScanStart; iScan < iScanEnd; iScan++)
576 index iCell = forward ? iScan : iScanEnd - 1 - (iScan - iScanStart);
578 auto c2f = mesh->cell2face[iCell];
579 TU uIncNewBuf(nVars);
580 auto RHSI = rhs[iCell];
584 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
586 index iFace = c2f[ic2f];
587 auto btype = mesh->GetFaceZone(iFace);
588 auto f2c = mesh->face2cell[iFace];
589 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
590 index iCellAtFace = f2c[0] == iCell ? 0 : 1;
591 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
592 (iCellAtFace ? -1 : 1);
595 if (iCell != iCellOther)
598 bool iCellOtherIsThisPart = iScanStart <= iCellOther && iCellOther < iScanEnd;
599 bool gsUseNew = gsUpdate && iCellOtherIsThisPart && (forward ? (iCellOther < iCell) : (iCellOther > iCell));
603 if (uIncIsZero && !gsUseNew)
606 TU uINCj = gsUseNew ? uIncNew[iCellOther] : uInc[iCellOther];
607 TU uj = u[iCellOther];
608 this->UFromOtherCell(uINCj, iFace, iCell, iCellOther, iCellAtFace);
609 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
612 fInc = fluxJacobian0_Right_Times_du(
614 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
615 Geom::BC_ID_INTERNAL, uINCj,
616 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
617 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
619 settings.useRoeJacobian);
622 uIncNewBuf -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
625 if ((!uIncNewBuf.allFinite()))
627 std::cout << RHSI.transpose() << std::endl
628 << fInc.transpose() << std::endl
629 << uINCj.transpose() << std::endl;
661 auto uIncNewI = uIncNew[iCell];
662 TU uIncOld = uIncNewI;
665 sumInc.array() += (uIncNewI - uIncOld).array().abs();
667 if (uIncNewI.hasNaN())
669 std::cout << uIncNewI.transpose() << std::endl
670 << uIncNewBuf.transpose() << std::endl
671 << JDiag.
getValue(iCell) << std::endl
672 << iCell << std::endl;
676#if defined(DNDS_DIST_MT_USE_OMP)
680#if defined(DNDS_DIST_MT_USE_OMP)
681# pragma omp declare reduction(TUAdd:TU : omp_out += omp_in) initializer(omp_priv = omp_orig)
682# pragma omp parallel for schedule(static) reduction(TUAdd : sumInc)
683 for (
int iPart = 0; iPart < mesh->NLocalParts(); iPart++)
684 cellOp(mesh->LocalPartStart(iPart), mesh->LocalPartEnd(iPart));
687 TU sumIncAll(cnvars);
695 template <EulerModel model>
721 bool forward,
TU &sumInc)
727 index nCellDist = mesh->NumCell();
728 sumInc.setZero(cnvars);
729#if defined(DNDS_DIST_MT_USE_OMP)
730# pragma omp declare reduction(TUAdd:TU : omp_out += omp_in) initializer(omp_priv = omp_orig)
731# pragma omp parallel for schedule(static) reduction(TUAdd : sumInc)
733 for (
index iScan = 0; iScan < nCellDist; iScan++)
736 iCell = forward ? iScan : nCellDist - 1 - iScan;
738 auto c2f = mesh->cell2face[iCell];
739 TU uIncNewBuf(nVars);
740 auto RHSI = rhs[iCell];
744 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
746 index iFace = c2f[ic2f];
747 auto f2c = mesh->face2cell[iFace];
748 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
749 index iCellAtFace = f2c[0] == iCell ? 0 : 1;
750 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
751 (iCellAtFace ? -1 : 1);
754 index iScanOther = forward ? iCellOther : nCellDist - 1 - iCellOther;
755 if (iCell != iCellOther)
758 auto uINCj = uInc[iCellOther];
760 fInc = fluxJacobian0_Right_Times_du(
761 u[iCellOther], u[iCell],
762 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
763 Geom::BC_ID_INTERNAL, uINCj,
764 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
765 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
767 settings.useRoeJacobian);
771 (vfv->GetIntPointDiffBaseValue(iCell, iFace, iCellAtFace, -1, std::array<int, 1>{0}, 1) *
775 (vfv->GetIntPointDiffBaseValue(iCellOther, iFace, 1 - iCellAtFace, -1, std::array<int, 1>{0}, 1) *
778 TU fIncSL = fluxJacobianC_Right_Times_du(u[iCell], unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1), Geom::BC_ID_INTERNAL, uRecSLInc);
779 TU fIncSR = fluxJacobianC_Right_Times_du(u[iCellOther], unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1), Geom::BC_ID_INTERNAL, uRecSRInc);
780 fIncS = fIncSL + fIncSR + lambdaFaceC[iFace] * (uRecSLInc - uRecSRInc);
783 uIncNewBuf -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
785 uIncNewBuf -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
788 if ((!uIncNewBuf.allFinite()))
790 std::cout << RHSI.transpose() << std::endl
791 << fInc.transpose() << std::endl
792 << uINCj.transpose() << std::endl;
798 auto uIncNewI = uInc[iCell];
799 TU uIncOld = uIncNewI;
802 sumInc.array() += (uIncNewI - uIncOld).array().abs();
804 if (uIncNewI.hasNaN())
806 std::cout << uIncNewI.transpose() << std::endl
807 << uIncNewBuf.transpose() << std::endl
808 << JDiag.
getValue(iCell) << std::endl
809 << iCell << std::endl;
813 TU sumIncAll(cnvars);
819 template <EulerModel model>, template <>)
853 index nCellDist = mesh->NumCell();
854 sumInc.setZero(cnvars);
857 this->LUSGSMatrixVec(alphaDiag, t, u, uInc, JDiag, bBuf);
860#if defined(DNDS_DIST_MT_USE_OMP)
861# pragma omp parallel for schedule(static)
863 for (
int iPart = 0; iPart < mesh->NLocalParts(); iPart++)
864 for (
index iScan = mesh->LocalPartStart(iPart); iScan < mesh->LocalPartEnd(iPart); iScan++)
868 auto c2f = mesh->cell2face[iCell];
870 bBuf[iCell] = rhs[iCell] - bBuf[iCell];
876 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
878 index iFace = c2f[ic2f];
879 auto f2c = mesh->face2cell[iFace];
880 index iCellOther = f2c[0] == iCell ? f2c[1] : f2c[0];
881 index iCellAtFace = f2c[0] == iCell ? 0 : 1;
882 TVec unitNorm = vfv->GetFaceNormFromCell(iFace, iCell, iCellAtFace, -1)(Seq012) *
883 (iCellAtFace ? -1 : 1);
884 if (iCellOther !=
UnInitIndex && iCell != iCellOther
886 && iCellOther >= mesh->NumCell())
889 TU uINCj = uInc[iCellOther];
890 TU uj = u[iCellOther];
891 this->UFromOtherCell(uINCj, iFace, iCell, iCellOther, iCellAtFace);
892 this->UFromOtherCell(uj, iFace, iCell, iCellOther, iCellAtFace);
895 fInc = fluxJacobian0_Right_Times_du(
897 unitNorm, GetFaceVGridFromCell(iFace, iCell, iCellAtFace, -1),
898 Geom::BC_ID_INTERNAL, uINCj,
899 lambdaFace[iFace], lambdaFaceC[iFace], lambdaFaceVis[iFace],
900 iCellAtFace ? lambdaFace4[iFace] : lambdaFace0[iFace], lambdaFace123[iFace], iCellAtFace ? lambdaFace0[iFace] : lambdaFace4[iFace],
902 settings.useRoeJacobian);
905 bBuf[iCell] -= (0.5 * alphaDiag) * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) *
913 jacLU.
Solve(bBuf, uIncNew);
930 template <EulerModel model>, )
940 void EulerEvaluator<model>::InitializeUDOF(ArrayDOFV<nVarsFixed> &u)
943 Eigen::VectorXd initConstVal = this->settings.farFieldStaticValue;
944 u.setConstant(initConstVal);
947#if defined(DNDS_DIST_MT_USE_OMP)
948# pragma omp parallel for schedule(runtime)
950 for (
int iCell = 0; iCell < mesh->NumCell(); iCell++)
952 auto c2f = mesh->cell2face[iCell];
953 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
955 index iFace = c2f[ic2f];
958 u[iCell](I4 + 1) *= 1.0;
966#if defined(DNDS_DIST_MT_USE_OMP)
967# pragma omp parallel for schedule(runtime)
969 for (
int iCell = 0; iCell < mesh->NumCell(); iCell++)
971 auto c2f = mesh->cell2face[iCell];
972 real d = dWall.at(iCell).mean();
974 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
978 real pMean, asqrMean, Hmean;
979 real gamma = settings.idealGasProperty.gamma;
981 gamma, pMean, asqrMean, Hmean);
982 real muRef = settings.idealGasProperty.muGas;
983 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * u[iCell](0));
984 real mufPhy1 = muEff(u[iCell], T);
985 real rhoOmegaaaWall = mufPhy1 /
sqr(d) * RANS::kWallOmegaCoeff * 0.1;
987 real rhoOmegaaaNew = std::max(rhoOmegaaaWall, u[iCell](I4 + 2));
988 real rhoOmegaaaOld = u[iCell](I4 + 2);
995 switch (settings.specialBuiltinInitializer)
999 if constexpr (model ==
NS || model ==
NS_2D)
1000#
if defined(DNDS_DIST_MT_USE_OMP)
1001# pragma omp parallel for schedule(runtime)
1003 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1006 real gamma = settings.idealGasProperty.gamma;
1008 real p = 1 + 2 * pos(1);
1014 real v = -0.025 * sqrt(gamma * p / rho) * std::cos(8 *
pi * pos(0));
1015 if constexpr (dim == 3)
1016 u[iCell] = Eigen::Vector<real, 5>{rho, 0, rho *
v, 0, 0.5 * rho *
sqr(
v) + p / (gamma - 1)};
1018 u[iCell] = Eigen::Vector<real, 4>{rho, 0, rho *
v, 0.5 * rho *
sqr(
v) + p / (gamma - 1)};
1020 else if constexpr (model ==
NS_3D)
1021#
if defined(DNDS_DIST_MT_USE_OMP)
1022# pragma omp parallel for schedule(runtime)
1024 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1027 real gamma = settings.idealGasProperty.gamma;
1029 real p = 1 + 2 * pos(1);
1035 real v = -0.025 * sqrt(gamma * p / rho) * std::cos(8 *
pi * pos(0)) * std::cos(8 *
pi * pos(2));
1036 u[iCell] = Eigen::Vector<real, 5>{rho, 0, rho *
v, 0, 0.5 * rho *
sqr(
v) + p / (gamma - 1)};
1043 if constexpr (model ==
NS || model ==
NS_2D || model ==
NS_EX)
1044#
if defined(DNDS_DIST_MT_USE_OMP)
1045# pragma omp parallel for schedule(runtime)
1047 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1050 auto c2n = mesh->cell2node[iCell];
1051 auto gCell = vfv->GetCellQuad(iCell);
1053 um.resizeLike(u[iCell]);
1055 gCell.IntegrationSimple(
1057 [&](TU &inc,
int ig)
1059 Geom::tPoint pPhysics = vfv->GetCellQuadraturePPhys(iCell, ig);
1060 if (settings.specialBuiltinInitializer == 2)
1062 else if (settings.specialBuiltinInitializer == 203)
1064 else if (settings.specialBuiltinInitializer == 202)
1068 inc *= vfv->GetCellJacobiDet(iCell, ig);
1070 u[iCell] = um / vfv->GetCellVol(iCell);
1075 if constexpr (model ==
NS || model ==
NS_2D)
1076#
if defined(DNDS_DIST_MT_USE_OMP)
1077# pragma omp parallel for schedule(runtime)
1079 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1082 auto c2n = mesh->cell2node[iCell];
1083 auto gCell = vfv->GetCellQuad(iCell);
1085 um.resizeLike(u[iCell]);
1087 gCell.IntegrationSimple(
1089 [&](TU &inc,
int ig)
1091 Geom::tPoint pPhysics = vfv->GetCellQuadraturePPhys(iCell, ig);
1093 inc *= vfv->GetCellJacobiDet(iCell, ig);
1095 u[iCell] = um / vfv->GetCellVol(iCell);
1100 if constexpr (model ==
NS_3D)
1102#if defined(DNDS_DIST_MT_USE_OMP)
1103# pragma omp parallel for schedule(runtime)
1105 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1109 real gamma = settings.idealGasProperty.gamma;
1110 auto c2n = mesh->cell2node[iCell];
1111 auto gCell = vfv->GetCellQuad(iCell);
1113 um.resizeLike(u[iCell]);
1117 gCell.IntegrationSimple(
1119 [&](TU &inc,
int ig)
1123 Geom::tPoint pPhysics = vfv->GetCellQuadraturePPhys(iCell, ig);
1124 real x{pPhysics(0)}, y{pPhysics(1)},
z{pPhysics(2)};
1125 real ux = std::sin(
x) * std::cos(y) * std::cos(
z);
1126 real uy = -std::cos(
x) * std::sin(y) * std::cos(
z);
1127 real p = 1. / (gamma *
sqr(M0)) + 1. / 16 * ((std::cos(2 *
x) + std::cos(2 * y)) * (2 + std::cos(2 *
z)));
1128 real rho = gamma *
sqr(M0) * p;
1129 real E = 0.5 * (
sqr(ux) +
sqr(uy)) * rho + p / (gamma - 1);
1138 inc *= vfv->GetCellJacobiDet(iCell, ig);
1140 u[iCell] = um / vfv->GetCellVol(iCell);
1146#if defined(DNDS_DIST_MT_USE_OMP)
1147# pragma omp parallel for schedule(runtime)
1149 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1153 real gamma = settings.idealGasProperty.gamma;
1154 auto c2n = mesh->cell2node[iCell];
1155 auto gCell = vfv->GetCellQuad(iCell);
1157 um.resizeLike(u[iCell]);
1161 gCell.IntegrationSimple(
1163 [&](TU &inc,
int ig)
1167 Geom::tPoint pPhysics = vfv->GetCellQuadraturePPhys(iCell, ig);
1169 Gas::IdealGasThermalConservative2Primitive<dim>(settings.farFieldStaticValue, farPrimitive, settings.idealGasProperty.gamma);
1170 real pInf = farPrimitive(I4);
1171 real r = pPhysics.norm();
1173 farPrimitive(I4) = pInf;
1174 farPrimitive(0) = 1;
1175 farPrimitive(Seq123) =
velo;
1177 Gas::IdealGasThermalPrimitive2Conservative<dim>(farPrimitive, inc, settings.idealGasProperty.gamma);
1178 inc *= vfv->GetCellJacobiDet(iCell, ig);
1180 u[iCell] = um / vfv->GetCellVol(iCell);
1186 log() <<
"Wrong specialBuiltinInitializer" << std::endl;
1191 if (settings.frameConstRotation.enabled)
1193#if defined(DNDS_DIST_MT_USE_OMP)
1194# pragma omp parallel for schedule(runtime)
1196 for (
int iCell = 0; iCell < mesh->NumCell(); iCell++)
1199 TransformURotatingFrame(ui, vfv->GetCellQuadraturePPhys(iCell, -1), -1);
1205 for (
auto &i : settings.boxInitializers)
1207#if defined(DNDS_DIST_MT_USE_OMP)
1208# pragma omp parallel for schedule(runtime)
1210 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1213 if (pos(0) > i.x0 && pos(0) < i.x1 &&
1214 pos(1) > i.y0 && pos(1) < i.y1 &&
1215 pos(2) > i.z0 && pos(2) < i.z1)
1223 for (
auto &i : settings.planeInitializers)
1225#if defined(DNDS_DIST_MT_USE_OMP)
1226# pragma omp parallel for schedule(runtime)
1228 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1231 if (pos(0) * i.a + pos(1) * i.b + pos(2) * i.c + i.h > 0)
1240 for (
auto &i : settings.exprtkInitializers)
1242 auto exprStr = i.GetExpr();
1243 ExprtkWrapperEvaluator exprtkEval;
1244 exprtkEval.AddScalar(
"inRegion");
1245 exprtkEval.AddScalar(
"iCell");
1246 exprtkEval.AddVector(
"x", dim);
1247 exprtkEval.AddVector(
"UPrim", nVars);
1248 exprtkEval.Compile(exprStr);
1249#if defined(DNDS_DIST_MT_USE_OMP)
1250# pragma omp parallel for schedule(runtime)
1252 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1255 auto c2n = mesh->cell2node[iCell];
1256 auto gCell = vfv->GetCellQuad(iCell);
1258 um.resizeLike(u[iCell]);
1261 bool someIn =
false;
1262 gCell.IntegrationSimple(
1264 [&](TU &inc,
int ig)
1266 Geom::tPoint pPhysics = vfv->GetCellQuadraturePPhys(iCell, ig);
1268 exprtkEval.Var(
"inRegion") = 0;
1269 exprtkEval.Var(
"iCell") =
real(iCell);
1270 exprtkEval.VarVec(
"x", 0) = pPhysics(0);
1271 exprtkEval.VarVec(
"x", 1) = pPhysics(1);
1272 if constexpr (dim == 3)
1273 exprtkEval.VarVec(
"x", 2) = pPhysics(2);
1276 Gas::IdealGasThermalConservative2Primitive<dim>(u[iCell], uPrimitive, settings.idealGasProperty.gamma);
1277 for (
int i = 0; i < nVars; i++)
1278 exprtkEval.VarVec(
"UPrim", i) = uPrimitive(i);
1280 real ret = exprtkEval.Evaluate();
1283 allIn = allIn && exprtkEval.Var(
"inRegion");
1284 someIn = someIn || exprtkEval.Var(
"inRegion");
1286 if (exprtkEval.Var(
"inRegion"))
1287 for (
int i = 0; i < nVars; i++)
1288 uPrimitive(i) = exprtkEval.VarVec(
"UPrim", i);
1289 Gas::IdealGasThermalPrimitive2Conservative<dim>(uPrimitive, inc, settings.idealGasProperty.gamma);
1290 if (!inc.allFinite())
1292 std::ostringstream oss0, oss1, oss2;
1293 oss0 << uPrimitive.transpose();
1294 oss1 << inc.transpose();
1295 oss2 <<
"x=" << pPhysics.transpose();
1298 fmt::format(
"Got invalid exprtk product: [{}] -> [{}]\n{}\n {}\n",
1299 oss0.str(), oss1.str(), oss2.str(), exprStr));
1301 inc *= vfv->GetCellJacobiDet(iCell, ig);
1305 u[iCell] = um / vfv->GetCellVol(iCell);
1310 template <EulerModel model>
1325 template <EulerModel model>
1342 template <EulerModel model>
1350#if defined(DNDS_DIST_MT_USE_OMP)
1351# pragma omp parallel for schedule(static)
1353 for (
index iCell = 0; iCell < u.
Size(); iCell++)
1355 real gamma = settings.idealGasProperty.gamma;
1357 Gas::IdealGasThermalConservative2Primitive<dim>(u[iCell], out, gamma);
1362 template <EulerModel model>
1370#if defined(DNDS_DIST_MT_USE_OMP)
1371# pragma omp parallel for schedule(static)
1373 for (
index iCell = 0; iCell < w.
Size(); iCell++)
1375 real gamma = settings.idealGasProperty.gamma;
1377 Gas::IdealGasThermalPrimitive2Conservative<dim>(w[iCell], out, gamma);
1382 template <EulerModel model>
1400 resc.setZero(nVars);
1402#if defined(DNDS_DIST_MT_USE_OMP)
1403# pragma omp declare reduction(TUAdd:TU : omp_out += omp_in) initializer(omp_priv = omp_orig)
1404# pragma omp parallel for schedule(static) reduction(TUAdd : resc)
1406 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1408 if (rhs[iCell].hasNaN() || (!rhs[iCell].allFinite()))
1410 std::cout << rhs[iCell] << std::endl;
1414 resc += rhs[iCell].array().abs().pow(P).matrix() * vfv->GetCellVol(iCell), rescBase += vfv->GetCellVol(iCell);
1416 resc += rhs[iCell].array().abs().pow(P).matrix(), rescBase += 1;
1421 res =
res.array().pow(1.0 / P).matrix();
1429 resc.resizeLike(rhs[0]);
1431#if defined(DNDS_DIST_MT_USE_OMP)
1432# pragma omp declare reduction(TUAdd:TU : omp_out = omp_out.array().max(omp_in.array())) initializer(omp_priv = omp_orig)
1433# pragma omp parallel for schedule(static) reduction(TUAdd : resc)
1435 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1436 resc = resc.array().max(rhs[iCell].array().abs()).matrix();
1454 _v = ((
P < 3) ? TU(
_v + R.
_v) : TU((
_v.array().max(R.
_v.array())).matrix()));
1459 template <EulerModel model>
1475 Eigen::Vector<real, -1> &
res,
1488#if defined(DNDS_DIST_MT_USE_OMP)
1489# pragma omp declare reduction(TUAdd : TU_P_Reduction<TU> : omp_out.reduce(omp_in)) initializer(omp_priv = omp_orig)
1490# pragma omp parallel for schedule(static) reduction(TUAdd : resc)
1492 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1494 auto qCell = vfv->GetCellQuad(iCell);
1496 rescCell.setZero(nVars);
1497 qCell.IntegrationSimple(
1499 [&](
auto &inc,
int iG)
1501 TU uR = u[iCell] + (vfv->GetIntPointDiffBaseValue(iCell, -1, -1, iG, 0, 1) * uRec[iCell]).transpose();
1504 Geom::tPoint pPhysics = vfv->GetCellQuadraturePPhys(iCell, iG);
1505 uR -= FCompareField(pPhysics, t);
1506 uR *= FCompareFieldWeight(pPhysics, t);
1509 resc.
_v = resc.
_v.array().max(uR.array().abs());
1510 inc = uR.array().abs().pow(P);
1511 inc *= vfv->GetCellJacobiDet(iCell, iG);
1514 resc.
_v += rescCell;
1521 res =
res.array().pow(1.0 / P).matrix();
1526 template <EulerModel model>, template <>)
1543 static const real safetyRatio = 1 - 1e-2;
1546 bool disable_shock_limiter = flags & LIMITER_UGRAD_Disable_Shock_Limiter;
1548#if defined(DNDS_DIST_MT_USE_OMP)
1549# pragma omp parallel for schedule(runtime)
1551 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1553 uGradNew[iCell] = uGrad[iCell];
1554 auto c2f = mesh->cell2face[iCell];
1557 uFaceInc.setZero(nVars, c2f.size() * 2);
1558 TU uOtherMin = u[iCell];
1559 TU uOtherMax = u[iCell];
1560 auto fEInternal = [](
const TU &u) ->
real
1561 {
return u(I4) - 0.5 * u(Seq123).squaredNorm() / (u(0) +
verySmallReal); };
1562 real eOtherMin, eOtherMax;
1563 eOtherMin = eOtherMax = fEInternal(u[iCell]);
1564 for (
rowsize ic2f = 0; ic2f < c2f.size(); ic2f++)
1566 index iFace = c2f[ic2f];
1567 uFaceInc(EigenAll, ic2f) =
1568 uGrad[iCell].transpose() *
1569 (vfv->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, -1) - vfv->GetCellQuadraturePPhys(iCell, -1))(SeqG012);
1570 index iCellOther = mesh->CellFaceOther(iCell, iFace);
1573 uOtherMin = uOtherMin.array().
min(u[iCellOther].array());
1574 uOtherMax = uOtherMin.array().max(u[iCellOther].array());
1575 eOtherMin = std::min(eOtherMin, fEInternal(u[iCellOther]));
1576 eOtherMax = std::max(eOtherMax, fEInternal(u[iCellOther]));
1584 TU uFaceIncMax = uFaceInc.array().rowwise().maxCoeff();
1585 TU uFaceIncMin = uFaceInc.array().rowwise().minCoeff();
1586 if (!disable_shock_limiter)
1589 alpha0.setConstant(nVars, 1.0);
1590 alpha0 = alpha0.array().min(((uOtherMax - u[iCell]).array().abs() / (uFaceIncMax.array().abs() +
verySmallReal)));
1591 alpha0 = alpha0.array().min(((uOtherMin - u[iCell]).array().abs() / (uFaceIncMin.array().abs() +
verySmallReal)));
1592 uGradNew[iCell].array().rowwise() *= alpha0.array().transpose();
1593 uFaceInc.array().colwise() *= alpha0.array();
1597 real alphaPP_Rho = 1.0;
1598 if (disable_shock_limiter)
1600 alphaPP_Rho = std::min(alphaPP_Rho, u[iCell][0] / (std::abs(uFaceIncMin(0)) +
smallReal * u[iCell][0]));
1601 if (alphaPP_Rho < 1.0)
1602 alphaPP_Rho *= safetyRatio;
1603 uGradNew[iCell].array() *= alphaPP_Rho;
1604 uFaceInc.array() *= alphaPP_Rho;
1607 TU_Batch uFaceAlpha0 = uFaceInc.colwise() + u[iCell];
1608 for (
int j = 0; j < uFaceAlpha0.cols(); j++)
1611 (uFaceAlpha0(I4, EigenAll).array() -
1612 0.5 * uFaceAlpha0(Seq123, EigenAll).colwise().squaredNorm().array() / (uFaceAlpha0(0, EigenAll).array() +
verySmallReal))
1614 real eC = fEInternal(u[iCell]);
1615 real deltaEFaceMin = minEFace - eC;
1616 real alphaPP_E = 1.0;
1617 if (deltaEFaceMin < 0)
1618 alphaPP_E = std::min(alphaPP_E, std::abs(eC * (1 - E_lb_eps)) / (
verySmallReal - deltaEFaceMin));
1619 if (alphaPP_E < 1.0)
1620 alphaPP_E *= safetyRatio;
1621 uGradNew[iCell](EigenAll, Seq01234) *= alphaPP_E;
1626 template <EulerModel model>, template <>)
1642 ArrayDOFV<nVarsFixed> &u,
1643 ArrayRECV<nVarsFixed> &uRec,
1644 ArrayDOFV<1> &uRecBeta,
index &nLim,
real &betaMin,
1648 static const real safetyRatio = 1 - 1e-5;
1649 static const real minRatio = 0.5;
1652 real betaCutOff = 1e-3;
1653 bool restrictOnVolPoints = (!settings.ignoreSourceTerm) || settings.forceVolURecBeta;
1655 if (settings.ppEpsIsRelaxed)
1659#if defined(DNDS_DIST_MT_USE_OMP)
1660# pragma omp parallel for schedule(runtime) reduction(min : rhoMin, pMin)
1662 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1665 Gas::IdealGasThermalConservative2Primitive<dim>(u[iCell], UPrim, settings.idealGasProperty.gamma);
1666 rhoMin = std::min(rhoMin, UPrim(0));
1667 pMin = std::min(pMin, UPrim(I4));
1671 rhoEps = std::min(rhoEps, minRatio * rhoMin);
1672 pEps = std::min(pEps, minRatio * pMin);
1675 index nLimLocal = 0;
1676 real minBetaLocal = 1;
1677#if defined(DNDS_DIST_MT_USE_OMP)
1678# pragma omp parallel for schedule(runtime) reduction(+ : nLimLocal) reduction(min : minBetaLocal)
1680 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1682 auto gCell = vfv->GetCellQuad(iCell);
1683 int nPoint = restrictOnVolPoints ? gCell.GetNumPoints() : 0;
1684 auto c2f = mesh->cell2face[iCell];
1685 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
1686 nPoint += vfv->GetFaceQuad(c2f[ic2f]).GetNumPoints();
1689 quadBase.resize(nPoint, vfv->GetCellAtr(iCell).NDOF - 1);
1691 if (restrictOnVolPoints)
1693 for (
int iG = 0; iG < gCell.GetNumPoints(); iG++)
1694 quadBase(iG, EigenAll) = vfv->GetIntPointDiffBaseValue(iCell, -1, -1, iG, 0, 1);
1695 nPoint += gCell.GetNumPoints();
1697 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
1699 auto gFace = vfv->GetFaceQuad(c2f[ic2f]);
1700 for (
int iG = 0; iG < gFace.GetNumPoints(); iG++)
1701 quadBase(nPoint + iG, EigenAll) = vfv->GetIntPointDiffBaseValue(iCell, c2f[ic2f], -1, iG, 0, 1);
1702 nPoint += gFace.GetNumPoints();
1705 DNDS_assert_info(u[iCell](0) >= rhoEps, fmt::format(
"rhoMean {}, {}", u[iCell](0), rhoEps));
1706 real gamma = settings.idealGasProperty.gamma;
1707 real pCent = (gamma - 1) * (u[iCell](I4) - 0.5 * u[iCell](Seq123).squaredNorm() / u[iCell](0));
1711 int curOrder = vfv->GetCellOrder(iCell);
1712 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> uRecBase = uRec[iCell];
1713 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> recBase;
1714 auto checkRecBaseGood = [&]()
1716 recBase = (quadBase * uRecBase).rowwise() + u[iCell].transpose();
1717 if (recBase(EigenAll, 0).minCoeff() < rhoEps)
1719 if constexpr (Traits::hasSA)
1720 if (recBase(EigenAll, I4 + 1).minCoeff() < rhoEps)
1722 if constexpr (Traits::has2EQ)
1723 if (recBase(EigenAll, I4 + 1).minCoeff() < rhoEps || recBase(EigenAll, I4 + 2).minCoeff() < rhoEps)
1725 Eigen::Vector<real, Eigen::Dynamic> ek =
1726 0.5 * (recBase(EigenAll, Seq123).array().square().rowwise().sum()) / recBase(EigenAll, 0).array();
1727 Eigen::Vector<real, Eigen::Dynamic> eInternalS = (recBase(EigenAll, I4) - ek);
1728 if (eInternalS.minCoeff() < pEps)
1732 if (checkRecBaseGood())
1734 uRecBeta[iCell](0) = 1;
1737 if (flag & EvaluateURecBeta_COMPRESS_TO_MEAN)
1739 while (curOrder > 0)
1741 uRecBase = vfv->template DownCastURecOrder<nVarsFixed>(curOrder, iCell, uRec, 0);
1742 if (checkRecBaseGood())
1744 uRec[iCell] = uRecBase;
1748 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed>
1749 recInc = quadBase * (uRec[iCell] - uRecBase);
1750 Eigen::Vector<real, Eigen::Dynamic> rhoS = recInc(EigenAll, 0) + recBase(EigenAll, 0);
1751 Eigen::Index rhoMinIdx;
1752 real rhoMin = rhoS.minCoeff(&rhoMinIdx);
1754 if (rhoMin < rhoEps)
1755 for (
int iG = 0; iG < rhoS.size(); iG++)
1756 if (recInc(iG, 0) < 0)
1757 theta1 = std::min(theta1, (recBase(iG, 0) - rhoEps) / (-recInc(iG, 0) +
verySmallReal));
1758#ifdef USE_NS_SA_NUT_REDUCED_ORDER
1759 if constexpr (Traits::hasSA)
1762 Eigen::Vector<real, Eigen::Dynamic> v1S = recInc(EigenAll, I4 + 1) + recBase(EigenAll, I4 + 1);
1763 real v1Min = v1S.minCoeff();
1765 for (
int iG = 0; iG < rhoS.size(); iG++)
1766 if (recInc(iG, I4 + 1) < 0)
1767 theta1 = std::min(theta1, (recBase(iG, I4 + 1) - v1Eps) / (-recInc(iG, I4 + 1) +
verySmallReal))
1772 if constexpr (Traits::has2EQ)
1777 Eigen::Vector<real, Eigen::Dynamic> v1S = recInc(EigenAll, I4 + 1) + recBase(EigenAll, I4 + 1);
1778 Eigen::Vector<real, Eigen::Dynamic> v2S = recInc(EigenAll, I4 + 2) + recBase(EigenAll, I4 + 2);
1779 real v1Min = v1S.minCoeff();
1780 real v2Min = v2S.minCoeff();
1782 for (
int iG = 0; iG < rhoS.size(); iG++)
1783 if (recInc(iG, I4 + 1) < 0)
1784 thetaC = std::min(thetaC, (recBase(iG, I4 + 1) - v1Eps) / (-recInc(iG, I4 + 1) +
verySmallReal));
1786 for (
int iG = 0; iG < rhoS.size(); iG++)
1787 if (recInc(iG, I4 + 2) < 0)
1788 thetaC = std::min(thetaC, (recBase(iG, I4 + 2) - v2Eps) / (-recInc(iG, I4 + 2) +
verySmallReal));
1792 uRec[iCell](EigenAll, {I4 + 1, I4 + 2}) *= thetaC * 0.9;
1796 if constexpr (Traits::hasRANS)
1797 recInc(EigenAll, Seq01234) *= theta1;
1800 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed>
1801 recVRhoG = recInc + recBase;
1803 Eigen::Vector<real, Eigen::Dynamic> ek = 0.5 * (recVRhoG(EigenAll, Seq123).array().square().rowwise().sum()) / recVRhoG(EigenAll, 0).array();
1804 Eigen::Vector<real, Eigen::Dynamic> eInternalS = recVRhoG(EigenAll, I4) - ek;
1807 if (pCent <= 2 * pEps)
1810 for (
int iG = 0; iG < rhoS.size(); iG++)
1812 if (eInternalS(iG) < 2 * pEps / (gamma - 1))
1814 real thetaThis = Gas::IdealGasGetCompressionRatioPressure<dim, 0, nVarsFixed>(
1815 recBase(iG, EigenAll).transpose(), recInc(iG, EigenAll).transpose(),
1817 thetaP = std::min(thetaP, thetaThis);
1821 uRecBeta[iCell](0) = theta1 * thetaP;
1825 if (uRecBeta[iCell](0) < 1)
1829 uRecBeta[iCell](0) *= std::pow(uRecBeta[iCell](0),
static_cast<int>(std::round(settings.uRecBetaCompressPower))) * safetyRatio;
1830 minBetaLocal = std::min(uRecBeta[iCell](0), minBetaLocal);
1831 if (uRecBeta[iCell](0) < betaCutOff)
1832 uRecBeta[iCell](0) = 0;
1834 if (uRecBeta[iCell](0) < 0)
1836 std::cout << fmt::format(
"theta1 {}, thetaP {}", theta1, thetaP) << std::endl;
1839 if (uRecBeta[iCell](0) < 1)
1840 uRec[iCell] = (uRec[iCell] - uRecBase) * uRecBeta[iCell](0) + uRecBase;
1843 recInc = quadBase * uRec[iCell];
1844 recVRhoG = recInc.rowwise() + u[iCell].transpose();
1845 ek = 0.5 * (recVRhoG(EigenAll, Seq123).array().square().rowwise().sum()) / recVRhoG(EigenAll, 0).array();
1846 eInternalS = (recVRhoG(EigenAll, I4) - ek);
1847 for (
int iG = 0; iG < eInternalS.size(); iG++)
1849 if (eInternalS(iG) < pEps)
1851 std::cout << std::scientific;
1852 std::cout << eInternalS.transpose() << std::endl;
1853 std::cout << curOrder << std::endl;
1854 std::cout << fmt::format(
"{} {} {}", theta1, thetaP, uRecBeta[iCell](0)) << std::endl;
1855 std::cout << u[iCell] << std::endl;
1856 std::cout << recInc.transpose() << std::endl;
1865 template <EulerModel model>
1872 if (settings.ppEpsIsRelaxed)
1873 rhoEps *= 0, pEps *= 0;
1875#if defined(DNDS_DIST_MT_USE_OMP)
1876# pragma omp parallel for schedule(runtime)
1878 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1880 real gamma = settings.idealGasProperty.gamma;
1882 if (u[iCell](0) < rhoEps)
1888 "AssertMeanValuePP Failed on cell {} rho\n",
1891 " eps={}, value={}",
1892 rhoEps, u[iCell](0)));
1893#if defined(DNDS_DIST_MT_USE_OMP)
1894# pragma omp critical
1898 real rhoEi = u[iCell](I4) - 0.5 * u[iCell](Seq123).squaredNorm() / u[iCell](0);
1899 if (rhoEi < pEps / (gamma - 1))
1905 "AssertMeanValuePP Failed on cell {} rhoEi\n",
1908 " eps={}, value={}",
1909 pEps / (gamma - 1), rhoEi));
1910#if defined(DNDS_DIST_MT_USE_OMP)
1911# pragma omp critical
1920 template <EulerModel model>
1944 real relax,
int compress,
1950 static const real safetyRatio = 1 - 1e-5;
1951 static const real minRatio = 0.5;
1953 if (settings.ppEpsIsRelaxed)
1955 pEps *= 0, rhoEps *= 0;
1956 DNDS_assert_info(relax < 1,
"Relaxed eps only for using relaxation in alpha");
1959 index nLimLocal = 0;
1960 real alphaMinLocal = 1;
1961#if defined(DNDS_DIST_MT_USE_OMP)
1962# pragma omp parallel for schedule(runtime) reduction(+ : nLimLocal) reduction(min : alphaMinLocal)
1964 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1966 real gamma = settings.idealGasProperty.gamma;
1968 TU inc =
res[iCell];
1970 real relaxedRho = rhoEps * relax + (u[iCell](0)) * (1 - relax);
1972 alphaRho = std::min(1.0, (u[iCell](0) - relaxedRho) / (-inc(0) -
smallReal * inc(0)));
1974 if constexpr (Traits::hasSA)
1991 if constexpr (Traits::has2EQ)
2005 TU uNew = u[iCell] + inc;
2006 real pNew = (uNew(I4) - 0.5 * uNew(Seq123).squaredNorm() / uNew(0)) * (gamma - 1);
2007 real pOld = (u[iCell](I4) - 0.5 * u[iCell](Seq123).squaredNorm() / u[iCell](0)) * (gamma - 1);
2008 real relaxedP = pEps;
2010 relaxedP = pEps + (pOld - pEps) * (1 - relax);
2013 if (pNew < relaxedP)
2016 real alphaC = Gas::IdealGasGetCompressionRatioPressure<dim, 0, nVarsFixed>(
2017 u[iCell], inc, relaxedP / (gamma - 1));
2018 alphaP = std::min(alphaP, alphaC);
2020 cellRHSAlpha[iCell](0) = alphaRho * alphaP;
2022 if (cellRHSAlpha[iCell](0) < 1)
2024 cellRHSAlpha[iCell](0) = std::pow(cellRHSAlpha[iCell](0), compress *
static_cast<int>(std::round(settings.uRecAlphaCompressPower)));
2026 cellRHSAlpha[iCell] *= safetyRatio,
2027 alphaMinLocal = std::min(alphaMinLocal, cellRHSAlpha[iCell](0));
2032 if (flag & EvaluateCellRHSAlpha_MIN_IF_NOT_ONE)
2033#if defined(DNDS_DIST_MT_USE_OMP)
2034# pragma omp parallel for schedule(static)
2036 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
2038 if (cellRHSAlpha[iCell](0) < 1)
2039 cellRHSAlpha[iCell](0) = alphaMin;
2041 if (flag & EvaluateCellRHSAlpha_MIN_ALL)
2042#if defined(DNDS_DIST_MT_USE_OMP)
2043# pragma omp parallel for schedule(static)
2045 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
2046 cellRHSAlpha[iCell](0) = alphaMin;
2049 template <EulerModel model>
2075 auto cellIsHalfAlpha = [&](
index iCell) ->
bool
2078 if (cellRHSAlpha[iCell](0) == 1.0)
2080 auto c2f = mesh->cell2face[iCell];
2081 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
2083 index iCellOther = vfv->CellFaceOther(iCell, c2f[ic2f]);
2085 if (cellRHSAlpha[iCellOther](0) != 1.0)
2092 auto cellAdjAlphaMin = [&](
index iCell) ->
real
2095 auto c2f = mesh->cell2face[iCell];
2096 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
2098 index iCellOther = vfv->CellFaceOther(iCell, c2f[ic2f]);
2100 ret = std::min(ret, cellRHSAlpha[iCellOther](0));
2111 index nLimLocal = 0;
2114 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
2116 real gamma = settings.idealGasProperty.gamma;
2117 TU inc =
res[iCell];
2119 TU uNew = u[iCell] + inc;
2120 real pNew = (uNew(I4) - 0.5 * uNew(Seq123).squaredNorm() / uNew(0)) * (gamma - 1);
2122 if (pNew < pEps || uNew(0) < rhoEps)
2126 cellRHSAlpha[iCell](0) = alphaMin;
2128 if constexpr (Traits::hasSA)
2135 if constexpr (Traits::has2EQ)
2149 template <EulerModel model>
2161 real smootherCentWeight = 1;
2162#if defined(DNDS_DIST_MT_USE_OMP)
2163# pragma omp parallel for schedule(runtime)
2165 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
2167 auto c2f = mesh->cell2face[iCell];
2170 for (
index iFace : c2f)
2172 index iCellOther = vfv->CellFaceOther(iCell, iFace);
2176 dTMean += dTau[iCellOther](0);
2179 dTMean += nAdj * smootherCentWeight * dTau[iCell](0);
2180 dTMean /= nAdj * (1 + smootherCentWeight);
2181 dTauNew[iCell](0) = std::min(dTau[iCell](0), dTMean);
2185 template <EulerModel model>
2198 for (
Geom::t_index i = Geom::BC_ID_DEFAULT_MAX; i < pBCHandler->size(); i++)
2200 if (pBCHandler->GetFlagFromIDSoft(i,
"anchorOpt") != 2)
2202 if (!profileRecorders.count(i))
2207 for (
index iBnd = 0; iBnd < mesh->NumBnd(); iBnd++)
2209 index iFace = mesh->bnd2faceV.at(iBnd);
2212 auto f2c = mesh->face2cell[iFace];
2213 auto gFace = vfv->GetFaceQuad(iFace);
2216 auto faceBndID = mesh->GetFaceZone(iFace);
2217 auto faceBCType = pBCHandler->GetTypeFromID(faceBndID);
2221 mesh->GetCoordsOnFace(iFace, coo);
2222 for (
int ic = 0; ic < coo.cols(); ic++)
2224 real r = settings.frameConstRotation.rVec(coo(EigenAll, ic)).norm();
2225 RMin = std::min(
r, RMin);
2226 RMax = std::max(
r, RMax);
2232 auto vExtra = pBCHandler->GetValueExtraFromID(i);
2237 index nDiv = vExtra.size() >= 1 ? vExtra(0) : 10;
2238 index divMethod = vExtra.size() >= 2 ? vExtra(1) : 0;
2242 profileRecorders.at(i).GenerateUniform(std::max(nDiv,
index(10)), nVars, RMin, RMax);
2244 profileRecorders.at(i).GenerateTanh(std::max(nDiv,
index(10)), nVars, RMin, RMax, divd0);
2247 for (
auto &
v : profileRecorders)
2249 for (
index iBnd = 0; iBnd < mesh->NumBnd(); iBnd++)
2251 index iFace = mesh->bnd2faceV.at(iBnd);
2254 auto f2c = mesh->face2cell[iFace];
2255 auto gFace = vfv->GetFaceQuad(iFace);
2258 auto faceBndID = mesh->GetFaceZone(iFace);
2259 auto faceBCType = pBCHandler->GetTypeFromID(faceBndID);
2261 if (pBCHandler->GetFlagFromIDSoft(faceBndID,
"anchorOpt") != 2)
2268 mesh->GetCoordsOnFace(iFace, coo);
2269 for (
int ic = 0; ic < coo.cols(); ic++)
2271 real r = settings.frameConstRotation.rVec(coo(EigenAll, ic)).norm();
2272 RMin = std::min(
r, RMin);
2273 RMax = std::max(
r, RMax);
2275 TU valIn = u[f2c[0]];
2276 valIn(Seq123) = settings.frameConstRotation.rtzFrame(vfv->GetFaceQuadraturePPhys(iFace, -1)).transpose()(Seq012, Seq012) * valIn(Seq123);
2277#ifndef USE_ABS_VELO_IN_ROTATION
2278 valIn(2) += valIn(0) * settings.frameConstRotation.Omega() * settings.frameConstRotation.rVec(vfv->GetFaceQuadraturePPhys(iFace, -1)).norm();
2282 profileRecorders.at(faceBndID).AddSimpleInterval(valIn, vfv->GetFaceArea(iFace), RMin, RMax);
2284 for (
auto &
v : profileRecorders)
2288 template <EulerModel model>
2298 for (
auto &
v : profileRecorders)
2300 if (pBCHandler->GetFlagFromIDSoft(
v.first,
"anchorOpt") == 2)
2302 v.second.v.array().rowwise() /= (
v.second.div.array() +
verySmallReal);
2303 v.second.div.setConstant(1.);
2304 v.second.v(I4, 0) = 0;
2305 for (
index i = 1; i <
v.second.Size(); i++)
2307 real vt0 =
v.second.v(2, i - 1) /
v.second.v(0, i - 1);
2308 real vt1 =
v.second.v(2, i) /
v.second.v(0, i);
2309 real l0 =
v.second.Len(i - 1);
2310 real l1 =
v.second.Len(i);
2311 real ldist = 0.5 * (l0 + l1);
2312 real vtm = (vt0 * l0 + vt1 * l1) / (l0 + l1);
2313 real rhom = (
v.second.v(0, i - 1) * l0 +
v.second.v(0, i) * l1) / (l0 + l1);
2314 real rc =
v.second.nodes[i];
2315 v.second.v(I4, i) =
v.second.v(I4, i - 1) + rhom *
sqr(vtm) / rc * ldist;
2317 if (mesh->getMPI().rank == 0)
2323 auto vExtra = pBCHandler->GetValueExtraFromID(
v.first);
2324 int showMethod = vExtra.size() >= 4 ? vExtra(3) : 0;
2326 log() << fmt::format(
"EulerEvaluator<model>::updateBCProfilesPressureRadialEq: p rise: [{:.3e}]",
v.second.v(I4, EigenLast))
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#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 + ...
#define DNDS_check_throw_info(expr, info)
Same as DNDS_check_throw but attaches a user-supplied info message to the thrown std::runtime_error.
Core finite-volume evaluator for compressible Navier-Stokes / Euler equations.
#define DNDS_FV_EULEREVALUATOR_GET_FIXED_EIGEN_SEQS
Declares compile-time Eigen index sequences for sub-vector access into conservative state vectors.
Runtime mathematical expression compiler and evaluator wrapping exprtk.
Robust linear-algebra primitives for small / moderately-sized Eigen matrices that are more numericall...
#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.
real min()
Global minimum across all entries (collective).
MPI-parallel distributed array of per-cell Degrees-of-Freedom (conservative variable vectors).
void addTo(const t_self &R, real r)
Scaled addition: this[i] += r * R[i] for every cell (axpy-style).
void setConstant(real R)
Set all DOF entries to a uniform scalar value.
Eigen::Vector< real, nVarsFixed > componentWiseNorm1()
Compute the per-component global L1 norm.
MPI-parallel distributed array of per-cell gradient matrices.
MPI-parallel distributed array of per-cell reconstruction coefficient matrices.
Core finite-volume evaluator for compressible Navier-Stokes / Euler equations.
void MinSmoothDTau(ArrayDOFV< 1 > &dTau, ArrayDOFV< 1 > &dTauNew)
Smooth the local time step across neighboring cells.
void EvaluateRecNorm(Eigen::Vector< real, -1 > &res, ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec, index P=1, bool compare=false, const tFCompareField &FCompareField=[](const Geom::tPoint &p, real t) { return TU::Zero();}, const tFCompareFieldWeight &FCompareFieldWeight=[](const Geom::tPoint &p, real t) { return 1.0;}, real t=0)
Compute the reconstruction error norm (optionally against an analytical field).
bool AssertMeanValuePP(ArrayDOFV< nVarsFixed > &u, bool panic)
Assert that all cell-mean values are physically realizable.
void UpdateLUSGSBackward(real alphaDiag, real t, ArrayDOFV< nVarsFixed > &rhs, ArrayDOFV< nVarsFixed > &u, ArrayDOFV< nVarsFixed > &uInc, JacobianDiagBlock< nVarsFixed > &JDiag, ArrayDOFV< nVarsFixed > &uIncNew)
Deprecated: use UpdateSGS with uIncIsZero=true instead. Kept for backward compatibility....
void FixUMaxFilter(ArrayDOFV< nVarsFixed > &u)
Clip extreme conserved-variable values to prevent overflow.
void UpdateSGS(real alphaDiag, real t, ArrayDOFV< nVarsFixed > &rhs, ArrayDOFV< nVarsFixed > &u, ArrayDOFV< nVarsFixed > &uInc, ArrayDOFV< nVarsFixed > &uIncNew, JacobianDiagBlock< nVarsFixed > &JDiag, bool forward, bool gsUpdate, TU &sumInc, bool uIncIsZero=false)
Symmetric Gauss-Seidel update for the implicit linear system.
void EvaluateURecBeta(ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec, ArrayDOFV< 1 > &uRecBeta, index &nLim, real &betaMin, int flag)
Evaluate the positivity-preserving reconstruction limiter (beta).
void MeanValuePrim2Cons(ArrayDOFV< nVarsFixed > &w, ArrayDOFV< nVarsFixed > &u)
Convert cell-mean primitive variables to conservative variables.
std::function< TU(const Geom::tPoint &, real)> tFCompareField
Callback type for analytical comparison field.
void UpdateLUSGSForward(real alphaDiag, real t, ArrayDOFV< nVarsFixed > &rhs, ArrayDOFV< nVarsFixed > &u, ArrayDOFV< nVarsFixed > &uInc, JacobianDiagBlock< nVarsFixed > &JDiag, ArrayDOFV< nVarsFixed > &uIncNew)
Deprecated: use UpdateSGS with uIncIsZero=true instead. Kept for backward compatibility....
void EvaluateNorm(Eigen::Vector< real, -1 > &res, ArrayDOFV< nVarsFixed > &rhs, index P=1, bool volWise=false, bool average=false)
Compute the norm of the RHS residual vector.
void updateBCProfilesPressureRadialEq()
Update boundary profiles using radial-equilibrium pressure extrapolation.
void MeanValueCons2Prim(ArrayDOFV< nVarsFixed > &u, ArrayDOFV< nVarsFixed > &w)
Convert cell-mean conservative variables to primitive variables.
std::function< real(const Geom::tPoint &, real)> tFCompareFieldWeight
Callback type for comparison weighting function.
void LUSGSMatrixSolveJacobianLU(real alphaDiag, real t, ArrayDOFV< nVarsFixed > &rhs, ArrayDOFV< nVarsFixed > &u, ArrayDOFV< nVarsFixed > &uInc, ArrayDOFV< nVarsFixed > &uIncNew, ArrayDOFV< nVarsFixed > &bBuf, JacobianDiagBlock< nVarsFixed > &JDiag, JacobianLocalLU< nVarsFixed > &jacLU, bool uIncIsZero, TU &sumInc)
Solve the implicit linear system using the pre-factored local LU.
void LimiterUGrad(ArrayDOFV< nVarsFixed > &u, ArrayGRADV< nVarsFixed, gDim > &uGrad, ArrayGRADV< nVarsFixed, gDim > &uGradNew, uint64_t flags=LIMITER_UGRAD_No_Flags)
Apply slope limiter to the gradient field.
void EvaluateCellRHSAlpha(ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec, ArrayDOFV< 1 > &uRecBeta, ArrayDOFV< nVarsFixed > &res, ArrayDOFV< 1 > &cellRHSAlpha, index &nLim, real &alphaMin, real relax, int compress=1, int flag=0)
Compute the positivity-preserving RHS scaling factor (alpha) per cell.
void updateBCProfiles(ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec)
Update boundary 1-D profiles from the current solution.
void TimeAverageAddition(ArrayDOFV< nVarsFixed > &w, ArrayDOFV< nVarsFixed > &wAveraged, real dt, real &tCur)
Accumulate time-averaged primitive variables for unsteady statistics.
void EvaluateCellRHSAlphaExpansion(ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec, ArrayDOFV< 1 > &uRecBeta, ArrayDOFV< nVarsFixed > &res, ArrayDOFV< 1 > &cellRHSAlpha, index &nLim, real alphaMin)
Expand a previously computed cellRHSAlpha toward 1 where safe.
void UpdateSGSWithRec(real alphaDiag, real t, ArrayDOFV< nVarsFixed > &rhs, ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec, ArrayDOFV< nVarsFixed > &uInc, ArrayRECV< nVarsFixed > &uRecInc, JacobianDiagBlock< nVarsFixed > &JDiag, bool forward, TU &sumInc)
SGS sweep coupled with reconstruction update.
Per-cell diagonal or block-diagonal Jacobian storage for implicit time stepping.
TU MatVecLeftInvert(index iCell, TV v)
Left-multiply a vector by the inverse Jacobian block for cell iCell.
tComponent getValue(index iCell) const
Return the Jacobian as a full matrix for cell iCell (either mode).
void GetInvert()
Compute and cache the inverse of every cell's Jacobian block.
Eigen::Vector< real, nVarsFlow > TU
Fixed-size 5-component conservative state vector (rho, rhoU, rhoV, rhoW, E).
void IdealGasThermal(real E, real rho, real vSqr, real gamma, real &p, real &asqr, real &H)
Thin wrapper delegating to IdealGas::IdealGasThermal.
auto IsentropicVortexCent(EulerEvaluator< model > &eval, const Geom::tPoint &x, real t, int cnVars)
Stationary isentropic vortex centered at the origin with zero background flow.
auto IsentropicVortex30(EulerEvaluator< model > &eval, const Geom::tPoint &x, real t, int cnVars)
Analytic isentropic vortex on a [-10,20] x [-10,20] periodic domain (period 30).
auto IsentropicVortex10(EulerEvaluator< model > &eval, const Geom::tPoint &x, real t, int cnVars, real chi)
Analytic isentropic vortex on a [0,10] x [0,10] periodic domain.
@ RANS_KOSST
Menter k-omega SST two-equation model.
@ RANS_KOWilcox
Wilcox k-omega two-equation model.
@ NS_2EQ_3D
NS + 2-equation RANS, 3D geometry (7 vars).
@ NS_SA_3D
NS + Spalart-Allmaras, 3D geometry (6 vars).
@ NS
Navier-Stokes, 2D geometry, 3D physics (5 vars).
@ NS_SA
NS + Spalart-Allmaras, 2D geometry (6 vars).
@ NS_2EQ
NS + 2-equation RANS, 2D geometry (7 vars).
@ NS_3D
Navier-Stokes, 3D geometry, 3D physics (5 vars).
@ NS_EX
Extended NS, 2D geometry, dynamic nVars (Eigen::Dynamic).
@ NS_2D
NS with 2D physics (2 velocity components, 4 vars). The only model with dim=2.
@ BCWallIsothermal
Isothermal wall; requires wall temperature in the BC value vector.
@ BCWall
No-slip viscous wall boundary.
Eigen::Matrix< real, 3, Eigen::Dynamic > tSmallCoords
void AllreduceOneReal(real &v, MPI_Op op, const MPIInfo &mpi)
Single-scalar Allreduce helper for reals (in-place, count = 1).
MPI_int Allreduce(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Allreduce.
const MPI_Datatype DNDS_MPI_INDEX
MPI datatype matching index (= MPI_INT64_T).
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
DNDS_CONSTANT const real pi
π in double precision (matches DNDS_E_PI macro).
Eigen::Matrix< real, Eigen::Dynamic, Eigen::Dynamic > MatrixXR
Column-major dynamic Eigen matrix of reals (default layout).
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).
DNDS_CONSTANT const real veryLargeReal
Catch-all upper bound ("practically infinity") for physical scalars.
const MPI_Datatype DNDS_MPI_REAL
MPI datatype matching real (= MPI_REAL8).
ssp< TArray > father
Owned-side array (must be resized before ghost setup).
index Size() const
Combined row count (father->Size() + son->Size()).
void Solve(tVec &b, tVec &result)
Complete LU factorization of the cell-local Jacobian for GMRES preconditioning.
One-dimensional profile for inlet/outlet boundary data.
void reduce(const TU_P_Reduction< TU > &R)
Eigen::Matrix wrapper that hides begin/end from fmt.
Eigen::Matrix< real, 5, 1 > v
Eigen::Vector3d n(1.0, 0.0, 0.0)