12#define CGAL_DISABLE_ROUNDING_MATH_CHECK
13#include <CGAL/Simple_cartesian.h>
14#include <CGAL/AABB_tree.h>
15#include <CGAL/AABB_traits_3.h>
16#include <CGAL/AABB_triangle_primitive_3.h>
17#undef CGAL_DISABLE_ROUNDING_MATH_CHECK
22 static const auto model =
NS_SA;
24 template <EulerModel model>
37 void EulerEvaluator<model>::GetWallDist_CollectTriangles(
39 std::vector<Eigen::Matrix<real, 3, 3>> &trianglesOut)
41 for (
index iBnd = 0; iBnd < mesh->NumBnd(); iBnd++)
46 index iFace = mesh->bnd2faceV[iBnd];
47 auto elem = mesh->GetFaceElement(iFace);
48 auto quad = vfv->GetFaceQuad(iFace);
54 mesh->GetCoordsOnFace(iFace, coords);
55 Eigen::Matrix<real, 3, 3> tri;
56 tri(EigenAll, 0) = coords(EigenAll, 0);
57 tri(EigenAll, 1) = coords(EigenAll, 1);
58 tri(EigenAll, 2) = coords(EigenAll, 1) +
Geom::tPoint{0., 0., vfv->GetFaceArea(iFace)};
59 trianglesOut.push_back(tri);
64 mesh->GetCoordsOnFace(iFace, coords);
65 Eigen::Matrix<real, 3, 3> tri;
66 tri(EigenAll, 0) = coords(EigenAll, 0);
67 tri(EigenAll, 1) = coords(EigenAll, 1);
68 tri(EigenAll, 2) = coords(EigenAll, 2);
69 trianglesOut.push_back(tri);
74 mesh->GetCoordsOnFace(iFace, coords);
75 Eigen::Matrix<real, 3, 3> tri;
76 tri(EigenAll, 0) = coords(EigenAll, 0);
77 tri(EigenAll, 1) = coords(EigenAll, 1);
78 tri(EigenAll, 2) = coords(EigenAll, 2);
79 trianglesOut.push_back(tri);
80 tri(EigenAll, 0) = coords(EigenAll, 0);
81 tri(EigenAll, 1) = coords(EigenAll, 2);
82 tri(EigenAll, 2) = coords(EigenAll, 3);
83 trianglesOut.push_back(tri);
93 for (
auto &qPatch : qPatches)
95 Eigen::Matrix<real, 3, 3> tri;
97 mesh->GetCoordsOnFace(iFace, coords);
98 for (
int iV = 0; iV < 3; iV++)
100 tri(EigenAll, iV) = coords(EigenAll, qPatch[iV] - 1);
101 else if (qPatch[iV] < 0)
102 tri(EigenAll, iV) = vfv->GetFaceQuadraturePPhys(iFace, -qPatch[iV] - 1);
104 tri(EigenAll, iV) = coords(EigenAll, 1) +
Geom::tPoint{0., 0., vfv->GetFaceArea(iFace)};
105 trianglesOut.push_back(tri);
113 template <EulerModel model>
121 void EulerEvaluator<model>::GetWallDist_ComputeFaceDistances()
123 dWallFace.resize(mesh->NumFaceProc());
124 for (
index iFace = 0; iFace < mesh->NumFaceProc(); iFace++)
126 auto f2c = mesh->face2cell[iFace];
127 real facialDist = dWall.at(f2c[0]).mean();
129 facialDist = 0.5 * (facialDist + dWall.at(f2c[1]).mean());
130 dWallFace[iFace] = facialDist;
135 template <EulerModel model>
144 void EulerEvaluator<model>::GetWallDist_AABB()
146 using TriArray = ArrayEigenMatrix<3, 3>;
147 ssp<TriArray> TrianglesLocal, TrianglesFull;
151 bool useQuadPatches = (settings.wallDistScheme == 1);
152 std::vector<Eigen::Matrix<real, 3, 3>> Triangles;
153 GetWallDist_CollectTriangles(useQuadPatches, Triangles);
155 TrianglesLocal->Resize(Triangles.size(), 3, 3);
156 for (
index i = 0; i < TrianglesLocal->Size(); i++)
157 (*TrianglesLocal)[i] = Triangles[i];
160 TrianglesTransformer.setFatherSon(TrianglesLocal, TrianglesFull);
161 TrianglesTransformer.createFatherGlobalMapping();
163 std::vector<index> pullingSet;
164 pullingSet.resize(TrianglesTransformer.pLGlobalMapping->globalSize());
165 for (
index i = 0; i < pullingSet.size(); i++)
167 TrianglesTransformer.createGhostMapping(pullingSet);
168 TrianglesTransformer.createMPITypes();
169 TrianglesTransformer.pullOnce();
170 if (mesh->coords.father->getMPI().rank == 0)
171 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() with minWallDist = {:.4e}, ", settings.minWallDist)
172 <<
" To search in " << TrianglesFull->Size() << std::endl;
174 auto executeSearch = [&]()
176 log() << fmt::format(
"Start search rank [{}]", mesh->getMPI().rank) << std::endl;
177 typedef CGAL::Simple_cartesian<double> K;
179 typedef K::Point_3 Point;
180 typedef K::Triangle_3 Triangle;
181 typedef std::vector<Triangle>::iterator Iterator;
182 typedef CGAL::AABB_triangle_primitive_3<K, Iterator> Primitive;
183 typedef CGAL::AABB_traits_3<K, Primitive> AABB_triangle_traits;
184 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
186 std::vector<Triangle> triangles;
187 triangles.reserve(TrianglesFull->Size());
189 for (
index i = 0; i < TrianglesFull->Size(); i++)
191 Point p0((*TrianglesFull)[i](0, 0), (*TrianglesFull)[i](1, 0), (*TrianglesFull)[i](2, 0));
192 Point p1((*TrianglesFull)[i](0, 1), (*TrianglesFull)[i](1, 1), (*TrianglesFull)[i](2, 1));
193 Point p2((*TrianglesFull)[i](0, 2), (*TrianglesFull)[i](1, 2), (*TrianglesFull)[i](2, 2));
194 triangles.push_back(Triangle(p0, p1, p2));
196 TrianglesLocal->Resize(0, 3, 3);
197 TrianglesFull->Resize(0, 3, 3);
199 this->dWall.resize(mesh->NumCellProc());
201 if (!triangles.empty())
203 Tree tree(triangles.begin(), triangles.end());
205 for (
index iCell = 0; iCell < mesh->NumCellProc(); iCell++)
207 auto quadCell = vfv->GetCellQuad(iCell);
208 dWall[iCell].resize(quadCell.GetNumPoints());
209 for (
int ig = 0; ig < quadCell.GetNumPoints(); ig++)
211 auto p = vfv->GetCellQuadraturePPhys(iCell, ig);
212 Point pQ(p[0], p[1], p[2]);
213 FT sqd = tree.squared_distance(pQ);
214 dWall[iCell][ig] = std::sqrt(sqd);
215 if (dWall[iCell][ig] < minDist)
216 minDist = dWall[iCell][ig];
217 dWall[iCell][ig] = std::max(settings.minWallDist, dWall[iCell][ig]);
223 for (
index iCell = 0; iCell < mesh->NumCellProc(); iCell++)
225 auto quadCell = vfv->GetCellQuad(iCell);
226 dWall[iCell].setConstant(quadCell.GetNumPoints(), std::pow(
veryLargeReal, 1. / 4.));
229 log() << fmt::format(
"[{}] MinDist: ", mesh->getMPI().rank) << minDist << std::endl;
231 if (settings.wallDistExection == 1)
233 { executeSearch(); });
234 else if (settings.wallDistExection > 1)
235 for (
int i = 0; i < settings.wallDistExection; i++)
237 if (mesh->getMPI().rank % settings.wallDistExection == i)
246 template <EulerModel model>
256 void EulerEvaluator<model>::GetWallDist_BatchedAABB()
258 typedef CGAL::Simple_cartesian<double> K;
260 typedef K::Point_3 Point;
261 typedef K::Triangle_3 Triangle;
262 typedef std::vector<Triangle>::iterator Iterator;
263 typedef CGAL::AABB_triangle_primitive_3<K, Iterator> Primitive;
264 typedef CGAL::AABB_traits_3<K, Primitive> AABB_triangle_traits;
265 typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
268 std::vector<Triangle> triangles;
269 triangles.reserve(mesh->NumBnd() * 8 + 8);
271 std::vector<Eigen::Matrix<real, 3, 3>> triEigen;
272 GetWallDist_CollectTriangles(
true, triEigen);
273 for (
auto &tri : triEigen)
275 Point p0(tri(0, 0), tri(1, 0), tri(2, 0));
276 Point p1(tri(0, 1), tri(1, 1), tri(2, 1));
277 Point p2(tri(0, 2), tri(1, 2), tri(2, 2));
278 triangles.push_back(Triangle(p0, p1, p2));
282 if (triangles.empty())
284 triangles.push_back(Triangle(
292 log() << fmt::format(
"[{},{}] ", mesh->getMPI().rank, triangles.size());
293 if (mesh->getMPI().rank % 10 == 0)
297 if (mesh->getMPI().rank == 0)
299 Tree tree(triangles.begin(), triangles.end());
301 if (settings.wallDistScheme == 2)
302 dWall.resize(mesh->NumCellProc());
304 index nProcessed = 0;
305 int cellLoadNum = std::max(1,
static_cast<int>(std::ceil(settings.wallDistCellLoadSize /
real(mesh->getMPI().size))));
306 if (mesh->coords.father->getMPI().rank == 0)
307 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() using cellLoadNum = {}, ", cellLoadNum)
310 if (settings.wallDistScheme == 20)
313 for (
auto &ds : dWall)
315 if (d <= settings.wallDistRefineMax)
318 if (mesh->coords.father->getMPI().rank == 0)
319 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() to refine {}, ", nRefine)
323 real t0 = MPI_Wtime();
324 for (
index iIter = 0;; iIter++)
326 std::vector<Geom::tPoint> pnts;
327 pnts.reserve(cellLoadNum * 64);
328 for (
int iCLoad = 0; iCLoad < cellLoadNum; iCLoad++)
330 index iCell = iCellBase + iCLoad;
331 if (iCell < mesh->NumCellProc())
333 auto quadCell = vfv->GetCellQuad(iCell);
334 for (
int ig = 0; ig < quadCell.GetNumPoints(); ig++)
336 if (settings.wallDistScheme == 20)
337 if (dWall[iCell][ig] > settings.wallDistRefineMax)
339 auto p = vfv->GetCellQuadraturePPhys(iCell, ig);
345 using PntArray = ArrayEigenMatrix<3, 1>;
346 ssp<PntArray> PntArrayLocal, PntArrayFull;
349 PntArrayLocal->Resize(pnts.size(), 3, 1);
350 for (
size_t i = 0; i < pnts.size(); i++)
351 (*PntArrayLocal)[i] = pnts[i];
353 PntTransformer.setFatherSon(PntArrayLocal, PntArrayFull);
354 PntTransformer.createFatherGlobalMapping();
355 std::vector<index> pullingSet;
356 pullingSet.resize(PntTransformer.pLGlobalMapping->globalSize());
357 if (!pullingSet.size())
359 if (mesh->getMPI().rank == 0)
360 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() iter [{}], nProcessed [{}], t [{:.6g}] ",
361 iIter, nProcessed, MPI_Wtime() - t0)
363 for (
index i = 0; i < pullingSet.size(); i++)
365 PntTransformer.createGhostMapping(pullingSet);
366 PntTransformer.createMPITypes();
367 PntTransformer.pullOnce();
368 if (mesh->getMPI().rank == 0)
369 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() iter [{}], pullOnce done, t [{:.6g}] ",
370 iIter, MPI_Wtime() - t0)
373 std::vector<real> distQueryFull(PntArrayFull->Size(),
veryLargeReal);
374 for (
int iQ = 0; iQ < PntArrayFull->Size(); iQ++)
376 Point pQ((*PntArrayFull)[iQ][0], (*PntArrayFull)[iQ][1], (*PntArrayFull)[iQ][2]);
377 FT sqd = tree.squared_distance(pQ);
378 distQueryFull[iQ] = std::sqrt(sqd);
380 if (mesh->getMPI().rank == 0)
381 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() iter [{}], query done, t [{:.6g}] ",
382 iIter, MPI_Wtime() - t0)
385 std::vector<real> distQueryFullReduced(PntArrayFull->Size(),
veryLargeReal);
386 MPI::Allreduce(distQueryFull.data(), distQueryFullReduced.data(), distQueryFull.size(),
DNDS_MPI_REAL, MPI_MIN, mesh->getMPI().comm);
388 if (mesh->getMPI().rank == 0)
389 log() << fmt::format(
"=== EulerEvaluator<model>::GetWallDist() iter [{}], reduce done, t [{:.6g}] ",
390 iIter, MPI_Wtime() - t0)
393 for (
int iCLoad = 0; iCLoad < cellLoadNum; iCLoad++)
395 index iCell = iCellBase + iCLoad;
396 if (iCell < mesh->NumCellProc())
398 auto quadCell = vfv->GetCellQuad(iCell);
399 if (settings.wallDistScheme == 2)
400 dWall[iCell].resize(quadCell.GetNumPoints());
401 for (
int ig = 0; ig < quadCell.GetNumPoints(); ig++)
403 if (settings.wallDistScheme == 20)
404 if (dWall[iCell][ig] > settings.wallDistRefineMax)
406 dWall[iCell][ig] = distQueryFullReduced.at(
407 PntTransformer.pLGhostMapping->ghostStart.at(mesh->getMPI().rank) +
414 iCellBase += cellLoadNum;
415 nProcessed += pullingSet.size();
420 template <EulerModel model>
430 void EulerEvaluator<model>::GetWallDist_Poisson()
432 int nSweep = settings.wallDistNJacobiSweep;
433 int nIter = settings.wallDistIter;
435 real smoothBias = 0.0;
436 int nGmresSubspace = 10;
437 int nGmresRestart = 1;
438 int useGmres = settings.wallDistLinSolver;
439 real resTh = settings.wallDistResTol;
441 int nPPoissonStartIter = settings.wallDistIterStart;
442 int nPPoisson = settings.wallDistPoissonP;
444 real dTauScale = settings.wallDistDTauScale;
446 ArrayDOFV<1> phi, rPhi, dPhi, dPhiNew, phiTmp, dTauInv;
447 ArrayDOFV<3> diffPhi;
448 vfv->BuildUDof(phi, 1);
449 vfv->BuildUDof(rPhi, 1);
450 vfv->BuildUDof(dPhi, 1);
451 vfv->BuildUDof(dPhiNew, 1);
452 vfv->BuildUDof(phiTmp, 1);
453 vfv->BuildUDof(dTauInv, 1);
454 vfv->BuildUDof(diffPhi, 3);
455 phi.setConstant(0.0);
456 dTauInv.setConstant(0.0);
458 std::vector<std::vector<real>> coefs;
459 coefs.resize(mesh->NumCell());
460 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
461 coefs.at(iCell).resize(mesh->cell2face[iCell].size() + 1);
463 std::vector<MatrixXR> mGGs;
464 mGGs.resize(mesh->NumCell());
467 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
469 Geom::tPoint bary = vfv->GetCellQuadraturePPhys(iCell, -1);
470 auto &mGG = mGGs.at(iCell);
471 mGG.setZero(3 + mesh->cell2face[iCell].size(), 3 + mesh->cell2face[iCell].size());
472 mGG({0, 1, 2}, {0, 1, 2}) = Eigen::Matrix3d::Identity();
473 real sumFaceArea = 0.;
474 for (
int ic2f = 0; ic2f < mesh->cell2face[iCell].size(); ic2f++)
476 index iFace = mesh->cell2face[iCell][ic2f];
477 index iCellOther = mesh->CellFaceOther(iCell, iFace);
478 int if2c = mesh->CellIsFaceBack(iCell, iFace) ? 0 : 1;
479 Geom::tPoint uNormOut = vfv->GetFaceNormFromCell(iFace, iCell, if2c, -1) * (if2c ? -1 : 1);
480 auto faceBndID = mesh->GetFaceZone(iFace);
481 auto faceBCType = pBCHandler->GetTypeFromID(faceBndID);
483 Geom::tPoint bFace = vfv->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, -1);
486 baryOther = vfv->GetOtherCellPointFromCell(
487 iCell, iCellOther, iFace,
488 vfv->GetCellQuadraturePPhys(iCellOther, -1));
494 baryOther = bFace * 2 - bary;
496 mGG({0, 1, 2}, 3 + ic2f) = -uNormOut * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell);
497 mGG(3 + ic2f, {0, 1, 2}) = (baryOther + bary - 2 * bFace).transpose();
498 mGG(3 + ic2f, 3 + ic2f) = 2;
499 sumFaceArea += vfv->GetFaceArea(iFace);
501 diffPhi[iCell] /= vfv->GetCellVol(iCell);
502 auto mGGLU = mGG.fullPivLu();
507 real LCell = vfv->GetCellVol(iCell) / sumFaceArea;
508 dTauInv[iCell](0) = 1. / (1. / std::pow(LCell, 2) * dTauScale);
510 dTauInv.trans.startPersistentPull();
511 dTauInv.trans.waitPersistentPull();
513 auto getDiffPhi = [&](ArrayDOFV<1> &phi, ArrayDOFV<3> &diffPhi)
515 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
517 Geom::tPoint bary = vfv->GetCellQuadraturePPhys(iCell, -1);
518 diffPhi[iCell].setZero();
519 Eigen::Vector<real, Eigen::Dynamic> bGG;
520 bGG.setZero(3 + mesh->cell2face[iCell].size());
521 for (
int ic2f = 0; ic2f < mesh->cell2face[iCell].size(); ic2f++)
523 index iFace = mesh->cell2face[iCell][ic2f];
524 index iCellOther = mesh->CellFaceOther(iCell, iFace);
525 int if2c = mesh->CellIsFaceBack(iCell, iFace) ? 0 : 1;
526 Geom::tPoint uNormOut = vfv->GetFaceNormFromCell(iFace, iCell, if2c, -1) * (if2c ? -1 : 1);
527 auto faceBndID = mesh->GetFaceZone(iFace);
528 auto faceBCType = pBCHandler->GetTypeFromID(faceBndID);
529 real phiOther = phi[iCell](0);
531 Geom::tPoint bFace = vfv->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, -1);
534 phiOther = phi[iCellOther](0);
535 baryOther = vfv->GetOtherCellPointFromCell(
536 iCell, iCellOther, iFace,
537 vfv->GetCellQuadraturePPhys(iCellOther, -1));
544 phiOther = -phi[iCell](0);
545 baryOther = bFace * 2 - bary;
547 real distThis = (bFace - bary).norm();
548 real distOther = (bFace - baryOther).norm();
549 real phiFace = (distOther * phi[iCell](0) + distThis * phiOther) / (distOther + distThis) - phi[iCell](0);
550 diffPhi[iCell] += uNormOut * vfv->GetFaceArea(iFace) * phiFace;
551 bGG(3 + ic2f) = phiOther + phi[iCell](0);
553 diffPhi[iCell] /= vfv->GetCellVol(iCell);
554 diffPhi[iCell] = (mGGs.at(iCell) * bGG)({0, 1, 2});
560 auto rhsPhi = [&](ArrayDOFV<1> &phi, ArrayDOFV<3> &diffPhi, ArrayDOFV<1> &rhs, std::vector<std::vector<real>> &coefs,
bool updateCoefs)
562 const real supressRec = 1.0;
563 getDiffPhi(phi, diffPhi);
564 diffPhi.trans.startPersistentPull();
565 diffPhi.trans.waitPersistentPull();
566 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
569 Geom::tPoint bary = vfv->GetCellQuadraturePPhys(iCell, -1);
571 coefs.at(iCell).at(0) = 0.;
572 for (
int ic2f = 0; ic2f < mesh->cell2face[iCell].size(); ic2f++)
574 index iFace = mesh->cell2face[iCell][ic2f];
575 index iCellOther = mesh->CellFaceOther(iCell, iFace);
576 int if2c = mesh->CellIsFaceBack(iCell, iFace) ? 0 : 1;
577 Geom::tPoint uNormOut = vfv->GetFaceNormFromCell(iFace, iCell, if2c, -1) * (if2c ? -1 : 1);
578 auto faceBndID = mesh->GetFaceZone(iFace);
579 auto faceBCType = pBCHandler->GetTypeFromID(faceBndID);
580 real phiOther = phi[iCell](0);
582 Geom::tPoint bFace = vfv->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, -1);
583 real phiThisFace = phi[iCell](0) + (bFace - bary).dot(diffPhi[iCell]) * supressRec;
584 real phiOtherFace = phiThisFace;
585 real diffPhiNormThis = diffPhi[iCell].dot(uNormOut) * supressRec;
586 real diffPhiNormOther = diffPhiNormThis;
590 phiOther = phi[iCellOther](0);
591 baryOther = vfv->GetOtherCellPointFromCell(
592 iCell, iCellOther, iFace,
593 vfv->GetCellQuadraturePPhys(iCellOther, -1));
594 phiOtherFace = phiOther + (bFace - baryOther).dot(diffPhi[iCellOther]) * supressRec;
595 diffPhiNormOther = diffPhi[iCellOther].dot(uNormOut) * supressRec;
596 diffPhiFace = 0.5 * (diffPhiFace + diffPhi[iCellOther] * supressRec);
603 phiOther = -phi[iCell](0), phiOtherFace = -phiThisFace;
606 diffPhiNormOther = -diffPhiNormThis;
607 diffPhiFace.setZero();
609 baryOther = bFace * 2 - bary;
612 real dist = std::abs((baryOther - bary).dot(uNormOut));
614 real diffPhiNorm = ((phiOtherFace - phiThisFace) * 1.0 / dist + 0.5 * (diffPhiNormOther + diffPhiNormThis));
615 diffPhiFace += ((phiOtherFace - phiThisFace) * 1.0 / dist) * uNormOut;
616 real diffPhiFaceMag = diffPhiFace.norm();
619 rhs[iCell](0) += std::pow(diffPhiFaceMag, pPoissonCur - 2) * diffPhiNorm * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell);
622 coefs.at(iCell).at(0) -= 1.0 / dist * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) * std::pow(diffPhiFaceMag, pPoissonCur - 2) * (pPoissonCur - 1);
623 coefs.at(iCell).at(1 + ic2f) = 1.0 / dist * vfv->GetFaceArea(iFace) / vfv->GetCellVol(iCell) * std::pow(diffPhiFaceMag, pPoissonCur - 2) * (pPoissonCur - 1);
629 auto solveDphi = [&](ArrayDOFV<1> &rhsPhi, ArrayDOFV<1> &dphi, ArrayDOFV<1> &dphiNew, std::vector<std::vector<real>> &coefs, ArrayDOFV<1> &dTauInv)
631 dphi.setConstant(0.0);
632 for (
int iSweep = 1; iSweep <= nSweep; iSweep++)
634 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
636 dphiNew[iCell] = rhsPhi[iCell];
637 for (
int ic2f = 0; ic2f < mesh->cell2face[iCell].size(); ic2f++)
639 index iFace = mesh->cell2face[iCell][ic2f];
640 index iCellOther = mesh->CellFaceOther(iCell, iFace);
642 dphiNew[iCell] += coefs[iCell][ic2f + 1] * dphi[iCellOther];
644 dphiNew[iCell] /= -coefs[iCell][0] + dTauInv[iCell](0);
646 dphiNew.trans.startPersistentPull();
647 dphiNew.trans.waitPersistentPull();
651 Linear::GMRES_LeftPreconditioned<ArrayDOFV<1>> gmres(
655 vfv->BuildUDof(
v, 1);
657 for (; pPoissonCur <= nPPoisson; pPoissonCur += 2)
662 for (
int iIter = 1; iIter <= nIter; iIter++)
664 rhsPhi(phi, diffPhi, rPhi, coefs,
true);
665 real normR = rPhi.norm2();
666 real normPhi = phi.norm2();
667 dPhi.setConstant(0.0);
671 solveDphi(rPhi, dPhi, dPhiNew, coefs, dTauInv);
676 [&](ArrayDOFV<1> &
x, ArrayDOFV<1> &
Ax)
678 real normX =
x.norm2();
681 rhsPhi(dPhiNew, diffPhi, phiTmp, coefs,
false);
682 dPhiNew.addTo(
x, ratio);
683 rhsPhi(dPhiNew, diffPhi,
Ax, coefs,
false);
684 Ax.addTo(phiTmp, -1.0);
689 Ax.trans.startPersistentPull();
690 Ax.trans.waitPersistentPull();
706 [&](ArrayDOFV<1> &
x, ArrayDOFV<1> &Mx)
709 solveDphi(
x, Mx, dPhiNew, coefs, dTauInv);
713 [&](ArrayDOFV<1> &a, ArrayDOFV<1> &
b) ->
real
728 real incNorm = dPhi.norm2();
731 phi.trans.startPersistentPull();
732 phi.trans.waitPersistentPull();
734 incNormBase = incNorm;
735 resNormBase = std::max(resNormBase, normR);
736 bool nowExit =
false;
737 if ((normR < resNormBase * resTh * std::pow(0.1, pPoissonCur - 2)) && iIter > nPPoissonStartIter)
739 if (iIter % nIterSee == 0 || iIter == nIter || nowExit)
740 if (phi.father->getMPI().rank == 0)
741 log() << fmt::format(
"EulerEvaluator<model>::GetWallDist(): poisson [p={}] [{}] inc: [{:.4e}] -> [{:.4e}], res: [{:.4e}] -> [{:.4e}]",
742 pPoissonCur, iIter, incNormBase, incNorm, resNormBase, normR)
747 getDiffPhi(phi, diffPhi);
748 diffPhi.trans.startPersistentPull();
749 diffPhi.trans.waitPersistentPull();
750 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
754 gradPhi = diffPhi[iCell];
756 for (
int ic2f = 0; ic2f < mesh->cell2face[iCell].size(); ic2f++)
758 index iFace = mesh->cell2face[iCell][ic2f];
759 index iCellOther = mesh->CellFaceOther(iCell, iFace);
762 gradPhi += diffPhi[iCell];
763 gradPhi += diffPhi[iCellOther] * smoothBias;
764 nD += 1. + smoothBias;
768 real gradPhiNorm = gradPhi.norm();
769 real dEst = std::pow(pPoissonCur /
real(pPoissonCur - 1) * phi[iCell](0) + std::pow(gradPhiNorm, pPoissonCur),
real(pPoissonCur - 1) / pPoissonCur) - std::pow(gradPhiNorm, pPoissonCur - 1);
771 dPhi[iCell](0) = dEst;
773 dPhi.trans.startPersistentPull();
774 dPhi.trans.waitPersistentPull();
778 auto minval = dPhi.min();
780 dWall.resize(mesh->NumCellProc());
781 for (
index iCell = 0; iCell < mesh->NumCellProc(); iCell++)
783 auto quadCell = vfv->GetCellQuad(iCell);
784 dWall[iCell].resize(quadCell.GetNumPoints());
787 for (
index iCell = 0; iCell < mesh->NumCellProc(); iCell++)
788 dWall.at(iCell).setConstant(std::max(dPhi[iCell](0), settings.minWallDist));
789 if (phi.father->getMPI().rank == 0)
790 log() << fmt::format(
"EulerEvaluator<model>::GetWallDist(): poisson min dist [{}]", minval(0)) << std::endl;
794 template <EulerModel model>
804 if (settings.wallDistScheme == 0 || settings.wallDistScheme == 1 || settings.wallDistScheme == 20)
806 if (settings.wallDistScheme == 2 || settings.wallDistScheme == 20)
807 GetWallDist_BatchedAABB();
808 if (settings.wallDistScheme == 3)
809 GetWallDist_Poisson();
810 GetWallDist_ComputeFaceDistances();
819 template <EulerModel model>
842 ArrayDOFV<nVarsFixed> &u,
843 ArrayRECV<nVarsFixed> &uRec,
852 bool dont_update_lambda01234 = flags & DT_Dont_update_lambda01234;
855 typename TVFV::template TFBoundary<nVarsFixed>
856 FBoundary = [&](
const TU &UL,
const TU &UMean,
index iCell,
index iFace,
int ig,
859 TVec normOutV = normOut(Seq012);
860 Eigen::Matrix<real, dim, dim> normBase = Geom::NormBuildLocalBaseV<dim>(normOutV);
861 bool compressed =
false;
862 TU ULfixed = this->CompressRecPart(
866 return this->generateBoundaryValue(ULfixed, UMean, iCell, iFace, ig, normOutV, normBase, pPhy, t, bType,
true, 1);
868 vfv->DoReconstruction2ndGrad(uGradBufNoLim, u, FBoundary, settings.direct2ndRecMethod);
869 uGradBufNoLim.trans.startPersistentPull();
870 uGradBufNoLim.trans.waitPersistentPull();
872#if defined(DNDS_DIST_MT_USE_OMP)
873# pragma omp parallel for schedule(runtime)
875 for (
index iFace = 0; iFace < mesh->NumFaceProc(); iFace++)
877 auto f2c = mesh->face2cell[iFace];
878 TVec unitNorm = vfv->GetFaceNorm(iFace, -1)(Seq012);
880 index iCellL = f2c[0];
882 this->UFromCell2Face(UL, iFace, f2c[0], 0);
884 real pL, asqrL, HL, pR, asqrR, HR;
885 TVec vL = UL(Seq123) / UL(0);
888 settings.idealGasProperty.gamma,
890 pR = pL, HR = HL, asqrR = asqrL;
894 this->UFromCell2Face(UR, iFace, f2c[1], 1);
895 uMean = (uMean + UR) * 0.5;
896 vR = UR(Seq123) / UR(0);
898 settings.idealGasProperty.gamma,
901 TDiffU GradULxy, GradURxy;
902 GradULxy.resize(Eigen::NoChange, nVars);
903 GradURxy.resize(Eigen::NoChange, nVars);
904 GradULxy.setZero(), GradURxy.setZero();
905 GradULxy(SeqG012, EigenAll) = uGradBuf[f2c[0]];
914 this->DiffUFromCell2Face(GradULxy, iFace, f2c[0], 0);
918 GradURxy(SeqG012, EigenAll) = uGradBuf[f2c[1]];
927 this->DiffUFromCell2Face(GradURxy, iFace, f2c[1], 1);
929 TDiffU GradUMeanXY = (GradURxy + GradULxy) / 2;
932 TVec veloMean = (uMean(Seq123).array() / uMean(0)).matrix();
934 real veloNMean = 0.5 * (vL + vR).dot(unitNorm);
935 real veloNL = vL.dot(unitNorm);
936 real veloNR = vR.dot(unitNorm);
937 real vgN = this->GetFaceVGrid(iFace, -1).dot(unitNorm);
951 real pMean, asqrMean, HMean;
953 settings.idealGasProperty.gamma,
954 pMean, asqrMean, HMean);
956 pMean = (pL + pR) * 0.5;
957 real aMean = sqrt(settings.idealGasProperty.gamma * pMean / uMean(0));
961 real lambdaConvection = std::abs(veloNMean - vgN) + aMean;
963 asqrL >= 0 && asqrR >= 0,
964 fmt::format(
" mean value violates PP! asqr: [{} {}]", asqrL, asqrR));
965 real aL = std::sqrt(asqrL);
966 real aR = std::sqrt(asqrR);
967 lambdaConvection = std::max(aL + std::abs(veloNL - vgN), aR + std::abs(veloNR - vgN));
970 real muRef = settings.idealGasProperty.muGas;
972 real gamma = settings.idealGasProperty.gamma;
973 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * uMean(0));
974 real muf = muEff(uMean, T);
976 real muTurb = this->getMuTur(uMean, GradUMeanXY, muRef, muf, iFace);
979 real lamVis = muf / uMean(0) *
980 std::max(4. / 3., gamma / settings.idealGasProperty.prGas);
982 real lamFace = lambdaConvection * vfv->GetFaceArea(iFace);
984 real area = vfv->GetFaceArea(iFace);
985 real areaSqr = area * area;
986 real volR = vfv->GetCellVol(iCellL);
990 volR = vfv->GetCellVol(f2c[1]);
992 lambdaFace[iFace] = lambdaConvection + lamVis * area * (1. / vfv->GetCellVol(iCellL) + 1. / volR);
993 lambdaFaceC[iFace] = std::abs(veloNMean - vgN) + lamVis * area * (1. / vfv->GetCellVol(iCellL) + 1. / volR);
994 lambdaFaceVis[iFace] = lamVis * area * (1. / vfv->GetCellVol(iCellL) + 1. / volR);
995 if (!dont_update_lambda01234)
996 lambdaFace0[iFace] = lambdaFace123[iFace] = lambdaFace4[iFace] = lambdaConvection;
1012 deltaLambdaFace[iFace] = std::max<real>({std::abs((vR - vL).dot(unitNorm) + aR - aL), std::abs((vR - vL).dot(unitNorm) - aR + aL), std::abs(aL - aR)});
1015#if defined(DNDS_DIST_MT_USE_OMP)
1016# pragma omp parallel for schedule(runtime) reduction(min : dtMin)
1018 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
1020 real lambdaCellC = 0;
1021 for (
auto iFace : mesh->cell2face[iCell])
1022 lambdaCellC += lambdaFace[iFace] * vfv->GetFaceArea(iFace);
1025 dt[iCell](0) = std::min(CFL * vfv->GetCellVol(iCell) * vfv->GetCellSmoothScaleRatio(iCell) / (lambdaCellC + 1e-100), MaxDt);
1026 dtMin = std::min(dtMin, dt[iCell](0));
1027 deltaLambdaCell[iCell](0) = 0;
1028 for (
auto iFace : mesh->cell2face[iCell])
1029 deltaLambdaCell[iCell](0) = std::max(deltaLambdaCell[iCell](0), deltaLambdaFace[iFace]);
1036 deltaLambdaCell.trans.startPersistentPull();
1038 deltaLambdaCell.trans.waitPersistentPull();
1044 dt.setConstant(dtMinall);
1052 template <EulerModel model>
1085 const TU_Batch &ULxy,
1086 const TU_Batch &URxy,
1089 const TDiffU_Batch &DiffUxy,
1090 const TDiffU_Batch &DiffUxyPrim,
1091 const TVec_Batch &unitNorm,
1092 const TVec_Batch &vgXY,
1093 const TVec &unitNormC,
1098 TReal_Batch &lam0V, TReal_Batch &lam123V, TReal_Batch &lam4V,
1101 index iFace,
bool ignoreVis)
1103 finc.resizeLike(ULxy);
1113 auto fluxFace_impl =
1133 const TU_Batch &ULxy = *p_ULxy;
1134 const TU_Batch &URxy = *p_URxy;
1135 const TU &ULMeanXy = *p_ULMeanXy;
1136 const TU &URMeanXy = *p_URMeanXy;
1137 const TDiffU_Batch &DiffUxy = *p_DiffUxy;
1138 const TDiffU_Batch &DiffUxyPrim = *p_DiffUxyPrim;
1139 const TVec_Batch &unitNorm = *p_unitNorm;
1140 const TVec_Batch &vgXY = *p_vgXY;
1141 const TVec &unitNormC = *p_unitNormC;
1142 const TVec &vgC = *p_vgC;
1143 TU_Batch &FLfix = *p_FLfix;
1144 TU_Batch &FRfix = *p_FRfix;
1145 TReal_Batch &lam0V = *p_lam0V;
1146 TReal_Batch &lam123V = *p_lam123V;
1147 TReal_Batch &lam4V = *p_lam4V;
1149 int nB = ULxy.cols();
1151 TU_Batch UMeanXy = 0.5 * (ULxy + URxy);
1154 real muRef = settings.idealGasProperty.muGas;
1155 real TRef = settings.idealGasProperty.TRef;
1157 auto f2c = mesh->face2cell[iFace];
1158 real dLambda = deltaLambdaCell[f2c[0]](0);
1160 dLambda = std::max(dLambda, deltaLambdaCell[f2c[1]](0));
1161 real fixScale = settings.rsFixScale;
1162 real incFScale = settings.rsIncFScale;
1165 visFluxV.resizeLike(ULxy);
1166 for (
int iB = 0; iB < nB; iB++)
1168 real pMean, asqrMean, Hmean;
1169 real gamma = settings.idealGasProperty.gamma;
1170 TU UMeanXYC = UMeanXy(EigenAll, iB);
1171 auto seqC = Eigen::seq(iB * dim, iB * dim + dim - 1);
1172 TDiffU DiffUxyC = DiffUxy(seqC, EigenAll);
1173 TDiffU DiffUxyPrimC = DiffUxyPrim(seqC, EigenAll);
1174 TVec uNormC = unitNorm(EigenAll, iB);
1175 Gas::IdealGasThermal(UMeanXYC(I4), UMeanXYC(0), (UMeanXYC(Seq123) / UMeanXYC(0)).squaredNorm(),
1176 gamma, pMean, asqrMean, Hmean);
1177 DNDS_assert_info(pMean > 0, fmt::format(
"{}, {}, {}", UMeanXYC(I4), UMeanXYC(0), (UMeanXYC(Seq123) / UMeanXYC(0)).squaredNorm()));
1178 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * UMeanXYC(0));
1180 muf = muEff(UMeanXYC, T);
1183#ifndef DNDS_FV_EULEREVALUATOR_IGNORE_VISCOUS_TERM
1186 real muTurb = this->getMuTur(UMeanXYC, DiffUxyC, muRef, muf, iFace);
1189 real k = settings.idealGasProperty.CpGas * muTurb / 0.9 +
1190 settings.idealGasProperty.CpGas * mufPhy / settings.idealGasProperty.prGas;
1192 VisFlux.resizeLike(ULMeanXy);
1194 Gas::ViscousFlux_IdealGas<dim>(
1196 settings.idealGasProperty.gamma,
1199 settings.idealGasProperty.CpGas,
1202 this->visFluxTurVariable(UMeanXYC, DiffUxyPrimC, muRef, mufPhy, muTurb, uNormC, iFace, VisFlux);
1208 visFluxV(EigenAll, iB) = VisFlux;
1211 if (!isfinite(pMean) || !isfinite(pMean) || !isfinite(pMean))
1213 std::cout << T << std::endl;
1214 std::cout << muf << std::endl;
1215 std::cout << pMean << std::endl;
1220 auto exitFun = [&]()
1222 std::cout <<
"face at" << vfv->GetFaceQuadraturePPhys(iFace, -1) <<
'\n';
1223 std::cout <<
"UL" << ULxy.transpose() <<
'\n';
1224 std::cout <<
"UR" << URxy.transpose() << std::endl;
1225 std::cout <<
"ULM" << ULMeanXy.transpose() <<
'\n';
1226 std::cout <<
"URM" << URMeanXy.transpose() << std::endl;
1241 auto &&UL,
auto &&UR,
auto &&ULm,
auto &&URm,
auto &&
vg,
auto &&
n,
1245 Gas::InviscidFlux_IdealGas_Dispatcher<dim>(rsType, UL, UR, ULm, URm,
vg,
n, gamma, finc, dLambda, fixScale, incFScale,exitFun, lam0, lam123, lam4);
1254 rsType = settings.rsTypeWall;
1257 auto runRsOnNorm = [&]()
1259 if (settings.rsMeanValueEig != 0 &&
1262 real lam0{0}, lam123{0}, lam4{0};
1263 Gas::InviscidFlux_IdealGas_Batch_Dispatcher<dim>(
1265 ULxy, URxy, ULMeanXy, URMeanXy, vgXY, vgC, unitNorm, unitNormC,
1266 settings.idealGasProperty.gamma, finc, dLambda, fixScale, incFScale,
1267 exitFun, lam0, lam123, lam4);
1268 lam0V.setConstant(lam0);
1269 lam123V.setConstant(lam123);
1270 lam4V.setConstant(lam4);
1273 for (
int iB = 0; iB < nB; iB++)
1275 RSWrapper_XY(rsType, ULxy(EigenAll, iB), URxy(EigenAll, iB), ULMeanXy, URMeanXy,
1276 vgXY(EigenAll, iB), unitNorm(EigenAll, iB),
1277 settings.idealGasProperty.gamma, finc(EigenAll, iB), dLambda, fixScale, incFScale,
1278 lam0V(iB), lam123V(iB), lam4V(iB));
1282 if (settings.rsRotateScheme == 0)
1288 TVec veloL = ULMeanXy(Seq123) / ULMeanXy(0);
1289 TVec veloR = URMeanXy(Seq123) / URMeanXy(0);
1290 TVec diffVelo = veloR - veloL;
1291 real diffVeloN = diffVelo.norm();
1292 real veloLN = veloL.norm();
1293 real veloRN = veloR.norm();
1299 if (settings.rsRotateScheme == 1)
1300 N1 = diffVelo / diffVeloN;
1301 else if (settings.rsRotateScheme == 2)
1305 DNDS_assert_info(std::abs(N1.norm() - 1) < 1e-5, fmt::format(
"{}", diffVeloN));
1306 N1 *=
sign(N1.dot(unitNormC));
1307 TReal_Batch N1Proj = N1.transpose() * unitNorm;
1309 TVec_Batch N2 = unitNorm - N1 * N1Proj;
1310 TReal_Batch N2Proj = N2.colwise().norm().array().max(
verySmallReal * 10);
1311 N2.array().rowwise() /= N2Proj.array();
1313 real N1ProjC = N1.dot(unitNormC);
1314 TVec N2C = unitNormC - N1 * N1ProjC;
1324 std::cout << unitNorm <<
"\n";
1325 std::cout <<
"N1" <<
"\n";
1326 std::cout << N1.transpose() <<
"\n";
1327 std::cout << N1B.transpose() <<
"\n";
1328 std::cout << N1Proj <<
"\n";
1329 std::cout <<
"N2" <<
"\n";
1330 std::cout << N2.transpose() <<
"\n";
1331 std::cout << N2Proj <<
"\n";
1332 std::cout << N2C.transpose() <<
"\n";
1333 std::cout << N2CProj <<
"\n";
1334 std::cout << std::endl;
1337 TReal_Batch lam4V1, lam0V1, lam123V1;
1338 lam0V1.resizeLike(lam0V);
1339 lam4V1.resizeLike(lam0V);
1340 lam123V1.resizeLike(lam0V);
1343 F1.resizeLike(finc);
1345 auto rsTypeAux = settings.rsTypeAux ==
Gas::UnknownRS ? rsType : settings.rsTypeAux;
1347 if (settings.rsMeanValueEig != 0 &&
1350 real lam0{0}, lam123{0}, lam4{0};
1351 Gas::InviscidFlux_IdealGas_Batch_Dispatcher<dim>(
1353 ULxy, URxy, ULMeanXy, URMeanXy, vgXY, vgC, N1B, N1,
1354 settings.idealGasProperty.gamma, F1, dLambda, fixScale, incFScale,
1355 exitFun, lam0, lam123, lam4);
1356 lam0V1.setConstant(lam0);
1357 lam123V1.setConstant(lam123);
1358 lam4V1.setConstant(lam4);
1361 for (
int iB = 0; iB < nB; iB++)
1363 RSWrapper_XY(rsTypeAux, ULxy(EigenAll, iB), URxy(EigenAll, iB), ULMeanXy, URMeanXy,
1364 vgXY(EigenAll, iB), N1,
1365 settings.idealGasProperty.gamma, F1(EigenAll, iB), dLambda, fixScale, incFScale,
1366 lam0V1(iB), lam123V1(iB), lam4V1(iB));
1369 if (settings.rsMeanValueEig != 0 &&
1372 real lam0{0}, lam123{0}, lam4{0};
1373 Gas::InviscidFlux_IdealGas_Batch_Dispatcher<dim>(
1375 ULxy, URxy, ULMeanXy, URMeanXy, vgXY, vgC, N2, N2C,
1376 settings.idealGasProperty.gamma, finc, dLambda, fixScale, incFScale,
1377 exitFun, lam0, lam123, lam4);
1378 lam0V.setConstant(lam0);
1379 lam123V.setConstant(lam123);
1380 lam4V.setConstant(lam4);
1383 for (
int iB = 0; iB < nB; iB++)
1385 RSWrapper_XY(rsType, ULxy(EigenAll, iB), URxy(EigenAll, iB), ULMeanXy, URMeanXy,
1386 vgXY(EigenAll, iB), N2(EigenAll, iB),
1387 settings.idealGasProperty.gamma, finc(EigenAll, iB), dLambda, fixScale, incFScale,
1388 lam0V(iB), lam123V(iB), lam4V(iB));
1391 finc.array().rowwise() *= N2Proj.array();
1392 finc.array() += F1.array().rowwise() * N1Proj.array();
1394 TReal_Batch N12ProjSum = N1Proj.array() + N2Proj.array();
1395 lam0V.array() *= N2Proj.array() / N12ProjSum.array();
1396 lam4V.array() *= N2Proj.array() / N12ProjSum.array();
1397 lam123V.array() *= N2Proj.array() / N12ProjSum.array();
1398 lam0V.array() += N1Proj.array() * lam0V1.array() / N12ProjSum.array();
1399 lam4V.array() += N1Proj.array() * lam4V1.array() / N12ProjSum.array();
1400 lam123V.array() += N1Proj.array() * lam123V1.array() / N12ProjSum.array();
1408#ifndef USE_ENTROPY_FIXED_LAMBDA_IN_SA
1409 lam123 = (std::abs(UL(1) / UL(0) -
vg(0)) + std::abs(UR(1) / UR(0) -
vg(0))) * 0.5;
1413 if constexpr (Traits::hasSA)
1416 Eigen::RowVector<
real, -1> lambdaFaceCC = lam123V;
1417 if (settings.ransEigScheme == 1)
1418 lambdaFaceCC = lambdaFaceCC.array().max(lam0V.array()).max(lam4V.array());
1419 auto vnR = ((URxy(Seq123, EigenAll).array().rowwise() / URxy(0, EigenAll).array() - vgXY.array()) * unitNorm.array()).colwise().sum();
1420 auto vnL = ((ULxy(Seq123, EigenAll).array().rowwise() / ULxy(0, EigenAll).array() - vgXY.array()) * unitNorm.array()).colwise().sum();
1421 finc(I4 + 1, EigenAll) =
1422 ((vnL * ULxy(I4 + 1, EigenAll).array() + vnR * URxy(I4 + 1, EigenAll).array()) -
1423 (URxy(I4 + 1, EigenAll).array() - ULxy(I4 + 1, EigenAll).array()) * lambdaFaceCC.array()) *
1426 if constexpr (Traits::has2EQ)
1428 Eigen::RowVector<
real, -1> lambdaFaceCC = lam123V;
1429 if (settings.ransEigScheme == 1)
1430 lambdaFaceCC = lambdaFaceCC.array().max(lam0V.array()).max(lam4V.array());
1431 auto vnR = ((URxy(Seq123, EigenAll).array().rowwise() / URxy(0, EigenAll).array() - vgXY.array()) * unitNorm.array()).colwise().sum();
1432 auto vnL = ((ULxy(Seq123, EigenAll).array().rowwise() / ULxy(0, EigenAll).array() - vgXY.array()) * unitNorm.array()).colwise().sum();
1433 finc(I4 + 1, EigenAll) =
1434 ((vnL * ULxy(I4 + 1, EigenAll).array() + vnR * URxy(I4 + 1, EigenAll).array()) -
1435 (URxy(I4 + 1, EigenAll).array() - ULxy(I4 + 1, EigenAll).array()) * lambdaFaceCC.array()) *
1437 finc(I4 + 2, EigenAll) =
1438 ((vnL * ULxy(I4 + 2, EigenAll).array() + vnR * URxy(I4 + 2, EigenAll).array()) -
1439 (URxy(I4 + 2, EigenAll).array() - ULxy(I4 + 2, EigenAll).array()) * lambdaFaceCC.array()) *
1441 finc(1, EigenAll).array() += UMeanXy(I4 + 1, EigenAll).array() * (2. / 3.);
1442 finc(I4, EigenAll).array() += UMeanXy(I4 + 1, EigenAll).array() * (2. / 3.) * UMeanXy(1, EigenAll).array() / UMeanXy(0, EigenAll).array();
1444 if constexpr (Traits::isExtended)
1447 Eigen::RowVector<
real, -1> lambdaFaceCC = lam123V;
1448 if (settings.ransEigScheme == 1)
1449 lambdaFaceCC = lambdaFaceCC.array().max(lam0V.array()).max(lam4V.array());
1450 auto vnR = ((URxy(Seq123, EigenAll).array().rowwise() / URxy(0, EigenAll).array() - vgXY.array()) * unitNorm.array()).colwise().sum();
1451 auto vnL = ((ULxy(Seq123, EigenAll).array().rowwise() / ULxy(0, EigenAll).array() - vgXY.array()) * unitNorm.array()).colwise().sum();
1452 finc(SeqI52Last, EigenAll) =
1453 ((vnL * ULxy(SeqI52Last, EigenAll).array() + vnR * URxy(SeqI52Last, EigenAll).array()) -
1454 (URxy(SeqI52Last, EigenAll).array() - ULxy(SeqI52Last, EigenAll).array()) * lambdaFaceCC.array()) *
1458#ifndef DNDS_FV_EULEREVALUATOR_IGNORE_VISCOUS_TERM
1463 if (finc.hasNaN() || (!finc.allFinite()))
1465 std::cout <<
"finc\n"
1466 << finc.transpose() <<
"\n";
1467 std::cout <<
"visFluxV\n"
1468 << visFluxV <<
"\n";
1469 std::cout <<
"lam0V\n"
1471 std::cout <<
"lam123V\n"
1473 std::cout <<
"lam4V\n"
1475 std::cout <<
"ULxy\n"
1476 << ULxy.transpose() <<
"\n";
1477 std::cout <<
"URxy\n"
1478 << URxy.transpose() <<
"\n";
1479 std::cout <<
"UMeanXy\n"
1480 << UMeanXy.transpose() <<
"\n";
1481 std::cout <<
"DiffUxy\n"
1483 std::cout <<
"DiffUxyPrim\n"
1484 << DiffUxyPrim <<
"\n";
1485 std::cout <<
"unitNorm\n"
1486 << unitNorm <<
"\n";
1487 std::cout <<
"btype\n"
1488 << btype << std::endl;
1495 return fluxFace_impl(
1508 &lam0V, &lam123V, &lam4V,
1514 template <EulerModel model>
1534 const TDiffU &DiffUxy,
1536 TJacobianU &jacobian,
1543 ret.resizeLike(UMeanXy);
1547 dWallC = dWall[iCell].mean();
1549 dWallC = dWall[iCell][ig];
1551 jacobian.setZero(UMeanXy.size(), UMeanXy.size());
1552#ifdef DNDS_FV_EULEREVALUATOR_SOURCE_TERM_ZERO
1557 ret(Seq123) += settings.constMassForce(Seq012) * UMeanXy(0);
1558 ret(I4) += settings.constMassForce(Seq012).dot(UMeanXy(Seq123));
1562 jacobian(I4, Seq123) -= settings.constMassForce(Seq012);
1564#ifdef USE_ABS_VELO_IN_ROTATION
1565 if (settings.frameConstRotation.enabled)
1567 if (Mode == 0 || Mode == 2)
1568 ret(Seq123) += -settings.frameConstRotation.vOmega().cross(Geom::ToThreeDim<dim>(UMeanXy(Seq123)))(Seq012);
1570 jacobian(Seq123, Seq123) -=
Geom::CrossVecToMat(-settings.frameConstRotation.vOmega())(Seq012, Seq012);
1573 if (settings.frameConstRotation.enabled)
1575 Geom::tPoint radi = pPhy - settings.frameConstRotation.center;
1576 Geom::tPoint radiR = radi - settings.frameConstRotation.axis * (settings.frameConstRotation.axis.dot(radi));
1577 TVec mvolForce = (radiR *
sqr(settings.frameConstRotation.Omega()) * UMeanXy(0))(Seq012);
1578 mvolForce += -2.0 * settings.frameConstRotation.vOmega().cross(Geom::ToThreeDim<dim>(UMeanXy(Seq123)))(Seq012);
1581 ret(Seq123) += mvolForce;
1582 ret(I4) += mvolForce.dot(UMeanXy(Seq123)) / UMeanXy(0);
1586 TMat dmvolForceDrhov =
Geom::CrossVecToMat(-2 * settings.frameConstRotation.vOmega())(Seq012, Seq012);
1587 jacobian(Seq123, Seq123) -= dmvolForceDrhov;
1588 jacobian(I4, Seq123) -= mvolForce + dmvolForceDrhov.transpose() * UMeanXy(Seq123) / UMeanXy(0);
1589 jacobian(I4, 0) -= -mvolForce.dot(UMeanXy(Seq123)) /
sqr(UMeanXy(0));
1596 uPrim.resizeLike(UMeanXy);
1605 if constexpr (Traits::isPlainNS)
1608 else if constexpr (Traits::hasSA)
1611 real pMean, asqrMean, Hmean;
1612 real gamma = settings.idealGasProperty.gamma;
1614 gamma, pMean, asqrMean, Hmean);
1616 real muRef = settings.idealGasProperty.muGas;
1617 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * UMeanXy(0));
1620 mufPhy = muf = muEff(UMeanXy, T);
1624 retInc.setZero(UMeanXy.size());
1627 real hMax = vfv->GetCellMaxLenScale(iCell);
1629 real lLES = hMax * settings.SADESScale;
1631 lLES = std::min(lLES, std::max({d * cWall, hMax * cWall}));
1632 auto sourceCaller = [&](
int mode)
1634 RANS::GetSource_SA<dim>(UMeanXy, DiffUxy, settings.idealGasProperty.muGas, muf,
1636 d, lLES, hMax, settings.SADESMode,
1638 settings.ransSARotCorrection, mode);
1652 jacobian += retInc.asDiagonal();
1656 else if constexpr (Traits::has2EQ)
1658 real pMean, asqrMean, Hmean;
1659 real gamma = settings.idealGasProperty.gamma;
1661 gamma, pMean, asqrMean, Hmean);
1663 real muRef = settings.idealGasProperty.muGas;
1664 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * UMeanXy(0));
1667 mufPhy = muf = muEff(UMeanXy, T);
1670 retInc.setZero(UMeanXy.size());
1672 TU UMeanXyFixed = UMeanXy;
1683 auto sourceCaller = [&](
int mode)
1686 RANS::GetSource_SST<dim>(UMeanXyFixed, DiffUxy, mufPhy, dWallC, vfv->GetCellMaxLenScale(iCell) * settings.SADESScale, retInc, mode);
1688 RANS::GetSource_KOWilcox<dim>(UMeanXyFixed, DiffUxy, mufPhy, dWallC, retInc, mode);
1690 RANS::GetSource_RealizableKe<dim>(UMeanXyFixed, DiffUxy, mufPhy, dWallC, retInc, mode);
1704 jacobian += retInc.asDiagonal();
1718 template <EulerModel model>
1747 const TMat &normBase,
1752 int geomMode,
int linMode)
1758 URxy.resizeLike(ULxy);
1759 auto bTypeEuler = pBCHandler->GetTypeFromID(btype);
1773 if (btype == Geom::BC_ID_DEFAULT_FAR ||
1777 URxy = generateBV_FarField(ULxy, ULMeanXy, iCell, iFace, iG,
1778 uNorm, normBase, pPhysics, t, btype, fixUL, geomMode);
1782 URxy = generateBV_SpecialFar(ULxy, ULMeanXy, iCell, iFace, iG,
1783 uNorm, normBase, pPhysics, t, btype);
1789 URxy = generateBV_InviscidWall(ULxy, ULMeanXy, iCell, iFace, iG,
1790 uNorm, normBase, pPhysics, t, btype);
1797 URxy = generateBV_ViscousWall(ULxy, ULMeanXy, iCell, iFace, iG,
1798 uNorm, normBase, pPhysics, t, btype, fixUL, linMode);
1804 URxy = generateBV_Outflow(ULxy, ULMeanXy, iCell, iFace, iG,
1805 uNorm, normBase, pPhysics, t, btype);
1819 URxy = generateBV_Inflow(ULxy, ULMeanXy, iCell, iFace, iG,
1820 uNorm, normBase, pPhysics, t, btype);
1829 URxy = generateBV_TotalConditionInflow(ULxy, ULMeanXy, iCell, iFace, iG,
1830 uNorm, normBase, pPhysics, t, btype);
1844 template <EulerModel model>
1870 TU &ULxy,
const TU &ULMeanXy,
1872 const TVec &uNorm,
const TMat &normBase,
1877 auto bTypeEuler = pBCHandler->GetTypeFromID(btype);
1879 URxy.resizeLike(ULxy);
1881 TU far = btype >= Geom::BC_ID_DEFAULT_MAX
1882 ? pBCHandler->GetValueFromID(btype)
1883 : TU(settings.farFieldStaticValue);
1885 far(Seq123) = pCLDriver->GetAOARotation()(Seq012, Seq012) * far(Seq123);
1889 if (settings.frameConstRotation.enabled && pBCHandler->GetFlagFromID(btype,
"frameOpt") != 0)
1890 far(Seq123) = (
Geom::RotateAxis(-settings.frameConstRotation.vOmega() * t) * Geom::ToThreeDim<dim>(far(Seq123)))(Seq012);
1893 TU ULxyStatic = ULxy;
1894 if (settings.frameConstRotation.enabled)
1895 TransformURotatingFrame(ULxyStatic, pPhysics, 1);
1897 real un = ULxy(Seq123).dot(uNorm) / ULxy(0);
1898 real gamma = settings.idealGasProperty.gamma;
1900 Gas::IdealGasThermal(ULxyStatic(I4), ULxyStatic(0), (ULxyStatic(Seq123) / ULxyStatic(0)).squaredNorm(), gamma, p, asqr, H);
1903 real a = std::sqrt(asqr);
1905 auto vg = this->GetFaceVGrid(iFace, iG, pPhysics);
1906 real vgN =
vg.dot(uNorm);
1908 if (un - vgN - a > 0)
1912 else if (un - vgN > 0)
1914 TU farPrimitive, ULxyPrimitive;
1915 farPrimitive.resizeLike(ULxyStatic);
1916 ULxyPrimitive.resizeLike(URxy);
1917 Gas::IdealGasThermalConservative2Primitive<dim>(far, farPrimitive, gamma);
1918 Gas::IdealGasThermalConservative2Primitive<dim>(ULxyStatic, ULxyPrimitive, gamma);
1919 if (bTypeEuler ==
EulerBCType::BCOutP && pBCHandler->GetFlagFromID(btype,
"anchorOpt") == 1)
1922 TU anchorPointRel = ULxy;
1923 if (anchorRecorders.count(btype))
1924 anchorPointRel = anchorRecorders.at(btype).val;
1925 TU anchorPointRelPrimitive = anchorPointRel;
1926 Gas::IdealGasThermalConservative2Primitive<dim>(anchorPointRel, anchorPointRelPrimitive, gamma);
1927 farPrimitive(I4) += std::max(ULxyPrimitive(I4) - anchorPointRelPrimitive(I4), -0.95 * farPrimitive(I4));
1930 if (bTypeEuler ==
EulerBCType::BCOutP && pBCHandler->GetFlagFromID(btype,
"anchorOpt") == 2)
1933 if (profileRecorders.count(btype))
1934 pInc = profileRecorders.at(btype).GetPlain(settings.frameConstRotation.rVec(pPhysics).norm())(I4);
1935 farPrimitive(I4) += std::max(pInc, -0.95 * farPrimitive(I4));
1937 ULxyPrimitive(I4) = farPrimitive(I4);
1938 Gas::IdealGasThermalPrimitive2Conservative<dim>(ULxyPrimitive, URxy, gamma);
1940 else if (un - vgN + a > 0)
1942 TU farPrimitive, ULxyPrimitive;
1943 farPrimitive.resizeLike(ULxyStatic);
1944 ULxyPrimitive.resizeLike(URxy);
1945 Gas::IdealGasThermalConservative2Primitive<dim>(far, farPrimitive, gamma);
1946 Gas::IdealGasThermalConservative2Primitive<dim>(ULxyStatic, ULxyPrimitive, gamma);
1947 farPrimitive(I4) = ULxyPrimitive(I4);
1948 Gas::IdealGasThermalPrimitive2Conservative<dim>(farPrimitive, URxy, gamma);
1954 if (settings.frameConstRotation.enabled)
1955 TransformURotatingFrame(URxy, pPhysics, -1);
1960 template <EulerModel model>
1982 TU &ULxy,
const TU &ULMeanXy,
1984 const TVec &uNorm,
const TMat &normBase,
1990 URxy.resizeLike(ULxy);
1992 if (btype == Geom::BC_ID_DEFAULT_SPECIAL_DMR_FAR)
1995 URxy = settings.farFieldStaticValue;
1997 if constexpr (dim == 3)
1999 if (((pPhysics(0) - uShock / std::sin(
pi / 3) * t - 1. / 6.) -
2000 pPhysics(1) / std::tan(
pi / 3)) > 0)
2001 URxy({0, 1, 2, 3, 4}) = Eigen::Vector<real, 5>{1.4, 0, 0, 0, 2.5};
2003 URxy({0, 1, 2, 3, 4}) = Eigen::Vector<real, 5>{8, 57.157676649772960, -33, 0, 5.635e2};
2007 if (((pPhysics(0) - uShock / std::sin(
pi / 3) * t - 1. / 6.) -
2008 pPhysics(1) / std::tan(
pi / 3)) > 0)
2009 URxy({0, 1, 2, 3}) = Eigen::Vector<real, 4>{1.4, 0, 0, 2.5};
2011 URxy({0, 1, 2, 3}) = Eigen::Vector<real, 4>{8, 57.157676649772960, -33, 5.635e2};
2014 else if (btype == Geom::BC_ID_DEFAULT_SPECIAL_RT_FAR)
2017 Eigen::VectorXd far = settings.farFieldStaticValue;
2018 real gamma = settings.idealGasProperty.gamma;
2019 real un = ULxy(Seq123).dot(uNorm) / ULxy(0);
2020 real vsqr = (ULxy(Seq123) / ULxy(0)).squaredNorm();
2025 real a = std::sqrt(asqr);
2026 real v = -0.025 * a * cos(pPhysics(0) * 8 *
pi);
2028 if (pPhysics(1) < 0.5)
2035 far(I4) = 0.5 * rho *
sqr(
v) + p / (gamma - 1);
2044 far(I4) = 0.5 * rho *
sqr(
v) + p / (gamma - 1);
2051 TU farPrimitive, ULxyPrimitive;
2052 farPrimitive.resizeLike(ULxy);
2053 ULxyPrimitive.resizeLike(URxy);
2054 Gas::IdealGasThermalConservative2Primitive<dim>(far, farPrimitive, gamma);
2055 Gas::IdealGasThermalConservative2Primitive<dim>(ULxy, ULxyPrimitive, gamma);
2056 ULxyPrimitive(I4) = farPrimitive(I4);
2057 Gas::IdealGasThermalPrimitive2Conservative<dim>(ULxyPrimitive, URxy, gamma);
2059 else if (un + a > 0)
2061 TU farPrimitive, ULxyPrimitive;
2062 farPrimitive.resizeLike(ULxy);
2063 ULxyPrimitive.resizeLike(URxy);
2064 Gas::IdealGasThermalConservative2Primitive<dim>(far, farPrimitive, gamma);
2065 Gas::IdealGasThermalConservative2Primitive<dim>(ULxy, ULxyPrimitive, gamma);
2066 farPrimitive(I4) = ULxyPrimitive(I4);
2067 Gas::IdealGasThermalPrimitive2Conservative<dim>(farPrimitive, URxy, gamma);
2072 else if (btype == Geom::BC_ID_DEFAULT_SPECIAL_IV_FAR)
2075 real gamma = settings.idealGasProperty.gamma;
2078 real r = std::sqrt(
sqr(pPhysics(0) - xc) +
sqr(pPhysics(1) - yc));
2079 real dT = -(gamma - 1) / (8 * gamma *
sqr(
pi)) *
sqr(chi) * std::exp(1 -
sqr(
r));
2080 real dux = chi / 2 /
pi * std::exp((1 -
sqr(
r)) / 2) * -(pPhysics(1) - xc);
2081 real duy = chi / 2 /
pi * std::exp((1 -
sqr(
r)) / 2) * +(pPhysics(0) - yc);
2086 real rho = std::pow(T /
S, 1 / (gamma - 1));
2087 real pVal = T * rho;
2088 real E = 0.5 * (
sqr(ux) +
sqr(uy)) * rho + pVal / (gamma - 1);
2096 else if (btype == Geom::BC_ID_DEFAULT_SPECIAL_2DRiemann_FAR)
2098 real gamma = settings.idealGasProperty.gamma;
2099 real bdL = 0.0, bdR = 1.0, bdD = 0.0, bdU = 1.0;
2101 real phi1 = -0.663324958071080;
2102 real phi2 = -0.422115882408869;
2103 real location = 0.8;
2104 real p1 = location + phi1 * t;
2105 real p2 = location + phi2 * t;
2106 real rho, u,
v, pre;
2108 ULxyPrimitive.resizeLike(ULxy);
2110 Gas::IdealGasThermalConservative2Primitive<dim>(ULxy, ULxyPrimitive, gamma);
2111 real rhoL = ULxyPrimitive(0);
2112 real uL = ULxyPrimitive(1);
2113 real vL = ULxyPrimitive(2);
2114 real preL = ULxyPrimitive(I4);
2115 TU farPrimitive = ULxyPrimitive;
2117 static const real bTol = 1e-9;
2118 if (std::abs(pPhysics(0) - bdL) < bTol)
2120 if (pPhysics(1) <= p2)
2121 rho = 0.137992831541219, u = 1.206045378311055,
v = 1.206045378311055, pre = 0.029032258064516;
2123 rho = 0.532258064516129, u = 1.206045378311055,
v = 0.0, pre = 0.3;
2125 else if (std::abs(pPhysics(0) - bdR) < bTol)
2127 if (pPhysics(1) <= p1)
2128 rho = rhoL, u = -uL,
v = vL, pre = preL;
2130 rho = rhoL, u = -uL,
v = vL, pre = preL;
2132 else if (std::abs(pPhysics(1) - bdU) < bTol)
2134 if (pPhysics(0) <= p1)
2135 rho = rhoL, u = uL,
v = -vL, pre = preL;
2137 rho = rhoL, u = uL,
v = -vL, pre = preL;
2139 else if (std::abs(pPhysics(1) - bdD) < bTol)
2141 if (pPhysics(0) <= p2)
2142 rho = 0.137992831541219, u = 1.206045378311055,
v = 1.206045378311055, pre = 0.029032258064516;
2144 rho = 0.532258064516129, u = 0.0,
v = 1.206045378311055, pre = 0.3;
2148 rho = u =
v = pre = std::nan(
"1");
2151 farPrimitive(0) = rho;
2152 farPrimitive(1) = u, farPrimitive(2) =
v;
2153 farPrimitive(I4) = pre;
2154 Gas::IdealGasThermalPrimitive2Conservative<dim>(farPrimitive, URxy, gamma);
2156 else if (pBCHandler->GetFlagFromID(btype,
"specialOpt") == 3001)
2159 Gas::IdealGasThermalConservative2Primitive<dim>(settings.farFieldStaticValue, farPrimitive, settings.idealGasProperty.gamma);
2160 real pInf = farPrimitive(I4);
2161 real r = pPhysics.norm();
2164 farPrimitive(0) = rho;
2165 farPrimitive(Seq123) =
velo;
2166 farPrimitive(I4) = pInf;
2167 Gas::IdealGasThermalPrimitive2Conservative<dim>(farPrimitive, URxy, settings.idealGasProperty.gamma);
2171 "btype [{}] or bTypeEuler [{}] or specialOpt [{}] is not supported",
2172 btype,
to_string(pBCHandler->GetTypeFromID(btype)),
2173 pBCHandler->GetFlagFromIDSoft(btype,
"specialOpt")));
2178 template <EulerModel model>
2199 TU &ULxy,
const TU &ULMeanXy,
2201 const TVec &uNorm,
const TMat &normBase,
2207 if (settings.frameConstRotation.enabled)
2208 this->TransformURotatingFrame_ABS_VELO(URxy, pPhysics, -1);
2209 URxy(Seq123) -= 2 * URxy(Seq123).dot(uNorm) * uNorm;
2210 if (settings.frameConstRotation.enabled)
2211 this->TransformURotatingFrame_ABS_VELO(URxy, pPhysics, 1);
2216 template <EulerModel model>
2241 TU &ULxy,
const TU &ULMeanXy,
2243 const TVec &uNorm,
const TMat &normBase,
2248 auto bTypeEuler = pBCHandler->GetTypeFromID(btype);
2252 if (settings.frameConstRotation.enabled && pBCHandler->GetFlagFromID(btype,
"frameOpt") == 0)
2253 this->TransformURotatingFrame_ABS_VELO(URxy, pPhysics, -1);
2254 if (settings.frameConstRotation.enabled && pBCHandler->GetFlagFromID(btype,
"frameOpt") != 0)
2255 this->TransformURotatingFrame(URxy, pPhysics, 1);
2257 if (settings.frameConstRotation.enabled && pBCHandler->GetFlagFromID(btype,
"frameOpt") == 0)
2258 this->TransformURotatingFrame_ABS_VELO(URxy, pPhysics, 1);
2259 if (settings.frameConstRotation.enabled && pBCHandler->GetFlagFromID(btype,
"frameOpt") != 0)
2260 this->TransformURotatingFrame(URxy, pPhysics, -1);
2268 real temp = pBCHandler->GetValueFromID(btype)(0);
2270 URxyPrim.resizeLike(ULxy);
2271 Gas::IdealGasThermalConservative2Primitive<dim>(URxy, URxyPrim, settings.idealGasProperty.gamma);
2272 DNDS_assert_info(URxyPrim(0) > 0 && URxyPrim(I4) > 0 && temp > 0, fmt::format(
"{}, {}, {}", URxyPrim(0), URxyPrim(I4), temp));
2273 real newDensity = URxyPrim(I4) / temp / settings.idealGasProperty.Rgas;
2274 URxyPrim(0) = newDensity;
2275 Gas::IdealGasThermalPrimitive2Conservative<dim>(URxyPrim, URxy, settings.idealGasProperty.gamma);
2277 if constexpr (Traits::hasSA)
2280#ifdef USE_FIX_ZERO_SA_NUT_AT_WALL
2282 ULxy(I4 + 1) = URxy(I4 + 1) = 0;
2285 if constexpr (Traits::has2EQ)
2287 URxy({I4 + 1, I4 + 2}) *= -1;
2288#ifdef USE_FIX_ZERO_SA_NUT_AT_WALL
2294 real d1 = dWall[iCell].mean();
2295 real k1 = ULMeanXy(I4 + 1) / ULMeanXy(0);
2297 real pMean, asqrMean, Hmean;
2298 real gamma = settings.idealGasProperty.gamma;
2299 Gas::IdealGasThermal(ULMeanXy(I4), ULMeanXy(0), (ULMeanXy(Seq123) / ULMeanXy(0)).squaredNorm(),
2300 gamma, pMean, asqrMean, Hmean);
2301 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * ULMeanXy(0));
2302 real mufPhy1 = muEff(ULMeanXy, T);
2303 real epsWall = 2 * mufPhy1 / ULMeanXy(0) * k1 /
sqr(d1);
2304 URxy(I4 + 2) = 2 * epsWall * ULxy(0) - ULxy(I4 + 2);
2309 real d1 = dWall[iCell].mean();
2310 real pMean, asqrMean, Hmean;
2311 real gamma = settings.idealGasProperty.gamma;
2312 Gas::IdealGasThermal(ULMeanXy(I4), ULMeanXy(0), (ULMeanXy(Seq123) / ULMeanXy(0)).squaredNorm(),
2313 gamma, pMean, asqrMean, Hmean);
2314 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * ULMeanXy(0));
2315 real mufPhy1 = muEff(ULMeanXy, T);
2317 real rhoOmegaaaWall = mufPhy1 /
sqr(d1) * RANS::kWallOmegaCoeff;
2318 URxy(I4 + 2) = 2 * rhoOmegaaaWall - ULxy(I4 + 2);
2325 template <EulerModel model>
2346 TU &ULxy,
const TU &ULMeanXy,
2348 const TVec &uNorm,
const TMat &normBase,
2356 template <EulerModel model>
2377 TU &ULxy,
const TU &ULMeanXy,
2379 const TVec &uNorm,
const TMat &normBase,
2384 TU URxy = pBCHandler->GetValueFromID(btype);
2386 URxy(Seq123) = pCLDriver->GetAOARotation()(Seq012, Seq012) * URxy(Seq123);
2388 if (settings.frameConstRotation.enabled)
2389 TransformURotatingFrame(URxy, pPhysics, -1);
2394 template <EulerModel model>
2417 TU &ULxy,
const TU &ULMeanXy,
2419 const TVec &uNorm,
const TMat &normBase,
2425 URxy.resizeLike(ULxy);
2427 TU ULxyStatic = ULxy;
2428 if (settings.frameConstRotation.enabled)
2429 TransformURotatingFrame(ULxyStatic, pPhysics, 1);
2431 ULxyPrimitive.resizeLike(ULxy);
2432 real gamma = settings.idealGasProperty.gamma;
2433 Gas::IdealGasThermalConservative2Primitive<dim>(ULxyStatic, ULxyPrimitive, gamma);
2434 TVec
v = ULxyStatic(Seq123).array() / ULxyStatic(0);
2435 real vSqr =
v.squaredNorm();
2437 TU farPrimitive = pBCHandler->GetValueFromID(btype);
2439 real pStag = pBCHandler->GetValueFromID(btype)(0);
2440 real tStag = pBCHandler->GetValueFromID(btype)(1);
2441 vSqr = std::min(vSqr, tStag * 2 * settings.idealGasProperty.CpGas * 0.95);
2442 real tStatic = tStag - 0.5 * vSqr / (settings.idealGasProperty.CpGas);
2443 real pStatic = pStag * std::pow(tStatic / tStag, gamma / (gamma - 1));
2444 real rStatic = pStatic / (settings.idealGasProperty.Rgas * tStatic);
2445 farPrimitive(0) = rStatic;
2446 farPrimitive(Seq123) = pBCHandler->GetValueFromID(btype)(Seq234).normalized() * std::sqrt(vSqr);
2447 farPrimitive(I4) = pStatic;
2448 Gas::IdealGasThermalPrimitive2Conservative<dim>(farPrimitive, URxy, gamma);
2451 URxy(Seq123) = pCLDriver->GetAOARotation()(Seq012, Seq012) * URxy(Seq123);
2452 if (settings.frameConstRotation.enabled)
2453 TransformURotatingFrame(URxy, pPhysics, -1);
2457 template <EulerModel model>
2473 auto &u = dataRefs.
u;
2474 auto &uRec = dataRefs.
uRec;
2475 auto &betaPP = dataRefs.
betaPP;
2476 auto &alphaPP = dataRefs.
alphaPP;
2481 outMap[
"RU"] = [&](
index iCell)
2482 {
return u[iCell](1); };
2483 outMap[
"RV"] = [&](
index iCell)
2484 {
return u[iCell](2); };
2485 outMap[
"RV"] = [&](
index iCell)
2486 {
return u[iCell](I4 - 1); };
2487 outMap[
"RE"] = [&](
index iCell)
2488 {
return u[iCell](I4); };
2489 outMap[
"R_REC_1"] = [&](
index iCell)
2490 {
return uRec[iCell](0, 0); };
2491 outMap[
"RU_REC_1"] = [&](
index iCell)
2492 {
return uRec[iCell](1, 0); };
2495 outMap[
"betaPP"] = [&](
index iCell)
2496 {
return betaPP[iCell](0); };
2497 outMap[
"alphaPP"] = [&](
index iCell)
2498 {
return alphaPP[iCell](0); };
2499 outMap[
"ACond"] = [&](
index iCell)
2501 auto AI = vfv->GetCellRecMatAInv(iCell);
2502 Eigen::MatrixXd AIInv = AI;
2506 outMap[
"dWall"] = [&](
index iCell)
2508 return eval.dWall.at(iCell).mean();
2510 outMap[
"minJacobiDetRel"] = [&](
index iCell)
2512 auto eCell = mesh->GetCellElement(iCell);
2513 auto qCell = vfv->GetCellQuad(iCell);
2515 for (
int iG = 0; iG < qCell.GetNumPoints(); iG++)
2516 minDetJac = std::min(vfv->GetCellJacobiDet(iCell, iG), minDetJac);
2519 outMap[
"cellVolume"] = [&](
index iCell)
2521 return vfv->GetCellVol(iCell);
2523 outMap[
"mut"] = [&](
index iCell)
2530 GradU.resize(Eigen::NoChange, nVars);
2532 if constexpr (gDim == 2)
2533 GradU({0, 1}, EigenAll) =
2534 vfv->GetIntPointDiffBaseValue(iCell, -1, -1, -1, std::array<int, 2>{1, 2}, 3) *
2537 GradU({0, 1, 2}, EigenAll) =
2538 vfv->GetIntPointDiffBaseValue(iCell, -1, -1, -1, std::array<int, 3>{1, 2, 3}, 4) *
2540 real pMean, asqrMean, Hmean;
2541 real gamma = settings.idealGasProperty.gamma;
2542 auto ULMeanXy = Uxy;
2543 Gas::IdealGasThermal(ULMeanXy(I4), ULMeanXy(0), (ULMeanXy(Seq123) / ULMeanXy(0)).squaredNorm(),
2544 gamma, pMean, asqrMean, Hmean);
2546 real muRef = settings.idealGasProperty.muGas;
2547 real T = pMean / ((gamma - 1) / gamma * settings.idealGasProperty.CpGas * ULMeanXy(0));
2548 real mufPhy = muEff(ULMeanXy, T);
2550 mut = RANS::GetMut_SST<dim>(Uxy, GradU, mufPhy, dWall[iCell].mean());
2552 mut = RANS::GetMut_KOWilcox<dim>(Uxy, GradU, mufPhy, dWall[iCell].mean());
2554 mut = RANS::GetMut_RealizableKe<dim>(Uxy, GradU, mufPhy, dWall[iCell].mean());
#define DNDS_MAKE_SSP(ssp,...)
#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 + ...
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.
#define DNDS_MPI_InsertCheck(mpi, info)
Debug helper: barrier + print "CHECK <info> RANK r @ fn @ file:line".
#define DNDS_SWITCH_INTELLISENSE(real, intellisense)
RANS two-equation turbulence model implementations for the DNDSR CFD solver.
void GetWallDist()
Compute wall distance for all cells (dispatcher).
void InitializeOutputPicker(OutputPicker &op, OutputOverlapDataRefs dataRefs)
Initialize an OutputPicker with field callbacks for VTK/HDF5 output.
Eigen::VectorFMTSafe< real, nVarsFixed > TU
Conservative variable vector (nVarsFixed components).
void EvaluateDt(ArrayDOFV< 1 > &dt, ArrayDOFV< nVarsFixed > &u, ArrayRECV< nVarsFixed > &uRec, real CFL, real &dtMinall, real MaxDt, bool UseLocaldt, real t, uint64_t flags=DT_No_Flags)
Estimate the local or global time step for each cell.
TU generateBoundaryValue(TU &ULxy, const TU &ULMeanXy, index iCell, index iFace, int iG, const TVec &uNorm, const TMat &normBase, const Geom::tPoint &pPhysics, real t, Geom::t_index btype, bool fixUL=false, int geomMode=0, int linMode=0)
Generate the ghost (boundary) state for a boundary face.
TU source(const TU &UMeanXy, const TDiffU &DiffUxy, const Geom::tPoint &pPhy, TJacobianU &jacobian, index iCell, index ig, int Mode)
Compute the source term at a cell quadrature point.
void fluxFace(const TU_Batch &ULxy, const TU_Batch &URxy, const TU &ULMeanXy, const TU &URMeanXy, const TDiffU_Batch &DiffUxy, const TDiffU_Batch &DiffUxyPrim, const TVec_Batch &unitNorm, const TVec_Batch &vg, const TVec &unitNormC, const TVec &vgC, TU_Batch &FLfix, TU_Batch &FRfix, TU_Batch &finc, TReal_Batch &lam0V, TReal_Batch &lam123V, TReal_Batch &lam4V, Geom::t_index btype, typename Gas::RiemannSolverType rsType, index iFace, bool ignoreVis)
Compute the numerical flux at a face (batched over quadrature points).
Registry that maps named cell-scalar output fields to getter lambdas.
std::map< std::string, tCellScalarFGet > tMap
Name-to-getter mapping type.
RiemannSolverType
Selects the approximate Riemann solver and its entropy-fix variant.
void IdealGasThermal(real E, real rho, real vSqr, real gamma, real &p, real &asqr, real &H)
Thin wrapper delegating to IdealGas::IdealGasThermal.
void IdealGasThermalConservative2Primitive(const TCons &U, TPrim &prim, real gamma)
Converts conservative variables to primitive variables for an ideal gas.
@ RANS_KOSST
Menter k-omega SST two-equation model.
@ RANS_RKE
Realizable k-epsilon two-equation model.
@ RANS_KOWilcox
Wilcox k-omega two-equation model.
@ NS_2EQ_3D
NS + 2-equation RANS, 3D geometry (7 vars).
@ NS_SA
NS + Spalart-Allmaras, 2D geometry (6 vars).
@ NS_2EQ
NS + 2-equation RANS, 2D geometry (7 vars).
@ BCWallIsothermal
Isothermal wall; requires wall temperature in the BC value vector.
@ BCWall
No-slip viscous wall boundary.
@ BCWallInvis
Inviscid slip wall boundary.
@ BCSpecial
Test-case-specific boundary (Riemann, DMR, isentropic vortex, RT).
@ BCOut
Supersonic outflow (extrapolation) boundary.
@ BCUnknown
Uninitialized / invalid sentinel.
@ BCInPsTs
Subsonic inflow with prescribed total pressure and temperature.
@ BCSym
Symmetry plane boundary.
@ BCFar
Far-field (characteristic-based) boundary.
@ BCOutP
Back-pressure (subsonic) outflow boundary.
@ BCIn
Supersonic inflow (fully prescribed state) boundary.
DNDS_DEVICE_CALLABLE constexpr t_real ParamSpaceVol(ParamSpace ps)
auto GetQuadPatches(Quadrature &q)
DNDS_DEVICE_CALLABLE bool FaceIDIsInternal(t_index id)
tGPoint RotateAxis(const tPoint &axis)
Eigen::Matrix< real, 3, Eigen::Dynamic > tSmallCoords
tGPoint CrossVecToMat(const tPoint &axn)
real EigenLeastSquareInverse(const Eigen::MatrixXd &A, Eigen::MatrixXd &AI, real svdTol)
Moore-Penrose pseudoinverse via SVD, dropping singular values below svdTol (relative to the largest)....
MPI_int Allreduce(const void *sendbuf, void *recvbuf, MPI_int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
Wrapper over MPI_Allreduce.
MPI_int Barrier(MPI_Comm comm)
Wrapper over MPI_Barrier.
void AllreduceOneIndex(index &v, MPI_Op op, const MPIInfo &mpi)
Single-scalar Allreduce helper for indices (in-place, count = 1).
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
void MPISerialDo(const MPIInfo &mpi, F f)
Execute f on each rank serially, in rank order.
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
DNDS_CONSTANT const real pi
π in double precision (matches DNDS_E_PI macro).
constexpr real sign(real a)
Signum function: +1, 0, or -1.
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).
std::string to_string(const Eigen::DenseBase< dir > &v, int precision=5, bool scientific=false)
Render an Eigen::DenseBase to a string via operator<<.
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).
References to arrays needed by the output data picker.
ArrayDOFV< 1 > & alphaPP
PP RHS limiter alpha.
ArrayRECV< nVarsFixed > & uRec
Reconstruction coefficients.
ArrayDOFV< 1 > & betaPP
PP reconstruction limiter beta.
ArrayDOFV< nVarsFixed > & u
Cell-centered conservative DOFs.
Eigen::Matrix wrapper that hides begin/end from fmt.
Eigen::Matrix< real, 5, 1 > v
Eigen::Vector3d vg(0, 0, 0)
Eigen::Vector3d n(1.0, 0.0, 0.0)