28void PLBound::Setup(
const int nb_i,
const int ncp_i,
29 const int b_type_i,
const int cp_type_i,
32 MFEM_VERIFY(b_type_i >= 0 && b_type_i <= 2,
"Bases not supported. "
33 "Please read class description to see supported types.");
34 MFEM_VERIFY(cp_type_i == 0 || cp_type_i == 1,
35 "Control point type not supported. Please read class "
36 "description to see supported types.");
48 auto scalenodes = [](
const Vector &in,
const real_t a,
const real_t b) -> Vector
50 Vector outVec(in.Size());
53 for (
int i = 0; i < in.Size(); i++)
55 outVec(i) =
a + (
b-
a)*(in(i)-minv)/(maxv-minv);
59 MFEM_VERIFY(ncp >= 2,
"At least 2 control points are required.");
63 control_points(0) = 0.0;
64 control_points(ncp-1) = 1.0;
68 MFEM_VERIFY(x,
"Error in getting points.");
69 for (
int i = 0; i < ncp-2; i++)
71 control_points(i+1) = x[i];
75 else if (cp_type == 1)
77 auto GetChebyshevNodes = [](
int n) -> Vector
80 for (
int i = 0; i < n; ++i)
82 cheb(i) = -
cos(M_PI * (
static_cast<real_t>(i) / (n - 1)));
86 control_points = GetChebyshevNodes(ncp);
90 MFEM_ABORT(
"Unsupported interval points. Use [0,1].\n");
92 control_points = scalenodes(control_points, 0.0, 1.0);
100 Vector bmv(nb), bpv(nb), bv(nb);
101 Vector bdmv(nb), bdpv(nb), bdv(nb);
106 for (
int j = 0; j < ncp; j++)
108 real_t x = control_points(j);
112 xm = 0.5*(control_points(j-1)+control_points(j));
117 xp = 0.5*(control_points(j)+control_points(j+1));
119 basis1d.Eval(xm, bmv, bdmv);
120 basis1d.Eval(xp, bpv, bdpv);
124 for (
int i = 0; i < nb; i++)
128 lbound(i, j) = bv(i);
129 ubound(i, j) = bv(i);
133 lbound(i, j) = bv(i);
134 ubound(i, j) = bv(i);
139 vals(1) = bmv(i) + dm*bdmv(i);
140 vals(2) = bpv(i) + dp*bdpv(i);
141 lbound(i, j) = vals.Min()-tol;
142 ubound(i, j) = vals.Max()+tol;
147 IntegrationRule irule(nb);
151 for (
int i = 0; i < nb; i++)
153 weights(i) = irule.IntPoint(i).weight;
154 nodes(i) = irule.IntPoint(i).x;
157 else if (b_type == 1)
160 for (
int i = 0; i < nb; i++)
162 weights(i) = irule.IntPoint(i).weight;
163 nodes(i) = irule.IntPoint(i).x;
166 else if (b_type == 2)
169 for (
int i = 0; i < nb; i++)
171 weights(i) = irule.IntPoint(i).weight;
172 nodes(i) = irule.IntPoint(i).x;
180 IntegrationRule irule_int(nb);
183 for (
int i = 0; i < nb; i++)
185 weights_int(i) = irule_int.IntPoint(i).weight;
186 nodes_int(i) = irule_int.IntPoint(i).x;
190 SetupBernsteinBasisMat(basisMatNodes, nodes);
192 basisMatLU = basisMatNodes;
196 bool factor = lu.Factor(nb);
197 MFEM_VERIFY(factor,
"Failure in LU factorization in PLBound.");
201 SetupBernsteinBasisMat(basisMatInt, nodes_int);
214 "Variable order meshes not yet supported.");
228 else if (!strncmp(name,
"H1_", 3) && strncmp(name,
"H1_Trace_", 9))
232 minncp = min_ncp_gll_x[cp_type][nb-2];
234 else if (!strncmp(name,
"H1Pos_", 6) && strncmp(name,
"H1Pos_Trace_", 12))
238 minncp = min_ncp_pos_x[cp_type][nb-2];
240 else if (!strncmp(name,
"L2_", 3) && strncmp(name,
"L2_T", 4))
244 minncp = min_ncp_gl_x[cp_type][nb-2];
246 else if (!strncmp(name,
"L2_T1", 5))
250 minncp = min_ncp_gll_x[cp_type][nb-2];
252 else if (!strncmp(name,
"L2_T2", 5))
256 minncp = min_ncp_pos_x[cp_type][nb-2];
260 MFEM_ABORT(
"Only H1 GLL/Positive & L2 GL/GLL/Positive bases supported.");
263 ncp = std::max(minncp, ncp_i);
265 Setup(nb, ncp, b_type, cp_type, tol);
268void PLBound::Get1DBounds(
const Vector &coeff,
Vector &intmin,
282 Vector nodal_vals, nodal_integ_vals;
288 for (
int i = 0; i < nb; i++)
290 basisMatNodes.
GetRow(i, shape);
291 nodal_vals(i) = shape*coeff;
292 basisMatInt.
GetRow(i, shape);
293 nodal_integ_vals(i) = shape*coeff;
305 for (
int i = 0; i < nb; i++)
307 x = 2.0*nodes_int(i)-1;
308 w = 2.0*weights_int(i);
309 a0 += 0.5*nodal_integ_vals(i)*w;
310 a1 += 1.5*nodal_integ_vals(i)*w*x;
314 for (
int i = 0; i < nb; i++)
317 coeffm(i) = nodal_vals(i) - a0 - a1*x;
324 lu.Solve(nb, 1, coeffm.GetData());
328 for (
int j = 0; j < ncp; j++)
330 x = 2.0*control_points(j)-1;
331 intmin(j) = a0 + a1*x;
332 intmax(j) = intmin(j);
337 coeffm.SetDataAndSize(coeff.
GetData(), nb);
340 for (
int i = 0; i < nb; i++)
343 for (
int j = 0; j < ncp; j++)
345 intmin(j) += min(lbound(i,j)*c, ubound(i,j)*c);
346 intmax(j) += max(lbound(i,j)*c, ubound(i,j)*c);
351void PLBound::Get2DBounds(
const Vector &coeff, Vector &intmin,
352 Vector &intmax)
const
354 intmin.SetSize(ncp*ncp);
355 intmax.SetSize(ncp*ncp);
358 Vector intminT(ncp*nb);
359 Vector intmaxT(ncp*nb);
361 for (
int i = 0; i < nb; i++)
363 Vector solcoeff(coeff.GetData()+i*nb, nb);
364 Vector intminrow(intminT.GetData()+i*ncp, ncp);
365 Vector intmaxrow(intmaxT.GetData()+i*ncp, ncp);
366 Get1DBounds(solcoeff, intminrow, intmaxrow);
368 Vector intminT2 = intminT;
371 Vector a0V(ncp), a1V(ncp);
381 DenseMatrix intminTM(intminT.GetData(), ncp, nb),
382 intmaxTM(intmaxT.GetData(), ncp, nb),
384 DenseMatrix minvalsM(nb, ncp), maxvalsM(nb, ncp), meanintvalsM(nb, ncp);
385 MultABt(basisMatNodes, intminTM, minvalsM);
386 MultABt(basisMatNodes, intmaxTM, maxvalsM);
387 intmeanTM = intminTM;
388 intmeanTM += intmaxTM;
390 MultABt(basisMatInt, intmeanTM, meanintvalsM);
400 for (
int j = 0; j < ncp; j++)
402 for (
int i = 0; i < nb; i++)
404 x = 2.0*nodes_int(i)-1;
405 w = 2.0*weights_int(i);
406 t = meanintvalsM(i,j);
411 for (
int i = 0; i < nb; i++)
414 minvalsM(i,j) -= a0V(j) + a1V(j)*x;
415 maxvalsM(i,j) -= a0V(j) + a1V(j)*x;
419 lu.Solve(nb, 1, minvalsM.GetColumn(j));
420 lu.Solve(nb, 1, maxvalsM.GetColumn(j));
421 for (
int i = 0; i < nb; i++)
423 intminT(i*ncp+j) = minvalsM(i,j);
424 intmaxT(i*ncp+j) = maxvalsM(i,j);
430 for (
int j = 0; j < nb; j++)
434 for (
int i = 0; i < ncp; i++)
436 t = 0.5*(intminT(j*ncp+i)+intmaxT(j*ncp+i));
442 for (
int j = 0; j < nb; j++)
445 for (
int i = 0; i < ncp; i++)
447 t = a0V(i) + a1V(i)*x;
448 intminT(j*ncp+i) -= t;
449 intmaxT(j*ncp+i) -= t;
455 for (
int j = 0; j < ncp; j++)
457 x = 2.0*control_points(j)-1;
458 for (
int i = 0; i < ncp; i++)
460 intmin(j*ncp+i) = a0V(i) + a1V(i)*x;
461 intmax(j*ncp+i) = intmin(j*ncp+i);
467 int id1 = 0, id2 = 0;
469 for (
int j = 0; j < nb; j++)
471 for (
int i = 0; i < ncp; i++)
473 real_t w0 = intminT(id1++);
474 real_t w1 = intmaxT(id2++);
475 for (
int k = 0; k < ncp; k++)
477 vals(0) = w0*lbound(j,k);
478 vals(1) = w0*ubound(j,k);
479 vals(2) = w1*lbound(j,k);
480 vals(3) = w1*ubound(j,k);
481 intmin(k*ncp+i) += vals.Min();
482 intmax(k*ncp+i) += vals.Max();
488void PLBound::Get3DBounds(
const Vector &coeff, Vector &intmin,
489 Vector &intmax)
const
495 intmin.SetSize(ncp3);
496 intmax.SetSize(ncp3);
499 Vector intminT(ncp2*nb);
500 Vector intmaxT(ncp2*nb);
503 for (
int i = 0; i < nb; i++)
505 Vector solcoeff(coeff.GetData()+i*nb2, nb2);
506 Vector intminrow(intminT.GetData()+i*ncp2, ncp2);
507 Vector intmaxrow(intmaxT.GetData()+i*ncp2, ncp2);
508 Get2DBounds(solcoeff, intminrow, intmaxrow);
510 DenseMatrix intminTM(intminT.GetData(), ncp2, nb),
511 intmaxTM(intmaxT.GetData(), ncp2, nb);
514 Vector a0V(ncp2), a1V(ncp2);
523 for (
int j = 0; j < ncp2; j++)
525 Vector meanBounds(nb), minBounds(nb), maxBounds(nb);
526 intminTM.GetRow(j, minBounds);
527 intmaxTM.GetRow(j, maxBounds);
528 for (
int i = 0; i < nb; i++)
530 meanBounds(i) = 0.5*(minBounds(i)+maxBounds(i));
532 Vector meanNodalIntVals(nb);
533 Vector minNodalVals(nb);
534 Vector maxNodalVals(nb);
536 for (
int i = 0; i < nb; i++)
538 basisMatNodes.
GetRow(i, row);
539 minNodalVals(i) = row*minBounds;
540 maxNodalVals(i) = row*maxBounds;
541 basisMatInt.
GetRow(i, row);
542 meanNodalIntVals(i) = row*meanBounds;
545 for (
int i = 0; i < nb; i++)
547 x = 2.0*nodes_int(i)-1;
548 w = 2.0*weights_int(i);
549 a0V(j) += 0.5*meanNodalIntVals(i)*w;
550 a1V(j) += 1.5*meanNodalIntVals(i)*w*x;
553 for (
int i = 0; i < nb; i++)
556 minBounds(i) -= a0V(j) + a1V(j)*x;
557 maxBounds(i) -= a0V(j) + a1V(j)*x;
561 lu.Solve(nb, 1, minBounds.GetData());
562 lu.Solve(nb, 1, maxBounds.GetData());
563 for (
int i = 0; i < nb; i++)
565 intminT(i*ncp2+j) = minBounds(i);
566 intmaxT(i*ncp2+j) = maxBounds(i);
573 for (
int j = 0; j < nb; j++)
577 for (
int i = 0; i < ncp2; i++)
579 t = 0.5*(intminT(j*ncp2+i)+intmaxT(j*ncp2+i));
585 for (
int j = 0; j < nb; j++)
588 for (
int i = 0; i < ncp2; i++)
590 t = a0V(i) + a1V(i)*x;
591 intminT(j*ncp2+i) -= t;
592 intmaxT(j*ncp2+i) -= t;
598 for (
int j = 0; j < ncp; j++)
600 x = 2.0*control_points(j)-1;
601 for (
int i = 0; i < ncp2; i++)
603 intmin(j*ncp2+i) = a0V(i) + a1V(i)*x;
604 intmax(j*ncp2+i) = a0V(i) + a1V(i)*x;
610 int id1 = 0, id2 = 0;
612 for (
int j = 0; j < nb; j++)
614 for (
int i = 0; i < ncp2; i++)
616 real_t w0 = intminT(id1++);
617 real_t w1 = intmaxT(id2++);
618 for (
int k = 0; k < ncp; k++)
620 vals(0) = w0*lbound(j,k);
621 vals(1) = w0*ubound(j,k);
622 vals(2) = w1*lbound(j,k);
623 vals(3) = w1*ubound(j,k);
624 intmin(k*ncp2+i) += vals.Min();
625 intmax(k*ncp2+i) += vals.Max();
636 Get1DBounds(coeff, intmin, intmax);
640 Get2DBounds(coeff, intmin, intmax);
644 Get3DBounds(coeff, intmin, intmax);
648 MFEM_ABORT(
"Currently not supported.");
652void PLBound::SetupBernsteinBasisMat(
DenseMatrix &basisMat,
655 const int nbern = nodesBern.
Size();
657 Array<int> ordering = el.GetLexicographicOrdering();
658 basisMat.
SetSize(nbern, nbern);
661 for (
int i = 0; i < nbern; i++)
664 el.CalcShape(ip, shape);
665 basisMat.
SetRow(i, shape);
669constexpr int PLBound::min_ncp_gl_x[2][11];
670constexpr int PLBound::min_ncp_gll_x[2][11];
671constexpr int PLBound::min_ncp_pos_x[2][11];
676 MFEM_VERIFY(b_type_i >= 0 && b_type_i <= 2,
"Invalid node type. Specify 0 "
677 "for GL, 1 for GLL, and 2 for positive " "bases.");
678 MFEM_VERIFY(cp_type_i == 0 || cp_type_i == 1,
"Invalid control point type. "
679 "Specify 0 for GL+end points, 1 for Chebyshev.");
682 MFEM_ABORT(
"GetMinimumPointsForGivenBases can only be used for maximum "
683 "order = 11, i.e. nb=12. 2*nb points should be sufficient to "
684 "bound the bases up to nb = 30.");
686 else if (b_type_i == 0)
688 return min_ncp_gl_x[cp_type_i][nb_i-2];
690 else if (b_type_i == 1)
692 return min_ncp_gll_x[cp_type_i][nb_i-2];
694 else if (b_type_i == 2)
696 return min_ncp_pos_x[cp_type_i][nb_i-2];
703 outp <<
"PLBound nb: " << nb << std::endl;
704 outp <<
"PLBound ncp: " << ncp << std::endl;
705 outp <<
"PLBound b_type: " << b_type << std::endl;
706 outp <<
"PLBound cp_type: " << cp_type << std::endl;
707 outp <<
"Print nodes: " << std::endl;
709 outp <<
"Print weights: " << std::endl;
711 outp <<
"Print control_points: " << std::endl;
712 control_points.
Print(outp);
713 outp <<
"Print lower bounds: " << std::endl;
715 outp <<
"Print upper bounds: " << std::endl;
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
T * GetData()
Returns the data.
@ GaussLobatto
Closed type.
@ GaussLegendre
Open type.
@ Positive
Bernstein polynomials.
Data type dense matrix using column-major storage.
void SetRow(int r, const real_t *row)
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
void Print(std::ostream &out=mfem::out, int width_=4) const override
Prints matrix to stream out.
void GetRow(int r, Vector &row) const
virtual const char * Name() const
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
const FiniteElementCollection * FEColl() const
virtual int GetMaxElementOrder() const
Return the maximum polynomial order over all elements.
Class for integration point with weight.
Arbitrary order L2 elements in 1D on a segment.
void GetNDBounds(const int rdim, const Vector &coeff, Vector &intmin, Vector &intmax) const
void Print(std::ostream &outp=mfem::out) const
PLBound(const int nb_i, const int ncp_i, const int b_type_i, const int cp_type_i, const real_t tol_i)
int GetMinimumPointsForGivenBases(int nb_i, int b_type_i, int cp_type_i) const
const real_t * GetPoints(const int p, const int btype, bool on_device=false)
Get the coordinates of the points of the given BasisType, btype.
Basis & GetBasis(const int p, const int btype)
Get a Poly_1D::Basis object of the given degree and BasisType, btype.
static void GaussLegendre(const int np, IntegrationRule *ir)
static void ClosedUniform(const int np, IntegrationRule *ir)
static void GaussLobatto(const int np, IntegrationRule *ir)
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
MFEM_HOST_DEVICE dual< value_type, gradient_type > cos(dual< value_type, gradient_type > a)
implementation of cosine for dual numbers
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.