MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
fe_nd.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// Nedelec Finite Element classes
13
14#include "fe_nd.hpp"
15#include "face_map_utils.hpp"
16#include "../coefficient.hpp"
17
18namespace mfem
19{
20
21using namespace std;
22
23const real_t ND_HexahedronElement::tk[18] =
24{ 1.,0.,0., 0.,1.,0., 0.,0.,1., -1.,0.,0., 0.,-1.,0., 0.,0.,-1. };
25
27 const int cb_type, const int ob_type)
28 : VectorTensorFiniteElement(3, 3*p*(p + 1)*(p + 1), p, cb_type, ob_type,
29 H_CURL, DofMapType::L2_DOF_MAP),
30 dof2tk(dof), cp(poly1d.ClosedPoints(p, cb_type))
31{
32 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
33
35
36 const real_t *op = poly1d.OpenPoints(p - 1, ob_type);
37 const int dof3 = dof/3;
38
39#ifndef MFEM_THREAD_SAFE
40 shape_cx.SetSize(p + 1);
41 shape_ox.SetSize(p);
42 shape_cy.SetSize(p + 1);
43 shape_oy.SetSize(p);
44 shape_cz.SetSize(p + 1);
45 shape_oz.SetSize(p);
46 dshape_cx.SetSize(p + 1);
47 dshape_cy.SetSize(p + 1);
48 dshape_cz.SetSize(p + 1);
49#endif
50
51 // edges
52 int o = 0;
53 for (int i = 0; i < p; i++) // (0,1)
54 {
55 dof_map[0*dof3 + i + (0 + 0*(p + 1))*p] = o++;
56 }
57 for (int i = 0; i < p; i++) // (1,2)
58 {
59 dof_map[1*dof3 + p + (i + 0*p)*(p + 1)] = o++;
60 }
61 for (int i = 0; i < p; i++) // (3,2)
62 {
63 dof_map[0*dof3 + i + (p + 0*(p + 1))*p] = o++;
64 }
65 for (int i = 0; i < p; i++) // (0,3)
66 {
67 dof_map[1*dof3 + 0 + (i + 0*p)*(p + 1)] = o++;
68 }
69 for (int i = 0; i < p; i++) // (4,5)
70 {
71 dof_map[0*dof3 + i + (0 + p*(p + 1))*p] = o++;
72 }
73 for (int i = 0; i < p; i++) // (5,6)
74 {
75 dof_map[1*dof3 + p + (i + p*p)*(p + 1)] = o++;
76 }
77 for (int i = 0; i < p; i++) // (7,6)
78 {
79 dof_map[0*dof3 + i + (p + p*(p + 1))*p] = o++;
80 }
81 for (int i = 0; i < p; i++) // (4,7)
82 {
83 dof_map[1*dof3 + 0 + (i + p*p)*(p + 1)] = o++;
84 }
85 for (int i = 0; i < p; i++) // (0,4)
86 {
87 dof_map[2*dof3 + 0 + (0 + i*(p + 1))*(p + 1)] = o++;
88 }
89 for (int i = 0; i < p; i++) // (1,5)
90 {
91 dof_map[2*dof3 + p + (0 + i*(p + 1))*(p + 1)] = o++;
92 }
93 for (int i = 0; i < p; i++) // (2,6)
94 {
95 dof_map[2*dof3 + p + (p + i*(p + 1))*(p + 1)] = o++;
96 }
97 for (int i = 0; i < p; i++) // (3,7)
98 {
99 dof_map[2*dof3 + 0 + (p + i*(p + 1))*(p + 1)] = o++;
100 }
101
102 // faces
103 // (3,2,1,0) -- bottom
104 for (int j = 1; j < p; j++) // x - components
105 for (int i = 0; i < p; i++)
106 {
107 dof_map[0*dof3 + i + ((p - j) + 0*(p + 1))*p] = o++;
108 }
109 for (int j = 0; j < p; j++) // y - components
110 for (int i = 1; i < p; i++)
111 {
112 dof_map[1*dof3 + i + ((p - 1 - j) + 0*p)*(p + 1)] = -1 - (o++);
113 }
114 // (0,1,5,4) -- front
115 for (int k = 1; k < p; k++) // x - components
116 for (int i = 0; i < p; i++)
117 {
118 dof_map[0*dof3 + i + (0 + k*(p + 1))*p] = o++;
119 }
120 for (int k = 0; k < p; k++) // z - components
121 for (int i = 1; i < p; i++ )
122 {
123 dof_map[2*dof3 + i + (0 + k*(p + 1))*(p + 1)] = o++;
124 }
125 // (1,2,6,5) -- right
126 for (int k = 1; k < p; k++) // y - components
127 for (int j = 0; j < p; j++)
128 {
129 dof_map[1*dof3 + p + (j + k*p)*(p + 1)] = o++;
130 }
131 for (int k = 0; k < p; k++) // z - components
132 for (int j = 1; j < p; j++)
133 {
134 dof_map[2*dof3 + p + (j + k*(p + 1))*(p + 1)] = o++;
135 }
136 // (2,3,7,6) -- back
137 for (int k = 1; k < p; k++) // x - components
138 for (int i = 0; i < p; i++)
139 {
140 dof_map[0*dof3 + (p - 1 - i) + (p + k*(p + 1))*p] = -1 - (o++);
141 }
142 for (int k = 0; k < p; k++) // z - components
143 for (int i = 1; i < p; i++)
144 {
145 dof_map[2*dof3 + (p - i) + (p + k*(p + 1))*(p + 1)] = o++;
146 }
147 // (3,0,4,7) -- left
148 for (int k = 1; k < p; k++) // y - components
149 for (int j = 0; j < p; j++)
150 {
151 dof_map[1*dof3 + 0 + ((p - 1 - j) + k*p)*(p + 1)] = -1 - (o++);
152 }
153 for (int k = 0; k < p; k++) // z - components
154 for (int j = 1; j < p; j++)
155 {
156 dof_map[2*dof3 + 0 + ((p - j) + k*(p + 1))*(p + 1)] = o++;
157 }
158 // (4,5,6,7) -- top
159 for (int j = 1; j < p; j++) // x - components
160 for (int i = 0; i < p; i++)
161 {
162 dof_map[0*dof3 + i + (j + p*(p + 1))*p] = o++;
163 }
164 for (int j = 0; j < p; j++) // y - components
165 for (int i = 1; i < p; i++)
166 {
167 dof_map[1*dof3 + i + (j + p*p)*(p + 1)] = o++;
168 }
169
170 // interior
171 // x-components
172 for (int k = 1; k < p; k++)
173 for (int j = 1; j < p; j++)
174 for (int i = 0; i < p; i++)
175 {
176 dof_map[0*dof3 + i + (j + k*(p + 1))*p] = o++;
177 }
178 // y-components
179 for (int k = 1; k < p; k++)
180 for (int j = 0; j < p; j++)
181 for (int i = 1; i < p; i++)
182 {
183 dof_map[1*dof3 + i + (j + k*p)*(p + 1)] = o++;
184 }
185 // z-components
186 for (int k = 0; k < p; k++)
187 for (int j = 1; j < p; j++)
188 for (int i = 1; i < p; i++)
189 {
190 dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++;
191 }
192
193 // set dof2tk and Nodes
194 o = 0;
195 // x-components
196 for (int k = 0; k <= p; k++)
197 for (int j = 0; j <= p; j++)
198 for (int i = 0; i < p; i++)
199 {
200 int idx;
201 if ((idx = dof_map[o++]) < 0)
202 {
203 dof2tk[idx = -1 - idx] = 3;
204 }
205 else
206 {
207 dof2tk[idx] = 0;
208 }
209 Nodes.IntPoint(idx).Set3(op[i], cp[j], cp[k]);
210 }
211 // y-components
212 for (int k = 0; k <= p; k++)
213 for (int j = 0; j < p; j++)
214 for (int i = 0; i <= p; i++)
215 {
216 int idx;
217 if ((idx = dof_map[o++]) < 0)
218 {
219 dof2tk[idx = -1 - idx] = 4;
220 }
221 else
222 {
223 dof2tk[idx] = 1;
224 }
225 Nodes.IntPoint(idx).Set3(cp[i], op[j], cp[k]);
226 }
227 // z-components
228 for (int k = 0; k < p; k++)
229 for (int j = 0; j <= p; j++)
230 for (int i = 0; i <= p; i++)
231 {
232 int idx;
233 if ((idx = dof_map[o++]) < 0)
234 {
235 dof2tk[idx = -1 - idx] = 5;
236 }
237 else
238 {
239 dof2tk[idx] = 2;
240 }
241 Nodes.IntPoint(idx).Set3(cp[i], cp[j], op[k]);
242 }
243}
244
247 Vector &dofs) const
248{
249 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
251 Vector xk(vk, vc.GetVDim());
252
254 const int nqpt = ir.GetNPoints();
255
256 IntegrationPoint ip3d;
257
258 int o = 0;
259 for (int c = 0; c < 3; ++c) // loop over x, y, z components
260 {
261 const int im = c == 0 ? order - 1 : order;
262 const int jm = c == 1 ? order - 1 : order;
263 const int km = c == 2 ? order - 1 : order;
264
265 for (int k = 0; k <= km; k++)
266 for (int j = 0; j <= jm; j++)
267 for (int i = 0; i <= im; i++)
268 {
269 int idx;
270 if ((idx = dof_map[o++]) < 0)
271 {
272 idx = -1 - idx;
273 }
274
275 const int id1 = c == 0 ? i : (c == 1 ? j : k);
276 const real_t h = cp[id1+1] - cp[id1];
277
278 real_t val = 0.0;
279
280 for (int q = 0; q < nqpt; q++)
281 {
282 const IntegrationPoint &ip1d = ir.IntPoint(q);
283
284 if (c == 0)
285 {
286 ip3d.Set3(cp[i] + (h*ip1d.x), cp[j], cp[k]);
287 }
288 else if (c == 1)
289 {
290 ip3d.Set3(cp[i], cp[j] + (h*ip1d.x), cp[k]);
291 }
292 else
293 {
294 ip3d.Set3(cp[i], cp[j], cp[k] + (h*ip1d.x));
295 }
296
297 Trans.SetIntPoint(&ip3d);
298 vc.Eval(xk, Trans, ip3d);
299
300 // xk^t J tk
301 const real_t ipval = Trans.Jacobian().InnerProduct(tk + dof2tk[idx]*dim, vk);
302 val += ip1d.weight * ipval;
303 }
304
305 dofs(idx) = val*h;
306 }
307 }
308}
309
311 DenseMatrix &shape) const
312{
313 const int p = order;
314
315#ifdef MFEM_THREAD_SAFE
316 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
317 Vector shape_cz(p + 1), shape_oz(p);
318#endif
319
321 {
322#ifdef MFEM_THREAD_SAFE
323 Vector dshape_cx(p + 1), dshape_cy(p + 1), dshape_cz(p + 1);
324#endif
325 basis1d.Eval(ip.x, shape_cx, dshape_cx);
326 basis1d.Eval(ip.y, shape_cy, dshape_cy);
327 basis1d.Eval(ip.z, shape_cz, dshape_cz);
329 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
330 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
331 obasis1d.EvalIntegrated(dshape_cz, shape_oz);
332 }
333 else
334 {
335 basis1d.Eval(ip.x, shape_cx);
336 basis1d.Eval(ip.y, shape_cy);
337 basis1d.Eval(ip.z, shape_cz);
338 obasis1d.Eval(ip.x, shape_ox);
339 obasis1d.Eval(ip.y, shape_oy);
340 obasis1d.Eval(ip.z, shape_oz);
341 }
342
343 int o = 0;
344 // x-components
345 for (int k = 0; k <= p; k++)
346 for (int j = 0; j <= p; j++)
347 for (int i = 0; i < p; i++)
348 {
349 int idx, s;
350 if ((idx = dof_map[o++]) < 0)
351 {
352 idx = -1 - idx, s = -1;
353 }
354 else
355 {
356 s = +1;
357 }
358 shape(idx,0) = s*shape_ox(i)*shape_cy(j)*shape_cz(k);
359 shape(idx,1) = 0.;
360 shape(idx,2) = 0.;
361 }
362 // y-components
363 for (int k = 0; k <= p; k++)
364 for (int j = 0; j < p; j++)
365 for (int i = 0; i <= p; i++)
366 {
367 int idx, s;
368 if ((idx = dof_map[o++]) < 0)
369 {
370 idx = -1 - idx, s = -1;
371 }
372 else
373 {
374 s = +1;
375 }
376 shape(idx,0) = 0.;
377 shape(idx,1) = s*shape_cx(i)*shape_oy(j)*shape_cz(k);
378 shape(idx,2) = 0.;
379 }
380 // z-components
381 for (int k = 0; k < p; k++)
382 for (int j = 0; j <= p; j++)
383 for (int i = 0; i <= p; i++)
384 {
385 int idx, s;
386 if ((idx = dof_map[o++]) < 0)
387 {
388 idx = -1 - idx, s = -1;
389 }
390 else
391 {
392 s = +1;
393 }
394 shape(idx,0) = 0.;
395 shape(idx,1) = 0.;
396 shape(idx,2) = s*shape_cx(i)*shape_cy(j)*shape_oz(k);
397 }
398}
399
401 DenseMatrix &curl_shape) const
402{
403 const int p = order;
404
405#ifdef MFEM_THREAD_SAFE
406 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
407 Vector shape_cz(p + 1), shape_oz(p);
408 Vector dshape_cx(p + 1), dshape_cy(p + 1), dshape_cz(p + 1);
409#endif
410
411 basis1d.Eval(ip.x, shape_cx, dshape_cx);
412 basis1d.Eval(ip.y, shape_cy, dshape_cy);
413 basis1d.Eval(ip.z, shape_cz, dshape_cz);
415 {
417 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
418 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
419 obasis1d.EvalIntegrated(dshape_cz, shape_oz);
420 }
421 else
422 {
423 obasis1d.Eval(ip.x, shape_ox);
424 obasis1d.Eval(ip.y, shape_oy);
425 obasis1d.Eval(ip.z, shape_oz);
426 }
427
428 int o = 0;
429 // x-components
430 for (int k = 0; k <= p; k++)
431 for (int j = 0; j <= p; j++)
432 for (int i = 0; i < p; i++)
433 {
434 int idx, s;
435 if ((idx = dof_map[o++]) < 0)
436 {
437 idx = -1 - idx, s = -1;
438 }
439 else
440 {
441 s = +1;
442 }
443 curl_shape(idx,0) = 0.;
444 curl_shape(idx,1) = s*shape_ox(i)* shape_cy(j)*dshape_cz(k);
445 curl_shape(idx,2) = -s*shape_ox(i)*dshape_cy(j)* shape_cz(k);
446 }
447 // y-components
448 for (int k = 0; k <= p; k++)
449 for (int j = 0; j < p; j++)
450 for (int i = 0; i <= p; i++)
451 {
452 int idx, s;
453 if ((idx = dof_map[o++]) < 0)
454 {
455 idx = -1 - idx, s = -1;
456 }
457 else
458 {
459 s = +1;
460 }
461 curl_shape(idx,0) = -s* shape_cx(i)*shape_oy(j)*dshape_cz(k);
462 curl_shape(idx,1) = 0.;
463 curl_shape(idx,2) = s*dshape_cx(i)*shape_oy(j)* shape_cz(k);
464 }
465 // z-components
466 for (int k = 0; k < p; k++)
467 for (int j = 0; j <= p; j++)
468 for (int i = 0; i <= p; i++)
469 {
470 int idx, s;
471 if ((idx = dof_map[o++]) < 0)
472 {
473 idx = -1 - idx, s = -1;
474 }
475 else
476 {
477 s = +1;
478 }
479 curl_shape(idx,0) = s* shape_cx(i)*dshape_cy(j)*shape_oz(k);
480 curl_shape(idx,1) = -s*dshape_cx(i)* shape_cy(j)*shape_oz(k);
481 curl_shape(idx,2) = 0.;
482 }
483}
484
485void ND_HexahedronElement::GetFaceMap(const int face_id,
486 Array<int> &face_map) const
487{
488 const int p = order;
489 const int pp1 = p + 1;
490 const int n_face_dofs_per_component = p*pp1;
491 const int n_dof_per_dim = p*pp1*pp1;
492
493 std::vector<int> n_dofs = {p, pp1, pp1, p};
494 std::vector<int> offsets, strides;
495
496 const auto f = internal::GetFaceNormal3D(face_id);
497 const int face_normal = f.first, level = f.second;
498 if (face_normal == 0) // x-normal
499 {
500 offsets =
501 {
502 n_dof_per_dim + (level ? pp1 - 1 : 0),
503 2*n_dof_per_dim + (level ? pp1 - 1 : 0)
504 };
505 strides = {pp1, p*pp1, pp1, pp1*pp1};
506 }
507 else if (face_normal == 1) // y-normal
508 {
509 offsets =
510 {
511 level ? p*(pp1 - 1) : 0,
512 2*n_dof_per_dim + (level ? pp1*(pp1 - 1) : 0)
513 };
514 strides = {1, p*pp1, 1, pp1*pp1};
515 }
516 else if (face_normal == 2) // z-normal
517 {
518 offsets =
519 {
520 level ? p*pp1*(pp1 - 1) : 0,
521 n_dof_per_dim + (level ? p*pp1*(pp1 - 1) : 0)
522 };
523 strides = {1, p, 1, pp1};
524 }
525
526 internal::FillFaceMap(n_face_dofs_per_component, offsets, strides, n_dofs,
527 face_map);
528}
529
530const real_t ND_QuadrilateralElement::tk[8] =
531{ 1.,0., 0.,1., -1.,0., 0.,-1. };
532
534 const int cb_type,
535 const int ob_type)
536 : VectorTensorFiniteElement(2, 2*p*(p + 1), p, cb_type, ob_type,
537 H_CURL, DofMapType::L2_DOF_MAP),
538 dof2tk(dof),
539 cp(poly1d.ClosedPoints(p, cb_type))
540{
541 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
542
544
545 const real_t *op = poly1d.OpenPoints(p - 1, ob_type);
546 const int dof2 = dof/2;
547
548#ifndef MFEM_THREAD_SAFE
549 shape_cx.SetSize(p + 1);
550 shape_ox.SetSize(p);
551 shape_cy.SetSize(p + 1);
552 shape_oy.SetSize(p);
553 dshape_cx.SetSize(p + 1);
554 dshape_cy.SetSize(p + 1);
555#endif
556
557 // edges
558 int o = 0;
559 for (int i = 0; i < p; i++) // (0,1)
560 {
561 dof_map[0*dof2 + i + 0*p] = o++;
562 }
563 for (int j = 0; j < p; j++) // (1,2)
564 {
565 dof_map[1*dof2 + p + j*(p + 1)] = o++;
566 }
567 for (int i = 0; i < p; i++) // (2,3)
568 {
569 dof_map[0*dof2 + (p - 1 - i) + p*p] = -1 - (o++);
570 }
571 for (int j = 0; j < p; j++) // (3,0)
572 {
573 dof_map[1*dof2 + 0 + (p - 1 - j)*(p + 1)] = -1 - (o++);
574 }
575
576 // interior
577 // x-components
578 for (int j = 1; j < p; j++)
579 for (int i = 0; i < p; i++)
580 {
581 dof_map[0*dof2 + i + j*p] = o++;
582 }
583 // y-components
584 for (int j = 0; j < p; j++)
585 for (int i = 1; i < p; i++)
586 {
587 dof_map[1*dof2 + i + j*(p + 1)] = o++;
588 }
589
590 // set dof2tk and Nodes
591 o = 0;
592 // x-components
593 for (int j = 0; j <= p; j++)
594 for (int i = 0; i < p; i++)
595 {
596 int idx;
597 if ((idx = dof_map[o++]) < 0)
598 {
599 dof2tk[idx = -1 - idx] = 2;
600 }
601 else
602 {
603 dof2tk[idx] = 0;
604 }
605 Nodes.IntPoint(idx).Set2(op[i], cp[j]);
606 }
607 // y-components
608 for (int j = 0; j < p; j++)
609 for (int i = 0; i <= p; i++)
610 {
611 int idx;
612 if ((idx = dof_map[o++]) < 0)
613 {
614 dof2tk[idx = -1 - idx] = 3;
615 }
616 else
617 {
618 dof2tk[idx] = 1;
619 }
620 Nodes.IntPoint(idx).Set2(cp[i], op[j]);
621 }
622}
623
626 Vector &dofs) const
627{
628 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
630 Vector xk(vk, vc.GetVDim());
631
633 const int nqpt = ir.GetNPoints();
634
635 IntegrationPoint ip2d;
636
637 int o = 0;
638 // x-components
639 for (int j = 0; j <= order; j++)
640 for (int i = 0; i < order; i++)
641 {
642 int idx;
643 if ((idx = dof_map[o++]) < 0)
644 {
645 idx = -1 - idx;
646 }
647
648 const real_t h = cp[i+1] - cp[i];
649
650 real_t val = 0.0;
651
652 for (int k = 0; k < nqpt; k++)
653 {
654 const IntegrationPoint &ip1d = ir.IntPoint(k);
655
656 ip2d.Set2(cp[i] + (h*ip1d.x), cp[j]);
657
658 Trans.SetIntPoint(&ip2d);
659 vc.Eval(xk, Trans, ip2d);
660
661 // xk^t J tk
662 const real_t ipval = Trans.Jacobian().InnerProduct(tk + dof2tk[idx]*dim, vk);
663 val += ip1d.weight * ipval;
664 }
665
666 dofs(idx) = val*h;
667 }
668 // y-components
669 for (int j = 0; j < order; j++)
670 for (int i = 0; i <= order; i++)
671 {
672 int idx;
673 if ((idx = dof_map[o++]) < 0)
674 {
675 idx = -1 - idx;
676 }
677
678 const real_t h = cp[j+1] - cp[j];
679
680 real_t val = 0.0;
681
682 for (int k = 0; k < nqpt; k++)
683 {
684 const IntegrationPoint &ip1d = ir.IntPoint(k);
685
686 ip2d.Set2(cp[i], cp[j] + (h*ip1d.x));
687
688 Trans.SetIntPoint(&ip2d);
689 vc.Eval(xk, Trans, ip2d);
690
691 // xk^t J tk
692 const real_t ipval = Trans.Jacobian().InnerProduct(tk + dof2tk[idx]*dim, vk);
693 val += ip1d.weight * ipval;
694 }
695
696 dofs(idx) = val*h;
697 }
698}
699
701 DenseMatrix &shape) const
702{
703 const int p = order;
704
705#ifdef MFEM_THREAD_SAFE
706 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
707#endif
708
710 {
711#ifdef MFEM_THREAD_SAFE
712 Vector dshape_cx(p + 1), dshape_cy(p + 1);
713#endif
714 basis1d.Eval(ip.x, shape_cx, dshape_cx);
715 basis1d.Eval(ip.y, shape_cy, dshape_cy);
717 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
718 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
719 }
720 else
721 {
722 basis1d.Eval(ip.x, shape_cx);
723 basis1d.Eval(ip.y, shape_cy);
724 obasis1d.Eval(ip.x, shape_ox);
725 obasis1d.Eval(ip.y, shape_oy);
726 }
728 int o = 0;
729 // x-components
730 for (int j = 0; j <= p; j++)
731 for (int i = 0; i < p; i++)
732 {
733 int idx, s;
734 if ((idx = dof_map[o++]) < 0)
735 {
736 idx = -1 - idx, s = -1;
737 }
738 else
739 {
740 s = +1;
741 }
742 shape(idx,0) = s*shape_ox(i)*shape_cy(j);
743 shape(idx,1) = 0.;
744 }
745 // y-components
746 for (int j = 0; j < p; j++)
747 for (int i = 0; i <= p; i++)
748 {
749 int idx, s;
750 if ((idx = dof_map[o++]) < 0)
751 {
752 idx = -1 - idx, s = -1;
753 }
754 else
755 {
756 s = +1;
757 }
758 shape(idx,0) = 0.;
759 shape(idx,1) = s*shape_cx(i)*shape_oy(j);
760 }
761}
762
764 DenseMatrix &curl_shape) const
765{
766 const int p = order;
767
768#ifdef MFEM_THREAD_SAFE
769 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
770 Vector dshape_cx(p + 1), dshape_cy(p + 1);
771#endif
772
773 basis1d.Eval(ip.x, shape_cx, dshape_cx);
774 basis1d.Eval(ip.y, shape_cy, dshape_cy);
776 {
778 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
779 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
780 }
781 else
782 {
783 obasis1d.Eval(ip.x, shape_ox);
784 obasis1d.Eval(ip.y, shape_oy);
785 }
786
787 int o = 0;
788 // x-components
789 for (int j = 0; j <= p; j++)
790 for (int i = 0; i < p; i++)
791 {
792 int idx, s;
793 if ((idx = dof_map[o++]) < 0)
794 {
795 idx = -1 - idx, s = -1;
796 }
797 else
798 {
799 s = +1;
800 }
801 curl_shape(idx,0) = -s*shape_ox(i)*dshape_cy(j);
802 }
803 // y-components
804 for (int j = 0; j < p; j++)
805 for (int i = 0; i <= p; i++)
806 {
807 int idx, s;
808 if ((idx = dof_map[o++]) < 0)
809 {
810 idx = -1 - idx, s = -1;
811 }
812 else
813 {
814 s = +1;
815 }
816 curl_shape(idx,0) = s*dshape_cx(i)*shape_oy(j);
817 }
818}
819
821 Array<int> &face_map) const
822{
823 const int p = order;
824 const int pp1 = order + 1;
825 const int n_face_dofs_per_component = p;
826 std::vector<int> strides = {(face_id == 0 || face_id == 2) ? 1 : pp1};
827 std::vector<int> n_dofs = {p};
828 std::vector<int> offsets;
829 switch (face_id)
830 {
831 case 0: offsets = {0}; break; // y = 0
832 case 1: offsets = {p*pp1 + pp1 - 1}; break; // x = 1
833 case 2: offsets = {p*(pp1 - 1)}; break; // y = 1
834 case 3: offsets = {p*pp1}; break; // x = 0
835 }
836 internal::FillFaceMap(n_face_dofs_per_component, offsets, strides, n_dofs,
837 face_map);
838}
839
840
841const real_t ND_TetrahedronElement::tk[18] =
842{ 1.,0.,0., 0.,1.,0., 0.,0.,1., -1.,1.,0., -1.,0.,1., 0.,-1.,1. };
843
844const real_t ND_TetrahedronElement::c = 1./4.;
845
847 : VectorFiniteElement(3, Geometry::TETRAHEDRON, p*(p + 2)*(p + 3)/2, p,
848 H_CURL, FunctionSpace::Pk), dof2tk(dof), doftrans(p)
849{
850 const real_t *eop = poly1d.OpenPoints(p - 1);
851 const real_t *fop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
852 const real_t *iop = (p > 2) ? poly1d.OpenPoints(p - 3) : NULL;
853
854 const int pm1 = p - 1, pm2 = p - 2, pm3 = p - 3;
855
856#ifndef MFEM_THREAD_SAFE
857 shape_x.SetSize(p);
858 shape_y.SetSize(p);
859 shape_z.SetSize(p);
860 shape_l.SetSize(p);
861 dshape_x.SetSize(p);
862 dshape_y.SetSize(p);
863 dshape_z.SetSize(p);
864 dshape_l.SetSize(p);
865 u.SetSize(dof, dim);
866#else
867 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
868#endif
869
870 int o = 0;
871 // edges
872 for (int i = 0; i < p; i++) // (0,1)
873 {
874 Nodes.IntPoint(o).Set3(eop[i], 0., 0.);
875 dof2tk[o++] = 0;
876 }
877 for (int i = 0; i < p; i++) // (0,2)
878 {
879 Nodes.IntPoint(o).Set3(0., eop[i], 0.);
880 dof2tk[o++] = 1;
881 }
882 for (int i = 0; i < p; i++) // (0,3)
883 {
884 Nodes.IntPoint(o).Set3(0., 0., eop[i]);
885 dof2tk[o++] = 2;
886 }
887 for (int i = 0; i < p; i++) // (1,2)
888 {
889 Nodes.IntPoint(o).Set3(eop[pm1-i], eop[i], 0.);
890 dof2tk[o++] = 3;
891 }
892 for (int i = 0; i < p; i++) // (1,3)
893 {
894 Nodes.IntPoint(o).Set3(eop[pm1-i], 0., eop[i]);
895 dof2tk[o++] = 4;
896 }
897 for (int i = 0; i < p; i++) // (2,3)
898 {
899 Nodes.IntPoint(o).Set3(0., eop[pm1-i], eop[i]);
900 dof2tk[o++] = 5;
901 }
902
903 // faces
904 for (int j = 0; j <= pm2; j++) // (1,2,3)
905 for (int i = 0; i + j <= pm2; i++)
906 {
907 real_t w = fop[i] + fop[j] + fop[pm2-i-j];
908 Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w);
909 dof2tk[o++] = 3;
910 Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w);
911 dof2tk[o++] = 4;
912 }
913 for (int j = 0; j <= pm2; j++) // (0,3,2)
914 for (int i = 0; i + j <= pm2; i++)
915 {
916 real_t w = fop[i] + fop[j] + fop[pm2-i-j];
917 Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w);
918 dof2tk[o++] = 2;
919 Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w);
920 dof2tk[o++] = 1;
921 }
922 for (int j = 0; j <= pm2; j++) // (0,1,3)
923 for (int i = 0; i + j <= pm2; i++)
924 {
925 real_t w = fop[i] + fop[j] + fop[pm2-i-j];
926 Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w);
927 dof2tk[o++] = 0;
928 Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w);
929 dof2tk[o++] = 2;
930 }
931 for (int j = 0; j <= pm2; j++) // (0,2,1)
932 for (int i = 0; i + j <= pm2; i++)
933 {
934 real_t w = fop[i] + fop[j] + fop[pm2-i-j];
935 Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.);
936 dof2tk[o++] = 1;
937 Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.);
938 dof2tk[o++] = 0;
939 }
940
941 // interior
942 for (int k = 0; k <= pm3; k++)
943 for (int j = 0; j + k <= pm3; j++)
944 for (int i = 0; i + j + k <= pm3; i++)
945 {
946 real_t w = iop[i] + iop[j] + iop[k] + iop[pm3-i-j-k];
947 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
948 dof2tk[o++] = 0;
949 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
950 dof2tk[o++] = 1;
951 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
952 dof2tk[o++] = 2;
953 }
954
955 DenseMatrix T(dof);
956 for (int m = 0; m < dof; m++)
957 {
958 const IntegrationPoint &ip = Nodes.IntPoint(m);
959 const real_t *tm = tk + 3*dof2tk[m];
960 o = 0;
961
962 poly1d.CalcBasis(pm1, ip.x, shape_x);
963 poly1d.CalcBasis(pm1, ip.y, shape_y);
964 poly1d.CalcBasis(pm1, ip.z, shape_z);
965 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l);
966
967 for (int k = 0; k <= pm1; k++)
968 for (int j = 0; j + k <= pm1; j++)
969 for (int i = 0; i + j + k <= pm1; i++)
970 {
971 real_t s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k);
972 T(o++, m) = s * tm[0];
973 T(o++, m) = s * tm[1];
974 T(o++, m) = s * tm[2];
975 }
976 for (int k = 0; k <= pm1; k++)
977 for (int j = 0; j + k <= pm1; j++)
978 {
979 real_t s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k);
980 T(o++, m) = s*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]);
981 T(o++, m) = s*((ip.z - c)*tm[0] - (ip.x - c)*tm[2]);
982 }
983 for (int k = 0; k <= pm1; k++)
984 {
985 T(o++, m) =
986 shape_y(pm1-k)*shape_z(k)*((ip.z - c)*tm[1] - (ip.y - c)*tm[2]);
987 }
988 }
989
990 Ti.Factor(T);
991 // mfem::out << "ND_TetrahedronElement(" << p << ") : "; Ti.TestInversion();
992}
993
995 DenseMatrix &shape) const
996{
997 const int pm1 = order - 1;
998
999#ifdef MFEM_THREAD_SAFE
1000 const int p = order;
1001 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
1002 DenseMatrix u(dof, dim);
1003#endif
1004
1005 poly1d.CalcBasis(pm1, ip.x, shape_x);
1006 poly1d.CalcBasis(pm1, ip.y, shape_y);
1007 poly1d.CalcBasis(pm1, ip.z, shape_z);
1008 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l);
1009
1010 int n = 0;
1011 for (int k = 0; k <= pm1; k++)
1012 for (int j = 0; j + k <= pm1; j++)
1013 for (int i = 0; i + j + k <= pm1; i++)
1014 {
1015 real_t s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k);
1016 u(n,0) = s; u(n,1) = 0.; u(n,2) = 0.; n++;
1017 u(n,0) = 0.; u(n,1) = s; u(n,2) = 0.; n++;
1018 u(n,0) = 0.; u(n,1) = 0.; u(n,2) = s; n++;
1019 }
1020 for (int k = 0; k <= pm1; k++)
1021 for (int j = 0; j + k <= pm1; j++)
1022 {
1023 real_t s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k);
1024 u(n,0) = s*(ip.y - c); u(n,1) = -s*(ip.x - c); u(n,2) = 0.; n++;
1025 u(n,0) = s*(ip.z - c); u(n,1) = 0.; u(n,2) = -s*(ip.x - c); n++;
1026 }
1027 for (int k = 0; k <= pm1; k++)
1028 {
1029 real_t s = shape_y(pm1-k)*shape_z(k);
1030 u(n,0) = 0.; u(n,1) = s*(ip.z - c); u(n,2) = -s*(ip.y - c); n++;
1031 }
1032
1033 Ti.Mult(u, shape);
1034}
1035
1037 DenseMatrix &curl_shape) const
1038{
1039 const int pm1 = order - 1;
1040
1041#ifdef MFEM_THREAD_SAFE
1042 const int p = order;
1043 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
1044 Vector dshape_x(p), dshape_y(p), dshape_z(p), dshape_l(p);
1045 DenseMatrix u(dof, dim);
1046#endif
1047
1048 poly1d.CalcBasis(pm1, ip.x, shape_x, dshape_x);
1049 poly1d.CalcBasis(pm1, ip.y, shape_y, dshape_y);
1050 poly1d.CalcBasis(pm1, ip.z, shape_z, dshape_z);
1051 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
1052
1053 int n = 0;
1054 for (int k = 0; k <= pm1; k++)
1055 for (int j = 0; j + k <= pm1; j++)
1056 for (int i = 0; i + j + k <= pm1; i++)
1057 {
1058 int l = pm1-i-j-k;
1059 const real_t dx = (dshape_x(i)*shape_l(l) -
1060 shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k);
1061 const real_t dy = (dshape_y(j)*shape_l(l) -
1062 shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k);
1063 const real_t dz = (dshape_z(k)*shape_l(l) -
1064 shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j);
1065
1066 u(n,0) = 0.; u(n,1) = dz; u(n,2) = -dy; n++;
1067 u(n,0) = -dz; u(n,1) = 0.; u(n,2) = dx; n++;
1068 u(n,0) = dy; u(n,1) = -dx; u(n,2) = 0.; n++;
1069 }
1070 for (int k = 0; k <= pm1; k++)
1071 for (int j = 0; j + k <= pm1; j++)
1072 {
1073 int i = pm1 - j - k;
1074 // s = shape_x(i)*shape_y(j)*shape_z(k);
1075 // curl of s*(ip.y - c, -(ip.x - c), 0):
1076 u(n,0) = shape_x(i)*(ip.x - c)*shape_y(j)*dshape_z(k);
1077 u(n,1) = shape_x(i)*shape_y(j)*(ip.y - c)*dshape_z(k);
1078 u(n,2) =
1079 -((dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k) +
1080 (dshape_y(j)*(ip.y - c) + shape_y(j))*shape_x(i)*shape_z(k));
1081 n++;
1082 // curl of s*(ip.z - c, 0, -(ip.x - c)):
1083 u(n,0) = -shape_x(i)*(ip.x - c)*dshape_y(j)*shape_z(k);
1084 u(n,1) = (shape_x(i)*shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)) +
1085 (dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k));
1086 u(n,2) = -shape_x(i)*dshape_y(j)*shape_z(k)*(ip.z - c);
1087 n++;
1088 }
1089 for (int k = 0; k <= pm1; k++)
1090 {
1091 int j = pm1 - k;
1092 // curl of shape_y(j)*shape_z(k)*(0, ip.z - c, -(ip.y - c)):
1093 u(n,0) = -((dshape_y(j)*(ip.y - c) + shape_y(j))*shape_z(k) +
1094 shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)));
1095 u(n,1) = 0.;
1096 u(n,2) = 0.; n++;
1097 }
1098
1099 Ti.Mult(u, curl_shape);
1100}
1101
1102
1103const real_t ND_TriangleElement::tk[8] =
1104{ 1.,0., -1.,1., 0.,-1., 0.,1. };
1105
1106const real_t ND_TriangleElement::c = 1./3.;
1107
1109 : VectorFiniteElement(2, Geometry::TRIANGLE, p*(p + 2), p,
1110 H_CURL, FunctionSpace::Pk),
1111 dof2tk(dof), doftrans(p)
1112{
1113 const real_t *eop = poly1d.OpenPoints(p - 1);
1114 const real_t *iop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
1115
1116 const int pm1 = p - 1, pm2 = p - 2;
1117
1118#ifndef MFEM_THREAD_SAFE
1119 shape_x.SetSize(p);
1120 shape_y.SetSize(p);
1121 shape_l.SetSize(p);
1122 dshape_x.SetSize(p);
1123 dshape_y.SetSize(p);
1124 dshape_l.SetSize(p);
1125 u.SetSize(dof, dim);
1126 curlu.SetSize(dof);
1127#else
1128 Vector shape_x(p), shape_y(p), shape_l(p);
1129#endif
1130
1131 int n = 0;
1132 // edges
1133 for (int i = 0; i < p; i++) // (0,1)
1134 {
1135 Nodes.IntPoint(n).Set2(eop[i], 0.);
1136 dof2tk[n++] = 0;
1137 }
1138 for (int i = 0; i < p; i++) // (1,2)
1139 {
1140 Nodes.IntPoint(n).Set2(eop[pm1-i], eop[i]);
1141 dof2tk[n++] = 1;
1142 }
1143 for (int i = 0; i < p; i++) // (2,0)
1144 {
1145 Nodes.IntPoint(n).Set2(0., eop[pm1-i]);
1146 dof2tk[n++] = 2;
1147 }
1148
1149 // interior
1150 for (int j = 0; j <= pm2; j++)
1151 for (int i = 0; i + j <= pm2; i++)
1152 {
1153 real_t w = iop[i] + iop[j] + iop[pm2-i-j];
1154 Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w);
1155 dof2tk[n++] = 0;
1156 Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w);
1157 dof2tk[n++] = 3;
1158 }
1159
1160 DenseMatrix T(dof);
1161 for (int m = 0; m < dof; m++)
1162 {
1163 const IntegrationPoint &ip = Nodes.IntPoint(m);
1164 const real_t *tm = tk + 2*dof2tk[m];
1165 n = 0;
1166
1167 poly1d.CalcBasis(pm1, ip.x, shape_x);
1168 poly1d.CalcBasis(pm1, ip.y, shape_y);
1169 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l);
1170
1171 for (int j = 0; j <= pm1; j++)
1172 for (int i = 0; i + j <= pm1; i++)
1173 {
1174 real_t s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j);
1175 T(n++, m) = s * tm[0];
1176 T(n++, m) = s * tm[1];
1177 }
1178 for (int j = 0; j <= pm1; j++)
1179 {
1180 T(n++, m) =
1181 shape_x(pm1-j)*shape_y(j)*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]);
1182 }
1183 }
1184
1185 Ti.Factor(T);
1186 // mfem::out << "ND_TriangleElement(" << p << ") : "; Ti.TestInversion();
1187}
1188
1190 DenseMatrix &shape) const
1191{
1192 const int pm1 = order - 1;
1193
1194#ifdef MFEM_THREAD_SAFE
1195 const int p = order;
1196 Vector shape_x(p), shape_y(p), shape_l(p);
1197 DenseMatrix u(dof, dim);
1198#endif
1199
1200 poly1d.CalcBasis(pm1, ip.x, shape_x);
1201 poly1d.CalcBasis(pm1, ip.y, shape_y);
1202 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l);
1203
1204 int n = 0;
1205 for (int j = 0; j <= pm1; j++)
1206 for (int i = 0; i + j <= pm1; i++)
1207 {
1208 real_t s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j);
1209 u(n,0) = s; u(n,1) = 0; n++;
1210 u(n,0) = 0; u(n,1) = s; n++;
1211 }
1212 for (int j = 0; j <= pm1; j++)
1213 {
1214 real_t s = shape_x(pm1-j)*shape_y(j);
1215 u(n,0) = s*(ip.y - c);
1216 u(n,1) = -s*(ip.x - c);
1217 n++;
1218 }
1219
1220 Ti.Mult(u, shape);
1221}
1222
1224 DenseMatrix &curl_shape) const
1225{
1226 const int pm1 = order - 1;
1227
1228#ifdef MFEM_THREAD_SAFE
1229 const int p = order;
1230 Vector shape_x(p), shape_y(p), shape_l(p);
1231 Vector dshape_x(p), dshape_y(p), dshape_l(p);
1232 Vector curlu(dof);
1233#endif
1234
1235 poly1d.CalcBasis(pm1, ip.x, shape_x, dshape_x);
1236 poly1d.CalcBasis(pm1, ip.y, shape_y, dshape_y);
1237 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l, dshape_l);
1238
1239 int n = 0;
1240 for (int j = 0; j <= pm1; j++)
1241 for (int i = 0; i + j <= pm1; i++)
1242 {
1243 int l = pm1-i-j;
1244 const real_t dx = (dshape_x(i)*shape_l(l) -
1245 shape_x(i)*dshape_l(l)) * shape_y(j);
1246 const real_t dy = (dshape_y(j)*shape_l(l) -
1247 shape_y(j)*dshape_l(l)) * shape_x(i);
1248
1249 curlu(n++) = -dy;
1250 curlu(n++) = dx;
1251 }
1252
1253 for (int j = 0; j <= pm1; j++)
1254 {
1255 int i = pm1 - j;
1256 // curl of shape_x(i)*shape_y(j) * (ip.y - c, -(ip.x - c), 0):
1257 curlu(n++) = -((dshape_x(i)*(ip.x - c) + shape_x(i)) * shape_y(j) +
1258 (dshape_y(j)*(ip.y - c) + shape_y(j)) * shape_x(i));
1259 }
1260
1261 Vector curl2d(curl_shape.Data(),dof);
1262 Ti.Mult(curlu, curl2d);
1263}
1264
1265
1266const real_t ND_SegmentElement::tk[1] = { 1. };
1267
1268ND_SegmentElement::ND_SegmentElement(const int p, const int ob_type)
1269 : VectorTensorFiniteElement(1, p, p - 1, ob_type, H_CURL,
1270 DofMapType::L2_DOF_MAP),
1271 dof2tk(dof)
1272{
1273 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
1274
1275 const real_t *op = poly1d.OpenPoints(p - 1, ob_type);
1276
1277 // set dof2tk and Nodes
1278 for (int i = 0; i < p; i++)
1279 {
1280 dof2tk[i] = 0;
1281 Nodes.IntPoint(i).x = op[i];
1282 }
1283}
1284
1286 Vector &shape) const
1287{
1289 obasis1d.Eval(ip.x, shape);
1290}
1291
1293 DenseMatrix &shape) const
1294{
1295 Vector vshape(shape.Data(), dof);
1296
1297 CalcShape(ip, vshape);
1298}
1299
1301 ElementTransformation &Trans,
1302 Vector &dofs) const
1303{
1304 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
1306 Vector xk(vk, vc.GetVDim());
1307
1311
1312 for (int i = 0; i < dof; i++)
1313 {
1314 const real_t h = cp[i+1] - cp[i];
1315 real_t val = 0.0;
1316
1317 for (int q = 0; q < ir.GetNPoints(); q++)
1318 {
1319 const IntegrationPoint &ip1d = ir.IntPoint(q);
1320 ip.x = cp[i] + h*ip1d.x;
1321 Trans.SetIntPoint(&ip);
1322 vc.Eval(xk, Trans, ip);
1323 val += ip1d.weight*Trans.Jacobian().InnerProduct(tk, vk);
1324 }
1325
1326 dofs(i) = val*h;
1327 }
1328}
1329
1330const real_t ND_WedgeElement::tk[15] =
1331{ 1.,0.,0., -1.,1.,0., 0.,-1.,0., 0.,0.,1., 0.,1.,0. };
1332
1334 const int cb_type,
1335 const int ob_type)
1336 : VectorFiniteElement(3, Geometry::PRISM,
1337 3 * p * ((p + 1) * (p + 2))/2, p,
1338 H_CURL, FunctionSpace::Qk),
1339 dof2tk(dof),
1340 t_dof(dof),
1341 s_dof(dof),
1342 doftrans(p),
1343 H1TriangleFE(p, cb_type),
1344 NDTriangleFE(p),
1345 H1SegmentFE(p, cb_type),
1346 NDSegmentFE(p, ob_type)
1347{
1348 MFEM_ASSERT(H1TriangleFE.GetDof() * NDSegmentFE.GetDof() +
1349 NDTriangleFE.GetDof() * H1SegmentFE.GetDof() == dof,
1350 "Mismatch in number of degrees of freedom "
1351 "when building ND_WedgeElement!");
1352
1353#ifndef MFEM_THREAD_SAFE
1354 t1_shape.SetSize(H1TriangleFE.GetDof());
1355 s1_shape.SetSize(H1SegmentFE.GetDof());
1356 tn_shape.SetSize(NDTriangleFE.GetDof(), 2);
1357 sn_shape.SetSize(NDSegmentFE.GetDof(), 1);
1358 t1_dshape.SetSize(H1TriangleFE.GetDof(), 2);
1359 s1_dshape.SetSize(H1SegmentFE.GetDof(), 1);
1360 tn_dshape.SetSize(NDTriangleFE.GetDof(), 1);
1361#endif
1362
1363 const int pm1 = p - 1, pm2 = p - 2;
1364
1365 const IntegrationRule &t1_n = H1TriangleFE.GetNodes();
1366 const IntegrationRule &tn_n = NDTriangleFE.GetNodes();
1367 const IntegrationRule &s1_n = H1SegmentFE.GetNodes();
1368 const IntegrationRule &sn_n = NDSegmentFE.GetNodes();
1369
1370 // edges
1371 int o = 0;
1372 for (int i = 0; i < p; i++) // (0,1)
1373 {
1374 t_dof[o] = i; s_dof[o] = 0; dof2tk[o] = 0;
1375 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1376 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1377 o++;
1378 }
1379 for (int i = 0; i < p; i++) // (1,2)
1380 {
1381 t_dof[o] = p + i; s_dof[o] = 0; dof2tk[o] = 1;
1382 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1383 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1384 o++;
1385 }
1386 for (int i = 0; i < p; i++) // (2,0)
1387 {
1388 t_dof[o] = 2 * p + i; s_dof[o] = 0; dof2tk[o] = 2;
1389 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1390 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1391 o++;
1392 }
1393 for (int i = 0; i < p; i++) // (3,4)
1394 {
1395 t_dof[o] = i; s_dof[o] = 1; dof2tk[o] = 0;
1396 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1397 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1398 o++;
1399 }
1400 for (int i = 0; i < p; i++) // (4,5)
1401 {
1402 t_dof[o] = p + i; s_dof[o] = 1; dof2tk[o] = 1;
1403 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1404 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1405 o++;
1406 }
1407 for (int i = 0; i < p; i++) // (5,3)
1408 {
1409 t_dof[o] = 2 * p + i; s_dof[o] = 1; dof2tk[o] = 2;
1410 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1411 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1412 o++;
1413 }
1414 for (int i = 0; i < p; i++) // (0,3)
1415 {
1416 t_dof[o] = 0; s_dof[o] = i; dof2tk[o] = 3;
1417 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1418 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1419 o++;
1420 }
1421 for (int i = 0; i < p; i++) // (1,4)
1422 {
1423 t_dof[o] = 1; s_dof[o] = i; dof2tk[o] = 3;
1424 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1425 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1426 o++;
1427 }
1428 for (int i = 0; i < p; i++) // (2,5)
1429 {
1430 t_dof[o] = 2; s_dof[o] = i; dof2tk[o] = 3;
1431 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1432 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1433 o++;
1434 }
1435
1436 // faces
1437 // (0,2,1) -- bottom
1438 int l = 0;
1439 for (int j = 0; j <= pm2; j++)
1440 for (int i = 0; i + j <= pm2; i++)
1441 {
1442 l = j + ( 2 * p - 1 - i) * i / 2;
1443 t_dof[o] = 3 * p + 2*l+1; s_dof[o] = 0; dof2tk[o] = 4;
1444 const IntegrationPoint & t_ip0 = tn_n.IntPoint(t_dof[o]);
1445 Nodes.IntPoint(o).Set3(t_ip0.x, t_ip0.y, s1_n.IntPoint(s_dof[o]).x);
1446 o++;
1447 t_dof[o] = 3 * p + 2*l; s_dof[o] = 0; dof2tk[o] = 0;
1448 const IntegrationPoint & t_ip1 = tn_n.IntPoint(t_dof[o]);
1449 Nodes.IntPoint(o).Set3(t_ip1.x, t_ip1.y, s1_n.IntPoint(s_dof[o]).x);
1450 o++;
1451 }
1452 // (3,4,5) -- top
1453 int m = 0;
1454 for (int j = 0; j <= pm2; j++)
1455 for (int i = 0; i + j <= pm2; i++)
1456 {
1457 t_dof[o] = 3 * p + m; s_dof[o] = 1; dof2tk[o] = 0; m++;
1458 const IntegrationPoint & t_ip0 = tn_n.IntPoint(t_dof[o]);
1459 Nodes.IntPoint(o).Set3(t_ip0.x, t_ip0.y, s1_n.IntPoint(s_dof[o]).x);
1460 o++;
1461 t_dof[o] = 3 * p + m; s_dof[o] = 1; dof2tk[o] = 4; m++;
1462 const IntegrationPoint & t_ip1 = tn_n.IntPoint(t_dof[o]);
1463 Nodes.IntPoint(o).Set3(t_ip1.x, t_ip1.y, s1_n.IntPoint(s_dof[o]).x);
1464 o++;
1465 }
1466 // (0, 1, 4, 3) -- xz plane
1467 for (int j = 2; j <= p; j++)
1468 for (int i = 0; i < p; i++)
1469 {
1470 t_dof[o] = i; s_dof[o] = j; dof2tk[o] = 0;
1471 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1472 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1473 o++;
1474 }
1475 for (int j = 0; j < p; j++)
1476 for (int i = 0; i < pm1; i++)
1477 {
1478 t_dof[o] = 3 + i; s_dof[o] = j; dof2tk[o] = 3;
1479 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1480 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1481 o++;
1482 }
1483 // (1, 2, 5, 4) -- (y-x)z plane
1484 for (int j = 2; j <= p; j++)
1485 for (int i = 0; i < p; i++)
1486 {
1487 t_dof[o] = p + i; s_dof[o] = j; dof2tk[o] = 1;
1488 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1489 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1490 o++;
1491 }
1492 for (int j = 0; j < p; j++)
1493 for (int i = 0; i < pm1; i++)
1494 {
1495 t_dof[o] = p + 2 + i; s_dof[o] = j; dof2tk[o] = 3;
1496 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1497 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1498 o++;
1499 }
1500 // (2, 0, 3, 5) -- yz plane
1501 for (int j = 2; j <= p; j++)
1502 for (int i = 0; i < p; i++)
1503 {
1504 t_dof[o] = 2 * p + i; s_dof[o] = j; dof2tk[o] = 2;
1505 const IntegrationPoint & t_ip = tn_n.IntPoint(t_dof[o]);
1506 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, s1_n.IntPoint(s_dof[o]).x);
1507 o++;
1508 }
1509 for (int j = 0; j < p; j++)
1510 for (int i = 0; i < pm1; i++)
1511 {
1512 t_dof[o] = 2 * p + 1 + i; s_dof[o] = j; dof2tk[o] = 3;
1513 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1514 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1515 o++;
1516 }
1517
1518 // interior
1519 for (int k = 2; k <= p; k++)
1520 {
1521 l = 0;
1522 for (int j = 0; j <= pm2; j++)
1523 for (int i = 0; i + j <= pm2; i++)
1524 {
1525 t_dof[o] = 3 * p + l; s_dof[o] = k; dof2tk[o] = 0; l++;
1526 const IntegrationPoint & t_ip0 = tn_n.IntPoint(t_dof[o]);
1527 Nodes.IntPoint(o).Set3(t_ip0.x, t_ip0.y, s1_n.IntPoint(s_dof[o]).x);
1528 o++;
1529 t_dof[o] = 3 * p + l; s_dof[o] = k; dof2tk[o] = 4; l++;
1530 const IntegrationPoint & t_ip1 = tn_n.IntPoint(t_dof[o]);
1531 Nodes.IntPoint(o).Set3(t_ip1.x, t_ip1.y, s1_n.IntPoint(s_dof[o]).x);
1532 o++;
1533 }
1534 }
1535 for (int k = 0; k < p; k++)
1536 {
1537 l = 0;
1538 for (int j = 0; j < pm2; j++)
1539 for (int i = 0; i + j < pm2; i++)
1540 {
1541 t_dof[o] = 3 * p + l; s_dof[o] = k; dof2tk[o] = 3; l++;
1542 const IntegrationPoint & t_ip = t1_n.IntPoint(t_dof[o]);
1543 Nodes.IntPoint(o).Set3(t_ip.x, t_ip.y, sn_n.IntPoint(s_dof[o]).x);
1544 o++;
1545 }
1546 }
1547}
1548
1550 DenseMatrix &shape) const
1551{
1552#ifdef MFEM_THREAD_SAFE
1553 Vector t1_shape(H1TriangleFE.GetDof());
1554 Vector s1_shape(H1SegmentFE.GetDof());
1555 DenseMatrix tn_shape(NDTriangleFE.GetDof(), 2);
1556 DenseMatrix sn_shape(NDSegmentFE.GetDof(), 1);
1557#endif
1558
1559 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1560
1561 H1TriangleFE.CalcShape(ip, t1_shape);
1562 NDTriangleFE.CalcVShape(ip, tn_shape);
1563 H1SegmentFE.CalcShape(ipz, s1_shape);
1564 NDSegmentFE.CalcVShape(ipz, sn_shape);
1565
1566 for (int i=0; i<dof; i++)
1567 {
1568 if ( dof2tk[i] != 3 )
1569 {
1570 shape(i, 0) = tn_shape(t_dof[i], 0) * s1_shape[s_dof[i]];
1571 shape(i, 1) = tn_shape(t_dof[i], 1) * s1_shape[s_dof[i]];
1572 shape(i, 2) = 0.0;
1573 }
1574 else
1575 {
1576 shape(i, 0) = 0.0;
1577 shape(i, 1) = 0.0;
1578 shape(i, 2) = t1_shape[t_dof[i]] * sn_shape(s_dof[i], 0);
1579 }
1580 }
1581}
1582
1584 DenseMatrix &curl_shape) const
1585{
1586#ifdef MFEM_THREAD_SAFE
1587 Vector s1_shape(H1SegmentFE.GetDof());
1588 DenseMatrix t1_dshape(H1TriangleFE.GetDof(), 2);
1589 DenseMatrix s1_dshape(H1SegmentFE.GetDof(), 1);
1590 DenseMatrix tn_shape(NDTriangleFE.GetDof(), 2);
1591 DenseMatrix sn_shape(NDSegmentFE.GetDof(), 1);
1592 DenseMatrix tn_dshape(NDTriangleFE.GetDof(), 1);
1593#endif
1594
1595 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
1596
1597 H1TriangleFE.CalcDShape(ip, t1_dshape);
1598 H1SegmentFE.CalcShape(ipz, s1_shape);
1599 H1SegmentFE.CalcDShape(ipz, s1_dshape);
1600 NDTriangleFE.CalcVShape(ip, tn_shape);
1601 NDTriangleFE.CalcCurlShape(ip, tn_dshape);
1602 NDSegmentFE.CalcVShape(ipz, sn_shape);
1603
1604 for (int i=0; i<dof; i++)
1605 {
1606 if ( dof2tk[i] != 3 )
1607 {
1608 curl_shape(i, 0) = -tn_shape(t_dof[i], 1) * s1_dshape(s_dof[i], 0);
1609 curl_shape(i, 1) = tn_shape(t_dof[i], 0) * s1_dshape(s_dof[i], 0);
1610 curl_shape(i, 2) = tn_dshape(t_dof[i], 0) * s1_shape[s_dof[i]];
1611 }
1612 else
1613 {
1614 curl_shape(i, 0) = t1_dshape(t_dof[i], 1) * sn_shape(s_dof[i], 0);
1615 curl_shape(i, 1) = -t1_dshape(t_dof[i], 0) * sn_shape(s_dof[i], 0);
1616 curl_shape(i, 2) = 0.0;
1617 }
1618 }
1619}
1620
1621const real_t ND_FuentesPyramidElement::tk[27] =
1622{
1623 1., 0., 0., 0., 1., 0., 0., 0., 1.,
1624 -1., 0., 1., -1.,-1., 1., 0.,-1., 1.,
1625 -1., 0., 0., 0.,-1., 0., -M_SQRT1_2,-M_SQRT1_2,M_SQRT2
1626};
1627
1629 const int cb_type,
1630 const int ob_type)
1631 : VectorFiniteElement(3, Geometry::PYRAMID, p * (3 * p * p + 5), p,
1632 H_CURL, FunctionSpace::Uk),
1633 dof2tk(dof), doftrans(p)
1634{
1635 zmax = 0.0;
1636
1637 const real_t *eop = poly1d.OpenPoints(p - 1);
1638 const real_t *top = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
1639 const real_t *qop = poly1d.OpenPoints(p - 1, ob_type);
1640 const real_t *qcp = poly1d.ClosedPoints(p, cb_type);
1641
1642 const int pm2 = p - 2;
1643
1644#ifndef MFEM_THREAD_SAFE
1645 tmp_E_E_ij.SetSize(p, dim);
1646 tmp_dE_E_ij.SetSize(p, dim);
1647 tmp_E_Q1_ijk.SetSize(p, p + 1, dim);
1648 tmp_dE_Q1_ijk.SetSize(p, p + 1, dim);
1649 tmp_E_Q2_ijk.SetSize(p, p + 1, dim);
1650 tmp_dE_Q2_ijk.SetSize(p, p + 1, dim);
1651 tmp_E_T_ijk.SetSize(p - 1, p, dim);
1652 tmp_dE_T_ijk.SetSize(p - 1, p, dim);
1653 tmp_phi_Q1_ij.SetSize(p + 1, p + 1);
1654 tmp_dphi_Q1_ij.SetSize(p + 1, p + 1, dim);
1655 tmp_phi_Q2_ij.SetSize(p + 1, p + 1);
1656 tmp_dphi_Q2_ij.SetSize(p + 1, p + 1, dim);
1657 tmp_phi_E_i.SetSize(p + 1);
1658 tmp_dphi_E_i.SetSize(p + 1, dim);
1659 u.SetSize(dof, dim);
1660 curlu.SetSize(dof, dim);
1661#else
1662 DenseMatrix tmp_E_E_ij(p, dim);
1663 DenseTensor tmp_E_Q1_ijk(p, p + 1, dim);
1664 DenseTensor tmp_dE_Q1_ijk(p, p + 1, dim);
1665 DenseTensor tmp_E_Q2_ijk(p, p + 1, dim);
1666 DenseTensor tmp_dE_Q2_ijk(p, p + 1, dim);
1667 DenseTensor tmp_E_T_ijk(p - 1, p, dim);
1668 DenseTensor tmp_dE_T_ijk(p - 1, p, dim);
1669 DenseMatrix tmp_phi_Q1_ij(p + 1, p + 1);
1670 DenseTensor tmp_dphi_Q1_ij(p + 1, p + 1, dim);
1671 DenseMatrix tmp_phi_Q2_ij(p + 1, p + 1);
1672 Vector tmp_phi_E_i(p + 1);
1673 DenseMatrix tmp_dphi_E_i(p + 1, dim);
1674 DenseMatrix u(dof, dim);
1675#endif
1676
1677 int o = 0;
1678
1679 // edges
1680 for (int i = 0; i < p; i++) // (0, 1)
1681 {
1682 Nodes.IntPoint(o).Set3(eop[i], 0., 0.);
1683 dof2tk[o++] = 0;
1684 }
1685 for (int i = 0; i < p; i++) // (1, 2)
1686 {
1687 Nodes.IntPoint(o).Set3(1., eop[i], 0.);
1688 dof2tk[o++] = 1;
1689 }
1690 for (int i = 0; i < p; i++) // (3, 2)
1691 {
1692 Nodes.IntPoint(o).Set3(eop[i], 1., 0.);
1693 dof2tk[o++] = 0;
1694 }
1695 for (int i = 0; i < p; i++) // (0, 3)
1696 {
1697 Nodes.IntPoint(o).Set3(0., eop[i], 0.);
1698 dof2tk[o++] = 1;
1699 }
1700 for (int i = 0; i < p; i++) // (0, 4)
1701 {
1702 Nodes.IntPoint(o).Set3(0., 0., eop[i]);
1703 dof2tk[o++] = 2;
1704 }
1705 for (int i = 0; i < p; i++) // (1, 4)
1706 {
1707 Nodes.IntPoint(o).Set3(1. - eop[i], 0., eop[i]);
1708 dof2tk[o++] = 3;
1709 }
1710 for (int i = 0; i < p; i++) // (2, 4)
1711 {
1712 Nodes.IntPoint(o).Set3(1. - eop[i], 1. - eop[i], eop[i]);
1713 dof2tk[o++] = 4;
1714 }
1715 for (int i = 0; i < p; i++) // (3, 4)
1716 {
1717 Nodes.IntPoint(o).Set3(0., 1. - eop[i], eop[i]);
1718 dof2tk[o++] = 5;
1719 }
1720
1721 // quadrilateral face (3, 2, 1, 0)
1722 // x-components
1723 for (int j = 1; j < p; j++)
1724 for (int i = 0; i < p; i++)
1725 {
1726 Nodes.IntPoint(o).Set3(qop[i], qcp[p-j], 0.);
1727 dof2tk[o++] = 0; // (1 0 0)
1728 }
1729
1730 // y-components
1731 for (int j = 0; j < p; j++)
1732 for (int i = 1; i < p; i++)
1733 {
1734 Nodes.IntPoint(o).Set3(qcp[i], qop[p-1-j], 0.);
1735 dof2tk[o++] = 7; // (0 -1 0)
1736 }
1737
1738 // triangular faces
1739 for (int j = 0; j <= pm2; j++) // (0, 1, 4)
1740 for (int i = 0; i + j <= pm2; i++)
1741 {
1742 real_t w = top[i] + top[j] + top[pm2-i-j];
1743 Nodes.IntPoint(o).Set3(top[i]/w, 0., top[j]/w);
1744 dof2tk[o++] = 0;
1745 Nodes.IntPoint(o).Set3(top[i]/w, 0., top[j]/w);
1746 dof2tk[o++] = 2;
1747 }
1748 for (int j = 0; j <= pm2; j++) // (1, 2, 4)
1749 for (int i = 0; i + j <= pm2; i++)
1750 {
1751 real_t w = top[i] + top[j] + top[pm2-i-j];
1752 Nodes.IntPoint(o).Set3((top[i] + top[pm2-i-j])/w, top[i]/w, top[j]/w);
1753 dof2tk[o++] = 1;
1754 Nodes.IntPoint(o).Set3((top[i] + top[pm2-i-j])/w, top[i]/w, top[j]/w);
1755 dof2tk[o++] = 3;
1756 }
1757 for (int j = 0; j <= pm2; j++) // (2, 3, 4)
1758 for (int i = 0; i + j <= pm2; i++)
1759 {
1760 real_t w = top[i] + top[j] + top[pm2-i-j];
1761 Nodes.IntPoint(o).Set3(top[pm2-i-j]/w, (top[i] + top[pm2-i-j])/w,
1762 top[j]/w);
1763 dof2tk[o++] = 6;
1764 Nodes.IntPoint(o).Set3(top[pm2-i-j]/w, (top[i] + top[pm2-i-j])/w,
1765 top[j]/w);
1766 dof2tk[o++] = 4;
1767 }
1768 for (int j = 0; j <= pm2; j++) // (3, 0, 4)
1769 for (int i = 0; i + j <= pm2; i++)
1770 {
1771 real_t w = top[i] + top[j] + top[pm2-i-j];
1772 Nodes.IntPoint(o).Set3(0., top[pm2-i-j]/w, top[j]/w);
1773 dof2tk[o++] = 7;
1774 Nodes.IntPoint(o).Set3(0., top[pm2-i-j]/w, top[j]/w);
1775 dof2tk[o++] = 5;
1776 }
1777
1778 // interior
1779 // x-components
1780 for (int k = 1; k < p; k++)
1781 for (int j = 1; j < p; j++)
1782 for (int i = 0; i < p; i++)
1783 {
1784 real_t w = 1.0 - qcp[k];
1785 Nodes.IntPoint(o).Set3(qop[i]*w, qcp[j]*w, qcp[k]);
1786 dof2tk[o++] = 0;
1787 }
1788 // y-components
1789 for (int k = 1; k < p; k++)
1790 for (int j = 0; j < p; j++)
1791 for (int i = 1; i < p; i++)
1792 {
1793 real_t w = 1.0 - qcp[k];
1794 Nodes.IntPoint(o).Set3(qcp[i]*w, qop[j]*w, qcp[k]);
1795 dof2tk[o++] = 1;
1796 }
1797 // z-components
1798 for (int k = 0; k < p; k++)
1799 for (int j = 1; j < p; j++)
1800 for (int i = 1; i < p; i++)
1801 {
1802 real_t w = 1.0 - qop[k];
1803 Nodes.IntPoint(o).Set3(qcp[i]*w, qcp[j]*w, qop[k]);
1804 dof2tk[o++] = 8;
1805 }
1806
1807 DenseMatrix T(dof);
1808
1809 for (int m = 0; m < dof; m++)
1810 {
1811 const IntegrationPoint &ip = Nodes.IntPoint(m);
1812 calcBasis(p, ip, tmp_E_E_ij, tmp_E_Q1_ijk, tmp_E_Q2_ijk, tmp_E_T_ijk,
1813 tmp_phi_Q1_ij, tmp_dphi_Q1_ij, tmp_phi_Q2_ij,
1814 tmp_phi_E_i, tmp_dphi_E_i, u);
1815
1816 const Vector tm({tk[3*dof2tk[m]], tk[3*dof2tk[m]+1], tk[3*dof2tk[m]+2]});
1817 u.Mult(tm, T.GetColumn(m));
1818 }
1819
1820 Ti.Factor(T);
1821}
1822
1824 DenseMatrix &shape) const
1825{
1826 const int p = order;
1827
1828#ifdef MFEM_THREAD_SAFE
1829 DenseMatrix tmp_E_E_ij(p, dim);
1830 DenseTensor tmp_E_Q1_ijk(p, p + 1, dim);
1831 DenseTensor tmp_E_Q2_ijk(p, p + 1, dim);
1832 DenseTensor tmp_E_T_ijk(p - 1, p, dim);
1833 DenseMatrix tmp_phi_Q1_ij(p + 1, p + 1);
1834 DenseTensor tmp_dphi_Q1_ij(p + 1, p + 1, dim);
1835 DenseMatrix tmp_phi_Q2_ij(p + 1, p + 1);
1836 Vector tmp_phi_E_i(p + 1);
1837 DenseMatrix tmp_dphi_E_i(p + 1, dim);
1838 DenseMatrix u(dof, dim);
1839#endif
1840
1841 calcBasis(p, ip, tmp_E_E_ij, tmp_E_Q1_ijk, tmp_E_Q2_ijk, tmp_E_T_ijk,
1842 tmp_phi_Q1_ij, tmp_dphi_Q1_ij, tmp_phi_Q2_ij,
1843 tmp_phi_E_i, tmp_dphi_E_i, u);
1844
1845 Ti.Mult(u, shape);
1846}
1847
1849 DenseMatrix &curl_shape) const
1850{
1851 const int p = order;
1852
1853#ifdef MFEM_THREAD_SAFE
1854 DenseMatrix tmp_E_E_ij(p, dim);
1855 DenseMatrix tmp_dE_E_ij(p, dim);
1856 DenseTensor tmp_E_Q1_ijk(p, p + 1, dim);
1857 DenseTensor tmp_dE_Q1_ijk(p, p + 1, dim);
1858 DenseTensor tmp_E_Q2_ijk(p, p + 1, dim);
1859 DenseTensor tmp_dE_Q2_ijk(p, p + 1, dim);
1860 DenseTensor tmp_E_T_ijk(p - 1, p, dim);
1861 DenseTensor tmp_dE_T_ijk(p - 1, p, dim);
1862 DenseMatrix tmp_phi_Q2_ij(p + 1, p + 1);
1863 DenseTensor tmp_dphi_Q2_ij(p + 1, p + 1, dim);
1864 Vector tmp_phi_E_i(p + 1);
1865 DenseMatrix tmp_dphi_E_i(p + 1, dim);
1866 DenseMatrix curlu(dof, dim);
1867#endif
1868
1869 calcCurlBasis(p, ip, tmp_E_E_ij, tmp_dE_E_ij, tmp_E_Q1_ijk, tmp_dE_Q1_ijk,
1870 tmp_E_Q2_ijk, tmp_dE_Q2_ijk, tmp_E_T_ijk, tmp_dE_T_ijk,
1871 tmp_phi_Q2_ij, tmp_dphi_Q2_ij, tmp_phi_E_i, tmp_dphi_E_i,
1872 curlu);
1873
1874 Ti.Mult(curlu, curl_shape);
1875}
1876
1878 DenseMatrix &shape) const
1879{
1880 const int p = order;
1881
1882#ifdef MFEM_THREAD_SAFE
1883 DenseMatrix tmp_E_E_ij(p, dim);
1884 DenseTensor tmp_E_Q1_ijk(p, p + 1, dim);
1885 DenseTensor tmp_E_Q2_ijk(p, p + 1, dim);
1886 DenseTensor tmp_E_T_ijk(p - 1, p, dim);
1887 DenseMatrix tmp_phi_Q1_ij(p + 1, p + 1);
1888 DenseTensor tmp_dphi_Q1_ij(p + 1, p + 1, dim);
1889 DenseMatrix tmp_phi_Q2_ij(p + 1, p + 1);
1890 Vector tmp_phi_E_i(p + 1);
1891 DenseMatrix tmp_dphi_E_i(p + 1, dim);
1892#endif
1893
1894 calcBasis(p, ip, tmp_E_E_ij, tmp_E_Q1_ijk, tmp_E_Q2_ijk, tmp_E_T_ijk,
1895 tmp_phi_Q1_ij, tmp_dphi_Q1_ij, tmp_phi_Q2_ij,
1896 tmp_phi_E_i, tmp_dphi_E_i, shape);
1897}
1898
1900 DenseMatrix &dshape) const
1901{
1902 const int p = order;
1903
1904#ifdef MFEM_THREAD_SAFE
1905 DenseMatrix tmp_E_E_ij(p, dim);
1906 DenseMatrix tmp_dE_E_ij(p, dim);
1907 DenseTensor tmp_E_Q1_ijk(p, p + 1, dim);
1908 DenseTensor tmp_dE_Q1_ijk(p, p + 1, dim);
1909 DenseTensor tmp_E_Q2_ijk(p, p + 1, dim);
1910 DenseTensor tmp_dE_Q2_ijk(p, p + 1, dim);
1911 DenseTensor tmp_E_T_ijk(p - 1, p, dim);
1912 DenseTensor tmp_dE_T_ijk(p - 1, p, dim);
1913 DenseMatrix tmp_phi_Q2_ij(p + 1, p + 1);
1914 DenseTensor tmp_dphi_Q2_ij(p + 1, p + 1, dim);
1915 Vector tmp_phi_E_i(p + 1);
1916 DenseMatrix tmp_dphi_E_i(p + 1, dim);
1917#endif
1918
1919 calcCurlBasis(p, ip, tmp_E_E_ij, tmp_dE_E_ij, tmp_E_Q1_ijk, tmp_dE_Q1_ijk,
1920 tmp_E_Q2_ijk, tmp_dE_Q2_ijk, tmp_E_T_ijk, tmp_dE_T_ijk,
1921 tmp_phi_Q2_ij, tmp_dphi_Q2_ij, tmp_phi_E_i, tmp_dphi_E_i,
1922 dshape);
1923}
1924
1925void ND_FuentesPyramidElement::calcBasis(const int p,
1926 const IntegrationPoint &ip,
1927 DenseMatrix & E_E_ik,
1928 DenseTensor & E_Q1_ijk,
1929 DenseTensor & E_Q2_ijk,
1930 DenseTensor & E_T_ijk,
1931 DenseMatrix & phi_Q1_ij,
1932 DenseTensor & dphi_Q1_ij,
1933 DenseMatrix & phi_Q2_ij,
1934 Vector & phi_E_k,
1935 DenseMatrix & dphi_E_k,
1936 DenseMatrix &W) const
1937{
1938 real_t x = ip.x;
1939 real_t y = ip.y;
1940 real_t z = ip.z;
1941 Vector xy({x,y}), dmu(3);
1942 real_t mu, mu2;
1943
1944 if (std::fabs(1.0 - z) < apex_tol)
1945 {
1946 z = 1.0 - apex_tol;
1947 y = 0.5 * (1.0 - z);
1948 x = 0.5 * (1.0 - z);
1949 xy(0) = x; xy(1) = y;
1950 }
1951 zmax = std::max(z, zmax);
1952
1953 W = 0.0;
1954
1955 int o = 0;
1956
1957 // Mixed Edges
1958 if (z < 1.0)
1959 {
1960 // (a, b) = (1, 2), c = 0
1961 mu = mu0(z, xy, 2);
1962 E_E(p, nu01(z, xy, 1), nu01_grad_nu01(z, xy, 1), E_E_ik);
1963 for (int i=0; i<p; i++, o++)
1964 for (int k=0; k<3; k++)
1965 {
1966 W(o, k) = mu * E_E_ik(i, k);
1967 }
1968
1969 // (a, b) = (1, 2), c = 1
1970 mu = mu1(z, xy, 2);
1971 for (int i=0; i<p; i++, o++)
1972 for (int k=0; k<3; k++)
1973 {
1974 W(o, k) = mu * E_E_ik(i, k);
1975 }
1976
1977 // (a, b) = (2, 1), c = 0
1978 mu = mu0(z, xy, 1);
1979 E_E(p, nu01(z, xy, 2), nu01_grad_nu01(z, xy, 2), E_E_ik);
1980 for (int i=0; i<p; i++, o++)
1981 for (int k=0; k<3; k++)
1982 {
1983 W(o, k) = mu * E_E_ik(i, k);
1984 }
1985
1986 // (a, b) = (2, 1), c = 1
1987 mu = mu1(z, xy, 1);
1988 for (int i=0; i<p; i++, o++)
1989 for (int k=0; k<3; k++)
1990 {
1991 W(o, k) = mu * E_E_ik(i, k);
1992 }
1993 }
1994
1995 // Triangle Edges
1996 if (z < 1.0)
1997 {
1998 E_E(p, lam15(x, y, z), lam15_grad_lam15(x, y, z), E_E_ik);
1999 for (int i=0; i<p; i++, o++)
2000 for (int k=0; k<3; k++)
2001 {
2002 W(o, k) = E_E_ik(i, k);
2003 }
2004
2005 E_E(p, lam25(x, y, z), lam25_grad_lam25(x, y, z), E_E_ik);
2006 for (int i=0; i<p; i++, o++)
2007 for (int k=0; k<3; k++)
2008 {
2009 W(o, k) = E_E_ik(i, k);
2010 }
2011
2012 E_E(p, lam35(x, y, z), lam35_grad_lam35(x, y, z), E_E_ik);
2013 for (int i=0; i<p; i++, o++)
2014 for (int k=0; k<3; k++)
2015 {
2016 W(o, k) = E_E_ik(i, k);
2017 }
2018
2019 E_E(p, lam45(x, y, z), lam45_grad_lam45(x, y, z), E_E_ik);
2020 for (int i=0; i<p; i++, o++)
2021 for (int k=0; k<3; k++)
2022 {
2023 W(o, k) = E_E_ik(i, k);
2024 }
2025 }
2026
2027 // Quadrilateral Face
2028 if (z < 1.0 && p >= 2)
2029 {
2030 mu = mu0(z);
2031 mu2 = mu * mu;
2032
2033 // Family I
2034 E_Q(p, mu01(z, xy, 1), mu01_grad_mu01(z, xy, 1), mu01(z, xy, 2),
2035 E_Q1_ijk);
2036 for (int j=2; j<=p; j++)
2037 for (int i=0; i<p; i++, o++)
2038 for (int k=0; k<3; k++)
2039 {
2040 W(o, k) = mu2 * E_Q1_ijk(i, j, k);
2041 }
2042
2043 // Family II
2044 E_Q(p, mu01(z, xy, 2), mu01_grad_mu01(z, xy, 2), mu01(z, xy, 1),
2045 E_Q2_ijk);
2046 for (int j=2; j<=p; j++)
2047 for (int i=0; i<p; i++, o++)
2048 for (int k=0; k<3; k++)
2049 {
2050 W(o, k) = mu2 * E_Q2_ijk(i, j, k);
2051 }
2052 }
2053
2054 // Triangular Faces
2055 if (z < 1.0 && p >= 2)
2056 {
2057 // Family I
2058 // (a, b) = (1, 2), c = 0
2059 mu = mu0(z, xy, 2);
2060 E_T(p, nu012(z, xy, 1), nu01_grad_nu01(z, xy, 1), E_T_ijk);
2061 for (int j=1; j<p; j++)
2062 for (int i=0; i+j<p; i++, o++)
2063 for (int k=0; k<3; k++)
2064 {
2065 W(o, k) = mu * E_T_ijk(i, j, k);
2066 }
2067
2068 // (a, b) = (1, 2), c = 1
2069 mu = mu1(z, xy, 2);
2070 for (int j=1; j<p; j++)
2071 for (int i=0; i+j<p; i++, o++)
2072 for (int k=0; k<3; k++)
2073 {
2074 W(o, k) = mu * E_T_ijk(i, j, k);
2075 }
2076
2077 // (a, b) = (2, 1), c = 0
2078 mu = mu0(z, xy, 1);
2079 E_T(p, nu012(z, xy, 2), nu01_grad_nu01(z, xy, 2), E_T_ijk);
2080 for (int j=1; j<p; j++)
2081 for (int i=0; i+j<p; i++, o++)
2082 for (int k=0; k<3; k++)
2083 {
2084 W(o, k) = mu * E_T_ijk(i, j, k);
2085 }
2086
2087 // (a, b) = (2, 1), c = 1
2088 mu = mu1(z, xy, 1);
2089 for (int j=1; j<p; j++)
2090 for (int i=0; i+j<p; i++, o++)
2091 for (int k=0; k<3; k++)
2092 {
2093 W(o, k) = mu * E_T_ijk(i, j, k);
2094 }
2095
2096 // Family II
2097 // (a, b) = (1, 2), c = 0
2098 mu = mu0(z, xy, 2);
2099 E_T(p, nu120(z, xy, 1), nu12_grad_nu12(z, xy, 1), E_T_ijk);
2100 for (int j=1; j<p; j++)
2101 for (int i=0; i+j<p; i++, o++)
2102 for (int k=0; k<3; k++)
2103 {
2104 W(o, k) = mu * E_T_ijk(i, j, k);
2105 }
2106
2107 // (a, b) = (1, 2), c = 1
2108 mu = mu1(z, xy, 2);
2109 for (int j=1; j<p; j++)
2110 for (int i=0; i+j<p; i++, o++)
2111 for (int k=0; k<3; k++)
2112 {
2113 W(o, k) = mu * E_T_ijk(i, j, k);
2114 }
2115
2116 // (a, b) = (2, 1), c = 0
2117 mu = mu0(z, xy, 1);
2118 E_T(p, nu120(z, xy, 2), nu12_grad_nu12(z, xy, 2), E_T_ijk);
2119 for (int j=1; j<p; j++)
2120 for (int i=0; i+j<p; i++, o++)
2121 for (int k=0; k<3; k++)
2122 {
2123 W(o, k) = mu * E_T_ijk(i, j, k);
2124 }
2125
2126 // (a, b) = (2, 1), c = 1
2127 mu = mu1(z, xy, 1);
2128 for (int j=1; j<p; j++)
2129 for (int i=0; i+j<p; i++, o++)
2130 for (int k=0; k<3; k++)
2131 {
2132 W(o, k) = mu * E_T_ijk(i, j, k);
2133 }
2134 }
2135
2136 // Interior
2137 if (z < 1.0 && p >= 2)
2138 {
2139 // Family I
2140 phi_Q(p, mu01(z, xy, 1), grad_mu01(z, xy, 1), mu01(z, xy, 2),
2141 grad_mu01(z, xy, 2), phi_Q1_ij, dphi_Q1_ij);
2142 phi_E(p, mu01(z), grad_mu01(z), phi_E_k, dphi_E_k);
2143 for (int k=2; k<=p; k++)
2144 for (int j=2; j<=p; j++)
2145 for (int i=2; i<=p; i++, o++)
2146 for (int l=0; l<3; l++)
2147 W(o, l) = dphi_Q1_ij(i, j, l) * phi_E_k(k) +
2148 phi_Q1_ij(i, j) * dphi_E_k(k, l);
2149
2150 // Family II
2151 mu = mu0(z);
2152 for (int k=2; k<=p; k++)
2153 for (int j=2; j<=p; j++)
2154 for (int i=0; i<p; i++, o++)
2155 for (int l=0; l<3; l++)
2156 {
2157 W(o, l) = mu * E_Q1_ijk(i, j, l) * phi_E_k(k);
2158 }
2159
2160 // Family III
2161 for (int k=2; k<=p; k++)
2162 for (int j=2; j<=p; j++)
2163 for (int i=0; i<p; i++, o++)
2164 for (int l=0; l<3; l++)
2165 {
2166 W(o, l) = mu * E_Q2_ijk(i, j, l) * phi_E_k(k);
2167 }
2168
2169 // Family IV
2170 // Re-using mu from Family II
2171 dmu = grad_mu0(z);
2172 phi_Q(p, mu01(z, xy, 2), mu01(z, xy, 1), phi_Q2_ij);
2173 for (int j=2; j<=p; j++)
2174 for (int i=2; i<=p; i++, o++)
2175 {
2176 const int n = std::max(i,j);
2177 const real_t nmu = n * pow(mu, n-1);
2178 for (int l=0; l<3; l++)
2179 {
2180 W(o, l) = nmu * phi_Q2_ij(i, j) * dmu(l);
2181 }
2182 }
2183 }
2184}
2185
2186void ND_FuentesPyramidElement::calcCurlBasis(const int p,
2187 const IntegrationPoint &ip,
2188 DenseMatrix & E_E_ik,
2189 DenseMatrix & dE_E_ik,
2190 DenseTensor & E_Q1_ijk,
2191 DenseTensor & dE_Q1_ijk,
2192 DenseTensor & E_Q2_ijk,
2193 DenseTensor & dE_Q2_ijk,
2194 DenseTensor & E_T_ijk,
2195 DenseTensor & dE_T_ijk,
2196 DenseMatrix & phi_Q2_ij,
2197 DenseTensor & dphi_Q2_ij,
2198 Vector & phi_E_k,
2199 DenseMatrix & dphi_E_k,
2200 DenseMatrix & dW) const
2201{
2202 real_t x = ip.x;
2203 real_t y = ip.y;
2204 real_t z = ip.z;
2205 Vector xy({x,y}), dmu(3);
2206 Vector dmuxE(3), E(3), dphi(3), muphi(3);
2207
2208 real_t mu, mu2;
2209
2210 if (std::fabs(1.0 - z) < apex_tol)
2211 {
2212 z = 1.0 - apex_tol;
2213 y = 0.5 * (1.0 - z);
2214 x = 0.5 * (1.0 - z);
2215 xy(0) = x; xy(1) = y;
2216 }
2217 zmax = std::max(z, zmax);
2218
2219 dW = 0.0;
2220
2221 int o = 0;
2222
2223 // Mixed Edges
2224 if (z < 1.0)
2225 {
2226 // (a, b) = (1, 2), c = 0
2227 mu = mu0(z, xy, 2);
2228 dmu = grad_mu0(z, xy, 2);
2229 E_E(p, nu01(z, xy, 1), grad_nu01(z, xy, 1), E_E_ik, dE_E_ik);
2230 for (int i=0; i<p; i++, o++)
2231 {
2232 E(0) = E_E_ik(i, 0); E(1) = E_E_ik(i, 1); E(2) = E_E_ik(i, 2);
2233 dmu.cross3D(E, dmuxE);
2234 for (int k=0; k<3; k++)
2235 {
2236 dW(o, k) = mu * dE_E_ik(i, k) + dmuxE(k);
2237 }
2238 }
2239
2240 // (a, b) = (1, 2), c = 1
2241 mu = mu1(z, xy, 2);
2242 dmu = grad_mu1(z, xy, 2);
2243 for (int i=0; i<p; i++, o++)
2244 {
2245 E(0) = E_E_ik(i, 0); E(1) = E_E_ik(i, 1); E(2) = E_E_ik(i, 2);
2246 dmu.cross3D(E, dmuxE);
2247 for (int k=0; k<3; k++)
2248 {
2249 dW(o, k) = mu * dE_E_ik(i, k) + dmuxE(k);
2250 }
2251 }
2252
2253 // (a, b) = (2, 1), c = 0
2254 mu = mu0(z, xy, 1);
2255 dmu = grad_mu0(z, xy, 1);
2256 E_E(p, nu01(z, xy, 2), grad_nu01(z, xy, 2), E_E_ik, dE_E_ik);
2257 for (int i=0; i<p; i++, o++)
2258 {
2259 E(0) = E_E_ik(i, 0); E(1) = E_E_ik(i, 1); E(2) = E_E_ik(i, 2);
2260 dmu.cross3D(E, dmuxE);
2261 for (int k=0; k<3; k++)
2262 {
2263 dW(o, k) = mu * dE_E_ik(i, k) + dmuxE(k);
2264 }
2265 }
2266
2267 // (a, b) = (2, 1), c = 1
2268 mu = mu1(z, xy, 1);
2269 dmu = grad_mu1(z, xy, 1);
2270 for (int i=0; i<p; i++, o++)
2271 {
2272 E(0) = E_E_ik(i, 0); E(1) = E_E_ik(i, 1); E(2) = E_E_ik(i, 2);
2273 dmu.cross3D(E, dmuxE);
2274 for (int k=0; k<3; k++)
2275 {
2276 dW(o, k) = mu * dE_E_ik(i, k) + dmuxE(k);
2277 }
2278 }
2279 }
2280
2281 // Triangle Edges
2282 if (z < 1.0)
2283 {
2284 E_E(p, lam15(x, y, z), grad_lam15(x, y, z), E_E_ik, dE_E_ik);
2285 for (int i=0; i<p; i++, o++)
2286 for (int k=0; k<3; k++)
2287 {
2288 dW(o, k) = dE_E_ik(i, k);
2289 }
2290
2291 E_E(p, lam25(x, y, z), grad_lam25(x, y, z), E_E_ik, dE_E_ik);
2292 for (int i=0; i<p; i++, o++)
2293 for (int k=0; k<3; k++)
2294 {
2295 dW(o, k) = dE_E_ik(i, k);
2296 }
2297
2298 E_E(p, lam35(x, y, z), grad_lam35(x, y, z), E_E_ik, dE_E_ik);
2299 for (int i=0; i<p; i++, o++)
2300 for (int k=0; k<3; k++)
2301 {
2302 dW(o, k) = dE_E_ik(i, k);
2303 }
2304
2305 E_E(p, lam45(x, y, z), grad_lam45(x, y, z), E_E_ik, dE_E_ik);
2306 for (int i=0; i<p; i++, o++)
2307 for (int k=0; k<3; k++)
2308 {
2309 dW(o, k) = dE_E_ik(i, k);
2310 }
2311 }
2312
2313 // Quadrilateral Face
2314 if (z < 1.0 && p >= 2)
2315 {
2316 mu = mu0(z);
2317 mu2 = mu * mu;
2318 dmu = grad_mu0(z);
2319
2320 // Family I
2321 E_Q(p, mu01(z, xy, 1), grad_mu01(z, xy, 1),
2322 mu01(z, xy, 2), grad_mu01(z, xy, 2), E_Q1_ijk, dE_Q1_ijk);
2323 for (int j=2; j<=p; j++)
2324 for (int i=0; i<p; i++, o++)
2325 {
2326 E(0) = E_Q1_ijk(i, j, 0);
2327 E(1) = E_Q1_ijk(i, j, 1);
2328 E(2) = E_Q1_ijk(i, j, 2);
2329 dmu.cross3D(E, dmuxE);
2330 for (int k=0; k<3; k++)
2331 {
2332 dW(o, k) = mu2 * dE_Q1_ijk(i, j, k) + 2.0 * mu * dmuxE(k);
2333 }
2334 }
2335
2336 // Family II
2337 E_Q(p, mu01(z, xy, 2), grad_mu01(z, xy, 2),
2338 mu01(z, xy, 1), grad_mu01(z, xy, 1), E_Q2_ijk, dE_Q2_ijk);
2339 for (int j=2; j<=p; j++)
2340 for (int i=0; i<p; i++, o++)
2341 {
2342 E(0) = E_Q2_ijk(i, j, 0);
2343 E(1) = E_Q2_ijk(i, j, 1);
2344 E(2) = E_Q2_ijk(i, j, 2);
2345 dmu.cross3D(E, dmuxE);
2346 for (int k=0; k<3; k++)
2347 {
2348 dW(o, k) = mu2 * dE_Q2_ijk(i, j, k) + 2.0 * mu * dmuxE(k);
2349 }
2350 }
2351 }
2352
2353 // Triangular Faces
2354 if (z < 1.0 && p >= 2)
2355 {
2356 // Family I
2357 // (a, b) = (1, 2), c = 0
2358 mu = mu0(z, xy, 2);
2359 dmu = grad_mu0(z, xy, 2);
2360 E_T(p, nu012(z, xy, 1), grad_nu012(z, xy, 1), E_T_ijk, dE_T_ijk);
2361 for (int j=1; j<p; j++)
2362 for (int i=0; i+j<p; i++, o++)
2363 {
2364 E(0) = E_T_ijk(i, j, 0);
2365 E(1) = E_T_ijk(i, j, 1);
2366 E(2) = E_T_ijk(i, j, 2);
2367 dmu.cross3D(E, dmuxE);
2368 for (int k=0; k<3; k++)
2369 {
2370 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2371 }
2372 }
2373
2374 // (a, b) = (1, 2), c = 1
2375 mu = mu1(z, xy, 2);
2376 dmu = grad_mu1(z, xy, 2);
2377 for (int j=1; j<p; j++)
2378 for (int i=0; i+j<p; i++, o++)
2379 {
2380 E(0) = E_T_ijk(i, j, 0);
2381 E(1) = E_T_ijk(i, j, 1);
2382 E(2) = E_T_ijk(i, j, 2);
2383 dmu.cross3D(E, dmuxE);
2384 for (int k=0; k<3; k++)
2385 {
2386 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2387 }
2388 }
2389
2390 // (a, b) = (2, 1), c = 0
2391 mu = mu0(z, xy, 1);
2392 dmu = grad_mu0(z, xy, 1);
2393 E_T(p, nu012(z, xy, 2), grad_nu012(z, xy, 2), E_T_ijk, dE_T_ijk);
2394 for (int j=1; j<p; j++)
2395 for (int i=0; i+j<p; i++, o++)
2396 {
2397 E(0) = E_T_ijk(i, j, 0);
2398 E(1) = E_T_ijk(i, j, 1);
2399 E(2) = E_T_ijk(i, j, 2);
2400 dmu.cross3D(E, dmuxE);
2401 for (int k=0; k<3; k++)
2402 {
2403 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2404 }
2405 }
2406
2407 // (a, b) = (2, 1), c = 1
2408 mu = mu1(z, xy, 1);
2409 dmu = grad_mu1(z, xy, 1);
2410 for (int j=1; j<p; j++)
2411 for (int i=0; i+j<p; i++, o++)
2412 {
2413 E(0) = E_T_ijk(i, j, 0);
2414 E(1) = E_T_ijk(i, j, 1);
2415 E(2) = E_T_ijk(i, j, 2);
2416 dmu.cross3D(E, dmuxE);
2417 for (int k=0; k<3; k++)
2418 {
2419 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2420 }
2421 }
2422
2423 // Family II
2424 // (a, b) = (1, 2), c = 0
2425 mu = mu0(z, xy, 2);
2426 dmu = grad_mu0(z, xy, 2);
2427 E_T(p, nu120(z, xy, 1), grad_nu120(z, xy, 1), E_T_ijk, dE_T_ijk);
2428 for (int j=1; j<p; j++)
2429 for (int i=0; i+j<p; i++, o++)
2430 {
2431 E(0) = E_T_ijk(i, j, 0);
2432 E(1) = E_T_ijk(i, j, 1);
2433 E(2) = E_T_ijk(i, j, 2);
2434 dmu.cross3D(E, dmuxE);
2435 for (int k=0; k<3; k++)
2436 {
2437 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2438 }
2439 }
2440
2441 // (a, b) = (1, 2), c = 1
2442 mu = mu1(z, xy, 2);
2443 dmu = grad_mu1(z, xy, 2);
2444 for (int j=1; j<p; j++)
2445 for (int i=0; i+j<p; i++, o++)
2446 {
2447 E(0) = E_T_ijk(i, j, 0);
2448 E(1) = E_T_ijk(i, j, 1);
2449 E(2) = E_T_ijk(i, j, 2);
2450 dmu.cross3D(E, dmuxE);
2451 for (int k=0; k<3; k++)
2452 {
2453 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2454 }
2455 }
2456
2457 // (a, b) = (2, 1), c = 0
2458 mu = mu0(z, xy, 1);
2459 dmu = grad_mu0(z, xy, 1);
2460 E_T(p, nu120(z, xy, 2), grad_nu120(z, xy, 2), E_T_ijk, dE_T_ijk);
2461 for (int j=1; j<p; j++)
2462 for (int i=0; i+j<p; i++, o++)
2463 {
2464 E(0) = E_T_ijk(i, j, 0);
2465 E(1) = E_T_ijk(i, j, 1);
2466 E(2) = E_T_ijk(i, j, 2);
2467 dmu.cross3D(E, dmuxE);
2468 for (int k=0; k<3; k++)
2469 {
2470 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2471 }
2472 }
2473
2474 // (a, b) = (2, 1), c = 1
2475 mu = mu1(z, xy, 1);
2476 dmu = grad_mu1(z, xy, 1);
2477 for (int j=1; j<p; j++)
2478 for (int i=0; i+j<p; i++, o++)
2479 {
2480 E(0) = E_T_ijk(i, j, 0);
2481 E(1) = E_T_ijk(i, j, 1);
2482 E(2) = E_T_ijk(i, j, 2);
2483 dmu.cross3D(E, dmuxE);
2484 for (int k=0; k<3; k++)
2485 {
2486 dW(o, k) = mu * dE_T_ijk(i, j, k) + dmuxE(k);
2487 }
2488 }
2489 }
2490
2491 // Interior
2492 if (z < 1.0 && p >= 2)
2493 {
2494 // Family I
2495 // Curl is zero so skip these functions
2496 o += (p - 1) * (p - 1) * (p - 1);
2497
2498 // Family II
2499 mu = mu0(z);
2500 dmu = grad_mu0(z);
2501 phi_E(p, mu01(z), grad_mu01(z), phi_E_k, dphi_E_k);
2502 for (int k=2; k<=p; k++)
2503 {
2504 dphi(0) = dphi_E_k(k, 0);
2505 dphi(1) = dphi_E_k(k, 1);
2506 dphi(2) = dphi_E_k(k, 2);
2507 add(mu, dphi, phi_E_k(k), dmu, muphi);
2508
2509 for (int j=2; j<=p; j++)
2510 for (int i=0; i<p; i++, o++)
2511 {
2512 E(0) = E_Q1_ijk(i, j, 0);
2513 E(1) = E_Q1_ijk(i, j, 1);
2514 E(2) = E_Q1_ijk(i, j, 2);
2515 muphi.cross3D(E, dmuxE);
2516 for (int l=0; l<3; l++)
2517 {
2518 dW(o, l) = mu * dE_Q1_ijk(i, j, l) * phi_E_k(k) + dmuxE(l);
2519 }
2520 }
2521 }
2522
2523 // Family III
2524 for (int k=2; k<=p; k++)
2525 {
2526 dphi(0) = dphi_E_k(k, 0);
2527 dphi(1) = dphi_E_k(k, 1);
2528 dphi(2) = dphi_E_k(k, 2);
2529 add(mu, dphi, phi_E_k(k), dmu, muphi);
2530
2531 for (int j=2; j<=p; j++)
2532 for (int i=0; i<p; i++, o++)
2533 {
2534 E(0) = E_Q2_ijk(i, j, 0);
2535 E(1) = E_Q2_ijk(i, j, 1);
2536 E(2) = E_Q2_ijk(i, j, 2);
2537 muphi.cross3D(E, dmuxE);
2538 for (int l=0; l<3; l++)
2539 {
2540 dW(o, l) = mu * dE_Q2_ijk(i, j, l) * phi_E_k(k) + dmuxE(l);
2541 }
2542 }
2543 }
2544
2545 // Family IV
2546 // Re-using mu from Family II
2547 dmu = grad_mu0(z);
2548 phi_Q(p, mu01(z, xy, 2), grad_mu01(z, xy, 2), mu01(z, xy, 1),
2549 grad_mu01(z, xy, 1), phi_Q2_ij, dphi_Q2_ij);
2550 for (int j=2; j<=p; j++)
2551 for (int i=2; i<=p; i++, o++)
2552 {
2553 const int n = std::max(i,j);
2554 const real_t nmu = n * pow(mu, n-1);
2555
2556 dphi(0) = dphi_Q2_ij(i, j, 0);
2557 dphi(1) = dphi_Q2_ij(i, j, 1);
2558 dphi(2) = dphi_Q2_ij(i, j, 2);
2559 dphi.cross3D(dmu, muphi);
2560
2561 for (int l=0; l<3; l++)
2562 {
2563 dW(o, l) = nmu * muphi(l);
2564 }
2565 }
2566 }
2567}
2568
2570 : VectorFiniteElement(1, Geometry::POINT, 2, p,
2571 H_CURL_R1D, FunctionSpace::Pk)
2572{
2573 // VectorFiniteElement::SetDerivMembers doesn't support 0D H_CURL elements
2574 // so we mimic a 1D element and then correct the dimension here.
2575 dim = 0;
2576 vdim = 2;
2577 cdim = 0;
2578}
2579
2581 DenseMatrix &shape) const
2582{
2583 shape(0,0) = 1.0;
2584 shape(0,1) = 0.0;
2585
2586 shape(1,0) = 0.0;
2587 shape(1,1) = 1.0;
2588}
2589
2591 DenseMatrix &shape) const
2592{
2593 CalcVShape(Trans.GetIntPoint(), shape);
2594}
2595
2596const real_t ND_R1D_SegmentElement::tk[9] = { 1.,0.,0., 0.,1.,0., 0.,0.,1. };
2597
2599 const int cb_type,
2600 const int ob_type)
2601 : VectorFiniteElement(1, Geometry::SEGMENT, 3 * p + 2, p,
2602 H_CURL_R1D, FunctionSpace::Pk),
2603 dof2tk(dof),
2604 cbasis1d(poly1d.GetBasis(p, VerifyClosed(cb_type))),
2605 obasis1d(poly1d.GetBasis(p - 1, VerifyOpen(ob_type)))
2606{
2607 // Override default types for VectorFiniteElements
2608 deriv_type = CURL;
2611
2612 // Override default dimensions for VectorFiniteElements
2613 vdim = 3;
2614 cdim = 3;
2615
2616 const real_t *cp = poly1d.ClosedPoints(p, cb_type);
2617 const real_t *op = poly1d.OpenPoints(p - 1, ob_type);
2618
2619#ifndef MFEM_THREAD_SAFE
2620 shape_cx.SetSize(p + 1);
2621 shape_ox.SetSize(p);
2622 dshape_cx.SetSize(p + 1);
2623#endif
2624
2625 dof_map.SetSize(dof);
2626
2627 int o = 0;
2628 // nodes
2629 // (0)
2630 Nodes.IntPoint(o).x = cp[0]; // y-directed
2631 dof_map[p] = o; dof2tk[o++] = 1;
2632 Nodes.IntPoint(o).x = cp[0]; // z-directed
2633 dof_map[2*p+1] = o; dof2tk[o++] = 2;
2634
2635 // (1)
2636 Nodes.IntPoint(o).x = cp[p]; // y-directed
2637 dof_map[2*p] = o; dof2tk[o++] = 1;
2638 Nodes.IntPoint(o).x = cp[p]; // z-directed
2639 dof_map[3*p+1] = o; dof2tk[o++] = 2;
2640
2641 // interior
2642 // x-components
2643 for (int i = 0; i < p; i++)
2644 {
2645 Nodes.IntPoint(o).x = op[i];
2646 dof_map[i] = o; dof2tk[o++] = 0;
2647 }
2648 // y-components
2649 for (int i = 1; i < p; i++)
2650 {
2651 Nodes.IntPoint(o).x = cp[i];
2652 dof_map[p+i] = o; dof2tk[o++] = 1;
2653 }
2654 // z-components
2655 for (int i = 1; i < p; i++)
2656 {
2657 Nodes.IntPoint(o).x = cp[i];
2658 dof_map[2*p+1+i] = o; dof2tk[o++] = 2;
2659 }
2660}
2661
2663 DenseMatrix &shape) const
2664{
2665 const int p = order;
2666
2667#ifdef MFEM_THREAD_SAFE
2668 Vector shape_cx(p + 1), shape_ox(p);
2669#endif
2670
2671 cbasis1d.Eval(ip.x, shape_cx);
2672 obasis1d.Eval(ip.x, shape_ox);
2673
2674 int o = 0;
2675 // x-components
2676 for (int i = 0; i < p; i++)
2677 {
2678 int idx = dof_map[o++];
2679 shape(idx,0) = shape_ox(i);
2680 shape(idx,1) = 0.;
2681 shape(idx,2) = 0.;
2682 }
2683 // y-components
2684 for (int i = 0; i <= p; i++)
2685 {
2686 int idx = dof_map[o++];
2687 shape(idx,0) = 0.;
2688 shape(idx,1) = shape_cx(i);
2689 shape(idx,2) = 0.;
2690 }
2691 // z-components
2692 for (int i = 0; i <= p; i++)
2693 {
2694 int idx = dof_map[o++];
2695 shape(idx,0) = 0.;
2696 shape(idx,1) = 0.;
2697 shape(idx,2) = shape_cx(i);
2698 }
2699}
2700
2702 DenseMatrix &shape) const
2703{
2704 CalcVShape(Trans.GetIntPoint(), shape);
2705 const DenseMatrix & JI = Trans.InverseJacobian();
2706 MFEM_ASSERT(JI.Width() == 1 && JI.Height() == 1,
2707 "ND_R1D_SegmentElement cannot be embedded in "
2708 "2 or 3 dimensional spaces");
2709 for (int i=0; i<dof; i++)
2710 {
2711 shape(i, 0) *= JI(0,0);
2712 }
2713}
2714
2716 DenseMatrix &curl_shape) const
2717{
2718 const int p = order;
2719
2720#ifdef MFEM_THREAD_SAFE
2721 Vector shape_cx(p + 1), shape_ox(p);
2722 Vector dshape_cx(p + 1);
2723#endif
2724
2725 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
2726 obasis1d.Eval(ip.x, shape_ox);
2727
2728 int o = 0;
2729 // x-components
2730 for (int i = 0; i < p; i++)
2731 {
2732 int idx = dof_map[o++];
2733 curl_shape(idx,0) = 0.;
2734 curl_shape(idx,1) = 0.;
2735 curl_shape(idx,2) = 0.;
2736 }
2737 // y-components
2738 for (int i = 0; i <= p; i++)
2739 {
2740 int idx = dof_map[o++];
2741 curl_shape(idx,0) = 0.;
2742 curl_shape(idx,1) = 0.;
2743 curl_shape(idx,2) = dshape_cx(i);
2744 }
2745 // z-components
2746 for (int i = 0; i <= p; i++)
2747 {
2748 int idx = dof_map[o++];
2749 curl_shape(idx,0) = 0.;
2750 curl_shape(idx,1) = -dshape_cx(i);
2751 curl_shape(idx,2) = 0.;
2752 }
2753}
2754
2756 DenseMatrix &curl_shape) const
2757{
2758 CalcCurlShape(Trans.GetIntPoint(), curl_shape);
2759 const DenseMatrix & J = Trans.Jacobian();
2760 MFEM_ASSERT(J.Width() == 1 && J.Height() == 1,
2761 "ND_R1D_SegmentElement cannot be embedded in "
2762 "2 or 3 dimensional spaces");
2763 curl_shape *= (1.0 / J.Weight());
2764}
2765
2767 ElementTransformation &Trans,
2768 Vector &dofs) const
2769{
2770 real_t data[3];
2771 Vector vk(data, 3);
2772
2773 for (int k = 0; k < dof; k++)
2774 {
2775 Trans.SetIntPoint(&Nodes.IntPoint(k));
2776
2777 vc.Eval(vk, Trans, Nodes.IntPoint(k));
2778 // dof_k = vk^t J tk
2779 Vector t(const_cast<real_t*>(&tk[dof2tk[k] * 3]), 3);
2780 dofs(k) = Trans.Jacobian()(0,0) * t(0) * vk(0) +
2781 t(1) * vk(1) + t(2) * vk(2);
2782 }
2783
2784}
2785
2787 ElementTransformation &Trans,
2788 DenseMatrix &I) const
2789{
2790 if (fe.GetRangeType() == SCALAR)
2791 {
2793 Vector shape(fe.GetDof());
2794
2795 real_t * tk_ptr = const_cast<real_t*>(tk);
2796
2797 I.SetSize(dof, vdim*fe.GetDof());
2798 for (int k = 0; k < dof; k++)
2799 {
2800 const IntegrationPoint &ip = Nodes.IntPoint(k);
2801
2802 Vector t1(&tk_ptr[dof2tk[k] * 3], 1);
2803 Vector t3(&tk_ptr[dof2tk[k] * 3], 3);
2804
2805 fe.CalcShape(ip, shape);
2806 Trans.SetIntPoint(&ip);
2807 // Transform ND edge tengents from reference to physical space
2808 // vk = J tk
2809 Trans.Jacobian().Mult(t1, vk);
2810 vk[1] = t3[1];
2811 vk[2] = t3[2];
2812 if (fe.GetMapType() == INTEGRAL)
2813 {
2814 real_t w = 1.0/Trans.Weight();
2815 for (int d = 0; d < vdim; d++)
2816 {
2817 vk[d] *= w;
2818 }
2819 }
2820
2821 for (int j = 0; j < shape.Size(); j++)
2822 {
2823 real_t s = shape(j);
2824 if (fabs(s) < 1e-12)
2825 {
2826 s = 0.0;
2827 }
2828 // Project scalar basis function multiplied by each coordinate
2829 // direction onto the transformed edge tangents
2830 for (int d = 0; d < vdim; d++)
2831 {
2832 I(k, j + d*shape.Size()) = s*vk[d];
2833 }
2834 }
2835 }
2836 }
2837 else
2838 {
2841
2842 real_t * tk_ptr = const_cast<real_t*>(tk);
2843
2844 I.SetSize(dof, fe.GetDof());
2845 for (int k = 0; k < dof; k++)
2846 {
2847 const IntegrationPoint &ip = Nodes.IntPoint(k);
2848
2849 Vector t1(&tk_ptr[dof2tk[k] * 3], 1);
2850 Vector t3(&tk_ptr[dof2tk[k] * 3], 3);
2851
2852 Trans.SetIntPoint(&ip);
2853 // Transform ND edge tangents from reference to physical space
2854 // vk = J tk
2855 Trans.Jacobian().Mult(t1, vk);
2856 // Compute fe basis functions in physical space
2857 fe.CalcVShape(Trans, vshape);
2858 // Project fe basis functions onto transformed edge tangents
2859 for (int j=0; j<vshape.Height(); j++)
2860 {
2861 I(k, j) = 0.0;
2862 I(k, j) += vshape(j, 0) * vk[0];
2863 if (vshape.Width() == 3)
2864 {
2865 I(k, j) += vshape(j, 1) * t3(1);
2866 I(k, j) += vshape(j, 2) * t3(2);
2867 }
2868 }
2869 }
2870 }
2871}
2872
2873const real_t ND_R2D_SegmentElement::tk[4] = { 1.,0., 0.,1. };
2874
2876 const int cb_type,
2877 const int ob_type)
2878 : VectorFiniteElement(1, Geometry::SEGMENT, 2 * p + 1, p,
2879 H_CURL_R2D, FunctionSpace::Pk),
2880 dof2tk(dof),
2881 cbasis1d(poly1d.GetBasis(p, VerifyClosed(cb_type))),
2882 obasis1d(poly1d.GetBasis(p - 1, VerifyOpen(ob_type)))
2883{
2884 // Override default dimensions for VectorFiniteElements
2885 vdim = 2;
2886 cdim = 1;
2887
2888 const real_t *cp = poly1d.ClosedPoints(p, cb_type);
2889 const real_t *op = poly1d.OpenPoints(p - 1, ob_type);
2890
2891#ifndef MFEM_THREAD_SAFE
2892 shape_cx.SetSize(p + 1);
2893 shape_ox.SetSize(p);
2894 dshape_cx.SetSize(p + 1);
2895#endif
2896
2897 dof_map.SetSize(dof);
2898
2899 int o = 0;
2900 // nodes
2901 // (0)
2902 Nodes.IntPoint(o).x = cp[0]; // z-directed
2903 dof_map[p] = o; dof2tk[o++] = 1;
2904
2905 // (1)
2906 Nodes.IntPoint(o).x = cp[p]; // z-directed
2907 dof_map[2*p] = o; dof2tk[o++] = 1;
2908
2909 // interior
2910 // x-components
2911 for (int i = 0; i < p; i++)
2912 {
2913 Nodes.IntPoint(o).x = op[i];
2914 dof_map[i] = o; dof2tk[o++] = 0;
2915 }
2916 // z-components
2917 for (int i = 1; i < p; i++)
2918 {
2919 Nodes.IntPoint(o).x = cp[i];
2920 dof_map[p+i] = o; dof2tk[o++] = 1;
2921 }
2922}
2923
2925 DenseMatrix &shape) const
2926{
2927 const int p = order;
2928
2929#ifdef MFEM_THREAD_SAFE
2930 Vector shape_cx(p + 1), shape_ox(p);
2931#endif
2932
2933 cbasis1d.Eval(ip.x, shape_cx);
2934 obasis1d.Eval(ip.x, shape_ox);
2935
2936 int o = 0;
2937 // x-components
2938 for (int i = 0; i < p; i++)
2939 {
2940 int idx = dof_map[o++];
2941 shape(idx,0) = shape_ox(i);
2942 shape(idx,1) = 0.;
2943 }
2944 // z-components
2945 for (int i = 0; i <= p; i++)
2946 {
2947 int idx = dof_map[o++];
2948 shape(idx,0) = 0.;
2949 shape(idx,1) = shape_cx(i);
2950 }
2951}
2952
2954 DenseMatrix &shape) const
2955{
2956 CalcVShape(Trans.GetIntPoint(), shape);
2957 const DenseMatrix & JI = Trans.InverseJacobian();
2958 MFEM_ASSERT(JI.Width() == 1 && JI.Height() == 1,
2959 "ND_R2D_SegmentElement cannot be embedded in "
2960 "2 or 3 dimensional spaces");
2961 for (int i=0; i<dof; i++)
2962 {
2963 shape(i, 0) *= JI(0,0);
2964 }
2965}
2966
2968 DenseMatrix &curl_shape) const
2969{
2970 const int p = order;
2971
2972#ifdef MFEM_THREAD_SAFE
2973 Vector shape_cx(p + 1), shape_ox(p);
2974 Vector dshape_cx(p + 1);
2975#endif
2976
2977 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
2978 obasis1d.Eval(ip.x, shape_ox);
2979
2980 int o = 0;
2981 // x-components
2982 for (int i = 0; i < p; i++)
2983 {
2984 int idx = dof_map[o++];
2985 curl_shape(idx,0) = 0.;
2986 }
2987 // z-components
2988 for (int i = 0; i <= p; i++)
2989 {
2990 int idx = dof_map[o++];
2991 curl_shape(idx,0) = -dshape_cx(i);
2992 }
2993}
2994
2995void ND_R2D_SegmentElement::LocalInterpolation(const VectorFiniteElement &cfe,
2996 ElementTransformation &Trans,
2997 DenseMatrix &I) const
2998{
2999 real_t vk[Geometry::MaxDim]; vk[1] = 0.0; vk[2] = 0.0;
3000 Vector xk(vk, dim);
3002 DenseMatrix vshape(cfe.GetDof(), vdim);
3003
3004 real_t * tk_ptr = const_cast<real_t*>(tk);
3005
3006 I.SetSize(dof, vshape.Height());
3007
3008 // assuming Trans is linear; this should be ok for all refinement types
3010 const DenseMatrix &J = Trans.Jacobian();
3011 for (int k = 0; k < dof; k++)
3012 {
3013 Vector t1(&tk_ptr[dof2tk[k] * 2], 1);
3014 Vector t2(&tk_ptr[dof2tk[k] * 2], 2);
3015
3016 Trans.Transform(Nodes.IntPoint(k), xk);
3017 ip.Set3(vk);
3018 cfe.CalcVShape(ip, vshape);
3019 // xk = J t_k
3020 J.Mult(t1, vk);
3021 // I_k = vshape_k.J.t_k, k=1,...,Dof
3022 for (int j = 0; j < vshape.Height(); j++)
3023 {
3024 real_t Ikj = 0.;
3025 for (int i = 0; i < dim; i++)
3026 {
3027 Ikj += vshape(j, i) * vk[i];
3028 }
3029 Ikj += vshape(j, 1) * t2(1);
3030 I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj;
3031 }
3032 }
3033}
3034
3036 ElementTransformation &Trans,
3037 Vector &dofs) const
3038{
3039 real_t data[3];
3040 Vector vk1(data, 1);
3041 Vector vk2(data, 2);
3042 Vector vk3(data, 3);
3043
3044 real_t * tk_ptr = const_cast<real_t*>(tk);
3045
3046 for (int k = 0; k < dof; k++)
3047 {
3048 Trans.SetIntPoint(&Nodes.IntPoint(k));
3049
3050 vc.Eval(vk3, Trans, Nodes.IntPoint(k));
3051 // dof_k = vk^t J tk
3052 Vector t1(&tk_ptr[dof2tk[k] * 2], 1);
3053 Vector t2(&tk_ptr[dof2tk[k] * 2], 2);
3054
3055 dofs(k) = Trans.Jacobian().InnerProduct(t1, vk2) + t2(1) * vk3(2);
3056 }
3057
3058}
3059
3061 const real_t *tk_fe)
3062 : VectorFiniteElement(2, G, Do, p,
3063 H_CURL_R2D, FunctionSpace::Pk),
3064 tk(tk_fe),
3065 dof_map(dof),
3066 dof2tk(dof)
3067{
3068 // Override default types for VectorFiniteElements
3069 deriv_type = CURL;
3072
3073 // Override default dimensions for VectorFiniteElements
3074 vdim = 3;
3075 cdim = 3;
3076}
3077
3079 DenseMatrix &shape) const
3080{
3081 CalcVShape(Trans.GetIntPoint(), shape);
3082 const DenseMatrix & JI = Trans.InverseJacobian();
3083 MFEM_ASSERT(JI.Width() == 2 && JI.Height() == 2,
3084 "ND_R2D_FiniteElement cannot be embedded in "
3085 "3 dimensional spaces");
3086 for (int i=0; i<dof; i++)
3087 {
3088 real_t sx = shape(i, 0);
3089 real_t sy = shape(i, 1);
3090 shape(i, 0) = sx * JI(0, 0) + sy * JI(1, 0);
3091 shape(i, 1) = sx * JI(0, 1) + sy * JI(1, 1);
3092 }
3093}
3094
3096 DenseMatrix &curl_shape) const
3097{
3098 CalcCurlShape(Trans.GetIntPoint(), curl_shape);
3099 const DenseMatrix & J = Trans.Jacobian();
3100 MFEM_ASSERT(J.Width() == 2 && J.Height() == 2,
3101 "ND_R2D_FiniteElement cannot be embedded in "
3102 "3 dimensional spaces");
3103 for (int i=0; i<dof; i++)
3104 {
3105 real_t sx = curl_shape(i, 0);
3106 real_t sy = curl_shape(i, 1);
3107 curl_shape(i, 0) = sx * J(0, 0) + sy * J(0, 1);
3108 curl_shape(i, 1) = sx * J(1, 0) + sy * J(1, 1);
3109 }
3110 curl_shape *= (1.0 / Trans.Weight());
3111}
3112
3113void ND_R2D_FiniteElement::LocalInterpolation(
3114 const VectorFiniteElement &cfe,
3115 ElementTransformation &Trans,
3116 DenseMatrix &I) const
3117{
3118 real_t vk[Geometry::MaxDim]; vk[2] = 0.0;
3119 Vector xk(vk, dim);
3121#ifdef MFEM_THREAD_SAFE
3122 DenseMatrix vshape(cfe.GetDof(), vdim);
3123#else
3124 vshape.SetSize(cfe.GetDof(), vdim);
3125#endif
3126
3127 real_t * tk_ptr = const_cast<real_t*>(tk);
3128
3129 I.SetSize(dof, vshape.Height());
3130
3131 // assuming Trans is linear; this should be ok for all refinement types
3133 const DenseMatrix &J = Trans.Jacobian();
3134 for (int k = 0; k < dof; k++)
3135 {
3136 Vector t2(&tk_ptr[dof2tk[k] * 3], 2);
3137 Vector t3(&tk_ptr[dof2tk[k] * 3], 3);
3138
3139 Trans.Transform(Nodes.IntPoint(k), xk);
3140 ip.Set3(vk);
3141 cfe.CalcVShape(ip, vshape);
3142 // xk = J t_k
3143 J.Mult(t2, vk);
3144 // I_k = vshape_k.J.t_k, k=1,...,Dof
3145 for (int j = 0; j < vshape.Height(); j++)
3146 {
3147 real_t Ikj = 0.;
3148 for (int i = 0; i < dim; i++)
3149 {
3150 Ikj += vshape(j, i) * vk[i];
3151 }
3152 Ikj += vshape(j, 2) * t3(2);
3153 I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj;
3154 }
3155 }
3156}
3157
3159 DenseMatrix &R) const
3160{
3161 real_t pt_data[Geometry::MaxDim];
3163 Vector pt(pt_data, dim);
3164
3165#ifdef MFEM_THREAD_SAFE
3167#endif
3168
3169 real_t * tk_ptr = const_cast<real_t*>(tk);
3170
3172 const DenseMatrix &Jinv = Trans.InverseJacobian();
3173 for (int j = 0; j < dof; j++)
3174 {
3175 Vector t2(&tk_ptr[dof2tk[j] * 3], 2);
3176 Vector t3(&tk_ptr[dof2tk[j] * 3], 3);
3177
3178 InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
3179 ip.Set(pt_data, dim);
3180 if (Geometries.CheckPoint(geom_type, ip)) // do we need an epsilon here?
3181 {
3182 CalcVShape(ip, vshape);
3183 Jinv.Mult(t2, pt_data);
3184 for (int k = 0; k < dof; k++)
3185 {
3186 real_t R_jk = 0.0;
3187 for (int d = 0; d < dim; d++)
3188 {
3189 R_jk += vshape(k,d)*pt_data[d];
3190 }
3191 R_jk += vshape(k, 2) * t3(2);
3192 R(j,k) = R_jk;
3193 }
3194 }
3195 else
3196 {
3197 // Set the whole row to avoid valgrind warnings in R.Threshold().
3198 R.SetRow(j, infinity());
3199 }
3200 }
3201 R.Threshold(1e-12);
3202}
3203
3205 ElementTransformation &Trans,
3206 Vector &dofs) const
3207{
3208 real_t data[3];
3209 Vector vk2(data, 2);
3210 Vector vk3(data, 3);
3211
3212 real_t * tk_ptr = const_cast<real_t*>(tk);
3213
3214 for (int k = 0; k < dof; k++)
3215 {
3216 Trans.SetIntPoint(&Nodes.IntPoint(k));
3217
3218 vc.Eval(vk3, Trans, Nodes.IntPoint(k));
3219 // dof_k = vk^t J tk
3220 Vector t2(&tk_ptr[dof2tk[k] * 3], 2);
3221 Vector t3(&tk_ptr[dof2tk[k] * 3], 3);
3222
3223 dofs(k) = Trans.Jacobian().InnerProduct(t2, vk2) + t3(2) * vk3(2);
3224 }
3225
3226}
3227
3229 ElementTransformation &Trans,
3230 DenseMatrix &I) const
3231{
3232 if (fe.GetRangeType() == SCALAR)
3233 {
3235 Vector shape(fe.GetDof());
3236
3237 real_t * tk_ptr = const_cast<real_t*>(tk);
3238
3239 I.SetSize(dof, vdim*fe.GetDof());
3240 for (int k = 0; k < dof; k++)
3241 {
3242 const IntegrationPoint &ip = Nodes.IntPoint(k);
3243
3244 Vector t2(&tk_ptr[dof2tk[k] * 3], 2);
3245 Vector t3(&tk_ptr[dof2tk[k] * 3], 3);
3246
3247 fe.CalcShape(ip, shape);
3248 Trans.SetIntPoint(&ip);
3249 // Transform ND edge tengents from reference to physical space
3250 // vk = J tk
3251 Trans.Jacobian().Mult(t2, vk);
3252 vk[2] = t3[2];
3253 if (fe.GetMapType() == INTEGRAL)
3254 {
3255 real_t w = 1.0/Trans.Weight();
3256 for (int d = 0; d < vdim; d++)
3257 {
3258 vk[d] *= w;
3259 }
3260 }
3261
3262 for (int j = 0; j < shape.Size(); j++)
3263 {
3264 real_t s = shape(j);
3265 if (fabs(s) < 1e-12)
3266 {
3267 s = 0.0;
3268 }
3269 // Project scalar basis function multiplied by each coordinate
3270 // direction onto the transformed edge tangents
3271 for (int d = 0; d < vdim; d++)
3272 {
3273 I(k, j + d*shape.Size()) = s*vk[d];
3274 }
3275 }
3276 }
3277 }
3278 else
3279 {
3282
3283 real_t * tk_ptr = const_cast<real_t*>(tk);
3284
3285 I.SetSize(dof, fe.GetDof());
3286 for (int k = 0; k < dof; k++)
3287 {
3288 const IntegrationPoint &ip = Nodes.IntPoint(k);
3289
3290 Vector t2(&tk_ptr[dof2tk[k] * 3], 2);
3291 Vector t3(&tk_ptr[dof2tk[k] * 3], 3);
3292
3293 Trans.SetIntPoint(&ip);
3294 // Transform ND edge tangents from reference to physical space
3295 // vk = J tk
3296 Trans.Jacobian().Mult(t2, vk);
3297 // Compute fe basis functions in physical space
3298 fe.CalcVShape(Trans, vshape);
3299 // Project fe basis functions onto transformed edge tangents
3300 for (int j=0; j<vshape.Height(); j++)
3301 {
3302 I(k, j) = 0.0;
3303 for (int i=0; i<2; i++)
3304 {
3305 I(k, j) += vshape(j, i) * vk[i];
3306 }
3307 if (vshape.Width() == 3)
3308 {
3309 I(k, j) += vshape(j, 2) * t3(2);
3310 }
3311 }
3312 }
3313 }
3314}
3315
3317 ElementTransformation &Trans,
3318 DenseMatrix &grad) const
3319{
3320 MFEM_ASSERT(fe.GetMapType() == VALUE, "");
3321
3322 DenseMatrix dshape(fe.GetDof(), fe.GetDim());
3323 Vector grad_k(fe.GetDof());
3324
3325 grad.SetSize(dof, fe.GetDof());
3326 for (int k = 0; k < dof; k++)
3327 {
3328 fe.CalcDShape(Nodes.IntPoint(k), dshape);
3329 dshape.Mult(tk + dof2tk[k]*vdim, grad_k);
3330 for (int j = 0; j < grad_k.Size(); j++)
3331 {
3332 grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j);
3333 }
3334 }
3335}
3336
3337const real_t ND_R2D_TriangleElement::tk_t[15] =
3338{ 1.,0.,0., -1.,1.,0., 0.,-1.,0., 0.,1.,0., 0.,0.,1. };
3339
3341 const int cb_type)
3342 : ND_R2D_FiniteElement(p, Geometry::TRIANGLE, ((3*p + 1)*(p + 2))/2, tk_t),
3343 ND_FE(p),
3344 H1_FE(p, cb_type)
3345{
3346 int pm1 = p - 1, pm2 = p - 2;
3347
3348#ifndef MFEM_THREAD_SAFE
3349 nd_shape.SetSize(ND_FE.GetDof(), 2);
3350 h1_shape.SetSize(H1_FE.GetDof());
3351 nd_dshape.SetSize(ND_FE.GetDof(), 1);
3352 h1_dshape.SetSize(H1_FE.GetDof(), 2);
3353#endif
3354
3355 int o = 0;
3356 int n = 0;
3357 int h = 0;
3358 // Three nodes
3359 dof_map[o] = -1 - h++; dof2tk[o++] = 4;
3360 dof_map[o] = -1 - h++; dof2tk[o++] = 4;
3361 dof_map[o] = -1 - h++; dof2tk[o++] = 4;
3362
3363 // Three edges
3364 for (int e=0; e<3; e++)
3365 {
3366 // Dofs in the plane
3367 for (int i=0; i<p; i++)
3368 {
3369 dof_map[o] = n++; dof2tk[o++] = e;
3370 }
3371 // z-directed dofs
3372 for (int i=0; i<pm1; i++)
3373 {
3374 dof_map[o] = -1 - h++; dof2tk[o++] = 4;
3375 }
3376 }
3377
3378 // Interior dofs in the plane
3379 for (int j = 0; j <= pm2; j++)
3380 for (int i = 0; i + j <= pm2; i++)
3381 {
3382 dof_map[o] = n++; dof2tk[o++] = 0;
3383 dof_map[o] = n++; dof2tk[o++] = 3;
3384 }
3385
3386 // Interior z-directed dofs
3387 for (int j = 0; j < pm1; j++)
3388 for (int i = 0; i + j < pm2; i++)
3389 {
3390 dof_map[o] = -1 - h++; dof2tk[o++] = 4;
3391 }
3392
3393 MFEM_VERIFY(n == ND_FE.GetDof(),
3394 "ND_R2D_Triangle incorrect number of ND dofs.");
3395 MFEM_VERIFY(h == H1_FE.GetDof(),
3396 "ND_R2D_Triangle incorrect number of H1 dofs.");
3397 MFEM_VERIFY(o == GetDof(),
3398 "ND_R2D_Triangle incorrect number of dofs.");
3399
3400 const IntegrationRule & nd_Nodes = ND_FE.GetNodes();
3401 const IntegrationRule & h1_Nodes = H1_FE.GetNodes();
3402
3403 for (int i=0; i<dof; i++)
3404 {
3405 int idx = dof_map[i];
3406 if (idx >= 0)
3407 {
3408 const IntegrationPoint & ip = nd_Nodes.IntPoint(idx);
3409 Nodes.IntPoint(i).Set2(ip.x, ip.y);
3410 }
3411 else
3412 {
3413 const IntegrationPoint & ip = h1_Nodes.IntPoint(-idx-1);
3414 Nodes.IntPoint(i).Set2(ip.x, ip.y);
3415 }
3416 }
3417}
3418
3420 DenseMatrix &shape) const
3421{
3422#ifdef MFEM_THREAD_SAFE
3423 DenseMatrix nd_shape(ND_FE.GetDof(), 2);
3424 Vector h1_shape(H1_FE.GetDof());
3425#endif
3426
3427 ND_FE.CalcVShape(ip, nd_shape);
3428 H1_FE.CalcShape(ip, h1_shape);
3429
3430 for (int i=0; i<dof; i++)
3431 {
3432 int idx = dof_map[i];
3433 if (idx >= 0)
3434 {
3435 shape(i, 0) = nd_shape(idx, 0);
3436 shape(i, 1) = nd_shape(idx, 1);
3437 shape(i, 2) = 0.0;
3438 }
3439 else
3440 {
3441 shape(i, 0) = 0.0;
3442 shape(i, 1) = 0.0;
3443 shape(i, 2) = h1_shape(-idx-1);
3444 }
3445 }
3446}
3447
3449 DenseMatrix &curl_shape) const
3450{
3451#ifdef MFEM_THREAD_SAFE
3452 DenseMatrix nd_dshape(ND_FE.GetDof(), 1);
3453 DenseMatrix h1_dshape(H1_FE.GetDof(), 2);
3454#endif
3455
3456 ND_FE.CalcCurlShape(ip, nd_dshape);
3457 H1_FE.CalcDShape(ip, h1_dshape);
3458
3459 for (int i=0; i<dof; i++)
3460 {
3461 int idx = dof_map[i];
3462 if (idx >= 0)
3463 {
3464 curl_shape(i, 0) = 0.0;
3465 curl_shape(i, 1) = 0.0;
3466 curl_shape(i, 2) = nd_dshape(idx, 0);
3467 }
3468 else
3469 {
3470 curl_shape(i, 0) = h1_dshape(-idx-1, 1);
3471 curl_shape(i, 1) = -h1_dshape(-idx-1, 0);
3472 curl_shape(i, 2) = 0.0;
3473 }
3474 }
3475}
3476
3477
3478const real_t ND_R2D_QuadrilateralElement::tk_q[15] =
3479{ 1.,0.,0., 0.,1.,0., -1.,0.,0., 0.,-1.,0., 0.,0.,1. };
3480
3482 const int cb_type,
3483 const int ob_type)
3484 : ND_R2D_FiniteElement(p, Geometry::SQUARE, ((3*p + 1)*(p + 1)), tk_q),
3485 cbasis1d(poly1d.GetBasis(p, VerifyClosed(cb_type))),
3486 obasis1d(poly1d.GetBasis(p - 1, VerifyOpen(ob_type)))
3487{
3488 const real_t *cp = poly1d.ClosedPoints(p, cb_type);
3489 const real_t *op = poly1d.OpenPoints(p - 1, ob_type);
3490 const int dofx = p*(p+1);
3491 const int dofy = p*(p+1);
3492 const int dofxy = dofx+dofy;
3493
3494#ifndef MFEM_THREAD_SAFE
3495 shape_cx.SetSize(p + 1);
3496 shape_ox.SetSize(p);
3497 shape_cy.SetSize(p + 1);
3498 shape_oy.SetSize(p);
3499 dshape_cx.SetSize(p + 1);
3500 dshape_cy.SetSize(p + 1);
3501#endif
3502
3504
3505 int o = 0;
3506 // nodes
3507 dof_map[dofxy] = o++; // (0)
3508 dof_map[dofxy+p] = o++; // (1)
3509 dof_map[dof-1] = o++; // (2)
3510 dof_map[dof-p-1] = o++; // (3)
3511
3512 // edges
3513 for (int i = 0; i < p; i++) // (0,1) - x-directed
3514 {
3515 dof_map[i + 0*p] = o++;
3516 }
3517 for (int i = 1; i < p; i++) // (0,1) - z-directed
3518 {
3519 dof_map[dofxy + i + 0*(p+1)] = o++;
3520 }
3521 for (int j = 0; j < p; j++) // (1,2) - y-directed
3522 {
3523 dof_map[dofx + p + j*(p + 1)] = o++;
3524 }
3525 for (int j = 1; j < p; j++) // (1,2) - z-directed
3526 {
3527 dof_map[dofxy + p + j*(p + 1)] = o++;
3528 }
3529 for (int i = 0; i < p; i++) // (2,3) - x-directed
3530 {
3531 dof_map[(p - 1 - i) + p*p] = -1 - (o++);
3532 }
3533 for (int i = 1; i < p; i++) // (2,3) - z-directed
3534 {
3535 dof_map[dofxy + (p - i) + p*(p + 1)] = o++;
3536 }
3537 for (int j = 0; j < p; j++) // (3,0) - y-directed
3538 {
3539 dof_map[dofx + 0 + (p - 1 - j)*(p + 1)] = -1 - (o++);
3540 }
3541 for (int j = 1; j < p; j++) // (3,0) - z-directed
3542 {
3543 dof_map[dofxy + (p - j)*(p + 1)] = o++;
3544 }
3545
3546 // interior
3547 // x-components
3548 for (int j = 1; j < p; j++)
3549 for (int i = 0; i < p; i++)
3550 {
3551 dof_map[i + j*p] = o++;
3552 }
3553 // y-components
3554 for (int j = 0; j < p; j++)
3555 for (int i = 1; i < p; i++)
3556 {
3557 dof_map[dofx + i + j*(p + 1)] = o++;
3558 }
3559 // z-components
3560 for (int j = 1; j < p; j++)
3561 for (int i = 1; i < p; i++)
3562 {
3563 dof_map[dofxy + i + j*(p + 1)] = o++;
3564 }
3565
3566 // set dof2tk and Nodes
3567 o = 0;
3568 // x-components
3569 for (int j = 0; j <= p; j++)
3570 for (int i = 0; i < p; i++)
3571 {
3572 int idx;
3573 if ((idx = dof_map[o++]) < 0)
3574 {
3575 dof2tk[idx = -1 - idx] = 2;
3576 }
3577 else
3578 {
3579 dof2tk[idx] = 0;
3580 }
3581 Nodes.IntPoint(idx).Set2(op[i], cp[j]);
3582 }
3583 // y-components
3584 for (int j = 0; j < p; j++)
3585 for (int i = 0; i <= p; i++)
3586 {
3587 int idx;
3588 if ((idx = dof_map[o++]) < 0)
3589 {
3590 dof2tk[idx = -1 - idx] = 3;
3591 }
3592 else
3593 {
3594 dof2tk[idx] = 1;
3595 }
3596 Nodes.IntPoint(idx).Set2(cp[i], op[j]);
3597 }
3598 // z-components
3599 for (int j = 0; j <= p; j++)
3600 for (int i = 0; i <= p; i++)
3601 {
3602 int idx = dof_map[o++];
3603 dof2tk[idx] = 4;
3604 Nodes.IntPoint(idx).Set2(cp[i], cp[j]);
3605 }
3606}
3607
3609 DenseMatrix &shape) const
3610{
3611 const int p = order;
3612
3613#ifdef MFEM_THREAD_SAFE
3614 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
3615#endif
3616
3617 cbasis1d.Eval(ip.x, shape_cx);
3618 obasis1d.Eval(ip.x, shape_ox);
3619 cbasis1d.Eval(ip.y, shape_cy);
3620 obasis1d.Eval(ip.y, shape_oy);
3621
3622 int o = 0;
3623 // x-components
3624 for (int j = 0; j <= p; j++)
3625 for (int i = 0; i < p; i++)
3626 {
3627 int idx, s;
3628 if ((idx = dof_map[o++]) < 0)
3629 {
3630 idx = -1 - idx, s = -1;
3631 }
3632 else
3633 {
3634 s = +1;
3635 }
3636 shape(idx,0) = s*shape_ox(i)*shape_cy(j);
3637 shape(idx,1) = 0.;
3638 shape(idx,2) = 0.;
3639 }
3640 // y-components
3641 for (int j = 0; j < p; j++)
3642 for (int i = 0; i <= p; i++)
3643 {
3644 int idx, s;
3645 if ((idx = dof_map[o++]) < 0)
3646 {
3647 idx = -1 - idx, s = -1;
3648 }
3649 else
3650 {
3651 s = +1;
3652 }
3653 shape(idx,0) = 0.;
3654 shape(idx,1) = s*shape_cx(i)*shape_oy(j);
3655 shape(idx,2) = 0.;
3656 }
3657 // z-components
3658 for (int j = 0; j <= p; j++)
3659 for (int i = 0; i <= p; i++)
3660 {
3661 int idx = dof_map[o++];
3662 shape(idx,0) = 0.;
3663 shape(idx,1) = 0.;
3664 shape(idx,2) = shape_cx(i)*shape_cy(j);
3665 }
3666}
3667
3669 DenseMatrix &curl_shape) const
3670{
3671 const int p = order;
3672
3673#ifdef MFEM_THREAD_SAFE
3674 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
3675 Vector dshape_cx(p + 1), dshape_cy(p + 1);
3676#endif
3677
3678 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
3679 obasis1d.Eval(ip.x, shape_ox);
3680 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
3681 obasis1d.Eval(ip.y, shape_oy);
3682
3683 int o = 0;
3684 // x-components
3685 for (int j = 0; j <= p; j++)
3686 for (int i = 0; i < p; i++)
3687 {
3688 int idx, s;
3689 if ((idx = dof_map[o++]) < 0)
3690 {
3691 idx = -1 - idx, s = -1;
3692 }
3693 else
3694 {
3695 s = +1;
3696 }
3697 curl_shape(idx,0) = 0.;
3698 curl_shape(idx,1) = 0.;
3699 curl_shape(idx,2) = -s*shape_ox(i)*dshape_cy(j);
3700 }
3701 // y-components
3702 for (int j = 0; j < p; j++)
3703 for (int i = 0; i <= p; i++)
3704 {
3705 int idx, s;
3706 if ((idx = dof_map[o++]) < 0)
3707 {
3708 idx = -1 - idx, s = -1;
3709 }
3710 else
3711 {
3712 s = +1;
3713 }
3714 curl_shape(idx,0) = 0.;
3715 curl_shape(idx,1) = 0.;
3716 curl_shape(idx,2) = s*dshape_cx(i)*shape_oy(j);
3717 }
3718 // z-components
3719 for (int j = 0; j <= p; j++)
3720 for (int i = 0; i <= p; i++)
3721 {
3722 int idx = dof_map[o++];
3723 curl_shape(idx,0) = shape_cx(i)*dshape_cy(j);
3724 curl_shape(idx,1) = -dshape_cx(i)*shape_cy(j);
3725 curl_shape(idx,2) = 0.;
3726 }
3727}
3728
3729}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
@ GaussLobatto
Closed type.
Definition fe_base.hpp:36
void Factor()
Factor the current DenseMatrix, *a.
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
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
Definition densemat.cpp:108
void Threshold(real_t eps)
Replace small entries, abs(a_ij) <= eps, with zero.
void SetRow(int r, const real_t *row)
real_t InnerProduct(const real_t *x, const real_t *y) const
Compute y^t A x.
Definition densemat.cpp:281
real_t * Data() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:131
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:125
real_t Weight() const
Definition densemat.cpp:553
void GetColumn(int c, Vector &col) const
Rank 3 tensor (array of matrices)
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
const DenseMatrix & InverseJacobian()
Return the inverse of the Jacobian matrix of the transformation at the currently set IntegrationPoint...
Definition eltrans.hpp:158
const IntegrationPoint & GetIntPoint()
Get a const reference to the currently set integration point. This will return NULL if no integration...
Definition eltrans.hpp:111
real_t Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint....
Definition eltrans.hpp:144
const DenseMatrix & Jacobian()
Return the Jacobian matrix of the transformation at the currently set IntegrationPoint,...
Definition eltrans.hpp:132
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
virtual void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_base.cpp:50
int dof
Number of degrees of freedom.
Definition fe_base.hpp:303
int GetRangeDim() const
Returns the vector dimension for vector-valued finite elements, which is also the dimension of the in...
Definition fe_base.hpp:387
virtual void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_base.cpp:75
IntegrationRule Nodes
Definition fe_base.hpp:306
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:381
int vdim
Vector dimension of vector-valued basis functions.
Definition fe_base.hpp:297
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition fe_base.hpp:436
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
Definition fe_base.hpp:427
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:476
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
int cdim
Dimension of curl for vector-valued basis functions.
Definition fe_base.hpp:298
@ CURL
Implements CalcCurlShape methods.
Definition fe_base.hpp:367
Geometry::Type geom_type
Geometry::Type of the reference element.
Definition fe_base.hpp:299
DenseMatrix vshape
Definition fe_base.hpp:308
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
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 DenseMatrix grad_mu01(real_t z)
static Vector lam45_grad_lam45(real_t x, real_t y, real_t z)
void phi_Q(int p, Vector s, Vector t, DenseMatrix &u) const
static constexpr real_t apex_tol
static Vector lam45(real_t x, real_t y, real_t z)
static void phi_E(int p, real_t s0, real_t s1, real_t *u)
static Vector nu012(real_t z, Vector xy, unsigned int ab)
static DenseMatrix grad_nu120(real_t z, Vector xy, unsigned int ab)
static DenseMatrix grad_lam25(real_t x, real_t y, real_t z)
void E_E(int p, Vector s, Vector sds, DenseMatrix &u) const
static Vector nu01_grad_nu01(real_t z, Vector xy, unsigned int ab)
static Vector lam35(real_t x, real_t y, real_t z)
static Vector lam25(real_t x, real_t y, real_t z)
static Vector nu01(real_t z, Vector xy, unsigned int ab)
static Vector lam25_grad_lam25(real_t x, real_t y, real_t z)
static Vector mu01(real_t z)
static DenseMatrix grad_nu012(real_t z, Vector xy, unsigned int ab)
static Vector grad_mu1(real_t z)
void E_T(int p, Vector s, Vector sds, DenseTensor &u) const
static real_t mu0(real_t z)
static Vector nu120(real_t z, Vector xy, unsigned int ab)
static Vector lam15_grad_lam15(real_t x, real_t y, real_t z)
Computes .
static Vector lam35_grad_lam35(real_t x, real_t y, real_t z)
static Vector grad_mu0(real_t z)
static DenseMatrix grad_lam35(real_t x, real_t y, real_t z)
static DenseMatrix grad_lam15(real_t x, real_t y, real_t z)
Gradients of the above two component vectors.
void E_Q(int p, Vector s, Vector ds, Vector t, DenseTensor &u) const
static Vector lam15(real_t x, real_t y, real_t z)
Two component vectors associated with edges touching the apex.
static Vector mu01_grad_mu01(real_t z, Vector xy, unsigned int ab)
static real_t mu1(real_t z)
static DenseMatrix grad_lam45(real_t x, real_t y, real_t z)
static DenseMatrix grad_nu01(real_t z, Vector xy, unsigned int ab)
static Vector nu12_grad_nu12(real_t z, Vector xy, unsigned int ab)
Describes the function space on each element.
Definition fe_base.hpp:276
static const int MaxDim
Definition geom.hpp:47
const IntegrationPoint & GetCenter(int GeomType) const
Return the center of the given Geometry::Type, GeomType.
Definition geom.hpp:75
static bool CheckPoint(int GeomType, const IntegrationPoint &ip)
Check if the given point is inside the given reference element.
Definition geom.cpp:435
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_h1.cpp:40
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_h1.cpp:59
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_h1.cpp:555
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_h1.cpp:533
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 Set(const real_t x1, const real_t x2, const real_t x3, const real_t w)
Definition intrules.hpp:68
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
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void CalcRawVShape(const IntegrationPoint &ip, DenseMatrix &shape) const
Definition fe_nd.cpp:1877
void CalcRawCurlShape(const IntegrationPoint &ip, DenseMatrix &dshape) const
Definition fe_nd.cpp:1899
ND_FuentesPyramidElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_nd.cpp:1628
virtual void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:1823
virtual void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:1848
ND_HexahedronElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Construct the ND_HexahedronElement of order p and closed and open BasisType cb_type and ob_type.
Definition fe_nd.cpp:26
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_nd.cpp:485
void ProjectIntegrated(VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
Definition fe_nd.cpp:245
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:310
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:400
ND_QuadrilateralElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Construct the ND_QuadrilateralElement of order p and closed and open BasisType cb_type and ob_type.
Definition fe_nd.cpp:533
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:700
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_nd.cpp:820
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:763
void ProjectIntegrated(VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
Definition fe_nd.cpp:624
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:2580
ND_R1D_PointElement(int p)
Construct the ND_R1D_PointElement.
Definition fe_nd.cpp:2569
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:2662
ND_R1D_SegmentElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Construct the ND_R1D_SegmentElement of order p and closed and open BasisType cb_type and ob_type.
Definition fe_nd.cpp:2598
void CalcPhysCurlShape(ElementTransformation &Trans, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in physical space at the point de...
Definition fe_nd.cpp:2755
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:2715
void Project(VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const override
Given a vector coefficient and a transformation, compute its projection (approximation) in the local ...
Definition fe_nd.cpp:2766
ND_R2D_FiniteElement(int p, Geometry::Type G, int Do, const real_t *tk_fe)
Definition fe_nd.cpp:3060
void CalcPhysCurlShape(ElementTransformation &Trans, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in physical space at the point de...
Definition fe_nd.cpp:3095
void Project(VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const override
Given a vector coefficient and a transformation, compute its projection (approximation) in the local ...
Definition fe_nd.cpp:3204
void CalcVShape(ElementTransformation &Trans, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in physical space at the point ...
Definition fe_nd.cpp:3078
void ProjectGrad(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &grad) const override
Compute the discrete gradient matrix from the given FiniteElement onto 'this' FiniteElement....
Definition fe_nd.cpp:3316
void GetLocalRestriction(ElementTransformation &Trans, DenseMatrix &R) const override
Return a local restriction matrix R (Dof x Dof) mapping fine dofs to coarse dofs.
Definition fe_nd.cpp:3158
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:3668
ND_R2D_QuadrilateralElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Construct the ND_R2D_QuadrilateralElement of order p and closed and open BasisType cb_type and ob_typ...
Definition fe_nd.cpp:3481
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:3608
void Project(VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const override
Given a vector coefficient and a transformation, compute its projection (approximation) in the local ...
Definition fe_nd.cpp:3035
ND_R2D_SegmentElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Construct the ND_R2D_SegmentElement of order p and closed and open BasisType cb_type and ob_type.
Definition fe_nd.cpp:2875
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:2924
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:2967
ND_R2D_TriangleElement(const int p, const int cb_type=BasisType::GaussLobatto)
Construct the ND_R2D_TriangleElement of order p.
Definition fe_nd.cpp:3340
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:3448
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:3419
ND_SegmentElement(const int p, const int ob_type=BasisType::GaussLegendre)
Construct the ND_SegmentElement of order p and open BasisType ob_type.
Definition fe_nd.cpp:1268
void ProjectIntegrated(VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
Definition fe_nd.cpp:1300
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:1292
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_nd.cpp:1285
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:1036
ND_TetrahedronElement(const int p)
Construct the ND_TetrahedronElement of order p.
Definition fe_nd.cpp:846
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:994
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:1189
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:1223
ND_TriangleElement(const int p)
Construct the ND_TriangleElement of order p.
Definition fe_nd.cpp:1108
void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const override
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_nd.cpp:1549
void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const override
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_nd.cpp:1583
ND_WedgeElement(const int p, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_nd.cpp:1333
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
void Eval(const real_t x, Vector &u) const
Evaluate the basis functions at point x in [0,1].
Definition fe_base.cpp:1875
bool IsIntegratedType() const
Returns true if the basis is "integrated", false otherwise.
Definition fe_base.hpp:1127
void ScaleIntegrated(bool scale_integrated_)
Set whether the "integrated" basis should be scaled by the subcell sizes. Has no effect for non-integ...
Definition fe_base.cpp:2132
void EvalIntegrated(const Vector &d, Vector &i) const
Evaluate the "integrated" basis type using pre-computed closed basis derivatives.
Definition fe_base.cpp:2107
const real_t * ClosedPoints(const int p, const int btype=BasisType::GaussLobatto, bool on_device=false)
Get coordinates of a closed (GaussLobatto) set of points if degree p.
Definition fe_base.hpp:1201
const real_t * OpenPoints(const int p, const int btype=BasisType::GaussLegendre, bool on_device=false)
Get coordinates of an open (GaussLegendre) set of points if degree p.
Definition fe_base.hpp:1193
static void CalcBasis(const int p, const real_t x, real_t *u)
Evaluate the values of a hierarchical 1D basis at point x hierarchical = k-th basis function is degre...
Definition fe_base.hpp:1220
Poly_1D::Basis & basis1d
Definition fe_base.hpp:1331
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 ...
Intermediate class for finite elements whose basis functions return vector values.
Definition fe_base.hpp:890
Vector data type.
Definition vector.hpp:82
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 mu
Definition ex25.cpp:140
mfem::real_t real_t
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
Definition dual.hpp:374
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
Geometry Geometries
Definition fe.cpp:49
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
float real_t
Definition config.hpp:46
Poly_1D poly1d
Definition fe.cpp:28
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void InvertLinearTrans(ElementTransformation &trans, const IntegrationPoint &pt, Vector &x)
Definition fe_base.cpp:768
constexpr real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:549
STL namespace.
real_t p(const Vector &x, real_t t)