MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
fe_pos.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// H1 Finite Element classes utilizing the Bernstein basis
13
14#include "fe_pos.hpp"
15#include "face_map_utils.hpp"
16#include "../bilininteg.hpp"
17#include "../lininteg.hpp"
18#include "../coefficient.hpp"
19
20namespace mfem
21{
22
23using namespace std;
24
26 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
27{
28 for (int i = 0; i < dof; i++)
29 {
30 const IntegrationPoint &ip = Nodes.IntPoint(i);
31 Trans.SetIntPoint(&ip);
32 dofs(i) = coeff.Eval(Trans, ip);
33 }
34}
35
37 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
38{
39 MFEM_ASSERT(dofs.Size() == vc.GetVDim()*dof, "");
40 Vector x(vc.GetVDim());
41
42 for (int i = 0; i < dof; i++)
43 {
44 const IntegrationPoint &ip = Nodes.IntPoint(i);
45 Trans.SetIntPoint(&ip);
46 vc.Eval (x, Trans, ip);
47 for (int j = 0; j < x.Size(); j++)
48 {
49 dofs(dof*j+i) = x(j);
50 }
51 }
52}
53
55 const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
56{
57 const NodalFiniteElement *nfe =
58 dynamic_cast<const NodalFiniteElement *>(&fe);
59
60 if (nfe && dof == nfe->GetDof())
61 {
62 nfe->Project(*this, Trans, I);
63 I.Invert();
64 }
65 else
66 {
67 // local L2 projection
68 DenseMatrix pos_mass, mixed_mass;
69 MassIntegrator mass_integ;
70
71 mass_integ.AssembleElementMatrix(*this, Trans, pos_mass);
72 mass_integ.AssembleElementMatrix2(fe, *this, Trans, mixed_mass);
73
74 DenseMatrixInverse pos_mass_inv(pos_mass);
75 I.SetSize(dof, fe.GetDof());
76 pos_mass_inv.Mult(mixed_mass, I);
77 }
78}
79
80
82 const int dims, const int p, const DofMapType dmtype)
83 : PositiveFiniteElement(dims, GetTensorProductGeometry(dims),
84 Pow(p + 1, dims), p,
85 dims > 1 ? FunctionSpace::Qk : FunctionSpace::Pk),
86 TensorBasisElement(dims, p, BasisType::Positive, dmtype) { }
87
89 Array<int> &face_map) const
90{
91 internal::GetTensorFaceMap(dim, order, face_id, face_map);
92}
93
94
96 : PositiveFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
97{
98 Nodes.IntPoint(0).x = 0.0;
99 Nodes.IntPoint(0).y = 0.0;
100 Nodes.IntPoint(1).x = 1.0;
101 Nodes.IntPoint(1).y = 0.0;
102 Nodes.IntPoint(2).x = 1.0;
103 Nodes.IntPoint(2).y = 1.0;
104 Nodes.IntPoint(3).x = 0.0;
105 Nodes.IntPoint(3).y = 1.0;
106 Nodes.IntPoint(4).x = 0.5;
107 Nodes.IntPoint(4).y = 0.0;
108 Nodes.IntPoint(5).x = 1.0;
109 Nodes.IntPoint(5).y = 0.5;
110 Nodes.IntPoint(6).x = 0.5;
111 Nodes.IntPoint(6).y = 1.0;
112 Nodes.IntPoint(7).x = 0.0;
113 Nodes.IntPoint(7).y = 0.5;
114 Nodes.IntPoint(8).x = 0.5;
115 Nodes.IntPoint(8).y = 0.5;
116}
117
119 Vector &shape) const
120{
121 real_t x = ip.x, y = ip.y;
122 real_t l1x, l2x, l3x, l1y, l2y, l3y;
123
124 l1x = (1. - x) * (1. - x);
125 l2x = 2. * x * (1. - x);
126 l3x = x * x;
127 l1y = (1. - y) * (1. - y);
128 l2y = 2. * y * (1. - y);
129 l3y = y * y;
130
131 shape(0) = l1x * l1y;
132 shape(4) = l2x * l1y;
133 shape(1) = l3x * l1y;
134 shape(7) = l1x * l2y;
135 shape(8) = l2x * l2y;
136 shape(5) = l3x * l2y;
137 shape(3) = l1x * l3y;
138 shape(6) = l2x * l3y;
139 shape(2) = l3x * l3y;
140}
141
143 DenseMatrix &dshape) const
144{
145 real_t x = ip.x, y = ip.y;
146 real_t l1x, l2x, l3x, l1y, l2y, l3y;
147 real_t d1x, d2x, d3x, d1y, d2y, d3y;
148
149 l1x = (1. - x) * (1. - x);
150 l2x = 2. * x * (1. - x);
151 l3x = x * x;
152 l1y = (1. - y) * (1. - y);
153 l2y = 2. * y * (1. - y);
154 l3y = y * y;
155
156 d1x = 2. * x - 2.;
157 d2x = 2. - 4. * x;
158 d3x = 2. * x;
159 d1y = 2. * y - 2.;
160 d2y = 2. - 4. * y;
161 d3y = 2. * y;
162
163 dshape(0,0) = d1x * l1y;
164 dshape(0,1) = l1x * d1y;
165
166 dshape(4,0) = d2x * l1y;
167 dshape(4,1) = l2x * d1y;
168
169 dshape(1,0) = d3x * l1y;
170 dshape(1,1) = l3x * d1y;
171
172 dshape(7,0) = d1x * l2y;
173 dshape(7,1) = l1x * d2y;
174
175 dshape(8,0) = d2x * l2y;
176 dshape(8,1) = l2x * d2y;
177
178 dshape(5,0) = d3x * l2y;
179 dshape(5,1) = l3x * d2y;
180
181 dshape(3,0) = d1x * l3y;
182 dshape(3,1) = l1x * d3y;
183
184 dshape(6,0) = d2x * l3y;
185 dshape(6,1) = l2x * d3y;
186
187 dshape(2,0) = d3x * l3y;
188 dshape(2,1) = l3x * d3y;
189}
190
192 ElementTransformation &Trans, DenseMatrix &I) const
193{
194 real_t s[9];
195 IntegrationPoint tr_ip;
196 Vector xx(&tr_ip.x, 2), shape(s, 9);
197
198 for (int i = 0; i < 9; i++)
199 {
200 Trans.Transform(Nodes.IntPoint(i), xx);
201 CalcShape(tr_ip, shape);
202 for (int j = 0; j < 9; j++)
203 if (fabs(I(i,j) = s[j]) < 1.0e-12)
204 {
205 I(i,j) = 0.0;
206 }
207 }
208 for (int i = 0; i < 9; i++)
209 {
210 real_t *d = &I(0,i);
211 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
212 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
213 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
214 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
215 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
216 0.25 * (d[0] + d[1] + d[2] + d[3]);
217 }
218}
219
221 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
222{
223 real_t *d = dofs.GetData();
224
225 for (int i = 0; i < 9; i++)
226 {
227 const IntegrationPoint &ip = Nodes.IntPoint(i);
228 Trans.SetIntPoint(&ip);
229 d[i] = coeff.Eval(Trans, ip);
230 }
231 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
232 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
233 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
234 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
235 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
236 0.25 * (d[0] + d[1] + d[2] + d[3]);
237}
238
241 Vector &dofs) const
242{
243 real_t v[3];
244 Vector x (v, vc.GetVDim());
245
246 for (int i = 0; i < 9; i++)
247 {
248 const IntegrationPoint &ip = Nodes.IntPoint(i);
249 Trans.SetIntPoint(&ip);
250 vc.Eval (x, Trans, ip);
251 for (int j = 0; j < x.Size(); j++)
252 {
253 dofs(9*j+i) = v[j];
254 }
255 }
256 for (int j = 0; j < x.Size(); j++)
257 {
258 real_t *d = &dofs(9*j);
259
260 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
261 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
262 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
263 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
264 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
265 0.25 * (d[0] + d[1] + d[2] + d[3]);
266 }
267}
268
269
271 : PositiveFiniteElement(1, Geometry::SEGMENT, 3, 2)
272{
273 Nodes.IntPoint(0).x = 0.0;
274 Nodes.IntPoint(1).x = 1.0;
275 Nodes.IntPoint(2).x = 0.5;
276}
277
279 Vector &shape) const
280{
281 const real_t x = ip.x, x1 = 1. - x;
282
283 shape(0) = x1 * x1;
284 shape(1) = x * x;
285 shape(2) = 2. * x * x1;
286}
287
289 DenseMatrix &dshape) const
290{
291 const real_t x = ip.x;
292
293 dshape(0,0) = 2. * x - 2.;
294 dshape(1,0) = 2. * x;
295 dshape(2,0) = 2. - 4. * x;
296}
297
298
300 : PositiveTensorFiniteElement(1, p, H1_DOF_MAP)
301{
302#ifndef MFEM_THREAD_SAFE
303 // thread private versions; see class header.
304 shape_x.SetSize(p+1);
305 dshape_x.SetSize(p+1);
306#endif
307
308 // Endpoints need to be first in the list, so reorder them.
309 Nodes.IntPoint(0).x = 0.0;
310 Nodes.IntPoint(1).x = 1.0;
311 for (int i = 1; i < p; i++)
312 {
313 Nodes.IntPoint(i+1).x = real_t(i)/p;
314 }
315}
316
318 Vector &shape) const
319{
320 const int p = order;
321
322#ifdef MFEM_THREAD_SAFE
323 Vector shape_x(p+1);
324#endif
325
326 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData() );
327
328 // Endpoints need to be first in the list, so reorder them.
329 shape(0) = shape_x(0);
330 shape(1) = shape_x(p);
331 for (int i = 1; i < p; i++)
332 {
333 shape(i+1) = shape_x(i);
334 }
335}
336
338 DenseMatrix &dshape) const
339{
340 const int p = order;
341
342#ifdef MFEM_THREAD_SAFE
343 Vector shape_x(p+1), dshape_x(p+1);
344#endif
345
346 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData(), dshape_x.GetData() );
347
348 // Endpoints need to be first in the list, so reorder them.
349 dshape(0,0) = dshape_x(0);
350 dshape(1,0) = dshape_x(p);
351 for (int i = 1; i < p; i++)
352 {
353 dshape(i+1,0) = dshape_x(i);
354 }
355}
356
357void H1Pos_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
358{
359 dofs = 0.0;
360 dofs[vertex] = 1.0;
361}
362
363
365 : PositiveTensorFiniteElement(2, p, H1_DOF_MAP)
366{
367#ifndef MFEM_THREAD_SAFE
368 const int p1 = p + 1;
369
370 shape_x.SetSize(p1);
371 shape_y.SetSize(p1);
372 dshape_x.SetSize(p1);
373 dshape_y.SetSize(p1);
374#endif
375
376 int o = 0;
377 for (int j = 0; j <= p; j++)
378 for (int i = 0; i <= p; i++)
379 {
380 Nodes.IntPoint(dof_map[o++]).Set2(real_t(i)/p, real_t(j)/p);
381 }
382}
383
385 Vector &shape) const
386{
387 const int p = order;
388
389#ifdef MFEM_THREAD_SAFE
390 Vector shape_x(p+1), shape_y(p+1);
391#endif
392
393 Poly_1D::CalcBernstein(p, ip.x, shape_x);
394 Poly_1D::CalcBernstein(p, ip.y, shape_y);
395
396 // Reorder so that vertices are at the beginning of the list
397 for (int o = 0, j = 0; j <= p; j++)
398 for (int i = 0; i <= p; i++)
399 {
400 shape(dof_map[o++]) = shape_x(i)*shape_y(j);
401 }
402}
403
405 DenseMatrix &dshape) const
406{
407 const int p = order;
408
409#ifdef MFEM_THREAD_SAFE
410 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
411#endif
412
413 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
414 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
415
416 // Reorder so that vertices are at the beginning of the list
417 for (int o = 0, j = 0; j <= p; j++)
418 for (int i = 0; i <= p; i++)
419 {
420 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j);
421 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j); o++;
422 }
423}
424
426{
427 dofs = 0.0;
428 dofs[vertex] = 1.0;
429}
430
431
433 : PositiveTensorFiniteElement(3, p, H1_DOF_MAP)
434{
435#ifndef MFEM_THREAD_SAFE
436 const int p1 = p + 1;
437
438 shape_x.SetSize(p1);
439 shape_y.SetSize(p1);
440 shape_z.SetSize(p1);
441 dshape_x.SetSize(p1);
442 dshape_y.SetSize(p1);
443 dshape_z.SetSize(p1);
444#endif
445
446 int o = 0;
447 for (int k = 0; k <= p; k++)
448 for (int j = 0; j <= p; j++)
449 for (int i = 0; i <= p; i++)
450 Nodes.IntPoint(dof_map[o++]).Set3(real_t(i)/p, real_t(j)/p,
451 real_t(k)/p);
452}
453
455 Vector &shape) const
456{
457 const int p = order;
458
459#ifdef MFEM_THREAD_SAFE
460 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
461#endif
462
463 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData() );
464 Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData() );
465 Poly_1D::CalcBernstein(p, ip.z, shape_z.GetData() );
466
467 for (int o = 0, k = 0; k <= p; k++)
468 for (int j = 0; j <= p; j++)
469 for (int i = 0; i <= p; i++)
470 {
471 shape(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_z(k);
472 }
473}
474
476 DenseMatrix &dshape) const
477{
478 const int p = order;
479
480#ifdef MFEM_THREAD_SAFE
481 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
482 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
483#endif
484
485 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData(), dshape_x.GetData() );
486 Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData(), dshape_y.GetData() );
487 Poly_1D::CalcBernstein(p, ip.z, shape_z.GetData(), dshape_z.GetData() );
488
489 for (int o = 0, k = 0; k <= p; k++)
490 for (int j = 0; j <= p; j++)
491 for (int i = 0; i <= p; i++)
492 {
493 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j)* shape_z(k);
494 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j)* shape_z(k);
495 dshape(dof_map[o],2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
496 }
497}
498
500{
501 dofs = 0.0;
502 dofs[vertex] = 1.0;
503}
504
505
507 : PositiveFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
508 FunctionSpace::Pk)
509{
510#ifndef MFEM_THREAD_SAFE
512 dshape_1d.SetSize(p + 1);
514#endif
516
517 struct Index
518 {
519 int p2p3;
520 Index(int p) { p2p3 = 2*p + 3; }
521 int operator()(int i, int j) { return ((p2p3-j)*j)/2+i; }
522 };
523 Index idx(p);
524
525 // vertices
526 dof_map[idx(0,0)] = 0;
527 Nodes.IntPoint(0).Set2(0., 0.);
528 dof_map[idx(p,0)] = 1;
529 Nodes.IntPoint(1).Set2(1., 0.);
530 dof_map[idx(0,p)] = 2;
531 Nodes.IntPoint(2).Set2(0., 1.);
532
533 // edges
534 int o = 3;
535 for (int i = 1; i < p; i++)
536 {
537 dof_map[idx(i,0)] = o;
538 Nodes.IntPoint(o++).Set2(real_t(i)/p, 0.);
539 }
540 for (int i = 1; i < p; i++)
541 {
542 dof_map[idx(p-i,i)] = o;
543 Nodes.IntPoint(o++).Set2(real_t(p-i)/p, real_t(i)/p);
544 }
545 for (int i = 1; i < p; i++)
546 {
547 dof_map[idx(0,p-i)] = o;
548 Nodes.IntPoint(o++).Set2(0., real_t(p-i)/p);
549 }
550
551 // interior
552 for (int j = 1; j < p; j++)
553 for (int i = 1; i + j < p; i++)
554 {
555 dof_map[idx(i,j)] = o;
556 Nodes.IntPoint(o++).Set2(real_t(i)/p, real_t(j)/p);
557 }
558}
559
561 const FiniteElement &fe, const IntegrationRule &ir,
562 DofToQuad::Mode mode,
563 Array<DofToQuad*> &dof2quad_array)
564{
565 DofToQuad *d2q = nullptr;
566 MFEM_VERIFY(mode == DofToQuad::RAGGED_TENSOR, "invalid mode requested");
567
568#if defined(MFEM_THREAD_SAFE) && defined(MFEM_USE_OPENMP)
569 #pragma omp critical (DofToQuad)
570#endif
571 {
572 for (int i = 0; i < dof2quad_array.Size(); i++)
573 {
574 d2q = dof2quad_array[i];
575 if (d2q->IntRule != &ir || d2q->mode != mode) { d2q = nullptr; }
576 }
577 if (!d2q)
578 {
579 d2q = new RaggedDofToQuad;
580 const int ndof = fe.GetOrder() + 1; // verify
581 const int nqpt = (int)floor(pow(ir.GetNPoints(), 1.0/fe.GetDim()) + 0.5);
582 d2q->FE = &fe;
583 d2q->IntRule = &ir;
584 d2q->mode = mode;
585 d2q->ndof = ndof;
586 d2q->nqpt = nqpt;
587
588 RaggedDofToQuad *rd2q = static_cast<RaggedDofToQuad*>(d2q);
589 rd2q->Ba1.SetSize(nqpt*ndof);
590 // second component of ragged tensor basis, technically dof*(dof-1)/2 entries
591 rd2q->Ba2.SetSize((int)nqpt*ndof*ndof);
592 rd2q->Ba1t.SetSize(nqpt*ndof);
593 rd2q->Ba2t.SetSize((int)nqpt*ndof*ndof);
594 // stores first component of ragged tensor basis with order p-1, for gradients only
595 rd2q->Ga1.SetSize(nqpt*(ndof -1));
596 // stores second component of ragged tensor basis with order p-1
597 rd2q->Ga2.SetSize(nqpt*(ndof-1)*(ndof -1));
598 rd2q->Ga1t.SetSize(nqpt*(ndof -1));
599 rd2q->Ga2t.SetSize(nqpt*(ndof-1)*(ndof -1));
600 rd2q->lex_map.SetSize(ndof * ndof);
601 Vector shape_a1(ndof), shape_a2(ndof * ndof);
602 Vector shape_Ga1(ndof-1), shape_Ga2((ndof-1) * (ndof-1));
603 for (int i = 0; i < nqpt; i++)
604 {
605 // The first 'nqpt' points in the first dimension 'ir' have the same x-coordinates as those
606 // of the 1D rule (ie. (2,0) Gauss-Jacobi rule). The first 'nqpt' points in the second dimension
607 // 'ir' have the same y-coordinates as those of the 1D rule for second dimension (i.e. (1,0)
608 // Gauss-Jacobi rule). Additionally, the Bernstein PA algorithms expect evaluation of the
609 // component 1D bases at the Stroud nodes pulled back to the unit square, so perform the pullback
610 // on the fly.
611 const real_t x = ir.IntPoint(i).x;
612 const real_t y = ir.IntPoint(nqpt*i).y / (1.0 - ir.IntPoint(nqpt*i).x);
613
614 Poly_1D::CalcBernstein(ndof-1, x, shape_a1);
615 Poly_1D::CalcBernstein(ndof-2, x, shape_Ga1);
616 for (int j = 0; j < ndof; j++)
617 {
618 rd2q->Ba1t[i+nqpt*j] = rd2q->Ba1[j+ndof*i] = shape_a1(j);
619 if (j < ndof-1)
620 {
621 rd2q->Ga1t[i+nqpt*j] = rd2q->Ga1[j+(ndof-1)*i] = shape_Ga1(j);
622 Poly_1D::CalcBernstein(ndof-2-j, y, shape_Ga2);
623 }
624
625 Poly_1D::CalcBernstein(ndof-1-j, y, shape_a2);
626 for (int k = 0; k < ndof-j; k++)
627 {
628 rd2q->Ba2t[i + nqpt*(j + ndof*k)] = rd2q->Ba2[k + ndof*(j + ndof*i)] = shape_a2(
629 k);
630 if (j < ndof-1 && k < ndof-j-1)
631 {
632 rd2q->Ga2t[i + nqpt*(j + (ndof-1)*k)] = rd2q->Ga2[k + (ndof-1)*(j +
633 (ndof-1)*i)] = shape_Ga2(k);
634 }
635 }
636 }
637 }
638
639 // stores the mapping from 2D Bernstein multi-index (i,j,p-i-j) to the
640 // lexicographic DOF ordering
641 for (int i = 0; i < ndof; i++)
642 {
643 for (int j = 0; j < ndof-i; j++)
644 {
645 int idx = ((2 * (ndof-1) + 3) - j) * j / 2 + i;
646 rd2q->lex_map[j + ndof*i] = idx;
647 }
648 }
650 }
651 }
652 return *d2q;
653}
654
655// static method
657 const int p, const real_t l1, const real_t l2, real_t *shape)
658{
659 const real_t l3 = 1. - l1 - l2;
660
661 // The (i,j) basis function is given by: T(i,j,p-i-j) l1^i l2^j l3^{p-i-j},
662 // where T(i,j,k) = (i+j+k)! / (i! j! k!)
663 // Another expression is given by the terms of the expansion:
664 // (l1 + l2 + l3)^p =
665 // \sum_{j=0}^p \binom{p}{j} l2^j
666 // \sum_{i=0}^{p-j} \binom{p-j}{i} l1^i l3^{p-j-i}
667 const int *bp = Poly_1D::Binom(p);
668 real_t z = 1.;
669 for (int o = 0, j = 0; j <= p; j++)
670 {
671 Poly_1D::CalcBinomTerms(p - j, l1, l3, &shape[o]);
672 real_t s = bp[j]*z;
673 for (int i = 0; i <= p - j; i++)
674 {
675 shape[o++] *= s;
676 }
677 z *= l2;
678 }
679}
680
681// static method
683 const int p, const real_t l1, const real_t l2,
684 real_t *dshape_1d, real_t *dshape)
685{
686 const int dof = ((p + 1)*(p + 2))/2;
687 const real_t l3 = 1. - l1 - l2;
688
689 const int *bp = Poly_1D::Binom(p);
690 real_t z = 1.;
691 for (int o = 0, j = 0; j <= p; j++)
692 {
694 real_t s = bp[j]*z;
695 for (int i = 0; i <= p - j; i++)
696 {
697 dshape[o++] = s*dshape_1d[i];
698 }
699 z *= l2;
700 }
701 z = 1.;
702 for (int i = 0; i <= p; i++)
703 {
705 real_t s = bp[i]*z;
706 for (int o = i, j = 0; j <= p - i; j++)
707 {
708 dshape[dof + o] = s*dshape_1d[j];
709 o += p + 1 - j;
710 }
711 z *= l1;
712 }
713}
714
716 Vector &shape) const
717{
718#ifdef MFEM_THREAD_SAFE
720#endif
721 CalcShape(order, ip.x, ip.y, m_shape.GetData());
722 for (int i = 0; i < dof; i++)
723 {
724 shape(dof_map[i]) = m_shape(i);
725 }
726}
727
729 DenseMatrix &dshape) const
730{
731#ifdef MFEM_THREAD_SAFE
734#endif
736 for (int d = 0; d < 2; d++)
737 {
738 for (int i = 0; i < dof; i++)
739 {
740 dshape(dof_map[i],d) = m_dshape(i,d);
741 }
742 }
743}
744
745
747 : PositiveFiniteElement(3, Geometry::TETRAHEDRON,
748 ((p + 1)*(p + 2)*(p + 3))/6, p, FunctionSpace::Pk)
749{
750#ifndef MFEM_THREAD_SAFE
752 dshape_1d.SetSize(p + 1);
754#endif
756
757 struct Index
758 {
759 int p, dof;
760 int tri(int k) { return (k*(k + 1))/2; }
761 int tet(int k) { return (k*(k + 1)*(k + 2))/6; }
762 Index(int p_) { p = p_; dof = tet(p + 1); }
763 int operator()(int i, int j, int k)
764 { return dof - tet(p - k) - tri(p + 1 - k - j) + i; }
765 };
766 Index idx(p);
767
768 // vertices
769 dof_map[idx(0,0,0)] = 0;
770 Nodes.IntPoint(0).Set3(0., 0., 0.);
771 dof_map[idx(p,0,0)] = 1;
772 Nodes.IntPoint(1).Set3(1., 0., 0.);
773 dof_map[idx(0,p,0)] = 2;
774 Nodes.IntPoint(2).Set3(0., 1., 0.);
775 dof_map[idx(0,0,p)] = 3;
776 Nodes.IntPoint(3).Set3(0., 0., 1.);
777
778 // edges (see Tetrahedron::edges in mesh/tetrahedron.cpp)
779 int o = 4;
780 for (int i = 1; i < p; i++) // (0,1)
781 {
782 dof_map[idx(i,0,0)] = o;
783 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., 0.);
784 }
785 for (int i = 1; i < p; i++) // (0,2)
786 {
787 dof_map[idx(0,i,0)] = o;
788 Nodes.IntPoint(o++).Set3(0., real_t(i)/p, 0.);
789 }
790 for (int i = 1; i < p; i++) // (0,3)
791 {
792 dof_map[idx(0,0,i)] = o;
793 Nodes.IntPoint(o++).Set3(0., 0., real_t(i)/p);
794 }
795 for (int i = 1; i < p; i++) // (1,2)
796 {
797 dof_map[idx(p-i,i,0)] = o;
798 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, real_t(i)/p, 0.);
799 }
800 for (int i = 1; i < p; i++) // (1,3)
801 {
802 dof_map[idx(p-i,0,i)] = o;
803 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, 0., real_t(i)/p);
804 }
805 for (int i = 1; i < p; i++) // (2,3)
806 {
807 dof_map[idx(0,p-i,i)] = o;
808 Nodes.IntPoint(o++).Set3(0., real_t(p-i)/p, real_t(i)/p);
809 }
810
811 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
812 for (int j = 1; j < p; j++)
813 for (int i = 1; i + j < p; i++) // (1,2,3)
814 {
815 dof_map[idx(p-i-j,i,j)] = o;
816 Nodes.IntPoint(o++).Set3(real_t(p-i-j)/p, real_t(i)/p, real_t(j)/p);
817 }
818 for (int j = 1; j < p; j++)
819 for (int i = 1; i + j < p; i++) // (0,3,2)
820 {
821 dof_map[idx(0,j,i)] = o;
822 Nodes.IntPoint(o++).Set3(0., real_t(j)/p, real_t(i)/p);
823 }
824 for (int j = 1; j < p; j++)
825 for (int i = 1; i + j < p; i++) // (0,1,3)
826 {
827 dof_map[idx(i,0,j)] = o;
828 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., real_t(j)/p);
829 }
830 for (int j = 1; j < p; j++)
831 for (int i = 1; i + j < p; i++) // (0,2,1)
832 {
833 dof_map[idx(j,i,0)] = o;
834 Nodes.IntPoint(o++).Set3(real_t(j)/p, real_t(i)/p, 0.);
835 }
836
837 // interior
838 for (int k = 1; k < p; k++)
839 for (int j = 1; j + k < p; j++)
840 for (int i = 1; i + j + k < p; i++)
841 {
842 dof_map[idx(i,j,k)] = o;
843 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, real_t(k)/p);
844 }
845}
846
848 const FiniteElement &fe, const IntegrationRule &ir,
849 DofToQuad::Mode mode,
850 Array<DofToQuad*> &dof2quad_array)
851{
852 DofToQuad *d2q = nullptr;
853 MFEM_VERIFY(mode == DofToQuad::RAGGED_TENSOR, "invalid mode requested");
854
855#if defined(MFEM_THREAD_SAFE) && defined(MFEM_USE_OPENMP)
856 #pragma omp critical (DofToQuad)
857#endif
858 {
859 for (int i = 0; i < dof2quad_array.Size(); i++)
860 {
861 d2q = dof2quad_array[i];
862 if (d2q->IntRule != &ir || d2q->mode != mode) { d2q = nullptr; }
863 }
864 if (!d2q)
865 {
866 d2q = new RaggedDofToQuad;
867 const int ndof = fe.GetOrder() + 1; // verify
868 const int nqpt = (int)floor(pow(ir.GetNPoints(), 1.0/fe.GetDim()) + 0.5);
869 const int basis_dim2d = ndof*(ndof+1) / 2;
870 const int basis_dim3d = ndof*(ndof+1)*(ndof+2) / 6;
871 const int basis_dim2d_diff = (ndof-1)*(ndof) / 2;
872 const int basis_dim3d_diff = (ndof-1)*(ndof)*(ndof+1) / 6;
873 d2q->FE = &fe;
874 d2q->IntRule = &ir;
875 d2q->mode = mode;
876 d2q->ndof = ndof;
877 d2q->nqpt = nqpt;
878
879 RaggedDofToQuad *rd2q = static_cast<RaggedDofToQuad*>(d2q);
880 rd2q->Ba1.SetSize(nqpt * ndof);
881 // second component of ragged tensor basis, technically dof*(dof-1)/2 entries
882 rd2q->Ba2.SetSize(nqpt * basis_dim2d);
883 // third component of ragged tensor basis, technically dof*(dof-1)/2 entries
884 rd2q->Ba3.SetSize(nqpt * basis_dim3d);
885 rd2q->Ba1t.SetSize(nqpt * ndof);
886 rd2q->Ba2t.SetSize(nqpt * basis_dim2d);
887 rd2q->Ba3t.SetSize(nqpt * basis_dim3d);
888 // stores first component of ragged tensor basis with order p-1, for gradients only
889 rd2q->Ga1.SetSize(nqpt * (ndof-1));
890 // stores second component of ragged tensor basis with order p-1
891 rd2q->Ga2.SetSize(nqpt * basis_dim2d_diff);
892 // stores third component of ragged tensor basis with order p-1
893 rd2q->Ga3.SetSize(nqpt * basis_dim3d_diff);
894 rd2q->Ga1t.SetSize(nqpt * (ndof-1));
895 rd2q->Ga2t.SetSize(nqpt * basis_dim2d_diff);
896 rd2q->Ga3t.SetSize(nqpt * basis_dim3d_diff);
897 rd2q->lex_map.SetSize(ndof * ndof * ndof);
898
899 rd2q->forward_map2d_diff.SetSize((ndof-1) * (ndof-1));
900 rd2q->forward_map3d_diff.SetSize((ndof-1) * (ndof-1) * (ndof-1));
901 rd2q->inverse_map2d_diff.SetSize(2 * basis_dim2d_diff);
902 rd2q->inverse_map3d_diff.SetSize(3 * basis_dim3d_diff);
903
904 rd2q->forward_map2d_mass.SetSize(ndof * ndof);
905 rd2q->forward_map3d_mass.SetSize(ndof * ndof * ndof);
906 rd2q->inverse_map2d_mass.SetSize(2 * basis_dim2d);
907 rd2q->inverse_map3d_mass.SetSize(2 * basis_dim3d);
908
909 // forward and inverse maps for multi-index to collapsed 1d index for diffusion, can combine
910 // these four loops, but need four idx's and clause for shorter diff loops
911 int idx = 0;
912 for (int i = 0; i < ndof-1; i++)
913 {
914 for (int j = 0; j < ndof-i-1; j++)
915 {
916 rd2q->forward_map2d_diff[j + (ndof-1)*i] = idx;
917 rd2q->inverse_map2d_diff[2*idx] = i;
918 rd2q->inverse_map2d_diff[1 + 2*idx] = j;
919 idx++;
920 }
921 }
922
923 idx = 0;
924 for (int k = 0; k < ndof-1; k++)
925 {
926 for (int j = 0; j < ndof-k-1; j++)
927 {
928 for (int i = 0; i < ndof-k-j-1; i++)
929 {
930 rd2q->forward_map3d_diff[k + (ndof-1)*(j + (ndof-1)*i)] = idx;
931 rd2q->inverse_map3d_diff[3*idx] = i;
932 rd2q->inverse_map3d_diff[1 + 3*idx] = j;
933 rd2q->inverse_map3d_diff[2 + 3*idx] = k;
934 idx++;
935 }
936 }
937 }
938
939 // forward and inverse maps for multi-index to collapsed 1d index for mass
940 idx = 0;
941 for (int j = 0; j < ndof; j++)
942 {
943 for (int i = 0; i < ndof-j; i++)
944 {
945 rd2q->forward_map2d_mass[j + ndof*i] = idx;
946 rd2q->inverse_map2d_mass[2*idx] = i;
947 rd2q->inverse_map2d_mass[1 + 2*idx] = j;
948 idx++;
949 }
950 }
951
952 idx = 0;
953 for (int k = 0; k < ndof; k++)
954 {
955 for (int j = 0; j < ndof-k; j++)
956 {
957 for (int i = 0; i < ndof-k-j; i++)
958 {
959 rd2q->forward_map3d_mass[k + ndof*(j + ndof*i)] = idx;
960 rd2q->inverse_map3d_mass[2*idx] = i;
961 rd2q->inverse_map3d_mass[1 + 2*idx] = j;
962 // d2q->inverse_map3d_mass[2 + 3*idx] = k;
963 idx++;
964 }
965 }
966 }
967
968 Vector shape_a1(ndof), shape_a2(ndof * ndof), shape_a3(ndof * ndof * ndof);
969 Vector shape_Ga1(ndof-1), shape_Ga2(ndof-1), shape_Ga3(ndof-1);
970 for (int i = 0; i < nqpt; i++)
971 {
972 // The first 'nqpt' points in the first dimension 'ir' have the same x-coordinates as those
973 // of the 1D rule (ie. (2,0) Gauss-Jacobi rule). The first 'nqpt' points in the second dimension
974 // 'ir' have the same y-coordinates as those of the 1D rule for second dimension (i.e. (1,0)
975 // Gauss-Jacobi rule). The first 'nqpt' points in the third dimension have the same z-coordinates
976 // as those of the 1D rule for the third dimension (i.e. Gauss-Legendre rule). Additionally,
977 // the Bernstein PA algorithms expect evaluation of the component 1D bases at the Stroud nodes
978 // pulled back to the unit cube, so perform the pullback on the fly.
979 const real_t x = ir.IntPoint(i).x;
980 const real_t y = ir.IntPoint(nqpt*i).y / (1.0 - ir.IntPoint(nqpt*i).x);
981 const real_t z = ir.IntPoint(nqpt*nqpt*i).z / (1.0 - ir.IntPoint(
982 nqpt*nqpt*i).x - ir.IntPoint(nqpt*nqpt*i).y);
983 Poly_1D::CalcBernstein(ndof-1, x, shape_a1);
984 Poly_1D::CalcBernstein(ndof-2, x, shape_Ga1);
985 for (int j = 0; j < ndof; j++)
986 {
987 rd2q->Ba1t[i+nqpt*j] = rd2q->Ba1[j+ndof*i] = shape_a1(j);
988 if (j < ndof-1)
989 {
990 rd2q->Ga1t[i+nqpt*j] = rd2q->Ga1[j+(ndof-1)*i] = shape_Ga1(j);
991 Poly_1D::CalcBernstein(ndof-2-j, y, shape_Ga2);
992 }
993
994 Poly_1D::CalcBernstein(ndof-1-j, y, shape_a2);
995 for (int k = 0; k < ndof-j; k++)
996 {
997 const int a_2d_mass = rd2q->forward_map2d_mass[k + ndof*j];
998 rd2q->Ba2t[i + nqpt*a_2d_mass] = rd2q->Ba2[a_2d_mass + basis_dim2d*i] =
999 shape_a2(
1000 k);
1001 if (j < ndof-1 && k < ndof-j-1)
1002 {
1003 const int a_2d_diff = rd2q->forward_map2d_diff[k + (ndof-1)*j];
1004 rd2q->Ga2t[i + nqpt*a_2d_diff] = rd2q->Ga2[a_2d_diff + basis_dim2d_diff*i] =
1005 shape_Ga2(k);
1006 Poly_1D::CalcBernstein(ndof-2-j-k, z, shape_Ga3);
1007 }
1008
1009 Poly_1D::CalcBernstein(ndof-1-j-k, z, shape_a3);
1010 for (int m = 0; m < ndof-j-k; m++)
1011 {
1012 const int a_3d_mass = rd2q->forward_map3d_mass[m + ndof*(k + ndof*j)];
1013 rd2q->Ba3t[i + nqpt*a_3d_mass] = rd2q->Ba3[a_3d_mass + basis_dim3d*i] =
1014 shape_a3(
1015 m);
1016 if (j < ndof-1 && k < ndof-j-1 && m < ndof-j-k-1)
1017 {
1018 // // collapsed 1D access
1019 // d2q->Ga3[i + nqpt*(m + d2q->offset3d[k + (ndof-1)*j])] = shape_Ga3(m);
1020 // collapsed 1D access with forward mapping
1021 const int a_3d_diff = rd2q->forward_map3d_diff[m + (ndof-1)*(k + (ndof-1)*j)];
1022 rd2q->Ga3t[i + nqpt*a_3d_diff] = rd2q->Ga3[a_3d_diff + basis_dim3d_diff*i] =
1023 shape_Ga3(m);
1024 }
1025 }
1026 }
1027 }
1028 }
1029
1030 // stores the mapping from 3D Bernstein multi-index (i,j,k,p-i-j-k) to the
1031 // lexicographic DOF ordering
1032 int p = ndof - 1;
1033 for (int i = 0; i < ndof; i++)
1034 {
1035 for (int j = 0; j < ndof-i; j++)
1036 {
1037 for (int k = 0; k < ndof-i-j; k++)
1038 {
1039 int dof = (p+1)*(p+2)*(p+3) / 6;
1040 int tet = (p-k)*(p-k+1)*(p-k+2) / 6;
1041 int tri = (p+1-k-j)*(p+2-k-j)/2;
1042 int multi_idx = dof - tet - tri + i;
1043 rd2q->lex_map[k + ndof*(j + ndof*i)] = multi_idx;
1044 }
1045 }
1046 }
1047
1049 }
1050 }
1051 return *d2q;
1052}
1053
1054// static method
1056 const int p, const real_t l1, const real_t l2, const real_t l3,
1057 real_t *shape)
1058{
1059 const real_t l4 = 1. - l1 - l2 - l3;
1060
1061 // The basis functions are the terms in the expansion:
1062 // (l1 + l2 + l3 + l4)^p =
1063 // \sum_{k=0}^p \binom{p}{k} l3^k
1064 // \sum_{j=0}^{p-k} \binom{p-k}{j} l2^j
1065 // \sum_{i=0}^{p-k-j} \binom{p-k-j}{i} l1^i l4^{p-k-j-i}
1066 const int *bp = Poly_1D::Binom(p);
1067 real_t l3k = 1.;
1068 for (int o = 0, k = 0; k <= p; k++)
1069 {
1070 const int *bpk = Poly_1D::Binom(p - k);
1071 const real_t ek = bp[k]*l3k;
1072 real_t l2j = 1.;
1073 for (int j = 0; j <= p - k; j++)
1074 {
1075 Poly_1D::CalcBinomTerms(p - k - j, l1, l4, &shape[o]);
1076 real_t ekj = ek*bpk[j]*l2j;
1077 for (int i = 0; i <= p - k - j; i++)
1078 {
1079 shape[o++] *= ekj;
1080 }
1081 l2j *= l2;
1082 }
1083 l3k *= l3;
1084 }
1085}
1086
1087// static method
1089 const int p, const real_t l1, const real_t l2, const real_t l3,
1090 real_t *dshape_1d, real_t *dshape)
1091{
1092 const int dof = ((p + 1)*(p + 2)*(p + 3))/6;
1093 const real_t l4 = 1. - l1 - l2 - l3;
1094
1095 // For the x derivatives, differentiate the terms of the expression:
1096 // \sum_{k=0}^p \binom{p}{k} l3^k
1097 // \sum_{j=0}^{p-k} \binom{p-k}{j} l2^j
1098 // \sum_{i=0}^{p-k-j} \binom{p-k-j}{i} l1^i l4^{p-k-j-i}
1099 const int *bp = Poly_1D::Binom(p);
1100 real_t l3k = 1.;
1101 for (int o = 0, k = 0; k <= p; k++)
1102 {
1103 const int *bpk = Poly_1D::Binom(p - k);
1104 const real_t ek = bp[k]*l3k;
1105 real_t l2j = 1.;
1106 for (int j = 0; j <= p - k; j++)
1107 {
1108 Poly_1D::CalcDBinomTerms(p - k - j, l1, l4, dshape_1d);
1109 real_t ekj = ek*bpk[j]*l2j;
1110 for (int i = 0; i <= p - k - j; i++)
1111 {
1112 dshape[o++] = dshape_1d[i]*ekj;
1113 }
1114 l2j *= l2;
1115 }
1116 l3k *= l3;
1117 }
1118 // For the y derivatives, differentiate the terms of the expression:
1119 // \sum_{k=0}^p \binom{p}{k} l3^k
1120 // \sum_{i=0}^{p-k} \binom{p-k}{i} l1^i
1121 // \sum_{j=0}^{p-k-i} \binom{p-k-i}{j} l2^j l4^{p-k-j-i}
1122 l3k = 1.;
1123 for (int ok = 0, k = 0; k <= p; k++)
1124 {
1125 const int *bpk = Poly_1D::Binom(p - k);
1126 const real_t ek = bp[k]*l3k;
1127 real_t l1i = 1.;
1128 for (int i = 0; i <= p - k; i++)
1129 {
1130 Poly_1D::CalcDBinomTerms(p - k - i, l2, l4, dshape_1d);
1131 real_t eki = ek*bpk[i]*l1i;
1132 int o = ok + i;
1133 for (int j = 0; j <= p - k - i; j++)
1134 {
1135 dshape[dof + o] = dshape_1d[j]*eki;
1136 o += p - k - j + 1;
1137 }
1138 l1i *= l1;
1139 }
1140 l3k *= l3;
1141 ok += ((p - k + 2)*(p - k + 1))/2;
1142 }
1143 // For the z derivatives, differentiate the terms of the expression:
1144 // \sum_{j=0}^p \binom{p}{j} l2^j
1145 // \sum_{i=0}^{p-j} \binom{p-j}{i} l1^i
1146 // \sum_{k=0}^{p-j-i} \binom{p-j-i}{k} l3^k l4^{p-k-j-i}
1147 real_t l2j = 1.;
1148 for (int j = 0; j <= p; j++)
1149 {
1150 const int *bpj = Poly_1D::Binom(p - j);
1151 const real_t ej = bp[j]*l2j;
1152 real_t l1i = 1.;
1153 for (int i = 0; i <= p - j; i++)
1154 {
1155 Poly_1D::CalcDBinomTerms(p - j - i, l3, l4, dshape_1d);
1156 real_t eji = ej*bpj[i]*l1i;
1157 int m = ((p + 2)*(p + 1))/2;
1158 int n = ((p - j + 2)*(p - j + 1))/2;
1159 for (int o = i, k = 0; k <= p - j - i; k++)
1160 {
1161 // m = ((p - k + 2)*(p - k + 1))/2;
1162 // n = ((p - k - j + 2)*(p - k - j + 1))/2;
1163 o += m;
1164 dshape[2*dof + o - n] = dshape_1d[k]*eji;
1165 m -= p - k + 1;
1166 n -= p - k - j + 1;
1167 }
1168 l1i *= l1;
1169 }
1170 l2j *= l2;
1171 }
1172}
1173
1175 Vector &shape) const
1176{
1177#ifdef MFEM_THREAD_SAFE
1179#endif
1180 CalcShape(order, ip.x, ip.y, ip.z, m_shape.GetData());
1181 for (int i = 0; i < dof; i++)
1182 {
1183 shape(dof_map[i]) = m_shape(i);
1184 }
1185}
1186
1188 DenseMatrix &dshape) const
1189{
1190#ifdef MFEM_THREAD_SAFE
1191 Vector dshape_1d(order + 1);
1193#endif
1194 CalcDShape(order, ip.x, ip.y, ip.z, dshape_1d.GetData(), m_dshape.Data());
1195 for (int d = 0; d < 3; d++)
1196 {
1197 for (int i = 0; i < dof; i++)
1198 {
1199 dshape(dof_map[i],d) = m_dshape(i,d);
1200 }
1201 }
1202}
1203
1204
1206 : PositiveFiniteElement(3, Geometry::PRISM,
1207 ((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
1208 TriangleFE(p),
1209 SegmentFE(p)
1210{
1211#ifndef MFEM_THREAD_SAFE
1216#endif
1217
1218 t_dof.SetSize(dof);
1219 s_dof.SetSize(dof);
1220
1221 // Nodal DoFs
1222 t_dof[0] = 0; s_dof[0] = 0;
1223 t_dof[1] = 1; s_dof[1] = 0;
1224 t_dof[2] = 2; s_dof[2] = 0;
1225 t_dof[3] = 0; s_dof[3] = 1;
1226 t_dof[4] = 1; s_dof[4] = 1;
1227 t_dof[5] = 2; s_dof[5] = 1;
1228
1229 // Edge DoFs
1230 int ne = p-1;
1231 for (int i=1; i<p; i++)
1232 {
1233 t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
1234 t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
1235 t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
1236 t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
1237 t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
1238 t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
1239 t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
1240 t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
1241 t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
1242 }
1243
1244 // Triangular Face DoFs
1245 int k=0;
1246 int nt = (p-1)*(p-2)/2;
1247 for (int j=1; j<p; j++)
1248 {
1249 for (int i=1; i<j; i++)
1250 {
1251 t_dof[6 + 9 * ne + k] = 3 * p + k; s_dof[6 + 9 * ne + k] = 0;
1252 t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
1253 k++;
1254 }
1255 }
1256
1257 // Quadrilateral Face DoFs
1258 k=0;
1259 int nq = (p-1)*(p-1);
1260 for (int j=1; j<p; j++)
1261 {
1262 for (int i=1; i<p; i++)
1263 {
1264 t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
1265 t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
1266 t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
1267
1268 s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
1269 s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
1270 s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
1271
1272 k++;
1273 }
1274 }
1275
1276 // Interior DoFs
1277 int m=0;
1278 for (k=1; k<p; k++)
1279 {
1280 int l=0;
1281 for (int j=1; j<p; j++)
1282 {
1283 for (int i=1; i<j; i++)
1284 {
1285 t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
1286 s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
1287 l++; m++;
1288 }
1289 }
1290 }
1291
1292 // Define Nodes
1293 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
1294 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
1295 for (int i=0; i<dof; i++)
1296 {
1297 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
1298 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
1299 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
1300 }
1301}
1302
1304 Vector &shape) const
1305{
1306#ifdef MFEM_THREAD_SAFE
1309#endif
1310
1311 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1312
1315
1316 for (int i=0; i<dof; i++)
1317 {
1318 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
1319 }
1320}
1321
1323 DenseMatrix &dshape) const
1324{
1325#ifdef MFEM_THREAD_SAFE
1330#endif
1331
1332 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1333
1338
1339 for (int i=0; i<dof; i++)
1340 {
1341 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
1342 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
1343 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
1344 }
1345}
1346
1348 : PositiveFiniteElement(3, Geometry::PYRAMID,
1349 ((p + 1)*(p + 2)*(2 * p + 3))/6, p,
1350 FunctionSpace::Uk),
1351 nterms(((p + 1)*(p + 2)*(p + 3)*(p + 4))/24)
1352{
1353#ifndef MFEM_THREAD_SAFE
1357#endif
1358
1359 Index idx;
1360
1361 // vertices
1362 dof_map[idx(p,0,0,0,0)] = 0;
1363 Nodes.IntPoint(0).Set3(0., 0., 0.);
1364 dof_map[idx(0,p,0,0,0)] = 1;
1365 Nodes.IntPoint(1).Set3(1., 0., 0.);
1366 dof_map[idx(0,0,p,0,0)] = 2;
1367 Nodes.IntPoint(2).Set3(1., 1., 0.);
1368 dof_map[idx(0,0,0,p,0)] = 3;
1369 Nodes.IntPoint(3).Set3(0., 1., 0.);
1370 dof_map[idx(0,0,0,0,p)] = 4;
1371 Nodes.IntPoint(4).Set3(0., 0., 1.);
1372
1373 // edges (see Geometry::Constants<Geometry::PYRAMID>::Edges
1374 // in fem/geom.cpp)
1375 int o = 5;
1376 for (int i = 1; i < p; i++) // (0,1)
1377 {
1378 dof_map[idx(p-i,i,0,0,0)] = o;
1379 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., 0.);
1380 }
1381 for (int i = 1; i < p; i++) // (1,2)
1382 {
1383 dof_map[idx(0,p-i,i,0,0)] = o;
1384 Nodes.IntPoint(o++).Set3(1.0, real_t(i)/p, 0.);
1385 }
1386 for (int i = 1; i < p; i++) // (3,2)
1387 {
1388 dof_map[idx(0,0,i,p-i,0)] = o;
1389 Nodes.IntPoint(o++).Set3(real_t(i)/p, 1., 0.);
1390 }
1391 for (int i = 1; i < p; i++) // (0,3)
1392 {
1393 dof_map[idx(p-i,0,0,i,0)] = o;
1394 Nodes.IntPoint(o++).Set3(0., real_t(i)/p, 0.);
1395 }
1396 for (int i = 1; i < p; i++) // (0,4)
1397 {
1398 dof_map[idx(p-i,0,0,0,i)] = o;
1399 Nodes.IntPoint(o++).Set3(0., 0., real_t(i)/p);
1400 }
1401 for (int i = 1; i < p; i++) // (1,4)
1402 {
1403 dof_map[idx(0,p-i,0,0,i)] = o;
1404 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, 0., real_t(i)/p);
1405 }
1406 for (int i = 1; i < p; i++) // (2,4)
1407 {
1408 dof_map[idx(0,0,p-i,0,i)] = o;
1409 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, real_t(p-i)/p, real_t(i)/p);
1410 }
1411 for (int i = 1; i < p; i++) // (3,4)
1412 {
1413 dof_map[idx(0,0,0,p-i,i)] = o;
1414 Nodes.IntPoint(o++).Set3(0., real_t(p-i)/p, real_t(i)/p);
1415 }
1416
1417 // faces (see Geometry::Constants<Geometry::PYRAMID>::FaceVert
1418 // in fem/geom.cpp)
1419 for (int j = 1; j < p; j++)
1420 {
1421 int i1 = j;
1422 int i2 = 0;
1423 int i3 = 0;
1424 int i4 = p - j;
1425 const int i5 = 0;
1426
1427 for (int i = 1; i <= p - j; i++) // (3,2,1,0)
1428 {
1429 i3++;
1430 i4--;
1431 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1432 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(p-j)/p, 0);
1433 }
1434 for (int i = p - j + 1; i < p; i++) // (3,2,1,0)
1435 {
1436 i1--;
1437 i2++;
1438 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1439 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(p-j)/p, 0);
1440 }
1441 }
1442 for (int j = 1; j < p; j++)
1443 for (int i = 1; i + j < p; i++) // (0, 1, 4)
1444 {
1445 dof_map[idx(p-i-j,i,0,0,j)] = o;
1446 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., real_t(j)/p);
1447 }
1448 for (int j = 1; j < p; j++)
1449 for (int i = 1; i + j < p; i++) // (1, 2, 4)
1450 {
1451 dof_map[idx(0,p-i-j,i,0,j)] = o;
1452 Nodes.IntPoint(o++).Set3(real_t(p-j)/p, real_t(i)/p, real_t(j)/p);
1453 }
1454 for (int j = 1; j < p; j++)
1455 for (int i = 1; i + j < p; i++) // (2, 3, 4)
1456 {
1457 dof_map[idx(0,0,p-i-j,i,j)] = o;
1458 Nodes.IntPoint(o++).Set3(real_t(p-i-j)/p, real_t(p-j)/p, real_t(j)/p);
1459 }
1460 for (int j = 1; j < p; j++)
1461 for (int i = 1; i + j < p; i++) // (3, 0, 4)
1462 {
1463 dof_map[idx(i,0,0,p-i-j,j)] = o;
1464 Nodes.IntPoint(o++).Set3(0., real_t(p-i-j)/p, real_t(j)/p);
1465 }
1466
1467 // interior
1468 for (int k = 1; k < p; k++)
1469 for (int j = 1; j + k < p; j++)
1470 {
1471 int i1 = p - j - k;
1472 int i2 = 0;
1473 int i3 = 0;
1474 int i4 = j;
1475 const int i5 = k;
1476
1477 for (int i = 1; i <= j; i++)
1478 {
1479 i3++;
1480 i4--;
1481 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1482 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
1483 }
1484 for (int i = j + 1; i + k < p; i++)
1485 {
1486 i1--;
1487 i2++;
1488 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1489 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
1490 }
1491 }
1492}
1493
1494// static method
1496 const real_t y, const real_t z,
1497 real_t *shape_1d,
1498 real_t *shape)
1499{
1500 const int lshape = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
1501 for (int i=0; i<lshape; i++) { shape[i] = 0.0; }
1502
1503 const real_t l1 = lam1(x, y, z);
1504 const real_t l2 = lam2(x, y, z);
1505 const real_t l3 = lam3(x, y, z);
1506 const real_t l4 = lam4(x, y, z);
1507 const real_t l5 = lam5(x, y, z);
1508
1509 // The basis functions are the terms in the expansion:
1510 // (l1 + l2 + l3 + l4 + l5)^p =
1511 // \sum_{l=0}^p \binom{p}{l} l5^l
1512 // \sum_{k=0}^{p-l} \binom{p-l}{k} l4^k
1513 // \sum_{j=0}^{p-l-k} \binom{p-l-k}{j} l3^j
1514 // \sum_{i=0}^{p-l-k-j} \binom{p-l-k-j}{i} l2^i l1^{p-l-k-j-i}
1515 Index idx;
1516 const int *bp = Poly_1D::Binom(p);
1517 real_t l5i5 = 1.;
1518 for (int i5 = 0; i5 <= p; i5++)
1519 {
1520 const int *bpi5 = Poly_1D::Binom(p - i5);
1521 const real_t ei5 = bp[i5]*l5i5;
1522 real_t l4i4 = 1.;
1523 for (int i4 = 0; i4 <= p - i5; i4++)
1524 {
1525 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1526 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1527 real_t l3i3 = 1.;
1528 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1529 {
1530 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, shape_1d);
1531 real_t ei345 = ei45*bpi45[i3]*l3i3;
1532 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1533 {
1534 const int i1 = p - i5 - i4 - i3 - i2;
1535 const int o = idx(i1,i2,i3,i4,i5);
1536 shape_1d[i2] *= ei345;
1537 shape[o] += shape_1d[i2];
1538 }
1539 l3i3 *= l3;
1540 }
1541 l4i4 *= l4;
1542 }
1543 l5i5 *= l5;
1544 }
1545}
1546
1547// static method
1549 const real_t y, const real_t z,
1550 real_t *dshape_1d, real_t *dshape)
1551{
1552 const int nterms = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
1553 for (int i=0; i<3*nterms; i++) { dshape[i] = 0.0; }
1554
1555 const real_t l1 = lam1(x, y, z);
1556 const real_t l2 = lam2(x, y, z);
1557 const real_t l3 = lam3(x, y, z);
1558 const real_t l4 = lam4(x, y, z);
1559 const real_t l5 = lam5(x, y, z);
1560
1561 const Vector dl1 = grad_lam1(x, y, z);
1562 const Vector dl2 = grad_lam2(x, y, z);
1563 const Vector dl3 = grad_lam3(x, y, z);
1564 const Vector dl4 = grad_lam4(x, y, z);
1565 const Vector dl5 = grad_lam5(x, y, z);
1566
1567 // The basis functions are the terms in the expansion:
1568 // (l1 + l2 + l3 + l4 + l5)^p
1569 // We will compute the derivative by first computing the derivatives
1570 // of these terms w.r.t each of the l1, l2, l3, l4, and l5 and summing
1571 // the results together.
1572 Index idx;
1573
1574 // Derivative w.r.t. l1 times grad(l1)
1575 const int *bp = Poly_1D::Binom(p);
1576 real_t l5i5 = 1.;
1577 for (int i5 = 0; i5 <= p; i5++)
1578 {
1579 const int *bpi5 = Poly_1D::Binom(p - i5);
1580 const real_t ei5 = bp[i5]*l5i5;
1581 real_t l4i4 = 1.;
1582 for (int i4 = 0; i4 <= p - i5; i4++)
1583 {
1584 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1585 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1586 real_t l3i3 = 1.;
1587 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1588 {
1589 Poly_1D::CalcDyBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1590 real_t ei345 = ei45*bpi45[i3]*l3i3;
1591 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1592 {
1593 const int i1 = p - i5 - i4 - i3 - i2;
1594 const int o = idx(i1,i2,i3,i4,i5);
1595 const real_t dshape_dl1 = dshape_1d[i2]*ei345;
1596 for (int d = 0; d < 3; d++)
1597 {
1598 dshape[o + d * nterms] += dshape_dl1 * dl1[d];
1599 }
1600 }
1601 l3i3 *= l3;
1602 }
1603 l4i4 *= l4;
1604 }
1605 l5i5 *= l5;
1606 }
1607
1608 // Derivative w.r.t. l2 times grad(l2)
1609 l5i5 = 1.;
1610 for (int i5 = 0; i5 <= p; i5++)
1611 {
1612 const int *bpi5 = Poly_1D::Binom(p - i5);
1613 const real_t ei5 = bp[i5]*l5i5;
1614 real_t l4i4 = 1.;
1615 for (int i4 = 0; i4 <= p - i5; i4++)
1616 {
1617 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1618 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1619 real_t l3i3 = 1.;
1620 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1621 {
1622 Poly_1D::CalcDxBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1623 real_t ei345 = ei45*bpi45[i3]*l3i3;
1624 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1625 {
1626 const int i1 = p - i5 - i4 - i3 - i2;
1627 const int o = idx(i1,i2,i3,i4,i5);
1628 const real_t dshape_dl2 = dshape_1d[i2]*ei345;
1629 for (int d = 0; d < 3; d++)
1630 {
1631 dshape[o + d * nterms] += dshape_dl2*dl2[d];
1632 }
1633 }
1634 l3i3 *= l3;
1635 }
1636 l4i4 *= l4;
1637 }
1638 l5i5 *= l5;
1639 }
1640
1641 // Derivative w.r.t. l3 times grad(l3)
1642 l5i5 = 1.;
1643 for (int i5 = 0; i5 <= p; i5++)
1644 {
1645 const int *bpi5 = Poly_1D::Binom(p - i5);
1646 const real_t ei5 = bp[i5]*l5i5;
1647 real_t l4i4 = 1.;
1648 for (int i4 = 0; i4 <= p - i5; i4++)
1649 {
1650 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1651 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1652 real_t l3i3 = 1.;
1653 for (int i3 = 1; i3 <= p - i5 - i4; i3++)
1654 {
1655 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1656 real_t ei345 = i3*ei45*bpi45[i3]*l3i3;
1657 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1658 {
1659 const int i1 = p - i5 - i4 - i3 - i2;
1660 const int o = idx(i1,i2,i3,i4,i5);
1661 const real_t dshape_dl3 = dshape_1d[i2]*ei345;
1662 for (int d = 0; d < 3; d++)
1663 {
1664 dshape[o + d * nterms] += dshape_dl3*dl3[d];
1665 }
1666 }
1667 l3i3 *= l3;
1668 }
1669 l4i4 *= l4;
1670 }
1671 l5i5 *= l5;
1672 }
1673
1674 // Derivative w.r.t. l4 times grad(l4)
1675 l5i5 = 1.;
1676 for (int i5 = 0; i5 <= p; i5++)
1677 {
1678 const int *bpi5 = Poly_1D::Binom(p - i5);
1679 const real_t ei5 = bp[i5]*l5i5;
1680 real_t l4i4 = 1.;
1681 for (int i4 = 1; i4 <= p - i5; i4++)
1682 {
1683 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1684 const real_t ei45 = i4*ei5*bpi5[i4]*l4i4;
1685 real_t l3i3 = 1.;
1686 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1687 {
1688 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1689 real_t ei345 = ei45*bpi45[i3]*l3i3;
1690 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1691 {
1692 const int i1 = p - i5 - i4 - i3 - i2;
1693 const int o = idx(i1,i2,i3,i4,i5);
1694 const real_t dshape_dl4 = dshape_1d[i2]*ei345;
1695 for (int d = 0; d < 3; d++)
1696 {
1697 dshape[o + d * nterms] += dshape_dl4*dl4[d];
1698 }
1699 }
1700 l3i3 *= l3;
1701 }
1702 l4i4 *= l4;
1703 }
1704 l5i5 *= l5;
1705 }
1706
1707 // Derivative w.r.t. l5 times grad(l5)
1708 l5i5 = 1.;
1709 for (int i5 = 1; i5 <= p; i5++)
1710 {
1711 const int *bpi5 = Poly_1D::Binom(p - i5);
1712 const real_t ei5 = i5*bp[i5]*l5i5;
1713 real_t l4i4 = 1.;
1714 for (int i4 = 0; i4 <= p - i5; i4++)
1715 {
1716 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1717 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1718 real_t l3i3 = 1.;
1719 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1720 {
1721 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1722 real_t ei345 = ei45*bpi45[i3]*l3i3;
1723 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1724 {
1725 const int i1 = p - i5 - i4 - i3 - i2;
1726 const int o = idx(i1,i2,i3,i4,i5);
1727 const real_t dshape_dl5 = dshape_1d[i2]*ei345;
1728 for (int d = 0; d < 3; d++)
1729 {
1730 dshape[o + d * nterms] += dshape_dl5*dl5[d];
1731 }
1732 }
1733 l3i3 *= l3;
1734 }
1735 l4i4 *= l4;
1736 }
1737 l5i5 *= l5;
1738 }
1739}
1740
1742 Vector &shape) const
1743{
1744#ifdef MFEM_THREAD_SAFE
1745 Vector m_shape_1d(order + 1);
1747#endif
1748
1749 CalcShape(order, ip.x, ip.y, ip.z, m_shape_1d.GetData(), m_shape.GetData());
1750
1751 for (auto const& it : dof_map)
1752 {
1753 if (it.first < m_shape.Size()) { shape[it.second] = m_shape[it.first]; }
1754 }
1755}
1756
1758 DenseMatrix &dshape) const
1759{
1760#ifdef MFEM_THREAD_SAFE
1761 Vector m_shape_1d(order + 1);
1763#endif
1764
1765 CalcDShape(order, ip.x, ip.y, ip.z,
1767
1768 for (auto const& it : dof_map)
1769 for (int d=0; d<3; d++)
1770 {
1771 dshape(it.second, d) = m_dshape(it.first, d);
1772 }
1773
1774}
1775
1777 : PositiveTensorFiniteElement(1, p, L2_DOF_MAP)
1778{
1779#ifndef MFEM_THREAD_SAFE
1780 shape_x.SetSize(p + 1);
1781 dshape_x.SetDataAndSize(NULL, p + 1);
1782#endif
1783
1784 if (p == 0)
1785 {
1786 Nodes.IntPoint(0).x = 0.5;
1787 }
1788 else
1789 {
1790 for (int i = 0; i <= p; i++)
1791 {
1792 Nodes.IntPoint(i).x = real_t(i)/p;
1793 }
1794 }
1795}
1796
1798 Vector &shape) const
1799{
1800 Poly_1D::CalcBernstein(order, ip.x, shape);
1801}
1802
1804 DenseMatrix &dshape) const
1805{
1806#ifdef MFEM_THREAD_SAFE
1807 Vector shape_x(dof), dshape_x(dshape.Data(), dof);
1808#else
1809 dshape_x.SetData(dshape.Data());
1810#endif
1811 Poly_1D::CalcBernstein(order, ip.x, shape_x, dshape_x);
1812}
1813
1814void L2Pos_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
1815{
1816 dofs = 0.0;
1817 dofs[vertex*order] = 1.0;
1818}
1819
1820
1822 : PositiveTensorFiniteElement(2, p, L2_DOF_MAP)
1823{
1824#ifndef MFEM_THREAD_SAFE
1825 shape_x.SetSize(p + 1);
1826 shape_y.SetSize(p + 1);
1827 dshape_x.SetSize(p + 1);
1828 dshape_y.SetSize(p + 1);
1829#endif
1830
1831 if (p == 0)
1832 {
1833 Nodes.IntPoint(0).Set2(0.5, 0.5);
1834 }
1835 else
1836 {
1837 for (int o = 0, j = 0; j <= p; j++)
1838 for (int i = 0; i <= p; i++)
1839 {
1840 Nodes.IntPoint(o++).Set2(real_t(i)/p, real_t(j)/p);
1841 }
1842 }
1843}
1844
1846 Vector &shape) const
1847{
1848 const int p = order;
1849
1850#ifdef MFEM_THREAD_SAFE
1851 Vector shape_x(p+1), shape_y(p+1);
1852#endif
1853
1854 Poly_1D::CalcBernstein(p, ip.x, shape_x);
1855 Poly_1D::CalcBernstein(p, ip.y, shape_y);
1856
1857 for (int o = 0, j = 0; j <= p; j++)
1858 for (int i = 0; i <= p; i++)
1859 {
1860 shape(o++) = shape_x(i)*shape_y(j);
1861 }
1862}
1863
1865 DenseMatrix &dshape) const
1866{
1867 const int p = order;
1868
1869#ifdef MFEM_THREAD_SAFE
1870 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
1871#endif
1872
1873 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
1874 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
1875
1876 for (int o = 0, j = 0; j <= p; j++)
1877 for (int i = 0; i <= p; i++)
1878 {
1879 dshape(o,0) = dshape_x(i)* shape_y(j);
1880 dshape(o,1) = shape_x(i)*dshape_y(j); o++;
1881 }
1882}
1883
1885{
1886 const int p = order;
1887
1888 dofs = 0.0;
1889 switch (vertex)
1890 {
1891 case 0: dofs[0] = 1.0; break;
1892 case 1: dofs[p] = 1.0; break;
1893 case 2: dofs[p*(p + 2)] = 1.0; break;
1894 case 3: dofs[p*(p + 1)] = 1.0; break;
1895 }
1896}
1897
1898
1900 : PositiveTensorFiniteElement(3, p, L2_DOF_MAP)
1901{
1902#ifndef MFEM_THREAD_SAFE
1903 shape_x.SetSize(p + 1);
1904 shape_y.SetSize(p + 1);
1905 shape_z.SetSize(p + 1);
1906 dshape_x.SetSize(p + 1);
1907 dshape_y.SetSize(p + 1);
1908 dshape_z.SetSize(p + 1);
1909#endif
1910
1911 if (p == 0)
1912 {
1913 Nodes.IntPoint(0).Set3(0.5, 0.5, 0.5);
1914 }
1915 else
1916 {
1917 for (int o = 0, k = 0; k <= p; k++)
1918 for (int j = 0; j <= p; j++)
1919 for (int i = 0; i <= p; i++)
1920 {
1921 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, real_t(k)/p);
1922 }
1923 }
1924}
1925
1927 Vector &shape) const
1928{
1929 const int p = order;
1930
1931#ifdef MFEM_THREAD_SAFE
1932 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
1933#endif
1934
1935 Poly_1D::CalcBernstein(p, ip.x, shape_x);
1936 Poly_1D::CalcBernstein(p, ip.y, shape_y);
1937 Poly_1D::CalcBernstein(p, ip.z, shape_z);
1938
1939 for (int o = 0, k = 0; k <= p; k++)
1940 for (int j = 0; j <= p; j++)
1941 for (int i = 0; i <= p; i++)
1942 {
1943 shape(o++) = shape_x(i)*shape_y(j)*shape_z(k);
1944 }
1945}
1946
1948 DenseMatrix &dshape) const
1949{
1950 const int p = order;
1951
1952#ifdef MFEM_THREAD_SAFE
1953 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
1954 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
1955#endif
1956
1957 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
1958 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
1959 Poly_1D::CalcBernstein(p, ip.z, shape_z, dshape_z);
1960
1961 for (int o = 0, k = 0; k <= p; k++)
1962 for (int j = 0; j <= p; j++)
1963 for (int i = 0; i <= p; i++)
1964 {
1965 dshape(o,0) = dshape_x(i)* shape_y(j)* shape_z(k);
1966 dshape(o,1) = shape_x(i)*dshape_y(j)* shape_z(k);
1967 dshape(o,2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
1968 }
1969}
1970
1972{
1973 const int p = order;
1974
1975 dofs = 0.0;
1976 switch (vertex)
1977 {
1978 case 0: dofs[0] = 1.0; break;
1979 case 1: dofs[p] = 1.0; break;
1980 case 2: dofs[p*(p + 2)] = 1.0; break;
1981 case 3: dofs[p*(p + 1)] = 1.0; break;
1982 case 4: dofs[p*(p + 1)*(p + 1)] = 1.0; break;
1983 case 5: dofs[p + p*(p + 1)*(p + 1)] = 1.0; break;
1984 case 6: dofs[dof - 1] = 1.0; break;
1985 case 7: dofs[dof - p - 1] = 1.0; break;
1986 }
1987}
1988
1989
1991 : PositiveFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
1992 FunctionSpace::Pk)
1993{
1994#ifndef MFEM_THREAD_SAFE
1995 dshape_1d.SetSize(p + 1);
1996#endif
1997
1998 if (p == 0)
1999 {
2000 Nodes.IntPoint(0).Set2(1./3, 1./3);
2001 }
2002 else
2003 {
2004 for (int o = 0, j = 0; j <= p; j++)
2005 for (int i = 0; i + j <= p; i++)
2006 {
2007 Nodes.IntPoint(o++).Set2(real_t(i)/p, real_t(j)/p);
2008 }
2009 }
2010}
2011
2013 Vector &shape) const
2014{
2016}
2017
2019 DenseMatrix &dshape) const
2020{
2021#ifdef MFEM_THREAD_SAFE
2022 Vector dshape_1d(order + 1);
2023#endif
2024
2025 H1Pos_TriangleElement::CalcDShape(order, ip.x, ip.y, dshape_1d.GetData(),
2026 dshape.Data());
2027}
2028
2029void L2Pos_TriangleElement::ProjectDelta(int vertex, Vector &dofs) const
2030{
2031 dofs = 0.0;
2032 switch (vertex)
2033 {
2034 case 0: dofs[0] = 1.0; break;
2035 case 1: dofs[order] = 1.0; break;
2036 case 2: dofs[dof-1] = 1.0; break;
2037 }
2038}
2039
2040
2042 : PositiveFiniteElement(3, Geometry::TETRAHEDRON,
2043 ((p + 1)*(p + 2)*(p + 3))/6, p, FunctionSpace::Pk)
2044{
2045#ifndef MFEM_THREAD_SAFE
2046 dshape_1d.SetSize(p + 1);
2047#endif
2048
2049 if (p == 0)
2050 {
2051 Nodes.IntPoint(0).Set3(0.25, 0.25, 0.25);
2052 }
2053 else
2054 {
2055 for (int o = 0, k = 0; k <= p; k++)
2056 for (int j = 0; j + k <= p; j++)
2057 for (int i = 0; i + j + k <= p; i++)
2058 {
2059 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, real_t(k)/p);
2060 }
2061 }
2062}
2063
2065 Vector &shape) const
2066{
2068 shape.GetData());
2069}
2070
2072 DenseMatrix &dshape) const
2073{
2074#ifdef MFEM_THREAD_SAFE
2075 Vector dshape_1d(order + 1);
2076#endif
2077
2079 dshape_1d.GetData(), dshape.Data());
2080}
2081
2083{
2084 dofs = 0.0;
2085 switch (vertex)
2086 {
2087 case 0: dofs[0] = 1.0; break;
2088 case 1: dofs[order] = 1.0; break;
2089 case 2: dofs[(order*(order+3))/2] = 1.0; break;
2090 case 3: dofs[dof-1] = 1.0; break;
2091 }
2092}
2093
2094
2096 : PositiveFiniteElement(3, Geometry::PRISM,
2097 ((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
2098 TriangleFE(p),
2099 SegmentFE(p)
2100{
2101#ifndef MFEM_THREAD_SAFE
2106#endif
2107
2108 t_dof.SetSize(dof);
2109 s_dof.SetSize(dof);
2110
2111 // Interior DoFs
2112 int m=0;
2113 for (int k=0; k<=p; k++)
2114 {
2115 int l=0;
2116 for (int j=0; j<=p; j++)
2117 {
2118 for (int i=0; i<=j; i++)
2119 {
2120 t_dof[m] = l;
2121 s_dof[m] = k;
2122 l++; m++;
2123 }
2124 }
2125 }
2126
2127 // Define Nodes
2128 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
2129 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
2130 for (int i=0; i<dof; i++)
2131 {
2132 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
2133 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
2134 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
2135 }
2136}
2137
2139 Vector &shape) const
2140{
2141#ifdef MFEM_THREAD_SAFE
2144#endif
2145
2146 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
2147
2150
2151 for (int i=0; i<dof; i++)
2152 {
2153 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
2154 }
2155}
2156
2158 DenseMatrix &dshape) const
2159{
2160#ifdef MFEM_THREAD_SAFE
2165#endif
2166
2167 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
2168
2173
2174 for (int i=0; i<dof; i++)
2175 {
2176 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
2177 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
2178 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
2179 }
2180}
2181
2183 : PositiveFiniteElement(3, Geometry::PYRAMID,
2184 ((p + 1)*(p + 2)*(2 * p + 3))/6, p,
2185 FunctionSpace::Uk),
2186 nterms(((p + 1)*(p + 2)*(p + 3)*(p + 4))/24)
2187{
2188#ifndef MFEM_THREAD_SAFE
2192#endif
2193
2194 Index idx;
2195
2196 if (p == 0)
2197 {
2198 dof_map[idx(0,0,0,0,0)] = 0;
2199 Nodes.IntPoint(0).Set3(0.375, 0.375, 0.25);
2200 }
2201 else
2202 {
2203 for (int o = 0, k = 0; k <= p; k++)
2204 for (int j = 0; j + k <= p; j++)
2205 {
2206 int i1 = p - j - k;
2207 int i2 = 0;
2208 int i3 = -1;
2209 int i4 = j + 1;
2210 const int i5 = k;
2211
2212 for (int i = 0; i <= j; i++)
2213 {
2214 i3++;
2215 i4--;
2216 dof_map[idx(i1,i2,i3,i4,i5)] = o;
2217 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
2218 }
2219 for (int i = j + 1; i + k <= p; i++)
2220 {
2221 i1--;
2222 i2++;
2223 dof_map[idx(i1,i2,i3,i4,i5)] = o;
2224 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
2225 }
2226 }
2227 }
2228}
2229
2230// static method
2232 const real_t y, const real_t z,
2233 real_t *shape_1d,
2234 real_t *shape)
2235{
2236 const int lshape = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
2237 for (int i=0; i<lshape; i++) { shape[i] = 0.0; }
2238
2239 const real_t l1 = lam1(x, y, z);
2240 const real_t l2 = lam2(x, y, z);
2241 const real_t l3 = lam3(x, y, z);
2242 const real_t l4 = lam4(x, y, z);
2243 const real_t l5 = lam5(x, y, z);
2244
2245 // The basis functions are the terms in the expansion:
2246 // (l1 + l2 + l3 + l4 + l5)^p =
2247 // \sum_{l=0}^p \binom{p}{l} l5^l
2248 // \sum_{k=0}^{p-l} \binom{p-l}{k} l4^k
2249 // \sum_{j=0}^{p-l-k} \binom{p-l-k}{j} l3^j
2250 // \sum_{i=0}^{p-l-k-j} \binom{p-l-k-j}{i} l2^i l1^{p-l-k-j-i}
2251 Index idx;
2252 const int *bp = Poly_1D::Binom(p);
2253 real_t l5i5 = 1.;
2254 for (int i5 = 0; i5 <= p; i5++)
2255 {
2256 const int *bpi5 = Poly_1D::Binom(p - i5);
2257 const real_t ei5 = bp[i5]*l5i5;
2258 real_t l4i4 = 1.;
2259 for (int i4 = 0; i4 <= p - i5; i4++)
2260 {
2261 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2262 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2263 real_t l3i3 = 1.;
2264 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2265 {
2266 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, shape_1d);
2267 real_t ei345 = ei45*bpi45[i3]*l3i3;
2268 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2269 {
2270 const int i1 = p - i5 - i4 - i3 - i2;
2271 const int o = idx(i1,i2,i3,i4,i5);
2272 shape_1d[i2] *= ei345;
2273 shape[o] += shape_1d[i2];
2274 }
2275 l3i3 *= l3;
2276 }
2277 l4i4 *= l4;
2278 }
2279 l5i5 *= l5;
2280 }
2281}
2282
2283// static method
2285 const real_t y, const real_t z,
2286 real_t *dshape_1d, real_t *dshape)
2287{
2288 const int nterms = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
2289 for (int i=0; i<3*nterms; i++) { dshape[i] = 0.0; }
2290
2291 const real_t l1 = lam1(x, y, z);
2292 const real_t l2 = lam2(x, y, z);
2293 const real_t l3 = lam3(x, y, z);
2294 const real_t l4 = lam4(x, y, z);
2295 const real_t l5 = lam5(x, y, z);
2296
2297 const Vector dl1 = grad_lam1(x, y, z);
2298 const Vector dl2 = grad_lam2(x, y, z);
2299 const Vector dl3 = grad_lam3(x, y, z);
2300 const Vector dl4 = grad_lam4(x, y, z);
2301 const Vector dl5 = grad_lam5(x, y, z);
2302
2303 // The basis functions are the terms in the expansion:
2304 // (l1 + l2 + l3 + l4 + l5)^p
2305 // We will compute the derivative by first computing the derivatives
2306 // of these terms w.r.t each of the l1, l2, l3, l4, and l5 and summing
2307 // the results together.
2308 Index idx;
2309
2310 // Derivative w.r.t. l1 times grad(l1)
2311 const int *bp = Poly_1D::Binom(p);
2312 real_t l5i5 = 1.;
2313 for (int i5 = 0; i5 <= p; i5++)
2314 {
2315 const int *bpi5 = Poly_1D::Binom(p - i5);
2316 const real_t ei5 = bp[i5]*l5i5;
2317 real_t l4i4 = 1.;
2318 for (int i4 = 0; i4 <= p - i5; i4++)
2319 {
2320 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2321 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2322 real_t l3i3 = 1.;
2323 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2324 {
2325 Poly_1D::CalcDyBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2326 real_t ei345 = ei45*bpi45[i3]*l3i3;
2327 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2328 {
2329 const int i1 = p - i5 - i4 - i3 - i2;
2330 const int o = idx(i1,i2,i3,i4,i5);
2331 const real_t dshape_dl1 = dshape_1d[i2]*ei345;
2332 for (int d = 0; d < 3; d++)
2333 {
2334 dshape[o + d * nterms] += dshape_dl1 * dl1[d];
2335 }
2336 }
2337 l3i3 *= l3;
2338 }
2339 l4i4 *= l4;
2340 }
2341 l5i5 *= l5;
2342 }
2343
2344 // Derivative w.r.t. l2 times grad(l2)
2345 l5i5 = 1.;
2346 for (int i5 = 0; i5 <= p; i5++)
2347 {
2348 const int *bpi5 = Poly_1D::Binom(p - i5);
2349 const real_t ei5 = bp[i5]*l5i5;
2350 real_t l4i4 = 1.;
2351 for (int i4 = 0; i4 <= p - i5; i4++)
2352 {
2353 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2354 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2355 real_t l3i3 = 1.;
2356 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2357 {
2358 Poly_1D::CalcDxBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2359 real_t ei345 = ei45*bpi45[i3]*l3i3;
2360 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2361 {
2362 const int i1 = p - i5 - i4 - i3 - i2;
2363 const int o = idx(i1,i2,i3,i4,i5);
2364 const real_t dshape_dl2 = dshape_1d[i2]*ei345;
2365 for (int d = 0; d < 3; d++)
2366 {
2367 dshape[o + d * nterms] += dshape_dl2*dl2[d];
2368 }
2369 }
2370 l3i3 *= l3;
2371 }
2372 l4i4 *= l4;
2373 }
2374 l5i5 *= l5;
2375 }
2376
2377 // Derivative w.r.t. l3 times grad(l3)
2378 l5i5 = 1.;
2379 for (int i5 = 0; i5 <= p; i5++)
2380 {
2381 const int *bpi5 = Poly_1D::Binom(p - i5);
2382 const real_t ei5 = bp[i5]*l5i5;
2383 real_t l4i4 = 1.;
2384 for (int i4 = 0; i4 <= p - i5; i4++)
2385 {
2386 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2387 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2388 real_t l3i3 = 1.;
2389 for (int i3 = 1; i3 <= p - i5 - i4; i3++)
2390 {
2391 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2392 real_t ei345 = i3*ei45*bpi45[i3]*l3i3;
2393 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2394 {
2395 const int i1 = p - i5 - i4 - i3 - i2;
2396 const int o = idx(i1,i2,i3,i4,i5);
2397 const real_t dshape_dl3 = dshape_1d[i2]*ei345;
2398 for (int d = 0; d < 3; d++)
2399 {
2400 dshape[o + d * nterms] += dshape_dl3*dl3[d];
2401 }
2402 }
2403 l3i3 *= l3;
2404 }
2405 l4i4 *= l4;
2406 }
2407 l5i5 *= l5;
2408 }
2409
2410 // Derivative w.r.t. l4 times grad(l4)
2411 l5i5 = 1.;
2412 for (int i5 = 0; i5 <= p; i5++)
2413 {
2414 const int *bpi5 = Poly_1D::Binom(p - i5);
2415 const real_t ei5 = bp[i5]*l5i5;
2416 real_t l4i4 = 1.;
2417 for (int i4 = 1; i4 <= p - i5; i4++)
2418 {
2419 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2420 const real_t ei45 = i4*ei5*bpi5[i4]*l4i4;
2421 real_t l3i3 = 1.;
2422 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2423 {
2424 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2425 real_t ei345 = ei45*bpi45[i3]*l3i3;
2426 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2427 {
2428 const int i1 = p - i5 - i4 - i3 - i2;
2429 const int o = idx(i1,i2,i3,i4,i5);
2430 const real_t dshape_dl4 = dshape_1d[i2]*ei345;
2431 for (int d = 0; d < 3; d++)
2432 {
2433 dshape[o + d * nterms] += dshape_dl4*dl4[d];
2434 }
2435 }
2436 l3i3 *= l3;
2437 }
2438 l4i4 *= l4;
2439 }
2440 l5i5 *= l5;
2441 }
2442
2443 // Derivative w.r.t. l5 times grad(l5)
2444 l5i5 = 1.;
2445 for (int i5 = 1; i5 <= p; i5++)
2446 {
2447 const int *bpi5 = Poly_1D::Binom(p - i5);
2448 const real_t ei5 = i5*bp[i5]*l5i5;
2449 real_t l4i4 = 1.;
2450 for (int i4 = 0; i4 <= p - i5; i4++)
2451 {
2452 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2453 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2454 real_t l3i3 = 1.;
2455 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2456 {
2457 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2458 real_t ei345 = ei45*bpi45[i3]*l3i3;
2459 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2460 {
2461 const int i1 = p - i5 - i4 - i3 - i2;
2462 const int o = idx(i1,i2,i3,i4,i5);
2463 const real_t dshape_dl5 = dshape_1d[i2]*ei345;
2464 for (int d = 0; d < 3; d++)
2465 {
2466 dshape[o + d * nterms] += dshape_dl5*dl5[d];
2467 }
2468 }
2469 l3i3 *= l3;
2470 }
2471 l4i4 *= l4;
2472 }
2473 l5i5 *= l5;
2474 }
2475}
2476
2478 Vector &shape) const
2479{
2480#ifdef MFEM_THREAD_SAFE
2481 Vector m_shape_1d(order + 1);
2483#endif
2484
2485 CalcShape(order, ip.x, ip.y, ip.z, m_shape_1d.GetData(), m_shape.GetData());
2486
2487 for (auto const& it : dof_map)
2488 {
2489 if (it.first < m_shape.Size()) { shape[it.second] = m_shape[it.first]; }
2490 }
2491}
2492
2494 DenseMatrix &dshape) const
2495{
2496#ifdef MFEM_THREAD_SAFE
2497 Vector m_shape_1d(order + 1);
2499#endif
2500
2501 CalcDShape(order, ip.x, ip.y, ip.z,
2503
2504 for (auto const& it : dof_map)
2505 for (int d=0; d<3; d++)
2506 {
2507 dshape(it.second, d) = m_dshape(it.first, d);
2508 }
2509}
2510
2511}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:941
Possible basis types. Note that not all elements can use all BasisType(s).
Definition fe_base.hpp:30
BiQuadPos2DFiniteElement()
Construct the BiQuadPos2DFiniteElement.
Definition fe_pos.cpp:95
void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const override
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
Definition fe_pos.cpp:220
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:118
void GetLocalInterpolation(ElementTransformation &Trans, DenseMatrix &I) const override
Return the local interpolation matrix I (Dof x Dof) where the fine element is the image of the base g...
Definition fe_pos.cpp:191
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:142
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication with the inverse of dense matrix.
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
real_t * Data() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:131
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 Invert()
Replaces the current matrix with its inverse.
Definition densemat.cpp:674
Structure representing the matrices/tensors needed to evaluate (in reference space) the values,...
Definition fe_base.hpp:141
Mode mode
Describes the contents of the B, Bt, G, and Gt arrays, see Mode.
Definition fe_base.hpp:182
const IntegrationRule * IntRule
IntegrationRule that defines the quadrature points at which the basis functions of the FE are evaluat...
Definition fe_base.hpp:150
Mode
Type of data stored in the arrays B, Bt, G, and Gt.
Definition fe_base.hpp:154
@ RAGGED_TENSOR
Ragged tensor product representation using 1D matrices/tensors with dimensions using 1D number of qua...
Definition fe_base.hpp:178
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:186
const class FiniteElement * FE
The FiniteElement that created and owns this object.
Definition fe_base.hpp:145
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:190
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
virtual void Transform(const IntegrationPoint &, Vector &)=0
Transform integration point from reference coordinates to physical coordinates and store them in the ...
Abstract class for all finite elements.
Definition fe_base.hpp:294
int dof
Number of degrees of freedom.
Definition fe_base.hpp:303
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:414
IntegrationRule Nodes
Definition fe_base.hpp:306
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:381
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:476
Array< DofToQuad * > dof2quad_array
Container for all DofToQuad objects created by the FiniteElement.
Definition fe_base.hpp:313
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:410
int order
Order/degree of the shape functions.
Definition fe_base.hpp:304
int dim
Dimension of reference space.
Definition fe_base.hpp:296
static real_t lam4(real_t x, real_t y, real_t z)
static Vector grad_lam5(real_t x, real_t y, real_t z)
static real_t lam3(real_t x, real_t y, real_t z)
static Vector grad_lam4(real_t x, real_t y, real_t z)
static real_t lam2(real_t x, real_t y, real_t z)
static real_t lam1(real_t x, real_t y, real_t z)
Pyramid "Affine" Coordinates.
static real_t lam5(real_t x, real_t y, real_t z)
static Vector grad_lam1(real_t x, real_t y, real_t z)
Gradients of the "Affine" Coordinates.
static Vector grad_lam2(real_t x, real_t y, real_t z)
static Vector grad_lam3(real_t x, real_t y, real_t z)
Describes the function space on each element.
Definition fe_base.hpp:276
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:475
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:454
H1Pos_HexahedronElement(const int p)
Construct the H1Pos_HexahedronElement of order p.
Definition fe_pos.cpp:432
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:499
H1Pos_PyramidElement(const int p)
Construct the H1Pos_PyramidElement of order p.
Definition fe_pos.cpp:1347
static void CalcShape(const int p, const real_t x, const real_t y, const real_t z, real_t *shape_1d, real_t *shape)
Definition fe_pos.cpp:1495
static void CalcDShape(const int p, const real_t x, const real_t y, const real_t z, real_t *dshape_1d, real_t *dshape)
Definition fe_pos.cpp:1548
std::map< int, int > dof_map
Definition fe_pos.hpp:307
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:384
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:425
H1Pos_QuadrilateralElement(const int p)
Construct the H1Pos_QuadrilateralElement of order p.
Definition fe_pos.cpp:364
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:404
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:337
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:317
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:357
H1Pos_SegmentElement(const int p)
Construct the H1Pos_SegmentElement of order p.
Definition fe_pos.cpp:299
static const DofToQuad & GetRaggedTensorDofToQuad(const FiniteElement &fe, const IntegrationRule &ir, DofToQuad::Mode mode, Array< DofToQuad * > &dof2quad_array)
Definition fe_pos.cpp:847
H1Pos_TetrahedronElement(const int p)
Construct the H1Pos_TetrahedronElement of order p.
Definition fe_pos.cpp:746
static void CalcShape(const int p, const real_t x, const real_t y, const real_t z, real_t *shape)
Definition fe_pos.cpp:1055
static void CalcDShape(const int p, const real_t x, const real_t y, const real_t z, real_t *dshape_1d, real_t *dshape)
Definition fe_pos.cpp:1088
H1Pos_TriangleElement(const int p)
Construct the H1Pos_TriangleElement of order p.
Definition fe_pos.cpp:506
static void CalcDShape(const int p, const real_t x, const real_t y, real_t *dshape_1d, real_t *dshape)
Definition fe_pos.cpp:682
static const DofToQuad & GetRaggedTensorDofToQuad(const FiniteElement &fe, const IntegrationRule &ir, DofToQuad::Mode mode, Array< DofToQuad * > &dof2quad_array)
Definition fe_pos.cpp:560
static void CalcShape(const int p, const real_t x, const real_t y, real_t *shape)
Definition fe_pos.cpp:656
H1Pos_TriangleElement TriangleFE
Definition fe_pos.hpp:277
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:1322
H1Pos_SegmentElement SegmentFE
Definition fe_pos.hpp:278
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:1303
H1Pos_WedgeElement(const int p)
Construct the H1Pos_WedgeElement of order p.
Definition fe_pos.cpp:1205
Class for integration point with weight.
Definition intrules.hpp:35
void Set2(const real_t x1, const real_t x2)
Definition intrules.hpp:59
void Set3(const real_t x1, const real_t x2, const real_t x3)
Definition intrules.hpp:57
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:258
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:1926
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:1971
L2Pos_HexahedronElement(const int p)
Construct the L2Pos_HexahedronElement of order p.
Definition fe_pos.cpp:1899
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:1947
static void CalcDShape(const int p, const real_t x, const real_t y, const real_t z, real_t *dshape_1d, real_t *dshape)
Definition fe_pos.cpp:2284
std::map< int, int > dof_map
Definition fe_pos.hpp:476
static void CalcShape(const int p, const real_t x, const real_t y, const real_t z, real_t *shape_1d, real_t *shape)
Definition fe_pos.cpp:2231
L2Pos_PyramidElement(const int p)
Construct the L2Pos_PyramidElement of order p.
Definition fe_pos.cpp:2182
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:1845
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:1884
L2Pos_QuadrilateralElement(const int p)
Construct the L2Pos_QuadrilateralElement of order p.
Definition fe_pos.cpp:1821
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:1864
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:1797
L2Pos_SegmentElement(const int p)
Construct the L2Pos_SegmentElement of order p.
Definition fe_pos.cpp:1776
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:1803
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:1814
L2Pos_TetrahedronElement(const int p)
Construct the L2Pos_TetrahedronElement of order p.
Definition fe_pos.cpp:2041
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:2082
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:2064
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:2071
L2Pos_TriangleElement(const int p)
Construct the L2Pos_TriangleElement of order p.
Definition fe_pos.cpp:1990
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:2012
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:2018
void ProjectDelta(int vertex, Vector &dofs) const override
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition fe_pos.cpp:2029
L2Pos_TriangleElement TriangleFE
Definition fe_pos.hpp:454
L2Pos_WedgeElement(const int p)
Construct the L2Pos_WedgeElement of order p.
Definition fe_pos.cpp:2095
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:2157
L2Pos_SegmentElement SegmentFE
Definition fe_pos.hpp:455
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:2138
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
Class for standard nodal finite elements.
Definition fe_base.hpp:798
void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const override
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
Definition fe_base.cpp:816
static void CalcDBinomTerms(const int p, const real_t x, const real_t y, real_t *d)
Compute the derivatives (w.r.t. x) of the terms in the expansion of the binomial (x + y)^p assuming t...
Definition fe_base.cpp:2255
static const int * Binom(const int p)
Get a pointer to an array containing the binomial coefficients "pchoose k" for k=0,...
Definition fe_base.cpp:2142
static void CalcDyBinomTerms(const int p, const real_t x, const real_t y, real_t *d)
Compute the derivatives (w.r.t. y) of the terms in the expansion of the binomial (x + y)^p....
Definition fe_base.cpp:2314
static void CalcBernstein(const int p, const real_t x, real_t *u)
Compute the values of the Bernstein basis functions of order p at coordinate x and store the results ...
Definition fe_base.hpp:1295
static void CalcBinomTerms(const int p, const real_t x, const real_t y, real_t *u)
Compute the p terms in the expansion of the binomial (x + y)^p and store them in the already allocate...
Definition fe_base.cpp:2191
static void CalcDxBinomTerms(const int p, const real_t x, const real_t y, real_t *d)
Compute the derivatives (w.r.t. x) of the terms in the expansion of the binomial (x + y)^p....
Definition fe_base.cpp:2285
Class for finite elements utilizing the always positive Bernstein basis.
Definition fe_pos.hpp:24
void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const override
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
Definition fe_pos.cpp:25
PositiveTensorFiniteElement(const int dims, const int p, const DofMapType dmtype)
Definition fe_pos.cpp:81
void GetFaceMap(const int face_id, Array< int > &face_map) const override
Return the mapping from lexicographic face DOFs to lexicographic element DOFs for the given local fac...
Definition fe_pos.cpp:88
void CalcShape(const IntegrationPoint &ip, Vector &shape) const override
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
Definition fe_pos.cpp:278
QuadPos1DFiniteElement()
Construct the QuadPos1DFiniteElement.
Definition fe_pos.cpp:270
void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const override
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Definition fe_pos.cpp:288
Structure representing the matrices/tensors needed to evaluate (in reference space) the values,...
Definition fe_base.hpp:247
Array< real_t > Ba3t
Definition fe_base.hpp:254
Array< int > inverse_map2d_mass
Definition fe_base.hpp:271
Array< real_t > Ga2
Definition fe_base.hpp:260
Array< int > forward_map3d_mass
Definition fe_base.hpp:270
Array< real_t > Ba1
Special basis function structures for positive (Bernstein) basis with partial assembly....
Definition fe_base.hpp:253
Array< int > inverse_map3d_mass
Definition fe_base.hpp:271
Array< real_t > Ba2
Definition fe_base.hpp:253
Array< real_t > Ba3
Definition fe_base.hpp:253
Array< real_t > Ba1t
Definition fe_base.hpp:254
Array< real_t > Ga1
Special structures for gradients of positive basis with partial assembly. The gradient arrays exploit...
Definition fe_base.hpp:260
Array< real_t > Ga3t
Definition fe_base.hpp:261
Array< real_t > Ba2t
Definition fe_base.hpp:254
Array< int > forward_map2d_mass
Definition fe_base.hpp:270
Array< real_t > Ga1t
Definition fe_base.hpp:261
Array< int > inverse_map3d_diff
Definition fe_base.hpp:268
Array< int > forward_map3d_diff
Definition fe_base.hpp:267
Array< int > inverse_map2d_diff
Definition fe_base.hpp:268
Array< real_t > Ga3
Definition fe_base.hpp:260
Array< int > forward_map2d_diff
Definition fe_base.hpp:267
Array< int > lex_map
Mapping from the Bernstein multi-index (a_1, ..., a_d) to the lexicographic dof index.
Definition fe_base.hpp:265
Array< real_t > Ga2t
Definition fe_base.hpp:261
Base class for vector Coefficients that optionally depend on time and space.
int GetVDim()
Returns dimension of the vector.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Vector data type.
Definition vector.hpp:82
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
void SetData(real_t *d)
Definition vector.hpp:184
@ lshape
Definition ex25.cpp:152
Linear1DFiniteElement SegmentFE
Definition segment.cpp:52
float real_t
Definition config.hpp:46
MFEM_EXPORT Linear2DFiniteElement TriangleFE
Definition fe.cpp:32
STL namespace.
real_t p(const Vector &x, real_t t)