MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
fe_pos.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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
560// static method
562 const int p, const real_t l1, const real_t l2, real_t *shape)
563{
564 const real_t l3 = 1. - l1 - l2;
565
566 // The (i,j) basis function is given by: T(i,j,p-i-j) l1^i l2^j l3^{p-i-j},
567 // where T(i,j,k) = (i+j+k)! / (i! j! k!)
568 // Another expression is given by the terms of the expansion:
569 // (l1 + l2 + l3)^p =
570 // \sum_{j=0}^p \binom{p}{j} l2^j
571 // \sum_{i=0}^{p-j} \binom{p-j}{i} l1^i l3^{p-j-i}
572 const int *bp = Poly_1D::Binom(p);
573 real_t z = 1.;
574 for (int o = 0, j = 0; j <= p; j++)
575 {
576 Poly_1D::CalcBinomTerms(p - j, l1, l3, &shape[o]);
577 real_t s = bp[j]*z;
578 for (int i = 0; i <= p - j; i++)
579 {
580 shape[o++] *= s;
581 }
582 z *= l2;
583 }
584}
585
586// static method
588 const int p, const real_t l1, const real_t l2,
589 real_t *dshape_1d, real_t *dshape)
590{
591 const int dof = ((p + 1)*(p + 2))/2;
592 const real_t l3 = 1. - l1 - l2;
593
594 const int *bp = Poly_1D::Binom(p);
595 real_t z = 1.;
596 for (int o = 0, j = 0; j <= p; j++)
597 {
599 real_t s = bp[j]*z;
600 for (int i = 0; i <= p - j; i++)
601 {
602 dshape[o++] = s*dshape_1d[i];
603 }
604 z *= l2;
605 }
606 z = 1.;
607 for (int i = 0; i <= p; i++)
608 {
610 real_t s = bp[i]*z;
611 for (int o = i, j = 0; j <= p - i; j++)
612 {
613 dshape[dof + o] = s*dshape_1d[j];
614 o += p + 1 - j;
615 }
616 z *= l1;
617 }
618}
619
621 Vector &shape) const
622{
623#ifdef MFEM_THREAD_SAFE
625#endif
626 CalcShape(order, ip.x, ip.y, m_shape.GetData());
627 for (int i = 0; i < dof; i++)
628 {
629 shape(dof_map[i]) = m_shape(i);
630 }
631}
632
634 DenseMatrix &dshape) const
635{
636#ifdef MFEM_THREAD_SAFE
639#endif
641 for (int d = 0; d < 2; d++)
642 {
643 for (int i = 0; i < dof; i++)
644 {
645 dshape(dof_map[i],d) = m_dshape(i,d);
646 }
647 }
648}
649
650
652 : PositiveFiniteElement(3, Geometry::TETRAHEDRON,
653 ((p + 1)*(p + 2)*(p + 3))/6, p, FunctionSpace::Pk)
654{
655#ifndef MFEM_THREAD_SAFE
657 dshape_1d.SetSize(p + 1);
659#endif
661
662 struct Index
663 {
664 int p, dof;
665 int tri(int k) { return (k*(k + 1))/2; }
666 int tet(int k) { return (k*(k + 1)*(k + 2))/6; }
667 Index(int p_) { p = p_; dof = tet(p + 1); }
668 int operator()(int i, int j, int k)
669 { return dof - tet(p - k) - tri(p + 1 - k - j) + i; }
670 };
671 Index idx(p);
672
673 // vertices
674 dof_map[idx(0,0,0)] = 0;
675 Nodes.IntPoint(0).Set3(0., 0., 0.);
676 dof_map[idx(p,0,0)] = 1;
677 Nodes.IntPoint(1).Set3(1., 0., 0.);
678 dof_map[idx(0,p,0)] = 2;
679 Nodes.IntPoint(2).Set3(0., 1., 0.);
680 dof_map[idx(0,0,p)] = 3;
681 Nodes.IntPoint(3).Set3(0., 0., 1.);
682
683 // edges (see Tetrahedron::edges in mesh/tetrahedron.cpp)
684 int o = 4;
685 for (int i = 1; i < p; i++) // (0,1)
686 {
687 dof_map[idx(i,0,0)] = o;
688 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., 0.);
689 }
690 for (int i = 1; i < p; i++) // (0,2)
691 {
692 dof_map[idx(0,i,0)] = o;
693 Nodes.IntPoint(o++).Set3(0., real_t(i)/p, 0.);
694 }
695 for (int i = 1; i < p; i++) // (0,3)
696 {
697 dof_map[idx(0,0,i)] = o;
698 Nodes.IntPoint(o++).Set3(0., 0., real_t(i)/p);
699 }
700 for (int i = 1; i < p; i++) // (1,2)
701 {
702 dof_map[idx(p-i,i,0)] = o;
703 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, real_t(i)/p, 0.);
704 }
705 for (int i = 1; i < p; i++) // (1,3)
706 {
707 dof_map[idx(p-i,0,i)] = o;
708 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, 0., real_t(i)/p);
709 }
710 for (int i = 1; i < p; i++) // (2,3)
711 {
712 dof_map[idx(0,p-i,i)] = o;
713 Nodes.IntPoint(o++).Set3(0., real_t(p-i)/p, real_t(i)/p);
714 }
715
716 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
717 for (int j = 1; j < p; j++)
718 for (int i = 1; i + j < p; i++) // (1,2,3)
719 {
720 dof_map[idx(p-i-j,i,j)] = o;
721 Nodes.IntPoint(o++).Set3(real_t(p-i-j)/p, real_t(i)/p, real_t(j)/p);
722 }
723 for (int j = 1; j < p; j++)
724 for (int i = 1; i + j < p; i++) // (0,3,2)
725 {
726 dof_map[idx(0,j,i)] = o;
727 Nodes.IntPoint(o++).Set3(0., real_t(j)/p, real_t(i)/p);
728 }
729 for (int j = 1; j < p; j++)
730 for (int i = 1; i + j < p; i++) // (0,1,3)
731 {
732 dof_map[idx(i,0,j)] = o;
733 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., real_t(j)/p);
734 }
735 for (int j = 1; j < p; j++)
736 for (int i = 1; i + j < p; i++) // (0,2,1)
737 {
738 dof_map[idx(j,i,0)] = o;
739 Nodes.IntPoint(o++).Set3(real_t(j)/p, real_t(i)/p, 0.);
740 }
741
742 // interior
743 for (int k = 1; k < p; k++)
744 for (int j = 1; j + k < p; j++)
745 for (int i = 1; i + j + k < p; i++)
746 {
747 dof_map[idx(i,j,k)] = o;
748 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, real_t(k)/p);
749 }
750}
751
752// static method
754 const int p, const real_t l1, const real_t l2, const real_t l3,
755 real_t *shape)
756{
757 const real_t l4 = 1. - l1 - l2 - l3;
758
759 // The basis functions are the terms in the expansion:
760 // (l1 + l2 + l3 + l4)^p =
761 // \sum_{k=0}^p \binom{p}{k} l3^k
762 // \sum_{j=0}^{p-k} \binom{p-k}{j} l2^j
763 // \sum_{i=0}^{p-k-j} \binom{p-k-j}{i} l1^i l4^{p-k-j-i}
764 const int *bp = Poly_1D::Binom(p);
765 real_t l3k = 1.;
766 for (int o = 0, k = 0; k <= p; k++)
767 {
768 const int *bpk = Poly_1D::Binom(p - k);
769 const real_t ek = bp[k]*l3k;
770 real_t l2j = 1.;
771 for (int j = 0; j <= p - k; j++)
772 {
773 Poly_1D::CalcBinomTerms(p - k - j, l1, l4, &shape[o]);
774 real_t ekj = ek*bpk[j]*l2j;
775 for (int i = 0; i <= p - k - j; i++)
776 {
777 shape[o++] *= ekj;
778 }
779 l2j *= l2;
780 }
781 l3k *= l3;
782 }
783}
784
785// static method
787 const int p, const real_t l1, const real_t l2, const real_t l3,
788 real_t *dshape_1d, real_t *dshape)
789{
790 const int dof = ((p + 1)*(p + 2)*(p + 3))/6;
791 const real_t l4 = 1. - l1 - l2 - l3;
792
793 // For the x derivatives, differentiate the terms of the expression:
794 // \sum_{k=0}^p \binom{p}{k} l3^k
795 // \sum_{j=0}^{p-k} \binom{p-k}{j} l2^j
796 // \sum_{i=0}^{p-k-j} \binom{p-k-j}{i} l1^i l4^{p-k-j-i}
797 const int *bp = Poly_1D::Binom(p);
798 real_t l3k = 1.;
799 for (int o = 0, k = 0; k <= p; k++)
800 {
801 const int *bpk = Poly_1D::Binom(p - k);
802 const real_t ek = bp[k]*l3k;
803 real_t l2j = 1.;
804 for (int j = 0; j <= p - k; j++)
805 {
806 Poly_1D::CalcDBinomTerms(p - k - j, l1, l4, dshape_1d);
807 real_t ekj = ek*bpk[j]*l2j;
808 for (int i = 0; i <= p - k - j; i++)
809 {
810 dshape[o++] = dshape_1d[i]*ekj;
811 }
812 l2j *= l2;
813 }
814 l3k *= l3;
815 }
816 // For the y derivatives, differentiate the terms of the expression:
817 // \sum_{k=0}^p \binom{p}{k} l3^k
818 // \sum_{i=0}^{p-k} \binom{p-k}{i} l1^i
819 // \sum_{j=0}^{p-k-i} \binom{p-k-i}{j} l2^j l4^{p-k-j-i}
820 l3k = 1.;
821 for (int ok = 0, k = 0; k <= p; k++)
822 {
823 const int *bpk = Poly_1D::Binom(p - k);
824 const real_t ek = bp[k]*l3k;
825 real_t l1i = 1.;
826 for (int i = 0; i <= p - k; i++)
827 {
828 Poly_1D::CalcDBinomTerms(p - k - i, l2, l4, dshape_1d);
829 real_t eki = ek*bpk[i]*l1i;
830 int o = ok + i;
831 for (int j = 0; j <= p - k - i; j++)
832 {
833 dshape[dof + o] = dshape_1d[j]*eki;
834 o += p - k - j + 1;
835 }
836 l1i *= l1;
837 }
838 l3k *= l3;
839 ok += ((p - k + 2)*(p - k + 1))/2;
840 }
841 // For the z derivatives, differentiate the terms of the expression:
842 // \sum_{j=0}^p \binom{p}{j} l2^j
843 // \sum_{i=0}^{p-j} \binom{p-j}{i} l1^i
844 // \sum_{k=0}^{p-j-i} \binom{p-j-i}{k} l3^k l4^{p-k-j-i}
845 real_t l2j = 1.;
846 for (int j = 0; j <= p; j++)
847 {
848 const int *bpj = Poly_1D::Binom(p - j);
849 const real_t ej = bp[j]*l2j;
850 real_t l1i = 1.;
851 for (int i = 0; i <= p - j; i++)
852 {
853 Poly_1D::CalcDBinomTerms(p - j - i, l3, l4, dshape_1d);
854 real_t eji = ej*bpj[i]*l1i;
855 int m = ((p + 2)*(p + 1))/2;
856 int n = ((p - j + 2)*(p - j + 1))/2;
857 for (int o = i, k = 0; k <= p - j - i; k++)
858 {
859 // m = ((p - k + 2)*(p - k + 1))/2;
860 // n = ((p - k - j + 2)*(p - k - j + 1))/2;
861 o += m;
862 dshape[2*dof + o - n] = dshape_1d[k]*eji;
863 m -= p - k + 1;
864 n -= p - k - j + 1;
865 }
866 l1i *= l1;
867 }
868 l2j *= l2;
869 }
870}
871
873 Vector &shape) const
874{
875#ifdef MFEM_THREAD_SAFE
877#endif
878 CalcShape(order, ip.x, ip.y, ip.z, m_shape.GetData());
879 for (int i = 0; i < dof; i++)
880 {
881 shape(dof_map[i]) = m_shape(i);
882 }
883}
884
886 DenseMatrix &dshape) const
887{
888#ifdef MFEM_THREAD_SAFE
891#endif
892 CalcDShape(order, ip.x, ip.y, ip.z, dshape_1d.GetData(), m_dshape.Data());
893 for (int d = 0; d < 3; d++)
894 {
895 for (int i = 0; i < dof; i++)
896 {
897 dshape(dof_map[i],d) = m_dshape(i,d);
898 }
899 }
900}
901
902
905 ((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
906 TriangleFE(p),
907 SegmentFE(p)
908{
909#ifndef MFEM_THREAD_SAFE
914#endif
915
918
919 // Nodal DoFs
920 t_dof[0] = 0; s_dof[0] = 0;
921 t_dof[1] = 1; s_dof[1] = 0;
922 t_dof[2] = 2; s_dof[2] = 0;
923 t_dof[3] = 0; s_dof[3] = 1;
924 t_dof[4] = 1; s_dof[4] = 1;
925 t_dof[5] = 2; s_dof[5] = 1;
926
927 // Edge DoFs
928 int ne = p-1;
929 for (int i=1; i<p; i++)
930 {
931 t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
932 t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
933 t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
934 t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
935 t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
936 t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
937 t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
938 t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
939 t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
940 }
941
942 // Triangular Face DoFs
943 int k=0;
944 int nt = (p-1)*(p-2)/2;
945 for (int j=1; j<p; j++)
946 {
947 for (int i=1; i<j; i++)
948 {
949 t_dof[6 + 9 * ne + k] = 3 * p + k; s_dof[6 + 9 * ne + k] = 0;
950 t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
951 k++;
952 }
953 }
954
955 // Quadrilateral Face DoFs
956 k=0;
957 int nq = (p-1)*(p-1);
958 for (int j=1; j<p; j++)
959 {
960 for (int i=1; i<p; i++)
961 {
962 t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
963 t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
964 t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
965
966 s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
967 s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
968 s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
969
970 k++;
971 }
972 }
973
974 // Interior DoFs
975 int m=0;
976 for (k=1; k<p; k++)
977 {
978 int l=0;
979 for (int j=1; j<p; j++)
980 {
981 for (int i=1; i<j; i++)
982 {
983 t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
984 s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
985 l++; m++;
986 }
987 }
988 }
989
990 // Define Nodes
991 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
992 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
993 for (int i=0; i<dof; i++)
994 {
995 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
996 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
997 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
998 }
999}
1000
1002 Vector &shape) const
1003{
1004#ifdef MFEM_THREAD_SAFE
1007#endif
1008
1009 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1010
1013
1014 for (int i=0; i<dof; i++)
1015 {
1016 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
1017 }
1018}
1019
1021 DenseMatrix &dshape) const
1022{
1023#ifdef MFEM_THREAD_SAFE
1028#endif
1029
1030 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1031
1036
1037 for (int i=0; i<dof; i++)
1038 {
1039 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
1040 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
1041 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
1042 }
1043}
1044
1046 : PositiveFiniteElement(3, Geometry::PYRAMID,
1047 ((p + 1)*(p + 2)*(2 * p + 3))/6, p,
1048 FunctionSpace::Uk),
1049 nterms(((p + 1)*(p + 2)*(p + 3)*(p + 4))/24)
1050{
1051#ifndef MFEM_THREAD_SAFE
1055#endif
1056
1057 Index idx;
1058
1059 // vertices
1060 dof_map[idx(p,0,0,0,0)] = 0;
1061 Nodes.IntPoint(0).Set3(0., 0., 0.);
1062 dof_map[idx(0,p,0,0,0)] = 1;
1063 Nodes.IntPoint(1).Set3(1., 0., 0.);
1064 dof_map[idx(0,0,p,0,0)] = 2;
1065 Nodes.IntPoint(2).Set3(1., 1., 0.);
1066 dof_map[idx(0,0,0,p,0)] = 3;
1067 Nodes.IntPoint(3).Set3(0., 1., 0.);
1068 dof_map[idx(0,0,0,0,p)] = 4;
1069 Nodes.IntPoint(4).Set3(0., 0., 1.);
1070
1071 // edges (see Geometry::Constants<Geometry::PYRAMID>::Edges
1072 // in fem/geom.cpp)
1073 int o = 5;
1074 for (int i = 1; i < p; i++) // (0,1)
1075 {
1076 dof_map[idx(p-i,i,0,0,0)] = o;
1077 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., 0.);
1078 }
1079 for (int i = 1; i < p; i++) // (1,2)
1080 {
1081 dof_map[idx(0,p-i,i,0,0)] = o;
1082 Nodes.IntPoint(o++).Set3(1.0, real_t(i)/p, 0.);
1083 }
1084 for (int i = 1; i < p; i++) // (3,2)
1085 {
1086 dof_map[idx(0,0,i,p-i,0)] = o;
1087 Nodes.IntPoint(o++).Set3(real_t(i)/p, 1., 0.);
1088 }
1089 for (int i = 1; i < p; i++) // (0,3)
1090 {
1091 dof_map[idx(p-i,0,0,i,0)] = o;
1092 Nodes.IntPoint(o++).Set3(0., real_t(i)/p, 0.);
1093 }
1094 for (int i = 1; i < p; i++) // (0,4)
1095 {
1096 dof_map[idx(p-i,0,0,0,i)] = o;
1097 Nodes.IntPoint(o++).Set3(0., 0., real_t(i)/p);
1098 }
1099 for (int i = 1; i < p; i++) // (1,4)
1100 {
1101 dof_map[idx(0,p-i,0,0,i)] = o;
1102 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, 0., real_t(i)/p);
1103 }
1104 for (int i = 1; i < p; i++) // (2,4)
1105 {
1106 dof_map[idx(0,0,p-i,0,i)] = o;
1107 Nodes.IntPoint(o++).Set3(real_t(p-i)/p, real_t(p-i)/p, real_t(i)/p);
1108 }
1109 for (int i = 1; i < p; i++) // (3,4)
1110 {
1111 dof_map[idx(0,0,0,p-i,i)] = o;
1112 Nodes.IntPoint(o++).Set3(0., real_t(p-i)/p, real_t(i)/p);
1113 }
1114
1115 // faces (see Geometry::Constants<Geometry::PYRAMID>::FaceVert
1116 // in fem/geom.cpp)
1117 for (int j = 1; j < p; j++)
1118 {
1119 int i1 = j;
1120 int i2 = 0;
1121 int i3 = 0;
1122 int i4 = p - j;
1123 const int i5 = 0;
1124
1125 for (int i = 1; i <= p - j; i++) // (3,2,1,0)
1126 {
1127 i3++;
1128 i4--;
1129 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1130 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(p-j)/p, 0);
1131 }
1132 for (int i = p - j + 1; i < p; i++) // (3,2,1,0)
1133 {
1134 i1--;
1135 i2++;
1136 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1137 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(p-j)/p, 0);
1138 }
1139 }
1140 for (int j = 1; j < p; j++)
1141 for (int i = 1; i + j < p; i++) // (0, 1, 4)
1142 {
1143 dof_map[idx(p-i-j,i,0,0,j)] = o;
1144 Nodes.IntPoint(o++).Set3(real_t(i)/p, 0., real_t(j)/p);
1145 }
1146 for (int j = 1; j < p; j++)
1147 for (int i = 1; i + j < p; i++) // (1, 2, 4)
1148 {
1149 dof_map[idx(0,p-i-j,i,0,j)] = o;
1150 Nodes.IntPoint(o++).Set3(real_t(p-j)/p, real_t(i)/p, real_t(j)/p);
1151 }
1152 for (int j = 1; j < p; j++)
1153 for (int i = 1; i + j < p; i++) // (2, 3, 4)
1154 {
1155 dof_map[idx(0,0,p-i-j,i,j)] = o;
1156 Nodes.IntPoint(o++).Set3(real_t(p-i-j)/p, real_t(p-j)/p, real_t(j)/p);
1157 }
1158 for (int j = 1; j < p; j++)
1159 for (int i = 1; i + j < p; i++) // (3, 0, 4)
1160 {
1161 dof_map[idx(i,0,0,p-i-j,j)] = o;
1162 Nodes.IntPoint(o++).Set3(0., real_t(p-i-j)/p, real_t(j)/p);
1163 }
1164
1165 // interior
1166 for (int k = 1; k < p; k++)
1167 for (int j = 1; j + k < p; j++)
1168 {
1169 int i1 = p - j - k;
1170 int i2 = 0;
1171 int i3 = 0;
1172 int i4 = j;
1173 const int i5 = k;
1174
1175 for (int i = 1; i <= j; i++)
1176 {
1177 i3++;
1178 i4--;
1179 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1180 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
1181 }
1182 for (int i = j + 1; i + k < p; i++)
1183 {
1184 i1--;
1185 i2++;
1186 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1187 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
1188 }
1189 }
1190}
1191
1192// static method
1194 const real_t y, const real_t z,
1195 real_t *shape_1d,
1196 real_t *shape)
1197{
1198 const int lshape = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
1199 for (int i=0; i<lshape; i++) { shape[i] = 0.0; }
1200
1201 const real_t l1 = lam1(x, y, z);
1202 const real_t l2 = lam2(x, y, z);
1203 const real_t l3 = lam3(x, y, z);
1204 const real_t l4 = lam4(x, y, z);
1205 const real_t l5 = lam5(x, y, z);
1206
1207 // The basis functions are the terms in the expansion:
1208 // (l1 + l2 + l3 + l4 + l5)^p =
1209 // \sum_{l=0}^p \binom{p}{l} l5^l
1210 // \sum_{k=0}^{p-l} \binom{p-l}{k} l4^k
1211 // \sum_{j=0}^{p-l-k} \binom{p-l-k}{j} l3^j
1212 // \sum_{i=0}^{p-l-k-j} \binom{p-l-k-j}{i} l2^i l1^{p-l-k-j-i}
1213 Index idx;
1214 const int *bp = Poly_1D::Binom(p);
1215 real_t l5i5 = 1.;
1216 for (int i5 = 0; i5 <= p; i5++)
1217 {
1218 const int *bpi5 = Poly_1D::Binom(p - i5);
1219 const real_t ei5 = bp[i5]*l5i5;
1220 real_t l4i4 = 1.;
1221 for (int i4 = 0; i4 <= p - i5; i4++)
1222 {
1223 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1224 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1225 real_t l3i3 = 1.;
1226 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1227 {
1228 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, shape_1d);
1229 real_t ei345 = ei45*bpi45[i3]*l3i3;
1230 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1231 {
1232 const int i1 = p - i5 - i4 - i3 - i2;
1233 const int o = idx(i1,i2,i3,i4,i5);
1234 shape_1d[i2] *= ei345;
1235 shape[o] += shape_1d[i2];
1236 }
1237 l3i3 *= l3;
1238 }
1239 l4i4 *= l4;
1240 }
1241 l5i5 *= l5;
1242 }
1243}
1244
1245// static method
1247 const real_t y, const real_t z,
1248 real_t *dshape_1d, real_t *dshape)
1249{
1250 const int nterms = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
1251 for (int i=0; i<3*nterms; i++) { dshape[i] = 0.0; }
1252
1253 const real_t l1 = lam1(x, y, z);
1254 const real_t l2 = lam2(x, y, z);
1255 const real_t l3 = lam3(x, y, z);
1256 const real_t l4 = lam4(x, y, z);
1257 const real_t l5 = lam5(x, y, z);
1258
1259 const Vector dl1 = grad_lam1(x, y, z);
1260 const Vector dl2 = grad_lam2(x, y, z);
1261 const Vector dl3 = grad_lam3(x, y, z);
1262 const Vector dl4 = grad_lam4(x, y, z);
1263 const Vector dl5 = grad_lam5(x, y, z);
1264
1265 // The basis functions are the terms in the expansion:
1266 // (l1 + l2 + l3 + l4 + l5)^p
1267 // We will compute the derivative by first computing the derivatives
1268 // of these terms w.r.t each of the l1, l2, l3, l4, and l5 and summing
1269 // the results together.
1270 Index idx;
1271
1272 // Derivative w.r.t. l1 times grad(l1)
1273 const int *bp = Poly_1D::Binom(p);
1274 real_t l5i5 = 1.;
1275 for (int i5 = 0; i5 <= p; i5++)
1276 {
1277 const int *bpi5 = Poly_1D::Binom(p - i5);
1278 const real_t ei5 = bp[i5]*l5i5;
1279 real_t l4i4 = 1.;
1280 for (int i4 = 0; i4 <= p - i5; i4++)
1281 {
1282 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1283 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1284 real_t l3i3 = 1.;
1285 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1286 {
1287 Poly_1D::CalcDyBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1288 real_t ei345 = ei45*bpi45[i3]*l3i3;
1289 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1290 {
1291 const int i1 = p - i5 - i4 - i3 - i2;
1292 const int o = idx(i1,i2,i3,i4,i5);
1293 const real_t dshape_dl1 = dshape_1d[i2]*ei345;
1294 for (int d = 0; d < 3; d++)
1295 {
1296 dshape[o + d * nterms] += dshape_dl1 * dl1[d];
1297 }
1298 }
1299 l3i3 *= l3;
1300 }
1301 l4i4 *= l4;
1302 }
1303 l5i5 *= l5;
1304 }
1305
1306 // Derivative w.r.t. l2 times grad(l2)
1307 l5i5 = 1.;
1308 for (int i5 = 0; i5 <= p; i5++)
1309 {
1310 const int *bpi5 = Poly_1D::Binom(p - i5);
1311 const real_t ei5 = bp[i5]*l5i5;
1312 real_t l4i4 = 1.;
1313 for (int i4 = 0; i4 <= p - i5; i4++)
1314 {
1315 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1316 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1317 real_t l3i3 = 1.;
1318 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1319 {
1320 Poly_1D::CalcDxBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1321 real_t ei345 = ei45*bpi45[i3]*l3i3;
1322 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1323 {
1324 const int i1 = p - i5 - i4 - i3 - i2;
1325 const int o = idx(i1,i2,i3,i4,i5);
1326 const real_t dshape_dl2 = dshape_1d[i2]*ei345;
1327 for (int d = 0; d < 3; d++)
1328 {
1329 dshape[o + d * nterms] += dshape_dl2*dl2[d];
1330 }
1331 }
1332 l3i3 *= l3;
1333 }
1334 l4i4 *= l4;
1335 }
1336 l5i5 *= l5;
1337 }
1338
1339 // Derivative w.r.t. l3 times grad(l3)
1340 l5i5 = 1.;
1341 for (int i5 = 0; i5 <= p; i5++)
1342 {
1343 const int *bpi5 = Poly_1D::Binom(p - i5);
1344 const real_t ei5 = bp[i5]*l5i5;
1345 real_t l4i4 = 1.;
1346 for (int i4 = 0; i4 <= p - i5; i4++)
1347 {
1348 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1349 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1350 real_t l3i3 = 1.;
1351 for (int i3 = 1; i3 <= p - i5 - i4; i3++)
1352 {
1353 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1354 real_t ei345 = i3*ei45*bpi45[i3]*l3i3;
1355 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1356 {
1357 const int i1 = p - i5 - i4 - i3 - i2;
1358 const int o = idx(i1,i2,i3,i4,i5);
1359 const real_t dshape_dl3 = dshape_1d[i2]*ei345;
1360 for (int d = 0; d < 3; d++)
1361 {
1362 dshape[o + d * nterms] += dshape_dl3*dl3[d];
1363 }
1364 }
1365 l3i3 *= l3;
1366 }
1367 l4i4 *= l4;
1368 }
1369 l5i5 *= l5;
1370 }
1371
1372 // Derivative w.r.t. l4 times grad(l4)
1373 l5i5 = 1.;
1374 for (int i5 = 0; i5 <= p; i5++)
1375 {
1376 const int *bpi5 = Poly_1D::Binom(p - i5);
1377 const real_t ei5 = bp[i5]*l5i5;
1378 real_t l4i4 = 1.;
1379 for (int i4 = 1; i4 <= p - i5; i4++)
1380 {
1381 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1382 const real_t ei45 = i4*ei5*bpi5[i4]*l4i4;
1383 real_t l3i3 = 1.;
1384 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1385 {
1386 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1387 real_t ei345 = ei45*bpi45[i3]*l3i3;
1388 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1389 {
1390 const int i1 = p - i5 - i4 - i3 - i2;
1391 const int o = idx(i1,i2,i3,i4,i5);
1392 const real_t dshape_dl4 = dshape_1d[i2]*ei345;
1393 for (int d = 0; d < 3; d++)
1394 {
1395 dshape[o + d * nterms] += dshape_dl4*dl4[d];
1396 }
1397 }
1398 l3i3 *= l3;
1399 }
1400 l4i4 *= l4;
1401 }
1402 l5i5 *= l5;
1403 }
1404
1405 // Derivative w.r.t. l5 times grad(l5)
1406 l5i5 = 1.;
1407 for (int i5 = 1; i5 <= p; i5++)
1408 {
1409 const int *bpi5 = Poly_1D::Binom(p - i5);
1410 const real_t ei5 = i5*bp[i5]*l5i5;
1411 real_t l4i4 = 1.;
1412 for (int i4 = 0; i4 <= p - i5; i4++)
1413 {
1414 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1415 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1416 real_t l3i3 = 1.;
1417 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1418 {
1419 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
1420 real_t ei345 = ei45*bpi45[i3]*l3i3;
1421 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1422 {
1423 const int i1 = p - i5 - i4 - i3 - i2;
1424 const int o = idx(i1,i2,i3,i4,i5);
1425 const real_t dshape_dl5 = dshape_1d[i2]*ei345;
1426 for (int d = 0; d < 3; d++)
1427 {
1428 dshape[o + d * nterms] += dshape_dl5*dl5[d];
1429 }
1430 }
1431 l3i3 *= l3;
1432 }
1433 l4i4 *= l4;
1434 }
1435 l5i5 *= l5;
1436 }
1437}
1438
1440 Vector &shape) const
1441{
1442#ifdef MFEM_THREAD_SAFE
1443 Vector m_shape_1d(order + 1);
1445#endif
1446
1447 CalcShape(order, ip.x, ip.y, ip.z, m_shape_1d.GetData(), m_shape.GetData());
1448
1449 for (auto const& it : dof_map)
1450 {
1451 if (it.first < m_shape.Size()) { shape[it.second] = m_shape[it.first]; }
1452 }
1453}
1454
1456 DenseMatrix &dshape) const
1457{
1458#ifdef MFEM_THREAD_SAFE
1459 Vector m_shape_1d(order + 1);
1461#endif
1462
1463 CalcDShape(order, ip.x, ip.y, ip.z,
1465
1466 for (auto const& it : dof_map)
1467 for (int d=0; d<3; d++)
1468 {
1469 dshape(it.second, d) = m_dshape(it.first, d);
1470 }
1471
1472}
1473
1475 : PositiveTensorFiniteElement(1, p, L2_DOF_MAP)
1476{
1477#ifndef MFEM_THREAD_SAFE
1478 shape_x.SetSize(p + 1);
1479 dshape_x.SetDataAndSize(NULL, p + 1);
1480#endif
1481
1482 if (p == 0)
1483 {
1484 Nodes.IntPoint(0).x = 0.5;
1485 }
1486 else
1487 {
1488 for (int i = 0; i <= p; i++)
1489 {
1490 Nodes.IntPoint(i).x = real_t(i)/p;
1491 }
1492 }
1493}
1494
1496 Vector &shape) const
1497{
1498 Poly_1D::CalcBernstein(order, ip.x, shape);
1499}
1500
1502 DenseMatrix &dshape) const
1503{
1504#ifdef MFEM_THREAD_SAFE
1505 Vector shape_x(dof), dshape_x(dshape.Data(), dof);
1506#else
1507 dshape_x.SetData(dshape.Data());
1508#endif
1509 Poly_1D::CalcBernstein(order, ip.x, shape_x, dshape_x);
1510}
1511
1512void L2Pos_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
1513{
1514 dofs = 0.0;
1515 dofs[vertex*order] = 1.0;
1516}
1517
1518
1520 : PositiveTensorFiniteElement(2, p, L2_DOF_MAP)
1521{
1522#ifndef MFEM_THREAD_SAFE
1523 shape_x.SetSize(p + 1);
1524 shape_y.SetSize(p + 1);
1525 dshape_x.SetSize(p + 1);
1526 dshape_y.SetSize(p + 1);
1527#endif
1528
1529 if (p == 0)
1530 {
1531 Nodes.IntPoint(0).Set2(0.5, 0.5);
1532 }
1533 else
1534 {
1535 for (int o = 0, j = 0; j <= p; j++)
1536 for (int i = 0; i <= p; i++)
1537 {
1538 Nodes.IntPoint(o++).Set2(real_t(i)/p, real_t(j)/p);
1539 }
1540 }
1541}
1542
1544 Vector &shape) const
1545{
1546 const int p = order;
1547
1548#ifdef MFEM_THREAD_SAFE
1549 Vector shape_x(p+1), shape_y(p+1);
1550#endif
1551
1552 Poly_1D::CalcBernstein(p, ip.x, shape_x);
1553 Poly_1D::CalcBernstein(p, ip.y, shape_y);
1554
1555 for (int o = 0, j = 0; j <= p; j++)
1556 for (int i = 0; i <= p; i++)
1557 {
1558 shape(o++) = shape_x(i)*shape_y(j);
1559 }
1560}
1561
1563 DenseMatrix &dshape) const
1564{
1565 const int p = order;
1566
1567#ifdef MFEM_THREAD_SAFE
1568 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
1569#endif
1570
1571 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
1572 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
1573
1574 for (int o = 0, j = 0; j <= p; j++)
1575 for (int i = 0; i <= p; i++)
1576 {
1577 dshape(o,0) = dshape_x(i)* shape_y(j);
1578 dshape(o,1) = shape_x(i)*dshape_y(j); o++;
1579 }
1580}
1581
1583{
1584 const int p = order;
1585
1586 dofs = 0.0;
1587 switch (vertex)
1588 {
1589 case 0: dofs[0] = 1.0; break;
1590 case 1: dofs[p] = 1.0; break;
1591 case 2: dofs[p*(p + 2)] = 1.0; break;
1592 case 3: dofs[p*(p + 1)] = 1.0; break;
1593 }
1594}
1595
1596
1598 : PositiveTensorFiniteElement(3, p, L2_DOF_MAP)
1599{
1600#ifndef MFEM_THREAD_SAFE
1601 shape_x.SetSize(p + 1);
1602 shape_y.SetSize(p + 1);
1603 shape_z.SetSize(p + 1);
1604 dshape_x.SetSize(p + 1);
1605 dshape_y.SetSize(p + 1);
1606 dshape_z.SetSize(p + 1);
1607#endif
1608
1609 if (p == 0)
1610 {
1611 Nodes.IntPoint(0).Set3(0.5, 0.5, 0.5);
1612 }
1613 else
1614 {
1615 for (int o = 0, k = 0; k <= p; k++)
1616 for (int j = 0; j <= p; j++)
1617 for (int i = 0; i <= p; i++)
1618 {
1619 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, real_t(k)/p);
1620 }
1621 }
1622}
1623
1625 Vector &shape) const
1626{
1627 const int p = order;
1628
1629#ifdef MFEM_THREAD_SAFE
1630 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
1631#endif
1632
1633 Poly_1D::CalcBernstein(p, ip.x, shape_x);
1634 Poly_1D::CalcBernstein(p, ip.y, shape_y);
1635 Poly_1D::CalcBernstein(p, ip.z, shape_z);
1636
1637 for (int o = 0, k = 0; k <= p; k++)
1638 for (int j = 0; j <= p; j++)
1639 for (int i = 0; i <= p; i++)
1640 {
1641 shape(o++) = shape_x(i)*shape_y(j)*shape_z(k);
1642 }
1643}
1644
1646 DenseMatrix &dshape) const
1647{
1648 const int p = order;
1649
1650#ifdef MFEM_THREAD_SAFE
1651 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
1652 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
1653#endif
1654
1655 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
1656 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
1657 Poly_1D::CalcBernstein(p, ip.z, shape_z, dshape_z);
1658
1659 for (int o = 0, k = 0; k <= p; k++)
1660 for (int j = 0; j <= p; j++)
1661 for (int i = 0; i <= p; i++)
1662 {
1663 dshape(o,0) = dshape_x(i)* shape_y(j)* shape_z(k);
1664 dshape(o,1) = shape_x(i)*dshape_y(j)* shape_z(k);
1665 dshape(o,2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
1666 }
1667}
1668
1670{
1671 const int p = order;
1672
1673 dofs = 0.0;
1674 switch (vertex)
1675 {
1676 case 0: dofs[0] = 1.0; break;
1677 case 1: dofs[p] = 1.0; break;
1678 case 2: dofs[p*(p + 2)] = 1.0; break;
1679 case 3: dofs[p*(p + 1)] = 1.0; break;
1680 case 4: dofs[p*(p + 1)*(p + 1)] = 1.0; break;
1681 case 5: dofs[p + p*(p + 1)*(p + 1)] = 1.0; break;
1682 case 6: dofs[dof - 1] = 1.0; break;
1683 case 7: dofs[dof - p - 1] = 1.0; break;
1684 }
1685}
1686
1687
1689 : PositiveFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
1690 FunctionSpace::Pk)
1691{
1692#ifndef MFEM_THREAD_SAFE
1693 dshape_1d.SetSize(p + 1);
1694#endif
1695
1696 if (p == 0)
1697 {
1698 Nodes.IntPoint(0).Set2(1./3, 1./3);
1699 }
1700 else
1701 {
1702 for (int o = 0, j = 0; j <= p; j++)
1703 for (int i = 0; i + j <= p; i++)
1704 {
1705 Nodes.IntPoint(o++).Set2(real_t(i)/p, real_t(j)/p);
1706 }
1707 }
1708}
1709
1711 Vector &shape) const
1712{
1714}
1715
1717 DenseMatrix &dshape) const
1718{
1719#ifdef MFEM_THREAD_SAFE
1720 Vector dshape_1d(order + 1);
1721#endif
1722
1723 H1Pos_TriangleElement::CalcDShape(order, ip.x, ip.y, dshape_1d.GetData(),
1724 dshape.Data());
1725}
1726
1727void L2Pos_TriangleElement::ProjectDelta(int vertex, Vector &dofs) const
1728{
1729 dofs = 0.0;
1730 switch (vertex)
1731 {
1732 case 0: dofs[0] = 1.0; break;
1733 case 1: dofs[order] = 1.0; break;
1734 case 2: dofs[dof-1] = 1.0; break;
1735 }
1736}
1737
1738
1740 : PositiveFiniteElement(3, Geometry::TETRAHEDRON,
1741 ((p + 1)*(p + 2)*(p + 3))/6, p, FunctionSpace::Pk)
1742{
1743#ifndef MFEM_THREAD_SAFE
1744 dshape_1d.SetSize(p + 1);
1745#endif
1746
1747 if (p == 0)
1748 {
1749 Nodes.IntPoint(0).Set3(0.25, 0.25, 0.25);
1750 }
1751 else
1752 {
1753 for (int o = 0, k = 0; k <= p; k++)
1754 for (int j = 0; j + k <= p; j++)
1755 for (int i = 0; i + j + k <= p; i++)
1756 {
1757 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, real_t(k)/p);
1758 }
1759 }
1760}
1761
1763 Vector &shape) const
1764{
1766 shape.GetData());
1767}
1768
1770 DenseMatrix &dshape) const
1771{
1772#ifdef MFEM_THREAD_SAFE
1773 Vector dshape_1d(order + 1);
1774#endif
1775
1777 dshape_1d.GetData(), dshape.Data());
1778}
1779
1781{
1782 dofs = 0.0;
1783 switch (vertex)
1784 {
1785 case 0: dofs[0] = 1.0; break;
1786 case 1: dofs[order] = 1.0; break;
1787 case 2: dofs[(order*(order+3))/2] = 1.0; break;
1788 case 3: dofs[dof-1] = 1.0; break;
1789 }
1790}
1791
1792
1794 : PositiveFiniteElement(3, Geometry::PRISM,
1795 ((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
1796 TriangleFE(p),
1797 SegmentFE(p)
1798{
1799#ifndef MFEM_THREAD_SAFE
1804#endif
1805
1806 t_dof.SetSize(dof);
1807 s_dof.SetSize(dof);
1808
1809 // Interior DoFs
1810 int m=0;
1811 for (int k=0; k<=p; k++)
1812 {
1813 int l=0;
1814 for (int j=0; j<=p; j++)
1815 {
1816 for (int i=0; i<=j; i++)
1817 {
1818 t_dof[m] = l;
1819 s_dof[m] = k;
1820 l++; m++;
1821 }
1822 }
1823 }
1824
1825 // Define Nodes
1826 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
1827 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
1828 for (int i=0; i<dof; i++)
1829 {
1830 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
1831 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
1832 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
1833 }
1834}
1835
1837 Vector &shape) const
1838{
1839#ifdef MFEM_THREAD_SAFE
1842#endif
1843
1844 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1845
1848
1849 for (int i=0; i<dof; i++)
1850 {
1851 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
1852 }
1853}
1854
1856 DenseMatrix &dshape) const
1857{
1858#ifdef MFEM_THREAD_SAFE
1863#endif
1864
1865 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1866
1871
1872 for (int i=0; i<dof; i++)
1873 {
1874 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
1875 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
1876 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
1877 }
1878}
1879
1881 : PositiveFiniteElement(3, Geometry::PYRAMID,
1882 ((p + 1)*(p + 2)*(2 * p + 3))/6, p,
1883 FunctionSpace::Uk),
1884 nterms(((p + 1)*(p + 2)*(p + 3)*(p + 4))/24)
1885{
1886#ifndef MFEM_THREAD_SAFE
1890#endif
1891
1892 Index idx;
1893
1894 // interior
1895 for (int o = 0, k = 0; k <= p; k++)
1896 for (int j = 0; j + k <= p; j++)
1897 {
1898 int i1 = p - j - k;
1899 int i2 = 0;
1900 int i3 = -1;
1901 int i4 = j + 1;
1902 const int i5 = k;
1903
1904 for (int i = 0; i <= j; i++)
1905 {
1906 i3++;
1907 i4--;
1908 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1909 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
1910 }
1911 for (int i = j + 1; i + k <= p; i++)
1912 {
1913 i1--;
1914 i2++;
1915 dof_map[idx(i1,i2,i3,i4,i5)] = o;
1916 Nodes.IntPoint(o++).Set3(real_t(i)/p, real_t(j)/p, 0);
1917 }
1918 }
1919}
1920
1921// static method
1923 const real_t y, const real_t z,
1924 real_t *shape_1d,
1925 real_t *shape)
1926{
1927 const int lshape = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
1928 for (int i=0; i<lshape; i++) { shape[i] = 0.0; }
1929
1930 const real_t l1 = lam1(x, y, z);
1931 const real_t l2 = lam2(x, y, z);
1932 const real_t l3 = lam3(x, y, z);
1933 const real_t l4 = lam4(x, y, z);
1934 const real_t l5 = lam5(x, y, z);
1935
1936 // The basis functions are the terms in the expansion:
1937 // (l1 + l2 + l3 + l4 + l5)^p =
1938 // \sum_{l=0}^p \binom{p}{l} l5^l
1939 // \sum_{k=0}^{p-l} \binom{p-l}{k} l4^k
1940 // \sum_{j=0}^{p-l-k} \binom{p-l-k}{j} l3^j
1941 // \sum_{i=0}^{p-l-k-j} \binom{p-l-k-j}{i} l2^i l1^{p-l-k-j-i}
1942 Index idx;
1943 const int *bp = Poly_1D::Binom(p);
1944 real_t l5i5 = 1.;
1945 for (int i5 = 0; i5 <= p; i5++)
1946 {
1947 const int *bpi5 = Poly_1D::Binom(p - i5);
1948 const real_t ei5 = bp[i5]*l5i5;
1949 real_t l4i4 = 1.;
1950 for (int i4 = 0; i4 <= p - i5; i4++)
1951 {
1952 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
1953 const real_t ei45 = ei5*bpi5[i4]*l4i4;
1954 real_t l3i3 = 1.;
1955 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
1956 {
1957 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, shape_1d);
1958 real_t ei345 = ei45*bpi45[i3]*l3i3;
1959 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
1960 {
1961 const int i1 = p - i5 - i4 - i3 - i2;
1962 const int o = idx(i1,i2,i3,i4,i5);
1963 shape_1d[i2] *= ei345;
1964 shape[o] += shape_1d[i2];
1965 }
1966 l3i3 *= l3;
1967 }
1968 l4i4 *= l4;
1969 }
1970 l5i5 *= l5;
1971 }
1972}
1973
1974// static method
1976 const real_t y, const real_t z,
1977 real_t *dshape_1d, real_t *dshape)
1978{
1979 const int nterms = ((p + 1)*(p + 2)*(p + 3)*(p + 4))/24;
1980 for (int i=0; i<3*nterms; i++) { dshape[i] = 0.0; }
1981
1982 const real_t l1 = lam1(x, y, z);
1983 const real_t l2 = lam2(x, y, z);
1984 const real_t l3 = lam3(x, y, z);
1985 const real_t l4 = lam4(x, y, z);
1986 const real_t l5 = lam5(x, y, z);
1987
1988 const Vector dl1 = grad_lam1(x, y, z);
1989 const Vector dl2 = grad_lam2(x, y, z);
1990 const Vector dl3 = grad_lam3(x, y, z);
1991 const Vector dl4 = grad_lam4(x, y, z);
1992 const Vector dl5 = grad_lam5(x, y, z);
1993
1994 // The basis functions are the terms in the expansion:
1995 // (l1 + l2 + l3 + l4 + l5)^p
1996 // We will compute the derivative by first computing the derivatives
1997 // of these terms w.r.t each of the l1, l2, l3, l4, and l5 and summing
1998 // the results together.
1999 Index idx;
2000
2001 // Derivative w.r.t. l1 times grad(l1)
2002 const int *bp = Poly_1D::Binom(p);
2003 real_t l5i5 = 1.;
2004 for (int i5 = 0; i5 <= p; i5++)
2005 {
2006 const int *bpi5 = Poly_1D::Binom(p - i5);
2007 const real_t ei5 = bp[i5]*l5i5;
2008 real_t l4i4 = 1.;
2009 for (int i4 = 0; i4 <= p - i5; i4++)
2010 {
2011 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2012 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2013 real_t l3i3 = 1.;
2014 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2015 {
2016 Poly_1D::CalcDyBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2017 real_t ei345 = ei45*bpi45[i3]*l3i3;
2018 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2019 {
2020 const int i1 = p - i5 - i4 - i3 - i2;
2021 const int o = idx(i1,i2,i3,i4,i5);
2022 const real_t dshape_dl1 = dshape_1d[i2]*ei345;
2023 for (int d = 0; d < 3; d++)
2024 {
2025 dshape[o + d * nterms] += dshape_dl1 * dl1[d];
2026 }
2027 }
2028 l3i3 *= l3;
2029 }
2030 l4i4 *= l4;
2031 }
2032 l5i5 *= l5;
2033 }
2034
2035 // Derivative w.r.t. l2 times grad(l2)
2036 l5i5 = 1.;
2037 for (int i5 = 0; i5 <= p; i5++)
2038 {
2039 const int *bpi5 = Poly_1D::Binom(p - i5);
2040 const real_t ei5 = bp[i5]*l5i5;
2041 real_t l4i4 = 1.;
2042 for (int i4 = 0; i4 <= p - i5; i4++)
2043 {
2044 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2045 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2046 real_t l3i3 = 1.;
2047 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2048 {
2049 Poly_1D::CalcDxBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2050 real_t ei345 = ei45*bpi45[i3]*l3i3;
2051 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2052 {
2053 const int i1 = p - i5 - i4 - i3 - i2;
2054 const int o = idx(i1,i2,i3,i4,i5);
2055 const real_t dshape_dl2 = dshape_1d[i2]*ei345;
2056 for (int d = 0; d < 3; d++)
2057 {
2058 dshape[o + d * nterms] += dshape_dl2*dl2[d];
2059 }
2060 }
2061 l3i3 *= l3;
2062 }
2063 l4i4 *= l4;
2064 }
2065 l5i5 *= l5;
2066 }
2067
2068 // Derivative w.r.t. l3 times grad(l3)
2069 l5i5 = 1.;
2070 for (int i5 = 0; i5 <= p; i5++)
2071 {
2072 const int *bpi5 = Poly_1D::Binom(p - i5);
2073 const real_t ei5 = bp[i5]*l5i5;
2074 real_t l4i4 = 1.;
2075 for (int i4 = 0; i4 <= p - i5; i4++)
2076 {
2077 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2078 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2079 real_t l3i3 = 1.;
2080 for (int i3 = 1; i3 <= p - i5 - i4; i3++)
2081 {
2082 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2083 real_t ei345 = i3*ei45*bpi45[i3]*l3i3;
2084 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2085 {
2086 const int i1 = p - i5 - i4 - i3 - i2;
2087 const int o = idx(i1,i2,i3,i4,i5);
2088 const real_t dshape_dl3 = dshape_1d[i2]*ei345;
2089 for (int d = 0; d < 3; d++)
2090 {
2091 dshape[o + d * nterms] += dshape_dl3*dl3[d];
2092 }
2093 }
2094 l3i3 *= l3;
2095 }
2096 l4i4 *= l4;
2097 }
2098 l5i5 *= l5;
2099 }
2100
2101 // Derivative w.r.t. l4 times grad(l4)
2102 l5i5 = 1.;
2103 for (int i5 = 0; i5 <= p; i5++)
2104 {
2105 const int *bpi5 = Poly_1D::Binom(p - i5);
2106 const real_t ei5 = bp[i5]*l5i5;
2107 real_t l4i4 = 1.;
2108 for (int i4 = 1; i4 <= p - i5; i4++)
2109 {
2110 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2111 const real_t ei45 = i4*ei5*bpi5[i4]*l4i4;
2112 real_t l3i3 = 1.;
2113 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2114 {
2115 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2116 real_t ei345 = ei45*bpi45[i3]*l3i3;
2117 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2118 {
2119 const int i1 = p - i5 - i4 - i3 - i2;
2120 const int o = idx(i1,i2,i3,i4,i5);
2121 const real_t dshape_dl4 = dshape_1d[i2]*ei345;
2122 for (int d = 0; d < 3; d++)
2123 {
2124 dshape[o + d * nterms] += dshape_dl4*dl4[d];
2125 }
2126 }
2127 l3i3 *= l3;
2128 }
2129 l4i4 *= l4;
2130 }
2131 l5i5 *= l5;
2132 }
2133
2134 // Derivative w.r.t. l5 times grad(l5)
2135 l5i5 = 1.;
2136 for (int i5 = 1; i5 <= p; i5++)
2137 {
2138 const int *bpi5 = Poly_1D::Binom(p - i5);
2139 const real_t ei5 = i5*bp[i5]*l5i5;
2140 real_t l4i4 = 1.;
2141 for (int i4 = 0; i4 <= p - i5; i4++)
2142 {
2143 const int *bpi45 = Poly_1D::Binom(p - i5 - i4);
2144 const real_t ei45 = ei5*bpi5[i4]*l4i4;
2145 real_t l3i3 = 1.;
2146 for (int i3 = 0; i3 <= p - i5 - i4; i3++)
2147 {
2148 Poly_1D::CalcBinomTerms(p - i5 - i4 - i3, l2, l1, dshape_1d);
2149 real_t ei345 = ei45*bpi45[i3]*l3i3;
2150 for (int i2 = 0; i2 <= p - i5 - i4 - i3; i2++)
2151 {
2152 const int i1 = p - i5 - i4 - i3 - i2;
2153 const int o = idx(i1,i2,i3,i4,i5);
2154 const real_t dshape_dl5 = dshape_1d[i2]*ei345;
2155 for (int d = 0; d < 3; d++)
2156 {
2157 dshape[o + d * nterms] += dshape_dl5*dl5[d];
2158 }
2159 }
2160 l3i3 *= l3;
2161 }
2162 l4i4 *= l4;
2163 }
2164 l5i5 *= l5;
2165 }
2166}
2167
2169 Vector &shape) const
2170{
2171#ifdef MFEM_THREAD_SAFE
2172 Vector m_shape_1d(order + 1);
2174#endif
2175
2176 CalcShape(order, ip.x, ip.y, ip.z, m_shape_1d.GetData(), m_shape.GetData());
2177
2178 for (auto const& it : dof_map)
2179 {
2180 if (it.first < m_shape.Size()) { shape[it.second] = m_shape[it.first]; }
2181 }
2182}
2183
2185 DenseMatrix &dshape) const
2186{
2187#ifdef MFEM_THREAD_SAFE
2188 Vector m_shape_1d(order + 1);
2190#endif
2191
2192 CalcDShape(order, ip.x, ip.y, ip.z,
2194
2195 for (auto const& it : dof_map)
2196 for (int d=0; d<3; d++)
2197 {
2198 dshape(it.second, d) = m_dshape(it.first, d);
2199 }
2200
2201}
2202
2203}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
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.
Definition densemat.hpp:114
real_t * GetData() const
Returns the matrix data array.
Definition densemat.hpp:118
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:108
void Invert()
Replaces the current matrix with its inverse.
Definition densemat.cpp:707
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:244
int dof
Number of degrees of freedom.
Definition fe_base.hpp:253
IntegrationRule Nodes
Definition fe_base.hpp:256
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:400
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:334
int order
Order/degree of the shape functions.
Definition fe_base.hpp:254
int dim
Dimension of reference space.
Definition fe_base.hpp:246
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:226
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:1045
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:1193
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:1246
std::map< int, int > dof_map
Definition fe_pos.hpp:277
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
H1Pos_TetrahedronElement(const int p)
Construct the H1Pos_TetrahedronElement of order p.
Definition fe_pos.cpp:651
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:753
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:786
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:587
static void CalcShape(const int p, const real_t x, const real_t y, real_t *shape)
Definition fe_pos.cpp:561
H1Pos_TriangleElement TriangleFE
Definition fe_pos.hpp:247
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:1020
H1Pos_SegmentElement SegmentFE
Definition fe_pos.hpp:248
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:1001
H1Pos_WedgeElement(const int p)
Construct the H1Pos_WedgeElement of order p.
Definition fe_pos.cpp:903
Class for integration point with weight.
Definition intrules.hpp:35
void Set2(const real_t x1, const real_t x2)
Definition intrules.hpp:89
void Set3(const real_t x1, const real_t x2, const real_t x3)
Definition intrules.hpp:79
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
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:1624
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:1669
L2Pos_HexahedronElement(const int p)
Construct the L2Pos_HexahedronElement of order p.
Definition fe_pos.cpp:1597
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:1645
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:1975
std::map< int, int > dof_map
Definition fe_pos.hpp:446
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:1922
L2Pos_PyramidElement(const int p)
Construct the L2Pos_PyramidElement of order p.
Definition fe_pos.cpp:1880
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:1543
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:1582
L2Pos_QuadrilateralElement(const int p)
Construct the L2Pos_QuadrilateralElement of order p.
Definition fe_pos.cpp:1519
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:1562
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:1495
L2Pos_SegmentElement(const int p)
Construct the L2Pos_SegmentElement of order p.
Definition fe_pos.cpp:1474
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:1501
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:1512
L2Pos_TetrahedronElement(const int p)
Construct the L2Pos_TetrahedronElement of order p.
Definition fe_pos.cpp:1739
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:1780
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:1762
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:1769
L2Pos_TriangleElement(const int p)
Construct the L2Pos_TriangleElement of order p.
Definition fe_pos.cpp:1688
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:1710
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:1716
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:1727
L2Pos_TriangleElement TriangleFE
Definition fe_pos.hpp:424
L2Pos_WedgeElement(const int p)
Construct the L2Pos_WedgeElement of order p.
Definition fe_pos.cpp:1793
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:1855
L2Pos_SegmentElement SegmentFE
Definition fe_pos.hpp:425
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:1836
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:721
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:796
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:2157
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:2044
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:2216
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:1215
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:2093
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:2187
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
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:183
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:558
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:235
void SetData(real_t *d)
Definition vector.hpp:176
@ lshape
Definition ex25.cpp:152
Linear1DFiniteElement SegmentFE
Definition segment.cpp:52
float real_t
Definition config.hpp:43
MFEM_EXPORT Linear2DFiniteElement TriangleFE
Definition fe.cpp:32
real_t p(const Vector &x, real_t t)