27 MFEM_VERIFY(ipar.
Size() == 1 &&
28 dpar.
Size() == 0,
"Invalid spacing function parameters");
29 return std::unique_ptr<SpacingFunction>(
32 MFEM_VERIFY(ipar.
Size() == 3 &&
33 dpar.
Size() == 1,
"Invalid spacing function parameters");
34 return std::unique_ptr<SpacingFunction>(
38 MFEM_VERIFY(ipar.Size() == 3 &&
39 dpar.
Size() == 1,
"Invalid spacing function parameters");
40 return std::unique_ptr<SpacingFunction>(
42 dpar[0], (
bool) ipar[2]));
44 MFEM_VERIFY(ipar.Size() == 3 &&
45 dpar.
Size() == 2,
"Invalid spacing function parameters");
46 return std::unique_ptr<SpacingFunction>(
48 dpar[1], (
bool) ipar[2]));
50 MFEM_VERIFY(ipar.Size() == 3 &&
51 dpar.
Size() == 2,
"Invalid spacing function parameters");
52 return std::unique_ptr<SpacingFunction>(
54 dpar[1], (
bool) ipar[2]));
56 MFEM_VERIFY(ipar.Size() == 3 &&
57 dpar.
Size() == 1,
"Invalid spacing function parameters");
58 return std::unique_ptr<SpacingFunction>(
60 (
bool) ipar[2], dpar[0]));
62 MFEM_VERIFY(ipar.Size() >= 3,
"Invalid spacing function parameters");
63 ipar.GetSubArray(3, ipar[1], relN);
64 ipar.GetSubArray(3 + ipar[1], ipar.Size() - 3 - ipar[1], iparsub);
65 return std::unique_ptr<SpacingFunction>(
67 (
bool) ipar[2], relN, iparsub,
70 MFEM_VERIFY(ipar.Size() >= 8,
"Invalid spacing function parameters");
71 ipar.GetSubArray(8, ipar.Size() - 8, iparsub);
72 return std::unique_ptr<SpacingFunction>(
74 ipar[3], ipar[4], iparsub,
77 MFEM_ABORT(
"Unknown spacing type \"" <<
int(spacingType) <<
"\"");
81 MFEM_ABORT(
"Unknown spacing type");
82 return std::unique_ptr<SpacingFunction>(
nullptr);
87 MFEM_ABORT(
"Base class SpacingFunction should not be cloned");
88 return std::unique_ptr<SpacingFunction>(
nullptr);
91void GeometricSpacingFunction::CalculateSpacing()
95 if (
n == 1) {
return; }
99 constexpr real_t convTol = 1.0e-8;
100 constexpr int maxIter = 100;
104 r = s < s_unif ? 1.5 : 0.5;
106 bool converged =
false;
107 for (
int iter=0; iter<maxIter; ++iter)
109 const real_t g = (s * (std::pow(r,
n) - 1.0)) - r + 1.0;
110 const real_t dg = (
n * s * std::pow(r,
n-1)) - 1.0;
113 if (std::abs(g / dg) < convTol)
120 MFEM_VERIFY(converged,
"Convergence failure in GeometricSpacingFunction");
123void BellSpacingFunction::CalculateSpacing()
135 MFEM_VERIFY(s0 + s1 < 1.0,
"Sum of first and last Bell spacings must be"
144 s[1] = 1.0 - s0 - s1;
153 for (
int i=1; i<
n-1; ++i)
181 constexpr int maxIter = 100;
182 constexpr real_t convTol = 1.0e-10;
183 bool converged =
false;
184 for (
int iter=0; iter<maxIter; ++iter)
187 for (j = 1; j <=
n - 3; j++)
189 wk[0] = (s[j] + s[j+1]) * (s[j] + s[j+1]);
191 wk[2] = (s[j-1] + s[j]) * (s[j-1] + s[j]) * (s[j-1] + s[j]);
193 wk[4] = (s[j+2] + s[j+1]) * (s[j+2] + s[j+1]) * (s[j+2] + s[j+1]);
194 wk[5] = wk[0] * wk[1] / wk[2];
195 wk[6] = wk[0] * wk[3] / wk[4];
196 a[j+1] =
a[j+1] + urk*(wk[5] -
a[j+1]);
197 b[j+1] =
b[j+1] + urk*(wk[6] -
b[j+1]);
200 for (j = 2; j <=
n - 2; j++)
203 + beta[j - 2]) +
b[j] + 2.0 -
alpha[j - 1];
205 alpha[j] = wk[1]*(
a[j]*beta[j - 1]*(2.0 -
alpha[j - 2]) +
206 2.0*
b[j] + beta[j - 1] + 1.0);
207 beta[j] = -
b[j]*wk[1];
208 gamma[j] = wk[1]*(
a[j]*(2.0*gamma[j - 1] - gamma[j - 2] -
209 alpha[j - 2]*gamma[j - 1]) + gamma[j - 1]);
215 s_new[j] = s_new[j-1] + s[j];
218 for (j =
n - 3; j >= 1; j--)
220 s_new[j] =
alpha[j+1]*s_new[j + 1] +
221 beta[j+1]*s_new[j + 2] + gamma[j+1];
225 for (j=
n-1; j>0; --j)
227 s_new[j] = s_new[j] - s_new[j-1];
231 for (j =
n - 2; j >= 2; j--)
233 wk[5] = wk[5] + s_new[j]*s_new[j];
234 wk[6] = wk[6] +
pow(s_new[j] - s[j], 2);
247 MFEM_VERIFY(converged,
"Convergence failure in BellSpacingFunction");
250void GaussianSpacingFunction::CalculateSpacing()
267 s[1] = 1.0 - s0 - s1;
282 const real_t slinear =
n * (s0 + (h * (s1 - s0) * 0.5 * (
n-1)));
284 MFEM_VERIFY(std::abs(slinear - 1.0) > 1.0e-8,
"Bell distribution is too "
285 <<
"close to linear.");
287 const real_t u = slinear < 1.0 ? 1.0 : -1.0;
292 constexpr int maxIter = 10;
293 constexpr real_t convTol = 1.0e-8;
294 bool converged =
false;
295 for (
int iter=0; iter<maxIter; ++iter)
299 const real_t m = 0.5 * (1.0 - (
u * c2 * lnz01));
300 const real_t dmdc = -
u * c * lnz01;
305 for (
int i=0; i<
n; ++i)
308 const real_t ti =
exp((-(x * x) + (2.0 * x * m)) *
u / c2);
312 drdc += ((-2.0 * (-(x * x) + (2.0 * x * m)) / (c2 * c)) +
313 ((2.0 * x * dmdc) / c2)) * ti;
319 if (std::abs(r) < convTol)
329 dc = std::min(dc, (
real_t) 2.0*c);
334 MFEM_VERIFY(converged,
"Convergence failure in GaussianSpacingFunction");
337 const real_t m = 0.5 * (1.0 - (
u * c2 * lnz01));
340 for (
int i=0; i<
n; ++i)
342 const real_t x = (i * h) - m;
343 s[i] = q *
exp(-
u*x*x / c2);
347void LogarithmicSpacingFunction::CalculateSpacing()
349 MFEM_VERIFY(
n > 0 && logBase > 1.0,
350 "Invalid parameters in LogarithmicSpacingFunction");
352 if (sym) { CalculateSymmetric(); }
353 else { CalculateNonsymmetric(); }
356void LogarithmicSpacingFunction::CalculateSymmetric()
360 const bool odd = (
n % 2 == 1);
362 const int M0 =
n / 2;
363 const int M = odd ? (M0 + 1) : M0;
369 for (
int i=M-2; i>=0; --i)
371 const real_t p_i = (
pow(logBase, (i+1)*h) - 1.0) / (logBase - 1.0);
383 const real_t t = odd ? 1.0 / (2.0 - s[M-1]) : 0.5;
385 for (
int i=0; i<M; ++i)
389 if (i < (M-1) || !odd)
396void LogarithmicSpacingFunction::CalculateNonsymmetric()
404 for (
int i=
n-2; i>=0; --i)
406 const real_t p_i = (
pow(logBase, (i+1)*h) - 1.0) / (logBase - 1.0);
417 MFEM_VERIFY(partition.
Size() == np - 1,
"");
418 bool validPartition =
true;
421 for (
int i=0; i<np-1; ++i)
423 partition[i] = dpar[i];
425 if (partition[i] <= 0.0 || partition[i] >= 1.0)
427 validPartition =
false;
430 if (i > 0 && partition[i] <= partition[i-1])
432 validPartition =
false;
436 MFEM_VERIFY(validPartition,
"");
446 for (
int p=0;
p<np; ++
p)
450 const int numIntParam = ipar[osi+1];
451 const int numDoubleParam = ipar[osi+2];
454 dpar_p.
SetSize(numDoubleParam);
456 for (
int i=0; i<numIntParam; ++i)
458 ipar_p[i] = ipar[osi + 3 + i];
461 for (
int i=0; i<numDoubleParam; ++i)
463 dpar_p[i] = dpar[osd + i];
468 osi += 3 + numIntParam;
469 osd += numDoubleParam;
470 n_total += npartition[
p];
472 MFEM_VERIFY(pieces[
p]->
Size() >= 1,
"");
475 MFEM_VERIFY(osi == ipar.
Size() && osd == dpar.
Size(),
"");
481 for (
auto &
p : pieces) {
p->ScaleParameters(
a); }
489 for (
auto&
p : pieces)
492 inum +=
p->NumIntParameters() + 3;
493 dnum +=
p->NumDoubleParameters();
497 <<
n <<
" " << np <<
" " << (int)
reverse <<
"\n";
499 for (
auto n : npartition)
506 for (
auto&
p : pieces)
509 "Piecewise spacings should not be composed");
510 os <<
"\n" << int(
p->GetSpacingType()) <<
" " <<
p->NumIntParameters()
511 <<
" " <<
p->NumDoubleParameters();
513 p->GetIntParameters(ipar);
515 for (
auto& ip : ipar)
522 for (
auto p : partition)
529 for (
auto&
p : pieces)
531 p->GetDoubleParameters(dpar);
546void PiecewiseSpacingFunction::CalculateSpacing()
548 MFEM_VERIFY(
n >= 1 && (
n % n0 == 0 ||
n < n0),
"");
549 const int ref =
n / n0;
550 const int cf = n0 /
n;
554 bool coarsen = cf > 1 &&
n > 1;
558 for (
int p=0;
p<np; ++
p)
560 const int csize = pieces[
p]->Size() / cf;
561 if (pieces[
p]->
Size() != cf * csize)
571 for (
auto&
p : pieces) {
p->
SetSize(1); }
575 MFEM_VERIFY(coarsen ||
n >= n0,
576 "Invalid case in PiecewiseSpacingFunction::CalculateSpacing");
579 for (
int p=0;
p<np; ++
p)
585 pieces[
p]->SetSize(npartition[
p] / cf);
589 pieces[
p]->SetSize(ref * npartition[
p]);
592 const real_t p0 = (
p == 0) ? 0.0 : partition[
p-1];
593 const real_t p1 = (
p == np - 1) ? 1.0 : partition[
p];
594 const real_t h_p = p1 - p0;
596 for (
int i=0; i<pieces[
p]->Size(); ++i)
598 s[n_total + i] = h_p * pieces[
p]->Eval(i);
601 n_total += pieces[
p]->Size();
604 MFEM_VERIFY(n_total ==
n,
"");
609 for (
const auto &
p : pieces)
627void PartialSpacingFunction::CalculateSpacing()
634 fullSpacing->SetSize(1);
638 const int ref =
n / num_elems;
639 MFEM_VERIFY(ref * num_elems ==
n,
"Invalid number of elements");
641 fullSpacing->SetSize(ref * num_elems_full);
643 const int os = ref * first_elem;
644 for (
int i = 0; i <
n; ++i)
646 s[i] = fullSpacing->Eval(os + i);
650 const double d1 = s.
Sum();
651 for (
int i = 0; i <
n; ++i)
659 fullSpacing->ScaleParameters(
a);
666 << first_elem <<
" " << num_elems <<
" " << num_elems_full <<
"\n";
670 os << int(fullSpacing->GetSpacingType()) <<
" "
671 << fullSpacing->NumIntParameters() <<
" "
672 << fullSpacing->NumDoubleParameters();
674 fullSpacing->GetIntParameters(ipar);
676 for (
auto& ip : ipar)
685 fullSpacing->GetDoubleParameters(dpar);
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
Bell spacing function, which produces spacing resembling a Bell curve.
Gaussian spacing function of the general form g(x) = a exp(-(x-m)^2 / c^2) for some scalar parameters...
Geometric spacing function.
Linear spacing function, defining the width of interval i as s + i * d.
Logarithmic spacing function, uniform in log base 10 by default.
Partial spacing function, defined as part of an existing spacing function.
void Print(std::ostream &os) const override
Prints all the data necessary to define the spacing function and its current state (size and other pa...
void SetupFull(SpacingType typeFull, Array< int > const &ipar, Vector const &dpar)
int NumDoubleParameters() const override
Returns the number of double parameters defining the spacing function.
int NumIntParameters() const override
Returns the number of integer parameters defining the spacing function.
void ScaleParameters(real_t a) override
Scales parameters by the factor a associated with Size().
Piecewise spacing function, with spacing functions defining spacing within arbitarily many fixed subi...
void ScaleParameters(real_t a) override
Scales parameters by the factor a associated with Size().
void Print(std::ostream &os) const override
Prints all the data necessary to define the spacing function and its current state (size and other pa...
bool Nested() const override
Returns true if the spacing function is nested during refinement.
void SetupPieces(Array< int > const &ipar, Vector const &dpar)
int Size() const
Returns the size, or number of intervals (elements).
virtual std::unique_ptr< SpacingFunction > Clone() const
Returns a clone (deep-copy) of this spacing function.
bool reverse
Whether to reverse the spacing.
int n
Size, or number of intervals (elements)
int Size() const
Returns the size of the vector.
real_t Sum() const
Return the sum of the vector entries.
void SetSize(int s)
Resize the vector to size s.
MFEM_HOST_DEVICE dual< value_type, gradient_type > log(dual< value_type, gradient_type > a)
implementation of the natural logarithm function for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > sqrt(dual< value_type, gradient_type > x)
implementation of square root for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
real_t u(const Vector &xvec)
std::unique_ptr< SpacingFunction > GetSpacingFunction(const SpacingType spacingType, Array< int > const &ipar, Vector const &dpar)
Returns a new SpacingFunction instance defined by the type and parameters.
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE Complex exp(const Complex &q)