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++)
139 vals(1) = bmv(i) + dm*bdmv(i);
140 vals(2) = bpv(i) + dp*bdpv(i);
141 lbound(j,i) = vals.Min()-tol;
142 ubound(j,i) = vals.Max()+tol;
145 lbound(j,i) = std::max(lbound(j,i),0_r);
151 IntegrationRule irule(nb);
155 for (
int i = 0; i < nb; i++)
157 weights(i) = irule.IntPoint(i).weight;
158 nodes(i) = irule.IntPoint(i).x;
161 else if (b_type == 1)
164 for (
int i = 0; i < nb; i++)
166 weights(i) = irule.IntPoint(i).weight;
167 nodes(i) = irule.IntPoint(i).x;
170 else if (b_type == 2)
173 for (
int i = 0; i < nb; i++)
175 weights(i) = irule.IntPoint(i).weight;
176 nodes(i) = irule.IntPoint(i).x;
184 IntegrationRule irule_int(nb);
187 for (
int i = 0; i < nb; i++)
189 weights_int(i) = irule_int.IntPoint(i).weight;
190 nodes_int(i) = irule_int.IntPoint(i).x;
194 SetupBernsteinBasisMat(basisMatNodes, nodes);
196 basisMatLU = basisMatNodes;
200 bool factor = lu.Factor(nb);
201 MFEM_VERIFY(factor,
"Failure in LU factorization in PLBound.");
205 SetupBernsteinBasisMat(basisMatInt, nodes_int);
218 "Variable order meshes not yet supported.");
232 else if (!strncmp(name,
"H1_", 3) && strncmp(name,
"H1_Trace_", 9))
236 minncp = min_ncp_gll_x[cp_type][nb-2];
238 else if (!strncmp(name,
"H1Pos_", 6) && strncmp(name,
"H1Pos_Trace_", 12))
242 minncp = min_ncp_pos_x[cp_type][nb-2];
244 else if (!strncmp(name,
"L2_", 3) && strncmp(name,
"L2_T", 4))
248 minncp = min_ncp_gl_x[cp_type][nb-2];
250 else if (!strncmp(name,
"L2_T1", 5))
254 minncp = min_ncp_gll_x[cp_type][nb-2];
256 else if (!strncmp(name,
"L2_T2", 5))
260 minncp = min_ncp_pos_x[cp_type][nb-2];
264 MFEM_ABORT(
"Only H1 GLL/Positive & L2 GL/GLL/Positive bases supported.");
267 ncp = std::max(minncp, ncp_i);
269 Setup(nb, ncp, b_type, cp_type, tol);
272void PLBound::Get1DBounds(
const Vector &coeff,
Vector &intmin,
285 Vector nodal_vals, nodal_integ_vals;
291 for (
int i = 0; i < nb; i++)
293 basisMatNodes.
GetRow(i, shape);
294 nodal_vals(i) = shape*coeff;
295 basisMatInt.
GetRow(i, shape);
296 nodal_integ_vals(i) = shape*coeff;
310 for (
int i = 0; i < nb; i++)
312 x = 2.0*nodes_int(i)-1;
313 w = 2.0*weights_int(i);
314 a0 += 0.5*nodal_integ_vals(i)*w;
315 a1 += 1.5*nodal_integ_vals(i)*w*x;
319 for (
int i = 0; i < nb; i++)
322 coeffm(i) = nodal_vals(i) - a0 - a1*x;
329 lu.Solve(nb, 1, coeffm.
GetData());
333 for (
int j = 0; j < ncp; j++)
335 x = 2.0*control_points(j)-1;
336 intmin(j) = a0 + a1*x;
337 intmax(j) = intmin(j);
345 for (
int i = 0; i < nb; i++)
348 for (
int j = 0; j < ncp; j++)
350 intmin(j) += min(lbound(j,i)*c, ubound(j,i)*c);
351 intmax(j) += max(lbound(j,i)*c, ubound(j,i)*c);
356void PLBound::Get2DBounds(
const Vector &coeff, Vector &intmin,
357 Vector &intmax)
const
359 intmin.SetSize(ncp*ncp);
360 intmax.SetSize(ncp*ncp);
363 Vector intminT(ncp*nb);
364 Vector intmaxT(ncp*nb);
366 for (
int i = 0; i < nb; i++)
368 Vector solcoeff(coeff.GetData()+i*nb, nb);
369 Vector intminrow(intminT.GetData()+i*ncp, ncp);
370 Vector intmaxrow(intmaxT.GetData()+i*ncp, ncp);
371 Get1DBounds(solcoeff, intminrow, intmaxrow);
373 Vector intminT2 = intminT;
376 Vector a0V(ncp), a1V(ncp);
386 DenseMatrix intminTM(intminT.GetData(), ncp, nb),
387 intmaxTM(intmaxT.GetData(), ncp, nb),
389 DenseMatrix minvalsM(nb, ncp), maxvalsM(nb, ncp), meanintvalsM(nb, ncp);
390 MultABt(basisMatNodes, intminTM, minvalsM);
391 MultABt(basisMatNodes, intmaxTM, maxvalsM);
392 intmeanTM = intminTM;
393 intmeanTM += intmaxTM;
395 MultABt(basisMatInt, intmeanTM, meanintvalsM);
405 for (
int j = 0; j < ncp; j++)
407 for (
int i = 0; i < nb; i++)
409 x = 2.0*nodes_int(i)-1;
410 w = 2.0*weights_int(i);
411 t = meanintvalsM(i,j);
416 for (
int i = 0; i < nb; i++)
419 minvalsM(i,j) -= a0V(j) + a1V(j)*x;
420 maxvalsM(i,j) -= a0V(j) + a1V(j)*x;
424 lu.Solve(nb, 1, minvalsM.GetColumn(j));
425 lu.Solve(nb, 1, maxvalsM.GetColumn(j));
426 for (
int i = 0; i < nb; i++)
428 intminT(i*ncp+j) = minvalsM(i,j);
429 intmaxT(i*ncp+j) = maxvalsM(i,j);
435 for (
int j = 0; j < nb; j++)
439 for (
int i = 0; i < ncp; i++)
441 t = 0.5*(intminT(j*ncp+i)+intmaxT(j*ncp+i));
447 for (
int j = 0; j < nb; j++)
450 for (
int i = 0; i < ncp; i++)
452 t = a0V(i) + a1V(i)*x;
453 intminT(j*ncp+i) -= t;
454 intmaxT(j*ncp+i) -= t;
460 for (
int j = 0; j < ncp; j++)
462 x = 2.0*control_points(j)-1;
463 for (
int i = 0; i < ncp; i++)
465 intmin(j*ncp+i) = a0V(i) + a1V(i)*x;
466 intmax(j*ncp+i) = intmin(j*ncp+i);
472 int id1 = 0, id2 = 0;
474 for (
int j = 0; j < nb; j++)
476 for (
int i = 0; i < ncp; i++)
478 real_t w0 = intminT(id1++);
479 real_t w1 = intmaxT(id2++);
480 for (
int k = 0; k < ncp; k++)
482 vals(0) = w0*lbound(k,j);
483 vals(1) = w0*ubound(k,j);
484 vals(2) = w1*lbound(k,j);
485 vals(3) = w1*ubound(k,j);
486 intmin(k*ncp+i) += vals.Min();
487 intmax(k*ncp+i) += vals.Max();
493void PLBound::Get3DBounds(
const Vector &coeff, Vector &intmin,
494 Vector &intmax)
const
500 intmin.SetSize(ncp3);
501 intmax.SetSize(ncp3);
504 Vector intminT(ncp2*nb);
505 Vector intmaxT(ncp2*nb);
508 for (
int i = 0; i < nb; i++)
510 Vector solcoeff(coeff.GetData()+i*nb2, nb2);
511 Vector intminrow(intminT.GetData()+i*ncp2, ncp2);
512 Vector intmaxrow(intmaxT.GetData()+i*ncp2, ncp2);
513 Get2DBounds(solcoeff, intminrow, intmaxrow);
515 DenseMatrix intminTM(intminT.GetData(), ncp2, nb),
516 intmaxTM(intmaxT.GetData(), ncp2, nb);
519 Vector a0V(ncp2), a1V(ncp2);
528 for (
int j = 0; j < ncp2; j++)
530 Vector meanBounds(nb), minBounds(nb), maxBounds(nb);
531 intminTM.GetRow(j, minBounds);
532 intmaxTM.GetRow(j, maxBounds);
533 for (
int i = 0; i < nb; i++)
535 meanBounds(i) = 0.5*(minBounds(i)+maxBounds(i));
537 Vector meanNodalIntVals(nb);
538 Vector minNodalVals(nb);
539 Vector maxNodalVals(nb);
541 for (
int i = 0; i < nb; i++)
543 basisMatNodes.
GetRow(i, row);
544 minNodalVals(i) = row*minBounds;
545 maxNodalVals(i) = row*maxBounds;
546 basisMatInt.
GetRow(i, row);
547 meanNodalIntVals(i) = row*meanBounds;
550 for (
int i = 0; i < nb; i++)
552 x = 2.0*nodes_int(i)-1;
553 w = 2.0*weights_int(i);
554 a0V(j) += 0.5*meanNodalIntVals(i)*w;
555 a1V(j) += 1.5*meanNodalIntVals(i)*w*x;
558 for (
int i = 0; i < nb; i++)
561 minNodalVals(i) -= a0V(j) + a1V(j)*x;
562 maxNodalVals(i) -= a0V(j) + a1V(j)*x;
566 lu.Solve(nb, 1, minNodalVals.GetData());
567 lu.Solve(nb, 1, maxNodalVals.GetData());
568 for (
int i = 0; i < nb; i++)
570 intminT(i*ncp2+j) = minNodalVals(i);
571 intmaxT(i*ncp2+j) = maxNodalVals(i);
578 for (
int j = 0; j < nb; j++)
582 for (
int i = 0; i < ncp2; i++)
584 t = 0.5*(intminT(j*ncp2+i)+intmaxT(j*ncp2+i));
590 for (
int j = 0; j < nb; j++)
593 for (
int i = 0; i < ncp2; i++)
595 t = a0V(i) + a1V(i)*x;
596 intminT(j*ncp2+i) -= t;
597 intmaxT(j*ncp2+i) -= t;
603 for (
int j = 0; j < ncp; j++)
605 x = 2.0*control_points(j)-1;
606 for (
int i = 0; i < ncp2; i++)
608 intmin(j*ncp2+i) = a0V(i) + a1V(i)*x;
609 intmax(j*ncp2+i) = a0V(i) + a1V(i)*x;
615 int id1 = 0, id2 = 0;
617 for (
int j = 0; j < nb; j++)
619 for (
int i = 0; i < ncp2; i++)
621 real_t w0 = intminT(id1++);
622 real_t w1 = intmaxT(id2++);
623 for (
int k = 0; k < ncp; k++)
625 vals(0) = w0*lbound(k,j);
626 vals(1) = w0*ubound(k,j);
627 vals(2) = w1*lbound(k,j);
628 vals(3) = w1*ubound(k,j);
629 intmin(k*ncp2+i) += vals.Min();
630 intmax(k*ncp2+i) += vals.Max();
641 Get1DBounds(coeff, intmin, intmax);
645 Get2DBounds(coeff, intmin, intmax);
649 Get3DBounds(coeff, intmin, intmax);
653 MFEM_ABORT(
"Currently not supported.");
657void PLBound::SetupBernsteinBasisMat(
DenseMatrix &basisMat,
660 const int nbern = nodesBern.
Size();
663 Array<int> ordering = el.GetLexicographicOrdering();
664 basisMat.
SetSize(nbern, nbern);
667 for (
int i = 0; i < nbern; i++)
670 el.CalcShape(ip, shape);
671 basisMat.
SetRow(i, shape);
675DenseMatrix PLBound::GetBoundingMatrix(
int dim,
bool is_lower)
const
679 const int ncpd =
static_cast<int>(std::pow(ncp,
dim));
680 const int nbd =
static_cast<int>(std::pow(nb,
dim));
681 DenseMatrix boundND(ncpd, nbd);
682 Vector phimin, phimax, col;
685 for (
int j = 0; j < nbd; j++)
688 boundND.GetColumnReference(j, col);
690 col = is_lower ? phimin : phimax;
695 return is_lower ? lbound : ubound;
700 return GetBoundingMatrix(
dim,
true);
705 return GetBoundingMatrix(
dim,
false);
708constexpr int PLBound::min_ncp_gl_x[2][11];
709constexpr int PLBound::min_ncp_gll_x[2][11];
710constexpr int PLBound::min_ncp_pos_x[2][11];
715 MFEM_VERIFY(b_type_i >= 0 && b_type_i <= 2,
"Invalid node type. Specify 0 "
716 "for GL, 1 for GLL, and 2 for positive " "bases.");
717 MFEM_VERIFY(cp_type_i == 0 || cp_type_i == 1,
"Invalid control point type. "
718 "Specify 0 for GL+end points, 1 for Chebyshev.");
721 MFEM_ABORT(
"GetMinimumPointsForGivenBases can only be used for maximum "
722 "order = 11, i.e. nb=12. 2*nb points should be sufficient to "
723 "bound the bases up to nb = 30.");
725 else if (b_type_i == 0)
727 return min_ncp_gl_x[cp_type_i][nb_i-2];
729 else if (b_type_i == 1)
731 return min_ncp_gll_x[cp_type_i][nb_i-2];
733 else if (b_type_i == 2)
735 return min_ncp_pos_x[cp_type_i][nb_i-2];
742 outp <<
"PLBound nb: " << nb << std::endl;
743 outp <<
"PLBound ncp: " << ncp << std::endl;
744 outp <<
"PLBound b_type: " << b_type << std::endl;
745 outp <<
"PLBound cp_type: " << cp_type << std::endl;
746 outp <<
"Print nodes: " << std::endl;
748 outp <<
"Print weights: " << std::endl;
750 outp <<
"Print control_points: " << std::endl;
751 control_points.
Print(outp);
752 outp <<
"Print lower bounds: " << std::endl;
754 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
Compute piecewise linear bounds for the lexicographically-ordered nodal coefficients in coeff in 1D/2...
void Print(std::ostream &outp=mfem::out) const
Print information about the bounds.
PLBound(const int nb_i, const int ncp_i, const int b_type_i, const int cp_type_i, const real_t tol_i)
DenseMatrix GetLowerBoundMatrix(int dim=1) const
Get lower and upper bounding matrix (ncp^dim x nb^dim)
int GetMinimumPointsForGivenBases(int nb_i, int b_type_i, int cp_type_i) const
Get minimum number of control points needed to bound the given bases.
DenseMatrix GetUpperBoundMatrix(int dim=1) 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.