MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
bounds.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12// Implementation of bounds
13
14#include "bounds.hpp"
15
16#include <limits>
17#include <cstring>
18#include <string>
19#include <cmath>
20#include <iostream>
21#include <algorithm>
22
23namespace mfem
24{
25
26using namespace std;
27
28void PLBound::Setup(const int nb_i, const int ncp_i,
29 const int b_type_i, const int cp_type_i,
30 const real_t tol_i)
31{
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.");
37 nb = nb_i;
38 ncp = ncp_i;
39 b_type = b_type_i;
40 cp_type = cp_type_i;
41 tol = tol_i;
42 lbound.SetSize(ncp, nb);
43 ubound.SetSize(ncp, nb);
44 nodes.SetSize(nb);
45 weights.SetSize(nb);
46 control_points.SetSize(ncp);
47
48 auto scalenodes = [](const Vector &in, const real_t a, const real_t b) -> Vector
49 {
50 Vector outVec(in.Size());
51 real_t maxv = in.Max();
52 real_t minv = in.Min();
53 for (int i = 0; i < in.Size(); i++)
54 {
55 outVec(i) = a + (b-a)*(in(i)-minv)/(maxv-minv);
56 }
57 return outVec;
58 };
59 MFEM_VERIFY(ncp >= 2,"At least 2 control points are required.");
60
61 if (cp_type == 0) // GL + End Point
62 {
63 control_points(0) = 0.0;
64 control_points(ncp-1) = 1.0;
65 if (ncp > 2)
66 {
67 const real_t *x = poly1d.GetPoints(ncp-3, 0);
68 MFEM_VERIFY(x, "Error in getting points.");
69 for (int i = 0; i < ncp-2; i++)
70 {
71 control_points(i+1) = x[i];
72 }
73 }
74 }
75 else if (cp_type == 1) // Chebyshev
76 {
77 auto GetChebyshevNodes = [](int n) -> Vector
78 {
79 Vector cheb(n);
80 for (int i = 0; i < n; ++i)
81 {
82 cheb(i) = -cos(M_PI * (static_cast<real_t>(i) / (n - 1)));
83 }
84 return cheb;
85 };
86 control_points = GetChebyshevNodes(ncp);
87 }
88 else
89 {
90 MFEM_ABORT("Unsupported interval points. Use [0,1].\n");
91 }
92 control_points = scalenodes(control_points, 0.0, 1.0); // rescale to [0,1]
93
94 Poly_1D::Basis &basis1d(poly1d.GetBasis(nb-1, b_type));
95
96 // Initialize bounds
97 lbound = 0.0;
98 ubound = 0.0;
99
100 Vector bmv(nb), bpv(nb), bv(nb); // basis values
101 Vector bdmv(nb), bdpv(nb), bdv(nb); // basis derivative values
102 Vector vals(3);
103
104 // See Section 3.1.1 of https://arxiv.org/pdf/2501.12349 for explanation of
105 // procedure below.
106 for (int j = 0; j < ncp; j++)
107 {
108 real_t x = control_points(j);
109 real_t xm = x;
110 if (j != 0)
111 {
112 xm = 0.5*(control_points(j-1)+control_points(j));
113 }
114 real_t xp = x;
115 if (j != ncp-1)
116 {
117 xp = 0.5*(control_points(j)+control_points(j+1));
118 }
119 basis1d.Eval(xm, bmv, bdmv);
120 basis1d.Eval(xp, bpv, bdpv);
121 basis1d.Eval(x, bv);
122 real_t dm = x-xm;
123 real_t dp = x-xp;
124 for (int i = 0; i < nb; i++)
125 {
126 if (j == 0)
127 {
128 lbound(j,i) = bv(i);
129 ubound(j,i) = bv(i);
130 }
131 else if (j == ncp-1)
132 {
133 lbound(j,i) = bv(i);
134 ubound(j,i) = bv(i);
135 }
136 else
137 {
138 vals(0) = bv(i);
139 vals(1) = bmv(i) + dm*bdmv(i);
140 vals(2) = bpv(i) + dp*bdpv(i);
141 lbound(j,i) = vals.Min()-tol; // tolerance for good measure
142 ubound(j,i) = vals.Max()+tol; // tolerance for good measure
143 if (b_type == 2)
144 {
145 lbound(j,i) = std::max(lbound(j,i),0_r);
146 }
147 }
148 }
149 }
150
151 IntegrationRule irule(nb);
152 if (b_type == 0)
153 {
155 for (int i = 0; i < nb; i++)
156 {
157 weights(i) = irule.IntPoint(i).weight;
158 nodes(i) = irule.IntPoint(i).x;
159 }
160 }
161 else if (b_type == 1)
162 {
164 for (int i = 0; i < nb; i++)
165 {
166 weights(i) = irule.IntPoint(i).weight;
167 nodes(i) = irule.IntPoint(i).x;
168 }
169 }
170 else if (b_type == 2)
171 {
173 for (int i = 0; i < nb; i++)
174 {
175 weights(i) = irule.IntPoint(i).weight;
176 nodes(i) = irule.IntPoint(i).x;
177 }
178 }
179
180 if (b_type == 2)
181 {
182 nodes_int.SetSize(nb);
183 weights_int.SetSize(nb);
184 IntegrationRule irule_int(nb);
185 {
187 for (int i = 0; i < nb; i++)
188 {
189 weights_int(i) = irule_int.IntPoint(i).weight;
190 nodes_int(i) = irule_int.IntPoint(i).x;
191 }
192 }
193
194 SetupBernsteinBasisMat(basisMatNodes, nodes);
195 // Setup memory for lu factors
196 basisMatLU = basisMatNodes;
197 lu_ip.SetSize(nb);
198 // Compute lu factors
199 LUFactors lu(basisMatLU.GetData(), lu_ip.GetData());
200 bool factor = lu.Factor(nb);
201 MFEM_VERIFY(factor,"Failure in LU factorization in PLBound.");
202
203 // Setup the Bernstein basis matrix for the GLL integration points. This
204 // is used to compute linear fit.
205 SetupBernsteinBasisMat(basisMatInt, nodes_int);
206 }
207 else
208 {
209 nodes_int.SetDataAndSize(nodes.GetData(), nb);
210 weights_int.SetDataAndSize(weights.GetData(), nb);
211 }
212}
213
214PLBound::PLBound(const FiniteElementSpace *fes, const int ncp_i,
215 const int cp_type_i)
216{
217 MFEM_VERIFY(!fes->IsVariableOrder(),
218 "Variable order meshes not yet supported.");
219 const char *name = fes->FEColl()->Name();
220 string cname = name;
221
222 cp_type = cp_type_i;
223 b_type = BasisType::Invalid;
224 nb = fes->GetMaxElementOrder()+1;
225 tol = 0.0;
226
227 int minncp = 2;
228 if (nb > 12)
229 {
230 minncp = 2*nb;
231 }
232 else if (!strncmp(name, "H1_", 3) && strncmp(name, "H1_Trace_", 9))
233 {
234 // H1 GLL
236 minncp = min_ncp_gll_x[cp_type][nb-2];
237 }
238 else if (!strncmp(name, "H1Pos_", 6) && strncmp(name, "H1Pos_Trace_", 12))
239 {
240 // H1 Positive
241 b_type = BasisType::Positive;
242 minncp = min_ncp_pos_x[cp_type][nb-2];
243 }
244 else if (!strncmp(name, "L2_", 3) && strncmp(name, "L2_T", 4))
245 {
246 // L2 Gauss-Legendre
248 minncp = min_ncp_gl_x[cp_type][nb-2];
249 }
250 else if (!strncmp(name, "L2_T1", 5))
251 {
252 // L2 GLL
254 minncp = min_ncp_gll_x[cp_type][nb-2];
255 }
256 else if (!strncmp(name, "L2_T2", 5))
257 {
258 // L2 Positive
259 b_type = BasisType::Positive;
260 minncp = min_ncp_pos_x[cp_type][nb-2];
261 }
262 else
263 {
264 MFEM_ABORT("Only H1 GLL/Positive & L2 GL/GLL/Positive bases supported.");
265 }
266
267 ncp = std::max(minncp, ncp_i);
268
269 Setup(nb, ncp, b_type, cp_type, tol);
270}
271
272void PLBound::Get1DBounds(const Vector &coeff, Vector &intmin,
273 Vector &intmax) const
274{
275 real_t x,w;
276 intmin.SetSize(ncp);
277 intmax.SetSize(ncp);
278 intmin = 0.0;
279 intmax = 0.0;
280 Vector coeffm;
281
282 real_t a0 = 0.0;
283 real_t a1 = 0.0;
284
285 Vector nodal_vals, nodal_integ_vals;
286 if (b_type == 2) // compute values at equispaced nodes and GLL nodes
287 {
288 nodal_vals.SetSize(nb);
289 nodal_integ_vals.SetSize(nb);
290 Vector shape(nb);
291 for (int i = 0; i < nb; i++)
292 {
293 basisMatNodes.GetRow(i, shape);
294 nodal_vals(i) = shape*coeff;
295 basisMatInt.GetRow(i, shape);
296 nodal_integ_vals(i) = shape*coeff;
297 }
298 }
299 else
300 {
301 nodal_vals.SetDataAndSize(coeff.GetData(), nb);
302 nodal_integ_vals.SetDataAndSize(coeff.GetData(), nb);
303 }
304
305 // compute L2 projection for linear bases: a0 + a1*x
306 if (proj)
307 {
308 coeffm.SetSize(nb);
309 coeffm = 0.0;
310 for (int i = 0; i < nb; i++)
311 {
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;
316 }
317
318 // offset the linear fit from nodal values
319 for (int i = 0; i < nb; i++)
320 {
321 x = 2.0*nodes(i)-1;
322 coeffm(i) = nodal_vals(i) - a0 - a1*x;
323 }
324
325 // compute coefficients for Bernstein
326 if (b_type == 2)
327 {
328 LUFactors lu(basisMatLU.GetData(), lu_ip.GetData());
329 lu.Solve(nb, 1, coeffm.GetData());
330 }
331
332 // initialize the bounds to be the linear fit
333 for (int j = 0; j < ncp; j++)
334 {
335 x = 2.0*control_points(j)-1;
336 intmin(j) = a0 + a1*x;
337 intmax(j) = intmin(j);
338 }
339 }
340 else
341 {
342 coeffm.SetDataAndSize(coeff.GetData(), nb);
343 }
344
345 for (int i = 0; i < nb; i++)
346 {
347 real_t c = coeffm(i);
348 for (int j = 0; j < ncp; j++)
349 {
350 intmin(j) += min(lbound(j,i)*c, ubound(j,i)*c);
351 intmax(j) += max(lbound(j,i)*c, ubound(j,i)*c);
352 }
353 }
354}
355
356void PLBound::Get2DBounds(const Vector &coeff, Vector &intmin,
357 Vector &intmax) const
358{
359 intmin.SetSize(ncp*ncp);
360 intmax.SetSize(ncp*ncp);
361 intmin = 0.0;
362 intmax = 0.0;
363 Vector intminT(ncp*nb);
364 Vector intmaxT(ncp*nb);
365 // Get bounds for each row of the solution
366 for (int i = 0; i < nb; i++)
367 {
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);
372 }
373 Vector intminT2 = intminT;
374
375 // Compute a0 and a1 for each column of nodes
376 Vector a0V(ncp), a1V(ncp);
377 a0V = 0.0;
378 a1V = 0.0;
379 real_t x,w,t;
380 if (proj)
381 {
382 if (b_type == 2)
383 {
384 // Note: DenseMatrix uses column-major ordering so we will need to
385 // transpose the matrix.
386 DenseMatrix intminTM(intminT.GetData(), ncp, nb),
387 intmaxTM(intmaxT.GetData(), ncp, nb),
388 intmeanTM(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;
394 intmeanTM *= 0.5;
395 MultABt(basisMatInt, intmeanTM, meanintvalsM);
396
397 // Compute the linear fit along each column and then offset it from
398 // the bounds on the coefficient.
399 // Note: Since Bernstein bases are positive, we can use the lower
400 // bounds to compute the lower bounding polynomial and subtract the
401 // linear fit before finding the Bernstein coefficients corresponding
402 // to the perturbation. Same for upper bounds. If the bases were not
403 // always positive, it is not yet clear if the perturbation
404 // coefficients will be this straightforward to compute.
405 for (int j = 0; j < ncp; j++) // row of interval points
406 {
407 for (int i = 0; i < nb; i++)
408 {
409 x = 2.0*nodes_int(i)-1; // x-coordinate
410 w = 2.0*weights_int(i); // weight
411 t = meanintvalsM(i,j);
412 a0V(j) += 0.5*t*w;
413 a1V(j) += 1.5*t*w*x;
414 }
415 // Offset linear fit
416 for (int i = 0; i < nb; i++)
417 {
418 x = 2.0*nodes(i)-1; // x-coordinate
419 minvalsM(i,j) -= a0V(j) + a1V(j)*x;
420 maxvalsM(i,j) -= a0V(j) + a1V(j)*x;
421 }
422 // Compute Bernstein coefficients
423 LUFactors lu(basisMatLU.GetData(), lu_ip.GetData());
424 lu.Solve(nb, 1, minvalsM.GetColumn(j));
425 lu.Solve(nb, 1, maxvalsM.GetColumn(j));
426 for (int i = 0; i < nb; i++)
427 {
428 intminT(i*ncp+j) = minvalsM(i,j);
429 intmaxT(i*ncp+j) = maxvalsM(i,j);
430 }
431 }
432 }
433 else
434 {
435 for (int j = 0; j < nb; j++) // row of nodes
436 {
437 x = 2.0*nodes(j)-1; // x-coordinate
438 w = 2.0*weights(j); // weight
439 for (int i = 0; i < ncp; i++) // column of interval points
440 {
441 t = 0.5*(intminT(j*ncp+i)+intmaxT(j*ncp+i));
442 a0V(i) += 0.5*t*w;
443 a1V(i) += 1.5*t*w*x;
444 }
445 }
446 // offset the linear fit from nodal values
447 for (int j = 0; j < nb; j++) // row of nodes
448 {
449 x = 2.0*nodes(j)-1; // x-coordinate
450 for (int i = 0; i < ncp; i++) // column of interval points
451 {
452 t = a0V(i) + a1V(i)*x;
453 intminT(j*ncp+i) -= t;
454 intmaxT(j*ncp+i) -= t;
455 }
456 }
457 }
458
459 // Initialize bounds using a0 and a1 values
460 for (int j = 0; j < ncp; j++) // row j
461 {
462 x = 2.0*control_points(j)-1;
463 for (int i = 0; i < ncp; i++) // column i
464 {
465 intmin(j*ncp+i) = a0V(i) + a1V(i)*x;
466 intmax(j*ncp+i) = intmin(j*ncp+i);
467 }
468 }
469 }
470
471 // Compute bounds
472 int id1 = 0, id2 = 0;
473 Vector vals(4);
474 for (int j = 0; j < nb; j++)
475 {
476 for (int i = 0; i < ncp; i++) // ith column
477 {
478 real_t w0 = intminT(id1++);
479 real_t w1 = intmaxT(id2++);
480 for (int k = 0; k < ncp; k++) // kth row
481 {
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();
488 }
489 }
490 }
491}
492
493void PLBound::Get3DBounds(const Vector &coeff, Vector &intmin,
494 Vector &intmax) const
495{
496 int nb2 = nb*nb,
497 ncp2 = ncp*ncp,
498 ncp3 = ncp*ncp*ncp;
499
500 intmin.SetSize(ncp3);
501 intmax.SetSize(ncp3);
502 intmin = 0.0;
503 intmax = 0.0;
504 Vector intminT(ncp2*nb);
505 Vector intmaxT(ncp2*nb);
506
507 // Get bounds for each slice of the solution
508 for (int i = 0; i < nb; i++)
509 {
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);
514 }
515 DenseMatrix intminTM(intminT.GetData(), ncp2, nb),
516 intmaxTM(intmaxT.GetData(), ncp2, nb);
517
518 // Compute a0 and a1 for each tower of nodes
519 Vector a0V(ncp2), a1V(ncp2);
520 a0V = 0.0;
521 a1V = 0.0;
522 real_t x,w,t;
523 if (proj)
524 {
525 if (b_type == 2) // Bernstein bases
526 {
527 // Compute the mean coefficients along each tower.
528 for (int j = 0; j < ncp2; j++) // slice of interval points
529 {
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++) // column of nodes
534 {
535 meanBounds(i) = 0.5*(minBounds(i)+maxBounds(i));
536 }
537 Vector meanNodalIntVals(nb);
538 Vector minNodalVals(nb);
539 Vector maxNodalVals(nb);
540 Vector row(nb);
541 for (int i = 0; i < nb; i++)
542 {
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;
548 }
549 // linear fit along each tower
550 for (int i = 0; i < nb; i++)
551 {
552 x = 2.0*nodes_int(i)-1; // x-coordinate
553 w = 2.0*weights_int(i); // weight
554 a0V(j) += 0.5*meanNodalIntVals(i)*w;
555 a1V(j) += 1.5*meanNodalIntVals(i)*w*x;
556 }
557 // offset the linear fit from bounding coefficients
558 for (int i = 0; i < nb; i++)
559 {
560 x = 2.0*nodes(i)-1; // x-coordinate
561 minNodalVals(i) -= a0V(j) + a1V(j)*x;
562 maxNodalVals(i) -= a0V(j) + a1V(j)*x;
563 }
564 // Compute Bernstein coefficients
565 LUFactors lu(basisMatLU.GetData(), lu_ip.GetData());
566 lu.Solve(nb, 1, minNodalVals.GetData());
567 lu.Solve(nb, 1, maxNodalVals.GetData());
568 for (int i = 0; i < nb; i++)
569 {
570 intminT(i*ncp2+j) = minNodalVals(i);
571 intmaxT(i*ncp2+j) = maxNodalVals(i);
572 }
573 }
574 }
575 else
576 {
577 // nodal bases
578 for (int j = 0; j < nb; j++) // tower of nodes
579 {
580 x = 2.0*nodes(j)-1; // x-coordinate
581 w = 2.0*weights(j); // weight
582 for (int i = 0; i < ncp2; i++) // slice of interval points
583 {
584 t = 0.5*(intminT(j*ncp2+i)+intmaxT(j*ncp2+i));
585 a0V(i) += 0.5*t*w;
586 a1V(i) += 1.5*t*w*x;
587 }
588 }
589 // offset the linear fit from nodal values
590 for (int j = 0; j < nb; j++) // row of nodes
591 {
592 x = 2.0*nodes(j)-1; // x-coordinate
593 for (int i = 0; i < ncp2; i++) // column of interval points
594 {
595 t = a0V(i) + a1V(i)*x;
596 intminT(j*ncp2+i) -= t;
597 intmaxT(j*ncp2+i) -= t;
598 }
599 }
600 }
601
602 // Initialize bounds using a0 and a1 values
603 for (int j = 0; j < ncp; j++) // slice j
604 {
605 x = 2.0*control_points(j)-1;
606 for (int i = 0; i < ncp2; i++) // tower i
607 {
608 intmin(j*ncp2+i) = a0V(i) + a1V(i)*x;
609 intmax(j*ncp2+i) = a0V(i) + a1V(i)*x;
610 }
611 }
612 }
613
614 // Compute bounds
615 int id1 = 0, id2 = 0;
616 Vector vals(4);
617 for (int j = 0; j < nb; j++)
618 {
619 for (int i = 0; i < ncp2; i++) // ith tower
620 {
621 real_t w0 = intminT(id1++);
622 real_t w1 = intmaxT(id2++);
623 for (int k = 0; k < ncp; k++) // kth slice
624 {
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();
631 }
632 }
633 }
634}
635
636void PLBound::GetNDBounds(const int rdim, const Vector &coeff,
637 Vector &intmin, Vector &intmax) const
638{
639 if (rdim == 1)
640 {
641 Get1DBounds(coeff, intmin, intmax);
642 }
643 else if (rdim == 2)
644 {
645 Get2DBounds(coeff, intmin, intmax);
646 }
647 else if (rdim == 3)
648 {
649 Get3DBounds(coeff, intmin, intmax);
650 }
651 else
652 {
653 MFEM_ABORT("Currently not supported.");
654 }
655}
656
657void PLBound::SetupBernsteinBasisMat(DenseMatrix &basisMat,
658 Vector &nodesBern) const
659{
660 const int nbern = nodesBern.Size();
661 L2_SegmentElement el(nbern-1, 2);
662 // we use L2 to leverage lexicographic order
663 Array<int> ordering = el.GetLexicographicOrdering();
664 basisMat.SetSize(nbern, nbern);
665 Vector shape(nbern);
667 for (int i = 0; i < nbern; i++)
668 {
669 ip.x = nodesBern(i);
670 el.CalcShape(ip, shape);
671 basisMat.SetRow(i, shape);
672 }
673}
674
675DenseMatrix PLBound::GetBoundingMatrix(int dim, bool is_lower) const
676{
677 if (dim > 1)
678 {
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;
683 Vector coeffs(nbd);
684 coeffs = 0.0;
685 for (int j = 0; j < nbd; j++)
686 {
687 coeffs(j) = 1.0;
688 boundND.GetColumnReference(j, col);
689 GetNDBounds(dim, coeffs, phimin, phimax);
690 col = is_lower ? phimin : phimax;
691 coeffs(j) = 0.0;
692 }
693 return boundND;
694 }
695 return is_lower ? lbound : ubound;
696}
697
699{
700 return GetBoundingMatrix(dim, true);
701}
702
704{
705 return GetBoundingMatrix(dim, false);
706}
707
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];
711
712int PLBound::GetMinimumPointsForGivenBases(int nb_i, int b_type_i,
713 int cp_type_i) const
714{
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.");
719 if (nb_i > 12)
720 {
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.");
724 }
725 else if (b_type_i == 0)
726 {
727 return min_ncp_gl_x[cp_type_i][nb_i-2];
728 }
729 else if (b_type_i == 1)
730 {
731 return min_ncp_gll_x[cp_type_i][nb_i-2];
732 }
733 else if (b_type_i == 2)
734 {
735 return min_ncp_pos_x[cp_type_i][nb_i-2];
736 }
737 return 0;
738}
739
740void PLBound::Print(std::ostream &outp) const
741{
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;
747 nodes.Print(outp);
748 outp << "Print weights: " << std::endl;
749 weights.Print(outp);
750 outp << "Print control_points: " << std::endl;
751 control_points.Print(outp);
752 outp << "Print lower bounds: " << std::endl;
753 lbound.Print(outp);
754 outp << "Print upper bounds: " << std::endl;
755 ubound.Print(outp);
756}
757
758}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
T * GetData()
Returns the data.
Definition array.hpp:159
@ GaussLobatto
Closed type.
Definition fe_base.hpp:36
@ GaussLegendre
Open type.
Definition fe_base.hpp:35
@ Positive
Bernstein polynomials.
Definition fe_base.hpp:37
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void SetRow(int r, const real_t *row)
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:135
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:125
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
Definition fe_coll.hpp:79
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition fespace.hpp:673
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:854
virtual int GetMaxElementOrder() const
Return the maximum polynomial order over all elements.
Definition fespace.hpp:669
Class for integration point with weight.
Definition intrules.hpp:35
Arbitrary order L2 elements in 1D on a segment.
Definition fe_l2.hpp:23
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...
Definition bounds.cpp:636
void Print(std::ostream &outp=mfem::out) const
Print information about the bounds.
Definition bounds.cpp:740
PLBound(const int nb_i, const int ncp_i, const int b_type_i, const int cp_type_i, const real_t tol_i)
Definition bounds.hpp:94
DenseMatrix GetLowerBoundMatrix(int dim=1) const
Get lower and upper bounding matrix (ncp^dim x nb^dim)
Definition bounds.cpp:698
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.
Definition bounds.cpp:712
DenseMatrix GetUpperBoundMatrix(int dim=1) const
Definition bounds.cpp:703
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.
Definition fe_base.hpp:1186
Basis & GetBasis(const int p, const int btype)
Get a Poly_1D::Basis object of the given degree and BasisType, btype.
Definition fe_base.cpp:2470
static void GaussLegendre(const int np, IntegrationRule *ir)
Definition intrules.cpp:620
static void ClosedUniform(const int np, IntegrationRule *ir)
Definition intrules.cpp:856
static void GaussLobatto(const int np, IntegrationRule *ir)
Definition intrules.cpp:708
Vector data type.
Definition vector.hpp:82
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition vector.cpp:870
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
Definition vector.hpp:191
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
int dim
Definition ex24.cpp:53
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
mfem::real_t real_t
MFEM_HOST_DEVICE dual< value_type, gradient_type > cos(dual< value_type, gradient_type > a)
implementation of cosine for dual numbers
Definition dual.hpp:296
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
float real_t
Definition config.hpp:46
Poly_1D poly1d
Definition fe.cpp:28
STL namespace.