10 static const int dim = 3;
11 static const int nVarsFixed = 6;
15 template <int nVarsFixed>
22 const TFBoundary<nVarsFixed> &FBoundary)
25 using namespace Geom::Elem;
26 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
28 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> BCC;
29 BCC.setZero(uRec[iCell].rows(), uRec[iCell].cols());
30 auto faceID = mesh->GetFaceZone(iFace);
33 auto qFace = this->GetFaceQuad(iFace);
34 if (settings.intOrderVRBCIsSame() || settings.functionalSettings.greenGauss1Weight != 0)
35 qFace.IntegrationSimple(
37 [&](
auto &vInc,
int iG)
40 this->GetIntPointDiffBaseValue(iCell, iFace, -1, iG, std::array<int, 1>{0}, 1);
41 Eigen::Vector<real, nVarsFixed> uBL =
46 Eigen::Vector<real, nVarsFixed> uBV =
49 u[iCell], iCell, iFace, iG,
50 this->GetFaceNorm(iFace, iG),
51 this->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, iG), faceID);
52 Eigen::RowVector<real, nVarsFixed> uIncBV = (uBV - u[iCell]).transpose();
53 if (settings.intOrderVRBCIsSame())
54 vInc = this->FFaceFunctional(dbv, uIncBV, iFace, iCell, iCell);
56 vInc.resizeLike(BCC), vInc.setZero();
58 if (settings.functionalSettings.greenGauss1Weight != 0)
61 vInc += (settings.functionalSettings.greenGauss1Bias * this->GetGreenGauss1WeightOnCell(iCell) *
62 this->coefficients_.matrixAHalf_GG[iCell].transpose() * this->GetFaceNorm(iFace, iG)(Seq012)) *
65 vInc *= this->GetFaceJacobiDet(iFace, iG);
68 if (!settings.intOrderVRBCIsSame())
70 auto qFace = Quadrature(mesh->GetFaceElement(iFace), settings.intOrderVRBCValue());
72 mesh->GetCoordsOnFace(iFace, coords);
75 [&](
auto &vInc,
int __xxx_iG,
const tPoint &pParam,
const Elem::tD01Nj &DiNj) {
76 BndVRPointCache &bndCacheEntry = baseWeight_.bndVRCaches.at(iFace).at(__xxx_iG);
77 auto &dbv = bndCacheEntry.D0Bj;
78 auto &np = bndCacheEntry.norm;
79 auto &JDet = bndCacheEntry.JDet;
80 auto &pPhy = bndCacheEntry.PPhy;
82 Eigen::Vector<real, nVarsFixed> uBL = (dbv * uRec[iCell]).transpose();
84 Eigen::Vector<real, nVarsFixed> uBV =
87 u[iCell], iCell, iFace, -2,
89 this->GetFacePointFromCell(iFace, iCell, -1, pPhy), faceID);
90 Eigen::RowVector<real, nVarsFixed> uIncBV = (uBV - u[iCell]).transpose();
91 vInc = this->FFaceFunctional(dbv, uIncBV, iFace, iCell, iCell);
99 template <
int nVarsFixed>
100 auto VariationalReconstruction<dim>::GetBoundaryRHSDiff(tURec<nVarsFixed> &uRec,
101 tURec<nVarsFixed> &uRecDiff,
102 tUDof<nVarsFixed> &u,
104 const TFBoundaryDiff<nVarsFixed> &FBoundaryDiff)
106 using namespace Geom;
107 using namespace Geom::Elem;
108 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
110 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> BCC;
111 BCC.setZero(uRec[iCell].rows(), uRec[iCell].cols());
112 auto faceID = mesh->GetFaceZone(iFace);
115 auto qFace = this->GetFaceQuad(iFace);
116 if (settings.intOrderVRBCIsSame() || settings.functionalSettings.greenGauss1Weight != 0)
117 qFace.IntegrationSimple(
119 [&](
auto &vInc,
int iG)
122 this->GetIntPointDiffBaseValue(iCell, iFace, -1, iG, std::array<int, 1>{0}, 1);
123 Eigen::Vector<real, nVarsFixed> uBL = (dbv * uRec[iCell]).transpose();
125 Eigen::Vector<real, nVarsFixed> uBLDiff = (dbv * uRecDiff[iCell]).transpose();
126 Eigen::Vector<real, nVarsFixed>
129 u[iCell], iCell, iFace, iG,
130 this->GetFaceNorm(iFace, iG),
131 this->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, iG), faceID);
132 Eigen::RowVector<real, nVarsFixed> uIncBV = uBV.transpose();
133 if (settings.intOrderVRBCIsSame())
134 vInc = this->FFaceFunctional(dbv, uIncBV, iFace, iCell, iCell);
136 vInc.resizeLike(BCC), vInc.setZero();
138 if (settings.functionalSettings.greenGauss1Weight != 0)
141 vInc += (settings.functionalSettings.greenGauss1Bias * this->GetGreenGauss1WeightOnCell(iCell) *
142 this->coefficients_.matrixAHalf_GG[iCell].transpose() * this->GetFaceNorm(iFace, iG)(Seq012)) *
145 vInc *= this->GetFaceJacobiDet(iFace, iG);
147 if (!settings.intOrderVRBCIsSame())
149 auto qFace = Quadrature(mesh->GetFaceElement(iFace), settings.intOrderVRBCValue());
151 mesh->GetCoordsOnFace(iFace, coords);
154 [&](
auto &vInc,
int __xxx_iG,
const tPoint &pParam,
const Elem::tD01Nj &DiNj)
156 BndVRPointCache &bndCacheEntry = baseWeight_.bndVRCaches.at(iFace).at(__xxx_iG);
157 auto &dbv = bndCacheEntry.D0Bj;
158 auto &np = bndCacheEntry.norm;
159 auto &JDet = bndCacheEntry.JDet;
160 auto &pPhy = bndCacheEntry.PPhy;
161 Eigen::Vector<real, nVarsFixed> uBL = (dbv * uRec[iCell]).transpose();
163 Eigen::Vector<real, nVarsFixed> uBLDiff = (dbv * uRecDiff[iCell]).transpose();
164 Eigen::Vector<real, nVarsFixed> uBV =
167 u[iCell], iCell, iFace, -2,
169 this->GetFacePointFromCell(iFace, iCell, -1, pPhy), faceID);
170 Eigen::RowVector<real, nVarsFixed> uIncBV = uBV.transpose();
171 vInc = this->FFaceFunctional(dbv, uIncBV, iFace, iCell, iCell);
180 template <int nVarsFixed>
185 tUGrad<nVarsFixed, dim> &uRec,
186 tUDof<nVarsFixed> &u,
187 const TFBoundary<nVarsFixed> &FBoundary,
190 using namespace Geom;
191 using namespace Geom::Elem;
193 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
194 static const auto Seq123 = Eigen::seq(Eigen::fix<1>, Eigen::fix<dim>);
196 if (method == 1 || method == 11)
199#if defined(DNDS_DIST_MT_USE_OMP)
200# pragma omp parallel for schedule(runtime)
202 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
204 int nVars = u[iCell].size();
205 auto c2f = mesh->cell2face[iCell];
206 Eigen::Matrix<real, nVarsFixed, dim> grad;
207 grad.setZero(nVars, dim);
209 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> bGG;
212 mGG.setZero(dim + c2f.size(), dim + c2f.size());
213 bGG.setZero(dim + c2f.size(), u[0].rows());
214 mGG(Seq012, Seq012).setIdentity();
218 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
220 index iFace = c2f[ic2f];
221 index iCellOther = CellFaceOther(iCell, iFace);
222 auto faceID = mesh->GetFaceZone(iFace);
223 int if2c = CellIsFaceBack(iCell, iFace) ? 0 : 1;
224 auto faceCent = this->GetFaceQuadraturePPhysFromCell(iFace, iCell, if2c, -1);
225 real lThis = (faceCent - this->GetCellBary(iCell)).norm();
226 if (settings.subs2ndOrderGGScheme == 0)
231 lThat = (this->GetOtherCellBaryFromCell(iCell, iCellOther, iFace) - faceCent).norm();
232 if (settings.subs2ndOrderGGScheme == 0)
234 Eigen::RowVector<real, nVarsFixed> uOther = u[iCellOther].transpose();
235 this->ApplyPeriodicTransform(if2c, faceID, uOther);
236 Eigen::Vector<real, dim> uNorm = this->GetFaceNormFromCell(iFace, iCell, -1, -1)(Seq012) * (CellIsFaceBack(iCell, iFace) ? 1. : -1.);
237 Eigen::Matrix<real, nVarsFixed, dim> gradInc =
238 (uOther.transpose() - u[iCell]) *
239 lThis / (lThis + lThat +
verySmallReal) * this->GetFaceArea(iFace) * uNorm.transpose();
243 mGG(Seq012, dim + ic2f) = -this->GetFaceArea(iFace) / (this->GetCellVol(iCell) +
verySmallReal) * uNorm;
244 mGG(dim + ic2f, Seq012) =
245 (this->GetCellBary(iCell)(Seq012) + this->GetOtherCellBaryFromCell(iCell, iCellOther, iFace)(Seq012) -
246 2 * faceCent(Seq012))
248 mGG(dim + ic2f, dim + ic2f) = 2;
249 bGG(dim + ic2f, EigenAll) = uOther + u[iCell].transpose();
254 auto faceID = mesh->GetFaceZone(iFace);
257 Eigen::Vector<real, nVarsFixed> uBL = u[iCell];
258 Eigen::Vector<real, nVarsFixed> uBV =
261 u[iCell], iCell, iFace, -1,
262 this->GetFaceNorm(iFace, -1),
264 Eigen::Vector<real, dim> uNorm = this->GetFaceNorm(iFace, -1)(Seq012);
265 grad += (uBV - u[iCell]) * 0.5 * this->GetFaceArea(iFace) * uNorm.transpose();
268 mGG(Seq012, dim + ic2f) = -this->GetFaceArea(iFace) / (this->GetCellVol(iCell) +
verySmallReal) * uNorm;
271 Eigen::Vector<real, dim> BaryOther = 2 * faceCent(Seq012) - this->GetCellBary(iCell)(Seq012);
272 mGG(dim + ic2f, Seq012) = (this->GetCellBary(iCell)(Seq012) + BaryOther -
273 2 * faceCent(Seq012))
275 mGG(dim + ic2f, dim + ic2f) = 2;
276 bGG(dim + ic2f, EigenAll) = (uBV + u[iCell]).transpose();
281 grad /= GetCellVol(iCell);
287 auto mGGLU = mGG.fullPivLu();
289 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> xGG = mGGLU.solve(bGG);
290 grad = xGG(Seq012, EigenAll).transpose();
292 if (mesh->GetCellElement(iCell).type == Elem::Pyramid5)
294 std::cout <<
"pyramid5\n";
295 std::cout << mGG << std::endl;
296 std::cout << bGG << std::endl;
297 auto svd = mGG.bdcSvd();
298 std::cout << svd.singularValues().transpose() << std::endl;
299 std::cout << svd.singularValues().maxCoeff() / svd.singularValues().minCoeff() << std::endl;
301 if (mesh->GetCellElement(iCell).type == Elem::Tet4)
303 std::cout <<
"Tet4\n";
304 std::cout << mGG << std::endl;
305 std::cout << bGG << std::endl;
306 auto svd = mGG.bdcSvd();
307 std::cout << svd.singularValues().transpose() << std::endl;
308 std::cout << svd.singularValues().maxCoeff() / svd.singularValues().minCoeff() << std::endl;
317 uRec[iCell] = grad.transpose();
320 else if (method == 2)
322#if defined(DNDS_DIST_MT_USE_OMP)
323# pragma omp parallel for schedule(runtime)
325 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
327 int nVars = u[iCell].size();
328 auto c2f = mesh->cell2face[iCell];
329 Eigen::Matrix<real, nVarsFixed, dim> grad;
330 grad.setZero(nVars, dim);
331 Eigen::Matrix<real, Eigen::Dynamic, dim> dcs;
332 Eigen::Matrix<real, Eigen::Dynamic, nVarsFixed> dus;
333 dcs.resize(c2f.size(), dim);
334 dus.resize(c2f.size(), nVars);
336 for (
int ic2f = 0; ic2f < c2f.size(); ic2f++)
338 index iFace = c2f[ic2f];
339 index iCellOther = CellFaceOther(iCell, iFace);
343 dcs(ic2f, EigenAll) = (GetOtherCellBaryFromCell(iCell, iCellOther, iFace) - GetCellBary(iCell))(Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>))
345 dus(ic2f, EigenAll) = (u[iCellOther] - u[iCell]).transpose();
349 auto faceID = mesh->GetFaceZone(iFace);
352 Eigen::Vector<real, nVarsFixed> uBL;
355 Eigen::Vector<real, nVarsFixed> uBV =
358 u[iCell], iCell, iFace, -1,
359 this->GetFaceNorm(iFace, -1),
360 this->GetFaceQuadraturePPhysFromCell(iFace, iCell, -1, -1), faceID);
361 dus(ic2f, EigenAll) = (uBV - u[iCell]).transpose();
363 dcs(ic2f, EigenAll) =
364 ((GetCellBary(iCell) - GetFaceQuadraturePPhys(iFace, -1)).dot(GetFaceNorm(iFace, -1)) * (-2.) * GetFaceNorm(iFace, -1))(
365 Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>))
371 auto svd = dcs.template bdcSvd<Eigen::ComputeFullU | Eigen::ComputeFullV>();
372 grad = svd.solve(dus).transpose();
373 uRec[iCell] = grad.transpose();
384 template <int nVarsFixed>
389 tURec<nVarsFixed> &uRec,
390 tUDof<nVarsFixed> &u,
391 const TFBoundary<nVarsFixed> &FBoundary,
393 const std::vector<int> &mask)
395 using namespace Geom;
396 using namespace Geom::Elem;
399 int nVars = u.father->MatRowSize();
402 tUGrad<nVarsFixed, dim> uGrad;
403 this->BuildUGrad(uGrad, u.father->MatRowSize(),
false,
false);
405 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
406 static const auto Seq123 = Eigen::seq(Eigen::fix<1>, Eigen::fix<dim>);
408 this->DoReconstruction2ndGrad(uGrad, u, FBoundary, method);
450#if defined(DNDS_DIST_MT_USE_OMP)
451# pragma omp parallel for schedule(static)
453 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
461 int nVars = u[iCell].size();
462 auto c2f = mesh->cell2face[iCell];
463 Eigen::Matrix<real, nVarsFixed, dim> grad = uGrad[iCell].transpose();
465 Eigen::Matrix<real, dim, dim> d1bv;
466 d1bv = this->GetIntPointDiffBaseValue(
467 iCell, -1, -1, -1, Seq123, dim + 1)(EigenAll, Seq012);
468 auto lud1bv = d1bv.partialPivLu();
469 if (lud1bv.rcond() > 1e9)
470 std::cout <<
"Large Cond " << lud1bv.rcond() << std::endl;
471 if (mask.size() == 0)
473 uRec[iCell].setZero();
474 uRec[iCell](Seq012, EigenAll) = lud1bv.solve(grad.transpose());
478 uRec[iCell](EigenAll, mask).setZero();
479 uRec[iCell](Seq012, mask) = lud1bv.solve(grad.transpose())(EigenAll, mask);
486 template <
int nVarsFixed>
496 using namespace Geom;
497 using namespace Geom::Elem;
498 using namespace Geom::Base;
499 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
503 if (settings.maxOrder == 1 && settings.subs2ndOrder != 0)
519#if defined(DNDS_DIST_MT_USE_OMP)
520# pragma omp parallel for schedule(static)
530 uRecNew[
iCell].setZero();
534 else if (settings.SORInstead)
563 else if (settings.SORInstead)
586 else if (settings.SORInstead && !
recordInc)
603#if defined(DNDS_DIST_MT_USE_OMP)
604# pragma omp parallel for schedule(static)
609#if defined(DNDS_DIST_MT_USE_OMP)
610# pragma omp parallel for schedule(static)
618 template <
int nVarsFixed>
626 using namespace Geom;
627 using namespace Geom::Elem;
628 using namespace Geom::Base;
630 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
632 if (settings.maxOrder == 1 && settings.subs2ndOrder != 0)
634#if defined(DNDS_DIST_MT_USE_OMP)
635# pragma omp parallel for schedule(static)
638 uRecNew[
iCell].setZero();
641#if defined(DNDS_DIST_MT_USE_OMP)
642# pragma omp parallel for schedule(runtime)
673 template <
int nVarsFixed>
683 using namespace Geom;
684 using namespace Geom::Elem;
685 using namespace Geom::Base;
687 static const auto Seq012 = Eigen::seq(Eigen::fix<0>, Eigen::fix<dim - 1>);
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
#define DNDS_SWITCH_INTELLISENSE(real, intellisense)
Primary solver state container: an ArrayEigenMatrix pair with MPI-collective vector-space operations.
The VR class that provides any information needed in high-order CFV.
void DoReconstruction2ndGrad(tUGrad< nVarsFixed, dim > &uRec, tUDof< nVarsFixed > &u, const TFBoundary< nVarsFixed > &FBoundary, int method)
fallback reconstruction method, explicit 2nd order FV reconstruction
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 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
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 ...
Eigen::Matrix< real, 3, Eigen::Dynamic > tSmallCoords
DNDS_DEVICE_CALLABLE bool FaceIDIsExternalBC(t_index id)
the host side operators are provided as implemented
DNDS_CONSTANT const index UnInitIndex
Sentinel "not initialised" index value (= INT64_MIN).
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
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).
Eigen::RowVector< real, Eigen::Dynamic > RowVectorXR
Dynamic row-vector of reals.
double real
Canonical floating-point scalar used throughout DNDSR (double precision).