27 template <
int dim,
typename ThetaArray>
31 if constexpr (dim == 2)
37 theta(0, EigenAll).square() +
38 theta(1, EigenAll).square();
42 theta(0, EigenAll).square() +
43 theta(1, EigenAll).square() * 0.5 +
44 theta(2, EigenAll).square();
48 theta(0, EigenAll).square() +
49 theta(1, EigenAll).square() * (1. / 3.) +
50 theta(2, EigenAll).square() * (1. / 3.) +
51 theta(3, EigenAll).square();
64 theta(0, EigenAll).square() +
65 theta(1, EigenAll).square() +
66 theta(2, EigenAll).square();
70 theta(0, EigenAll).square() +
71 theta(1, EigenAll).square() +
72 theta(2, EigenAll).square() +
73 theta(3, EigenAll).square() * 0.5 +
74 theta(4, EigenAll).square() * 0.5 +
75 theta(5, EigenAll).square() * 0.5;
79 theta(0, EigenAll).square() +
80 theta(1, EigenAll).square() +
81 theta(2, EigenAll).square() +
82 theta(3, EigenAll).square() * (1. / 3.) +
83 theta(4, EigenAll).square() * (1. / 3.) +
84 theta(5, EigenAll).square() * (1. / 3.) +
85 theta(6, EigenAll).square() * (1. / 3.) +
86 theta(7, EigenAll).square() * (1. / 3.) +
87 theta(8, EigenAll).square() * (1. / 3.) +
88 theta(9, EigenAll).square() * (1. / 6.);
104 template <
int dim,
typename ThetaArray1,
typename ThetaArray2>
108 static_assert(dim == 2,
"PolynomialDotProduct only implemented for dim=2");
109 switch (theta1.rows())
113 theta1(0, EigenAll) * theta2(0, EigenAll) +
114 theta1(1, EigenAll) * theta2(1, EigenAll);
118 theta1(0, EigenAll) * theta2(0, EigenAll) +
119 theta1(1, EigenAll) * theta2(1, EigenAll) * 0.5 +
120 theta1(2, EigenAll) * theta2(2, EigenAll);
124 theta1(0, EigenAll) * theta2(0, EigenAll) +
125 theta1(1, EigenAll) * theta2(1, EigenAll) * (1. / 3.) +
126 theta1(2, EigenAll) * theta2(2, EigenAll) * (1. / 3.) +
127 theta1(3, EigenAll) * theta2(3, EigenAll);
138 template <
typename TinOthers,
typename Tout>
139 static inline void FWBAP_L2_Multiway_Polynomial2D(
const TinOthers &uOthers,
int Nother, Tout &uOut,
real n1 = 1)
141 using namespace DNDS;
142 static const int p = 4;
146 uUp.resizeLike(uOthers[0]);
148 Eigen::ArrayXd uDown;
149 uDown.resize(uOthers[0].cols());
152 for (
int iOther = 0; iOther < Nother; iOther++)
153 uMax = uMax.max(uOthers[iOther].abs());
154 uMax.rowwise() = uMax.colwise().maxCoeff();
157 for (
int iOther = 0; iOther < Nother; iOther++)
159 Eigen::ArrayXd thetaNorm;
160 Eigen::ArrayXXd theta = uOthers[iOther] / uMax;
161 thetaNorm = PolynomialSquaredNorm<2>(theta);
162 thetaNorm += verySmallReal_pDiP;
163 thetaNorm = thetaNorm.pow(-p / 2);
165 real exn = iOther ? 1.0 : n1;
166 uDown += thetaNorm * exn;
167 uUp += theta.rowwise() * thetaNorm.transpose() * exn;
208 std::cout <<
"Limiter FWBAP_L2_Multiway Failed" << std::endl;
209 std::cout << uMax.transpose() << std::endl;
210 std::cout << uUp.transpose() << std::endl;
211 std::cout << uDown.transpose() << std::endl;
219 template <
typename Tcenter,
typename TinOthers,
typename Tout>
220 static inline void FMEMM_Multiway_Polynomial2D(
const Tcenter &u,
const TinOthers &uOthers,
int Nother, Tout &uOut,
real n1 = 1)
222 using namespace DNDS;
223 static const int p = 4;
225 Eigen::ArrayXXd umax = u.abs();
228 Eigen::ArrayXXd theta0 = u / umax;
229 Eigen::ArrayXXd thetaMinNorm = theta0;
231 for (
int iOther = 0; iOther < Nother; iOther++)
233 Eigen::ArrayXd thetaMinNormNorm;
234 Eigen::ArrayXd thetaNorm;
235 Eigen::ArrayXXd theta = uOthers[iOther] / umax;
236 Eigen::ArrayXd theta0DotTheta;
237 thetaNorm = PolynomialSquaredNorm<2>(theta);
238 thetaMinNormNorm = PolynomialSquaredNorm<2>(thetaMinNorm);
239 theta0DotTheta = PolynomialDotProduct<2>(theta, theta0);
240 Eigen::ArrayXd selection = (thetaNorm - thetaMinNormNorm).
sign() * 0.5 + 0.5;
241 thetaMinNorm = theta.rowwise() * (1 - selection).transpose() +
242 thetaMinNorm.rowwise() * selection.transpose();
246 Eigen::ArrayXd thetaNorm;
247 Eigen::ArrayXd thetaMinNormNorm;
248 thetaNorm = PolynomialSquaredNorm<2>(theta0);
249 thetaMinNormNorm = PolynomialSquaredNorm<2>(thetaMinNorm);
253 Eigen::ArrayXd replaceFactor = replaceLoc * 0 + 1;
256 replaceFactor = (replaceFactor - 1) / replaceLoc;
259 Eigen::ArrayXd ifReplace = (thetaNorm - thetaMinNormNorm).
sign() * 0.5 + 0.5;
260 replaceFactor = ifReplace * replaceFactor + (1 - ifReplace);
262 uOut = u.rowwise() * replaceFactor.transpose() + (thetaMinNorm * umax).rowwise() * (1 - replaceFactor).transpose();
266 std::cout <<
"Limiter FMEMM_L2_Multiway Failed" << std::endl;
267 std::cout << umax.transpose() << std::endl;
268 std::cout << uOut.transpose() << std::endl;
269 std::cout << replaceFactor << std::endl;
270 std::cout << replaceLoc << std::endl;
278 template <
typename TinOthers,
typename Tout>
279 static inline void FWBAP_L2_Multiway_PolynomialOrth(
const TinOthers &uOthers,
int Nother, Tout &uOut,
real n1 = 1)
281 using namespace DNDS;
282 static const int p = 4;
286 uUp.resizeLike(uOthers[0]);
288 Eigen::ArrayXd uDown;
289 uDown.resize(uOthers[0].cols());
292 for (
int iOther = 0; iOther < Nother; iOther++)
293 uMax = uMax.max(uOthers[iOther].abs());
294 uMax.rowwise() = uMax.colwise().maxCoeff();
297 for (
int iOther = 0; iOther < Nother; iOther++)
299 Eigen::ArrayXd thetaNorm;
300 Eigen::ArrayXXd theta = uOthers[iOther] / uMax;
301 thetaNorm = (theta * theta).colwise().sum();
302 thetaNorm += verySmallReal_pDiP;
303 thetaNorm = thetaNorm.pow(-p / 2);
305 real exn = iOther ? 1.0 : n1;
306 uDown += thetaNorm * exn;
307 uUp += theta.rowwise() * thetaNorm.transpose() * exn;
314 std::cout <<
"Limiter FWBAP_L2_Multiway Failed" << std::endl;
315 std::cout << uMax.transpose() << std::endl;
316 std::cout << uUp.transpose() << std::endl;
317 std::cout << uDown.transpose() << std::endl;
322 namespace _Limiters_Internal
329 real theta1 = std::pow(u1 / (u2 +
signP(u2) * 1e-12), p - 1.0);
330 real theta2 = std::pow(u1 / (u2 +
signP(u2) * 1e-12), p);
332 return u1 * (
n + theta1) / (
n + theta2);
337 std::vector<real> thetaBuf(J);
338 real *theta = thetaBuf.data();
339 for (
int ii = 0; ii < J; ++ii)
341 theta[ii] = (u[0] +
signP(u[0]) * 1e-12) / (u[ii] +
signP(u[ii]) * 1e-12);
347 for (
int ii = 0; ii < J; ++ii)
349 sumLocal1 += std::pow(theta[ii], (p - 1.0));
350 sumLocal2 += std::pow(theta[ii], p);
353 return u[0] * sumLocal1 / (sumLocal2 + 1e-12);
360 template <
typename TinOthers,
typename Tout>
364 static const int p = 4;
368 uUp.resizeLike(uOthers[0]);
371 Tout uCent = uOthers[0];
378 for (
int iOther = 1; iOther < Nother; iOther++)
380 Tout thetaInverse = uOthers[0] / (uOthers[iOther].abs() + verySmallReal_pDiP) * uOthers[iOther].
sign();
381 uDown += thetaInverse.square() * thetaInverse.square();
382 uUp += thetaInverse.cube();
383 uCent *= uOthers[iOther].sign().abs();
385 uOut = uCent * (uUp + n1) / (uDown + n1);
431 template <
typename Tin1,
typename Tin2,
typename Tout>
435 static const int p = 4;
449 Tout frac = (u1 / (u2.abs() + verySmallReal_pDiP) * u2.sign());
461 auto theta1 = frac.cube();
462 auto theta2 = frac.square() * frac.square();
464 uOut = u1 * (
n + theta1) / (
n + theta2);
465 uOut *= u2.sign().abs();
482 template <
typename Tin1,
typename Tin2,
typename Tout>
486 static const int p = 4;
489 Tout frac = (u1 / (u2.abs() + verySmallReal_pDiP) * u2.sign());
491 auto theta1 = frac.cube();
492 auto theta2 = frac.square() * frac.square();
494 uOut = u1 * (
n + theta1) / (
n + theta2);
495 uOut *= u2.sign().abs() * (0.5 * (u1.sign() + u2.sign()).abs());
502 template <
typename Tin1,
typename Tin2,
typename Tout>
505 uOut = u1.abs().min(u2.abs()) * (u1.sign() + u2.sign()) * 0.5;
511 template <
typename Tin1,
typename Tin2,
typename Tout>
514 uOut = (u1.sign() + u2.sign()) * (u1 * u2).abs() / ((u1 + u2).abs() +
verySmallReal);
517 template <
int dim,
int nVarsFixed,
typename Tin1,
typename Tin2,
typename Tout>
520 static const int p = 4;
523 static const int nDofMax = dim == 2 ? 6 : 10;
524 Eigen::Array<real, Eigen::Dynamic, nVarsFixed, Eigen::AutoAlign, nDofMax> uMax = u1.abs().max(u2.abs()) + verySmallReal_pDiP;
525 uMax.rowwise() = uMax.colwise().maxCoeff();
526 Eigen::ArrayXd u1p, u2p;
527 Eigen::Array<real, Eigen::Dynamic, nVarsFixed, Eigen::AutoAlign, nDofMax> theta1 = u1 / uMax;
528 Eigen::Array<real, Eigen::Dynamic, nVarsFixed, Eigen::AutoAlign, nDofMax> theta2 = u2 / uMax;
529 u1p = PolynomialSquaredNorm<dim>(theta1);
530 u2p = PolynomialSquaredNorm<dim>(theta2);
537 uOut = (u2.rowwise() * u1p.transpose() +
n * (u1.rowwise() * u2p.transpose())).rowwise() / ((u1p +
n * u2p) +
verySmallReal).transpose();
540 template <
int dim,
int nVarsFixed,
typename Tin1,
typename Tin2,
typename Tout>
543 static const int p = 4;
546 static const int nDofMax = dim == 2 ? 6 : 10;
547 Eigen::Array<real, Eigen::Dynamic, nVarsFixed, Eigen::AutoAlign, nDofMax> uMax = u1.abs().max(u2.abs()) + verySmallReal_pDiP;
548 uMax.rowwise() = uMax.colwise().maxCoeff();
549 Eigen::ArrayXd u1p, u2p;
550 Eigen::Array<real, Eigen::Dynamic, nVarsFixed, Eigen::AutoAlign, nDofMax> theta1 = u1 / uMax;
551 Eigen::Array<real, Eigen::Dynamic, nVarsFixed, Eigen::AutoAlign, nDofMax> theta2 = u2 / uMax;
552 u1p = PolynomialSquaredNorm<dim>(theta1);
553 u2p = PolynomialSquaredNorm<dim>(theta2);
560 Eigen::ArrayXd replaceFactor = replaceLoc * 0 + 1;
563 replaceFactor = (replaceFactor - 1) / replaceLoc;
566 Eigen::ArrayXd ifReplace = (u1p - u2p).
sign() * 0.5 + 0.5;
569 replaceFactor = (1 - ifReplace);
571 uOut = u1.rowwise() * replaceFactor.transpose() + u2.rowwise() * (1 - replaceFactor).transpose();
576 template <
typename Tin1,
typename Tin2,
typename Tout>
579 static const int p = 4;
582 Eigen::ArrayXXd uMax = u1.abs().max(u2.abs()) + verySmallReal_pDiP;
583 uMax.rowwise() = uMax.colwise().maxCoeff();
584 Eigen::ArrayXd u1p, u2p;
585 Eigen::ArrayXXd theta1 = u1 / uMax;
586 Eigen::ArrayXXd theta2 = u2 / uMax;
587 u1p = (theta1 * theta1).colwise().sum();
588 u2p = (theta2 * theta2).colwise().sum();
589 u1p = u1p.pow(p / 2);
590 u2p = u2p.pow(p / 2);
592 uOut = (u2.rowwise() * u1p.transpose() +
n * (u1.rowwise() * u2p.transpose())).rowwise() / ((u1p +
n * u2p) +
verySmallReal).transpose();
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
real W12n1(real u1, real u2)
real W12center(real *u, const int J, real n)
void FWBAP_L2_Cut_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
void FWBAP_L2_Multiway(const TinOthers &uOthers, int Nother, Tout &uOut, real n1=1.0)
input vector<Eigen::Array-like>
void FMEMM_Biway_PolynomialNorm(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
void FMINMOD_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
input eigen arrays
void FWBAP_L2_Biway_PolynomialOrth(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
void FVanLeer_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
input eigen arrays
void FWBAP_L2_Biway_PolynomialNorm(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
Eigen::ArrayXd PolynomialSquaredNorm(const ThetaArray &theta)
Computes the weighted polynomial squared norm of each column of theta.
void FWBAP_L2_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
input eigen arrays
Eigen::ArrayXd PolynomialDotProduct(const ThetaArray1 &theta1, const ThetaArray2 &theta2)
Computes a weighted polynomial dot product between theta1 and theta2.
the host side operators are provided as implemented
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
constexpr real sign(real a)
Signum function: +1, 0, or -1.
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
constexpr real signP(real a)
"Signum, biased toward +1": treats 0 as positive.
Eigen::Vector3d n(1.0, 0.0, 0.0)