DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
VariationalReconstruction.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <unordered_map>
4#include <set>
5#include <utility>
6
7#include "VRDefines.hpp"
8#include "VRSettings.hpp"
10#include "Geom/DiffTensors.hpp"
11#include "FiniteVolume.hpp"
12
13namespace DNDS::CFV
14{
15 /**
16 * @brief Accumulates the weighted diff-order tensor inner product into Conj
17 * across all polynomial orders present in the given diff vectors.
18 *
19 * Replaces the 4 copies of the switch(cnDiffs) fallthrough pattern
20 * in FFaceFunctional. Iterates over all (i,j) pairs and accumulates
21 * NormSymDiffOrderTensorV contributions for each polynomial order.
22 *
23 * @tparam dim Spatial dimension (2 or 3)
24 * @tparam powV Combinatorial power (1 unless USE_ECCENTRIC_COMB_POW_2)
25 * @param DiffI Diff base values for left side (cnDiffs x nColsI)
26 * @param DiffJ Diff base values for right side (cnDiffs x nColsJ)
27 * @param Conj Output conjugation matrix (nColsI x nColsJ), accumulated into
28 * @param wgd Squared face weight vector (one entry per order)
29 * @param cnDiffs Number of diff rows (= total NDOF for the max order present)
30 * @param faceL Length scale; pass 0 for anisotropic path (all faceLPow = 1)
31 */
32 template <int dim, int powV = 1, class TDiffI, class TDiffJ>
34 const Eigen::MatrixBase<TDiffI> &DiffI,
35 const Eigen::MatrixBase<TDiffJ> &DiffJ,
36 MatrixXR &Conj,
37 const Eigen::Vector<real, Eigen::Dynamic> &wgd,
38 int cnDiffs,
39 real faceL)
40 {
41 using namespace Geom::Base;
42
43 // Each order's start index and count are compile-time constants,
44 // so segment<N>() produces fixed-size Eigen expressions (no dynamic alloc).
45 auto accumOrder = [&](auto order_tag, auto start_tag, auto count_tag, int wIdx)
46 {
47 constexpr int order = decltype(order_tag)::value;
48 constexpr int start = decltype(start_tag)::value;
49 constexpr int count = decltype(count_tag)::value;
50 // faceL^(order*2) via integer multiplication; faceL==0 means anisotropic (scale=1)
51 real faceLPow;
52 if constexpr (order == 0)
53 faceLPow = 1.0;
54 else if constexpr (order == 1)
55 faceLPow = faceL * faceL;
56 else if constexpr (order == 2)
57 {
58 real fL2 = faceL * faceL;
59 faceLPow = fL2 * fL2;
60 }
61 else // order == 3
62 {
63 real fL2 = faceL * faceL;
64 faceLPow = fL2 * fL2 * fL2;
65 }
66 real scale = wgd(wIdx) * (faceL == 0 ? 1.0 : faceLPow);
67 for (int i = 0; i < DiffI.cols(); i++)
68 for (int j = 0; j < DiffJ.cols(); j++)
69 Conj(i, j) += NormSymDiffOrderTensorV<dim, order, powV>(
70 DiffI.col(i).template segment<count>(start),
71 DiffJ.col(j).template segment<count>(start)) *
72 scale;
73 };
74
75 if constexpr (dim == 2)
76 {
77 // dim=2 NDOF per order: 1, 2, 3, 4 cumulative: 1, 3, 6, 10
78 DNDS_assert(cnDiffs == 10 || cnDiffs == 6 || cnDiffs == 3 || cnDiffs == 1);
79 if (cnDiffs >= 10) accumOrder(std::integral_constant<int, 3>{}, std::integral_constant<int, 6>{}, std::integral_constant<int, 4>{}, 3);
80 if (cnDiffs >= 6) accumOrder(std::integral_constant<int, 2>{}, std::integral_constant<int, 3>{}, std::integral_constant<int, 3>{}, 2);
81 if (cnDiffs >= 3) accumOrder(std::integral_constant<int, 1>{}, std::integral_constant<int, 1>{}, std::integral_constant<int, 2>{}, 1);
82 accumOrder(std::integral_constant<int, 0>{}, std::integral_constant<int, 0>{}, std::integral_constant<int, 1>{}, 0);
83 }
84 else
85 {
86 // dim=3 NDOF per order: 1, 3, 6, 10 cumulative: 1, 4, 10, 20
87 DNDS_assert(cnDiffs == 20 || cnDiffs == 10 || cnDiffs == 4 || cnDiffs == 1);
88 if (cnDiffs >= 20) accumOrder(std::integral_constant<int, 3>{}, std::integral_constant<int, 10>{}, std::integral_constant<int, 10>{}, 3);
89 if (cnDiffs >= 10) accumOrder(std::integral_constant<int, 2>{}, std::integral_constant<int, 4>{}, std::integral_constant<int, 6>{}, 2);
90 if (cnDiffs >= 4) accumOrder(std::integral_constant<int, 1>{}, std::integral_constant<int, 1>{}, std::integral_constant<int, 3>{}, 1);
91 accumOrder(std::integral_constant<int, 0>{}, std::integral_constant<int, 0>{}, std::integral_constant<int, 1>{}, 0);
92 }
93 }
94
95 /**
96 * @brief
97 * The VR class that provides any information needed in high-order CFV
98 *
99 * @details
100 * VR holds a primitive mesh and any needed derived information about geometry and
101 * general reconstruction coefficients
102 *
103 * The (differentiable) input of VR is merely: geometry (mesh),
104 * and the weight inputs if using distributed weight;
105 * output are all values derived using construct* method
106 *
107 */
108 template <int dim = 2>
110 {
111 public:
112 int getDim() const { return dim; }
114
115 private:
116 VRSettings settings = VRSettings{dim};
117
118 public:
120 {
121 return settings;
122 }
123
125 {
126 settings = s;
127 // Slice the FiniteVolumeSettings base portion into the base class copy.
128 // FiniteVolume methods read maxOrder, intOrder, ignoreMeshGeometryDeficiency,
129 // and nIterCellSmoothScale from its own `settings` member. This keeps
130 // them in sync. All VR-specific fields remain only in `this->settings`.
131 t_base::settings = settings;
132 }
133
134 /// @brief Backward-compatible overload accepting JSON (used by Python bindings).
136 {
138 s.ParseFromJson(j);
140 }
141
142 public:
143 using TFTrans = std::function<void(Eigen::Ref<MatrixXR>, Geom::t_index)>;
144
145 private:
146 /**
147 * @brief Holds the base function moments, face weights, diff-base caches,
148 * and boundary VR point caches produced by ConstructBaseAndWeight().
149 *
150 * These members are built once and then read by FDiffBaseValue(),
151 * GetIntPointDiffBaseValue(), FFaceFunctional(), and indirectly by
152 * reconstruction and limiter methods.
153 */
154 struct VRBaseWeight
155 {
156 t3VecPair faceAlignedScales; /// @brief face-aligned length scales
157 t3MatPair faceMajorCoordScale; /// @brief face major coordinate transform
158 tVVecPair cellBaseMoment; /// @brief cell base function moments
159 tVVecPair faceWeight; /// @brief face quadrature weights
160 tMatsPair cellDiffBaseCache; /// @brief cached diff-base values at cell quad points
161 tMatsPair faceDiffBaseCache; /// @brief cached diff-base values at face quad points
162 tVMatPair cellDiffBaseCacheCent; /// @brief cached diff-base values at cell centroids
163 tVMatPair faceDiffBaseCacheCent; /// @brief cached diff-base values at face centroids
164
172 std::unordered_map<index, std::vector<BndVRPointCache>> bndVRCaches; /// @brief boundary face VR caches
173 };
174
175 VRBaseWeight baseWeight_;
176 using BndVRPointCache = typename VRBaseWeight::BndVRPointCache;
177
178 /**
179 * @brief Holds the reconstruction coefficient matrices produced by ConstructRecCoeff().
180 *
181 * Grouping these members clarifies the data-ownership boundary: VRBaseWeight
182 * members (above) are built by ConstructBaseAndWeight(), while these
183 * coefficient members are built by ConstructRecCoeff() from the base/weight data.
184 */
185 struct VRCoefficients
186 {
187 tMatsPair matrixAB; /// @brief A and B blocks per face, used during ConstructRecCoeff
188 tVecsPair vectorB; /// @brief B vector per cell
189 bool needOriginalMatrix = false;
190 tMatsPair matrixAAInvB; /// @brief A^{-1}B blocks per cell (main reconstruction matrix)
191 tMatsPair vectorAInvB; /// @brief A^{-1}b vectors per cell
192 tVMatPair matrixSecondary; /// @brief secondary-rec matrices on each face
193 tVMatPair matrixAHalf_GG; /// @brief Green-Gauss half matrices
194
195 tVMatPair matrixA; /// @brief full A matrix per cell (when needOriginalMatrix)
196
197 std::vector<Eigen::MatrixXd> volIntCholeskyL;
198 bool needVolIntCholeskyL = false;
199 std::vector<Eigen::MatrixXd> matrixACholeskyL;
200 bool needMatrixACholeskyL = false;
201
202 auto GetCellRecMatAInv(index iCell)
203 {
204 return matrixAAInvB(iCell, 0);
205 }
206
207 auto GetCellRecMatAInvB(index iCell, int ic2f)
208 {
209 return matrixAAInvB(iCell, 1 + ic2f);
210 }
211
212 auto &get_matrixAAInvB() { return matrixAAInvB; }
213 auto &get_vectorAInvB() { return vectorAInvB; }
214 };
215
216 VRCoefficients coefficients_;
217
218 // for periodic transformation inside scalars, eg. velocity components
219 TFTrans FTransPeriodic, FTransPeriodicBack;
220
221 public:
227
229 {
230 FTransPeriodic = nFTransPeriodic;
231 FTransPeriodicBack = nFTransPeriodicBack;
232 }
233
234 // directly SetPeriodicTransformations with mesh knowing that there is only
235 // a 2D/3D vector in it
236 template <size_t pDim>
237 void SetPeriodicTransformations(std::array<int, pDim> Seq123)
238 {
240 [mesh = mesh, Seq123](auto u, Geom::t_index id)
241 {
242 u(EigenAll, Seq123) = mesh->periodicInfo.TransVector<pDim, Eigen::Dynamic>(u(EigenAll, Seq123).transpose(), id).transpose();
243 },
244 [mesh = mesh, Seq123](auto u, Geom::t_index id)
245 {
246 u(EigenAll, Seq123) = mesh->periodicInfo.TransVectorBack<pDim, Eigen::Dynamic>(u(EigenAll, Seq123).transpose(), id).transpose();
247 });
248 }
249
251 {
253 [](auto u, Geom::t_index id) {},
254 [](auto u, Geom::t_index id) {});
255 }
256
257 /**
258 * @brief Applies the appropriate periodic transformation to one or more data matrices.
259 *
260 * Determines from `if2c` and `faceID` whether the current cell is the donor
261 * or main side of the periodic pair, and calls FTransPeriodic or
262 * FTransPeriodicBack accordingly. No-op when the mesh is not periodic.
263 *
264 * @param if2c Face-to-cell local index (0 = back, 1 = front)
265 * @param faceID Boundary zone ID of the face
266 * @param data One or more Eigen matrix references to transform
267 */
268 template <typename... Ts>
270 {
271 if (!mesh->isPeriodic)
272 return;
273 DNDS_assert(FTransPeriodic && FTransPeriodicBack);
274 if ((if2c == 1 && Geom::FaceIDIsPeriodicMain(faceID)) ||
275 (if2c == 0 && Geom::FaceIDIsPeriodicDonor(faceID))) // I am donor
276 (FTransPeriodic(data, faceID), ...);
277 if ((if2c == 1 && Geom::FaceIDIsPeriodicDonor(faceID)) ||
278 (if2c == 0 && Geom::FaceIDIsPeriodicMain(faceID))) // I am main
279 (FTransPeriodicBack(data, faceID), ...);
280 }
281
282 void ConstructMetrics();
283
284 using tFGetBoundaryWeight = std::function<real(Geom::t_index, int)>;
285
287 { return 1.0; });
288
289 void ConstructRecCoeff();
290
292 {
293 return coefficients_.GetCellRecMatAInv(iCell);
294 }
295
297 {
298 return coefficients_.GetCellRecMatAInvB(iCell, ic2f);
299 }
300
302 {
303 return coefficients_.get_matrixAAInvB();
304 }
305
307 {
308 return coefficients_.get_vectorAInvB();
309 }
310
311 /**
312 * @brief flag = 0 means use moment data, or else use no moment (as 0)
313 * pPhy must be relative to cell
314 * if iFace < 0, means anywhere
315 * if iFace > 0, iG == -1, means center; iG < -1, then anywhere
316 */
317 template <class TOut>
319 const Geom::tPoint &pPhy, // conventional input above
320 index iCell, index iFace, int iG, int flag = 0)
321 {
322 using namespace Geom;
323 using namespace Geom::Base;
324
325 auto pCen = cellCent[iCell];
326 tPoint pPhysicsC = pPhy - pCen;
327
328 if (!settings.baseSettings.localOrientation)
329 {
331 if (!settings.baseSettings.anisotropicLengths)
332 {
333 if constexpr (dim == 2)
334 simpleScale({0, 1}).setConstant(simpleScale({0, 1}).array().maxCoeff());
335 else
336 simpleScale.setConstant(simpleScale.array().maxCoeff());
337 }
338 tPoint pPhysicsCScaled = pPhysicsC.array() / simpleScale.array();
339 if constexpr (dim == 2)
340 FPolynomialFill2D(DiBj, pPhysicsCScaled(0), pPhysicsCScaled(1), pPhysicsCScaled(2), simpleScale(0), simpleScale(1), simpleScale(2), (int)DiBj.rows(), (int)DiBj.cols());
341 else
342 FPolynomialFill3D(DiBj, pPhysicsCScaled(0), pPhysicsCScaled(1), pPhysicsCScaled(2), simpleScale(0), simpleScale(1), simpleScale(2), (int)DiBj.rows(), (int)DiBj.cols());
343 }
344 else
345 {
347 if (!settings.baseSettings.anisotropicLengths)
348 {
349 if constexpr (dim == 2)
350 simpleScale({0, 1}).setConstant(simpleScale({0, 1}).array().maxCoeff());
351 else
352 simpleScale.setConstant(simpleScale.array().maxCoeff());
353 }
354 tPoint pPhysicsCMajor = cellMajorCoord[iCell].transpose() * pPhysicsC;
355 tPoint pPhysicsCScaled = pPhysicsCMajor.array() / simpleScale.array();
356 if constexpr (dim == 2)
357 FPolynomialFill2D(DiBj, pPhysicsCScaled(0), pPhysicsCScaled(1), pPhysicsCScaled(2), simpleScale(0), simpleScale(1), simpleScale(2), DiBj.rows(), DiBj.cols());
358 else
359 FPolynomialFill3D(DiBj, pPhysicsCScaled(0), pPhysicsCScaled(1), pPhysicsCScaled(2), simpleScale(0), simpleScale(1), simpleScale(2), DiBj.rows(), DiBj.cols());
360 tGPoint dXijdxi = cellMajorCoord[iCell];
362 }
363
364 if (flag == 0)
365 {
366 auto baseMoment = baseWeight_.cellBaseMoment[iCell];
367 DiBj(0, EigenAll) -= baseMoment.transpose();
368 }
369 }
370
371 /**
372 * @brief if if2c < 0, then calculated, if maxDiff == 255, then seen as all diffs
373 * if iFace < 0, then seen as cell int points; if iG < 1, then seen as center
374 * @todo : divide GetIntPointDiffBaseValue into different calls
375 * @warning maxDiff is max(diffList) + 1 not len(difflist)
376 * @todo: //TODO add support for rotational periodic boundary!
377 */
378 template <class TList>
382 TList &&diffList = EigenAll,
384 {
385 if (iFace >= 0)
386 {
387 maxDiff = std::min(maxDiff, GetFaceAtr(iFace).NDIFF);
388 if (if2c < 0)
389 if2c = CellIsFaceBack(iCell, iFace) ? 0 : 1;
390 if (settings.cacheDiffBase && maxDiff <= settings.cacheDiffBaseSize)
391 {
392 // auto gFace = this->GetFaceQuad(iFace);
393
394 if (iG >= 0)
395 {
396 return baseWeight_.faceDiffBaseCache(iFace, iG + (baseWeight_.faceDiffBaseCache.RowSize(iFace) / 2) * if2c)(
397 std::forward<TList>(diffList), Eigen::seq(Eigen::fix<1>, EigenLast));
398 }
399 else
400 {
401 int maxNDOF = int(baseWeight_.faceDiffBaseCacheCent[iFace].cols()) / 2;
402 return baseWeight_.faceDiffBaseCacheCent[iFace](
403 std::forward<TList>(diffList),
404 Eigen::seq(if2c * maxNDOF + 1,
405 if2c * maxNDOF + maxNDOF - 1));
406 }
407 }
408 else
409 {
410 // Actual computing:
411 ///@todo //!!!!TODO: take care of periodic case
413 dbv.resize(maxDiff, GetCellAtr(iCell).NDOF);
415 return dbv(std::forward<TList>(diffList), Eigen::seq(Eigen::fix<1>, EigenLast));
416 }
417 }
418 else
419 {
420 maxDiff = std::min(maxDiff, GetCellAtr(iCell).NDIFF);
421 if (settings.cacheDiffBase && maxDiff <= settings.cacheDiffBaseSize)
422 {
423 if (iG >= 0)
424 {
425 return baseWeight_.cellDiffBaseCache(iCell, iG)(
426 std::forward<TList>(diffList), Eigen::seq(Eigen::fix<1>, EigenLast));
427 }
428 else
429 {
430 return baseWeight_.cellDiffBaseCacheCent[iCell](
431 std::forward<TList>(diffList), Eigen::seq(Eigen::fix<1>, EigenLast));
432 }
433 }
434 else
435 {
437 dbv.resize(maxDiff, GetCellAtr(iCell).NDOF);
439 return dbv(std::forward<TList>(diffList), Eigen::seq(Eigen::fix<1>, EigenLast));
440 }
441 }
442 }
443
444 /**
445 * @brief if if2c < 0, then calculated with iCell hen seen as all diffs
446 */
447 auto
449 {
450 if (if2c < 0)
451 if2c = CellIsFaceBack(iCell, iFace) ? 0 : 1;
452 int maxNDOFM1 = coefficients_.matrixSecondary[iFace].cols() / 2;
453 return coefficients_.matrixSecondary[iFace](
454 EigenAll, Eigen::seq(
455 if2c * maxNDOFM1 + 0,
456 if2c * maxNDOFM1 + maxNDOFM1 - 1));
457 }
458
459 template <class TDiffIDerived, class TDiffJDerived>
461 const Eigen::MatrixBase<TDiffIDerived> &DiffI, const Eigen::MatrixBase<TDiffJDerived> &DiffJ,
463 {
464 using namespace Geom;
465 using namespace Geom::Base;
466 Eigen::Vector<real, Eigen::Dynamic> wgd = baseWeight_.faceWeight[iFace].array().square();
467 DNDS_assert(DiffI.rows() == DiffJ.rows());
468 int cnDiffs = DiffI.rows();
469
471 Conj.resize(DiffI.cols(), DiffJ.cols());
472 Conj.setZero();
473
474 //* PJH - rotation invariant scheme
475 tPoint faceLV;
476 switch (settings.functionalSettings.scaleType)
477 {
479 faceLV = baseWeight_.faceAlignedScales[iFace];
480 break;
483 faceLV = baseWeight_.faceAlignedScales[iFace];
484 break;
485 default:
486 DNDS_assert(false);
487 }
488
489 // real faceL = (faceLV.array().maxCoeff());
490 // * warning component_3 of the scale vector in 2D is forced to 1! not 0!
491 real faceL = 0;
493 faceL = std::sqrt(faceLV(Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>)).array().square().mean());
496 faceL = faceLV(Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>)).norm();
499 {
500 faceL = this->GetCellMaxLenScale(mesh->face2cell(iFace, 0)) * 0.5;
501 if (mesh->face2cell(iFace, 1) != UnInitIndex)
502 faceL = std::max(faceL, this->GetCellMaxLenScale(mesh->face2cell(iFace, 1)));
503 }
504 // CellMax option is the same as BaryDiff in terms of faceLOrig (being the Bary Dist)
505 // CellMax only uses another faceL
506
507 faceL *= settings.functionalSettings.scaleMultiplier;
508
509#ifdef USE_ECCENTRIC_COMB_POW_2
510 static constexpr int powV = 2;
511#else
512 static constexpr int powV = 1;
513#endif
514
515 if (!settings.functionalSettings.useAnisotropicFunctional)
516 {
518 }
519 else
520 {
521 using TMatCopy = Eigen::Matrix<
522 real,
523 Eigen::MatrixBase<TDiffIDerived>::RowsAtCompileTime,
524 Eigen::MatrixBase<TDiffIDerived>::ColsAtCompileTime>;
527 tGPoint coordTrans = baseWeight_.faceMajorCoordScale[iFace].transpose() *
528 settings.functionalSettings.scaleMultiplier;
529 if constexpr (dim == 2)
530 coordTrans(2, 2) = 1;
531 {
532 // tPoint norm = this->GetFaceNorm(iFace, -1);
533 // real normScale = (coordTrans * norm).norm();
534 // coordTrans(0, EigenAll) = norm.transpose() * faceL;
535 // coordTrans({1, 2}, EigenAll).setZero();
536 }
537 {
538 // coordTrans = Geom::NormBuildLocalBaseV<3>(norm).transpose() * faceL;
539 }
540 {
541 // coordTrans *= (2 * std::sqrt(3));
542 // tPoint lengths = coordTrans.rowwise().norm();
543 // // tPoint lengthsNew = lengths.array() * faceL / (faceL + lengths.array());
544 // tPoint lengthsNew = lengths.array().min(faceL);
545 // coordTrans.array().colwise() *= lengthsNew.array() / (lengths.array() + verySmallReal);
546
547 // // if (lengths(0) > 1e2 * lengths(1) || lengths(1) > 1e2 * lengths(0))
548 // // {
549 // // std::cout << "FACE " << iFace << std::endl;
550 // // std::cout << lengths << std::endl;
551 // // std::cout << faceL << std::endl;
552 // // }
553 }
554 {
555 // tPoint norm = this->GetFaceNorm(iFace, -1);
556 // auto getCellFaceMajorPNorm = [&](index iCell) -> tPoint
557 // {
558 // tGPoint cellMajorCoordTrans = this->cellMajorCoord[iCell].transpose().rowwise().normalized();
559 // tPoint normCos = (cellMajorCoordTrans * norm).array().abs();
560 // tPoint pNorm;
561 // if (normCos(0) < normCos(1))
562 // pNorm = cellMajorCoordTrans(1, EigenAll).transpose();
563 // else
564 // pNorm = cellMajorCoordTrans(0, EigenAll).transpose();
565 // return pNorm;
566 // };
567 // tPoint pNormL = getCellFaceMajorPNorm(iCellL);
568 // tPoint pNormR = getCellFaceMajorPNorm(iCellR);
569 // auto getProjection = [](tPoint n) -> tGPoint
570 // {
571 // tGPoint U = Geom::NormBuildLocalBaseV<3>(n).transpose();
572 // return U.transpose() * Eigen::Vector3d{1, 0, 0}.asDiagonal() * U;
573 // };
574 // ConvertDiffsLinMap<dim>(DiffI_Norm, getProjection(pNormL));
575 // ConvertDiffsLinMap<dim>(DiffJ_Norm, getProjection(pNormR));
576
577 // coordTrans(0, EigenAll) = norm.transpose() * faceL;
578 // coordTrans({1, 2}, EigenAll).setZero();
579 }
583 {
584 tPoint norm = this->GetFaceNorm(iFace, -1);
585 real areaL = this->GetFaceArea(iFace);
586 if constexpr (dim == 3)
587 areaL = std::sqrt(areaL);
588 real tw = 1. / std::min({1.0, faceLOrig / (areaL + 0.001 * faceLOrig)});
589 real nw = 1;
590 // real tw = 1. / std::max({1.0, areaL / (faceLOrig + 0.001 * areaL)});
591 // real tw = 1.0;
593 {
594 if (mesh->face2cell(iFace, 1) != UnInitIndex)
595 {
596 norm = this->GetOtherCellBaryFromCell(mesh->face2cell(iFace, 0),
597 mesh->face2cell(iFace, 1), iFace) -
598 this->GetCellBary(mesh->face2cell(iFace, 0));
599 norm.normalize();
600 }
601 }
602 else if (
604 {
605 DNDS_assert_info(mesh->nodeWallDist.father && mesh->nodeWallDist.father->Size() == mesh->NumNode(), "must build mesh's nodeWallDist before this");
606 real meanAR = GetCellAR(mesh->face2cell(iFace, 0));
607 real wd = 0.0;
609 if (mesh->face2cell(iFace, 1) != UnInitIndex)
610 {
611 h_min_LR = std::min(h_min_LR, GetCellNodeMinLenScale(mesh->face2cell(iFace, 1)));
612 meanAR = 0.5 * (meanAR + GetCellAR(mesh->face2cell(iFace, 1)));
613 norm.setZero();
614 real wdDiv = 0.0;
615 for (int if2n = 0; if2n < mesh->face2node[iFace].size(); if2n++)
616 {
617 auto d = mesh->GetCoordWallDistOnFace(iFace, 0);
618 norm += d;
619 wd += d.norm();
620 wdDiv += 1.0;
621 }
622 wd /= wdDiv;
623 norm.stableNormalize();
624 }
625 // else: norm stays face norm, wd is 0.0
626 // original WallDist ani
627 tw = 1.0;
628 nw = 1. / meanAR;
629 // WallDist V1:
630 auto f_dhInterp = [](real d)
631 {
632 real d0 = 1e-6;
633 real d1 = 1;
634 real h0 = 1e-6;
635 real h1 = 1;
636 real a = std::log(h1 / h0) / (d1 - d0);
637 d = std::max(d, d0);
638 real ret = h0 * std::exp(a * (d - d0));
639 // ret = std::min(ret, h1);
640 return ret;
641 };
643 h_reference = std::max(h_min_LR, h_reference);
644 // std::cout << wd << ", " << h_reference << std::endl;
645 tw = 1.0;
646 nw = std::min(1.0, h_reference / faceL);
647 }
648
649 coordTrans = Geom::NormBuildLocalBaseV<3>(norm).transpose() * faceL;
650 coordTrans(0, EigenAll) *= nw;
651 coordTrans({1, 2}, EigenAll) *= tw * settings.functionalSettings.tanWeightScale;
652 }
654 {
655 // same as norm but using InertiaCoordBB for tan
656 tPoint norm = this->GetFaceNorm(iFace, -1);
657 real areaL = this->GetFaceArea(iFace);
658 if constexpr (dim == 3)
659 areaL = std::sqrt(areaL);
660 // real tw = 1. / std::min({1.0, faceLOrig / (areaL + 0.001 * faceLOrig)});
661 real nw = 1;
662
663 tGPoint coordTransN = coordTrans.rowwise().normalized();
664 tPoint near_norm = (coordTransN * norm).array().abs();
665 int iMax = -1;
666 real maxCos = near_norm.maxCoeff(&iMax);
667 tGPoint coordTrans_new = coordTrans;
668
669 coordTrans_new(iMax, EigenAll) = norm.transpose() * (faceL * nw);
670 tGPoint coordTrans_newN = coordTrans_new.rowwise().normalized();
671
672 tPoint axis_ev = coordTrans_newN.eigenvalues().array().abs();
673 real axis_cond = axis_ev.maxCoeff() / axis_ev.minCoeff(); // valid for 2-d as 0,0,1 is also normalized
674 if (axis_cond < 10.0)
676 }
678 {
679 tGPoint coordTransN = coordTrans.rowwise().normalized(); // supposed to be a unitary matrix
680 coordTrans = coordTransN.transpose() * coordTrans;
681 }
684 {
685 }
686
689
691 }
692 return Conj;
693 }
694
696 {
697 if (settings.functionalSettings.greenGaussSpacial == 0)
698 {
700 real v = std::max(0.0, std::log(AR));
701 return settings.functionalSettings.greenGauss1Weight *
702 std::pow(std::tanh(v / 4), 3);
703 }
704 else
705 {
706 return settings.functionalSettings.greenGauss1Weight;
707 }
708 }
709
711 {
712 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
713 auto lens = this->cellMajorHBox[iCell](Seq012);
714 return (lens.maxCoeff() + verySmallReal) / (lens.minCoeff() + verySmallReal);
715 }
716
717 template <int nVarsFixed = 1>
719 {
720 DNDS_assert(coefficients_.matrixA.Size() == mesh->NumCellProc());
721 for (index iCell = 0; iCell < mesh->NumCellProc(); iCell++)
722 uRec1[iCell] = coefficients_.matrixA[iCell] * uRec[iCell];
723 }
724
725 template <int nVarsFixed = 1>
727 int curOrder,
728 index iCell,
729 tURec<nVarsFixed> &uRec,
730 int downCastMethod)
731 {
732 int degree2Start = dim == 3 ? 3 : 2;
733 int degree3Start = dim == 3 ? 9 : 5;
734
735 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> ret = uRec[iCell];
736 if (downCastMethod == 1)
737 DNDS_assert(coefficients_.volIntCholeskyL.size() == mesh->cell2node.father->Size());
738 if (downCastMethod == 2)
739 DNDS_assert(coefficients_.matrixACholeskyL.size() == mesh->cell2node.father->Size());
740
741 auto toOrtho = [&]()
742 {
743 switch (downCastMethod)
744 {
745 case 0:
746 break;
747 case 1:
748 coefficients_.volIntCholeskyL.at(iCell).template triangularView<Eigen::Lower>().applyThisOnTheLeft(ret);
749 break;
750 case 2:
751 coefficients_.matrixACholeskyL.at(iCell).template triangularView<Eigen::Lower>().applyThisOnTheLeft(ret);
752 break;
753 default:
754 DNDS_assert(false);
755 break;
756 }
757 };
758
759 auto toOrigin = [&]()
760 {
761 switch (downCastMethod)
762 {
763 case 0:
764 break;
765 case 1:
766 ret = coefficients_.volIntCholeskyL.at(iCell).template triangularView<Eigen::Lower>().solve(ret);
767 break;
768 case 2:
769 ret = coefficients_.matrixACholeskyL.at(iCell).template triangularView<Eigen::Lower>().solve(ret);
770 break;
771 default:
772 DNDS_assert(false);
773 break;
774 }
775 };
776
777 switch (curOrder)
778 {
779 case 0:
780 break;
781 case 1:
782 ret *= 0.0;
783 break;
784 case 2:
785 {
786 toOrtho();
787 ret(Eigen::seq(degree2Start, EigenLast), EigenAll) *= 0.0;
788 toOrigin();
789 }
790 break;
791 case 3:
792 {
793 toOrtho();
794 ret(Eigen::seq(degree3Start, EigenLast), EigenAll) *= 0.0;
795 toOrigin();
796 }
797 break;
798 default:
799 std::cout << "bad input order : " << curOrder << std::endl;
800 DNDS_assert(false);
801 break;
802 }
803
804 return ret;
805 }
806
807 template <int nVarsFixed>
808 void BuildURec(tURec<nVarsFixed> &u, int nVars, bool buildSon = true, bool buildTrans = true)
809 {
810 using namespace Geom::Base;
811 int maxNDOF = GetNDof<dim>(settings.maxOrder);
812 u.InitPair("VR::BuildURec::u", mpi);
813 u.father->Resize(mesh->NumCell(), maxNDOF - 1, nVars);
814 if (buildSon)
815 u.son->Resize(mesh->NumCellGhost(), maxNDOF - 1, nVars);
816 if (buildTrans)
817 {
819 u.TransAttach();
820 u.trans.BorrowGGIndexing(mesh->cell2node.trans);
821 u.trans.createMPITypes();
822 u.trans.initPersistentPull();
823 u.trans.initPersistentPush();
824 }
825
826 for (index iCell = 0; iCell < u.Size(); iCell++)
827 u[iCell].setZero();
828 }
829
830 template <int nVarsFixed>
831 void BuildUGrad(tUGrad<nVarsFixed, dim> &u, int nVars, bool buildSon = true, bool buildTrans = true)
832 {
833 using namespace Geom::Base;
834 u.InitPair("VR::BuildUGrad::u", mpi);
835 u.father->Resize(mesh->NumCell(), dim, nVars);
836 if (buildSon)
837 u.son->Resize(mesh->NumCellGhost(), dim, nVars);
838 if (buildTrans)
839 {
841 u.TransAttach();
842 u.trans.BorrowGGIndexing(mesh->cell2node.trans);
843 u.trans.createMPITypes();
844 u.trans.initPersistentPull();
845 u.trans.initPersistentPush();
846 }
847
848 for (index iCell = 0; iCell < u.Size(); iCell++)
849 u[iCell].setZero();
850 }
851
852 void BuildScalar(tScalarPair &u, bool buildSon = true, bool buildTrans = true)
853 {
854 u.InitPair("VR::BuildScalar::u", mpi);
855 u.father->Resize(mesh->NumCell());
856 if (buildSon)
857 u.son->Resize(mesh->NumCellGhost());
858 if (buildTrans)
859 {
861 u.TransAttach();
862 u.trans.BorrowGGIndexing(mesh->cell2node.trans);
863 u.trans.createMPITypes();
864 u.trans.initPersistentPull();
865 u.trans.initPersistentPush();
866 }
867
868 for (index iCell = 0; iCell < u.Size(); iCell++)
869 u(iCell, 0) = 0;
870 }
871
872 template <int nVarsFixed = 1>
873 void BuildUDofNode(tUDof<nVarsFixed> &u, int nVars, bool buildSon = true, bool buildTrans = true)
874 {
875 u.InitPair("VR::BuildUDofNode::u", mpi);
876 u.father->Resize(mesh->NumNode(), nVars, 1);
877 if (buildSon)
878 u.son->Resize(mesh->NumNodeGhost(), nVars, 1);
879 if (buildTrans)
880 {
882 u.TransAttach();
883 u.trans.BorrowGGIndexing(mesh->coords.trans);
884 u.trans.createMPITypes();
885 u.trans.initPersistentPull();
886 u.trans.initPersistentPush();
887 }
888
889 for (index iCell = 0; iCell < u.Size(); iCell++)
890 u[iCell].setZero();
891 }
892
893 template <int nVarsFixed = 5>
894 using TFBoundary = std::function<Eigen::Vector<real, nVarsFixed>(
895 const Eigen::Vector<real, nVarsFixed> &, // UBL
896 const Eigen::Vector<real, nVarsFixed> &, // UMEAN
897 index, index, int, // iCell, iFace, ig
898 const Geom::tPoint &, // Norm
899 const Geom::tPoint &, // pPhy
900 Geom::t_index fType // fCode
901 )>;
902
903 template <int nVarsFixed = 5>
904 using TFBoundaryDiff = std::function<Eigen::Vector<real, nVarsFixed>(
905 const Eigen::Vector<real, nVarsFixed> &, // UBL
906 const Eigen::Vector<real, nVarsFixed> &, // dUMEAN
907 const Eigen::Vector<real, nVarsFixed> &, // UMEAN
908 index, index, int, // iCell, iFace, ig
909 const Geom::tPoint &, // Norm
910 const Geom::tPoint &, // pPhy
911 Geom::t_index fType // fCode
912 )>;
913
914 private: // only used in reconstruction implementation hxx
915 template <int nVarsFixed = 5>
916 auto GetBoundaryRHS(tURec<nVarsFixed> &uRec,
920
921 private: // only used in reconstruction implementation hxx
922 template <int nVarsFixed = 5>
923 auto GetBoundaryRHSDiff(tURec<nVarsFixed> &uRec,
928
929 public:
930 /**
931 * \brief fallback reconstruction method,
932 * explicit 2nd order FV reconstruction
933 * \param uRec output, reconstructed gradients
934 * \param u input, mean values
935 * \param FBoundary see TFBoundary
936 * \param method currently 1==2nd-order-GaussGreen
937 */
938 template <int nVarsFixed = 5>
943 int method);
944
945 /**
946 * \brief fallback reconstruction method,
947 * explicit 2nd order FV reconstruction
948 * \param uRec output, reconstructed gradients
949 * \param u input, mean values
950 * \param FBoundary see TFBoundary
951 * \param method currently 1==2nd-order-GaussGreen
952 */
953 template <int nVarsFixed = 5>
955 tURec<nVarsFixed> &uRec,
958 int method,
959 const std::vector<int> &mask);
960
961 /**
962 * \brief iterative variational reconstruction method
963 * \details
964 * DoReconstructionIter updates uRec (could locate into uRecNew)
965 * $$
966 * ur_i = A_{i}^{-1}B_{ij}ur_j + A_{i}^{-1}b_{i}
967 * $$
968 * which is a fixed-point solver (using SOR/Jacobi sweeping)
969 *
970 * if recordInc, value in the output array is actually defined as :
971 * $$
972 * -(A_{i}^{-1}B_{ij}ur_j + A_{i}^{-1}b_{i}) + ur_i
973 * $$
974 * which is the RHS of Block-Jacobi preconditioned system
975 *
976 * \param uRec input/ouput, reconstructed coefficients, is output if putIntoNew==false, otherwise is used as medium value
977 * \param uRecNew input/ouput, reconstructed coefficients, is output if putIntoNew==true, otherwise is used as medium value
978 * \param u input, mean values
979 * \param FBoundary see TFBoundary
980 * \param putIntoNew put valid output into uRecNew or not
981 * \param recordInc if true, uRecNew holds the incremental value to this iteration
982 * @warning mind that uRec could be overwritten
983 */
984 template <int nVarsFixed = 5>
986 tURec<nVarsFixed> &uRec,
987 tURec<nVarsFixed> &uRecNew,
990 bool putIntoNew = false,
991 bool recordInc = false,
992 bool uRecIsZero = false);
993 /***********************************************************/
994
995 /**
996 * @brief puts into uRecNew with Mat * uRecDiff; uses the Block-jacobi preconditioned reconstruction system as Mat.
997 * \details
998 * the matrix operation can be viewed as
999 * $$
1000 * vr_i = ur_j - A_{i}^{-1}B_{ij}ur_j
1001 * $$
1002 * which is the Jacobian of the DoReconstructionIter's RHS output.
1003 * Note that we account for nonlinear effects from BC
1004 * \param uRec input, the base value
1005 * \param uRecDiff input, the diff value, $x$ in $y=Jx$, or the disturbance value
1006 * \param uRecNew output, the result, $y$, or the response value
1007 * \param u input, mean value
1008 * \param FBoundary Vec F(const Vec &uL, const Vec& dUL, const tPoint &unitNorm, const tPoint &p, t_index faceID),
1009 * with Vec == Eigen::Vector<real, nVarsFixed>
1010 * uRecDiff should be untouched
1011 */
1012 template <int nVarsFixed = 5>
1014 tURec<nVarsFixed> &uRec,
1016 tURec<nVarsFixed> &uRecNew,
1019 /***********************************************************/
1020
1021 /** //TODO
1022 * @brief do a SOR iteration from uRecNew, with uRecInc as the RHSterm of Block-Jacobi preconditioned system
1023 */
1024 template <int nVarsFixed = 5>
1026 tURec<nVarsFixed> &uRec,
1027 tURec<nVarsFixed> &uRecInc,
1028 tURec<nVarsFixed> &uRecNew,
1031 bool reverse = false);
1032
1033 /***********************************************************/
1034
1035 /***********************************************************/
1036
1037 template <int nVarsFixed, int nVarsSee = 2>
1040 const std::array<int, nVarsSee> &varsSee);
1041
1042 template <int nVarsFixed>
1043 using TFPost = std::function<void(Eigen::Matrix<real, 1, nVarsFixed> &)>; // post process reconstructed values (as row vector)
1044
1045 template <int nVarsFixed>
1048 const Eigen::Vector<real, nVarsFixed> &varsSee,
1049 const TFPost<nVarsFixed> &FPost);
1050
1051 static const int maxRecDOFBatch = dim == 2 ? 4 : 10;
1052 static const int maxRecDOF = dim == 2 ? 9 : 19;
1053 static const int maxNDiff = dim == 2 ? 10 : 20;
1054 static const int maxNeighbour = 7;
1055
1056 template <int nVarsFixed>
1058
1059 template <int nVarsFixed>
1060 using tFMEig = std::function<tLimitBatch<nVarsFixed>(
1061 const Eigen::Vector<real, nVarsFixed> &uL,
1062 const Eigen::Vector<real, nVarsFixed> &uR,
1063 const Geom::tPoint &uNorm,
1064 const Eigen::Ref<tLimitBatch<nVarsFixed>> &data)>;
1065
1066 /**
1067 * @brief FM(uLeft,uRight,norm) gives vsize * vsize mat of Left Eigen Vectors
1068 *
1069 */
1070 template <int nVarsFixed>
1071 void DoLimiterWBAP_C(
1073 tURec<nVarsFixed> &uRec,
1074 tURec<nVarsFixed> &uRecNew,
1076 tScalarPair &si,
1077 bool ifAll,
1079 bool putIntoNew = false);
1080
1081 /**
1082 * @brief FM(uLeft,uRight,norm) gives vsize * vsize mat of Left Eigen Vectors
1083 *
1084 */
1085 template <int nVarsFixed>
1086 void DoLimiterWBAP_3(
1088 tURec<nVarsFixed> &uRec,
1089 tURec<nVarsFixed> &uRecNew,
1091 tScalarPair &si,
1092 bool ifAll,
1094 bool putIntoNew = false);
1095
1097 {
1098 using namespace Geom;
1099 std::string name = "VR_Matrix";
1100 auto cwd = serializerP->GetCurrentPath();
1101 serializerP->CreatePath(name);
1102 serializerP->GoToPath(name);
1103
1104 mesh->BuildCell2CellFace();
1105 mesh->cell2cellFace.WriteSerialize(serializerP, "cell2cellFace", true);
1106 mesh->AdjGlobal2LocalC2CFace();
1107
1108 DNDS_assert(coefficients_.matrixAAInvB.father->Size() == mesh->NumCell());
1109 DNDS_assert(coefficients_.matrixAAInvB.son->Size() == mesh->NumCellGhost());
1110 coefficients_.matrixAAInvB.WriteSerialize(serializerP, "matrixAAInvB", false);
1111
1112 serializerP->GoToPath(cwd);
1113 }
1114 };
1115}
1116// NOLINTBEGIN(bugprone-macro-parentheses)
1117#define DNDS_VARIATIONALRECONSTRUCTION_RECONSTRUCTION_INS_EXTERN(dim, nVarsFixed, ext) \
1118 namespace DNDS::CFV \
1119 { \
1120 ext template void VariationalReconstruction<dim>::DoReconstruction2ndGrad<nVarsFixed>( \
1121 tUGrad<nVarsFixed, dim> & uRec, \
1122 tUDof<nVarsFixed> &u, \
1123 const TFBoundary<nVarsFixed> &FBoundary, \
1124 int method); \
1125 \
1126 ext template void VariationalReconstruction<dim>::DoReconstruction2nd<nVarsFixed>( \
1127 tURec<nVarsFixed> & uRec, \
1128 tUDof<nVarsFixed> &u, \
1129 const TFBoundary<nVarsFixed> &FBoundary, \
1130 int method, \
1131 const std::vector<int> &mask); \
1132 \
1133 ext template void VariationalReconstruction<dim>::DoReconstructionIter<nVarsFixed>( \
1134 tURec<nVarsFixed> & uRec, \
1135 tURec<nVarsFixed> &uRecNew, \
1136 tUDof<nVarsFixed> &u, \
1137 const TFBoundary<nVarsFixed> &FBoundary, \
1138 bool putIntoNew, \
1139 bool recordInc, \
1140 bool uRecIsZero); \
1141 \
1142 ext template void VariationalReconstruction<dim>::DoReconstructionIterDiff<nVarsFixed>( \
1143 tURec<nVarsFixed> & uRec, \
1144 tURec<nVarsFixed> &uRecDiff, \
1145 tURec<nVarsFixed> &uRecNew, \
1146 tUDof<nVarsFixed> &u, \
1147 const TFBoundaryDiff<nVarsFixed> &FBoundaryDiff); \
1148 \
1149 ext template void VariationalReconstruction<dim>::DoReconstructionIterSOR<nVarsFixed>( \
1150 tURec<nVarsFixed> & uRec, \
1151 tURec<nVarsFixed> &uRecInc, \
1152 tURec<nVarsFixed> &uRecNew, \
1153 tUDof<nVarsFixed> &u, \
1154 const TFBoundaryDiff<nVarsFixed> &FBoundaryDiff, \
1155 bool reverse); \
1156 }
1157
1167
1168#define DNDS_VARIATIONALRECONSTRUCTION_LIMITERPROCEDURE_INS_EXTERN(dim, nVarsFixed, ext) \
1169 namespace DNDS::CFV \
1170 { \
1171 ext template void VariationalReconstruction<dim>::DoCalculateSmoothIndicator<nVarsFixed, 2>( \
1172 tScalarPair & si, tURec<nVarsFixed> &uRec, tUDof<nVarsFixed> &u, \
1173 const std::array<int, 2> &varsSee); \
1174 \
1175 ext template void VariationalReconstruction<dim>::DoCalculateSmoothIndicatorV1<nVarsFixed>( \
1176 tScalarPair & si, tURec<nVarsFixed> &uRec, tUDof<nVarsFixed> &u, \
1177 const Eigen::Vector<real, nVarsFixed> &varsSee, \
1178 const TFPost<nVarsFixed> &FPost); \
1179 \
1180 ext template void VariationalReconstruction<dim>::DoLimiterWBAP_C( \
1181 tUDof<nVarsFixed> &u, \
1182 tURec<nVarsFixed> &uRec, \
1183 tURec<nVarsFixed> &uRecNew, \
1184 tURec<nVarsFixed> &uRecBuf, \
1185 tScalarPair &si, \
1186 bool ifAll, \
1187 const tFMEig<nVarsFixed> &FM, const tFMEig<nVarsFixed> &FMI, \
1188 bool putIntoNew); \
1189 \
1190 ext template void VariationalReconstruction<dim>::DoLimiterWBAP_3( \
1191 tUDof<nVarsFixed> &u, \
1192 tURec<nVarsFixed> &uRec, \
1193 tURec<nVarsFixed> &uRecNew, \
1194 tURec<nVarsFixed> &uRecBuf, \
1195 tScalarPair &si, \
1196 bool ifAll, \
1197 const tFMEig<nVarsFixed> &FM, const tFMEig<nVarsFixed> &FMI, \
1198 bool putIntoNew); \
1199 }
1200// NOLINTEND(bugprone-macro-parentheses)
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
#define DNDS_VARIATIONALRECONSTRUCTION_RECONSTRUCTION_INS_EXTERN(dim, nVarsFixed, ext)
#define DNDS_VARIATIONALRECONSTRUCTION_LIMITERPROCEDURE_INS_EXTERN(dim, nVarsFixed, ext)
t3MatPair cellMajorCoord
constructed using ConstructMetrics()
real GetCellMaxLenScale(index iCell)
Geom::tPoint GetCellBary(index iCell)
t3VecPair cellCent
constructed using ConstructMetrics()
Geom::tPoint GetCellQuadraturePPhys(index iCell, int iG)
Geom::tPoint GetOtherCellBaryFromCell(index iCell, index iCellOther, index iFace)
real GetCellNodeMinLenScale(index iCell)
ssp< Geom::UnstructuredMesh > mesh
Geom::tPoint GetFaceNorm(index iFace, int iG) const
bool CellIsFaceBack(index iCell, index iFace) const
Geom::tPoint GetFaceQuadraturePPhysFromCell(index iFace, index iCell, rowsize if2c, int iG)
FiniteVolumeSettings settings
FiniteVolumeDeviceView< B > t_deviceView
real GetFaceArea(index iFace) const
t3VecPair cellMajorHBox
constructed using ConstructMetrics()
t3VecPair cellAlignedHBox
constructed using ConstructMetrics()
RecAtr & GetFaceAtr(index iFace)
RecAtr & GetCellAtr(index iCell)
The VR class that provides any information needed in high-order CFV.
void FDiffBaseValue(TOut &DiBj, const Geom::tPoint &pPhy, index iCell, index iFace, int iG, int flag=0)
flag = 0 means use moment data, or else use no moment (as 0) pPhy must be relative to cell if iFace <...
void BuildScalar(tScalarPair &u, bool buildSon=true, bool buildTrans=true)
void WriteSerializeRecMatrix(const Serializer::SerializerBaseSSP &serializerP)
void SetPeriodicTransformations(const TFTrans &nFTransPeriodic, const TFTrans &nFTransPeriodicBack)
auto DownCastURecOrder(int curOrder, index iCell, tURec< nVarsFixed > &uRec, int downCastMethod)
void parseSettings(VRSettings::json &j)
Backward-compatible overload accepting JSON (used by Python bindings).
void DoLimiterWBAP_3(tUDof< nVarsFixed > &u, tURec< nVarsFixed > &uRec, tURec< nVarsFixed > &uRecNew, tURec< nVarsFixed > &uRecBuf, tScalarPair &si, bool ifAll, const tFMEig< nVarsFixed > &FM, const tFMEig< nVarsFixed > &FMI, bool putIntoNew=false)
FM(uLeft,uRight,norm) gives vsize * vsize mat of Left Eigen Vectors.
std::function< Eigen::Vector< real, nVarsFixed >(const Eigen::Vector< real, nVarsFixed > &, const Eigen::Vector< real, nVarsFixed > &, const Eigen::Vector< real, nVarsFixed > &, index, index, int, const Geom::tPoint &, const Geom::tPoint &, Geom::t_index fType)> TFBoundaryDiff
void ApplyPeriodicTransform(int if2c, Geom::t_index faceID, Ts &...data) const
Applies the appropriate periodic transformation to one or more data matrices.
void ConstructBaseAndWeight(const tFGetBoundaryWeight &id2faceDircWeight=[](Geom::t_index id, int iOrder) { return 1.0;})
std::function< void(Eigen::Matrix< real, 1, nVarsFixed > &)> TFPost
void BuildUGrad(tUGrad< nVarsFixed, dim > &u, int nVars, bool buildSon=true, bool buildTrans=true)
void BuildURec(tURec< nVarsFixed > &u, int nVars, bool buildSon=true, bool buildTrans=true)
VariationalReconstruction(MPIInfo nMpi, ssp< Geom::UnstructuredMesh > nMesh)
auto GetMatrixSecondary(index iCell, index iFace, index if2c)
if if2c < 0, then calculated with iCell hen seen as all diffs
std::function< void(Eigen::Ref< MatrixXR >, Geom::t_index)> TFTrans
void DoReconstruction2ndGrad(tUGrad< nVarsFixed, dim > &uRec, tUDof< nVarsFixed > &u, const TFBoundary< nVarsFixed > &FBoundary, int method)
fallback reconstruction method, explicit 2nd order FV reconstruction
void DoLimiterWBAP_C(tUDof< nVarsFixed > &u, tURec< nVarsFixed > &uRec, tURec< nVarsFixed > &uRecNew, tURec< nVarsFixed > &uRecBuf, tScalarPair &si, bool ifAll, const tFMEig< nVarsFixed > &FM, const tFMEig< nVarsFixed > &FMI, bool putIntoNew=false)
FM(uLeft,uRight,norm) gives vsize * vsize mat of Left Eigen Vectors.
void DoCalculateSmoothIndicatorV1(tScalarPair &si, tURec< nVarsFixed > &uRec, tUDof< nVarsFixed > &u, const Eigen::Vector< real, nVarsFixed > &varsSee, const TFPost< nVarsFixed > &FPost)
void DoReconstructionIter(tURec< nVarsFixed > &uRec, tURec< nVarsFixed > &uRecNew, tUDof< nVarsFixed > &u, const TFBoundary< nVarsFixed > &FBoundary, bool putIntoNew=false, bool recordInc=false, bool uRecIsZero=false)
iterative variational reconstruction method
void SetPeriodicTransformations(std::array< int, pDim > Seq123)
void DoCalculateSmoothIndicator(tScalarPair &si, tURec< nVarsFixed > &uRec, tUDof< nVarsFixed > &u, const std::array< int, nVarsSee > &varsSee)
void MatrixAMult(tURec< nVarsFixed > &uRec, tURec< nVarsFixed > &uRec1)
Eigen::Matrix< real, -1, nVarsFixed, 0, CFV::VariationalReconstruction< dim >::maxRecDOFBatch > tLimitBatch
void DoReconstruction2nd(tURec< nVarsFixed > &uRec, tUDof< nVarsFixed > &u, const TFBoundary< nVarsFixed > &FBoundary, int method, const std::vector< int > &mask)
fallback reconstruction method, explicit 2nd order FV reconstruction
void DoReconstructionIterSOR(tURec< nVarsFixed > &uRec, tURec< nVarsFixed > &uRecInc, tURec< nVarsFixed > &uRecNew, tUDof< nVarsFixed > &u, const TFBoundaryDiff< nVarsFixed > &FBoundaryDiff, bool reverse=false)
do a SOR iteration from uRecNew, with uRecInc as the RHSterm of Block-Jacobi preconditioned system
std::function< Eigen::Vector< real, nVarsFixed >(const Eigen::Vector< real, nVarsFixed > &, const Eigen::Vector< real, nVarsFixed > &, index, index, int, const Geom::tPoint &, const Geom::tPoint &, Geom::t_index fType)> TFBoundary
void DoReconstructionIterDiff(tURec< nVarsFixed > &uRec, tURec< nVarsFixed > &uRecDiff, tURec< nVarsFixed > &uRecNew, tUDof< nVarsFixed > &u, const TFBoundaryDiff< nVarsFixed > &FBoundaryDiff)
puts into uRecNew with Mat * uRecDiff; uses the Block-jacobi preconditioned reconstruction system as ...
std::function< tLimitBatch< nVarsFixed >(const Eigen::Vector< real, nVarsFixed > &uL, const Eigen::Vector< real, nVarsFixed > &uR, const Geom::tPoint &uNorm, const Eigen::Ref< tLimitBatch< nVarsFixed > > &data)> tFMEig
MatrixXR GetIntPointDiffBaseValue(index iCell, index iFace, rowsize if2c, int iG, TList &&diffList=EigenAll, uint8_t maxDiff=UINT8_MAX)
if if2c < 0, then calculated, if maxDiff == 255, then seen as all diffs if iFace < 0,...
std::function< real(Geom::t_index, int)> tFGetBoundaryWeight
auto FFaceFunctional(const Eigen::MatrixBase< TDiffIDerived > &DiffI, const Eigen::MatrixBase< TDiffJDerived > &DiffJ, index iFace, index iCellL, index iCellR)
void BuildUDofNode(tUDof< nVarsFixed > &u, int nVars, bool buildSon=true, bool buildTrans=true)
void AccumulateDiffOrderContributions(const Eigen::MatrixBase< TDiffI > &DiffI, const Eigen::MatrixBase< TDiffJ > &DiffJ, MatrixXR &Conj, const Eigen::Vector< real, Eigen::Dynamic > &wgd, int cnDiffs, real faceL)
Accumulates the weighted diff-order tensor inner product into Conj across all polynomial orders prese...
int32_t t_index
Definition Geometric.hpp:6
Eigen::Vector3d tPoint
Definition Geometric.hpp:9
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodicDonor(t_index id)
DNDS_DEVICE_CALLABLE bool FaceIDIsPeriodicMain(t_index id)
ssp< SerializerBase > SerializerBaseSSP
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
Definition Defines.hpp:176
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
Definition Defines.hpp:194
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
Definition Defines.hpp:109
Eigen::Matrix< real, Eigen::Dynamic, Eigen::Dynamic > MatrixXR
Column-major dynamic Eigen matrix of reals (default layout).
Definition Defines.hpp:205
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
Eigen::RowVector< real, Eigen::Dynamic > RowVectorXR
Dynamic row-vector of reals.
Definition Defines.hpp:209
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:105
void TransAttach()
Bind the transformer to the current father / son pointers.
ssp< TArray > father
Owned-side array (must be resized before ghost setup).
index Size() const
Combined row count (father->Size() + son->Size()).
void InitPair(const std::string &name, Args &&...args)
Allocate both father and son arrays, forwarding all args to TArray constructor.
ssp< TArray > son
Ghost-side array (sized automatically by createMPITypes / BorrowAndPull).
TTrans trans
Ghost-communication engine bound to father and son.
A means to translate nlohmann json into c++ primitive data types and back; and stores then during com...
struct DNDS::CFV::VRSettings::BaseSettings baseSettings
struct DNDS::CFV::VRSettings::FunctionalSettings functionalSettings
nlohmann::ordered_json json
bool cacheDiffBase
integration degree for VR matrices on BC faces, -1 means using int Order, < -1 means using intOrderVR...
uint8_t cacheDiffBaseSize
if cache the base function values on each of the quadrature points
Lightweight bundle of an MPI communicator and the calling rank's coordinates.
Definition MPI.hpp:215
dof1 setConstant(0.0)
Eigen::Matrix< real, 5, 1 > v
double order
Definition test_ODE.cpp:257