1 // Copyright (c) 2010-2021, 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 // Finite Element classes
13
14 #include "fe.hpp"
15 #include "fe_coll.hpp"
16 #include "../mesh/nurbs.hpp"
17 #include "bilininteg.hpp"
18 #include <cmath>
19
20 namespace mfem
21 {
22
23 using namespace std;
24
FiniteElement(int D,Geometry::Type G,int Do,int O,int F)25 FiniteElement::FiniteElement(int D, Geometry::Type G, int Do, int O, int F)
26 : Nodes(Do)
27 {
28 dim = D ; geom_type = G ; dof = Do ; order = O ; func_space = F;
29 range_type = SCALAR;
30 map_type = VALUE;
31 deriv_type = NONE;
32 deriv_range_type = SCALAR;
33 deriv_map_type = VALUE;
34 for (int i = 0; i < Geometry::MaxDim; i++) { orders[i] = -1; }
35 #ifndef MFEM_THREAD_SAFE
36 vshape.SetSize(dof, dim);
37 #endif
38 }
39
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const40 void FiniteElement::CalcVShape (
41 const IntegrationPoint &ip, DenseMatrix &shape) const
42 {
43 MFEM_ABORT("method is not implemented for this class");
44 }
45
CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const46 void FiniteElement::CalcVShape (
47 ElementTransformation &Trans, DenseMatrix &shape) const
48 {
49 MFEM_ABORT("method is not implemented for this class");
50 }
51
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const52 void FiniteElement::CalcDivShape (
53 const IntegrationPoint &ip, Vector &divshape) const
54 {
55 MFEM_ABORT("method is not implemented for this class");
56 }
57
CalcPhysDivShape(ElementTransformation & Trans,Vector & div_shape) const58 void FiniteElement::CalcPhysDivShape(
59 ElementTransformation &Trans, Vector &div_shape) const
60 {
61 CalcDivShape(Trans.GetIntPoint(), div_shape);
62 div_shape *= (1.0 / Trans.Weight());
63 }
64
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const65 void FiniteElement::CalcCurlShape(const IntegrationPoint &ip,
66 DenseMatrix &curl_shape) const
67 {
68 MFEM_ABORT("method is not implemented for this class");
69 }
70
CalcPhysCurlShape(ElementTransformation & Trans,DenseMatrix & curl_shape) const71 void FiniteElement::CalcPhysCurlShape(ElementTransformation &Trans,
72 DenseMatrix &curl_shape) const
73 {
74 switch (dim)
75 {
76 case 3:
77 {
78 #ifdef MFEM_THREAD_SAFE
79 DenseMatrix vshape(dof, dim);
80 #endif
81 CalcCurlShape(Trans.GetIntPoint(), vshape);
82 MultABt(vshape, Trans.Jacobian(), curl_shape);
83 curl_shape *= (1.0 / Trans.Weight());
84 break;
85 }
86 case 2:
87 // This is valid for both 2x2 and 3x2 Jacobians
88 CalcCurlShape(Trans.GetIntPoint(), curl_shape);
89 curl_shape *= (1.0 / Trans.Weight());
90 break;
91 default:
92 MFEM_ABORT("Invalid dimension, Dim = " << dim);
93 }
94 }
95
GetFaceDofs(int face,int ** dofs,int * ndofs) const96 void FiniteElement::GetFaceDofs(int face, int **dofs, int *ndofs) const
97 {
98 MFEM_ABORT("method is not overloaded");
99 }
100
CalcHessian(const IntegrationPoint & ip,DenseMatrix & h) const101 void FiniteElement::CalcHessian (const IntegrationPoint &ip,
102 DenseMatrix &h) const
103 {
104 MFEM_ABORT("method is not overloaded");
105 }
106
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const107 void FiniteElement::GetLocalInterpolation (ElementTransformation &Trans,
108 DenseMatrix &I) const
109 {
110 MFEM_ABORT("method is not overloaded");
111 }
112
GetLocalRestriction(ElementTransformation &,DenseMatrix &) const113 void FiniteElement::GetLocalRestriction(ElementTransformation &,
114 DenseMatrix &) const
115 {
116 MFEM_ABORT("method is not overloaded");
117 }
118
GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const119 void FiniteElement::GetTransferMatrix(const FiniteElement &fe,
120 ElementTransformation &Trans,
121 DenseMatrix &I) const
122 {
123 MFEM_ABORT("method is not overloaded");
124 }
125
Project(Coefficient & coeff,ElementTransformation & Trans,Vector & dofs) const126 void FiniteElement::Project (
127 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
128 {
129 MFEM_ABORT("method is not overloaded");
130 }
131
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const132 void FiniteElement::Project (
133 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
134 {
135 MFEM_ABORT("method is not overloaded");
136 }
137
ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const138 void FiniteElement::ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
139 Vector &dofs) const
140 {
141 mfem_error ("FiniteElement::ProjectFromNodes() (vector) is not overloaded!");
142 }
143
ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const144 void FiniteElement::ProjectMatrixCoefficient(
145 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
146 {
147 MFEM_ABORT("method is not overloaded");
148 }
149
ProjectDelta(int vertex,Vector & dofs) const150 void FiniteElement::ProjectDelta(int vertex, Vector &dofs) const
151 {
152 MFEM_ABORT("method is not implemented for this element");
153 }
154
Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const155 void FiniteElement::Project(
156 const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
157 {
158 MFEM_ABORT("method is not implemented for this element");
159 }
160
ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const161 void FiniteElement::ProjectGrad(
162 const FiniteElement &fe, ElementTransformation &Trans,
163 DenseMatrix &grad) const
164 {
165 MFEM_ABORT("method is not implemented for this element");
166 }
167
ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const168 void FiniteElement::ProjectCurl(
169 const FiniteElement &fe, ElementTransformation &Trans,
170 DenseMatrix &curl) const
171 {
172 MFEM_ABORT("method is not implemented for this element");
173 }
174
ProjectDiv(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & div) const175 void FiniteElement::ProjectDiv(
176 const FiniteElement &fe, ElementTransformation &Trans,
177 DenseMatrix &div) const
178 {
179 MFEM_ABORT("method is not implemented for this element");
180 }
181
CalcPhysShape(ElementTransformation & Trans,Vector & shape) const182 void FiniteElement::CalcPhysShape(ElementTransformation &Trans,
183 Vector &shape) const
184 {
185 CalcShape(Trans.GetIntPoint(), shape);
186 if (map_type == INTEGRAL)
187 {
188 shape /= Trans.Weight();
189 }
190 }
191
CalcPhysDShape(ElementTransformation & Trans,DenseMatrix & dshape) const192 void FiniteElement::CalcPhysDShape(ElementTransformation &Trans,
193 DenseMatrix &dshape) const
194 {
195 MFEM_ASSERT(map_type == VALUE, "");
196 #ifdef MFEM_THREAD_SAFE
197 DenseMatrix vshape(dof, dim);
198 #endif
199 CalcDShape(Trans.GetIntPoint(), vshape);
200 Mult(vshape, Trans.InverseJacobian(), dshape);
201 }
202
CalcPhysLaplacian(ElementTransformation & Trans,Vector & Laplacian) const203 void FiniteElement::CalcPhysLaplacian(ElementTransformation &Trans,
204 Vector &Laplacian) const
205 {
206 MFEM_ASSERT(map_type == VALUE, "");
207
208 // Simpler routine if mapping is affine
209 if (Trans.Hessian().FNorm2() < 1e-20)
210 {
211 CalcPhysLinLaplacian(Trans, Laplacian);
212 return;
213 }
214
215 // Compute full Hessian first if non-affine
216 int size = (dim*(dim+1))/2;
217 DenseMatrix hess(dof, size);
218 CalcPhysHessian(Trans,hess);
219
220 if (dim == 3)
221 {
222 for (int nd = 0; nd < dof; nd++)
223 {
224 Laplacian[nd] = hess(nd,0) + hess(nd,4) + hess(nd,5);
225 }
226 }
227 else if (dim == 2)
228 {
229 for (int nd = 0; nd < dof; nd++)
230 {
231 Laplacian[nd] = hess(nd,0) + hess(nd,2);
232 }
233 }
234 else
235 {
236 for (int nd = 0; nd < dof; nd++)
237 {
238 Laplacian[nd] = hess(nd,0);
239 }
240 }
241 }
242
243
244 // Assume a linear mapping
CalcPhysLinLaplacian(ElementTransformation & Trans,Vector & Laplacian) const245 void FiniteElement::CalcPhysLinLaplacian(ElementTransformation &Trans,
246 Vector &Laplacian) const
247 {
248 MFEM_ASSERT(map_type == VALUE, "");
249 int size = (dim*(dim+1))/2;
250 DenseMatrix hess(dof, size);
251 DenseMatrix Gij(dim,dim);
252 Vector scale(size);
253
254 CalcHessian (Trans.GetIntPoint(), hess);
255 MultAAt(Trans.InverseJacobian(), Gij);
256
257 if (dim == 3)
258 {
259 scale[0] = Gij(0,0);
260 scale[1] = 2*Gij(0,1);
261 scale[2] = 2*Gij(0,2);
262
263 scale[3] = 2*Gij(1,2);
264 scale[4] = Gij(2,2);
265
266 scale[5] = Gij(1,1);
267 }
268 else if (dim == 2)
269 {
270 scale[0] = Gij(0,0);
271 scale[1] = 2*Gij(0,1);
272 scale[2] = Gij(1,1);
273 }
274 else
275 {
276 scale[0] = Gij(0,0);
277 }
278
279 for (int nd = 0; nd < dof; nd++)
280 {
281 Laplacian[nd] = 0.0;
282 for (int ii = 0; ii < size; ii++)
283 {
284 Laplacian[nd] += hess(nd,ii)*scale[ii];
285 }
286 }
287
288 }
289
CalcPhysHessian(ElementTransformation & Trans,DenseMatrix & Hessian) const290 void FiniteElement::CalcPhysHessian(ElementTransformation &Trans,
291 DenseMatrix& Hessian) const
292 {
293 MFEM_ASSERT(map_type == VALUE, "");
294
295 // Roll 2-Tensors in vectors and 4-Tensor in Matrix, exploiting symmetry
296 Array<int> map(dim*dim);
297 if (dim == 3)
298 {
299 map[0] = 0;
300 map[1] = 1;
301 map[2] = 2;
302
303 map[3] = 1;
304 map[4] = 5;
305 map[5] = 3;
306
307 map[6] = 2;
308 map[7] = 3;
309 map[8] = 4;
310 }
311 else if (dim == 2)
312 {
313 map[0] = 0;
314 map[1] = 1;
315
316 map[2] = 1;
317 map[3] = 2;
318 }
319 else
320 {
321 map[0] = 0;
322 }
323
324 // Hessian in ref coords
325 int size = (dim*(dim+1))/2;
326 DenseMatrix hess(dof, size);
327 CalcHessian(Trans.GetIntPoint(), hess);
328
329 // Gradient in physical coords
330 if (Trans.Hessian().FNorm2() > 1e-10)
331 {
332 DenseMatrix grad(dof, dim);
333 CalcPhysDShape(Trans, grad);
334 DenseMatrix gmap(dof, size);
335 Mult(grad,Trans.Hessian(),gmap);
336 hess -= gmap;
337 }
338
339 // LHM
340 DenseMatrix lhm(size,size);
341 DenseMatrix invJ = Trans.Jacobian();
342 lhm = 0.0;
343 for (int i = 0; i < dim; i++)
344 {
345 for (int j = 0; j < dim; j++)
346 {
347 for (int k = 0; k < dim; k++)
348 {
349 for (int l = 0; l < dim; l++)
350 {
351 lhm(map[i*dim+j],map[k*dim+l]) += invJ(i,k)*invJ(j,l);
352 }
353 }
354 }
355 }
356 // Correct multiplicity
357 Vector mult(size);
358 mult = 0.0;
359 for (int i = 0; i < dim*dim; i++) { mult[map[i]]++; }
360 lhm.InvRightScaling(mult);
361
362 // Hessian in physical coords
363 lhm.Invert();
364 Mult( hess, lhm, Hessian);
365 }
366
GetDofToQuad(const IntegrationRule &,DofToQuad::Mode) const367 const DofToQuad &FiniteElement::GetDofToQuad(const IntegrationRule &,
368 DofToQuad::Mode) const
369 {
370 MFEM_ABORT("method is not implemented for this element");
371 return *dof2quad_array[0]; // suppress a warning
372 }
373
~FiniteElement()374 FiniteElement::~FiniteElement()
375 {
376 for (int i = 0; i < dof2quad_array.Size(); i++)
377 {
378 delete dof2quad_array[i];
379 }
380 }
381
382
NodalLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I,const ScalarFiniteElement & fine_fe) const383 void ScalarFiniteElement::NodalLocalInterpolation (
384 ElementTransformation &Trans, DenseMatrix &I,
385 const ScalarFiniteElement &fine_fe) const
386 {
387 double v[Geometry::MaxDim];
388 Vector vv (v, dim);
389 IntegrationPoint f_ip;
390
391 #ifdef MFEM_THREAD_SAFE
392 Vector c_shape(dof);
393 #endif
394
395 MFEM_ASSERT(map_type == fine_fe.GetMapType(), "");
396
397 I.SetSize(fine_fe.dof, dof);
398 for (int i = 0; i < fine_fe.dof; i++)
399 {
400 Trans.Transform(fine_fe.Nodes.IntPoint(i), vv);
401 f_ip.Set(v, dim);
402 CalcShape(f_ip, c_shape);
403 for (int j = 0; j < dof; j++)
404 {
405 if (fabs(I(i,j) = c_shape(j)) < 1.0e-12)
406 {
407 I(i,j) = 0.0;
408 }
409 }
410 }
411 if (map_type == INTEGRAL)
412 {
413 // assuming Trans is linear; this should be ok for all refinement types
414 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
415 I *= Trans.Weight();
416 }
417 }
418
ScalarLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I,const ScalarFiniteElement & fine_fe) const419 void ScalarFiniteElement::ScalarLocalInterpolation(
420 ElementTransformation &Trans, DenseMatrix &I,
421 const ScalarFiniteElement &fine_fe) const
422 {
423 // General "interpolation", defined by L2 projection
424
425 double v[Geometry::MaxDim];
426 Vector vv (v, dim);
427 IntegrationPoint f_ip;
428
429 const int fs = fine_fe.GetDof(), cs = this->GetDof();
430 I.SetSize(fs, cs);
431 Vector fine_shape(fs), coarse_shape(cs);
432 DenseMatrix fine_mass(fs), fine_coarse_mass(fs, cs); // initialized with 0
433 const int ir_order =
434 std::max(GetOrder(), fine_fe.GetOrder()) + fine_fe.GetOrder();
435 const IntegrationRule &ir = IntRules.Get(fine_fe.GetGeomType(), ir_order);
436
437 for (int i = 0; i < ir.GetNPoints(); i++)
438 {
439 const IntegrationPoint &ip = ir.IntPoint(i);
440 fine_fe.CalcShape(ip, fine_shape);
441 Trans.Transform(ip, vv);
442 f_ip.Set(v, dim);
443 this->CalcShape(f_ip, coarse_shape);
444
445 AddMult_a_VVt(ip.weight, fine_shape, fine_mass);
446 AddMult_a_VWt(ip.weight, fine_shape, coarse_shape, fine_coarse_mass);
447 }
448
449 DenseMatrixInverse fine_mass_inv(fine_mass);
450 fine_mass_inv.Mult(fine_coarse_mass, I);
451
452 if (map_type == INTEGRAL)
453 {
454 // assuming Trans is linear; this should be ok for all refinement types
455 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
456 I *= Trans.Weight();
457 }
458 }
459
ScalarLocalRestriction(ElementTransformation & Trans,DenseMatrix & R,const ScalarFiniteElement & coarse_fe) const460 void ScalarFiniteElement::ScalarLocalRestriction(
461 ElementTransformation &Trans, DenseMatrix &R,
462 const ScalarFiniteElement &coarse_fe) const
463 {
464 // General "restriction", defined by L2 projection
465 double v[Geometry::MaxDim];
466 Vector vv (v, dim);
467 IntegrationPoint f_ip;
468
469 const int cs = coarse_fe.GetDof(), fs = this->GetDof();
470 R.SetSize(cs, fs);
471 Vector fine_shape(fs), coarse_shape(cs);
472 DenseMatrix coarse_mass(cs), coarse_fine_mass(cs, fs); // initialized with 0
473 const int ir_order = GetOrder() + coarse_fe.GetOrder();
474 const IntegrationRule &ir = IntRules.Get(coarse_fe.GetGeomType(), ir_order);
475
476 for (int i = 0; i < ir.GetNPoints(); i++)
477 {
478 const IntegrationPoint &ip = ir.IntPoint(i);
479 this->CalcShape(ip, fine_shape);
480 Trans.Transform(ip, vv);
481 f_ip.Set(v, dim);
482 coarse_fe.CalcShape(f_ip, coarse_shape);
483
484 AddMult_a_VVt(ip.weight, coarse_shape, coarse_mass);
485 AddMult_a_VWt(ip.weight, coarse_shape, fine_shape, coarse_fine_mass);
486 }
487
488 DenseMatrixInverse coarse_mass_inv(coarse_mass);
489 coarse_mass_inv.Mult(coarse_fine_mass, R);
490
491 if (map_type == INTEGRAL)
492 {
493 // assuming Trans is linear; this should be ok for all refinement types
494 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
495 R *= 1.0 / Trans.Weight();
496 }
497 }
498
GetDofToQuad(const IntegrationRule & ir,DofToQuad::Mode mode) const499 const DofToQuad &ScalarFiniteElement::GetDofToQuad(const IntegrationRule &ir,
500 DofToQuad::Mode mode) const
501 {
502 MFEM_VERIFY(mode == DofToQuad::FULL, "invalid mode requested");
503
504 for (int i = 0; i < dof2quad_array.Size(); i++)
505 {
506 const DofToQuad &d2q = *dof2quad_array[i];
507 if (d2q.IntRule == &ir && d2q.mode == mode) { return d2q; }
508 }
509
510 DofToQuad *d2q = new DofToQuad;
511 const int nqpt = ir.GetNPoints();
512 d2q->FE = this;
513 d2q->IntRule = &ir;
514 d2q->mode = mode;
515 d2q->ndof = dof;
516 d2q->nqpt = nqpt;
517 d2q->B.SetSize(nqpt*dof);
518 d2q->Bt.SetSize(dof*nqpt);
519 d2q->G.SetSize(nqpt*dim*dof);
520 d2q->Gt.SetSize(dof*nqpt*dim);
521 #ifdef MFEM_THREAD_SAFE
522 Vector c_shape(dof);
523 DenseMatrix vshape(dof, dim);
524 #endif
525 for (int i = 0; i < nqpt; i++)
526 {
527 const IntegrationPoint &ip = ir.IntPoint(i);
528 CalcShape(ip, c_shape);
529 for (int j = 0; j < dof; j++)
530 {
531 d2q->B[i+nqpt*j] = d2q->Bt[j+dof*i] = c_shape(j);
532 }
533 CalcDShape(ip, vshape);
534 for (int d = 0; d < dim; d++)
535 {
536 for (int j = 0; j < dof; j++)
537 {
538 d2q->G[i+nqpt*(d+dim*j)] = d2q->Gt[j+dof*(i+nqpt*d)] = vshape(j,d);
539 }
540 }
541 }
542 dof2quad_array.Append(d2q);
543 return *d2q;
544 }
545
546 // protected method
GetTensorDofToQuad(const TensorBasisElement & tb,const IntegrationRule & ir,DofToQuad::Mode mode) const547 const DofToQuad &ScalarFiniteElement::GetTensorDofToQuad(
548 const TensorBasisElement &tb,
549 const IntegrationRule &ir, DofToQuad::Mode mode) const
550 {
551 MFEM_VERIFY(mode == DofToQuad::TENSOR, "invalid mode requested");
552
553 for (int i = 0; i < dof2quad_array.Size(); i++)
554 {
555 const DofToQuad &d2q = *dof2quad_array[i];
556 if (d2q.IntRule == &ir && d2q.mode == mode) { return d2q; }
557 }
558
559 DofToQuad *d2q = new DofToQuad;
560 const Poly_1D::Basis &basis_1d = tb.GetBasis1D();
561 const int ndof = order + 1;
562 const int nqpt = (int)floor(pow(ir.GetNPoints(), 1.0/dim) + 0.5);
563 d2q->FE = this;
564 d2q->IntRule = &ir;
565 d2q->mode = mode;
566 d2q->ndof = ndof;
567 d2q->nqpt = nqpt;
568 d2q->B.SetSize(nqpt*ndof);
569 d2q->Bt.SetSize(ndof*nqpt);
570 d2q->G.SetSize(nqpt*ndof);
571 d2q->Gt.SetSize(ndof*nqpt);
572 Vector val(ndof), grad(ndof);
573 for (int i = 0; i < nqpt; i++)
574 {
575 // The first 'nqpt' points in 'ir' have the same x-coordinates as those
576 // of the 1D rule.
577 basis_1d.Eval(ir.IntPoint(i).x, val, grad);
578 for (int j = 0; j < ndof; j++)
579 {
580 d2q->B[i+nqpt*j] = d2q->Bt[j+ndof*i] = val(j);
581 d2q->G[i+nqpt*j] = d2q->Gt[j+ndof*i] = grad(j);
582 }
583 }
584 dof2quad_array.Append(d2q);
585 return *d2q;
586 }
587
588
ProjectCurl_2D(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const589 void NodalFiniteElement::ProjectCurl_2D(
590 const FiniteElement &fe, ElementTransformation &Trans,
591 DenseMatrix &curl) const
592 {
593 DenseMatrix curl_shape(fe.GetDof(), 1);
594
595 curl.SetSize(dof, fe.GetDof());
596 for (int i = 0; i < dof; i++)
597 {
598 fe.CalcCurlShape(Nodes.IntPoint(i), curl_shape);
599
600 double w = 1.0;
601 if (GetMapType() == FiniteElement::VALUE)
602 {
603 Trans.SetIntPoint(&Nodes.IntPoint(i));
604 w /= Trans.Weight();
605 }
606 for (int j = 0; j < fe.GetDof(); j++)
607 {
608 curl(i,j) = w * curl_shape(j,0);
609 }
610 }
611 }
612
InvertLinearTrans(ElementTransformation & trans,const IntegrationPoint & pt,Vector & x)613 void InvertLinearTrans(ElementTransformation &trans,
614 const IntegrationPoint &pt, Vector &x)
615 {
616 // invert a linear transform with one Newton step
617 IntegrationPoint p0;
618 p0.Set3(0, 0, 0);
619 trans.Transform(p0, x);
620
621 double store[3];
622 Vector v(store, x.Size());
623 pt.Get(v, x.Size());
624 v -= x;
625
626 trans.InverseJacobian().Mult(v, x);
627 }
628
GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const629 void NodalFiniteElement::GetLocalRestriction(ElementTransformation &Trans,
630 DenseMatrix &R) const
631 {
632 IntegrationPoint ipt;
633 Vector pt(&ipt.x, dim);
634
635 #ifdef MFEM_THREAD_SAFE
636 Vector c_shape(dof);
637 #endif
638
639 Trans.SetIntPoint(&Nodes[0]);
640
641 for (int j = 0; j < dof; j++)
642 {
643 InvertLinearTrans(Trans, Nodes[j], pt);
644 if (Geometries.CheckPoint(geom_type, ipt)) // do we need an epsilon here?
645 {
646 CalcShape(ipt, c_shape);
647 R.SetRow(j, c_shape);
648 }
649 else
650 {
651 // Set the whole row to avoid valgrind warnings in R.Threshold().
652 R.SetRow(j, infinity());
653 }
654 }
655 R.Threshold(1e-12);
656 }
657
Project(Coefficient & coeff,ElementTransformation & Trans,Vector & dofs) const658 void NodalFiniteElement::Project (
659 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
660 {
661 for (int i = 0; i < dof; i++)
662 {
663 const IntegrationPoint &ip = Nodes.IntPoint(i);
664 // some coefficients expect that Trans.IntPoint is the same
665 // as the second argument of Eval
666 Trans.SetIntPoint(&ip);
667 dofs(i) = coeff.Eval (Trans, ip);
668 if (map_type == INTEGRAL)
669 {
670 dofs(i) *= Trans.Weight();
671 }
672 }
673 }
674
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const675 void NodalFiniteElement::Project (
676 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
677 {
678 MFEM_ASSERT(dofs.Size() == vc.GetVDim()*dof, "");
679 Vector x(vc.GetVDim());
680
681 for (int i = 0; i < dof; i++)
682 {
683 const IntegrationPoint &ip = Nodes.IntPoint(i);
684 Trans.SetIntPoint(&ip);
685 vc.Eval (x, Trans, ip);
686 if (map_type == INTEGRAL)
687 {
688 x *= Trans.Weight();
689 }
690 for (int j = 0; j < x.Size(); j++)
691 {
692 dofs(dof*j+i) = x(j);
693 }
694 }
695 }
696
ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const697 void NodalFiniteElement::ProjectMatrixCoefficient(
698 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
699 {
700 // (mc.height x mc.width) @ DOFs -> (dof x mc.width x mc.height) in dofs
701 MFEM_ASSERT(dofs.Size() == mc.GetHeight()*mc.GetWidth()*dof, "");
702 DenseMatrix MQ(mc.GetHeight(), mc.GetWidth());
703
704 for (int k = 0; k < dof; k++)
705 {
706 T.SetIntPoint(&Nodes.IntPoint(k));
707 mc.Eval(MQ, T, Nodes.IntPoint(k));
708 if (map_type == INTEGRAL) { MQ *= T.Weight(); }
709 for (int r = 0; r < MQ.Height(); r++)
710 {
711 for (int d = 0; d < MQ.Width(); d++)
712 {
713 dofs(k+dof*(d+MQ.Width()*r)) = MQ(r,d);
714 }
715 }
716 }
717 }
718
Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const719 void NodalFiniteElement::Project(
720 const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
721 {
722 if (fe.GetRangeType() == SCALAR)
723 {
724 Vector shape(fe.GetDof());
725
726 I.SetSize(dof, fe.GetDof());
727 if (map_type == fe.GetMapType())
728 {
729 for (int k = 0; k < dof; k++)
730 {
731 fe.CalcShape(Nodes.IntPoint(k), shape);
732 for (int j = 0; j < shape.Size(); j++)
733 {
734 I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j);
735 }
736 }
737 }
738 else
739 {
740 for (int k = 0; k < dof; k++)
741 {
742 Trans.SetIntPoint(&Nodes.IntPoint(k));
743 fe.CalcPhysShape(Trans, shape);
744 if (map_type == INTEGRAL)
745 {
746 shape *= Trans.Weight();
747 }
748 for (int j = 0; j < shape.Size(); j++)
749 {
750 I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j);
751 }
752 }
753 }
754 }
755 else
756 {
757 DenseMatrix vshape(fe.GetDof(), Trans.GetSpaceDim());
758
759 I.SetSize(vshape.Width()*dof, fe.GetDof());
760 for (int k = 0; k < dof; k++)
761 {
762 Trans.SetIntPoint(&Nodes.IntPoint(k));
763 fe.CalcVShape(Trans, vshape);
764 if (map_type == INTEGRAL)
765 {
766 vshape *= Trans.Weight();
767 }
768 for (int j = 0; j < vshape.Height(); j++)
769 for (int d = 0; d < vshape.Width(); d++)
770 {
771 I(k+d*dof,j) = vshape(j,d);
772 }
773 }
774 }
775 }
776
ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const777 void NodalFiniteElement::ProjectGrad(
778 const FiniteElement &fe, ElementTransformation &Trans,
779 DenseMatrix &grad) const
780 {
781 MFEM_ASSERT(fe.GetMapType() == VALUE, "");
782 MFEM_ASSERT(Trans.GetSpaceDim() == dim, "")
783
784 DenseMatrix dshape(fe.GetDof(), dim), grad_k(fe.GetDof(), dim), Jinv(dim);
785
786 grad.SetSize(dim*dof, fe.GetDof());
787 for (int k = 0; k < dof; k++)
788 {
789 const IntegrationPoint &ip = Nodes.IntPoint(k);
790 fe.CalcDShape(ip, dshape);
791 Trans.SetIntPoint(&ip);
792 CalcInverse(Trans.Jacobian(), Jinv);
793 Mult(dshape, Jinv, grad_k);
794 if (map_type == INTEGRAL)
795 {
796 grad_k *= Trans.Weight();
797 }
798 for (int j = 0; j < grad_k.Height(); j++)
799 for (int d = 0; d < dim; d++)
800 {
801 grad(k+d*dof,j) = grad_k(j,d);
802 }
803 }
804 }
805
ProjectDiv(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & div) const806 void NodalFiniteElement::ProjectDiv(
807 const FiniteElement &fe, ElementTransformation &Trans,
808 DenseMatrix &div) const
809 {
810 double detJ;
811 Vector div_shape(fe.GetDof());
812
813 div.SetSize(dof, fe.GetDof());
814 for (int k = 0; k < dof; k++)
815 {
816 const IntegrationPoint &ip = Nodes.IntPoint(k);
817 fe.CalcDivShape(ip, div_shape);
818 if (map_type == VALUE)
819 {
820 Trans.SetIntPoint(&ip);
821 detJ = Trans.Weight();
822 for (int j = 0; j < div_shape.Size(); j++)
823 {
824 div(k,j) = (fabs(div_shape(j)) < 1e-12) ? 0.0 : div_shape(j)/detJ;
825 }
826 }
827 else
828 {
829 for (int j = 0; j < div_shape.Size(); j++)
830 {
831 div(k,j) = (fabs(div_shape(j)) < 1e-12) ? 0.0 : div_shape(j);
832 }
833 }
834 }
835 }
836
837
Project(Coefficient & coeff,ElementTransformation & Trans,Vector & dofs) const838 void PositiveFiniteElement::Project(
839 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
840 {
841 for (int i = 0; i < dof; i++)
842 {
843 const IntegrationPoint &ip = Nodes.IntPoint(i);
844 Trans.SetIntPoint(&ip);
845 dofs(i) = coeff.Eval(Trans, ip);
846 }
847 }
848
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const849 void PositiveFiniteElement::Project(
850 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
851 {
852 MFEM_ASSERT(dofs.Size() == vc.GetVDim()*dof, "");
853 Vector x(vc.GetVDim());
854
855 for (int i = 0; i < dof; i++)
856 {
857 const IntegrationPoint &ip = Nodes.IntPoint(i);
858 Trans.SetIntPoint(&ip);
859 vc.Eval (x, Trans, ip);
860 for (int j = 0; j < x.Size(); j++)
861 {
862 dofs(dof*j+i) = x(j);
863 }
864 }
865 }
866
Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const867 void PositiveFiniteElement::Project(
868 const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
869 {
870 const NodalFiniteElement *nfe =
871 dynamic_cast<const NodalFiniteElement *>(&fe);
872
873 if (nfe && dof == nfe->GetDof())
874 {
875 nfe->Project(*this, Trans, I);
876 I.Invert();
877 }
878 else
879 {
880 // local L2 projection
881 DenseMatrix pos_mass, mixed_mass;
882 MassIntegrator mass_integ;
883
884 mass_integ.AssembleElementMatrix(*this, Trans, pos_mass);
885 mass_integ.AssembleElementMatrix2(fe, *this, Trans, mixed_mass);
886
887 DenseMatrixInverse pos_mass_inv(pos_mass);
888 I.SetSize(dof, fe.GetDof());
889 pos_mass_inv.Mult(mixed_mass, I);
890 }
891 }
892
893
CalcShape(const IntegrationPoint & ip,Vector & shape) const894 void VectorFiniteElement::CalcShape (
895 const IntegrationPoint &ip, Vector &shape ) const
896 {
897 mfem_error ("Error: Cannot use scalar CalcShape(...) function with\n"
898 " VectorFiniteElements!");
899 }
900
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const901 void VectorFiniteElement::CalcDShape (
902 const IntegrationPoint &ip, DenseMatrix &dshape ) const
903 {
904 mfem_error ("Error: Cannot use scalar CalcDShape(...) function with\n"
905 " VectorFiniteElements!");
906 }
907
SetDerivMembers()908 void VectorFiniteElement::SetDerivMembers()
909 {
910 switch (map_type)
911 {
912 case H_DIV:
913 deriv_type = DIV;
914 deriv_range_type = SCALAR;
915 deriv_map_type = INTEGRAL;
916 break;
917 case H_CURL:
918 switch (dim)
919 {
920 case 3: // curl: 3D H_CURL -> 3D H_DIV
921 deriv_type = CURL;
922 deriv_range_type = VECTOR;
923 deriv_map_type = H_DIV;
924 break;
925 case 2:
926 // curl: 2D H_CURL -> INTEGRAL
927 deriv_type = CURL;
928 deriv_range_type = SCALAR;
929 deriv_map_type = INTEGRAL;
930 break;
931 case 1:
932 deriv_type = NONE;
933 deriv_range_type = SCALAR;
934 deriv_map_type = INTEGRAL;
935 break;
936 default:
937 MFEM_ABORT("Invalid dimension, Dim = " << dim);
938 }
939 break;
940 default:
941 MFEM_ABORT("Invalid MapType = " << map_type);
942 }
943 }
944
CalcVShape_RT(ElementTransformation & Trans,DenseMatrix & shape) const945 void VectorFiniteElement::CalcVShape_RT (
946 ElementTransformation &Trans, DenseMatrix &shape) const
947 {
948 MFEM_ASSERT(map_type == H_DIV, "");
949 #ifdef MFEM_THREAD_SAFE
950 DenseMatrix vshape(dof, dim);
951 #endif
952 CalcVShape(Trans.GetIntPoint(), vshape);
953 MultABt(vshape, Trans.Jacobian(), shape);
954 shape *= (1.0 / Trans.Weight());
955 }
956
CalcVShape_ND(ElementTransformation & Trans,DenseMatrix & shape) const957 void VectorFiniteElement::CalcVShape_ND (
958 ElementTransformation &Trans, DenseMatrix &shape) const
959 {
960 MFEM_ASSERT(map_type == H_CURL, "");
961 #ifdef MFEM_THREAD_SAFE
962 DenseMatrix vshape(dof, dim);
963 #endif
964 CalcVShape(Trans.GetIntPoint(), vshape);
965 Mult(vshape, Trans.InverseJacobian(), shape);
966 }
967
Project_RT(const double * nk,const Array<int> & d2n,VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const968 void VectorFiniteElement::Project_RT(
969 const double *nk, const Array<int> &d2n,
970 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
971 {
972 double vk[Geometry::MaxDim];
973 const int sdim = Trans.GetSpaceDim();
974 MFEM_ASSERT(vc.GetVDim() == sdim, "");
975 Vector xk(vk, sdim);
976 const bool square_J = (dim == sdim);
977
978 for (int k = 0; k < dof; k++)
979 {
980 Trans.SetIntPoint(&Nodes.IntPoint(k));
981 vc.Eval(xk, Trans, Nodes.IntPoint(k));
982 // dof_k = nk^t adj(J) xk
983 dofs(k) = Trans.AdjugateJacobian().InnerProduct(vk, nk + d2n[k]*dim);
984 if (!square_J) { dofs(k) /= Trans.Weight(); }
985 }
986 }
987
Project_RT(const double * nk,const Array<int> & d2n,Vector & vc,ElementTransformation & Trans,Vector & dofs) const988 void VectorFiniteElement::Project_RT(
989 const double *nk, const Array<int> &d2n,
990 Vector &vc, ElementTransformation &Trans, Vector &dofs) const
991 {
992 const int sdim = Trans.GetSpaceDim();
993 const bool square_J = (dim == sdim);
994
995 for (int k = 0; k < dof; k++)
996 {
997 Trans.SetIntPoint(&Nodes.IntPoint(k));
998 // dof_k = nk^t adj(J) xk
999 Vector vk(vc.GetData()+k*sdim, sdim);
1000 dofs(k) = Trans.AdjugateJacobian().InnerProduct(vk, nk + d2n[k]*dim);
1001 if (!square_J) { dofs(k) /= Trans.Weight(); }
1002 }
1003 }
1004
ProjectMatrixCoefficient_RT(const double * nk,const Array<int> & d2n,MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const1005 void VectorFiniteElement::ProjectMatrixCoefficient_RT(
1006 const double *nk, const Array<int> &d2n,
1007 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
1008 {
1009 // project the rows of the matrix coefficient in an RT space
1010
1011 const int sdim = T.GetSpaceDim();
1012 MFEM_ASSERT(mc.GetWidth() == sdim, "");
1013 const bool square_J = (dim == sdim);
1014 DenseMatrix MQ(mc.GetHeight(), mc.GetWidth());
1015 Vector nk_phys(sdim), dofs_k(MQ.Height());
1016 MFEM_ASSERT(dofs.Size() == dof*MQ.Height(), "");
1017
1018 for (int k = 0; k < dof; k++)
1019 {
1020 T.SetIntPoint(&Nodes.IntPoint(k));
1021 mc.Eval(MQ, T, Nodes.IntPoint(k));
1022 // nk_phys = adj(J)^t nk
1023 T.AdjugateJacobian().MultTranspose(nk + d2n[k]*dim, nk_phys);
1024 if (!square_J) { nk_phys /= T.Weight(); }
1025 MQ.Mult(nk_phys, dofs_k);
1026 for (int r = 0; r < MQ.Height(); r++)
1027 {
1028 dofs(k+dof*r) = dofs_k(r);
1029 }
1030 }
1031 }
1032
Project_RT(const double * nk,const Array<int> & d2n,const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const1033 void VectorFiniteElement::Project_RT(
1034 const double *nk, const Array<int> &d2n, const FiniteElement &fe,
1035 ElementTransformation &Trans, DenseMatrix &I) const
1036 {
1037 if (fe.GetRangeType() == SCALAR)
1038 {
1039 double vk[Geometry::MaxDim];
1040 Vector shape(fe.GetDof());
1041 int sdim = Trans.GetSpaceDim();
1042
1043 I.SetSize(dof, sdim*fe.GetDof());
1044 for (int k = 0; k < dof; k++)
1045 {
1046 const IntegrationPoint &ip = Nodes.IntPoint(k);
1047
1048 fe.CalcShape(ip, shape);
1049 Trans.SetIntPoint(&ip);
1050 // Transform RT face normals from reference to physical space
1051 // vk = adj(J)^T nk
1052 Trans.AdjugateJacobian().MultTranspose(nk + d2n[k]*dim, vk);
1053 if (fe.GetMapType() == INTEGRAL)
1054 {
1055 double w = 1.0/Trans.Weight();
1056 for (int d = 0; d < dim; d++)
1057 {
1058 vk[d] *= w;
1059 }
1060 }
1061
1062 for (int j = 0; j < shape.Size(); j++)
1063 {
1064 double s = shape(j);
1065 if (fabs(s) < 1e-12)
1066 {
1067 s = 0.0;
1068 }
1069 // Project scalar basis function multiplied by each coordinate
1070 // direction onto the transformed face normals
1071 for (int d = 0; d < sdim; d++)
1072 {
1073 I(k,j+d*shape.Size()) = s*vk[d];
1074 }
1075 }
1076 }
1077 }
1078 else
1079 {
1080 int sdim = Trans.GetSpaceDim();
1081 double vk[Geometry::MaxDim];
1082 DenseMatrix vshape(fe.GetDof(), sdim);
1083 Vector vshapenk(fe.GetDof());
1084 const bool square_J = (dim == sdim);
1085
1086 I.SetSize(dof, fe.GetDof());
1087 for (int k = 0; k < dof; k++)
1088 {
1089 const IntegrationPoint &ip = Nodes.IntPoint(k);
1090
1091 Trans.SetIntPoint(&ip);
1092 // Transform RT face normals from reference to physical space
1093 // vk = adj(J)^T nk
1094 Trans.AdjugateJacobian().MultTranspose(nk + d2n[k]*dim, vk);
1095 // Compute fe basis functions in physical space
1096 fe.CalcVShape(Trans, vshape);
1097 // Project fe basis functions onto transformed face normals
1098 vshape.Mult(vk, vshapenk);
1099 if (!square_J) { vshapenk /= Trans.Weight(); }
1100 for (int j=0; j<vshapenk.Size(); j++)
1101 {
1102 I(k,j) = vshapenk(j);
1103 }
1104 }
1105 }
1106 }
1107
ProjectGrad_RT(const double * nk,const Array<int> & d2n,const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const1108 void VectorFiniteElement::ProjectGrad_RT(
1109 const double *nk, const Array<int> &d2n, const FiniteElement &fe,
1110 ElementTransformation &Trans, DenseMatrix &grad) const
1111 {
1112 if (dim != 2)
1113 {
1114 mfem_error("VectorFiniteElement::ProjectGrad_RT works only in 2D!");
1115 }
1116
1117 DenseMatrix dshape(fe.GetDof(), fe.GetDim());
1118 Vector grad_k(fe.GetDof());
1119 double tk[2];
1120
1121 grad.SetSize(dof, fe.GetDof());
1122 for (int k = 0; k < dof; k++)
1123 {
1124 fe.CalcDShape(Nodes.IntPoint(k), dshape);
1125 tk[0] = nk[d2n[k]*dim+1];
1126 tk[1] = -nk[d2n[k]*dim];
1127 dshape.Mult(tk, grad_k);
1128 for (int j = 0; j < grad_k.Size(); j++)
1129 {
1130 grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j);
1131 }
1132 }
1133 }
1134
ProjectCurl_ND(const double * tk,const Array<int> & d2t,const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const1135 void VectorFiniteElement::ProjectCurl_ND(
1136 const double *tk, const Array<int> &d2t, const FiniteElement &fe,
1137 ElementTransformation &Trans, DenseMatrix &curl) const
1138 {
1139 #ifdef MFEM_THREAD_SAFE
1140 DenseMatrix curlshape(fe.GetDof(), dim);
1141 DenseMatrix curlshape_J(fe.GetDof(), dim);
1142 DenseMatrix J(dim, dim);
1143 #else
1144 curlshape.SetSize(fe.GetDof(), dim);
1145 curlshape_J.SetSize(fe.GetDof(), dim);
1146 J.SetSize(dim, dim);
1147 #endif
1148
1149 Vector curl_k(fe.GetDof());
1150
1151 curl.SetSize(dof, fe.GetDof());
1152 for (int k = 0; k < dof; k++)
1153 {
1154 const IntegrationPoint &ip = Nodes.IntPoint(k);
1155
1156 // calculate J^t * J / |J|
1157 Trans.SetIntPoint(&ip);
1158 MultAtB(Trans.Jacobian(), Trans.Jacobian(), J);
1159 J *= 1.0 / Trans.Weight();
1160
1161 // transform curl of shapes (rows) by J^t * J / |J|
1162 fe.CalcCurlShape(ip, curlshape);
1163 Mult(curlshape, J, curlshape_J);
1164
1165 curlshape_J.Mult(tk + d2t[k]*dim, curl_k);
1166 for (int j = 0; j < curl_k.Size(); j++)
1167 {
1168 curl(k,j) = (fabs(curl_k(j)) < 1e-12) ? 0.0 : curl_k(j);
1169 }
1170 }
1171 }
1172
ProjectCurl_RT(const double * nk,const Array<int> & d2n,const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const1173 void VectorFiniteElement::ProjectCurl_RT(
1174 const double *nk, const Array<int> &d2n, const FiniteElement &fe,
1175 ElementTransformation &Trans, DenseMatrix &curl) const
1176 {
1177 DenseMatrix curl_shape(fe.GetDof(), dim);
1178 Vector curl_k(fe.GetDof());
1179
1180 curl.SetSize(dof, fe.GetDof());
1181 for (int k = 0; k < dof; k++)
1182 {
1183 fe.CalcCurlShape(Nodes.IntPoint(k), curl_shape);
1184 curl_shape.Mult(nk + d2n[k]*dim, curl_k);
1185 for (int j = 0; j < curl_k.Size(); j++)
1186 {
1187 curl(k,j) = (fabs(curl_k(j)) < 1e-12) ? 0.0 : curl_k(j);
1188 }
1189 }
1190 }
1191
Project_ND(const double * tk,const Array<int> & d2t,VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const1192 void VectorFiniteElement::Project_ND(
1193 const double *tk, const Array<int> &d2t,
1194 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
1195 {
1196 double vk[Geometry::MaxDim];
1197 Vector xk(vk, vc.GetVDim());
1198
1199 for (int k = 0; k < dof; k++)
1200 {
1201 Trans.SetIntPoint(&Nodes.IntPoint(k));
1202
1203 vc.Eval(xk, Trans, Nodes.IntPoint(k));
1204 // dof_k = xk^t J tk
1205 dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*dim, vk);
1206 }
1207 }
1208
Project_ND(const double * tk,const Array<int> & d2t,Vector & vc,ElementTransformation & Trans,Vector & dofs) const1209 void VectorFiniteElement::Project_ND(
1210 const double *tk, const Array<int> &d2t,
1211 Vector &vc, ElementTransformation &Trans, Vector &dofs) const
1212 {
1213 for (int k = 0; k < dof; k++)
1214 {
1215 Trans.SetIntPoint(&Nodes.IntPoint(k));
1216 Vector vk(vc.GetData()+k*dim, dim);
1217 // dof_k = xk^t J tk
1218 dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*dim, vk);
1219 }
1220 }
1221
ProjectMatrixCoefficient_ND(const double * tk,const Array<int> & d2t,MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const1222 void VectorFiniteElement::ProjectMatrixCoefficient_ND(
1223 const double *tk, const Array<int> &d2t,
1224 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
1225 {
1226 // project the rows of the matrix coefficient in an ND space
1227
1228 const int sdim = T.GetSpaceDim();
1229 MFEM_ASSERT(mc.GetWidth() == sdim, "");
1230 DenseMatrix MQ(mc.GetHeight(), mc.GetWidth());
1231 Vector tk_phys(sdim), dofs_k(MQ.Height());
1232 MFEM_ASSERT(dofs.Size() == dof*MQ.Height(), "");
1233
1234 for (int k = 0; k < dof; k++)
1235 {
1236 T.SetIntPoint(&Nodes.IntPoint(k));
1237 mc.Eval(MQ, T, Nodes.IntPoint(k));
1238 // tk_phys = J tk
1239 T.Jacobian().Mult(tk + d2t[k]*dim, tk_phys);
1240 MQ.Mult(tk_phys, dofs_k);
1241 for (int r = 0; r < MQ.Height(); r++)
1242 {
1243 dofs(k+dof*r) = dofs_k(r);
1244 }
1245 }
1246 }
1247
Project_ND(const double * tk,const Array<int> & d2t,const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const1248 void VectorFiniteElement::Project_ND(
1249 const double *tk, const Array<int> &d2t, const FiniteElement &fe,
1250 ElementTransformation &Trans, DenseMatrix &I) const
1251 {
1252 if (fe.GetRangeType() == SCALAR)
1253 {
1254 int sdim = Trans.GetSpaceDim();
1255 double vk[Geometry::MaxDim];
1256 Vector shape(fe.GetDof());
1257
1258 I.SetSize(dof, sdim*fe.GetDof());
1259 for (int k = 0; k < dof; k++)
1260 {
1261 const IntegrationPoint &ip = Nodes.IntPoint(k);
1262
1263 fe.CalcShape(ip, shape);
1264 Trans.SetIntPoint(&ip);
1265 // Transform ND edge tengents from reference to physical space
1266 // vk = J tk
1267 Trans.Jacobian().Mult(tk + d2t[k]*dim, vk);
1268 if (fe.GetMapType() == INTEGRAL)
1269 {
1270 double w = 1.0/Trans.Weight();
1271 for (int d = 0; d < sdim; d++)
1272 {
1273 vk[d] *= w;
1274 }
1275 }
1276
1277 for (int j = 0; j < shape.Size(); j++)
1278 {
1279 double s = shape(j);
1280 if (fabs(s) < 1e-12)
1281 {
1282 s = 0.0;
1283 }
1284 // Project scalar basis function multiplied by each coordinate
1285 // direction onto the transformed edge tangents
1286 for (int d = 0; d < sdim; d++)
1287 {
1288 I(k, j + d*shape.Size()) = s*vk[d];
1289 }
1290 }
1291 }
1292 }
1293 else
1294 {
1295 int sdim = Trans.GetSpaceDim();
1296 double vk[Geometry::MaxDim];
1297 DenseMatrix vshape(fe.GetDof(), sdim);
1298 Vector vshapetk(fe.GetDof());
1299
1300 I.SetSize(dof, fe.GetDof());
1301 for (int k = 0; k < dof; k++)
1302 {
1303 const IntegrationPoint &ip = Nodes.IntPoint(k);
1304
1305 Trans.SetIntPoint(&ip);
1306 // Transform ND edge tangents from reference to physical space
1307 // vk = J tk
1308 Trans.Jacobian().Mult(tk + d2t[k]*dim, vk);
1309 // Compute fe basis functions in physical space
1310 fe.CalcVShape(Trans, vshape);
1311 // Project fe basis functions onto transformed edge tangents
1312 vshape.Mult(vk, vshapetk);
1313 for (int j=0; j<vshapetk.Size(); j++)
1314 {
1315 I(k, j) = vshapetk(j);
1316 }
1317 }
1318 }
1319 }
1320
ProjectGrad_ND(const double * tk,const Array<int> & d2t,const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const1321 void VectorFiniteElement::ProjectGrad_ND(
1322 const double *tk, const Array<int> &d2t, const FiniteElement &fe,
1323 ElementTransformation &Trans, DenseMatrix &grad) const
1324 {
1325 MFEM_ASSERT(fe.GetMapType() == VALUE, "");
1326
1327 DenseMatrix dshape(fe.GetDof(), fe.GetDim());
1328 Vector grad_k(fe.GetDof());
1329
1330 grad.SetSize(dof, fe.GetDof());
1331 for (int k = 0; k < dof; k++)
1332 {
1333 fe.CalcDShape(Nodes.IntPoint(k), dshape);
1334 dshape.Mult(tk + d2t[k]*dim, grad_k);
1335 for (int j = 0; j < grad_k.Size(); j++)
1336 {
1337 grad(k,j) = (fabs(grad_k(j)) < 1e-12) ? 0.0 : grad_k(j);
1338 }
1339 }
1340 }
1341
LocalL2Projection_RT(const VectorFiniteElement & cfe,ElementTransformation & Trans,DenseMatrix & I) const1342 void VectorFiniteElement::LocalL2Projection_RT(
1343 const VectorFiniteElement &cfe, ElementTransformation &Trans,
1344 DenseMatrix &I) const
1345 {
1346 Vector v(dim);
1347 IntegrationPoint tr_ip;
1348
1349 const int fs = dof, cs = cfe.GetDof();
1350 I.SetSize(fs, cs);
1351 DenseMatrix fine_shape(fs, dim), coarse_shape(cs, cfe.GetDim());
1352 DenseMatrix fine_mass(fs), fine_coarse_mass(fs, cs); // initialized with 0
1353 const int ir_order =
1354 std::max(GetOrder(), this->GetOrder()) + this->GetOrder();
1355 const IntegrationRule &ir = IntRules.Get(this->GetGeomType(), ir_order);
1356
1357 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
1358 const DenseMatrix &adjJ = Trans.AdjugateJacobian();
1359 for (int i = 0; i < ir.GetNPoints(); i++)
1360 {
1361 const IntegrationPoint &ip = ir.IntPoint(i);
1362 double w = ip.weight;
1363 this->CalcVShape(ip, fine_shape);
1364 Trans.Transform(ip, v);
1365 tr_ip.Set(v, dim);
1366 cfe.CalcVShape(tr_ip, coarse_shape);
1367
1368 AddMult_a_AAt(w, fine_shape, fine_mass);
1369 for (int k=0; k<fs; ++k)
1370 {
1371 for (int j=0; j<cs; ++j)
1372 {
1373 double Mkj = 0.0;
1374 for (int d1=0; d1<dim; ++d1)
1375 {
1376 for (int d2=0; d2<dim; ++d2)
1377 {
1378 Mkj += w*fine_shape(k,d1)*adjJ(d2,d1)*coarse_shape(j,d2);
1379 }
1380 }
1381 fine_coarse_mass(k,j) += (fabs(Mkj) < 1e-12) ? 0.0 : Mkj;
1382 }
1383 }
1384 }
1385 DenseMatrixInverse fine_mass_inv(fine_mass);
1386 fine_mass_inv.Mult(fine_coarse_mass, I);
1387 }
1388
LocalInterpolation_RT(const VectorFiniteElement & cfe,const double * nk,const Array<int> & d2n,ElementTransformation & Trans,DenseMatrix & I) const1389 void VectorFiniteElement::LocalInterpolation_RT(
1390 const VectorFiniteElement &cfe, const double *nk, const Array<int> &d2n,
1391 ElementTransformation &Trans, DenseMatrix &I) const
1392 {
1393 MFEM_ASSERT(map_type == cfe.GetMapType(), "");
1394
1395 if (!is_nodal) { return LocalL2Projection_RT(cfe, Trans, I); }
1396
1397 double vk[Geometry::MaxDim];
1398 Vector xk(vk, dim);
1399 IntegrationPoint ip;
1400 #ifdef MFEM_THREAD_SAFE
1401 DenseMatrix vshape(cfe.GetDof(), cfe.GetDim());
1402 #else
1403 DenseMatrix vshape(cfe.vshape.Data(), cfe.GetDof(), cfe.GetDim());
1404 #endif
1405 I.SetSize(dof, vshape.Height());
1406
1407 // assuming Trans is linear; this should be ok for all refinement types
1408 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
1409 const DenseMatrix &adjJ = Trans.AdjugateJacobian();
1410 for (int k = 0; k < dof; k++)
1411 {
1412 Trans.Transform(Nodes.IntPoint(k), xk);
1413 ip.Set3(vk);
1414 cfe.CalcVShape(ip, vshape);
1415 // xk = |J| J^{-t} n_k
1416 adjJ.MultTranspose(nk + d2n[k]*dim, vk);
1417 // I_k = vshape_k.adj(J)^t.n_k, k=1,...,dof
1418 for (int j = 0; j < vshape.Height(); j++)
1419 {
1420 double Ikj = 0.;
1421 for (int i = 0; i < dim; i++)
1422 {
1423 Ikj += vshape(j, i) * vk[i];
1424 }
1425 I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj;
1426 }
1427 }
1428 }
1429
LocalL2Projection_ND(const VectorFiniteElement & cfe,ElementTransformation & Trans,DenseMatrix & I) const1430 void VectorFiniteElement::LocalL2Projection_ND(
1431 const VectorFiniteElement &cfe,
1432 ElementTransformation &Trans, DenseMatrix &I) const
1433 {
1434 Vector v(dim);
1435 IntegrationPoint tr_ip;
1436
1437 const int fs = dof, cs = cfe.GetDof();
1438 I.SetSize(fs, cs);
1439 DenseMatrix fine_shape(fs, dim), coarse_shape(cs, cfe.GetDim());
1440 DenseMatrix fine_mass(fs), fine_coarse_mass(fs, cs); // initialized with 0
1441 const int ir_order =
1442 std::max(GetOrder(), this->GetOrder()) + this->GetOrder();
1443 const IntegrationRule &ir = IntRules.Get(this->GetGeomType(), ir_order);
1444
1445 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
1446 const DenseMatrix &J = Trans.Jacobian();
1447 for (int i = 0; i < ir.GetNPoints(); i++)
1448 {
1449 const IntegrationPoint &ip = ir.IntPoint(i);
1450 this->CalcVShape(ip, fine_shape);
1451 Trans.Transform(ip, v);
1452 tr_ip.Set(v, dim);
1453 cfe.CalcVShape(tr_ip, coarse_shape);
1454
1455 AddMult_a_AAt(ip.weight, fine_shape, fine_mass);
1456 for (int k=0; k<fs; ++k)
1457 {
1458 for (int j=0; j<cs; ++j)
1459 {
1460 double Mkj = 0.0;
1461 for (int d1=0; d1<dim; ++d1)
1462 {
1463 for (int d2=0; d2<dim; ++d2)
1464 {
1465 Mkj += ip.weight*fine_shape(k,d1)*J(d1,d2)*coarse_shape(j,d2);
1466 }
1467 }
1468 fine_coarse_mass(k,j) += (fabs(Mkj) < 1e-12) ? 0.0 : Mkj;
1469 }
1470 }
1471 }
1472 DenseMatrixInverse fine_mass_inv(fine_mass);
1473 fine_mass_inv.Mult(fine_coarse_mass, I);
1474 }
1475
LocalInterpolation_ND(const VectorFiniteElement & cfe,const double * tk,const Array<int> & d2t,ElementTransformation & Trans,DenseMatrix & I) const1476 void VectorFiniteElement::LocalInterpolation_ND(
1477 const VectorFiniteElement &cfe, const double *tk, const Array<int> &d2t,
1478 ElementTransformation &Trans, DenseMatrix &I) const
1479 {
1480 if (!is_nodal) { return LocalL2Projection_ND(cfe, Trans, I); }
1481
1482 double vk[Geometry::MaxDim];
1483 Vector xk(vk, dim);
1484 IntegrationPoint ip;
1485 #ifdef MFEM_THREAD_SAFE
1486 DenseMatrix vshape(cfe.GetDof(), cfe.GetDim());
1487 #else
1488 DenseMatrix vshape(cfe.vshape.Data(), cfe.GetDof(), cfe.GetDim());
1489 #endif
1490 I.SetSize(dof, vshape.Height());
1491
1492 // assuming Trans is linear; this should be ok for all refinement types
1493 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
1494 const DenseMatrix &J = Trans.Jacobian();
1495 for (int k = 0; k < dof; k++)
1496 {
1497 Trans.Transform(Nodes.IntPoint(k), xk);
1498 ip.Set3(vk);
1499 cfe.CalcVShape(ip, vshape);
1500 // xk = J t_k
1501 J.Mult(tk + d2t[k]*dim, vk);
1502 // I_k = vshape_k.J.t_k, k=1,...,Dof
1503 for (int j = 0; j < vshape.Height(); j++)
1504 {
1505 double Ikj = 0.;
1506 for (int i = 0; i < dim; i++)
1507 {
1508 Ikj += vshape(j, i) * vk[i];
1509 }
1510 I(k, j) = (fabs(Ikj) < 1e-12) ? 0.0 : Ikj;
1511 }
1512 }
1513 }
1514
LocalRestriction_RT(const double * nk,const Array<int> & d2n,ElementTransformation & Trans,DenseMatrix & R) const1515 void VectorFiniteElement::LocalRestriction_RT(
1516 const double *nk, const Array<int> &d2n, ElementTransformation &Trans,
1517 DenseMatrix &R) const
1518 {
1519 double pt_data[Geometry::MaxDim];
1520 IntegrationPoint ip;
1521 Vector pt(pt_data, dim);
1522
1523 #ifdef MFEM_THREAD_SAFE
1524 DenseMatrix vshape(dof, dim);
1525 #endif
1526
1527 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
1528 const DenseMatrix &J = Trans.Jacobian();
1529 const double weight = Trans.Weight();
1530 for (int j = 0; j < dof; j++)
1531 {
1532 InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
1533 ip.Set(pt_data, dim);
1534 if (Geometries.CheckPoint(geom_type, ip)) // do we need an epsilon here?
1535 {
1536 CalcVShape(ip, vshape);
1537 J.MultTranspose(nk+dim*d2n[j], pt_data);
1538 pt /= weight;
1539 for (int k = 0; k < dof; k++)
1540 {
1541 double R_jk = 0.0;
1542 for (int d = 0; d < dim; d++)
1543 {
1544 R_jk += vshape(k,d)*pt_data[d];
1545 }
1546 R(j,k) = R_jk;
1547 }
1548 }
1549 else
1550 {
1551 // Set the whole row to avoid valgrind warnings in R.Threshold().
1552 R.SetRow(j, infinity());
1553 }
1554 }
1555 R.Threshold(1e-12);
1556 }
1557
LocalRestriction_ND(const double * tk,const Array<int> & d2t,ElementTransformation & Trans,DenseMatrix & R) const1558 void VectorFiniteElement::LocalRestriction_ND(
1559 const double *tk, const Array<int> &d2t, ElementTransformation &Trans,
1560 DenseMatrix &R) const
1561 {
1562 double pt_data[Geometry::MaxDim];
1563 IntegrationPoint ip;
1564 Vector pt(pt_data, dim);
1565
1566 #ifdef MFEM_THREAD_SAFE
1567 DenseMatrix vshape(dof, dim);
1568 #endif
1569
1570 Trans.SetIntPoint(&Geometries.GetCenter(geom_type));
1571 const DenseMatrix &Jinv = Trans.InverseJacobian();
1572 for (int j = 0; j < dof; j++)
1573 {
1574 InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
1575 ip.Set(pt_data, dim);
1576 if (Geometries.CheckPoint(geom_type, ip)) // do we need an epsilon here?
1577 {
1578 CalcVShape(ip, vshape);
1579 Jinv.Mult(tk+dim*d2t[j], pt_data);
1580 for (int k = 0; k < dof; k++)
1581 {
1582 double R_jk = 0.0;
1583 for (int d = 0; d < dim; d++)
1584 {
1585 R_jk += vshape(k,d)*pt_data[d];
1586 }
1587 R(j,k) = R_jk;
1588 }
1589 }
1590 else
1591 {
1592 // Set the whole row to avoid valgrind warnings in R.Threshold().
1593 R.SetRow(j, infinity());
1594 }
1595 }
1596 R.Threshold(1e-12);
1597 }
1598
1599
PointFiniteElement()1600 PointFiniteElement::PointFiniteElement()
1601 : NodalFiniteElement(0, Geometry::POINT, 1, 0)
1602 {
1603 lex_ordering.SetSize(1);
1604 lex_ordering[0] = 0;
1605 Nodes.IntPoint(0).x = 0.0;
1606 }
1607
CalcShape(const IntegrationPoint & ip,Vector & shape) const1608 void PointFiniteElement::CalcShape(const IntegrationPoint &ip,
1609 Vector &shape) const
1610 {
1611 shape(0) = 1.;
1612 }
1613
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1614 void PointFiniteElement::CalcDShape(const IntegrationPoint &ip,
1615 DenseMatrix &dshape) const
1616 {
1617 // dshape is (1 x 0) - nothing to compute
1618 }
1619
Linear1DFiniteElement()1620 Linear1DFiniteElement::Linear1DFiniteElement()
1621 : NodalFiniteElement(1, Geometry::SEGMENT, 2, 1)
1622 {
1623 Nodes.IntPoint(0).x = 0.0;
1624 Nodes.IntPoint(1).x = 1.0;
1625 }
1626
CalcShape(const IntegrationPoint & ip,Vector & shape) const1627 void Linear1DFiniteElement::CalcShape(const IntegrationPoint &ip,
1628 Vector &shape) const
1629 {
1630 shape(0) = 1. - ip.x;
1631 shape(1) = ip.x;
1632 }
1633
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1634 void Linear1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1635 DenseMatrix &dshape) const
1636 {
1637 dshape(0,0) = -1.;
1638 dshape(1,0) = 1.;
1639 }
1640
Linear2DFiniteElement()1641 Linear2DFiniteElement::Linear2DFiniteElement()
1642 : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1)
1643 {
1644 Nodes.IntPoint(0).x = 0.0;
1645 Nodes.IntPoint(0).y = 0.0;
1646 Nodes.IntPoint(1).x = 1.0;
1647 Nodes.IntPoint(1).y = 0.0;
1648 Nodes.IntPoint(2).x = 0.0;
1649 Nodes.IntPoint(2).y = 1.0;
1650 }
1651
CalcShape(const IntegrationPoint & ip,Vector & shape) const1652 void Linear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
1653 Vector &shape) const
1654 {
1655 shape(0) = 1. - ip.x - ip.y;
1656 shape(1) = ip.x;
1657 shape(2) = ip.y;
1658 }
1659
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1660 void Linear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1661 DenseMatrix &dshape) const
1662 {
1663 dshape(0,0) = -1.; dshape(0,1) = -1.;
1664 dshape(1,0) = 1.; dshape(1,1) = 0.;
1665 dshape(2,0) = 0.; dshape(2,1) = 1.;
1666 }
1667
BiLinear2DFiniteElement()1668 BiLinear2DFiniteElement::BiLinear2DFiniteElement()
1669 : NodalFiniteElement(2, Geometry::SQUARE, 4, 1, FunctionSpace::Qk)
1670 {
1671 Nodes.IntPoint(0).x = 0.0;
1672 Nodes.IntPoint(0).y = 0.0;
1673 Nodes.IntPoint(1).x = 1.0;
1674 Nodes.IntPoint(1).y = 0.0;
1675 Nodes.IntPoint(2).x = 1.0;
1676 Nodes.IntPoint(2).y = 1.0;
1677 Nodes.IntPoint(3).x = 0.0;
1678 Nodes.IntPoint(3).y = 1.0;
1679 }
1680
CalcShape(const IntegrationPoint & ip,Vector & shape) const1681 void BiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
1682 Vector &shape) const
1683 {
1684 shape(0) = (1. - ip.x) * (1. - ip.y) ;
1685 shape(1) = ip.x * (1. - ip.y) ;
1686 shape(2) = ip.x * ip.y ;
1687 shape(3) = (1. - ip.x) * ip.y ;
1688 }
1689
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1690 void BiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1691 DenseMatrix &dshape) const
1692 {
1693 dshape(0,0) = -1. + ip.y; dshape(0,1) = -1. + ip.x ;
1694 dshape(1,0) = 1. - ip.y; dshape(1,1) = -ip.x ;
1695 dshape(2,0) = ip.y ; dshape(2,1) = ip.x ;
1696 dshape(3,0) = -ip.y ; dshape(3,1) = 1. - ip.x ;
1697 }
1698
CalcHessian(const IntegrationPoint & ip,DenseMatrix & h) const1699 void BiLinear2DFiniteElement::CalcHessian(
1700 const IntegrationPoint &ip, DenseMatrix &h) const
1701 {
1702 h(0,0) = 0.; h(0,1) = 1.; h(0,2) = 0.;
1703 h(1,0) = 0.; h(1,1) = -1.; h(1,2) = 0.;
1704 h(2,0) = 0.; h(2,1) = 1.; h(2,2) = 0.;
1705 h(3,0) = 0.; h(3,1) = -1.; h(3,2) = 0.;
1706 }
1707
1708
GaussLinear2DFiniteElement()1709 GaussLinear2DFiniteElement::GaussLinear2DFiniteElement()
1710 : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1, FunctionSpace::Pk)
1711 {
1712 Nodes.IntPoint(0).x = 1./6.;
1713 Nodes.IntPoint(0).y = 1./6.;
1714 Nodes.IntPoint(1).x = 2./3.;
1715 Nodes.IntPoint(1).y = 1./6.;
1716 Nodes.IntPoint(2).x = 1./6.;
1717 Nodes.IntPoint(2).y = 2./3.;
1718 }
1719
CalcShape(const IntegrationPoint & ip,Vector & shape) const1720 void GaussLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
1721 Vector &shape) const
1722 {
1723 const double x = ip.x, y = ip.y;
1724
1725 shape(0) = 5./3. - 2. * (x + y);
1726 shape(1) = 2. * (x - 1./6.);
1727 shape(2) = 2. * (y - 1./6.);
1728 }
1729
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1730 void GaussLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1731 DenseMatrix &dshape) const
1732 {
1733 dshape(0,0) = -2.; dshape(0,1) = -2.;
1734 dshape(1,0) = 2.; dshape(1,1) = 0.;
1735 dshape(2,0) = 0.; dshape(2,1) = 2.;
1736 }
1737
ProjectDelta(int vertex,Vector & dofs) const1738 void GaussLinear2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
1739 {
1740 dofs(vertex) = 2./3.;
1741 dofs((vertex+1)%3) = 1./6.;
1742 dofs((vertex+2)%3) = 1./6.;
1743 }
1744
1745
1746 // 0.5-0.5/sqrt(3) and 0.5+0.5/sqrt(3)
1747 const double GaussBiLinear2DFiniteElement::p[] =
1748 { 0.2113248654051871177454256, 0.7886751345948128822545744 };
1749
GaussBiLinear2DFiniteElement()1750 GaussBiLinear2DFiniteElement::GaussBiLinear2DFiniteElement()
1751 : NodalFiniteElement(2, Geometry::SQUARE, 4, 1, FunctionSpace::Qk)
1752 {
1753 Nodes.IntPoint(0).x = p[0];
1754 Nodes.IntPoint(0).y = p[0];
1755 Nodes.IntPoint(1).x = p[1];
1756 Nodes.IntPoint(1).y = p[0];
1757 Nodes.IntPoint(2).x = p[1];
1758 Nodes.IntPoint(2).y = p[1];
1759 Nodes.IntPoint(3).x = p[0];
1760 Nodes.IntPoint(3).y = p[1];
1761 }
1762
CalcShape(const IntegrationPoint & ip,Vector & shape) const1763 void GaussBiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
1764 Vector &shape) const
1765 {
1766 const double x = ip.x, y = ip.y;
1767
1768 shape(0) = 3. * (p[1] - x) * (p[1] - y);
1769 shape(1) = 3. * (x - p[0]) * (p[1] - y);
1770 shape(2) = 3. * (x - p[0]) * (y - p[0]);
1771 shape(3) = 3. * (p[1] - x) * (y - p[0]);
1772 }
1773
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1774 void GaussBiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1775 DenseMatrix &dshape) const
1776 {
1777 const double x = ip.x, y = ip.y;
1778
1779 dshape(0,0) = 3. * (y - p[1]); dshape(0,1) = 3. * (x - p[1]);
1780 dshape(1,0) = 3. * (p[1] - y); dshape(1,1) = 3. * (p[0] - x);
1781 dshape(2,0) = 3. * (y - p[0]); dshape(2,1) = 3. * (x - p[0]);
1782 dshape(3,0) = 3. * (p[0] - y); dshape(3,1) = 3. * (p[1] - x);
1783 }
1784
ProjectDelta(int vertex,Vector & dofs) const1785 void GaussBiLinear2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
1786 {
1787 #if 1
1788 dofs(vertex) = p[1]*p[1];
1789 dofs((vertex+1)%4) = p[0]*p[1];
1790 dofs((vertex+2)%4) = p[0]*p[0];
1791 dofs((vertex+3)%4) = p[0]*p[1];
1792 #else
1793 dofs = 1.0;
1794 #endif
1795 }
1796
1797
P1OnQuadFiniteElement()1798 P1OnQuadFiniteElement::P1OnQuadFiniteElement()
1799 : NodalFiniteElement(2, Geometry::SQUARE, 3, 1, FunctionSpace::Qk)
1800 {
1801 Nodes.IntPoint(0).x = 0.0;
1802 Nodes.IntPoint(0).y = 0.0;
1803 Nodes.IntPoint(1).x = 1.0;
1804 Nodes.IntPoint(1).y = 0.0;
1805 Nodes.IntPoint(2).x = 0.0;
1806 Nodes.IntPoint(2).y = 1.0;
1807 }
1808
CalcShape(const IntegrationPoint & ip,Vector & shape) const1809 void P1OnQuadFiniteElement::CalcShape(const IntegrationPoint &ip,
1810 Vector &shape) const
1811 {
1812 shape(0) = 1. - ip.x - ip.y;
1813 shape(1) = ip.x;
1814 shape(2) = ip.y;
1815 }
1816
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1817 void P1OnQuadFiniteElement::CalcDShape(const IntegrationPoint &ip,
1818 DenseMatrix &dshape) const
1819 {
1820 dshape(0,0) = -1.; dshape(0,1) = -1.;
1821 dshape(1,0) = 1.; dshape(1,1) = 0.;
1822 dshape(2,0) = 0.; dshape(2,1) = 1.;
1823 }
1824
1825
Quad1DFiniteElement()1826 Quad1DFiniteElement::Quad1DFiniteElement()
1827 : NodalFiniteElement(1, Geometry::SEGMENT, 3, 2)
1828 {
1829 Nodes.IntPoint(0).x = 0.0;
1830 Nodes.IntPoint(1).x = 1.0;
1831 Nodes.IntPoint(2).x = 0.5;
1832 }
1833
CalcShape(const IntegrationPoint & ip,Vector & shape) const1834 void Quad1DFiniteElement::CalcShape(const IntegrationPoint &ip,
1835 Vector &shape) const
1836 {
1837 double x = ip.x;
1838 double l1 = 1.0 - x, l2 = x, l3 = 2. * x - 1.;
1839
1840 shape(0) = l1 * (-l3);
1841 shape(1) = l2 * l3;
1842 shape(2) = 4. * l1 * l2;
1843 }
1844
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1845 void Quad1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1846 DenseMatrix &dshape) const
1847 {
1848 double x = ip.x;
1849
1850 dshape(0,0) = 4. * x - 3.;
1851 dshape(1,0) = 4. * x - 1.;
1852 dshape(2,0) = 4. - 8. * x;
1853 }
1854
1855
QuadPos1DFiniteElement()1856 QuadPos1DFiniteElement::QuadPos1DFiniteElement()
1857 : PositiveFiniteElement(1, Geometry::SEGMENT, 3, 2)
1858 {
1859 Nodes.IntPoint(0).x = 0.0;
1860 Nodes.IntPoint(1).x = 1.0;
1861 Nodes.IntPoint(2).x = 0.5;
1862 }
1863
CalcShape(const IntegrationPoint & ip,Vector & shape) const1864 void QuadPos1DFiniteElement::CalcShape(const IntegrationPoint &ip,
1865 Vector &shape) const
1866 {
1867 const double x = ip.x, x1 = 1. - x;
1868
1869 shape(0) = x1 * x1;
1870 shape(1) = x * x;
1871 shape(2) = 2. * x * x1;
1872 }
1873
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1874 void QuadPos1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1875 DenseMatrix &dshape) const
1876 {
1877 const double x = ip.x;
1878
1879 dshape(0,0) = 2. * x - 2.;
1880 dshape(1,0) = 2. * x;
1881 dshape(2,0) = 2. - 4. * x;
1882 }
1883
Quad2DFiniteElement()1884 Quad2DFiniteElement::Quad2DFiniteElement()
1885 : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 2)
1886 {
1887 Nodes.IntPoint(0).x = 0.0;
1888 Nodes.IntPoint(0).y = 0.0;
1889 Nodes.IntPoint(1).x = 1.0;
1890 Nodes.IntPoint(1).y = 0.0;
1891 Nodes.IntPoint(2).x = 0.0;
1892 Nodes.IntPoint(2).y = 1.0;
1893 Nodes.IntPoint(3).x = 0.5;
1894 Nodes.IntPoint(3).y = 0.0;
1895 Nodes.IntPoint(4).x = 0.5;
1896 Nodes.IntPoint(4).y = 0.5;
1897 Nodes.IntPoint(5).x = 0.0;
1898 Nodes.IntPoint(5).y = 0.5;
1899 }
1900
CalcShape(const IntegrationPoint & ip,Vector & shape) const1901 void Quad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
1902 Vector &shape) const
1903 {
1904 double x = ip.x, y = ip.y;
1905 double l1 = 1.-x-y, l2 = x, l3 = y;
1906
1907 shape(0) = l1 * (2. * l1 - 1.);
1908 shape(1) = l2 * (2. * l2 - 1.);
1909 shape(2) = l3 * (2. * l3 - 1.);
1910 shape(3) = 4. * l1 * l2;
1911 shape(4) = 4. * l2 * l3;
1912 shape(5) = 4. * l3 * l1;
1913 }
1914
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const1915 void Quad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
1916 DenseMatrix &dshape) const
1917 {
1918 double x = ip.x, y = ip.y;
1919
1920 dshape(0,0) =
1921 dshape(0,1) = 4. * (x + y) - 3.;
1922
1923 dshape(1,0) = 4. * x - 1.;
1924 dshape(1,1) = 0.;
1925
1926 dshape(2,0) = 0.;
1927 dshape(2,1) = 4. * y - 1.;
1928
1929 dshape(3,0) = -4. * (2. * x + y - 1.);
1930 dshape(3,1) = -4. * x;
1931
1932 dshape(4,0) = 4. * y;
1933 dshape(4,1) = 4. * x;
1934
1935 dshape(5,0) = -4. * y;
1936 dshape(5,1) = -4. * (x + 2. * y - 1.);
1937 }
1938
CalcHessian(const IntegrationPoint & ip,DenseMatrix & h) const1939 void Quad2DFiniteElement::CalcHessian (const IntegrationPoint &ip,
1940 DenseMatrix &h) const
1941 {
1942 h(0,0) = 4.;
1943 h(0,1) = 4.;
1944 h(0,2) = 4.;
1945
1946 h(1,0) = 4.;
1947 h(1,1) = 0.;
1948 h(1,2) = 0.;
1949
1950 h(2,0) = 0.;
1951 h(2,1) = 0.;
1952 h(2,2) = 4.;
1953
1954 h(3,0) = -8.;
1955 h(3,1) = -4.;
1956 h(3,2) = 0.;
1957
1958 h(4,0) = 0.;
1959 h(4,1) = 4.;
1960 h(4,2) = 0.;
1961
1962 h(5,0) = 0.;
1963 h(5,1) = -4.;
1964 h(5,2) = -8.;
1965 }
1966
ProjectDelta(int vertex,Vector & dofs) const1967 void Quad2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
1968 {
1969 #if 0
1970 dofs = 1.;
1971 #else
1972 dofs = 0.;
1973 dofs(vertex) = 1.;
1974 switch (vertex)
1975 {
1976 case 0: dofs(3) = 0.25; dofs(5) = 0.25; break;
1977 case 1: dofs(3) = 0.25; dofs(4) = 0.25; break;
1978 case 2: dofs(4) = 0.25; dofs(5) = 0.25; break;
1979 }
1980 #endif
1981 }
1982
1983
1984 const double GaussQuad2DFiniteElement::p[] =
1985 { 0.0915762135097707434595714634022015, 0.445948490915964886318329253883051 };
1986
GaussQuad2DFiniteElement()1987 GaussQuad2DFiniteElement::GaussQuad2DFiniteElement()
1988 : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 2), A(6), D(6,2), pol(6)
1989 {
1990 Nodes.IntPoint(0).x = p[0];
1991 Nodes.IntPoint(0).y = p[0];
1992 Nodes.IntPoint(1).x = 1. - 2. * p[0];
1993 Nodes.IntPoint(1).y = p[0];
1994 Nodes.IntPoint(2).x = p[0];
1995 Nodes.IntPoint(2).y = 1. - 2. * p[0];
1996 Nodes.IntPoint(3).x = p[1];
1997 Nodes.IntPoint(3).y = p[1];
1998 Nodes.IntPoint(4).x = 1. - 2. * p[1];
1999 Nodes.IntPoint(4).y = p[1];
2000 Nodes.IntPoint(5).x = p[1];
2001 Nodes.IntPoint(5).y = 1. - 2. * p[1];
2002
2003 for (int i = 0; i < 6; i++)
2004 {
2005 const double x = Nodes.IntPoint(i).x, y = Nodes.IntPoint(i).y;
2006 A(0,i) = 1.;
2007 A(1,i) = x;
2008 A(2,i) = y;
2009 A(3,i) = x * x;
2010 A(4,i) = x * y;
2011 A(5,i) = y * y;
2012 }
2013
2014 A.Invert();
2015 }
2016
CalcShape(const IntegrationPoint & ip,Vector & shape) const2017 void GaussQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
2018 Vector &shape) const
2019 {
2020 const double x = ip.x, y = ip.y;
2021 pol(0) = 1.;
2022 pol(1) = x;
2023 pol(2) = y;
2024 pol(3) = x * x;
2025 pol(4) = x * y;
2026 pol(5) = y * y;
2027
2028 A.Mult(pol, shape);
2029 }
2030
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2031 void GaussQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
2032 DenseMatrix &dshape) const
2033 {
2034 const double x = ip.x, y = ip.y;
2035 D(0,0) = 0.; D(0,1) = 0.;
2036 D(1,0) = 1.; D(1,1) = 0.;
2037 D(2,0) = 0.; D(2,1) = 1.;
2038 D(3,0) = 2. * x; D(3,1) = 0.;
2039 D(4,0) = y; D(4,1) = x;
2040 D(5,0) = 0.; D(5,1) = 2. * y;
2041
2042 Mult(A, D, dshape);
2043 }
2044
2045
BiQuad2DFiniteElement()2046 BiQuad2DFiniteElement::BiQuad2DFiniteElement()
2047 : NodalFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
2048 {
2049 Nodes.IntPoint(0).x = 0.0;
2050 Nodes.IntPoint(0).y = 0.0;
2051 Nodes.IntPoint(1).x = 1.0;
2052 Nodes.IntPoint(1).y = 0.0;
2053 Nodes.IntPoint(2).x = 1.0;
2054 Nodes.IntPoint(2).y = 1.0;
2055 Nodes.IntPoint(3).x = 0.0;
2056 Nodes.IntPoint(3).y = 1.0;
2057 Nodes.IntPoint(4).x = 0.5;
2058 Nodes.IntPoint(4).y = 0.0;
2059 Nodes.IntPoint(5).x = 1.0;
2060 Nodes.IntPoint(5).y = 0.5;
2061 Nodes.IntPoint(6).x = 0.5;
2062 Nodes.IntPoint(6).y = 1.0;
2063 Nodes.IntPoint(7).x = 0.0;
2064 Nodes.IntPoint(7).y = 0.5;
2065 Nodes.IntPoint(8).x = 0.5;
2066 Nodes.IntPoint(8).y = 0.5;
2067 }
2068
CalcShape(const IntegrationPoint & ip,Vector & shape) const2069 void BiQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
2070 Vector &shape) const
2071 {
2072 double x = ip.x, y = ip.y;
2073 double l1x, l2x, l3x, l1y, l2y, l3y;
2074
2075 l1x = (x - 1.) * (2. * x - 1);
2076 l2x = 4. * x * (1. - x);
2077 l3x = x * (2. * x - 1.);
2078 l1y = (y - 1.) * (2. * y - 1);
2079 l2y = 4. * y * (1. - y);
2080 l3y = y * (2. * y - 1.);
2081
2082 shape(0) = l1x * l1y;
2083 shape(4) = l2x * l1y;
2084 shape(1) = l3x * l1y;
2085 shape(7) = l1x * l2y;
2086 shape(8) = l2x * l2y;
2087 shape(5) = l3x * l2y;
2088 shape(3) = l1x * l3y;
2089 shape(6) = l2x * l3y;
2090 shape(2) = l3x * l3y;
2091 }
2092
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2093 void BiQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
2094 DenseMatrix &dshape) const
2095 {
2096 double x = ip.x, y = ip.y;
2097 double l1x, l2x, l3x, l1y, l2y, l3y;
2098 double d1x, d2x, d3x, d1y, d2y, d3y;
2099
2100 l1x = (x - 1.) * (2. * x - 1);
2101 l2x = 4. * x * (1. - x);
2102 l3x = x * (2. * x - 1.);
2103 l1y = (y - 1.) * (2. * y - 1);
2104 l2y = 4. * y * (1. - y);
2105 l3y = y * (2. * y - 1.);
2106
2107 d1x = 4. * x - 3.;
2108 d2x = 4. - 8. * x;
2109 d3x = 4. * x - 1.;
2110 d1y = 4. * y - 3.;
2111 d2y = 4. - 8. * y;
2112 d3y = 4. * y - 1.;
2113
2114 dshape(0,0) = d1x * l1y;
2115 dshape(0,1) = l1x * d1y;
2116
2117 dshape(4,0) = d2x * l1y;
2118 dshape(4,1) = l2x * d1y;
2119
2120 dshape(1,0) = d3x * l1y;
2121 dshape(1,1) = l3x * d1y;
2122
2123 dshape(7,0) = d1x * l2y;
2124 dshape(7,1) = l1x * d2y;
2125
2126 dshape(8,0) = d2x * l2y;
2127 dshape(8,1) = l2x * d2y;
2128
2129 dshape(5,0) = d3x * l2y;
2130 dshape(5,1) = l3x * d2y;
2131
2132 dshape(3,0) = d1x * l3y;
2133 dshape(3,1) = l1x * d3y;
2134
2135 dshape(6,0) = d2x * l3y;
2136 dshape(6,1) = l2x * d3y;
2137
2138 dshape(2,0) = d3x * l3y;
2139 dshape(2,1) = l3x * d3y;
2140 }
2141
ProjectDelta(int vertex,Vector & dofs) const2142 void BiQuad2DFiniteElement::ProjectDelta(int vertex, Vector &dofs) const
2143 {
2144 #if 0
2145 dofs = 1.;
2146 #else
2147 dofs = 0.;
2148 dofs(vertex) = 1.;
2149 switch (vertex)
2150 {
2151 case 0: dofs(4) = 0.25; dofs(7) = 0.25; break;
2152 case 1: dofs(4) = 0.25; dofs(5) = 0.25; break;
2153 case 2: dofs(5) = 0.25; dofs(6) = 0.25; break;
2154 case 3: dofs(6) = 0.25; dofs(7) = 0.25; break;
2155 }
2156 dofs(8) = 1./16.;
2157 #endif
2158 }
2159
2160
H1Ser_QuadrilateralElement(const int p)2161 H1Ser_QuadrilateralElement::H1Ser_QuadrilateralElement(const int p)
2162 : ScalarFiniteElement(2, Geometry::SQUARE, (p*p + 3*p +6) / 2, p,
2163 FunctionSpace::Qk)
2164 {
2165 // Store the dof_map of the associated TensorBasisElement, which will be used
2166 // to create the serendipity dof map. Its size is larger than the size of
2167 // the serendipity element.
2168 TensorBasisElement tbeTemp =
2169 TensorBasisElement(2, p, BasisType::GaussLobatto,
2170 TensorBasisElement::DofMapType::Sr_DOF_MAP);
2171 const Array<int> tp_dof_map = tbeTemp.GetDofMap();
2172
2173 const double *cp = poly1d.ClosedPoints(p, BasisType::GaussLobatto);
2174
2175 // Fixing the Nodes is exactly the same as the H1_QuadrilateralElement
2176 // constructor except we only use those values of the associated tensor
2177 // product dof_map that are <= the number of serendipity Dofs e.g. only DoFs
2178 // 0-7 out of the 9 tensor product dofs (at quadratic order)
2179 int o = 0;
2180
2181 for (int j = 0; j <= p; j++)
2182 {
2183 for (int i = 0; i <= p; i++)
2184 {
2185 if (tp_dof_map[o] < Nodes.Size())
2186 {
2187 Nodes.IntPoint(tp_dof_map[o]).x = cp[i];
2188 Nodes.IntPoint(tp_dof_map[o]).y = cp[j];
2189 }
2190 o++;
2191 }
2192 }
2193 }
2194
CalcShape(const IntegrationPoint & ip,Vector & shape) const2195 void H1Ser_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
2196 Vector &shape) const
2197 {
2198 int p = (this)->GetOrder();
2199 double x = ip.x, y = ip.y;
2200
2201 Poly_1D::Basis edgeNodalBasis(poly1d.GetBasis(p, BasisType::GaussLobatto));
2202 Vector nodalX(p+1);
2203 Vector nodalY(p+1);
2204
2205 edgeNodalBasis.Eval(x, nodalX);
2206 edgeNodalBasis.Eval(y, nodalY);
2207
2208 // First, fix edge-based shape functions. Use a nodal interpolant for edge
2209 // points, weighted by the linear function that vanishes on opposite edge.
2210 for (int i = 0; i < p-1; i++)
2211 {
2212 shape(4 + 0*(p-1) + i) = (nodalX(i+1))*(1.-y); // south edge 0->1
2213 shape(4 + 1*(p-1) + i) = (nodalY(i+1))*x; // east edge 1->2
2214 shape(4 + 3*(p-1) - i - 1) = (nodalX(i+1)) * y; // north edge 3->2
2215 shape(4 + 4*(p-1) - i - 1) = (nodalY(i+1)) * (1. - x); // west edge 0->3
2216 }
2217
2218 BiLinear2DFiniteElement bilinear = BiLinear2DFiniteElement();
2219 Vector bilinearsAtIP(4);
2220 bilinear.CalcShape(ip, bilinearsAtIP);
2221
2222 const double *edgePts(poly1d.ClosedPoints(p, BasisType::GaussLobatto));
2223
2224 // Next, set the shape function associated with vertex V, evaluated at (x,y)
2225 // to be: bilinear function associated to V, evaluated at (x,y) - sum (shape
2226 // function at edge point P, weighted by bilinear function for V evaluated at
2227 // P) where the sum is taken only for points P on edges incident to V.
2228
2229 double vtx0fix =0;
2230 double vtx1fix =0;
2231 double vtx2fix =0;
2232 double vtx3fix =0;
2233 for (int i = 0; i<p-1; i++)
2234 {
2235 vtx0fix += (1-edgePts[i+1])*(shape(4 + i) +
2236 shape(4 + 4*(p-1) - i - 1)); // bot+left edge
2237 vtx1fix += (1-edgePts[i+1])*(shape(4 + 1*(p-1) + i) +
2238 shape(4 + (p-2)-i)); // right+bot edge
2239 vtx2fix += (1-edgePts[i+1])*(shape(4 + 2*(p-1) + i) +
2240 shape(1 + 2*p-i)); // top+right edge
2241 vtx3fix += (1-edgePts[i+1])*(shape(4 + 3*(p-1) + i) +
2242 shape(3*p - i)); // left+top edge
2243 }
2244 shape(0) = bilinearsAtIP(0) - vtx0fix;
2245 shape(1) = bilinearsAtIP(1) - vtx1fix;
2246 shape(2) = bilinearsAtIP(2) - vtx2fix;
2247 shape(3) = bilinearsAtIP(3) - vtx3fix;
2248
2249 // Interior basis functions appear starting at order p=4. These are non-nodal
2250 // bubble functions.
2251 if (p > 3)
2252 {
2253 double *legX = new double[p-1];
2254 double *legY = new double[p-1];
2255 Poly_1D *storeLegendre = new Poly_1D();
2256
2257 storeLegendre->CalcLegendre(p-2, x, legX);
2258 storeLegendre->CalcLegendre(p-2, y, legY);
2259
2260 int interior_total = 0;
2261 for (int j = 4; j < p + 1; j++)
2262 {
2263 for (int k = 0; k < j-3; k++)
2264 {
2265 shape(4 + 4*(p-1) + interior_total)
2266 = legX[k] * legY[j-4-k] * x * (1. - x) * y * (1. - y);
2267 interior_total++;
2268 }
2269 }
2270
2271 delete[] legX;
2272 delete[] legY;
2273 delete storeLegendre;
2274 }
2275 }
2276
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2277 void H1Ser_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
2278 DenseMatrix &dshape) const
2279 {
2280 int p = (this)->GetOrder();
2281 double x = ip.x, y = ip.y;
2282
2283 Poly_1D::Basis edgeNodalBasis(poly1d.GetBasis(p, BasisType::GaussLobatto));
2284 Vector nodalX(p+1);
2285 Vector DnodalX(p+1);
2286 Vector nodalY(p+1);
2287 Vector DnodalY(p+1);
2288
2289 edgeNodalBasis.Eval(x, nodalX, DnodalX);
2290 edgeNodalBasis.Eval(y, nodalY, DnodalY);
2291
2292 for (int i = 0; i < p-1; i++)
2293 {
2294 dshape(4 + 0*(p-1) + i,0) = DnodalX(i+1) * (1.-y);
2295 dshape(4 + 0*(p-1) + i,1) = -nodalX(i+1);
2296 dshape(4 + 1*(p-1) + i,0) = nodalY(i+1);
2297 dshape(4 + 1*(p-1) + i,1) = DnodalY(i+1)*x;
2298 dshape(4 + 3*(p-1) - i - 1,0) = DnodalX(i+1)*y;
2299 dshape(4 + 3*(p-1) - i - 1,1) = nodalX(i+1);
2300 dshape(4 + 4*(p-1) - i - 1,0) = -nodalY(i+1);
2301 dshape(4 + 4*(p-1) - i - 1,1) = DnodalY(i+1) * (1.-x);
2302 }
2303
2304 BiLinear2DFiniteElement bilinear = BiLinear2DFiniteElement();
2305 DenseMatrix DbilinearsAtIP(4);
2306 bilinear.CalcDShape(ip, DbilinearsAtIP);
2307
2308 const double *edgePts(poly1d.ClosedPoints(p, BasisType::GaussLobatto));
2309
2310 dshape(0,0) = DbilinearsAtIP(0,0);
2311 dshape(0,1) = DbilinearsAtIP(0,1);
2312 dshape(1,0) = DbilinearsAtIP(1,0);
2313 dshape(1,1) = DbilinearsAtIP(1,1);
2314 dshape(2,0) = DbilinearsAtIP(2,0);
2315 dshape(2,1) = DbilinearsAtIP(2,1);
2316 dshape(3,0) = DbilinearsAtIP(3,0);
2317 dshape(3,1) = DbilinearsAtIP(3,1);
2318
2319 for (int i = 0; i<p-1; i++)
2320 {
2321 dshape(0,0) -= (1-edgePts[i+1])*(dshape(4 + 0*(p-1) + i, 0) +
2322 dshape(4 + 4*(p-1) - i - 1,0));
2323 dshape(0,1) -= (1-edgePts[i+1])*(dshape(4 + 0*(p-1) + i, 1) +
2324 dshape(4 + 4*(p-1) - i - 1,1));
2325 dshape(1,0) -= (1-edgePts[i+1])*(dshape(4 + 1*(p-1) + i, 0) +
2326 dshape(4 + (p-2)-i, 0));
2327 dshape(1,1) -= (1-edgePts[i+1])*(dshape(4 + 1*(p-1) + i, 1) +
2328 dshape(4 + (p-2)-i, 1));
2329 dshape(2,0) -= (1-edgePts[i+1])*(dshape(4 + 2*(p-1) + i, 0) +
2330 dshape(1 + 2*p-i, 0));
2331 dshape(2,1) -= (1-edgePts[i+1])*(dshape(4 + 2*(p-1) + i, 1) +
2332 dshape(1 + 2*p-i, 1));
2333 dshape(3,0) -= (1-edgePts[i+1])*(dshape(4 + 3*(p-1) + i, 0) +
2334 dshape(3*p - i, 0));
2335 dshape(3,1) -= (1-edgePts[i+1])*(dshape(4 + 3*(p-1) + i, 1) +
2336 dshape(3*p - i, 1));
2337 }
2338
2339 if (p > 3)
2340 {
2341 double *legX = new double[p-1];
2342 double *legY = new double[p-1];
2343 double *DlegX = new double[p-1];
2344 double *DlegY = new double[p-1];
2345 Poly_1D *storeLegendre = new Poly_1D();
2346
2347 storeLegendre->CalcLegendre(p-2, x, legX, DlegX);
2348 storeLegendre->CalcLegendre(p-2, y, legY, DlegY);
2349
2350 int interior_total = 0;
2351 for (int j = 4; j < p + 1; j++)
2352 {
2353 for (int k = 0; k < j-3; k++)
2354 {
2355 dshape(4 + 4*(p-1) + interior_total, 0) =
2356 legY[j-4-k]*y*(1-y) * (DlegX[k]*x*(1-x) + legX[k]*(1-2*x));
2357 dshape(4 + 4*(p-1) + interior_total, 1) =
2358 legX[k]*x*(1-x) * (DlegY[j-4-k]*y*(1-y) + legY[j-4-k]*(1-2*y));
2359 interior_total++;
2360 }
2361 }
2362 delete[] legX;
2363 delete[] legY;
2364 delete[] DlegX;
2365 delete[] DlegY;
2366 delete storeLegendre;
2367 }
2368 }
2369
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const2370 void H1Ser_QuadrilateralElement::GetLocalInterpolation(ElementTransformation
2371 &Trans,
2372 DenseMatrix &I) const
2373 {
2374 // For p<=4, the basis is nodal; for p>4, the quad-interior functions are
2375 // non-nodal.
2376 if (order <= 4)
2377 {
2378 NodalLocalInterpolation(Trans, I, *this);
2379 }
2380 else
2381 {
2382 ScalarLocalInterpolation(Trans, I, *this);
2383 }
2384 }
2385
2386
BiQuadPos2DFiniteElement()2387 BiQuadPos2DFiniteElement::BiQuadPos2DFiniteElement()
2388 : PositiveFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
2389 {
2390 Nodes.IntPoint(0).x = 0.0;
2391 Nodes.IntPoint(0).y = 0.0;
2392 Nodes.IntPoint(1).x = 1.0;
2393 Nodes.IntPoint(1).y = 0.0;
2394 Nodes.IntPoint(2).x = 1.0;
2395 Nodes.IntPoint(2).y = 1.0;
2396 Nodes.IntPoint(3).x = 0.0;
2397 Nodes.IntPoint(3).y = 1.0;
2398 Nodes.IntPoint(4).x = 0.5;
2399 Nodes.IntPoint(4).y = 0.0;
2400 Nodes.IntPoint(5).x = 1.0;
2401 Nodes.IntPoint(5).y = 0.5;
2402 Nodes.IntPoint(6).x = 0.5;
2403 Nodes.IntPoint(6).y = 1.0;
2404 Nodes.IntPoint(7).x = 0.0;
2405 Nodes.IntPoint(7).y = 0.5;
2406 Nodes.IntPoint(8).x = 0.5;
2407 Nodes.IntPoint(8).y = 0.5;
2408 }
2409
CalcShape(const IntegrationPoint & ip,Vector & shape) const2410 void BiQuadPos2DFiniteElement::CalcShape(const IntegrationPoint &ip,
2411 Vector &shape) const
2412 {
2413 double x = ip.x, y = ip.y;
2414 double l1x, l2x, l3x, l1y, l2y, l3y;
2415
2416 l1x = (1. - x) * (1. - x);
2417 l2x = 2. * x * (1. - x);
2418 l3x = x * x;
2419 l1y = (1. - y) * (1. - y);
2420 l2y = 2. * y * (1. - y);
2421 l3y = y * y;
2422
2423 shape(0) = l1x * l1y;
2424 shape(4) = l2x * l1y;
2425 shape(1) = l3x * l1y;
2426 shape(7) = l1x * l2y;
2427 shape(8) = l2x * l2y;
2428 shape(5) = l3x * l2y;
2429 shape(3) = l1x * l3y;
2430 shape(6) = l2x * l3y;
2431 shape(2) = l3x * l3y;
2432 }
2433
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2434 void BiQuadPos2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
2435 DenseMatrix &dshape) const
2436 {
2437 double x = ip.x, y = ip.y;
2438 double l1x, l2x, l3x, l1y, l2y, l3y;
2439 double d1x, d2x, d3x, d1y, d2y, d3y;
2440
2441 l1x = (1. - x) * (1. - x);
2442 l2x = 2. * x * (1. - x);
2443 l3x = x * x;
2444 l1y = (1. - y) * (1. - y);
2445 l2y = 2. * y * (1. - y);
2446 l3y = y * y;
2447
2448 d1x = 2. * x - 2.;
2449 d2x = 2. - 4. * x;
2450 d3x = 2. * x;
2451 d1y = 2. * y - 2.;
2452 d2y = 2. - 4. * y;
2453 d3y = 2. * y;
2454
2455 dshape(0,0) = d1x * l1y;
2456 dshape(0,1) = l1x * d1y;
2457
2458 dshape(4,0) = d2x * l1y;
2459 dshape(4,1) = l2x * d1y;
2460
2461 dshape(1,0) = d3x * l1y;
2462 dshape(1,1) = l3x * d1y;
2463
2464 dshape(7,0) = d1x * l2y;
2465 dshape(7,1) = l1x * d2y;
2466
2467 dshape(8,0) = d2x * l2y;
2468 dshape(8,1) = l2x * d2y;
2469
2470 dshape(5,0) = d3x * l2y;
2471 dshape(5,1) = l3x * d2y;
2472
2473 dshape(3,0) = d1x * l3y;
2474 dshape(3,1) = l1x * d3y;
2475
2476 dshape(6,0) = d2x * l3y;
2477 dshape(6,1) = l2x * d3y;
2478
2479 dshape(2,0) = d3x * l3y;
2480 dshape(2,1) = l3x * d3y;
2481 }
2482
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const2483 void BiQuadPos2DFiniteElement::GetLocalInterpolation(
2484 ElementTransformation &Trans, DenseMatrix &I) const
2485 {
2486 double s[9];
2487 IntegrationPoint tr_ip;
2488 Vector xx(&tr_ip.x, 2), shape(s, 9);
2489
2490 for (int i = 0; i < 9; i++)
2491 {
2492 Trans.Transform(Nodes.IntPoint(i), xx);
2493 CalcShape(tr_ip, shape);
2494 for (int j = 0; j < 9; j++)
2495 if (fabs(I(i,j) = s[j]) < 1.0e-12)
2496 {
2497 I(i,j) = 0.0;
2498 }
2499 }
2500 for (int i = 0; i < 9; i++)
2501 {
2502 double *d = &I(0,i);
2503 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
2504 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
2505 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
2506 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
2507 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
2508 0.25 * (d[0] + d[1] + d[2] + d[3]);
2509 }
2510 }
2511
Project(Coefficient & coeff,ElementTransformation & Trans,Vector & dofs) const2512 void BiQuadPos2DFiniteElement::Project(
2513 Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
2514 {
2515 double *d = dofs;
2516
2517 for (int i = 0; i < 9; i++)
2518 {
2519 const IntegrationPoint &ip = Nodes.IntPoint(i);
2520 Trans.SetIntPoint(&ip);
2521 d[i] = coeff.Eval(Trans, ip);
2522 }
2523 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
2524 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
2525 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
2526 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
2527 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
2528 0.25 * (d[0] + d[1] + d[2] + d[3]);
2529 }
2530
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const2531 void BiQuadPos2DFiniteElement::Project (
2532 VectorCoefficient &vc, ElementTransformation &Trans,
2533 Vector &dofs) const
2534 {
2535 double v[3];
2536 Vector x (v, vc.GetVDim());
2537
2538 for (int i = 0; i < 9; i++)
2539 {
2540 const IntegrationPoint &ip = Nodes.IntPoint(i);
2541 Trans.SetIntPoint(&ip);
2542 vc.Eval (x, Trans, ip);
2543 for (int j = 0; j < x.Size(); j++)
2544 {
2545 dofs(9*j+i) = v[j];
2546 }
2547 }
2548 for (int j = 0; j < x.Size(); j++)
2549 {
2550 double *d = &dofs(9*j);
2551
2552 d[4] = 2. * d[4] - 0.5 * (d[0] + d[1]);
2553 d[5] = 2. * d[5] - 0.5 * (d[1] + d[2]);
2554 d[6] = 2. * d[6] - 0.5 * (d[2] + d[3]);
2555 d[7] = 2. * d[7] - 0.5 * (d[3] + d[0]);
2556 d[8] = 4. * d[8] - 0.5 * (d[4] + d[5] + d[6] + d[7]) -
2557 0.25 * (d[0] + d[1] + d[2] + d[3]);
2558 }
2559 }
2560
2561
GaussBiQuad2DFiniteElement()2562 GaussBiQuad2DFiniteElement::GaussBiQuad2DFiniteElement()
2563 : NodalFiniteElement(2, Geometry::SQUARE, 9, 2, FunctionSpace::Qk)
2564 {
2565 const double p1 = 0.5*(1.-sqrt(3./5.));
2566
2567 Nodes.IntPoint(0).x = p1;
2568 Nodes.IntPoint(0).y = p1;
2569 Nodes.IntPoint(4).x = 0.5;
2570 Nodes.IntPoint(4).y = p1;
2571 Nodes.IntPoint(1).x = 1.-p1;
2572 Nodes.IntPoint(1).y = p1;
2573 Nodes.IntPoint(7).x = p1;
2574 Nodes.IntPoint(7).y = 0.5;
2575 Nodes.IntPoint(8).x = 0.5;
2576 Nodes.IntPoint(8).y = 0.5;
2577 Nodes.IntPoint(5).x = 1.-p1;
2578 Nodes.IntPoint(5).y = 0.5;
2579 Nodes.IntPoint(3).x = p1;
2580 Nodes.IntPoint(3).y = 1.-p1;
2581 Nodes.IntPoint(6).x = 0.5;
2582 Nodes.IntPoint(6).y = 1.-p1;
2583 Nodes.IntPoint(2).x = 1.-p1;
2584 Nodes.IntPoint(2).y = 1.-p1;
2585 }
2586
CalcShape(const IntegrationPoint & ip,Vector & shape) const2587 void GaussBiQuad2DFiniteElement::CalcShape(const IntegrationPoint &ip,
2588 Vector &shape) const
2589 {
2590 const double a = sqrt(5./3.);
2591 const double p1 = 0.5*(1.-sqrt(3./5.));
2592
2593 double x = a*(ip.x-p1), y = a*(ip.y-p1);
2594 double l1x, l2x, l3x, l1y, l2y, l3y;
2595
2596 l1x = (x - 1.) * (2. * x - 1);
2597 l2x = 4. * x * (1. - x);
2598 l3x = x * (2. * x - 1.);
2599 l1y = (y - 1.) * (2. * y - 1);
2600 l2y = 4. * y * (1. - y);
2601 l3y = y * (2. * y - 1.);
2602
2603 shape(0) = l1x * l1y;
2604 shape(4) = l2x * l1y;
2605 shape(1) = l3x * l1y;
2606 shape(7) = l1x * l2y;
2607 shape(8) = l2x * l2y;
2608 shape(5) = l3x * l2y;
2609 shape(3) = l1x * l3y;
2610 shape(6) = l2x * l3y;
2611 shape(2) = l3x * l3y;
2612 }
2613
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2614 void GaussBiQuad2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
2615 DenseMatrix &dshape) const
2616 {
2617 const double a = sqrt(5./3.);
2618 const double p1 = 0.5*(1.-sqrt(3./5.));
2619
2620 double x = a*(ip.x-p1), y = a*(ip.y-p1);
2621 double l1x, l2x, l3x, l1y, l2y, l3y;
2622 double d1x, d2x, d3x, d1y, d2y, d3y;
2623
2624 l1x = (x - 1.) * (2. * x - 1);
2625 l2x = 4. * x * (1. - x);
2626 l3x = x * (2. * x - 1.);
2627 l1y = (y - 1.) * (2. * y - 1);
2628 l2y = 4. * y * (1. - y);
2629 l3y = y * (2. * y - 1.);
2630
2631 d1x = a * (4. * x - 3.);
2632 d2x = a * (4. - 8. * x);
2633 d3x = a * (4. * x - 1.);
2634 d1y = a * (4. * y - 3.);
2635 d2y = a * (4. - 8. * y);
2636 d3y = a * (4. * y - 1.);
2637
2638 dshape(0,0) = d1x * l1y;
2639 dshape(0,1) = l1x * d1y;
2640
2641 dshape(4,0) = d2x * l1y;
2642 dshape(4,1) = l2x * d1y;
2643
2644 dshape(1,0) = d3x * l1y;
2645 dshape(1,1) = l3x * d1y;
2646
2647 dshape(7,0) = d1x * l2y;
2648 dshape(7,1) = l1x * d2y;
2649
2650 dshape(8,0) = d2x * l2y;
2651 dshape(8,1) = l2x * d2y;
2652
2653 dshape(5,0) = d3x * l2y;
2654 dshape(5,1) = l3x * d2y;
2655
2656 dshape(3,0) = d1x * l3y;
2657 dshape(3,1) = l1x * d3y;
2658
2659 dshape(6,0) = d2x * l3y;
2660 dshape(6,1) = l2x * d3y;
2661
2662 dshape(2,0) = d3x * l3y;
2663 dshape(2,1) = l3x * d3y;
2664 }
2665
BiCubic2DFiniteElement()2666 BiCubic2DFiniteElement::BiCubic2DFiniteElement()
2667 : NodalFiniteElement (2, Geometry::SQUARE, 16, 3, FunctionSpace::Qk)
2668 {
2669 Nodes.IntPoint(0).x = 0.;
2670 Nodes.IntPoint(0).y = 0.;
2671 Nodes.IntPoint(1).x = 1.;
2672 Nodes.IntPoint(1).y = 0.;
2673 Nodes.IntPoint(2).x = 1.;
2674 Nodes.IntPoint(2).y = 1.;
2675 Nodes.IntPoint(3).x = 0.;
2676 Nodes.IntPoint(3).y = 1.;
2677 Nodes.IntPoint(4).x = 1./3.;
2678 Nodes.IntPoint(4).y = 0.;
2679 Nodes.IntPoint(5).x = 2./3.;
2680 Nodes.IntPoint(5).y = 0.;
2681 Nodes.IntPoint(6).x = 1.;
2682 Nodes.IntPoint(6).y = 1./3.;
2683 Nodes.IntPoint(7).x = 1.;
2684 Nodes.IntPoint(7).y = 2./3.;
2685 Nodes.IntPoint(8).x = 2./3.;
2686 Nodes.IntPoint(8).y = 1.;
2687 Nodes.IntPoint(9).x = 1./3.;
2688 Nodes.IntPoint(9).y = 1.;
2689 Nodes.IntPoint(10).x = 0.;
2690 Nodes.IntPoint(10).y = 2./3.;
2691 Nodes.IntPoint(11).x = 0.;
2692 Nodes.IntPoint(11).y = 1./3.;
2693 Nodes.IntPoint(12).x = 1./3.;
2694 Nodes.IntPoint(12).y = 1./3.;
2695 Nodes.IntPoint(13).x = 2./3.;
2696 Nodes.IntPoint(13).y = 1./3.;
2697 Nodes.IntPoint(14).x = 1./3.;
2698 Nodes.IntPoint(14).y = 2./3.;
2699 Nodes.IntPoint(15).x = 2./3.;
2700 Nodes.IntPoint(15).y = 2./3.;
2701 }
2702
CalcShape(const IntegrationPoint & ip,Vector & shape) const2703 void BiCubic2DFiniteElement::CalcShape(
2704 const IntegrationPoint &ip, Vector &shape) const
2705 {
2706 double x = ip.x, y = ip.y;
2707
2708 double w1x, w2x, w3x, w1y, w2y, w3y;
2709 double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y;
2710
2711 w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.;
2712 w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.;
2713
2714 l0x = (- 4.5) * w1x * w2x * w3x;
2715 l1x = ( 13.5) * x * w2x * w3x;
2716 l2x = (-13.5) * x * w1x * w3x;
2717 l3x = ( 4.5) * x * w1x * w2x;
2718
2719 l0y = (- 4.5) * w1y * w2y * w3y;
2720 l1y = ( 13.5) * y * w2y * w3y;
2721 l2y = (-13.5) * y * w1y * w3y;
2722 l3y = ( 4.5) * y * w1y * w2y;
2723
2724 shape(0) = l0x * l0y;
2725 shape(1) = l3x * l0y;
2726 shape(2) = l3x * l3y;
2727 shape(3) = l0x * l3y;
2728 shape(4) = l1x * l0y;
2729 shape(5) = l2x * l0y;
2730 shape(6) = l3x * l1y;
2731 shape(7) = l3x * l2y;
2732 shape(8) = l2x * l3y;
2733 shape(9) = l1x * l3y;
2734 shape(10) = l0x * l2y;
2735 shape(11) = l0x * l1y;
2736 shape(12) = l1x * l1y;
2737 shape(13) = l2x * l1y;
2738 shape(14) = l1x * l2y;
2739 shape(15) = l2x * l2y;
2740 }
2741
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2742 void BiCubic2DFiniteElement::CalcDShape(
2743 const IntegrationPoint &ip, DenseMatrix &dshape) const
2744 {
2745 double x = ip.x, y = ip.y;
2746
2747 double w1x, w2x, w3x, w1y, w2y, w3y;
2748 double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y;
2749 double d0x, d1x, d2x, d3x, d0y, d1y, d2y, d3y;
2750
2751 w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.;
2752 w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.;
2753
2754 l0x = (- 4.5) * w1x * w2x * w3x;
2755 l1x = ( 13.5) * x * w2x * w3x;
2756 l2x = (-13.5) * x * w1x * w3x;
2757 l3x = ( 4.5) * x * w1x * w2x;
2758
2759 l0y = (- 4.5) * w1y * w2y * w3y;
2760 l1y = ( 13.5) * y * w2y * w3y;
2761 l2y = (-13.5) * y * w1y * w3y;
2762 l3y = ( 4.5) * y * w1y * w2y;
2763
2764 d0x = -5.5 + ( 18. - 13.5 * x) * x;
2765 d1x = 9. + (-45. + 40.5 * x) * x;
2766 d2x = -4.5 + ( 36. - 40.5 * x) * x;
2767 d3x = 1. + (- 9. + 13.5 * x) * x;
2768
2769 d0y = -5.5 + ( 18. - 13.5 * y) * y;
2770 d1y = 9. + (-45. + 40.5 * y) * y;
2771 d2y = -4.5 + ( 36. - 40.5 * y) * y;
2772 d3y = 1. + (- 9. + 13.5 * y) * y;
2773
2774 dshape( 0,0) = d0x * l0y; dshape( 0,1) = l0x * d0y;
2775 dshape( 1,0) = d3x * l0y; dshape( 1,1) = l3x * d0y;
2776 dshape( 2,0) = d3x * l3y; dshape( 2,1) = l3x * d3y;
2777 dshape( 3,0) = d0x * l3y; dshape( 3,1) = l0x * d3y;
2778 dshape( 4,0) = d1x * l0y; dshape( 4,1) = l1x * d0y;
2779 dshape( 5,0) = d2x * l0y; dshape( 5,1) = l2x * d0y;
2780 dshape( 6,0) = d3x * l1y; dshape( 6,1) = l3x * d1y;
2781 dshape( 7,0) = d3x * l2y; dshape( 7,1) = l3x * d2y;
2782 dshape( 8,0) = d2x * l3y; dshape( 8,1) = l2x * d3y;
2783 dshape( 9,0) = d1x * l3y; dshape( 9,1) = l1x * d3y;
2784 dshape(10,0) = d0x * l2y; dshape(10,1) = l0x * d2y;
2785 dshape(11,0) = d0x * l1y; dshape(11,1) = l0x * d1y;
2786 dshape(12,0) = d1x * l1y; dshape(12,1) = l1x * d1y;
2787 dshape(13,0) = d2x * l1y; dshape(13,1) = l2x * d1y;
2788 dshape(14,0) = d1x * l2y; dshape(14,1) = l1x * d2y;
2789 dshape(15,0) = d2x * l2y; dshape(15,1) = l2x * d2y;
2790 }
2791
CalcHessian(const IntegrationPoint & ip,DenseMatrix & h) const2792 void BiCubic2DFiniteElement::CalcHessian(
2793 const IntegrationPoint &ip, DenseMatrix &h) const
2794 {
2795 double x = ip.x, y = ip.y;
2796
2797 double w1x, w2x, w3x, w1y, w2y, w3y;
2798 double l0x, l1x, l2x, l3x, l0y, l1y, l2y, l3y;
2799 double d0x, d1x, d2x, d3x, d0y, d1y, d2y, d3y;
2800 double h0x, h1x, h2x, h3x, h0y, h1y, h2y, h3y;
2801
2802 w1x = x - 1./3.; w2x = x - 2./3.; w3x = x - 1.;
2803 w1y = y - 1./3.; w2y = y - 2./3.; w3y = y - 1.;
2804
2805 l0x = (- 4.5) * w1x * w2x * w3x;
2806 l1x = ( 13.5) * x * w2x * w3x;
2807 l2x = (-13.5) * x * w1x * w3x;
2808 l3x = ( 4.5) * x * w1x * w2x;
2809
2810 l0y = (- 4.5) * w1y * w2y * w3y;
2811 l1y = ( 13.5) * y * w2y * w3y;
2812 l2y = (-13.5) * y * w1y * w3y;
2813 l3y = ( 4.5) * y * w1y * w2y;
2814
2815 d0x = -5.5 + ( 18. - 13.5 * x) * x;
2816 d1x = 9. + (-45. + 40.5 * x) * x;
2817 d2x = -4.5 + ( 36. - 40.5 * x) * x;
2818 d3x = 1. + (- 9. + 13.5 * x) * x;
2819
2820 d0y = -5.5 + ( 18. - 13.5 * y) * y;
2821 d1y = 9. + (-45. + 40.5 * y) * y;
2822 d2y = -4.5 + ( 36. - 40.5 * y) * y;
2823 d3y = 1. + (- 9. + 13.5 * y) * y;
2824
2825 h0x = -27. * x + 18.;
2826 h1x = 81. * x - 45.;
2827 h2x = -81. * x + 36.;
2828 h3x = 27. * x - 9.;
2829
2830 h0y = -27. * y + 18.;
2831 h1y = 81. * y - 45.;
2832 h2y = -81. * y + 36.;
2833 h3y = 27. * y - 9.;
2834
2835 h( 0,0) = h0x * l0y; h( 0,1) = d0x * d0y; h( 0,2) = l0x * h0y;
2836 h( 1,0) = h3x * l0y; h( 1,1) = d3x * d0y; h( 1,2) = l3x * h0y;
2837 h( 2,0) = h3x * l3y; h( 2,1) = d3x * d3y; h( 2,2) = l3x * h3y;
2838 h( 3,0) = h0x * l3y; h( 3,1) = d0x * d3y; h( 3,2) = l0x * h3y;
2839 h( 4,0) = h1x * l0y; h( 4,1) = d1x * d0y; h( 4,2) = l1x * h0y;
2840 h( 5,0) = h2x * l0y; h( 5,1) = d2x * d0y; h( 5,2) = l2x * h0y;
2841 h( 6,0) = h3x * l1y; h( 6,1) = d3x * d1y; h( 6,2) = l3x * h1y;
2842 h( 7,0) = h3x * l2y; h( 7,1) = d3x * d2y; h( 7,2) = l3x * h2y;
2843 h( 8,0) = h2x * l3y; h( 8,1) = d2x * d3y; h( 8,2) = l2x * h3y;
2844 h( 9,0) = h1x * l3y; h( 9,1) = d1x * d3y; h( 9,2) = l1x * h3y;
2845 h(10,0) = h0x * l2y; h(10,1) = d0x * d2y; h(10,2) = l0x * h2y;
2846 h(11,0) = h0x * l1y; h(11,1) = d0x * d1y; h(11,2) = l0x * h1y;
2847 h(12,0) = h1x * l1y; h(12,1) = d1x * d1y; h(12,2) = l1x * h1y;
2848 h(13,0) = h2x * l1y; h(13,1) = d2x * d1y; h(13,2) = l2x * h1y;
2849 h(14,0) = h1x * l2y; h(14,1) = d1x * d2y; h(14,2) = l1x * h2y;
2850 h(15,0) = h2x * l2y; h(15,1) = d2x * d2y; h(15,2) = l2x * h2y;
2851 }
2852
2853
Cubic1DFiniteElement()2854 Cubic1DFiniteElement::Cubic1DFiniteElement()
2855 : NodalFiniteElement(1, Geometry::SEGMENT, 4, 3)
2856 {
2857 Nodes.IntPoint(0).x = 0.0;
2858 Nodes.IntPoint(1).x = 1.0;
2859 Nodes.IntPoint(2).x = 0.33333333333333333333;
2860 Nodes.IntPoint(3).x = 0.66666666666666666667;
2861 }
2862
CalcShape(const IntegrationPoint & ip,Vector & shape) const2863 void Cubic1DFiniteElement::CalcShape(const IntegrationPoint &ip,
2864 Vector &shape) const
2865 {
2866 double x = ip.x;
2867 double l1 = x,
2868 l2 = (1.0-x),
2869 l3 = (0.33333333333333333333-x),
2870 l4 = (0.66666666666666666667-x);
2871
2872 shape(0) = 4.5 * l2 * l3 * l4;
2873 shape(1) = 4.5 * l1 * l3 * l4;
2874 shape(2) = 13.5 * l1 * l2 * l4;
2875 shape(3) = -13.5 * l1 * l2 * l3;
2876 }
2877
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2878 void Cubic1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
2879 DenseMatrix &dshape) const
2880 {
2881 double x = ip.x;
2882
2883 dshape(0,0) = -5.5 + x * (18. - 13.5 * x);
2884 dshape(1,0) = 1. - x * (9. - 13.5 * x);
2885 dshape(2,0) = 9. - x * (45. - 40.5 * x);
2886 dshape(3,0) = -4.5 + x * (36. - 40.5 * x);
2887 }
2888
2889
Cubic2DFiniteElement()2890 Cubic2DFiniteElement::Cubic2DFiniteElement()
2891 : NodalFiniteElement(2, Geometry::TRIANGLE, 10, 3)
2892 {
2893 Nodes.IntPoint(0).x = 0.0;
2894 Nodes.IntPoint(0).y = 0.0;
2895 Nodes.IntPoint(1).x = 1.0;
2896 Nodes.IntPoint(1).y = 0.0;
2897 Nodes.IntPoint(2).x = 0.0;
2898 Nodes.IntPoint(2).y = 1.0;
2899 Nodes.IntPoint(3).x = 0.33333333333333333333;
2900 Nodes.IntPoint(3).y = 0.0;
2901 Nodes.IntPoint(4).x = 0.66666666666666666667;
2902 Nodes.IntPoint(4).y = 0.0;
2903 Nodes.IntPoint(5).x = 0.66666666666666666667;
2904 Nodes.IntPoint(5).y = 0.33333333333333333333;
2905 Nodes.IntPoint(6).x = 0.33333333333333333333;
2906 Nodes.IntPoint(6).y = 0.66666666666666666667;
2907 Nodes.IntPoint(7).x = 0.0;
2908 Nodes.IntPoint(7).y = 0.66666666666666666667;
2909 Nodes.IntPoint(8).x = 0.0;
2910 Nodes.IntPoint(8).y = 0.33333333333333333333;
2911 Nodes.IntPoint(9).x = 0.33333333333333333333;
2912 Nodes.IntPoint(9).y = 0.33333333333333333333;
2913 }
2914
CalcShape(const IntegrationPoint & ip,Vector & shape) const2915 void Cubic2DFiniteElement::CalcShape(const IntegrationPoint &ip,
2916 Vector &shape) const
2917 {
2918 double x = ip.x, y = ip.y;
2919 double l1 = (-1. + x + y),
2920 lx = (-1. + 3.*x),
2921 ly = (-1. + 3.*y);
2922
2923 shape(0) = -0.5*l1*(3.*l1 + 1.)*(3.*l1 + 2.);
2924 shape(1) = 0.5*x*(lx - 1.)*lx;
2925 shape(2) = 0.5*y*(-1. + ly)*ly;
2926 shape(3) = 4.5*x*l1*(3.*l1 + 1.);
2927 shape(4) = -4.5*x*lx*l1;
2928 shape(5) = 4.5*x*lx*y;
2929 shape(6) = 4.5*x*y*ly;
2930 shape(7) = -4.5*y*l1*ly;
2931 shape(8) = 4.5*y*l1*(1. + 3.*l1);
2932 shape(9) = -27.*x*y*l1;
2933 }
2934
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const2935 void Cubic2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
2936 DenseMatrix &dshape) const
2937 {
2938 double x = ip.x, y = ip.y;
2939
2940 dshape(0,0) = 0.5*(-11. + 36.*y - 9.*(x*(-4. + 3.*x) + 6.*x*y + 3.*y*y));
2941 dshape(1,0) = 1. + 4.5*x*(-2. + 3.*x);
2942 dshape(2,0) = 0.;
2943 dshape(3,0) = 4.5*(2. + 9.*x*x - 5.*y + 3.*y*y + 2.*x*(-5. + 6.*y));
2944 dshape(4,0) = -4.5*(1. - 1.*y + x*(-8. + 9.*x + 6.*y));
2945 dshape(5,0) = 4.5*(-1. + 6.*x)*y;
2946 dshape(6,0) = 4.5*y*(-1. + 3.*y);
2947 dshape(7,0) = 4.5*(1. - 3.*y)*y;
2948 dshape(8,0) = 4.5*y*(-5. + 6.*x + 6.*y);
2949 dshape(9,0) = -27.*y*(-1. + 2.*x + y);
2950
2951 dshape(0,1) = 0.5*(-11. + 36.*y - 9.*(x*(-4. + 3.*x) + 6.*x*y + 3.*y*y));
2952 dshape(1,1) = 0.;
2953 dshape(2,1) = 1. + 4.5*y*(-2. + 3.*y);
2954 dshape(3,1) = 4.5*x*(-5. + 6.*x + 6.*y);
2955 dshape(4,1) = 4.5*(1. - 3.*x)*x;
2956 dshape(5,1) = 4.5*x*(-1. + 3.*x);
2957 dshape(6,1) = 4.5*x*(-1. + 6.*y);
2958 dshape(7,1) = -4.5*(1. + x*(-1. + 6.*y) + y*(-8. + 9.*y));
2959 dshape(8,1) = 4.5*(2. + 3.*x*x + y*(-10. + 9.*y) + x*(-5. + 12.*y));
2960 dshape(9,1) = -27.*x*(-1. + x + 2.*y);
2961 }
2962
CalcHessian(const IntegrationPoint & ip,DenseMatrix & h) const2963 void Cubic2DFiniteElement::CalcHessian (const IntegrationPoint &ip,
2964 DenseMatrix &h) const
2965 {
2966 double x = ip.x, y = ip.y;
2967
2968 h(0,0) = 18.-27.*(x+y);
2969 h(0,1) = 18.-27.*(x+y);
2970 h(0,2) = 18.-27.*(x+y);
2971
2972 h(1,0) = -9.+27.*x;
2973 h(1,1) = 0.;
2974 h(1,2) = 0.;
2975
2976 h(2,0) = 0.;
2977 h(2,1) = 0.;
2978 h(2,2) = -9.+27.*y;
2979
2980 h(3,0) = -45.+81.*x+54.*y;
2981 h(3,1) = -22.5+54.*x+27.*y;
2982 h(3,2) = 27.*x;
2983
2984 h(4,0) = 36.-81.*x-27.*y;
2985 h(4,1) = 4.5-27.*x;
2986 h(4,2) = 0.;
2987
2988 h(5,0) = 27.*y;
2989 h(5,1) = -4.5+27.*x;
2990 h(5,2) = 0.;
2991
2992 h(6,0) = 0.;
2993 h(6,1) = -4.5+27.*y;
2994 h(6,2) = 27.*x;
2995
2996 h(7,0) = 0.;
2997 h(7,1) = 4.5-27.*y;
2998 h(7,2) = 36.-27.*x-81.*y;
2999
3000 h(8,0) = 27.*y;
3001 h(8,1) = -22.5+27.*x+54.*y;
3002 h(8,2) = -45.+54.*x+81.*y;
3003
3004 h(9,0) = -54.*y;
3005 h(9,1) = 27.-54.*(x+y);
3006 h(9,2) = -54.*x;
3007 }
3008
3009
Cubic3DFiniteElement()3010 Cubic3DFiniteElement::Cubic3DFiniteElement()
3011 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 20, 3)
3012 {
3013 Nodes.IntPoint(0).x = 0;
3014 Nodes.IntPoint(0).y = 0;
3015 Nodes.IntPoint(0).z = 0;
3016 Nodes.IntPoint(1).x = 1.;
3017 Nodes.IntPoint(1).y = 0;
3018 Nodes.IntPoint(1).z = 0;
3019 Nodes.IntPoint(2).x = 0;
3020 Nodes.IntPoint(2).y = 1.;
3021 Nodes.IntPoint(2).z = 0;
3022 Nodes.IntPoint(3).x = 0;
3023 Nodes.IntPoint(3).y = 0;
3024 Nodes.IntPoint(3).z = 1.;
3025 Nodes.IntPoint(4).x = 0.3333333333333333333333333333;
3026 Nodes.IntPoint(4).y = 0;
3027 Nodes.IntPoint(4).z = 0;
3028 Nodes.IntPoint(5).x = 0.6666666666666666666666666667;
3029 Nodes.IntPoint(5).y = 0;
3030 Nodes.IntPoint(5).z = 0;
3031 Nodes.IntPoint(6).x = 0;
3032 Nodes.IntPoint(6).y = 0.3333333333333333333333333333;
3033 Nodes.IntPoint(6).z = 0;
3034 Nodes.IntPoint(7).x = 0;
3035 Nodes.IntPoint(7).y = 0.6666666666666666666666666667;
3036 Nodes.IntPoint(7).z = 0;
3037 Nodes.IntPoint(8).x = 0;
3038 Nodes.IntPoint(8).y = 0;
3039 Nodes.IntPoint(8).z = 0.3333333333333333333333333333;
3040 Nodes.IntPoint(9).x = 0;
3041 Nodes.IntPoint(9).y = 0;
3042 Nodes.IntPoint(9).z = 0.6666666666666666666666666667;
3043 Nodes.IntPoint(10).x = 0.6666666666666666666666666667;
3044 Nodes.IntPoint(10).y = 0.3333333333333333333333333333;
3045 Nodes.IntPoint(10).z = 0;
3046 Nodes.IntPoint(11).x = 0.3333333333333333333333333333;
3047 Nodes.IntPoint(11).y = 0.6666666666666666666666666667;
3048 Nodes.IntPoint(11).z = 0;
3049 Nodes.IntPoint(12).x = 0.6666666666666666666666666667;
3050 Nodes.IntPoint(12).y = 0;
3051 Nodes.IntPoint(12).z = 0.3333333333333333333333333333;
3052 Nodes.IntPoint(13).x = 0.3333333333333333333333333333;
3053 Nodes.IntPoint(13).y = 0;
3054 Nodes.IntPoint(13).z = 0.6666666666666666666666666667;
3055 Nodes.IntPoint(14).x = 0;
3056 Nodes.IntPoint(14).y = 0.6666666666666666666666666667;
3057 Nodes.IntPoint(14).z = 0.3333333333333333333333333333;
3058 Nodes.IntPoint(15).x = 0;
3059 Nodes.IntPoint(15).y = 0.3333333333333333333333333333;
3060 Nodes.IntPoint(15).z = 0.6666666666666666666666666667;
3061 Nodes.IntPoint(16).x = 0.3333333333333333333333333333;
3062 Nodes.IntPoint(16).y = 0.3333333333333333333333333333;
3063 Nodes.IntPoint(16).z = 0.3333333333333333333333333333;
3064 Nodes.IntPoint(17).x = 0;
3065 Nodes.IntPoint(17).y = 0.3333333333333333333333333333;
3066 Nodes.IntPoint(17).z = 0.3333333333333333333333333333;
3067 Nodes.IntPoint(18).x = 0.3333333333333333333333333333;
3068 Nodes.IntPoint(18).y = 0;
3069 Nodes.IntPoint(18).z = 0.3333333333333333333333333333;
3070 Nodes.IntPoint(19).x = 0.3333333333333333333333333333;
3071 Nodes.IntPoint(19).y = 0.3333333333333333333333333333;
3072 Nodes.IntPoint(19).z = 0;
3073 }
3074
CalcShape(const IntegrationPoint & ip,Vector & shape) const3075 void Cubic3DFiniteElement::CalcShape(const IntegrationPoint &ip,
3076 Vector &shape) const
3077 {
3078 double x = ip.x, y = ip.y, z = ip.z;
3079
3080 shape(0) = -((-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z)*
3081 (-1 + 3*x + 3*y + 3*z))/2.;
3082 shape(4) = (9*x*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.;
3083 shape(5) = (-9*x*(-1 + 3*x)*(-1 + x + y + z))/2.;
3084 shape(1) = (x*(2 + 9*(-1 + x)*x))/2.;
3085 shape(6) = (9*y*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.;
3086 shape(19) = -27*x*y*(-1 + x + y + z);
3087 shape(10) = (9*x*(-1 + 3*x)*y)/2.;
3088 shape(7) = (-9*y*(-1 + 3*y)*(-1 + x + y + z))/2.;
3089 shape(11) = (9*x*y*(-1 + 3*y))/2.;
3090 shape(2) = (y*(2 + 9*(-1 + y)*y))/2.;
3091 shape(8) = (9*z*(-1 + x + y + z)*(-2 + 3*x + 3*y + 3*z))/2.;
3092 shape(18) = -27*x*z*(-1 + x + y + z);
3093 shape(12) = (9*x*(-1 + 3*x)*z)/2.;
3094 shape(17) = -27*y*z*(-1 + x + y + z);
3095 shape(16) = 27*x*y*z;
3096 shape(14) = (9*y*(-1 + 3*y)*z)/2.;
3097 shape(9) = (-9*z*(-1 + x + y + z)*(-1 + 3*z))/2.;
3098 shape(13) = (9*x*z*(-1 + 3*z))/2.;
3099 shape(15) = (9*y*z*(-1 + 3*z))/2.;
3100 shape(3) = (z*(2 + 9*(-1 + z)*z))/2.;
3101 }
3102
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3103 void Cubic3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
3104 DenseMatrix &dshape) const
3105 {
3106 double x = ip.x, y = ip.y, z = ip.z;
3107
3108 dshape(0,0) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) +
3109 x*(-4 + 6*y + 6*z)))/2.;
3110 dshape(0,1) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) +
3111 x*(-4 + 6*y + 6*z)))/2.;
3112 dshape(0,2) = (-11 + 36*y + 36*z - 9*(3*pow(x,2) + 3*pow(y + z,2) +
3113 x*(-4 + 6*y + 6*z)))/2.;
3114 dshape(4,0) = (9*(9*pow(x,2) + (-1 + y + z)*(-2 + 3*y + 3*z) +
3115 2*x*(-5 + 6*y + 6*z)))/2.;
3116 dshape(4,1) = (9*x*(-5 + 6*x + 6*y + 6*z))/2.;
3117 dshape(4,2) = (9*x*(-5 + 6*x + 6*y + 6*z))/2.;
3118 dshape(5,0) = (-9*(1 - y - z + x*(-8 + 9*x + 6*y + 6*z)))/2.;
3119 dshape(5,1) = (9*(1 - 3*x)*x)/2.;
3120 dshape(5,2) = (9*(1 - 3*x)*x)/2.;
3121 dshape(1,0) = 1 + (9*x*(-2 + 3*x))/2.;
3122 dshape(1,1) = 0;
3123 dshape(1,2) = 0;
3124 dshape(6,0) = (9*y*(-5 + 6*x + 6*y + 6*z))/2.;
3125 dshape(6,1) = (9*(2 + 3*pow(x,2) - 10*y - 5*z + 3*(y + z)*(3*y + z) +
3126 x*(-5 + 12*y + 6*z)))/2.;
3127 dshape(6,2) = (9*y*(-5 + 6*x + 6*y + 6*z))/2.;
3128 dshape(19,0) = -27*y*(-1 + 2*x + y + z);
3129 dshape(19,1) = -27*x*(-1 + x + 2*y + z);
3130 dshape(19,2) = -27*x*y;
3131 dshape(10,0) = (9*(-1 + 6*x)*y)/2.;
3132 dshape(10,1) = (9*x*(-1 + 3*x))/2.;
3133 dshape(10,2) = 0;
3134 dshape(7,0) = (9*(1 - 3*y)*y)/2.;
3135 dshape(7,1) = (-9*(1 + x*(-1 + 6*y) - z + y*(-8 + 9*y + 6*z)))/2.;
3136 dshape(7,2) = (9*(1 - 3*y)*y)/2.;
3137 dshape(11,0) = (9*y*(-1 + 3*y))/2.;
3138 dshape(11,1) = (9*x*(-1 + 6*y))/2.;
3139 dshape(11,2) = 0;
3140 dshape(2,0) = 0;
3141 dshape(2,1) = 1 + (9*y*(-2 + 3*y))/2.;
3142 dshape(2,2) = 0;
3143 dshape(8,0) = (9*z*(-5 + 6*x + 6*y + 6*z))/2.;
3144 dshape(8,1) = (9*z*(-5 + 6*x + 6*y + 6*z))/2.;
3145 dshape(8,2) = (9*(2 + 3*pow(x,2) - 5*y - 10*z + 3*(y + z)*(y + 3*z) +
3146 x*(-5 + 6*y + 12*z)))/2.;
3147 dshape(18,0) = -27*z*(-1 + 2*x + y + z);
3148 dshape(18,1) = -27*x*z;
3149 dshape(18,2) = -27*x*(-1 + x + y + 2*z);
3150 dshape(12,0) = (9*(-1 + 6*x)*z)/2.;
3151 dshape(12,1) = 0;
3152 dshape(12,2) = (9*x*(-1 + 3*x))/2.;
3153 dshape(17,0) = -27*y*z;
3154 dshape(17,1) = -27*z*(-1 + x + 2*y + z);
3155 dshape(17,2) = -27*y*(-1 + x + y + 2*z);
3156 dshape(16,0) = 27*y*z;
3157 dshape(16,1) = 27*x*z;
3158 dshape(16,2) = 27*x*y;
3159 dshape(14,0) = 0;
3160 dshape(14,1) = (9*(-1 + 6*y)*z)/2.;
3161 dshape(14,2) = (9*y*(-1 + 3*y))/2.;
3162 dshape(9,0) = (9*(1 - 3*z)*z)/2.;
3163 dshape(9,1) = (9*(1 - 3*z)*z)/2.;
3164 dshape(9,2) = (9*(-1 + x + y + 8*z - 6*(x + y)*z - 9*pow(z,2)))/2.;
3165 dshape(13,0) = (9*z*(-1 + 3*z))/2.;
3166 dshape(13,1) = 0;
3167 dshape(13,2) = (9*x*(-1 + 6*z))/2.;
3168 dshape(15,0) = 0;
3169 dshape(15,1) = (9*z*(-1 + 3*z))/2.;
3170 dshape(15,2) = (9*y*(-1 + 6*z))/2.;
3171 dshape(3,0) = 0;
3172 dshape(3,1) = 0;
3173 dshape(3,2) = 1 + (9*z*(-2 + 3*z))/2.;
3174 }
3175
3176
P0TriangleFiniteElement()3177 P0TriangleFiniteElement::P0TriangleFiniteElement()
3178 : NodalFiniteElement(2, Geometry::TRIANGLE, 1, 0)
3179 {
3180 Nodes.IntPoint(0).x = 0.333333333333333333;
3181 Nodes.IntPoint(0).y = 0.333333333333333333;
3182 }
3183
CalcShape(const IntegrationPoint & ip,Vector & shape) const3184 void P0TriangleFiniteElement::CalcShape(const IntegrationPoint &ip,
3185 Vector &shape) const
3186 {
3187 shape(0) = 1.0;
3188 }
3189
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3190 void P0TriangleFiniteElement::CalcDShape(const IntegrationPoint &ip,
3191 DenseMatrix &dshape) const
3192 {
3193 dshape(0,0) = 0.0;
3194 dshape(0,1) = 0.0;
3195 }
3196
3197
P0QuadFiniteElement()3198 P0QuadFiniteElement::P0QuadFiniteElement()
3199 : NodalFiniteElement(2, Geometry::SQUARE, 1, 0, FunctionSpace::Qk)
3200 {
3201 Nodes.IntPoint(0).x = 0.5;
3202 Nodes.IntPoint(0).y = 0.5;
3203 }
3204
CalcShape(const IntegrationPoint & ip,Vector & shape) const3205 void P0QuadFiniteElement::CalcShape(const IntegrationPoint &ip,
3206 Vector &shape) const
3207 {
3208 shape(0) = 1.0;
3209 }
3210
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3211 void P0QuadFiniteElement::CalcDShape(const IntegrationPoint &ip,
3212 DenseMatrix &dshape) const
3213 {
3214 dshape(0,0) = 0.0;
3215 dshape(0,1) = 0.0;
3216 }
3217
3218
Linear3DFiniteElement()3219 Linear3DFiniteElement::Linear3DFiniteElement()
3220 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 4, 1)
3221 {
3222 Nodes.IntPoint(0).x = 0.0;
3223 Nodes.IntPoint(0).y = 0.0;
3224 Nodes.IntPoint(0).z = 0.0;
3225 Nodes.IntPoint(1).x = 1.0;
3226 Nodes.IntPoint(1).y = 0.0;
3227 Nodes.IntPoint(1).z = 0.0;
3228 Nodes.IntPoint(2).x = 0.0;
3229 Nodes.IntPoint(2).y = 1.0;
3230 Nodes.IntPoint(2).z = 0.0;
3231 Nodes.IntPoint(3).x = 0.0;
3232 Nodes.IntPoint(3).y = 0.0;
3233 Nodes.IntPoint(3).z = 1.0;
3234 }
3235
CalcShape(const IntegrationPoint & ip,Vector & shape) const3236 void Linear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
3237 Vector &shape) const
3238 {
3239 shape(0) = 1. - ip.x - ip.y - ip.z;
3240 shape(1) = ip.x;
3241 shape(2) = ip.y;
3242 shape(3) = ip.z;
3243 }
3244
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3245 void Linear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
3246 DenseMatrix &dshape) const
3247 {
3248 if (dshape.Height() == 4)
3249 {
3250 double *A = &dshape(0,0);
3251 A[0] = -1.; A[4] = -1.; A[8] = -1.;
3252 A[1] = 1.; A[5] = 0.; A[9] = 0.;
3253 A[2] = 0.; A[6] = 1.; A[10] = 0.;
3254 A[3] = 0.; A[7] = 0.; A[11] = 1.;
3255 }
3256 else
3257 {
3258 dshape(0,0) = -1.; dshape(0,1) = -1.; dshape(0,2) = -1.;
3259 dshape(1,0) = 1.; dshape(1,1) = 0.; dshape(1,2) = 0.;
3260 dshape(2,0) = 0.; dshape(2,1) = 1.; dshape(2,2) = 0.;
3261 dshape(3,0) = 0.; dshape(3,1) = 0.; dshape(3,2) = 1.;
3262 }
3263 }
3264
GetFaceDofs(int face,int ** dofs,int * ndofs) const3265 void Linear3DFiniteElement::GetFaceDofs (int face, int **dofs, int *ndofs)
3266 const
3267 {
3268 static int face_dofs[4][3] = {{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}};
3269
3270 *ndofs = 3;
3271 *dofs = face_dofs[face];
3272 }
3273
3274
Quadratic3DFiniteElement()3275 Quadratic3DFiniteElement::Quadratic3DFiniteElement()
3276 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 10, 2)
3277 {
3278 Nodes.IntPoint(0).x = 0.0;
3279 Nodes.IntPoint(0).y = 0.0;
3280 Nodes.IntPoint(0).z = 0.0;
3281 Nodes.IntPoint(1).x = 1.0;
3282 Nodes.IntPoint(1).y = 0.0;
3283 Nodes.IntPoint(1).z = 0.0;
3284 Nodes.IntPoint(2).x = 0.0;
3285 Nodes.IntPoint(2).y = 1.0;
3286 Nodes.IntPoint(2).z = 0.0;
3287 Nodes.IntPoint(3).x = 0.0;
3288 Nodes.IntPoint(3).y = 0.0;
3289 Nodes.IntPoint(3).z = 1.0;
3290 Nodes.IntPoint(4).x = 0.5;
3291 Nodes.IntPoint(4).y = 0.0;
3292 Nodes.IntPoint(4).z = 0.0;
3293 Nodes.IntPoint(5).x = 0.0;
3294 Nodes.IntPoint(5).y = 0.5;
3295 Nodes.IntPoint(5).z = 0.0;
3296 Nodes.IntPoint(6).x = 0.0;
3297 Nodes.IntPoint(6).y = 0.0;
3298 Nodes.IntPoint(6).z = 0.5;
3299 Nodes.IntPoint(7).x = 0.5;
3300 Nodes.IntPoint(7).y = 0.5;
3301 Nodes.IntPoint(7).z = 0.0;
3302 Nodes.IntPoint(8).x = 0.5;
3303 Nodes.IntPoint(8).y = 0.0;
3304 Nodes.IntPoint(8).z = 0.5;
3305 Nodes.IntPoint(9).x = 0.0;
3306 Nodes.IntPoint(9).y = 0.5;
3307 Nodes.IntPoint(9).z = 0.5;
3308 }
3309
CalcShape(const IntegrationPoint & ip,Vector & shape) const3310 void Quadratic3DFiniteElement::CalcShape(const IntegrationPoint &ip,
3311 Vector &shape) const
3312 {
3313 double L0, L1, L2, L3;
3314
3315 L0 = 1. - ip.x - ip.y - ip.z;
3316 L1 = ip.x;
3317 L2 = ip.y;
3318 L3 = ip.z;
3319
3320 shape(0) = L0 * ( 2.0 * L0 - 1.0 );
3321 shape(1) = L1 * ( 2.0 * L1 - 1.0 );
3322 shape(2) = L2 * ( 2.0 * L2 - 1.0 );
3323 shape(3) = L3 * ( 2.0 * L3 - 1.0 );
3324 shape(4) = 4.0 * L0 * L1;
3325 shape(5) = 4.0 * L0 * L2;
3326 shape(6) = 4.0 * L0 * L3;
3327 shape(7) = 4.0 * L1 * L2;
3328 shape(8) = 4.0 * L1 * L3;
3329 shape(9) = 4.0 * L2 * L3;
3330 }
3331
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3332 void Quadratic3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
3333 DenseMatrix &dshape) const
3334 {
3335 double x, y, z, L0;
3336
3337 x = ip.x;
3338 y = ip.y;
3339 z = ip.z;
3340 L0 = 1.0 - x - y - z;
3341
3342 dshape(0,0) = dshape(0,1) = dshape(0,2) = 1.0 - 4.0 * L0;
3343 dshape(1,0) = -1.0 + 4.0 * x; dshape(1,1) = 0.0; dshape(1,2) = 0.0;
3344 dshape(2,0) = 0.0; dshape(2,1) = -1.0 + 4.0 * y; dshape(2,2) = 0.0;
3345 dshape(3,0) = dshape(3,1) = 0.0; dshape(3,2) = -1.0 + 4.0 * z;
3346 dshape(4,0) = 4.0 * (L0 - x); dshape(4,1) = dshape(4,2) = -4.0 * x;
3347 dshape(5,0) = dshape(5,2) = -4.0 * y; dshape(5,1) = 4.0 * (L0 - y);
3348 dshape(6,0) = dshape(6,1) = -4.0 * z; dshape(6,2) = 4.0 * (L0 - z);
3349 dshape(7,0) = 4.0 * y; dshape(7,1) = 4.0 * x; dshape(7,2) = 0.0;
3350 dshape(8,0) = 4.0 * z; dshape(8,1) = 0.0; dshape(8,2) = 4.0 * x;
3351 dshape(9,0) = 0.0; dshape(9,1) = 4.0 * z; dshape(9,2) = 4.0 * y;
3352 }
3353
TriLinear3DFiniteElement()3354 TriLinear3DFiniteElement::TriLinear3DFiniteElement()
3355 : NodalFiniteElement(3, Geometry::CUBE, 8, 1, FunctionSpace::Qk)
3356 {
3357 Nodes.IntPoint(0).x = 0.0;
3358 Nodes.IntPoint(0).y = 0.0;
3359 Nodes.IntPoint(0).z = 0.0;
3360
3361 Nodes.IntPoint(1).x = 1.0;
3362 Nodes.IntPoint(1).y = 0.0;
3363 Nodes.IntPoint(1).z = 0.0;
3364
3365 Nodes.IntPoint(2).x = 1.0;
3366 Nodes.IntPoint(2).y = 1.0;
3367 Nodes.IntPoint(2).z = 0.0;
3368
3369 Nodes.IntPoint(3).x = 0.0;
3370 Nodes.IntPoint(3).y = 1.0;
3371 Nodes.IntPoint(3).z = 0.0;
3372
3373 Nodes.IntPoint(4).x = 0.0;
3374 Nodes.IntPoint(4).y = 0.0;
3375 Nodes.IntPoint(4).z = 1.0;
3376
3377 Nodes.IntPoint(5).x = 1.0;
3378 Nodes.IntPoint(5).y = 0.0;
3379 Nodes.IntPoint(5).z = 1.0;
3380
3381 Nodes.IntPoint(6).x = 1.0;
3382 Nodes.IntPoint(6).y = 1.0;
3383 Nodes.IntPoint(6).z = 1.0;
3384
3385 Nodes.IntPoint(7).x = 0.0;
3386 Nodes.IntPoint(7).y = 1.0;
3387 Nodes.IntPoint(7).z = 1.0;
3388 }
3389
CalcShape(const IntegrationPoint & ip,Vector & shape) const3390 void TriLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
3391 Vector &shape) const
3392 {
3393 double x = ip.x, y = ip.y, z = ip.z;
3394 double ox = 1.-x, oy = 1.-y, oz = 1.-z;
3395
3396 shape(0) = ox * oy * oz;
3397 shape(1) = x * oy * oz;
3398 shape(2) = x * y * oz;
3399 shape(3) = ox * y * oz;
3400 shape(4) = ox * oy * z;
3401 shape(5) = x * oy * z;
3402 shape(6) = x * y * z;
3403 shape(7) = ox * y * z;
3404 }
3405
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3406 void TriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
3407 DenseMatrix &dshape) const
3408 {
3409 double x = ip.x, y = ip.y, z = ip.z;
3410 double ox = 1.-x, oy = 1.-y, oz = 1.-z;
3411
3412 dshape(0,0) = - oy * oz;
3413 dshape(0,1) = - ox * oz;
3414 dshape(0,2) = - ox * oy;
3415
3416 dshape(1,0) = oy * oz;
3417 dshape(1,1) = - x * oz;
3418 dshape(1,2) = - x * oy;
3419
3420 dshape(2,0) = y * oz;
3421 dshape(2,1) = x * oz;
3422 dshape(2,2) = - x * y;
3423
3424 dshape(3,0) = - y * oz;
3425 dshape(3,1) = ox * oz;
3426 dshape(3,2) = - ox * y;
3427
3428 dshape(4,0) = - oy * z;
3429 dshape(4,1) = - ox * z;
3430 dshape(4,2) = ox * oy;
3431
3432 dshape(5,0) = oy * z;
3433 dshape(5,1) = - x * z;
3434 dshape(5,2) = x * oy;
3435
3436 dshape(6,0) = y * z;
3437 dshape(6,1) = x * z;
3438 dshape(6,2) = x * y;
3439
3440 dshape(7,0) = - y * z;
3441 dshape(7,1) = ox * z;
3442 dshape(7,2) = ox * y;
3443 }
3444
3445
P0SegmentFiniteElement(int Ord)3446 P0SegmentFiniteElement::P0SegmentFiniteElement(int Ord)
3447 : NodalFiniteElement(1, Geometry::SEGMENT, 1, Ord) // default Ord = 0
3448 {
3449 Nodes.IntPoint(0).x = 0.5;
3450 }
3451
CalcShape(const IntegrationPoint & ip,Vector & shape) const3452 void P0SegmentFiniteElement::CalcShape(const IntegrationPoint &ip,
3453 Vector &shape) const
3454 {
3455 shape(0) = 1.0;
3456 }
3457
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3458 void P0SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip,
3459 DenseMatrix &dshape) const
3460 {
3461 dshape(0,0) = 0.0;
3462 }
3463
CrouzeixRaviartFiniteElement()3464 CrouzeixRaviartFiniteElement::CrouzeixRaviartFiniteElement()
3465 : NodalFiniteElement(2, Geometry::TRIANGLE, 3, 1)
3466 {
3467 Nodes.IntPoint(0).x = 0.5;
3468 Nodes.IntPoint(0).y = 0.0;
3469 Nodes.IntPoint(1).x = 0.5;
3470 Nodes.IntPoint(1).y = 0.5;
3471 Nodes.IntPoint(2).x = 0.0;
3472 Nodes.IntPoint(2).y = 0.5;
3473 }
3474
CalcShape(const IntegrationPoint & ip,Vector & shape) const3475 void CrouzeixRaviartFiniteElement::CalcShape(const IntegrationPoint &ip,
3476 Vector &shape) const
3477 {
3478 shape(0) = 1.0 - 2.0 * ip.y;
3479 shape(1) = -1.0 + 2.0 * ( ip.x + ip.y );
3480 shape(2) = 1.0 - 2.0 * ip.x;
3481 }
3482
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3483 void CrouzeixRaviartFiniteElement::CalcDShape(const IntegrationPoint &ip,
3484 DenseMatrix &dshape) const
3485 {
3486 dshape(0,0) = 0.0; dshape(0,1) = -2.0;
3487 dshape(1,0) = 2.0; dshape(1,1) = 2.0;
3488 dshape(2,0) = -2.0; dshape(2,1) = 0.0;
3489 }
3490
CrouzeixRaviartQuadFiniteElement()3491 CrouzeixRaviartQuadFiniteElement::CrouzeixRaviartQuadFiniteElement()
3492 // the FunctionSpace should be rotated (45 degrees) Q_1
3493 // i.e. the span of { 1, x, y, x^2 - y^2 }
3494 : NodalFiniteElement(2, Geometry::SQUARE, 4, 2, FunctionSpace::Qk)
3495 {
3496 Nodes.IntPoint(0).x = 0.5;
3497 Nodes.IntPoint(0).y = 0.0;
3498 Nodes.IntPoint(1).x = 1.0;
3499 Nodes.IntPoint(1).y = 0.5;
3500 Nodes.IntPoint(2).x = 0.5;
3501 Nodes.IntPoint(2).y = 1.0;
3502 Nodes.IntPoint(3).x = 0.0;
3503 Nodes.IntPoint(3).y = 0.5;
3504 }
3505
CalcShape(const IntegrationPoint & ip,Vector & shape) const3506 void CrouzeixRaviartQuadFiniteElement::CalcShape(const IntegrationPoint &ip,
3507 Vector &shape) const
3508 {
3509 const double l1 = ip.x+ip.y-0.5, l2 = 1.-l1, l3 = ip.x-ip.y+0.5, l4 = 1.-l3;
3510
3511 shape(0) = l2 * l3;
3512 shape(1) = l1 * l3;
3513 shape(2) = l1 * l4;
3514 shape(3) = l2 * l4;
3515 }
3516
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const3517 void CrouzeixRaviartQuadFiniteElement::CalcDShape(const IntegrationPoint &ip,
3518 DenseMatrix &dshape) const
3519 {
3520 const double x2 = 2.*ip.x, y2 = 2.*ip.y;
3521
3522 dshape(0,0) = 1. - x2; dshape(0,1) = -2. + y2;
3523 dshape(1,0) = x2; dshape(1,1) = 1. - y2;
3524 dshape(2,0) = 1. - x2; dshape(2,1) = y2;
3525 dshape(3,0) = -2. + x2; dshape(3,1) = 1. - y2;
3526 }
3527
3528
RT0TriangleFiniteElement()3529 RT0TriangleFiniteElement::RT0TriangleFiniteElement()
3530 : VectorFiniteElement(2, Geometry::TRIANGLE, 3, 1, H_DIV)
3531 {
3532 Nodes.IntPoint(0).x = 0.5;
3533 Nodes.IntPoint(0).y = 0.0;
3534 Nodes.IntPoint(1).x = 0.5;
3535 Nodes.IntPoint(1).y = 0.5;
3536 Nodes.IntPoint(2).x = 0.0;
3537 Nodes.IntPoint(2).y = 0.5;
3538 }
3539
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const3540 void RT0TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip,
3541 DenseMatrix &shape) const
3542 {
3543 double x = ip.x, y = ip.y;
3544
3545 shape(0,0) = x;
3546 shape(0,1) = y - 1.;
3547 shape(1,0) = x;
3548 shape(1,1) = y;
3549 shape(2,0) = x - 1.;
3550 shape(2,1) = y;
3551 }
3552
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const3553 void RT0TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip,
3554 Vector &divshape) const
3555 {
3556 divshape(0) = 2.;
3557 divshape(1) = 2.;
3558 divshape(2) = 2.;
3559 }
3560
3561 const double RT0TriangleFiniteElement::nk[3][2] =
3562 { {0, -1}, {1, 1}, {-1, 0} };
3563
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3564 void RT0TriangleFiniteElement::GetLocalInterpolation (
3565 ElementTransformation &Trans, DenseMatrix &I) const
3566 {
3567 int k, j;
3568 #ifdef MFEM_THREAD_SAFE
3569 DenseMatrix vshape(dof, dim);
3570 DenseMatrix Jinv(dim);
3571 #endif
3572
3573 #ifdef MFEM_DEBUG
3574 for (k = 0; k < 3; k++)
3575 {
3576 CalcVShape (Nodes.IntPoint(k), vshape);
3577 for (j = 0; j < 3; j++)
3578 {
3579 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
3580 if (j == k) { d -= 1.0; }
3581 if (fabs(d) > 1.0e-12)
3582 {
3583 mfem::err << "RT0TriangleFiniteElement::GetLocalInterpolation (...)\n"
3584 " k = " << k << ", j = " << j << ", d = " << d << endl;
3585 mfem_error();
3586 }
3587 }
3588 }
3589 #endif
3590
3591 IntegrationPoint ip;
3592 ip.x = ip.y = 0.0;
3593 Trans.SetIntPoint (&ip);
3594 // Trans must be linear
3595 // set Jinv = |J| J^{-t} = adj(J)^t
3596 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
3597 double vk[2];
3598 Vector xk (vk, 2);
3599
3600 for (k = 0; k < 3; k++)
3601 {
3602 Trans.Transform (Nodes.IntPoint (k), xk);
3603 ip.x = vk[0]; ip.y = vk[1];
3604 CalcVShape (ip, vshape);
3605 // vk = |J| J^{-t} nk
3606 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
3607 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
3608 for (j = 0; j < 3; j++)
3609 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
3610 {
3611 I(k,j) = 0.0;
3612 }
3613 }
3614 }
3615
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3616 void RT0TriangleFiniteElement::Project (
3617 VectorCoefficient &vc, ElementTransformation &Trans,
3618 Vector &dofs) const
3619 {
3620 double vk[2];
3621 Vector xk (vk, 2);
3622 #ifdef MFEM_THREAD_SAFE
3623 DenseMatrix Jinv(dim);
3624 #endif
3625
3626 for (int k = 0; k < 3; k++)
3627 {
3628 Trans.SetIntPoint (&Nodes.IntPoint (k));
3629 // set Jinv = |J| J^{-t} = adj(J)^t
3630 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
3631
3632 vc.Eval (xk, Trans, Nodes.IntPoint (k));
3633 // xk^t |J| J^{-t} nk
3634 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
3635 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
3636 }
3637 }
3638
RT0QuadFiniteElement()3639 RT0QuadFiniteElement::RT0QuadFiniteElement()
3640 : VectorFiniteElement(2, Geometry::SQUARE, 4, 1, H_DIV, FunctionSpace::Qk)
3641 {
3642 Nodes.IntPoint(0).x = 0.5;
3643 Nodes.IntPoint(0).y = 0.0;
3644 Nodes.IntPoint(1).x = 1.0;
3645 Nodes.IntPoint(1).y = 0.5;
3646 Nodes.IntPoint(2).x = 0.5;
3647 Nodes.IntPoint(2).y = 1.0;
3648 Nodes.IntPoint(3).x = 0.0;
3649 Nodes.IntPoint(3).y = 0.5;
3650 }
3651
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const3652 void RT0QuadFiniteElement::CalcVShape(const IntegrationPoint &ip,
3653 DenseMatrix &shape) const
3654 {
3655 double x = ip.x, y = ip.y;
3656
3657 shape(0,0) = 0;
3658 shape(0,1) = y - 1.;
3659 shape(1,0) = x;
3660 shape(1,1) = 0;
3661 shape(2,0) = 0;
3662 shape(2,1) = y;
3663 shape(3,0) = x - 1.;
3664 shape(3,1) = 0;
3665 }
3666
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const3667 void RT0QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip,
3668 Vector &divshape) const
3669 {
3670 divshape(0) = 1.;
3671 divshape(1) = 1.;
3672 divshape(2) = 1.;
3673 divshape(3) = 1.;
3674 }
3675
3676 const double RT0QuadFiniteElement::nk[4][2] =
3677 { {0, -1}, {1, 0}, {0, 1}, {-1, 0} };
3678
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3679 void RT0QuadFiniteElement::GetLocalInterpolation (
3680 ElementTransformation &Trans, DenseMatrix &I) const
3681 {
3682 int k, j;
3683 #ifdef MFEM_THREAD_SAFE
3684 DenseMatrix vshape(dof, dim);
3685 DenseMatrix Jinv(dim);
3686 #endif
3687
3688 #ifdef MFEM_DEBUG
3689 for (k = 0; k < 4; k++)
3690 {
3691 CalcVShape (Nodes.IntPoint(k), vshape);
3692 for (j = 0; j < 4; j++)
3693 {
3694 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
3695 if (j == k) { d -= 1.0; }
3696 if (fabs(d) > 1.0e-12)
3697 {
3698 mfem::err << "RT0QuadFiniteElement::GetLocalInterpolation (...)\n"
3699 " k = " << k << ", j = " << j << ", d = " << d << endl;
3700 mfem_error();
3701 }
3702 }
3703 }
3704 #endif
3705
3706 IntegrationPoint ip;
3707 ip.x = ip.y = 0.0;
3708 Trans.SetIntPoint (&ip);
3709 // Trans must be linear (more to have embedding?)
3710 // set Jinv = |J| J^{-t} = adj(J)^t
3711 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
3712 double vk[2];
3713 Vector xk (vk, 2);
3714
3715 for (k = 0; k < 4; k++)
3716 {
3717 Trans.Transform (Nodes.IntPoint (k), xk);
3718 ip.x = vk[0]; ip.y = vk[1];
3719 CalcVShape (ip, vshape);
3720 // vk = |J| J^{-t} nk
3721 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
3722 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
3723 for (j = 0; j < 4; j++)
3724 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
3725 {
3726 I(k,j) = 0.0;
3727 }
3728 }
3729 }
3730
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3731 void RT0QuadFiniteElement::Project (
3732 VectorCoefficient &vc, ElementTransformation &Trans,
3733 Vector &dofs) const
3734 {
3735 double vk[2];
3736 Vector xk (vk, 2);
3737 #ifdef MFEM_THREAD_SAFE
3738 DenseMatrix Jinv(dim);
3739 #endif
3740
3741 for (int k = 0; k < 4; k++)
3742 {
3743 Trans.SetIntPoint (&Nodes.IntPoint (k));
3744 // set Jinv = |J| J^{-t} = adj(J)^t
3745 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
3746
3747 vc.Eval (xk, Trans, Nodes.IntPoint (k));
3748 // xk^t |J| J^{-t} nk
3749 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
3750 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
3751 }
3752 }
3753
RT1TriangleFiniteElement()3754 RT1TriangleFiniteElement::RT1TriangleFiniteElement()
3755 : VectorFiniteElement(2, Geometry::TRIANGLE, 8, 2, H_DIV)
3756 {
3757 Nodes.IntPoint(0).x = 0.33333333333333333333;
3758 Nodes.IntPoint(0).y = 0.0;
3759 Nodes.IntPoint(1).x = 0.66666666666666666667;
3760 Nodes.IntPoint(1).y = 0.0;
3761 Nodes.IntPoint(2).x = 0.66666666666666666667;
3762 Nodes.IntPoint(2).y = 0.33333333333333333333;
3763 Nodes.IntPoint(3).x = 0.33333333333333333333;
3764 Nodes.IntPoint(3).y = 0.66666666666666666667;
3765 Nodes.IntPoint(4).x = 0.0;
3766 Nodes.IntPoint(4).y = 0.66666666666666666667;
3767 Nodes.IntPoint(5).x = 0.0;
3768 Nodes.IntPoint(5).y = 0.33333333333333333333;
3769 Nodes.IntPoint(6).x = 0.33333333333333333333;
3770 Nodes.IntPoint(6).y = 0.33333333333333333333;
3771 Nodes.IntPoint(7).x = 0.33333333333333333333;
3772 Nodes.IntPoint(7).y = 0.33333333333333333333;
3773 }
3774
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const3775 void RT1TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip,
3776 DenseMatrix &shape) const
3777 {
3778 double x = ip.x, y = ip.y;
3779
3780 shape(0,0) = -2 * x * (-1 + x + 2 * y);
3781 shape(0,1) = -2 * (-1 + y) * (-1 + x + 2 * y);
3782 shape(1,0) = 2 * x * (x - y);
3783 shape(1,1) = 2 * (x - y) * (-1 + y);
3784 shape(2,0) = 2 * x * (-1 + 2 * x + y);
3785 shape(2,1) = 2 * y * (-1 + 2 * x + y);
3786 shape(3,0) = 2 * x * (-1 + x + 2 * y);
3787 shape(3,1) = 2 * y * (-1 + x + 2 * y);
3788 shape(4,0) = -2 * (-1 + x) * (x - y);
3789 shape(4,1) = 2 * y * (-x + y);
3790 shape(5,0) = -2 * (-1 + x) * (-1 + 2 * x + y);
3791 shape(5,1) = -2 * y * (-1 + 2 * x + y);
3792 shape(6,0) = -3 * x * (-2 + 2 * x + y);
3793 shape(6,1) = -3 * y * (-1 + 2 * x + y);
3794 shape(7,0) = -3 * x * (-1 + x + 2 * y);
3795 shape(7,1) = -3 * y * (-2 + x + 2 * y);
3796 }
3797
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const3798 void RT1TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip,
3799 Vector &divshape) const
3800 {
3801 double x = ip.x, y = ip.y;
3802
3803 divshape(0) = -2 * (-4 + 3 * x + 6 * y);
3804 divshape(1) = 2 + 6 * x - 6 * y;
3805 divshape(2) = -4 + 12 * x + 6 * y;
3806 divshape(3) = -4 + 6 * x + 12 * y;
3807 divshape(4) = 2 - 6 * x + 6 * y;
3808 divshape(5) = -2 * (-4 + 6 * x + 3 * y);
3809 divshape(6) = -9 * (-1 + 2 * x + y);
3810 divshape(7) = -9 * (-1 + x + 2 * y);
3811 }
3812
3813 const double RT1TriangleFiniteElement::nk[8][2] =
3814 {
3815 { 0,-1}, { 0,-1},
3816 { 1, 1}, { 1, 1},
3817 {-1, 0}, {-1, 0},
3818 { 1, 0}, { 0, 1}
3819 };
3820
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3821 void RT1TriangleFiniteElement::GetLocalInterpolation (
3822 ElementTransformation &Trans, DenseMatrix &I) const
3823 {
3824 int k, j;
3825 #ifdef MFEM_THREAD_SAFE
3826 DenseMatrix vshape(dof, dim);
3827 DenseMatrix Jinv(dim);
3828 #endif
3829
3830 #ifdef MFEM_DEBUG
3831 for (k = 0; k < 8; k++)
3832 {
3833 CalcVShape (Nodes.IntPoint(k), vshape);
3834 for (j = 0; j < 8; j++)
3835 {
3836 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
3837 if (j == k) { d -= 1.0; }
3838 if (fabs(d) > 1.0e-12)
3839 {
3840 mfem::err << "RT1QuadFiniteElement::GetLocalInterpolation (...)\n"
3841 " k = " << k << ", j = " << j << ", d = " << d << endl;
3842 mfem_error();
3843 }
3844 }
3845 }
3846 #endif
3847
3848 IntegrationPoint ip;
3849 ip.x = ip.y = 0.0;
3850 Trans.SetIntPoint (&ip);
3851 // Trans must be linear (more to have embedding?)
3852 // set Jinv = |J| J^{-t} = adj(J)^t
3853 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
3854 double vk[2];
3855 Vector xk (vk, 2);
3856
3857 for (k = 0; k < 8; k++)
3858 {
3859 Trans.Transform (Nodes.IntPoint (k), xk);
3860 ip.x = vk[0]; ip.y = vk[1];
3861 CalcVShape (ip, vshape);
3862 // vk = |J| J^{-t} nk
3863 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
3864 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
3865 for (j = 0; j < 8; j++)
3866 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
3867 {
3868 I(k,j) = 0.0;
3869 }
3870 }
3871 }
3872
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3873 void RT1TriangleFiniteElement::Project (
3874 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
3875 {
3876 double vk[2];
3877 Vector xk (vk, 2);
3878 #ifdef MFEM_THREAD_SAFE
3879 DenseMatrix Jinv(dim);
3880 #endif
3881
3882 for (int k = 0; k < 8; k++)
3883 {
3884 Trans.SetIntPoint (&Nodes.IntPoint (k));
3885 // set Jinv = |J| J^{-t} = adj(J)^t
3886 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
3887
3888 vc.Eval (xk, Trans, Nodes.IntPoint (k));
3889 // xk^t |J| J^{-t} nk
3890 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
3891 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
3892 dofs(k) *= 0.5;
3893 }
3894 }
3895
RT1QuadFiniteElement()3896 RT1QuadFiniteElement::RT1QuadFiniteElement()
3897 : VectorFiniteElement(2, Geometry::SQUARE, 12, 2, H_DIV, FunctionSpace::Qk)
3898 {
3899 // y = 0
3900 Nodes.IntPoint(0).x = 1./3.;
3901 Nodes.IntPoint(0).y = 0.0;
3902 Nodes.IntPoint(1).x = 2./3.;
3903 Nodes.IntPoint(1).y = 0.0;
3904 // x = 1
3905 Nodes.IntPoint(2).x = 1.0;
3906 Nodes.IntPoint(2).y = 1./3.;
3907 Nodes.IntPoint(3).x = 1.0;
3908 Nodes.IntPoint(3).y = 2./3.;
3909 // y = 1
3910 Nodes.IntPoint(4).x = 2./3.;
3911 Nodes.IntPoint(4).y = 1.0;
3912 Nodes.IntPoint(5).x = 1./3.;
3913 Nodes.IntPoint(5).y = 1.0;
3914 // x = 0
3915 Nodes.IntPoint(6).x = 0.0;
3916 Nodes.IntPoint(6).y = 2./3.;
3917 Nodes.IntPoint(7).x = 0.0;
3918 Nodes.IntPoint(7).y = 1./3.;
3919 // x = 0.5 (interior)
3920 Nodes.IntPoint(8).x = 0.5;
3921 Nodes.IntPoint(8).y = 1./3.;
3922 Nodes.IntPoint(9).x = 0.5;
3923 Nodes.IntPoint(9).y = 2./3.;
3924 // y = 0.5 (interior)
3925 Nodes.IntPoint(10).x = 1./3.;
3926 Nodes.IntPoint(10).y = 0.5;
3927 Nodes.IntPoint(11).x = 2./3.;
3928 Nodes.IntPoint(11).y = 0.5;
3929 }
3930
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const3931 void RT1QuadFiniteElement::CalcVShape(const IntegrationPoint &ip,
3932 DenseMatrix &shape) const
3933 {
3934 double x = ip.x, y = ip.y;
3935
3936 // y = 0
3937 shape(0,0) = 0;
3938 shape(0,1) = -( 1. - 3.*y + 2.*y*y)*( 2. - 3.*x);
3939 shape(1,0) = 0;
3940 shape(1,1) = -( 1. - 3.*y + 2.*y*y)*(-1. + 3.*x);
3941 // x = 1
3942 shape(2,0) = (-x + 2.*x*x)*( 2. - 3.*y);
3943 shape(2,1) = 0;
3944 shape(3,0) = (-x + 2.*x*x)*(-1. + 3.*y);
3945 shape(3,1) = 0;
3946 // y = 1
3947 shape(4,0) = 0;
3948 shape(4,1) = (-y + 2.*y*y)*(-1. + 3.*x);
3949 shape(5,0) = 0;
3950 shape(5,1) = (-y + 2.*y*y)*( 2. - 3.*x);
3951 // x = 0
3952 shape(6,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y);
3953 shape(6,1) = 0;
3954 shape(7,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y);
3955 shape(7,1) = 0;
3956 // x = 0.5 (interior)
3957 shape(8,0) = (4.*x - 4.*x*x)*( 2. - 3.*y);
3958 shape(8,1) = 0;
3959 shape(9,0) = (4.*x - 4.*x*x)*(-1. + 3.*y);
3960 shape(9,1) = 0;
3961 // y = 0.5 (interior)
3962 shape(10,0) = 0;
3963 shape(10,1) = (4.*y - 4.*y*y)*( 2. - 3.*x);
3964 shape(11,0) = 0;
3965 shape(11,1) = (4.*y - 4.*y*y)*(-1. + 3.*x);
3966 }
3967
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const3968 void RT1QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip,
3969 Vector &divshape) const
3970 {
3971 double x = ip.x, y = ip.y;
3972
3973 divshape(0) = -(-3. + 4.*y)*( 2. - 3.*x);
3974 divshape(1) = -(-3. + 4.*y)*(-1. + 3.*x);
3975 divshape(2) = (-1. + 4.*x)*( 2. - 3.*y);
3976 divshape(3) = (-1. + 4.*x)*(-1. + 3.*y);
3977 divshape(4) = (-1. + 4.*y)*(-1. + 3.*x);
3978 divshape(5) = (-1. + 4.*y)*( 2. - 3.*x);
3979 divshape(6) = -(-3. + 4.*x)*(-1. + 3.*y);
3980 divshape(7) = -(-3. + 4.*x)*( 2. - 3.*y);
3981 divshape(8) = ( 4. - 8.*x)*( 2. - 3.*y);
3982 divshape(9) = ( 4. - 8.*x)*(-1. + 3.*y);
3983 divshape(10) = ( 4. - 8.*y)*( 2. - 3.*x);
3984 divshape(11) = ( 4. - 8.*y)*(-1. + 3.*x);
3985 }
3986
3987 const double RT1QuadFiniteElement::nk[12][2] =
3988 {
3989 // y = 0
3990 {0,-1}, {0,-1},
3991 // X = 1
3992 {1, 0}, {1, 0},
3993 // y = 1
3994 {0, 1}, {0, 1},
3995 // x = 0
3996 {-1,0}, {-1,0},
3997 // x = 0.5 (interior)
3998 {1, 0}, {1, 0},
3999 // y = 0.5 (interior)
4000 {0, 1}, {0, 1}
4001 };
4002
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const4003 void RT1QuadFiniteElement::GetLocalInterpolation (
4004 ElementTransformation &Trans, DenseMatrix &I) const
4005 {
4006 int k, j;
4007 #ifdef MFEM_THREAD_SAFE
4008 DenseMatrix vshape(dof, dim);
4009 DenseMatrix Jinv(dim);
4010 #endif
4011
4012 #ifdef MFEM_DEBUG
4013 for (k = 0; k < 12; k++)
4014 {
4015 CalcVShape (Nodes.IntPoint(k), vshape);
4016 for (j = 0; j < 12; j++)
4017 {
4018 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
4019 if (j == k) { d -= 1.0; }
4020 if (fabs(d) > 1.0e-12)
4021 {
4022 mfem::err << "RT1QuadFiniteElement::GetLocalInterpolation (...)\n"
4023 " k = " << k << ", j = " << j << ", d = " << d << endl;
4024 mfem_error();
4025 }
4026 }
4027 }
4028 #endif
4029
4030 IntegrationPoint ip;
4031 ip.x = ip.y = 0.0;
4032 Trans.SetIntPoint (&ip);
4033 // Trans must be linear (more to have embedding?)
4034 // set Jinv = |J| J^{-t} = adj(J)^t
4035 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
4036 double vk[2];
4037 Vector xk (vk, 2);
4038
4039 for (k = 0; k < 12; k++)
4040 {
4041 Trans.Transform (Nodes.IntPoint (k), xk);
4042 ip.x = vk[0]; ip.y = vk[1];
4043 CalcVShape (ip, vshape);
4044 // vk = |J| J^{-t} nk
4045 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
4046 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
4047 for (j = 0; j < 12; j++)
4048 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
4049 {
4050 I(k,j) = 0.0;
4051 }
4052 }
4053 }
4054
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const4055 void RT1QuadFiniteElement::Project (
4056 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
4057 {
4058 double vk[2];
4059 Vector xk (vk, 2);
4060 #ifdef MFEM_THREAD_SAFE
4061 DenseMatrix Jinv(dim);
4062 #endif
4063
4064 for (int k = 0; k < 12; k++)
4065 {
4066 Trans.SetIntPoint (&Nodes.IntPoint (k));
4067 // set Jinv = |J| J^{-t} = adj(J)^t
4068 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
4069
4070 vc.Eval (xk, Trans, Nodes.IntPoint (k));
4071 // xk^t |J| J^{-t} nk
4072 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
4073 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
4074 }
4075 }
4076
4077 const double RT2TriangleFiniteElement::M[15][15] =
4078 {
4079 {
4080 0, -5.3237900077244501311, 5.3237900077244501311, 16.647580015448900262,
4081 0, 24.442740046346700787, -16.647580015448900262, -12.,
4082 -19.118950038622250656, -47.237900077244501311, 0, -34.414110069520051180,
4083 12., 30.590320061795601049, 15.295160030897800524
4084 },
4085 {
4086 0, 1.5, -1.5, -15., 0, 2.625, 15., 15., -4.125, 30., 0, -14.625, -15.,
4087 -15., 10.5
4088 },
4089 {
4090 0, -0.67620999227554986889, 0.67620999227554986889, 7.3524199845510997378,
4091 0, -3.4427400463467007866, -7.3524199845510997378, -12.,
4092 4.1189500386222506555, -0.76209992275549868892, 0, 7.4141100695200511800,
4093 12., -6.5903200617956010489, -3.2951600308978005244
4094 },
4095 {
4096 0, 0, 1.5, 0, 0, 1.5, -11.471370023173350393, 0, 2.4713700231733503933,
4097 -11.471370023173350393, 0, 2.4713700231733503933, 15.295160030897800524,
4098 0, -3.2951600308978005244
4099 },
4100 {
4101 0, 0, 4.875, 0, 0, 4.875, -16.875, 0, -16.875, -16.875, 0, -16.875, 10.5,
4102 36., 10.5
4103 },
4104 {
4105 0, 0, 1.5, 0, 0, 1.5, 2.4713700231733503933, 0, -11.471370023173350393,
4106 2.4713700231733503933, 0, -11.471370023173350393, -3.2951600308978005244,
4107 0, 15.295160030897800524
4108 },
4109 {
4110 -0.67620999227554986889, 0, -3.4427400463467007866, 0,
4111 7.3524199845510997378, 0.67620999227554986889, 7.4141100695200511800, 0,
4112 -0.76209992275549868892, 4.1189500386222506555, -12.,
4113 -7.3524199845510997378, -3.2951600308978005244, -6.5903200617956010489,
4114 12.
4115 },
4116 {
4117 1.5, 0, 2.625, 0, -15., -1.5, -14.625, 0, 30., -4.125, 15., 15., 10.5,
4118 -15., -15.
4119 },
4120 {
4121 -5.3237900077244501311, 0, 24.442740046346700787, 0, 16.647580015448900262,
4122 5.3237900077244501311, -34.414110069520051180, 0, -47.237900077244501311,
4123 -19.118950038622250656, -12., -16.647580015448900262, 15.295160030897800524,
4124 30.590320061795601049, 12.
4125 },
4126 { 0, 0, 18., 0, 0, 6., -42., 0, -30., -26., 0, -14., 24., 32., 8.},
4127 { 0, 0, 6., 0, 0, 18., -14., 0, -26., -30., 0, -42., 8., 32., 24.},
4128 { 0, 0, -6., 0, 0, -4., 30., 0, 4., 22., 0, 4., -24., -16., 0},
4129 { 0, 0, -4., 0, 0, -8., 20., 0, 8., 36., 0, 8., -16., -32., 0},
4130 { 0, 0, -8., 0, 0, -4., 8., 0, 36., 8., 0, 20., 0, -32., -16.},
4131 { 0, 0, -4., 0, 0, -6., 4., 0, 22., 4., 0, 30., 0, -16., -24.}
4132 };
4133
RT2TriangleFiniteElement()4134 RT2TriangleFiniteElement::RT2TriangleFiniteElement()
4135 : VectorFiniteElement(2, Geometry::TRIANGLE, 15, 3, H_DIV)
4136 {
4137 const double p = 0.11270166537925831148;
4138
4139 Nodes.IntPoint(0).x = p;
4140 Nodes.IntPoint(0).y = 0.0;
4141 Nodes.IntPoint(1).x = 0.5;
4142 Nodes.IntPoint(1).y = 0.0;
4143 Nodes.IntPoint(2).x = 1.-p;
4144 Nodes.IntPoint(2).y = 0.0;
4145 Nodes.IntPoint(3).x = 1.-p;
4146 Nodes.IntPoint(3).y = p;
4147 Nodes.IntPoint(4).x = 0.5;
4148 Nodes.IntPoint(4).y = 0.5;
4149 Nodes.IntPoint(5).x = p;
4150 Nodes.IntPoint(5).y = 1.-p;
4151 Nodes.IntPoint(6).x = 0.0;
4152 Nodes.IntPoint(6).y = 1.-p;
4153 Nodes.IntPoint(7).x = 0.0;
4154 Nodes.IntPoint(7).y = 0.5;
4155 Nodes.IntPoint(8).x = 0.0;
4156 Nodes.IntPoint(8).y = p;
4157 Nodes.IntPoint(9).x = 0.25;
4158 Nodes.IntPoint(9).y = 0.25;
4159 Nodes.IntPoint(10).x = 0.25;
4160 Nodes.IntPoint(10).y = 0.25;
4161 Nodes.IntPoint(11).x = 0.5;
4162 Nodes.IntPoint(11).y = 0.25;
4163 Nodes.IntPoint(12).x = 0.5;
4164 Nodes.IntPoint(12).y = 0.25;
4165 Nodes.IntPoint(13).x = 0.25;
4166 Nodes.IntPoint(13).y = 0.5;
4167 Nodes.IntPoint(14).x = 0.25;
4168 Nodes.IntPoint(14).y = 0.5;
4169 }
4170
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const4171 void RT2TriangleFiniteElement::CalcVShape(const IntegrationPoint &ip,
4172 DenseMatrix &shape) const
4173 {
4174 double x = ip.x, y = ip.y;
4175
4176 double Bx[15] = {1., 0., x, 0., y, 0., x*x, 0., x*y, 0., y*y, 0., x*x*x,
4177 x*x*y, x*y*y
4178 };
4179 double By[15] = {0., 1., 0., x, 0., y, 0., x*x, 0., x*y, 0., y*y,
4180 x*x*y, x*y*y, y*y*y
4181 };
4182
4183 for (int i = 0; i < 15; i++)
4184 {
4185 double cx = 0.0, cy = 0.0;
4186 for (int j = 0; j < 15; j++)
4187 {
4188 cx += M[i][j] * Bx[j];
4189 cy += M[i][j] * By[j];
4190 }
4191 shape(i,0) = cx;
4192 shape(i,1) = cy;
4193 }
4194 }
4195
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const4196 void RT2TriangleFiniteElement::CalcDivShape(const IntegrationPoint &ip,
4197 Vector &divshape) const
4198 {
4199 double x = ip.x, y = ip.y;
4200
4201 double DivB[15] = {0., 0., 1., 0., 0., 1., 2.*x, 0., y, x, 0., 2.*y,
4202 4.*x*x, 4.*x*y, 4.*y*y
4203 };
4204
4205 for (int i = 0; i < 15; i++)
4206 {
4207 double div = 0.0;
4208 for (int j = 0; j < 15; j++)
4209 {
4210 div += M[i][j] * DivB[j];
4211 }
4212 divshape(i) = div;
4213 }
4214 }
4215
4216 const double RT2QuadFiniteElement::pt[4] = {0.,1./3.,2./3.,1.};
4217
4218 const double RT2QuadFiniteElement::dpt[3] = {0.25,0.5,0.75};
4219
RT2QuadFiniteElement()4220 RT2QuadFiniteElement::RT2QuadFiniteElement()
4221 : VectorFiniteElement(2, Geometry::SQUARE, 24, 3, H_DIV, FunctionSpace::Qk)
4222 {
4223 // y = 0 (pt[0])
4224 Nodes.IntPoint(0).x = dpt[0]; Nodes.IntPoint(0).y = pt[0];
4225 Nodes.IntPoint(1).x = dpt[1]; Nodes.IntPoint(1).y = pt[0];
4226 Nodes.IntPoint(2).x = dpt[2]; Nodes.IntPoint(2).y = pt[0];
4227 // x = 1 (pt[3])
4228 Nodes.IntPoint(3).x = pt[3]; Nodes.IntPoint(3).y = dpt[0];
4229 Nodes.IntPoint(4).x = pt[3]; Nodes.IntPoint(4).y = dpt[1];
4230 Nodes.IntPoint(5).x = pt[3]; Nodes.IntPoint(5).y = dpt[2];
4231 // y = 1 (pt[3])
4232 Nodes.IntPoint(6).x = dpt[2]; Nodes.IntPoint(6).y = pt[3];
4233 Nodes.IntPoint(7).x = dpt[1]; Nodes.IntPoint(7).y = pt[3];
4234 Nodes.IntPoint(8).x = dpt[0]; Nodes.IntPoint(8).y = pt[3];
4235 // x = 0 (pt[0])
4236 Nodes.IntPoint(9).x = pt[0]; Nodes.IntPoint(9).y = dpt[2];
4237 Nodes.IntPoint(10).x = pt[0]; Nodes.IntPoint(10).y = dpt[1];
4238 Nodes.IntPoint(11).x = pt[0]; Nodes.IntPoint(11).y = dpt[0];
4239 // x = pt[1] (interior)
4240 Nodes.IntPoint(12).x = pt[1]; Nodes.IntPoint(12).y = dpt[0];
4241 Nodes.IntPoint(13).x = pt[1]; Nodes.IntPoint(13).y = dpt[1];
4242 Nodes.IntPoint(14).x = pt[1]; Nodes.IntPoint(14).y = dpt[2];
4243 // x = pt[2] (interior)
4244 Nodes.IntPoint(15).x = pt[2]; Nodes.IntPoint(15).y = dpt[0];
4245 Nodes.IntPoint(16).x = pt[2]; Nodes.IntPoint(16).y = dpt[1];
4246 Nodes.IntPoint(17).x = pt[2]; Nodes.IntPoint(17).y = dpt[2];
4247 // y = pt[1] (interior)
4248 Nodes.IntPoint(18).x = dpt[0]; Nodes.IntPoint(18).y = pt[1];
4249 Nodes.IntPoint(19).x = dpt[1]; Nodes.IntPoint(19).y = pt[1];
4250 Nodes.IntPoint(20).x = dpt[2]; Nodes.IntPoint(20).y = pt[1];
4251 // y = pt[2] (interior)
4252 Nodes.IntPoint(21).x = dpt[0]; Nodes.IntPoint(21).y = pt[2];
4253 Nodes.IntPoint(22).x = dpt[1]; Nodes.IntPoint(22).y = pt[2];
4254 Nodes.IntPoint(23).x = dpt[2]; Nodes.IntPoint(23).y = pt[2];
4255 }
4256
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const4257 void RT2QuadFiniteElement::CalcVShape(const IntegrationPoint &ip,
4258 DenseMatrix &shape) const
4259 {
4260 double x = ip.x, y = ip.y;
4261
4262 double ax0 = pt[0] - x;
4263 double ax1 = pt[1] - x;
4264 double ax2 = pt[2] - x;
4265 double ax3 = pt[3] - x;
4266
4267 double by0 = dpt[0] - y;
4268 double by1 = dpt[1] - y;
4269 double by2 = dpt[2] - y;
4270
4271 double ay0 = pt[0] - y;
4272 double ay1 = pt[1] - y;
4273 double ay2 = pt[2] - y;
4274 double ay3 = pt[3] - y;
4275
4276 double bx0 = dpt[0] - x;
4277 double bx1 = dpt[1] - x;
4278 double bx2 = dpt[2] - x;
4279
4280 double A01 = pt[0] - pt[1];
4281 double A02 = pt[0] - pt[2];
4282 double A12 = pt[1] - pt[2];
4283 double A03 = pt[0] - pt[3];
4284 double A13 = pt[1] - pt[3];
4285 double A23 = pt[2] - pt[3];
4286
4287 double B01 = dpt[0] - dpt[1];
4288 double B02 = dpt[0] - dpt[2];
4289 double B12 = dpt[1] - dpt[2];
4290
4291 double tx0 = (bx1*bx2)/(B01*B02);
4292 double tx1 = -(bx0*bx2)/(B01*B12);
4293 double tx2 = (bx0*bx1)/(B02*B12);
4294
4295 double ty0 = (by1*by2)/(B01*B02);
4296 double ty1 = -(by0*by2)/(B01*B12);
4297 double ty2 = (by0*by1)/(B02*B12);
4298
4299 // y = 0 (p[0])
4300 shape(0, 0) = 0;
4301 shape(0, 1) = (ay1*ay2*ay3)/(A01*A02*A03)*tx0;
4302 shape(1, 0) = 0;
4303 shape(1, 1) = (ay1*ay2*ay3)/(A01*A02*A03)*tx1;
4304 shape(2, 0) = 0;
4305 shape(2, 1) = (ay1*ay2*ay3)/(A01*A02*A03)*tx2;
4306 // x = 1 (p[3])
4307 shape(3, 0) = (ax0*ax1*ax2)/(A03*A13*A23)*ty0;
4308 shape(3, 1) = 0;
4309 shape(4, 0) = (ax0*ax1*ax2)/(A03*A13*A23)*ty1;
4310 shape(4, 1) = 0;
4311 shape(5, 0) = (ax0*ax1*ax2)/(A03*A13*A23)*ty2;
4312 shape(5, 1) = 0;
4313 // y = 1 (p[3])
4314 shape(6, 0) = 0;
4315 shape(6, 1) = (ay0*ay1*ay2)/(A03*A13*A23)*tx2;
4316 shape(7, 0) = 0;
4317 shape(7, 1) = (ay0*ay1*ay2)/(A03*A13*A23)*tx1;
4318 shape(8, 0) = 0;
4319 shape(8, 1) = (ay0*ay1*ay2)/(A03*A13*A23)*tx0;
4320 // x = 0 (p[0])
4321 shape(9, 0) = (ax1*ax2*ax3)/(A01*A02*A03)*ty2;
4322 shape(9, 1) = 0;
4323 shape(10, 0) = (ax1*ax2*ax3)/(A01*A02*A03)*ty1;
4324 shape(10, 1) = 0;
4325 shape(11, 0) = (ax1*ax2*ax3)/(A01*A02*A03)*ty0;
4326 shape(11, 1) = 0;
4327 // x = p[1] (interior)
4328 shape(12, 0) = (ax0*ax2*ax3)/(A01*A12*A13)*ty0;
4329 shape(12, 1) = 0;
4330 shape(13, 0) = (ax0*ax2*ax3)/(A01*A12*A13)*ty1;
4331 shape(13, 1) = 0;
4332 shape(14, 0) = (ax0*ax2*ax3)/(A01*A12*A13)*ty2;
4333 shape(14, 1) = 0;
4334 // x = p[2] (interior)
4335 shape(15, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty0;
4336 shape(15, 1) = 0;
4337 shape(16, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty1;
4338 shape(16, 1) = 0;
4339 shape(17, 0) = -(ax0*ax1*ax3)/(A02*A12*A23)*ty2;
4340 shape(17, 1) = 0;
4341 // y = p[1] (interior)
4342 shape(18, 0) = 0;
4343 shape(18, 1) = (ay0*ay2*ay3)/(A01*A12*A13)*tx0;
4344 shape(19, 0) = 0;
4345 shape(19, 1) = (ay0*ay2*ay3)/(A01*A12*A13)*tx1;
4346 shape(20, 0) = 0;
4347 shape(20, 1) = (ay0*ay2*ay3)/(A01*A12*A13)*tx2;
4348 // y = p[2] (interior)
4349 shape(21, 0) = 0;
4350 shape(21, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx0;
4351 shape(22, 0) = 0;
4352 shape(22, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx1;
4353 shape(23, 0) = 0;
4354 shape(23, 1) = -(ay0*ay1*ay3)/(A02*A12*A23)*tx2;
4355 }
4356
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const4357 void RT2QuadFiniteElement::CalcDivShape(const IntegrationPoint &ip,
4358 Vector &divshape) const
4359 {
4360 double x = ip.x, y = ip.y;
4361
4362 double a01 = pt[0]*pt[1];
4363 double a02 = pt[0]*pt[2];
4364 double a12 = pt[1]*pt[2];
4365 double a03 = pt[0]*pt[3];
4366 double a13 = pt[1]*pt[3];
4367 double a23 = pt[2]*pt[3];
4368
4369 double bx0 = dpt[0] - x;
4370 double bx1 = dpt[1] - x;
4371 double bx2 = dpt[2] - x;
4372
4373 double by0 = dpt[0] - y;
4374 double by1 = dpt[1] - y;
4375 double by2 = dpt[2] - y;
4376
4377 double A01 = pt[0] - pt[1];
4378 double A02 = pt[0] - pt[2];
4379 double A12 = pt[1] - pt[2];
4380 double A03 = pt[0] - pt[3];
4381 double A13 = pt[1] - pt[3];
4382 double A23 = pt[2] - pt[3];
4383
4384 double A012 = pt[0] + pt[1] + pt[2];
4385 double A013 = pt[0] + pt[1] + pt[3];
4386 double A023 = pt[0] + pt[2] + pt[3];
4387 double A123 = pt[1] + pt[2] + pt[3];
4388
4389 double B01 = dpt[0] - dpt[1];
4390 double B02 = dpt[0] - dpt[2];
4391 double B12 = dpt[1] - dpt[2];
4392
4393 double tx0 = (bx1*bx2)/(B01*B02);
4394 double tx1 = -(bx0*bx2)/(B01*B12);
4395 double tx2 = (bx0*bx1)/(B02*B12);
4396
4397 double ty0 = (by1*by2)/(B01*B02);
4398 double ty1 = -(by0*by2)/(B01*B12);
4399 double ty2 = (by0*by1)/(B02*B12);
4400
4401 // y = 0 (p[0])
4402 divshape(0) = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx0;
4403 divshape(1) = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx1;
4404 divshape(2) = -(a12 + a13 + a23 - 2.*A123*y + 3.*y*y)/(A01*A02*A03)*tx2;
4405 // x = 1 (p[3])
4406 divshape(3) = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty0;
4407 divshape(4) = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty1;
4408 divshape(5) = -(a01 + a02 + a12 - 2.*A012*x + 3.*x*x)/(A03*A13*A23)*ty2;
4409 // y = 1 (p[3])
4410 divshape(6) = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx2;
4411 divshape(7) = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx1;
4412 divshape(8) = -(a01 + a02 + a12 - 2.*A012*y + 3.*y*y)/(A03*A13*A23)*tx0;
4413 // x = 0 (p[0])
4414 divshape(9) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty2;
4415 divshape(10) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty1;
4416 divshape(11) = -(a12 + a13 + a23 - 2.*A123*x + 3.*x*x)/(A01*A02*A03)*ty0;
4417 // x = p[1] (interior)
4418 divshape(12) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty0;
4419 divshape(13) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty1;
4420 divshape(14) = -(a02 + a03 + a23 - 2.*A023*x + 3.*x*x)/(A01*A12*A13)*ty2;
4421 // x = p[2] (interior)
4422 divshape(15) = (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty0;
4423 divshape(16) = (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty1;
4424 divshape(17) = (a01 + a03 + a13 - 2.*A013*x + 3.*x*x)/(A02*A12*A23)*ty2;
4425 // y = p[1] (interior)
4426 divshape(18) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx0;
4427 divshape(19) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx1;
4428 divshape(20) = -(a02 + a03 + a23 - 2.*A023*y + 3.*y*y)/(A01*A12*A13)*tx2;
4429 // y = p[2] (interior)
4430 divshape(21) = (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx0;
4431 divshape(22) = (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx1;
4432 divshape(23) = (a01 + a03 + a13 - 2.*A013*y + 3.*y*y)/(A02*A12*A23)*tx2;
4433 }
4434
4435 const double RT2QuadFiniteElement::nk[24][2] =
4436 {
4437 // y = 0
4438 {0,-1}, {0,-1}, {0,-1},
4439 // x = 1
4440 {1, 0}, {1, 0}, {1, 0},
4441 // y = 1
4442 {0, 1}, {0, 1}, {0, 1},
4443 // x = 0
4444 {-1,0}, {-1,0}, {-1,0},
4445 // x = p[1] (interior)
4446 {1, 0}, {1, 0}, {1, 0},
4447 // x = p[2] (interior)
4448 {1, 0}, {1, 0}, {1, 0},
4449 // y = p[1] (interior)
4450 {0, 1}, {0, 1}, {0, 1},
4451 // y = p[1] (interior)
4452 {0, 1}, {0, 1}, {0, 1}
4453 };
4454
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const4455 void RT2QuadFiniteElement::GetLocalInterpolation (
4456 ElementTransformation &Trans, DenseMatrix &I) const
4457 {
4458 int k, j;
4459 #ifdef MFEM_THREAD_SAFE
4460 DenseMatrix vshape(dof, dim);
4461 DenseMatrix Jinv(dim);
4462 #endif
4463
4464 #ifdef MFEM_DEBUG
4465 for (k = 0; k < 24; k++)
4466 {
4467 CalcVShape (Nodes.IntPoint(k), vshape);
4468 for (j = 0; j < 24; j++)
4469 {
4470 double d = vshape(j,0)*nk[k][0]+vshape(j,1)*nk[k][1];
4471 if (j == k) { d -= 1.0; }
4472 if (fabs(d) > 1.0e-12)
4473 {
4474 mfem::err << "RT2QuadFiniteElement::GetLocalInterpolation (...)\n"
4475 " k = " << k << ", j = " << j << ", d = " << d << endl;
4476 mfem_error();
4477 }
4478 }
4479 }
4480 #endif
4481
4482 IntegrationPoint ip;
4483 ip.x = ip.y = 0.0;
4484 Trans.SetIntPoint (&ip);
4485 // Trans must be linear (more to have embedding?)
4486 // set Jinv = |J| J^{-t} = adj(J)^t
4487 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
4488 double vk[2];
4489 Vector xk (vk, 2);
4490
4491 for (k = 0; k < 24; k++)
4492 {
4493 Trans.Transform (Nodes.IntPoint (k), xk);
4494 ip.x = vk[0]; ip.y = vk[1];
4495 CalcVShape (ip, vshape);
4496 // vk = |J| J^{-t} nk
4497 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1];
4498 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1];
4499 for (j = 0; j < 24; j++)
4500 if (fabs (I(k,j) = vshape(j,0)*vk[0]+vshape(j,1)*vk[1]) < 1.0e-12)
4501 {
4502 I(k,j) = 0.0;
4503 }
4504 }
4505 }
4506
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const4507 void RT2QuadFiniteElement::Project (
4508 VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
4509 {
4510 double vk[2];
4511 Vector xk (vk, 2);
4512 #ifdef MFEM_THREAD_SAFE
4513 DenseMatrix Jinv(dim);
4514 #endif
4515
4516 for (int k = 0; k < 24; k++)
4517 {
4518 Trans.SetIntPoint (&Nodes.IntPoint (k));
4519 // set Jinv = |J| J^{-t} = adj(J)^t
4520 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
4521
4522 vc.Eval (xk, Trans, Nodes.IntPoint (k));
4523 // xk^t |J| J^{-t} nk
4524 dofs(k) = (vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1] ) +
4525 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1] ));
4526 }
4527 }
4528
P1SegmentFiniteElement()4529 P1SegmentFiniteElement::P1SegmentFiniteElement()
4530 : NodalFiniteElement(1, Geometry::SEGMENT, 2, 1)
4531 {
4532 Nodes.IntPoint(0).x = 0.33333333333333333333;
4533 Nodes.IntPoint(1).x = 0.66666666666666666667;
4534 }
4535
CalcShape(const IntegrationPoint & ip,Vector & shape) const4536 void P1SegmentFiniteElement::CalcShape(const IntegrationPoint &ip,
4537 Vector &shape) const
4538 {
4539 double x = ip.x;
4540
4541 shape(0) = 2. - 3. * x;
4542 shape(1) = 3. * x - 1.;
4543 }
4544
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4545 void P1SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip,
4546 DenseMatrix &dshape) const
4547 {
4548 dshape(0,0) = -3.;
4549 dshape(1,0) = 3.;
4550 }
4551
4552
P2SegmentFiniteElement()4553 P2SegmentFiniteElement::P2SegmentFiniteElement()
4554 : NodalFiniteElement(1, Geometry::SEGMENT, 3, 2)
4555 {
4556 const double p = 0.11270166537925831148;
4557
4558 Nodes.IntPoint(0).x = p;
4559 Nodes.IntPoint(1).x = 0.5;
4560 Nodes.IntPoint(2).x = 1.-p;
4561 }
4562
CalcShape(const IntegrationPoint & ip,Vector & shape) const4563 void P2SegmentFiniteElement::CalcShape(const IntegrationPoint &ip,
4564 Vector &shape) const
4565 {
4566 const double p = 0.11270166537925831148;
4567 const double w = 1./((1-2*p)*(1-2*p));
4568 double x = ip.x;
4569
4570 shape(0) = (2*x-1)*(x-1+p)*w;
4571 shape(1) = 4*(x-1+p)*(p-x)*w;
4572 shape(2) = (2*x-1)*(x-p)*w;
4573 }
4574
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4575 void P2SegmentFiniteElement::CalcDShape(const IntegrationPoint &ip,
4576 DenseMatrix &dshape) const
4577 {
4578 const double p = 0.11270166537925831148;
4579 const double w = 1./((1-2*p)*(1-2*p));
4580 double x = ip.x;
4581
4582 dshape(0,0) = (-3+4*x+2*p)*w;
4583 dshape(1,0) = (4-8*x)*w;
4584 dshape(2,0) = (-1+4*x-2*p)*w;
4585 }
4586
4587
Lagrange1DFiniteElement(int degree)4588 Lagrange1DFiniteElement::Lagrange1DFiniteElement(int degree)
4589 : NodalFiniteElement(1, Geometry::SEGMENT, degree+1, degree)
4590 {
4591 int i, m = degree;
4592
4593 Nodes.IntPoint(0).x = 0.0;
4594 Nodes.IntPoint(1).x = 1.0;
4595 for (i = 1; i < m; i++)
4596 {
4597 Nodes.IntPoint(i+1).x = double(i) / m;
4598 }
4599
4600 rwk.SetSize(degree+1);
4601 #ifndef MFEM_THREAD_SAFE
4602 rxxk.SetSize(degree+1);
4603 #endif
4604
4605 rwk(0) = 1.0;
4606 for (i = 1; i <= m; i++)
4607 {
4608 rwk(i) = rwk(i-1) * ( (double)(m) / (double)(i) );
4609 }
4610 for (i = 0; i < m/2+1; i++)
4611 {
4612 rwk(m-i) = ( rwk(i) *= rwk(m-i) );
4613 }
4614 for (i = m-1; i >= 0; i -= 2)
4615 {
4616 rwk(i) = -rwk(i);
4617 }
4618 }
4619
CalcShape(const IntegrationPoint & ip,Vector & shape) const4620 void Lagrange1DFiniteElement::CalcShape(const IntegrationPoint &ip,
4621 Vector &shape) const
4622 {
4623 double w, wk, x = ip.x;
4624 int i, k, m = GetOrder();
4625
4626 #ifdef MFEM_THREAD_SAFE
4627 Vector rxxk(m+1);
4628 #endif
4629
4630 k = (int) floor ( m * x + 0.5 );
4631 k = k > m ? m : k < 0 ? 0 : k; // clamp k to [0,m]
4632
4633 wk = 1.0;
4634 for (i = 0; i <= m; i++)
4635 if (i != k)
4636 {
4637 wk *= ( rxxk(i) = x - (double)(i) / m );
4638 }
4639 w = wk * ( rxxk(k) = x - (double)(k) / m );
4640
4641 if (k != 0)
4642 {
4643 shape(0) = w * rwk(0) / rxxk(0);
4644 }
4645 else
4646 {
4647 shape(0) = wk * rwk(0);
4648 }
4649 if (k != m)
4650 {
4651 shape(1) = w * rwk(m) / rxxk(m);
4652 }
4653 else
4654 {
4655 shape(1) = wk * rwk(k);
4656 }
4657 for (i = 1; i < m; i++)
4658 if (i != k)
4659 {
4660 shape(i+1) = w * rwk(i) / rxxk(i);
4661 }
4662 else
4663 {
4664 shape(k+1) = wk * rwk(k);
4665 }
4666 }
4667
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4668 void Lagrange1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
4669 DenseMatrix &dshape) const
4670 {
4671 double s, srx, w, wk, x = ip.x;
4672 int i, k, m = GetOrder();
4673
4674 #ifdef MFEM_THREAD_SAFE
4675 Vector rxxk(m+1);
4676 #endif
4677
4678 k = (int) floor ( m * x + 0.5 );
4679 k = k > m ? m : k < 0 ? 0 : k; // clamp k to [0,m]
4680
4681 wk = 1.0;
4682 for (i = 0; i <= m; i++)
4683 if (i != k)
4684 {
4685 wk *= ( rxxk(i) = x - (double)(i) / m );
4686 }
4687 w = wk * ( rxxk(k) = x - (double)(k) / m );
4688
4689 for (i = 0; i <= m; i++)
4690 {
4691 rxxk(i) = 1.0 / rxxk(i);
4692 }
4693 srx = 0.0;
4694 for (i = 0; i <= m; i++)
4695 if (i != k)
4696 {
4697 srx += rxxk(i);
4698 }
4699 s = w * srx + wk;
4700
4701 if (k != 0)
4702 {
4703 dshape(0,0) = (s - w * rxxk(0)) * rwk(0) * rxxk(0);
4704 }
4705 else
4706 {
4707 dshape(0,0) = wk * srx * rwk(0);
4708 }
4709 if (k != m)
4710 {
4711 dshape(1,0) = (s - w * rxxk(m)) * rwk(m) * rxxk(m);
4712 }
4713 else
4714 {
4715 dshape(1,0) = wk * srx * rwk(k);
4716 }
4717 for (i = 1; i < m; i++)
4718 if (i != k)
4719 {
4720 dshape(i+1,0) = (s - w * rxxk(i)) * rwk(i) * rxxk(i);
4721 }
4722 else
4723 {
4724 dshape(k+1,0) = wk * srx * rwk(k);
4725 }
4726 }
4727
4728
P1TetNonConfFiniteElement()4729 P1TetNonConfFiniteElement::P1TetNonConfFiniteElement()
4730 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 4, 1)
4731 {
4732 Nodes.IntPoint(0).x = 0.33333333333333333333;
4733 Nodes.IntPoint(0).y = 0.33333333333333333333;
4734 Nodes.IntPoint(0).z = 0.33333333333333333333;
4735
4736 Nodes.IntPoint(1).x = 0.0;
4737 Nodes.IntPoint(1).y = 0.33333333333333333333;
4738 Nodes.IntPoint(1).z = 0.33333333333333333333;
4739
4740 Nodes.IntPoint(2).x = 0.33333333333333333333;
4741 Nodes.IntPoint(2).y = 0.0;
4742 Nodes.IntPoint(2).z = 0.33333333333333333333;
4743
4744 Nodes.IntPoint(3).x = 0.33333333333333333333;
4745 Nodes.IntPoint(3).y = 0.33333333333333333333;
4746 Nodes.IntPoint(3).z = 0.0;
4747
4748 }
4749
CalcShape(const IntegrationPoint & ip,Vector & shape) const4750 void P1TetNonConfFiniteElement::CalcShape(const IntegrationPoint &ip,
4751 Vector &shape) const
4752 {
4753 double L0, L1, L2, L3;
4754
4755 L1 = ip.x; L2 = ip.y; L3 = ip.z; L0 = 1.0 - L1 - L2 - L3;
4756 shape(0) = 1.0 - 3.0 * L0;
4757 shape(1) = 1.0 - 3.0 * L1;
4758 shape(2) = 1.0 - 3.0 * L2;
4759 shape(3) = 1.0 - 3.0 * L3;
4760 }
4761
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4762 void P1TetNonConfFiniteElement::CalcDShape(const IntegrationPoint &ip,
4763 DenseMatrix &dshape) const
4764 {
4765 dshape(0,0) = 3.0; dshape(0,1) = 3.0; dshape(0,2) = 3.0;
4766 dshape(1,0) = -3.0; dshape(1,1) = 0.0; dshape(1,2) = 0.0;
4767 dshape(2,0) = 0.0; dshape(2,1) = -3.0; dshape(2,2) = 0.0;
4768 dshape(3,0) = 0.0; dshape(3,1) = 0.0; dshape(3,2) = -3.0;
4769 }
4770
4771
P0TetFiniteElement()4772 P0TetFiniteElement::P0TetFiniteElement()
4773 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 1, 0)
4774 {
4775 Nodes.IntPoint(0).x = 0.25;
4776 Nodes.IntPoint(0).y = 0.25;
4777 Nodes.IntPoint(0).z = 0.25;
4778 }
4779
CalcShape(const IntegrationPoint & ip,Vector & shape) const4780 void P0TetFiniteElement::CalcShape(const IntegrationPoint &ip,
4781 Vector &shape) const
4782 {
4783 shape(0) = 1.0;
4784 }
4785
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4786 void P0TetFiniteElement::CalcDShape(const IntegrationPoint &ip,
4787 DenseMatrix &dshape) const
4788 {
4789 dshape(0,0) = 0.0; dshape(0,1) = 0.0; dshape(0,2) = 0.0;
4790 }
4791
4792
P0HexFiniteElement()4793 P0HexFiniteElement::P0HexFiniteElement()
4794 : NodalFiniteElement(3, Geometry::CUBE, 1, 0, FunctionSpace::Qk)
4795 {
4796 Nodes.IntPoint(0).x = 0.5;
4797 Nodes.IntPoint(0).y = 0.5;
4798 Nodes.IntPoint(0).z = 0.5;
4799 }
4800
CalcShape(const IntegrationPoint & ip,Vector & shape) const4801 void P0HexFiniteElement::CalcShape(const IntegrationPoint &ip,
4802 Vector &shape) const
4803 {
4804 shape(0) = 1.0;
4805 }
4806
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4807 void P0HexFiniteElement::CalcDShape(const IntegrationPoint &ip,
4808 DenseMatrix &dshape) const
4809 {
4810 dshape(0,0) = 0.0; dshape(0,1) = 0.0; dshape(0,2) = 0.0;
4811 }
4812
4813
LagrangeHexFiniteElement(int degree)4814 LagrangeHexFiniteElement::LagrangeHexFiniteElement (int degree)
4815 : NodalFiniteElement(3, Geometry::CUBE, (degree+1)*(degree+1)*(degree+1),
4816 degree, FunctionSpace::Qk)
4817 {
4818 if (degree == 2)
4819 {
4820 I = new int[dof];
4821 J = new int[dof];
4822 K = new int[dof];
4823 // nodes
4824 I[ 0] = 0; J[ 0] = 0; K[ 0] = 0;
4825 I[ 1] = 1; J[ 1] = 0; K[ 1] = 0;
4826 I[ 2] = 1; J[ 2] = 1; K[ 2] = 0;
4827 I[ 3] = 0; J[ 3] = 1; K[ 3] = 0;
4828 I[ 4] = 0; J[ 4] = 0; K[ 4] = 1;
4829 I[ 5] = 1; J[ 5] = 0; K[ 5] = 1;
4830 I[ 6] = 1; J[ 6] = 1; K[ 6] = 1;
4831 I[ 7] = 0; J[ 7] = 1; K[ 7] = 1;
4832 // edges
4833 I[ 8] = 2; J[ 8] = 0; K[ 8] = 0;
4834 I[ 9] = 1; J[ 9] = 2; K[ 9] = 0;
4835 I[10] = 2; J[10] = 1; K[10] = 0;
4836 I[11] = 0; J[11] = 2; K[11] = 0;
4837 I[12] = 2; J[12] = 0; K[12] = 1;
4838 I[13] = 1; J[13] = 2; K[13] = 1;
4839 I[14] = 2; J[14] = 1; K[14] = 1;
4840 I[15] = 0; J[15] = 2; K[15] = 1;
4841 I[16] = 0; J[16] = 0; K[16] = 2;
4842 I[17] = 1; J[17] = 0; K[17] = 2;
4843 I[18] = 1; J[18] = 1; K[18] = 2;
4844 I[19] = 0; J[19] = 1; K[19] = 2;
4845 // faces
4846 I[20] = 2; J[20] = 2; K[20] = 0;
4847 I[21] = 2; J[21] = 0; K[21] = 2;
4848 I[22] = 1; J[22] = 2; K[22] = 2;
4849 I[23] = 2; J[23] = 1; K[23] = 2;
4850 I[24] = 0; J[24] = 2; K[24] = 2;
4851 I[25] = 2; J[25] = 2; K[25] = 1;
4852 // element
4853 I[26] = 2; J[26] = 2; K[26] = 2;
4854 }
4855 else if (degree == 3)
4856 {
4857 I = new int[dof];
4858 J = new int[dof];
4859 K = new int[dof];
4860 // nodes
4861 I[ 0] = 0; J[ 0] = 0; K[ 0] = 0;
4862 I[ 1] = 1; J[ 1] = 0; K[ 1] = 0;
4863 I[ 2] = 1; J[ 2] = 1; K[ 2] = 0;
4864 I[ 3] = 0; J[ 3] = 1; K[ 3] = 0;
4865 I[ 4] = 0; J[ 4] = 0; K[ 4] = 1;
4866 I[ 5] = 1; J[ 5] = 0; K[ 5] = 1;
4867 I[ 6] = 1; J[ 6] = 1; K[ 6] = 1;
4868 I[ 7] = 0; J[ 7] = 1; K[ 7] = 1;
4869 // edges
4870 I[ 8] = 2; J[ 8] = 0; K[ 8] = 0;
4871 I[ 9] = 3; J[ 9] = 0; K[ 9] = 0;
4872 I[10] = 1; J[10] = 2; K[10] = 0;
4873 I[11] = 1; J[11] = 3; K[11] = 0;
4874 I[12] = 2; J[12] = 1; K[12] = 0;
4875 I[13] = 3; J[13] = 1; K[13] = 0;
4876 I[14] = 0; J[14] = 2; K[14] = 0;
4877 I[15] = 0; J[15] = 3; K[15] = 0;
4878 I[16] = 2; J[16] = 0; K[16] = 1;
4879 I[17] = 3; J[17] = 0; K[17] = 1;
4880 I[18] = 1; J[18] = 2; K[18] = 1;
4881 I[19] = 1; J[19] = 3; K[19] = 1;
4882 I[20] = 2; J[20] = 1; K[20] = 1;
4883 I[21] = 3; J[21] = 1; K[21] = 1;
4884 I[22] = 0; J[22] = 2; K[22] = 1;
4885 I[23] = 0; J[23] = 3; K[23] = 1;
4886 I[24] = 0; J[24] = 0; K[24] = 2;
4887 I[25] = 0; J[25] = 0; K[25] = 3;
4888 I[26] = 1; J[26] = 0; K[26] = 2;
4889 I[27] = 1; J[27] = 0; K[27] = 3;
4890 I[28] = 1; J[28] = 1; K[28] = 2;
4891 I[29] = 1; J[29] = 1; K[29] = 3;
4892 I[30] = 0; J[30] = 1; K[30] = 2;
4893 I[31] = 0; J[31] = 1; K[31] = 3;
4894 // faces
4895 I[32] = 2; J[32] = 3; K[32] = 0;
4896 I[33] = 3; J[33] = 3; K[33] = 0;
4897 I[34] = 2; J[34] = 2; K[34] = 0;
4898 I[35] = 3; J[35] = 2; K[35] = 0;
4899 I[36] = 2; J[36] = 0; K[36] = 2;
4900 I[37] = 3; J[37] = 0; K[37] = 2;
4901 I[38] = 2; J[38] = 0; K[38] = 3;
4902 I[39] = 3; J[39] = 0; K[39] = 3;
4903 I[40] = 1; J[40] = 2; K[40] = 2;
4904 I[41] = 1; J[41] = 3; K[41] = 2;
4905 I[42] = 1; J[42] = 2; K[42] = 3;
4906 I[43] = 1; J[43] = 3; K[43] = 3;
4907 I[44] = 3; J[44] = 1; K[44] = 2;
4908 I[45] = 2; J[45] = 1; K[45] = 2;
4909 I[46] = 3; J[46] = 1; K[46] = 3;
4910 I[47] = 2; J[47] = 1; K[47] = 3;
4911 I[48] = 0; J[48] = 3; K[48] = 2;
4912 I[49] = 0; J[49] = 2; K[49] = 2;
4913 I[50] = 0; J[50] = 3; K[50] = 3;
4914 I[51] = 0; J[51] = 2; K[51] = 3;
4915 I[52] = 2; J[52] = 2; K[52] = 1;
4916 I[53] = 3; J[53] = 2; K[53] = 1;
4917 I[54] = 2; J[54] = 3; K[54] = 1;
4918 I[55] = 3; J[55] = 3; K[55] = 1;
4919 // element
4920 I[56] = 2; J[56] = 2; K[56] = 2;
4921 I[57] = 3; J[57] = 2; K[57] = 2;
4922 I[58] = 3; J[58] = 3; K[58] = 2;
4923 I[59] = 2; J[59] = 3; K[59] = 2;
4924 I[60] = 2; J[60] = 2; K[60] = 3;
4925 I[61] = 3; J[61] = 2; K[61] = 3;
4926 I[62] = 3; J[62] = 3; K[62] = 3;
4927 I[63] = 2; J[63] = 3; K[63] = 3;
4928 }
4929 else
4930 {
4931 mfem_error ("LagrangeHexFiniteElement::LagrangeHexFiniteElement");
4932 }
4933
4934 fe1d = new Lagrange1DFiniteElement(degree);
4935 dof1d = fe1d -> GetDof();
4936
4937 #ifndef MFEM_THREAD_SAFE
4938 shape1dx.SetSize(dof1d);
4939 shape1dy.SetSize(dof1d);
4940 shape1dz.SetSize(dof1d);
4941
4942 dshape1dx.SetSize(dof1d,1);
4943 dshape1dy.SetSize(dof1d,1);
4944 dshape1dz.SetSize(dof1d,1);
4945 #endif
4946
4947 for (int n = 0; n < dof; n++)
4948 {
4949 Nodes.IntPoint(n).x = fe1d -> GetNodes().IntPoint(I[n]).x;
4950 Nodes.IntPoint(n).y = fe1d -> GetNodes().IntPoint(J[n]).x;
4951 Nodes.IntPoint(n).z = fe1d -> GetNodes().IntPoint(K[n]).x;
4952 }
4953 }
4954
CalcShape(const IntegrationPoint & ip,Vector & shape) const4955 void LagrangeHexFiniteElement::CalcShape(const IntegrationPoint &ip,
4956 Vector &shape) const
4957 {
4958 IntegrationPoint ipy, ipz;
4959 ipy.x = ip.y;
4960 ipz.x = ip.z;
4961
4962 #ifdef MFEM_THREAD_SAFE
4963 Vector shape1dx(dof1d), shape1dy(dof1d), shape1dz(dof1d);
4964 #endif
4965
4966 fe1d -> CalcShape(ip, shape1dx);
4967 fe1d -> CalcShape(ipy, shape1dy);
4968 fe1d -> CalcShape(ipz, shape1dz);
4969
4970 for (int n = 0; n < dof; n++)
4971 {
4972 shape(n) = shape1dx(I[n]) * shape1dy(J[n]) * shape1dz(K[n]);
4973 }
4974 }
4975
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const4976 void LagrangeHexFiniteElement::CalcDShape(const IntegrationPoint &ip,
4977 DenseMatrix &dshape) const
4978 {
4979 IntegrationPoint ipy, ipz;
4980 ipy.x = ip.y;
4981 ipz.x = ip.z;
4982
4983 #ifdef MFEM_THREAD_SAFE
4984 Vector shape1dx(dof1d), shape1dy(dof1d), shape1dz(dof1d);
4985 DenseMatrix dshape1dx(dof1d,1), dshape1dy(dof1d,1), dshape1dz(dof1d,1);
4986 #endif
4987
4988 fe1d -> CalcShape(ip, shape1dx);
4989 fe1d -> CalcShape(ipy, shape1dy);
4990 fe1d -> CalcShape(ipz, shape1dz);
4991
4992 fe1d -> CalcDShape(ip, dshape1dx);
4993 fe1d -> CalcDShape(ipy, dshape1dy);
4994 fe1d -> CalcDShape(ipz, dshape1dz);
4995
4996 for (int n = 0; n < dof; n++)
4997 {
4998 dshape(n,0) = dshape1dx(I[n],0) * shape1dy(J[n]) * shape1dz(K[n]);
4999 dshape(n,1) = shape1dx(I[n]) * dshape1dy(J[n],0) * shape1dz(K[n]);
5000 dshape(n,2) = shape1dx(I[n]) * shape1dy(J[n]) * dshape1dz(K[n],0);
5001 }
5002 }
5003
~LagrangeHexFiniteElement()5004 LagrangeHexFiniteElement::~LagrangeHexFiniteElement ()
5005 {
5006 delete fe1d;
5007
5008 delete [] I;
5009 delete [] J;
5010 delete [] K;
5011 }
5012
5013
RefinedLinear1DFiniteElement()5014 RefinedLinear1DFiniteElement::RefinedLinear1DFiniteElement()
5015 : NodalFiniteElement(1, Geometry::SEGMENT, 3, 4)
5016 {
5017 Nodes.IntPoint(0).x = 0.0;
5018 Nodes.IntPoint(1).x = 1.0;
5019 Nodes.IntPoint(2).x = 0.5;
5020 }
5021
CalcShape(const IntegrationPoint & ip,Vector & shape) const5022 void RefinedLinear1DFiniteElement::CalcShape(const IntegrationPoint &ip,
5023 Vector &shape) const
5024 {
5025 double x = ip.x;
5026
5027 if (x <= 0.5)
5028 {
5029 shape(0) = 1.0 - 2.0 * x;
5030 shape(1) = 0.0;
5031 shape(2) = 2.0 * x;
5032 }
5033 else
5034 {
5035 shape(0) = 0.0;
5036 shape(1) = 2.0 * x - 1.0;
5037 shape(2) = 2.0 - 2.0 * x;
5038 }
5039 }
5040
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const5041 void RefinedLinear1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
5042 DenseMatrix &dshape) const
5043 {
5044 double x = ip.x;
5045
5046 if (x <= 0.5)
5047 {
5048 dshape(0,0) = - 2.0;
5049 dshape(1,0) = 0.0;
5050 dshape(2,0) = 2.0;
5051 }
5052 else
5053 {
5054 dshape(0,0) = 0.0;
5055 dshape(1,0) = 2.0;
5056 dshape(2,0) = - 2.0;
5057 }
5058 }
5059
RefinedLinear2DFiniteElement()5060 RefinedLinear2DFiniteElement::RefinedLinear2DFiniteElement()
5061 : NodalFiniteElement(2, Geometry::TRIANGLE, 6, 5)
5062 {
5063 Nodes.IntPoint(0).x = 0.0;
5064 Nodes.IntPoint(0).y = 0.0;
5065 Nodes.IntPoint(1).x = 1.0;
5066 Nodes.IntPoint(1).y = 0.0;
5067 Nodes.IntPoint(2).x = 0.0;
5068 Nodes.IntPoint(2).y = 1.0;
5069 Nodes.IntPoint(3).x = 0.5;
5070 Nodes.IntPoint(3).y = 0.0;
5071 Nodes.IntPoint(4).x = 0.5;
5072 Nodes.IntPoint(4).y = 0.5;
5073 Nodes.IntPoint(5).x = 0.0;
5074 Nodes.IntPoint(5).y = 0.5;
5075 }
5076
CalcShape(const IntegrationPoint & ip,Vector & shape) const5077 void RefinedLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
5078 Vector &shape) const
5079 {
5080 int i;
5081
5082 double L0, L1, L2;
5083 L0 = 2.0 * ( 1. - ip.x - ip.y );
5084 L1 = 2.0 * ( ip.x );
5085 L2 = 2.0 * ( ip.y );
5086
5087 // The reference triangle is split in 4 triangles as follows:
5088 //
5089 // T0 - 0,3,5
5090 // T1 - 1,3,4
5091 // T2 - 2,4,5
5092 // T3 - 3,4,5
5093
5094 for (i = 0; i < 6; i++)
5095 {
5096 shape(i) = 0.0;
5097 }
5098
5099 if (L0 >= 1.0) // T0
5100 {
5101 shape(0) = L0 - 1.0;
5102 shape(3) = L1;
5103 shape(5) = L2;
5104 }
5105 else if (L1 >= 1.0) // T1
5106 {
5107 shape(3) = L0;
5108 shape(1) = L1 - 1.0;
5109 shape(4) = L2;
5110 }
5111 else if (L2 >= 1.0) // T2
5112 {
5113 shape(5) = L0;
5114 shape(4) = L1;
5115 shape(2) = L2 - 1.0;
5116 }
5117 else // T3
5118 {
5119 shape(3) = 1.0 - L2;
5120 shape(4) = 1.0 - L0;
5121 shape(5) = 1.0 - L1;
5122 }
5123 }
5124
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const5125 void RefinedLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
5126 DenseMatrix &dshape) const
5127 {
5128 int i,j;
5129
5130 double L0, L1, L2;
5131 L0 = 2.0 * ( 1. - ip.x - ip.y );
5132 L1 = 2.0 * ( ip.x );
5133 L2 = 2.0 * ( ip.y );
5134
5135 double DL0[2], DL1[2], DL2[2];
5136 DL0[0] = -2.0; DL0[1] = -2.0;
5137 DL1[0] = 2.0; DL1[1] = 0.0;
5138 DL2[0] = 0.0; DL2[1] = 2.0;
5139
5140 for (i = 0; i < 6; i++)
5141 for (j = 0; j < 2; j++)
5142 {
5143 dshape(i,j) = 0.0;
5144 }
5145
5146 if (L0 >= 1.0) // T0
5147 {
5148 for (j = 0; j < 2; j++)
5149 {
5150 dshape(0,j) = DL0[j];
5151 dshape(3,j) = DL1[j];
5152 dshape(5,j) = DL2[j];
5153 }
5154 }
5155 else if (L1 >= 1.0) // T1
5156 {
5157 for (j = 0; j < 2; j++)
5158 {
5159 dshape(3,j) = DL0[j];
5160 dshape(1,j) = DL1[j];
5161 dshape(4,j) = DL2[j];
5162 }
5163 }
5164 else if (L2 >= 1.0) // T2
5165 {
5166 for (j = 0; j < 2; j++)
5167 {
5168 dshape(5,j) = DL0[j];
5169 dshape(4,j) = DL1[j];
5170 dshape(2,j) = DL2[j];
5171 }
5172 }
5173 else // T3
5174 {
5175 for (j = 0; j < 2; j++)
5176 {
5177 dshape(3,j) = - DL2[j];
5178 dshape(4,j) = - DL0[j];
5179 dshape(5,j) = - DL1[j];
5180 }
5181 }
5182 }
5183
RefinedLinear3DFiniteElement()5184 RefinedLinear3DFiniteElement::RefinedLinear3DFiniteElement()
5185 : NodalFiniteElement(3, Geometry::TETRAHEDRON, 10, 4)
5186 {
5187 Nodes.IntPoint(0).x = 0.0;
5188 Nodes.IntPoint(0).y = 0.0;
5189 Nodes.IntPoint(0).z = 0.0;
5190 Nodes.IntPoint(1).x = 1.0;
5191 Nodes.IntPoint(1).y = 0.0;
5192 Nodes.IntPoint(1).z = 0.0;
5193 Nodes.IntPoint(2).x = 0.0;
5194 Nodes.IntPoint(2).y = 1.0;
5195 Nodes.IntPoint(2).z = 0.0;
5196 Nodes.IntPoint(3).x = 0.0;
5197 Nodes.IntPoint(3).y = 0.0;
5198 Nodes.IntPoint(3).z = 1.0;
5199 Nodes.IntPoint(4).x = 0.5;
5200 Nodes.IntPoint(4).y = 0.0;
5201 Nodes.IntPoint(4).z = 0.0;
5202 Nodes.IntPoint(5).x = 0.0;
5203 Nodes.IntPoint(5).y = 0.5;
5204 Nodes.IntPoint(5).z = 0.0;
5205 Nodes.IntPoint(6).x = 0.0;
5206 Nodes.IntPoint(6).y = 0.0;
5207 Nodes.IntPoint(6).z = 0.5;
5208 Nodes.IntPoint(7).x = 0.5;
5209 Nodes.IntPoint(7).y = 0.5;
5210 Nodes.IntPoint(7).z = 0.0;
5211 Nodes.IntPoint(8).x = 0.5;
5212 Nodes.IntPoint(8).y = 0.0;
5213 Nodes.IntPoint(8).z = 0.5;
5214 Nodes.IntPoint(9).x = 0.0;
5215 Nodes.IntPoint(9).y = 0.5;
5216 Nodes.IntPoint(9).z = 0.5;
5217 }
5218
CalcShape(const IntegrationPoint & ip,Vector & shape) const5219 void RefinedLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
5220 Vector &shape) const
5221 {
5222 int i;
5223
5224 double L0, L1, L2, L3, L4, L5;
5225 L0 = 2.0 * ( 1. - ip.x - ip.y - ip.z );
5226 L1 = 2.0 * ( ip.x );
5227 L2 = 2.0 * ( ip.y );
5228 L3 = 2.0 * ( ip.z );
5229 L4 = 2.0 * ( ip.x + ip.y );
5230 L5 = 2.0 * ( ip.y + ip.z );
5231
5232 // The reference tetrahedron is split in 8 tetrahedra as follows:
5233 //
5234 // T0 - 0,4,5,6
5235 // T1 - 1,4,7,8
5236 // T2 - 2,5,7,9
5237 // T3 - 3,6,8,9
5238 // T4 - 4,5,6,8
5239 // T5 - 4,5,7,8
5240 // T6 - 5,6,8,9
5241 // T7 - 5,7,8,9
5242
5243 for (i = 0; i < 10; i++)
5244 {
5245 shape(i) = 0.0;
5246 }
5247
5248 if (L0 >= 1.0) // T0
5249 {
5250 shape(0) = L0 - 1.0;
5251 shape(4) = L1;
5252 shape(5) = L2;
5253 shape(6) = L3;
5254 }
5255 else if (L1 >= 1.0) // T1
5256 {
5257 shape(4) = L0;
5258 shape(1) = L1 - 1.0;
5259 shape(7) = L2;
5260 shape(8) = L3;
5261 }
5262 else if (L2 >= 1.0) // T2
5263 {
5264 shape(5) = L0;
5265 shape(7) = L1;
5266 shape(2) = L2 - 1.0;
5267 shape(9) = L3;
5268 }
5269 else if (L3 >= 1.0) // T3
5270 {
5271 shape(6) = L0;
5272 shape(8) = L1;
5273 shape(9) = L2;
5274 shape(3) = L3 - 1.0;
5275 }
5276 else if ((L4 <= 1.0) && (L5 <= 1.0)) // T4
5277 {
5278 shape(4) = 1.0 - L5;
5279 shape(5) = L2;
5280 shape(6) = 1.0 - L4;
5281 shape(8) = 1.0 - L0;
5282 }
5283 else if ((L4 >= 1.0) && (L5 <= 1.0)) // T5
5284 {
5285 shape(4) = 1.0 - L5;
5286 shape(5) = 1.0 - L1;
5287 shape(7) = L4 - 1.0;
5288 shape(8) = L3;
5289 }
5290 else if ((L4 <= 1.0) && (L5 >= 1.0)) // T6
5291 {
5292 shape(5) = 1.0 - L3;
5293 shape(6) = 1.0 - L4;
5294 shape(8) = L1;
5295 shape(9) = L5 - 1.0;
5296 }
5297 else if ((L4 >= 1.0) && (L5 >= 1.0)) // T7
5298 {
5299 shape(5) = L0;
5300 shape(7) = L4 - 1.0;
5301 shape(8) = 1.0 - L2;
5302 shape(9) = L5 - 1.0;
5303 }
5304 }
5305
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const5306 void RefinedLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
5307 DenseMatrix &dshape) const
5308 {
5309 int i,j;
5310
5311 double L0, L1, L2, L3, L4, L5;
5312 L0 = 2.0 * ( 1. - ip.x - ip.y - ip.z );
5313 L1 = 2.0 * ( ip.x );
5314 L2 = 2.0 * ( ip.y );
5315 L3 = 2.0 * ( ip.z );
5316 L4 = 2.0 * ( ip.x + ip.y );
5317 L5 = 2.0 * ( ip.y + ip.z );
5318
5319 double DL0[3], DL1[3], DL2[3], DL3[3], DL4[3], DL5[3];
5320 DL0[0] = -2.0; DL0[1] = -2.0; DL0[2] = -2.0;
5321 DL1[0] = 2.0; DL1[1] = 0.0; DL1[2] = 0.0;
5322 DL2[0] = 0.0; DL2[1] = 2.0; DL2[2] = 0.0;
5323 DL3[0] = 0.0; DL3[1] = 0.0; DL3[2] = 2.0;
5324 DL4[0] = 2.0; DL4[1] = 2.0; DL4[2] = 0.0;
5325 DL5[0] = 0.0; DL5[1] = 2.0; DL5[2] = 2.0;
5326
5327 for (i = 0; i < 10; i++)
5328 for (j = 0; j < 3; j++)
5329 {
5330 dshape(i,j) = 0.0;
5331 }
5332
5333 if (L0 >= 1.0) // T0
5334 {
5335 for (j = 0; j < 3; j++)
5336 {
5337 dshape(0,j) = DL0[j];
5338 dshape(4,j) = DL1[j];
5339 dshape(5,j) = DL2[j];
5340 dshape(6,j) = DL3[j];
5341 }
5342 }
5343 else if (L1 >= 1.0) // T1
5344 {
5345 for (j = 0; j < 3; j++)
5346 {
5347 dshape(4,j) = DL0[j];
5348 dshape(1,j) = DL1[j];
5349 dshape(7,j) = DL2[j];
5350 dshape(8,j) = DL3[j];
5351 }
5352 }
5353 else if (L2 >= 1.0) // T2
5354 {
5355 for (j = 0; j < 3; j++)
5356 {
5357 dshape(5,j) = DL0[j];
5358 dshape(7,j) = DL1[j];
5359 dshape(2,j) = DL2[j];
5360 dshape(9,j) = DL3[j];
5361 }
5362 }
5363 else if (L3 >= 1.0) // T3
5364 {
5365 for (j = 0; j < 3; j++)
5366 {
5367 dshape(6,j) = DL0[j];
5368 dshape(8,j) = DL1[j];
5369 dshape(9,j) = DL2[j];
5370 dshape(3,j) = DL3[j];
5371 }
5372 }
5373 else if ((L4 <= 1.0) && (L5 <= 1.0)) // T4
5374 {
5375 for (j = 0; j < 3; j++)
5376 {
5377 dshape(4,j) = - DL5[j];
5378 dshape(5,j) = DL2[j];
5379 dshape(6,j) = - DL4[j];
5380 dshape(8,j) = - DL0[j];
5381 }
5382 }
5383 else if ((L4 >= 1.0) && (L5 <= 1.0)) // T5
5384 {
5385 for (j = 0; j < 3; j++)
5386 {
5387 dshape(4,j) = - DL5[j];
5388 dshape(5,j) = - DL1[j];
5389 dshape(7,j) = DL4[j];
5390 dshape(8,j) = DL3[j];
5391 }
5392 }
5393 else if ((L4 <= 1.0) && (L5 >= 1.0)) // T6
5394 {
5395 for (j = 0; j < 3; j++)
5396 {
5397 dshape(5,j) = - DL3[j];
5398 dshape(6,j) = - DL4[j];
5399 dshape(8,j) = DL1[j];
5400 dshape(9,j) = DL5[j];
5401 }
5402 }
5403 else if ((L4 >= 1.0) && (L5 >= 1.0)) // T7
5404 {
5405 for (j = 0; j < 3; j++)
5406 {
5407 dshape(5,j) = DL0[j];
5408 dshape(7,j) = DL4[j];
5409 dshape(8,j) = - DL2[j];
5410 dshape(9,j) = DL5[j];
5411 }
5412 }
5413 }
5414
5415
RefinedBiLinear2DFiniteElement()5416 RefinedBiLinear2DFiniteElement::RefinedBiLinear2DFiniteElement()
5417 : NodalFiniteElement(2, Geometry::SQUARE, 9, 1, FunctionSpace::rQk)
5418 {
5419 Nodes.IntPoint(0).x = 0.0;
5420 Nodes.IntPoint(0).y = 0.0;
5421 Nodes.IntPoint(1).x = 1.0;
5422 Nodes.IntPoint(1).y = 0.0;
5423 Nodes.IntPoint(2).x = 1.0;
5424 Nodes.IntPoint(2).y = 1.0;
5425 Nodes.IntPoint(3).x = 0.0;
5426 Nodes.IntPoint(3).y = 1.0;
5427 Nodes.IntPoint(4).x = 0.5;
5428 Nodes.IntPoint(4).y = 0.0;
5429 Nodes.IntPoint(5).x = 1.0;
5430 Nodes.IntPoint(5).y = 0.5;
5431 Nodes.IntPoint(6).x = 0.5;
5432 Nodes.IntPoint(6).y = 1.0;
5433 Nodes.IntPoint(7).x = 0.0;
5434 Nodes.IntPoint(7).y = 0.5;
5435 Nodes.IntPoint(8).x = 0.5;
5436 Nodes.IntPoint(8).y = 0.5;
5437 }
5438
CalcShape(const IntegrationPoint & ip,Vector & shape) const5439 void RefinedBiLinear2DFiniteElement::CalcShape(const IntegrationPoint &ip,
5440 Vector &shape) const
5441 {
5442 int i;
5443 double x = ip.x, y = ip.y;
5444 double Lx, Ly;
5445 Lx = 2.0 * ( 1. - x );
5446 Ly = 2.0 * ( 1. - y );
5447
5448 // The reference square is split in 4 squares as follows:
5449 //
5450 // T0 - 0,4,7,8
5451 // T1 - 1,4,5,8
5452 // T2 - 2,5,6,8
5453 // T3 - 3,6,7,8
5454
5455 for (i = 0; i < 9; i++)
5456 {
5457 shape(i) = 0.0;
5458 }
5459
5460 if ((x <= 0.5) && (y <= 0.5)) // T0
5461 {
5462 shape(0) = (Lx - 1.0) * (Ly - 1.0);
5463 shape(4) = (2.0 - Lx) * (Ly - 1.0);
5464 shape(8) = (2.0 - Lx) * (2.0 - Ly);
5465 shape(7) = (Lx - 1.0) * (2.0 - Ly);
5466 }
5467 else if ((x >= 0.5) && (y <= 0.5)) // T1
5468 {
5469 shape(4) = Lx * (Ly - 1.0);
5470 shape(1) = (1.0 - Lx) * (Ly - 1.0);
5471 shape(5) = (1.0 - Lx) * (2.0 - Ly);
5472 shape(8) = Lx * (2.0 - Ly);
5473 }
5474 else if ((x >= 0.5) && (y >= 0.5)) // T2
5475 {
5476 shape(8) = Lx * Ly ;
5477 shape(5) = (1.0 - Lx) * Ly ;
5478 shape(2) = (1.0 - Lx) * (1.0 - Ly);
5479 shape(6) = Lx * (1.0 - Ly);
5480 }
5481 else if ((x <= 0.5) && (y >= 0.5)) // T3
5482 {
5483 shape(7) = (Lx - 1.0) * Ly ;
5484 shape(8) = (2.0 - Lx) * Ly ;
5485 shape(6) = (2.0 - Lx) * (1.0 - Ly);
5486 shape(3) = (Lx - 1.0) * (1.0 - Ly);
5487 }
5488 }
5489
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const5490 void RefinedBiLinear2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
5491 DenseMatrix &dshape) const
5492 {
5493 int i,j;
5494 double x = ip.x, y = ip.y;
5495 double Lx, Ly;
5496 Lx = 2.0 * ( 1. - x );
5497 Ly = 2.0 * ( 1. - y );
5498
5499 for (i = 0; i < 9; i++)
5500 for (j = 0; j < 2; j++)
5501 {
5502 dshape(i,j) = 0.0;
5503 }
5504
5505 if ((x <= 0.5) && (y <= 0.5)) // T0
5506 {
5507 dshape(0,0) = 2.0 * (1.0 - Ly);
5508 dshape(0,1) = 2.0 * (1.0 - Lx);
5509
5510 dshape(4,0) = 2.0 * (Ly - 1.0);
5511 dshape(4,1) = -2.0 * (2.0 - Lx);
5512
5513 dshape(8,0) = 2.0 * (2.0 - Ly);
5514 dshape(8,1) = 2.0 * (2.0 - Lx);
5515
5516 dshape(7,0) = -2.0 * (2.0 - Ly);
5517 dshape(7,0) = 2.0 * (Lx - 1.0);
5518 }
5519 else if ((x >= 0.5) && (y <= 0.5)) // T1
5520 {
5521 dshape(4,0) = -2.0 * (Ly - 1.0);
5522 dshape(4,1) = -2.0 * Lx;
5523
5524 dshape(1,0) = 2.0 * (Ly - 1.0);
5525 dshape(1,1) = -2.0 * (1.0 - Lx);
5526
5527 dshape(5,0) = 2.0 * (2.0 - Ly);
5528 dshape(5,1) = 2.0 * (1.0 - Lx);
5529
5530 dshape(8,0) = -2.0 * (2.0 - Ly);
5531 dshape(8,1) = 2.0 * Lx;
5532 }
5533 else if ((x >= 0.5) && (y >= 0.5)) // T2
5534 {
5535 dshape(8,0) = -2.0 * Ly;
5536 dshape(8,1) = -2.0 * Lx;
5537
5538 dshape(5,0) = 2.0 * Ly;
5539 dshape(5,1) = -2.0 * (1.0 - Lx);
5540
5541 dshape(2,0) = 2.0 * (1.0 - Ly);
5542 dshape(2,1) = 2.0 * (1.0 - Lx);
5543
5544 dshape(6,0) = -2.0 * (1.0 - Ly);
5545 dshape(6,1) = 2.0 * Lx;
5546 }
5547 else if ((x <= 0.5) && (y >= 0.5)) // T3
5548 {
5549 dshape(7,0) = -2.0 * Ly;
5550 dshape(7,1) = -2.0 * (Lx - 1.0);
5551
5552 dshape(8,0) = 2.0 * Ly ;
5553 dshape(8,1) = -2.0 * (2.0 - Lx);
5554
5555 dshape(6,0) = 2.0 * (1.0 - Ly);
5556 dshape(6,1) = 2.0 * (2.0 - Lx);
5557
5558 dshape(3,0) = -2.0 * (1.0 - Ly);
5559 dshape(3,1) = 2.0 * (Lx - 1.0);
5560 }
5561 }
5562
RefinedTriLinear3DFiniteElement()5563 RefinedTriLinear3DFiniteElement::RefinedTriLinear3DFiniteElement()
5564 : NodalFiniteElement(3, Geometry::CUBE, 27, 2, FunctionSpace::rQk)
5565 {
5566 double I[27];
5567 double J[27];
5568 double K[27];
5569 // nodes
5570 I[ 0] = 0.0; J[ 0] = 0.0; K[ 0] = 0.0;
5571 I[ 1] = 1.0; J[ 1] = 0.0; K[ 1] = 0.0;
5572 I[ 2] = 1.0; J[ 2] = 1.0; K[ 2] = 0.0;
5573 I[ 3] = 0.0; J[ 3] = 1.0; K[ 3] = 0.0;
5574 I[ 4] = 0.0; J[ 4] = 0.0; K[ 4] = 1.0;
5575 I[ 5] = 1.0; J[ 5] = 0.0; K[ 5] = 1.0;
5576 I[ 6] = 1.0; J[ 6] = 1.0; K[ 6] = 1.0;
5577 I[ 7] = 0.0; J[ 7] = 1.0; K[ 7] = 1.0;
5578 // edges
5579 I[ 8] = 0.5; J[ 8] = 0.0; K[ 8] = 0.0;
5580 I[ 9] = 1.0; J[ 9] = 0.5; K[ 9] = 0.0;
5581 I[10] = 0.5; J[10] = 1.0; K[10] = 0.0;
5582 I[11] = 0.0; J[11] = 0.5; K[11] = 0.0;
5583 I[12] = 0.5; J[12] = 0.0; K[12] = 1.0;
5584 I[13] = 1.0; J[13] = 0.5; K[13] = 1.0;
5585 I[14] = 0.5; J[14] = 1.0; K[14] = 1.0;
5586 I[15] = 0.0; J[15] = 0.5; K[15] = 1.0;
5587 I[16] = 0.0; J[16] = 0.0; K[16] = 0.5;
5588 I[17] = 1.0; J[17] = 0.0; K[17] = 0.5;
5589 I[18] = 1.0; J[18] = 1.0; K[18] = 0.5;
5590 I[19] = 0.0; J[19] = 1.0; K[19] = 0.5;
5591 // faces
5592 I[20] = 0.5; J[20] = 0.5; K[20] = 0.0;
5593 I[21] = 0.5; J[21] = 0.0; K[21] = 0.5;
5594 I[22] = 1.0; J[22] = 0.5; K[22] = 0.5;
5595 I[23] = 0.5; J[23] = 1.0; K[23] = 0.5;
5596 I[24] = 0.0; J[24] = 0.5; K[24] = 0.5;
5597 I[25] = 0.5; J[25] = 0.5; K[25] = 1.0;
5598 // element
5599 I[26] = 0.5; J[26] = 0.5; K[26] = 0.5;
5600
5601 for (int n = 0; n < 27; n++)
5602 {
5603 Nodes.IntPoint(n).x = I[n];
5604 Nodes.IntPoint(n).y = J[n];
5605 Nodes.IntPoint(n).z = K[n];
5606 }
5607 }
5608
CalcShape(const IntegrationPoint & ip,Vector & shape) const5609 void RefinedTriLinear3DFiniteElement::CalcShape(const IntegrationPoint &ip,
5610 Vector &shape) const
5611 {
5612 int i, N[8];
5613 double Lx, Ly, Lz;
5614 double x = ip.x, y = ip.y, z = ip.z;
5615
5616 for (i = 0; i < 27; i++)
5617 {
5618 shape(i) = 0.0;
5619 }
5620
5621 if ((x <= 0.5) && (y <= 0.5) && (z <= 0.5)) // T0
5622 {
5623 Lx = 1.0 - 2.0 * x;
5624 Ly = 1.0 - 2.0 * y;
5625 Lz = 1.0 - 2.0 * z;
5626
5627 N[0] = 0;
5628 N[1] = 8;
5629 N[2] = 20;
5630 N[3] = 11;
5631 N[4] = 16;
5632 N[5] = 21;
5633 N[6] = 26;
5634 N[7] = 24;
5635 }
5636 else if ((x >= 0.5) && (y <= 0.5) && (z <= 0.5)) // T1
5637 {
5638 Lx = 2.0 - 2.0 * x;
5639 Ly = 1.0 - 2.0 * y;
5640 Lz = 1.0 - 2.0 * z;
5641
5642 N[0] = 8;
5643 N[1] = 1;
5644 N[2] = 9;
5645 N[3] = 20;
5646 N[4] = 21;
5647 N[5] = 17;
5648 N[6] = 22;
5649 N[7] = 26;
5650 }
5651 else if ((x <= 0.5) && (y >= 0.5) && (z <= 0.5)) // T2
5652 {
5653 Lx = 2.0 - 2.0 * x;
5654 Ly = 2.0 - 2.0 * y;
5655 Lz = 1.0 - 2.0 * z;
5656
5657 N[0] = 20;
5658 N[1] = 9;
5659 N[2] = 2;
5660 N[3] = 10;
5661 N[4] = 26;
5662 N[5] = 22;
5663 N[6] = 18;
5664 N[7] = 23;
5665 }
5666 else if ((x >= 0.5) && (y >= 0.5) && (z <= 0.5)) // T3
5667 {
5668 Lx = 1.0 - 2.0 * x;
5669 Ly = 2.0 - 2.0 * y;
5670 Lz = 1.0 - 2.0 * z;
5671
5672 N[0] = 11;
5673 N[1] = 20;
5674 N[2] = 10;
5675 N[3] = 3;
5676 N[4] = 24;
5677 N[5] = 26;
5678 N[6] = 23;
5679 N[7] = 19;
5680 }
5681 else if ((x <= 0.5) && (y <= 0.5) && (z >= 0.5)) // T4
5682 {
5683 Lx = 1.0 - 2.0 * x;
5684 Ly = 1.0 - 2.0 * y;
5685 Lz = 2.0 - 2.0 * z;
5686
5687 N[0] = 16;
5688 N[1] = 21;
5689 N[2] = 26;
5690 N[3] = 24;
5691 N[4] = 4;
5692 N[5] = 12;
5693 N[6] = 25;
5694 N[7] = 15;
5695 }
5696 else if ((x >= 0.5) && (y <= 0.5) && (z >= 0.5)) // T5
5697 {
5698 Lx = 2.0 - 2.0 * x;
5699 Ly = 1.0 - 2.0 * y;
5700 Lz = 2.0 - 2.0 * z;
5701
5702 N[0] = 21;
5703 N[1] = 17;
5704 N[2] = 22;
5705 N[3] = 26;
5706 N[4] = 12;
5707 N[5] = 5;
5708 N[6] = 13;
5709 N[7] = 25;
5710 }
5711 else if ((x <= 0.5) && (y >= 0.5) && (z >= 0.5)) // T6
5712 {
5713 Lx = 2.0 - 2.0 * x;
5714 Ly = 2.0 - 2.0 * y;
5715 Lz = 2.0 - 2.0 * z;
5716
5717 N[0] = 26;
5718 N[1] = 22;
5719 N[2] = 18;
5720 N[3] = 23;
5721 N[4] = 25;
5722 N[5] = 13;
5723 N[6] = 6;
5724 N[7] = 14;
5725 }
5726 else // T7
5727 {
5728 Lx = 1.0 - 2.0 * x;
5729 Ly = 2.0 - 2.0 * y;
5730 Lz = 2.0 - 2.0 * z;
5731
5732 N[0] = 24;
5733 N[1] = 26;
5734 N[2] = 23;
5735 N[3] = 19;
5736 N[4] = 15;
5737 N[5] = 25;
5738 N[6] = 14;
5739 N[7] = 7;
5740 }
5741
5742 shape(N[0]) = Lx * Ly * Lz;
5743 shape(N[1]) = (1 - Lx) * Ly * Lz;
5744 shape(N[2]) = (1 - Lx) * (1 - Ly) * Lz;
5745 shape(N[3]) = Lx * (1 - Ly) * Lz;
5746 shape(N[4]) = Lx * Ly * (1 - Lz);
5747 shape(N[5]) = (1 - Lx) * Ly * (1 - Lz);
5748 shape(N[6]) = (1 - Lx) * (1 - Ly) * (1 - Lz);
5749 shape(N[7]) = Lx * (1 - Ly) * (1 - Lz);
5750 }
5751
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const5752 void RefinedTriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
5753 DenseMatrix &dshape) const
5754 {
5755 int i, j, N[8];
5756 double Lx, Ly, Lz;
5757 double x = ip.x, y = ip.y, z = ip.z;
5758
5759 for (i = 0; i < 27; i++)
5760 for (j = 0; j < 3; j++)
5761 {
5762 dshape(i,j) = 0.0;
5763 }
5764
5765 if ((x <= 0.5) && (y <= 0.5) && (z <= 0.5)) // T0
5766 {
5767 Lx = 1.0 - 2.0 * x;
5768 Ly = 1.0 - 2.0 * y;
5769 Lz = 1.0 - 2.0 * z;
5770
5771 N[0] = 0;
5772 N[1] = 8;
5773 N[2] = 20;
5774 N[3] = 11;
5775 N[4] = 16;
5776 N[5] = 21;
5777 N[6] = 26;
5778 N[7] = 24;
5779 }
5780 else if ((x >= 0.5) && (y <= 0.5) && (z <= 0.5)) // T1
5781 {
5782 Lx = 2.0 - 2.0 * x;
5783 Ly = 1.0 - 2.0 * y;
5784 Lz = 1.0 - 2.0 * z;
5785
5786 N[0] = 8;
5787 N[1] = 1;
5788 N[2] = 9;
5789 N[3] = 20;
5790 N[4] = 21;
5791 N[5] = 17;
5792 N[6] = 22;
5793 N[7] = 26;
5794 }
5795 else if ((x <= 0.5) && (y >= 0.5) && (z <= 0.5)) // T2
5796 {
5797 Lx = 2.0 - 2.0 * x;
5798 Ly = 2.0 - 2.0 * y;
5799 Lz = 1.0 - 2.0 * z;
5800
5801 N[0] = 20;
5802 N[1] = 9;
5803 N[2] = 2;
5804 N[3] = 10;
5805 N[4] = 26;
5806 N[5] = 22;
5807 N[6] = 18;
5808 N[7] = 23;
5809 }
5810 else if ((x >= 0.5) && (y >= 0.5) && (z <= 0.5)) // T3
5811 {
5812 Lx = 1.0 - 2.0 * x;
5813 Ly = 2.0 - 2.0 * y;
5814 Lz = 1.0 - 2.0 * z;
5815
5816 N[0] = 11;
5817 N[1] = 20;
5818 N[2] = 10;
5819 N[3] = 3;
5820 N[4] = 24;
5821 N[5] = 26;
5822 N[6] = 23;
5823 N[7] = 19;
5824 }
5825 else if ((x <= 0.5) && (y <= 0.5) && (z >= 0.5)) // T4
5826 {
5827 Lx = 1.0 - 2.0 * x;
5828 Ly = 1.0 - 2.0 * y;
5829 Lz = 2.0 - 2.0 * z;
5830
5831 N[0] = 16;
5832 N[1] = 21;
5833 N[2] = 26;
5834 N[3] = 24;
5835 N[4] = 4;
5836 N[5] = 12;
5837 N[6] = 25;
5838 N[7] = 15;
5839 }
5840 else if ((x >= 0.5) && (y <= 0.5) && (z >= 0.5)) // T5
5841 {
5842 Lx = 2.0 - 2.0 * x;
5843 Ly = 1.0 - 2.0 * y;
5844 Lz = 2.0 - 2.0 * z;
5845
5846 N[0] = 21;
5847 N[1] = 17;
5848 N[2] = 22;
5849 N[3] = 26;
5850 N[4] = 12;
5851 N[5] = 5;
5852 N[6] = 13;
5853 N[7] = 25;
5854 }
5855 else if ((x <= 0.5) && (y >= 0.5) && (z >= 0.5)) // T6
5856 {
5857 Lx = 2.0 - 2.0 * x;
5858 Ly = 2.0 - 2.0 * y;
5859 Lz = 2.0 - 2.0 * z;
5860
5861 N[0] = 26;
5862 N[1] = 22;
5863 N[2] = 18;
5864 N[3] = 23;
5865 N[4] = 25;
5866 N[5] = 13;
5867 N[6] = 6;
5868 N[7] = 14;
5869 }
5870 else // T7
5871 {
5872 Lx = 1.0 - 2.0 * x;
5873 Ly = 2.0 - 2.0 * y;
5874 Lz = 2.0 - 2.0 * z;
5875
5876 N[0] = 24;
5877 N[1] = 26;
5878 N[2] = 23;
5879 N[3] = 19;
5880 N[4] = 15;
5881 N[5] = 25;
5882 N[6] = 14;
5883 N[7] = 7;
5884 }
5885
5886 dshape(N[0],0) = -2.0 * Ly * Lz ;
5887 dshape(N[0],1) = -2.0 * Lx * Lz ;
5888 dshape(N[0],2) = -2.0 * Lx * Ly ;
5889
5890 dshape(N[1],0) = 2.0 * Ly * Lz ;
5891 dshape(N[1],1) = -2.0 * (1 - Lx) * Lz ;
5892 dshape(N[1],2) = -2.0 * (1 - Lx) * Ly ;
5893
5894 dshape(N[2],0) = 2.0 * (1 - Ly) * Lz ;
5895 dshape(N[2],1) = 2.0 * (1 - Lx) * Lz ;
5896 dshape(N[2],2) = -2.0 * (1 - Lx) * (1 - Ly);
5897
5898 dshape(N[3],0) = -2.0 * (1 - Ly) * Lz ;
5899 dshape(N[3],1) = 2.0 * Lx * Lz ;
5900 dshape(N[3],2) = -2.0 * Lx * (1 - Ly);
5901
5902 dshape(N[4],0) = -2.0 * Ly * (1 - Lz);
5903 dshape(N[4],1) = -2.0 * Lx * (1 - Lz);
5904 dshape(N[4],2) = 2.0 * Lx * Ly ;
5905
5906 dshape(N[5],0) = 2.0 * Ly * (1 - Lz);
5907 dshape(N[5],1) = -2.0 * (1 - Lx) * (1 - Lz);
5908 dshape(N[5],2) = 2.0 * (1 - Lx) * Ly ;
5909
5910 dshape(N[6],0) = 2.0 * (1 - Ly) * (1 - Lz);
5911 dshape(N[6],1) = 2.0 * (1 - Lx) * (1 - Lz);
5912 dshape(N[6],2) = 2.0 * (1 - Lx) * (1 - Ly);
5913
5914 dshape(N[7],0) = -2.0 * (1 - Ly) * (1 - Lz);
5915 dshape(N[7],1) = 2.0 * Lx * (1 - Lz);
5916 dshape(N[7],2) = 2.0 * Lx * (1 - Ly);
5917 }
5918
5919
Nedelec1HexFiniteElement()5920 Nedelec1HexFiniteElement::Nedelec1HexFiniteElement()
5921 : VectorFiniteElement(3, Geometry::CUBE, 12, 1, H_CURL, FunctionSpace::Qk)
5922 {
5923 // not real nodes ...
5924 Nodes.IntPoint(0).x = 0.5;
5925 Nodes.IntPoint(0).y = 0.0;
5926 Nodes.IntPoint(0).z = 0.0;
5927
5928 Nodes.IntPoint(1).x = 1.0;
5929 Nodes.IntPoint(1).y = 0.5;
5930 Nodes.IntPoint(1).z = 0.0;
5931
5932 Nodes.IntPoint(2).x = 0.5;
5933 Nodes.IntPoint(2).y = 1.0;
5934 Nodes.IntPoint(2).z = 0.0;
5935
5936 Nodes.IntPoint(3).x = 0.0;
5937 Nodes.IntPoint(3).y = 0.5;
5938 Nodes.IntPoint(3).z = 0.0;
5939
5940 Nodes.IntPoint(4).x = 0.5;
5941 Nodes.IntPoint(4).y = 0.0;
5942 Nodes.IntPoint(4).z = 1.0;
5943
5944 Nodes.IntPoint(5).x = 1.0;
5945 Nodes.IntPoint(5).y = 0.5;
5946 Nodes.IntPoint(5).z = 1.0;
5947
5948 Nodes.IntPoint(6).x = 0.5;
5949 Nodes.IntPoint(6).y = 1.0;
5950 Nodes.IntPoint(6).z = 1.0;
5951
5952 Nodes.IntPoint(7).x = 0.0;
5953 Nodes.IntPoint(7).y = 0.5;
5954 Nodes.IntPoint(7).z = 1.0;
5955
5956 Nodes.IntPoint(8).x = 0.0;
5957 Nodes.IntPoint(8).y = 0.0;
5958 Nodes.IntPoint(8).z = 0.5;
5959
5960 Nodes.IntPoint(9).x = 1.0;
5961 Nodes.IntPoint(9).y = 0.0;
5962 Nodes.IntPoint(9).z = 0.5;
5963
5964 Nodes.IntPoint(10).x= 1.0;
5965 Nodes.IntPoint(10).y= 1.0;
5966 Nodes.IntPoint(10).z= 0.5;
5967
5968 Nodes.IntPoint(11).x= 0.0;
5969 Nodes.IntPoint(11).y= 1.0;
5970 Nodes.IntPoint(11).z= 0.5;
5971 }
5972
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const5973 void Nedelec1HexFiniteElement::CalcVShape(const IntegrationPoint &ip,
5974 DenseMatrix &shape) const
5975 {
5976 double x = ip.x, y = ip.y, z = ip.z;
5977
5978 shape(0,0) = (1. - y) * (1. - z);
5979 shape(0,1) = 0.;
5980 shape(0,2) = 0.;
5981
5982 shape(2,0) = y * (1. - z);
5983 shape(2,1) = 0.;
5984 shape(2,2) = 0.;
5985
5986 shape(4,0) = z * (1. - y);
5987 shape(4,1) = 0.;
5988 shape(4,2) = 0.;
5989
5990 shape(6,0) = y * z;
5991 shape(6,1) = 0.;
5992 shape(6,2) = 0.;
5993
5994 shape(1,0) = 0.;
5995 shape(1,1) = x * (1. - z);
5996 shape(1,2) = 0.;
5997
5998 shape(3,0) = 0.;
5999 shape(3,1) = (1. - x) * (1. - z);
6000 shape(3,2) = 0.;
6001
6002 shape(5,0) = 0.;
6003 shape(5,1) = x * z;
6004 shape(5,2) = 0.;
6005
6006 shape(7,0) = 0.;
6007 shape(7,1) = (1. - x) * z;
6008 shape(7,2) = 0.;
6009
6010 shape(8,0) = 0.;
6011 shape(8,1) = 0.;
6012 shape(8,2) = (1. - x) * (1. - y);
6013
6014 shape(9,0) = 0.;
6015 shape(9,1) = 0.;
6016 shape(9,2) = x * (1. - y);
6017
6018 shape(10,0) = 0.;
6019 shape(10,1) = 0.;
6020 shape(10,2) = x * y;
6021
6022 shape(11,0) = 0.;
6023 shape(11,1) = 0.;
6024 shape(11,2) = y * (1. - x);
6025
6026 }
6027
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const6028 void Nedelec1HexFiniteElement::CalcCurlShape(const IntegrationPoint &ip,
6029 DenseMatrix &curl_shape)
6030 const
6031 {
6032 double x = ip.x, y = ip.y, z = ip.z;
6033
6034 curl_shape(0,0) = 0.;
6035 curl_shape(0,1) = y - 1.;
6036 curl_shape(0,2) = 1. - z;
6037
6038 curl_shape(2,0) = 0.;
6039 curl_shape(2,1) = -y;
6040 curl_shape(2,2) = z - 1.;
6041
6042 curl_shape(4,0) = 0;
6043 curl_shape(4,1) = 1. - y;
6044 curl_shape(4,2) = z;
6045
6046 curl_shape(6,0) = 0.;
6047 curl_shape(6,1) = y;
6048 curl_shape(6,2) = -z;
6049
6050 curl_shape(1,0) = x;
6051 curl_shape(1,1) = 0.;
6052 curl_shape(1,2) = 1. - z;
6053
6054 curl_shape(3,0) = 1. - x;
6055 curl_shape(3,1) = 0.;
6056 curl_shape(3,2) = z - 1.;
6057
6058 curl_shape(5,0) = -x;
6059 curl_shape(5,1) = 0.;
6060 curl_shape(5,2) = z;
6061
6062 curl_shape(7,0) = x - 1.;
6063 curl_shape(7,1) = 0.;
6064 curl_shape(7,2) = -z;
6065
6066 curl_shape(8,0) = x - 1.;
6067 curl_shape(8,1) = 1. - y;
6068 curl_shape(8,2) = 0.;
6069
6070 curl_shape(9,0) = -x;
6071 curl_shape(9,1) = y - 1.;
6072 curl_shape(9,2) = 0;
6073
6074 curl_shape(10,0) = x;
6075 curl_shape(10,1) = -y;
6076 curl_shape(10,2) = 0.;
6077
6078 curl_shape(11,0) = 1. - x;
6079 curl_shape(11,1) = y;
6080 curl_shape(11,2) = 0.;
6081 }
6082
6083 const double Nedelec1HexFiniteElement::tk[12][3] =
6084 {
6085 {1,0,0}, {0,1,0}, {1,0,0}, {0,1,0},
6086 {1,0,0}, {0,1,0}, {1,0,0}, {0,1,0},
6087 {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}
6088 };
6089
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const6090 void Nedelec1HexFiniteElement::GetLocalInterpolation (
6091 ElementTransformation &Trans, DenseMatrix &I) const
6092 {
6093 int k, j;
6094 #ifdef MFEM_THREAD_SAFE
6095 DenseMatrix vshape(dof, dim);
6096 #endif
6097
6098 #ifdef MFEM_DEBUG
6099 for (k = 0; k < 12; k++)
6100 {
6101 CalcVShape (Nodes.IntPoint(k), vshape);
6102 for (j = 0; j < 12; j++)
6103 {
6104 double d = ( vshape(j,0)*tk[k][0] + vshape(j,1)*tk[k][1] +
6105 vshape(j,2)*tk[k][2] );
6106 if (j == k) { d -= 1.0; }
6107 if (fabs(d) > 1.0e-12)
6108 {
6109 mfem::err << "Nedelec1HexFiniteElement::GetLocalInterpolation (...)\n"
6110 " k = " << k << ", j = " << j << ", d = " << d << endl;
6111 mfem_error();
6112 }
6113 }
6114 }
6115 #endif
6116
6117 IntegrationPoint ip;
6118 ip.x = ip.y = ip.z = 0.0;
6119 Trans.SetIntPoint (&ip);
6120 // Trans must be linear (more to have embedding?)
6121 const DenseMatrix &J = Trans.Jacobian();
6122 double vk[3];
6123 Vector xk (vk, 3);
6124
6125 for (k = 0; k < 12; k++)
6126 {
6127 Trans.Transform (Nodes.IntPoint (k), xk);
6128 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
6129 CalcVShape (ip, vshape);
6130 // vk = J tk
6131 vk[0] = J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2];
6132 vk[1] = J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2];
6133 vk[2] = J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2];
6134 for (j = 0; j < 12; j++)
6135 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
6136 vshape(j,2)*vk[2])) < 1.0e-12)
6137 {
6138 I(k,j) = 0.0;
6139 }
6140 }
6141 }
6142
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const6143 void Nedelec1HexFiniteElement::Project (
6144 VectorCoefficient &vc, ElementTransformation &Trans,
6145 Vector &dofs) const
6146 {
6147 double vk[3];
6148 Vector xk (vk, 3);
6149
6150 for (int k = 0; k < 12; k++)
6151 {
6152 Trans.SetIntPoint (&Nodes.IntPoint (k));
6153 const DenseMatrix &J = Trans.Jacobian();
6154
6155 vc.Eval (xk, Trans, Nodes.IntPoint (k));
6156 // xk^t J tk
6157 dofs(k) =
6158 vk[0] * ( J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2] ) +
6159 vk[1] * ( J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2] ) +
6160 vk[2] * ( J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2] );
6161 }
6162 }
6163
6164
Nedelec1TetFiniteElement()6165 Nedelec1TetFiniteElement::Nedelec1TetFiniteElement()
6166 : VectorFiniteElement(3, Geometry::TETRAHEDRON, 6, 1, H_CURL)
6167 {
6168 // not real nodes ...
6169 Nodes.IntPoint(0).x = 0.5;
6170 Nodes.IntPoint(0).y = 0.0;
6171 Nodes.IntPoint(0).z = 0.0;
6172
6173 Nodes.IntPoint(1).x = 0.0;
6174 Nodes.IntPoint(1).y = 0.5;
6175 Nodes.IntPoint(1).z = 0.0;
6176
6177 Nodes.IntPoint(2).x = 0.0;
6178 Nodes.IntPoint(2).y = 0.0;
6179 Nodes.IntPoint(2).z = 0.5;
6180
6181 Nodes.IntPoint(3).x = 0.5;
6182 Nodes.IntPoint(3).y = 0.5;
6183 Nodes.IntPoint(3).z = 0.0;
6184
6185 Nodes.IntPoint(4).x = 0.5;
6186 Nodes.IntPoint(4).y = 0.0;
6187 Nodes.IntPoint(4).z = 0.5;
6188
6189 Nodes.IntPoint(5).x = 0.0;
6190 Nodes.IntPoint(5).y = 0.5;
6191 Nodes.IntPoint(5).z = 0.5;
6192 }
6193
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const6194 void Nedelec1TetFiniteElement::CalcVShape(const IntegrationPoint &ip,
6195 DenseMatrix &shape) const
6196 {
6197 double x = ip.x, y = ip.y, z = ip.z;
6198
6199 shape(0,0) = 1. - y - z;
6200 shape(0,1) = x;
6201 shape(0,2) = x;
6202
6203 shape(1,0) = y;
6204 shape(1,1) = 1. - x - z;
6205 shape(1,2) = y;
6206
6207 shape(2,0) = z;
6208 shape(2,1) = z;
6209 shape(2,2) = 1. - x - y;
6210
6211 shape(3,0) = -y;
6212 shape(3,1) = x;
6213 shape(3,2) = 0.;
6214
6215 shape(4,0) = -z;
6216 shape(4,1) = 0.;
6217 shape(4,2) = x;
6218
6219 shape(5,0) = 0.;
6220 shape(5,1) = -z;
6221 shape(5,2) = y;
6222 }
6223
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const6224 void Nedelec1TetFiniteElement::CalcCurlShape(const IntegrationPoint &ip,
6225 DenseMatrix &curl_shape)
6226 const
6227 {
6228 curl_shape(0,0) = 0.;
6229 curl_shape(0,1) = -2.;
6230 curl_shape(0,2) = 2.;
6231
6232 curl_shape(1,0) = 2.;
6233 curl_shape(1,1) = 0.;
6234 curl_shape(1,2) = -2.;
6235
6236 curl_shape(2,0) = -2.;
6237 curl_shape(2,1) = 2.;
6238 curl_shape(2,2) = 0.;
6239
6240 curl_shape(3,0) = 0.;
6241 curl_shape(3,1) = 0.;
6242 curl_shape(3,2) = 2.;
6243
6244 curl_shape(4,0) = 0.;
6245 curl_shape(4,1) = -2.;
6246 curl_shape(4,2) = 0.;
6247
6248 curl_shape(5,0) = 2.;
6249 curl_shape(5,1) = 0.;
6250 curl_shape(5,2) = 0.;
6251 }
6252
6253 const double Nedelec1TetFiniteElement::tk[6][3] =
6254 {{1,0,0}, {0,1,0}, {0,0,1}, {-1,1,0}, {-1,0,1}, {0,-1,1}};
6255
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const6256 void Nedelec1TetFiniteElement::GetLocalInterpolation (
6257 ElementTransformation &Trans, DenseMatrix &I) const
6258 {
6259 int k, j;
6260 #ifdef MFEM_THREAD_SAFE
6261 DenseMatrix vshape(dof, dim);
6262 #endif
6263
6264 #ifdef MFEM_DEBUG
6265 for (k = 0; k < 6; k++)
6266 {
6267 CalcVShape (Nodes.IntPoint(k), vshape);
6268 for (j = 0; j < 6; j++)
6269 {
6270 double d = ( vshape(j,0)*tk[k][0] + vshape(j,1)*tk[k][1] +
6271 vshape(j,2)*tk[k][2] );
6272 if (j == k) { d -= 1.0; }
6273 if (fabs(d) > 1.0e-12)
6274 {
6275 mfem::err << "Nedelec1TetFiniteElement::GetLocalInterpolation (...)\n"
6276 " k = " << k << ", j = " << j << ", d = " << d << endl;
6277 mfem_error();
6278 }
6279 }
6280 }
6281 #endif
6282
6283 IntegrationPoint ip;
6284 ip.x = ip.y = ip.z = 0.0;
6285 Trans.SetIntPoint (&ip);
6286 // Trans must be linear
6287 const DenseMatrix &J = Trans.Jacobian();
6288 double vk[3];
6289 Vector xk (vk, 3);
6290
6291 for (k = 0; k < 6; k++)
6292 {
6293 Trans.Transform (Nodes.IntPoint (k), xk);
6294 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
6295 CalcVShape (ip, vshape);
6296 // vk = J tk
6297 vk[0] = J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2];
6298 vk[1] = J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2];
6299 vk[2] = J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2];
6300 for (j = 0; j < 6; j++)
6301 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
6302 vshape(j,2)*vk[2])) < 1.0e-12)
6303 {
6304 I(k,j) = 0.0;
6305 }
6306 }
6307 }
6308
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const6309 void Nedelec1TetFiniteElement::Project (
6310 VectorCoefficient &vc, ElementTransformation &Trans,
6311 Vector &dofs) const
6312 {
6313 double vk[3];
6314 Vector xk (vk, 3);
6315
6316 for (int k = 0; k < 6; k++)
6317 {
6318 Trans.SetIntPoint (&Nodes.IntPoint (k));
6319 const DenseMatrix &J = Trans.Jacobian();
6320
6321 vc.Eval (xk, Trans, Nodes.IntPoint (k));
6322 // xk^t J tk
6323 dofs(k) =
6324 vk[0] * ( J(0,0)*tk[k][0]+J(0,1)*tk[k][1]+J(0,2)*tk[k][2] ) +
6325 vk[1] * ( J(1,0)*tk[k][0]+J(1,1)*tk[k][1]+J(1,2)*tk[k][2] ) +
6326 vk[2] * ( J(2,0)*tk[k][0]+J(2,1)*tk[k][1]+J(2,2)*tk[k][2] );
6327 }
6328 }
6329
RT0HexFiniteElement()6330 RT0HexFiniteElement::RT0HexFiniteElement()
6331 : VectorFiniteElement(3, Geometry::CUBE, 6, 1, H_DIV, FunctionSpace::Qk)
6332 {
6333 // not real nodes ...
6334 // z = 0, y = 0, x = 1, y = 1, x = 0, z = 1
6335 Nodes.IntPoint(0).x = 0.5;
6336 Nodes.IntPoint(0).y = 0.5;
6337 Nodes.IntPoint(0).z = 0.0;
6338
6339 Nodes.IntPoint(1).x = 0.5;
6340 Nodes.IntPoint(1).y = 0.0;
6341 Nodes.IntPoint(1).z = 0.5;
6342
6343 Nodes.IntPoint(2).x = 1.0;
6344 Nodes.IntPoint(2).y = 0.5;
6345 Nodes.IntPoint(2).z = 0.5;
6346
6347 Nodes.IntPoint(3).x = 0.5;
6348 Nodes.IntPoint(3).y = 1.0;
6349 Nodes.IntPoint(3).z = 0.5;
6350
6351 Nodes.IntPoint(4).x = 0.0;
6352 Nodes.IntPoint(4).y = 0.5;
6353 Nodes.IntPoint(4).z = 0.5;
6354
6355 Nodes.IntPoint(5).x = 0.5;
6356 Nodes.IntPoint(5).y = 0.5;
6357 Nodes.IntPoint(5).z = 1.0;
6358 }
6359
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const6360 void RT0HexFiniteElement::CalcVShape(const IntegrationPoint &ip,
6361 DenseMatrix &shape) const
6362 {
6363 double x = ip.x, y = ip.y, z = ip.z;
6364 // z = 0
6365 shape(0,0) = 0.;
6366 shape(0,1) = 0.;
6367 shape(0,2) = z - 1.;
6368 // y = 0
6369 shape(1,0) = 0.;
6370 shape(1,1) = y - 1.;
6371 shape(1,2) = 0.;
6372 // x = 1
6373 shape(2,0) = x;
6374 shape(2,1) = 0.;
6375 shape(2,2) = 0.;
6376 // y = 1
6377 shape(3,0) = 0.;
6378 shape(3,1) = y;
6379 shape(3,2) = 0.;
6380 // x = 0
6381 shape(4,0) = x - 1.;
6382 shape(4,1) = 0.;
6383 shape(4,2) = 0.;
6384 // z = 1
6385 shape(5,0) = 0.;
6386 shape(5,1) = 0.;
6387 shape(5,2) = z;
6388 }
6389
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const6390 void RT0HexFiniteElement::CalcDivShape(const IntegrationPoint &ip,
6391 Vector &divshape) const
6392 {
6393 divshape(0) = 1.;
6394 divshape(1) = 1.;
6395 divshape(2) = 1.;
6396 divshape(3) = 1.;
6397 divshape(4) = 1.;
6398 divshape(5) = 1.;
6399 }
6400
6401 const double RT0HexFiniteElement::nk[6][3] =
6402 {{0,0,-1}, {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0}, {0,0,1}};
6403
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const6404 void RT0HexFiniteElement::GetLocalInterpolation (
6405 ElementTransformation &Trans, DenseMatrix &I) const
6406 {
6407 int k, j;
6408 #ifdef MFEM_THREAD_SAFE
6409 DenseMatrix vshape(dof, dim);
6410 DenseMatrix Jinv(dim);
6411 #endif
6412
6413 #ifdef MFEM_DEBUG
6414 for (k = 0; k < 6; k++)
6415 {
6416 CalcVShape (Nodes.IntPoint(k), vshape);
6417 for (j = 0; j < 6; j++)
6418 {
6419 double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] +
6420 vshape(j,2)*nk[k][2] );
6421 if (j == k) { d -= 1.0; }
6422 if (fabs(d) > 1.0e-12)
6423 {
6424 mfem::err << "RT0HexFiniteElement::GetLocalInterpolation (...)\n"
6425 " k = " << k << ", j = " << j << ", d = " << d << endl;
6426 mfem_error();
6427 }
6428 }
6429 }
6430 #endif
6431
6432 IntegrationPoint ip;
6433 ip.x = ip.y = ip.z = 0.0;
6434 Trans.SetIntPoint (&ip);
6435 // Trans must be linear
6436 // set Jinv = |J| J^{-t} = adj(J)^t
6437 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
6438 double vk[3];
6439 Vector xk (vk, 3);
6440
6441 for (k = 0; k < 6; k++)
6442 {
6443 Trans.Transform (Nodes.IntPoint (k), xk);
6444 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
6445 CalcVShape (ip, vshape);
6446 // vk = |J| J^{-t} nk
6447 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2];
6448 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2];
6449 vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2];
6450 for (j = 0; j < 6; j++)
6451 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
6452 vshape(j,2)*vk[2])) < 1.0e-12)
6453 {
6454 I(k,j) = 0.0;
6455 }
6456 }
6457 }
6458
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const6459 void RT0HexFiniteElement::Project (
6460 VectorCoefficient &vc, ElementTransformation &Trans,
6461 Vector &dofs) const
6462 {
6463 double vk[3];
6464 Vector xk (vk, 3);
6465 #ifdef MFEM_THREAD_SAFE
6466 DenseMatrix Jinv(dim);
6467 #endif
6468
6469 for (int k = 0; k < 6; k++)
6470 {
6471 Trans.SetIntPoint (&Nodes.IntPoint (k));
6472 // set Jinv = |J| J^{-t} = adj(J)^t
6473 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
6474
6475 vc.Eval (xk, Trans, Nodes.IntPoint (k));
6476 // xk^t |J| J^{-t} nk
6477 dofs(k) =
6478 vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) +
6479 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) +
6480 vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] );
6481 }
6482 }
6483
RT1HexFiniteElement()6484 RT1HexFiniteElement::RT1HexFiniteElement()
6485 : VectorFiniteElement(3, Geometry::CUBE, 36, 2, H_DIV, FunctionSpace::Qk)
6486 {
6487 // z = 0
6488 Nodes.IntPoint(2).x = 1./3.;
6489 Nodes.IntPoint(2).y = 1./3.;
6490 Nodes.IntPoint(2).z = 0.0;
6491 Nodes.IntPoint(3).x = 2./3.;
6492 Nodes.IntPoint(3).y = 1./3.;
6493 Nodes.IntPoint(3).z = 0.0;
6494 Nodes.IntPoint(0).x = 1./3.;
6495 Nodes.IntPoint(0).y = 2./3.;
6496 Nodes.IntPoint(0).z = 0.0;
6497 Nodes.IntPoint(1).x = 2./3.;
6498 Nodes.IntPoint(1).y = 2./3.;
6499 Nodes.IntPoint(1).z = 0.0;
6500 // y = 0
6501 Nodes.IntPoint(4).x = 1./3.;
6502 Nodes.IntPoint(4).y = 0.0;
6503 Nodes.IntPoint(4).z = 1./3.;
6504 Nodes.IntPoint(5).x = 2./3.;
6505 Nodes.IntPoint(5).y = 0.0;
6506 Nodes.IntPoint(5).z = 1./3.;
6507 Nodes.IntPoint(6).x = 1./3.;
6508 Nodes.IntPoint(6).y = 0.0;
6509 Nodes.IntPoint(6).z = 2./3.;
6510 Nodes.IntPoint(7).x = 2./3.;
6511 Nodes.IntPoint(7).y = 0.0;
6512 Nodes.IntPoint(7).z = 2./3.;
6513 // x = 1
6514 Nodes.IntPoint(8).x = 1.0;
6515 Nodes.IntPoint(8).y = 1./3.;
6516 Nodes.IntPoint(8).z = 1./3.;
6517 Nodes.IntPoint(9).x = 1.0;
6518 Nodes.IntPoint(9).y = 2./3.;
6519 Nodes.IntPoint(9).z = 1./3.;
6520 Nodes.IntPoint(10).x = 1.0;
6521 Nodes.IntPoint(10).y = 1./3.;
6522 Nodes.IntPoint(10).z = 2./3.;
6523 Nodes.IntPoint(11).x = 1.0;
6524 Nodes.IntPoint(11).y = 2./3.;
6525 Nodes.IntPoint(11).z = 2./3.;
6526 // y = 1
6527 Nodes.IntPoint(13).x = 1./3.;
6528 Nodes.IntPoint(13).y = 1.0;
6529 Nodes.IntPoint(13).z = 1./3.;
6530 Nodes.IntPoint(12).x = 2./3.;
6531 Nodes.IntPoint(12).y = 1.0;
6532 Nodes.IntPoint(12).z = 1./3.;
6533 Nodes.IntPoint(15).x = 1./3.;
6534 Nodes.IntPoint(15).y = 1.0;
6535 Nodes.IntPoint(15).z = 2./3.;
6536 Nodes.IntPoint(14).x = 2./3.;
6537 Nodes.IntPoint(14).y = 1.0;
6538 Nodes.IntPoint(14).z = 2./3.;
6539 // x = 0
6540 Nodes.IntPoint(17).x = 0.0;
6541 Nodes.IntPoint(17).y = 1./3.;
6542 Nodes.IntPoint(17).z = 1./3.;
6543 Nodes.IntPoint(16).x = 0.0;
6544 Nodes.IntPoint(16).y = 2./3.;
6545 Nodes.IntPoint(16).z = 1./3.;
6546 Nodes.IntPoint(19).x = 0.0;
6547 Nodes.IntPoint(19).y = 1./3.;
6548 Nodes.IntPoint(19).z = 2./3.;
6549 Nodes.IntPoint(18).x = 0.0;
6550 Nodes.IntPoint(18).y = 2./3.;
6551 Nodes.IntPoint(18).z = 2./3.;
6552 // z = 1
6553 Nodes.IntPoint(20).x = 1./3.;
6554 Nodes.IntPoint(20).y = 1./3.;
6555 Nodes.IntPoint(20).z = 1.0;
6556 Nodes.IntPoint(21).x = 2./3.;
6557 Nodes.IntPoint(21).y = 1./3.;
6558 Nodes.IntPoint(21).z = 1.0;
6559 Nodes.IntPoint(22).x = 1./3.;
6560 Nodes.IntPoint(22).y = 2./3.;
6561 Nodes.IntPoint(22).z = 1.0;
6562 Nodes.IntPoint(23).x = 2./3.;
6563 Nodes.IntPoint(23).y = 2./3.;
6564 Nodes.IntPoint(23).z = 1.0;
6565 // x = 0.5 (interior)
6566 Nodes.IntPoint(24).x = 0.5;
6567 Nodes.IntPoint(24).y = 1./3.;
6568 Nodes.IntPoint(24).z = 1./3.;
6569 Nodes.IntPoint(25).x = 0.5;
6570 Nodes.IntPoint(25).y = 1./3.;
6571 Nodes.IntPoint(25).z = 2./3.;
6572 Nodes.IntPoint(26).x = 0.5;
6573 Nodes.IntPoint(26).y = 2./3.;
6574 Nodes.IntPoint(26).z = 1./3.;
6575 Nodes.IntPoint(27).x = 0.5;
6576 Nodes.IntPoint(27).y = 2./3.;
6577 Nodes.IntPoint(27).z = 2./3.;
6578 // y = 0.5 (interior)
6579 Nodes.IntPoint(28).x = 1./3.;
6580 Nodes.IntPoint(28).y = 0.5;
6581 Nodes.IntPoint(28).z = 1./3.;
6582 Nodes.IntPoint(29).x = 1./3.;
6583 Nodes.IntPoint(29).y = 0.5;
6584 Nodes.IntPoint(29).z = 2./3.;
6585 Nodes.IntPoint(30).x = 2./3.;
6586 Nodes.IntPoint(30).y = 0.5;
6587 Nodes.IntPoint(30).z = 1./3.;
6588 Nodes.IntPoint(31).x = 2./3.;
6589 Nodes.IntPoint(31).y = 0.5;
6590 Nodes.IntPoint(31).z = 2./3.;
6591 // z = 0.5 (interior)
6592 Nodes.IntPoint(32).x = 1./3.;
6593 Nodes.IntPoint(32).y = 1./3.;
6594 Nodes.IntPoint(32).z = 0.5;
6595 Nodes.IntPoint(33).x = 1./3.;
6596 Nodes.IntPoint(33).y = 2./3.;
6597 Nodes.IntPoint(33).z = 0.5;
6598 Nodes.IntPoint(34).x = 2./3.;
6599 Nodes.IntPoint(34).y = 1./3.;
6600 Nodes.IntPoint(34).z = 0.5;
6601 Nodes.IntPoint(35).x = 2./3.;
6602 Nodes.IntPoint(35).y = 2./3.;
6603 Nodes.IntPoint(35).z = 0.5;
6604 }
6605
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const6606 void RT1HexFiniteElement::CalcVShape(const IntegrationPoint &ip,
6607 DenseMatrix &shape) const
6608 {
6609 double x = ip.x, y = ip.y, z = ip.z;
6610 // z = 0
6611 shape(2,0) = 0.;
6612 shape(2,1) = 0.;
6613 shape(2,2) = -(1. - 3.*z + 2.*z*z)*( 2. - 3.*x)*( 2. - 3.*y);
6614 shape(3,0) = 0.;
6615 shape(3,1) = 0.;
6616 shape(3,2) = -(1. - 3.*z + 2.*z*z)*(-1. + 3.*x)*( 2. - 3.*y);
6617 shape(0,0) = 0.;
6618 shape(0,1) = 0.;
6619 shape(0,2) = -(1. - 3.*z + 2.*z*z)*( 2. - 3.*x)*(-1. + 3.*y);
6620 shape(1,0) = 0.;
6621 shape(1,1) = 0.;
6622 shape(1,2) = -(1. - 3.*z + 2.*z*z)*(-1. + 3.*x)*(-1. + 3.*y);
6623 // y = 0
6624 shape(4,0) = 0.;
6625 shape(4,1) = -(1. - 3.*y + 2.*y*y)*( 2. - 3.*x)*( 2. - 3.*z);
6626 shape(4,2) = 0.;
6627 shape(5,0) = 0.;
6628 shape(5,1) = -(1. - 3.*y + 2.*y*y)*(-1. + 3.*x)*( 2. - 3.*z);
6629 shape(5,2) = 0.;
6630 shape(6,0) = 0.;
6631 shape(6,1) = -(1. - 3.*y + 2.*y*y)*( 2. - 3.*x)*(-1. + 3.*z);
6632 shape(6,2) = 0.;
6633 shape(7,0) = 0.;
6634 shape(7,1) = -(1. - 3.*y + 2.*y*y)*(-1. + 3.*x)*(-1. + 3.*z);
6635 shape(7,2) = 0.;
6636 // x = 1
6637 shape(8,0) = (-x + 2.*x*x)*( 2. - 3.*y)*( 2. - 3.*z);
6638 shape(8,1) = 0.;
6639 shape(8,2) = 0.;
6640 shape(9,0) = (-x + 2.*x*x)*(-1. + 3.*y)*( 2. - 3.*z);
6641 shape(9,1) = 0.;
6642 shape(9,2) = 0.;
6643 shape(10,0) = (-x + 2.*x*x)*( 2. - 3.*y)*(-1. + 3.*z);
6644 shape(10,1) = 0.;
6645 shape(10,2) = 0.;
6646 shape(11,0) = (-x + 2.*x*x)*(-1. + 3.*y)*(-1. + 3.*z);
6647 shape(11,1) = 0.;
6648 shape(11,2) = 0.;
6649 // y = 1
6650 shape(13,0) = 0.;
6651 shape(13,1) = (-y + 2.*y*y)*( 2. - 3.*x)*( 2. - 3.*z);
6652 shape(13,2) = 0.;
6653 shape(12,0) = 0.;
6654 shape(12,1) = (-y + 2.*y*y)*(-1. + 3.*x)*( 2. - 3.*z);
6655 shape(12,2) = 0.;
6656 shape(15,0) = 0.;
6657 shape(15,1) = (-y + 2.*y*y)*( 2. - 3.*x)*(-1. + 3.*z);
6658 shape(15,2) = 0.;
6659 shape(14,0) = 0.;
6660 shape(14,1) = (-y + 2.*y*y)*(-1. + 3.*x)*(-1. + 3.*z);
6661 shape(14,2) = 0.;
6662 // x = 0
6663 shape(17,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y)*( 2. - 3.*z);
6664 shape(17,1) = 0.;
6665 shape(17,2) = 0.;
6666 shape(16,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y)*( 2. - 3.*z);
6667 shape(16,1) = 0.;
6668 shape(16,2) = 0.;
6669 shape(19,0) = -(1. - 3.*x + 2.*x*x)*( 2. - 3.*y)*(-1. + 3.*z);
6670 shape(19,1) = 0.;
6671 shape(19,2) = 0.;
6672 shape(18,0) = -(1. - 3.*x + 2.*x*x)*(-1. + 3.*y)*(-1. + 3.*z);
6673 shape(18,1) = 0.;
6674 shape(18,2) = 0.;
6675 // z = 1
6676 shape(20,0) = 0.;
6677 shape(20,1) = 0.;
6678 shape(20,2) = (-z + 2.*z*z)*( 2. - 3.*x)*( 2. - 3.*y);
6679 shape(21,0) = 0.;
6680 shape(21,1) = 0.;
6681 shape(21,2) = (-z + 2.*z*z)*(-1. + 3.*x)*( 2. - 3.*y);
6682 shape(22,0) = 0.;
6683 shape(22,1) = 0.;
6684 shape(22,2) = (-z + 2.*z*z)*( 2. - 3.*x)*(-1. + 3.*y);
6685 shape(23,0) = 0.;
6686 shape(23,1) = 0.;
6687 shape(23,2) = (-z + 2.*z*z)*(-1. + 3.*x)*(-1. + 3.*y);
6688 // x = 0.5 (interior)
6689 shape(24,0) = (4.*x - 4.*x*x)*( 2. - 3.*y)*( 2. - 3.*z);
6690 shape(24,1) = 0.;
6691 shape(24,2) = 0.;
6692 shape(25,0) = (4.*x - 4.*x*x)*( 2. - 3.*y)*(-1. + 3.*z);
6693 shape(25,1) = 0.;
6694 shape(25,2) = 0.;
6695 shape(26,0) = (4.*x - 4.*x*x)*(-1. + 3.*y)*( 2. - 3.*z);
6696 shape(26,1) = 0.;
6697 shape(26,2) = 0.;
6698 shape(27,0) = (4.*x - 4.*x*x)*(-1. + 3.*y)*(-1. + 3.*z);
6699 shape(27,1) = 0.;
6700 shape(27,2) = 0.;
6701 // y = 0.5 (interior)
6702 shape(28,0) = 0.;
6703 shape(28,1) = (4.*y - 4.*y*y)*( 2. - 3.*x)*( 2. - 3.*z);
6704 shape(28,2) = 0.;
6705 shape(29,0) = 0.;
6706 shape(29,1) = (4.*y - 4.*y*y)*( 2. - 3.*x)*(-1. + 3.*z);
6707 shape(29,2) = 0.;
6708 shape(30,0) = 0.;
6709 shape(30,1) = (4.*y - 4.*y*y)*(-1. + 3.*x)*( 2. - 3.*z);
6710 shape(30,2) = 0.;
6711 shape(31,0) = 0.;
6712 shape(31,1) = (4.*y - 4.*y*y)*(-1. + 3.*x)*(-1. + 3.*z);
6713 shape(31,2) = 0.;
6714 // z = 0.5 (interior)
6715 shape(32,0) = 0.;
6716 shape(32,1) = 0.;
6717 shape(32,2) = (4.*z - 4.*z*z)*( 2. - 3.*x)*( 2. - 3.*y);
6718 shape(33,0) = 0.;
6719 shape(33,1) = 0.;
6720 shape(33,2) = (4.*z - 4.*z*z)*( 2. - 3.*x)*(-1. + 3.*y);
6721 shape(34,0) = 0.;
6722 shape(34,1) = 0.;
6723 shape(34,2) = (4.*z - 4.*z*z)*(-1. + 3.*x)*( 2. - 3.*y);
6724 shape(35,0) = 0.;
6725 shape(35,1) = 0.;
6726 shape(35,2) = (4.*z - 4.*z*z)*(-1. + 3.*x)*(-1. + 3.*y);
6727 }
6728
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const6729 void RT1HexFiniteElement::CalcDivShape(const IntegrationPoint &ip,
6730 Vector &divshape) const
6731 {
6732 double x = ip.x, y = ip.y, z = ip.z;
6733 // z = 0
6734 divshape(2) = -(-3. + 4.*z)*( 2. - 3.*x)*( 2. - 3.*y);
6735 divshape(3) = -(-3. + 4.*z)*(-1. + 3.*x)*( 2. - 3.*y);
6736 divshape(0) = -(-3. + 4.*z)*( 2. - 3.*x)*(-1. + 3.*y);
6737 divshape(1) = -(-3. + 4.*z)*(-1. + 3.*x)*(-1. + 3.*y);
6738 // y = 0
6739 divshape(4) = -(-3. + 4.*y)*( 2. - 3.*x)*( 2. - 3.*z);
6740 divshape(5) = -(-3. + 4.*y)*(-1. + 3.*x)*( 2. - 3.*z);
6741 divshape(6) = -(-3. + 4.*y)*( 2. - 3.*x)*(-1. + 3.*z);
6742 divshape(7) = -(-3. + 4.*y)*(-1. + 3.*x)*(-1. + 3.*z);
6743 // x = 1
6744 divshape(8) = (-1. + 4.*x)*( 2. - 3.*y)*( 2. - 3.*z);
6745 divshape(9) = (-1. + 4.*x)*(-1. + 3.*y)*( 2. - 3.*z);
6746 divshape(10) = (-1. + 4.*x)*( 2. - 3.*y)*(-1. + 3.*z);
6747 divshape(11) = (-1. + 4.*x)*(-1. + 3.*y)*(-1. + 3.*z);
6748 // y = 1
6749 divshape(13) = (-1. + 4.*y)*( 2. - 3.*x)*( 2. - 3.*z);
6750 divshape(12) = (-1. + 4.*y)*(-1. + 3.*x)*( 2. - 3.*z);
6751 divshape(15) = (-1. + 4.*y)*( 2. - 3.*x)*(-1. + 3.*z);
6752 divshape(14) = (-1. + 4.*y)*(-1. + 3.*x)*(-1. + 3.*z);
6753 // x = 0
6754 divshape(17) = -(-3. + 4.*x)*( 2. - 3.*y)*( 2. - 3.*z);
6755 divshape(16) = -(-3. + 4.*x)*(-1. + 3.*y)*( 2. - 3.*z);
6756 divshape(19) = -(-3. + 4.*x)*( 2. - 3.*y)*(-1. + 3.*z);
6757 divshape(18) = -(-3. + 4.*x)*(-1. + 3.*y)*(-1. + 3.*z);
6758 // z = 1
6759 divshape(20) = (-1. + 4.*z)*( 2. - 3.*x)*( 2. - 3.*y);
6760 divshape(21) = (-1. + 4.*z)*(-1. + 3.*x)*( 2. - 3.*y);
6761 divshape(22) = (-1. + 4.*z)*( 2. - 3.*x)*(-1. + 3.*y);
6762 divshape(23) = (-1. + 4.*z)*(-1. + 3.*x)*(-1. + 3.*y);
6763 // x = 0.5 (interior)
6764 divshape(24) = ( 4. - 8.*x)*( 2. - 3.*y)*( 2. - 3.*z);
6765 divshape(25) = ( 4. - 8.*x)*( 2. - 3.*y)*(-1. + 3.*z);
6766 divshape(26) = ( 4. - 8.*x)*(-1. + 3.*y)*( 2. - 3.*z);
6767 divshape(27) = ( 4. - 8.*x)*(-1. + 3.*y)*(-1. + 3.*z);
6768 // y = 0.5 (interior)
6769 divshape(28) = ( 4. - 8.*y)*( 2. - 3.*x)*( 2. - 3.*z);
6770 divshape(29) = ( 4. - 8.*y)*( 2. - 3.*x)*(-1. + 3.*z);
6771 divshape(30) = ( 4. - 8.*y)*(-1. + 3.*x)*( 2. - 3.*z);
6772 divshape(31) = ( 4. - 8.*y)*(-1. + 3.*x)*(-1. + 3.*z);
6773 // z = 0.5 (interior)
6774 divshape(32) = ( 4. - 8.*z)*( 2. - 3.*x)*( 2. - 3.*y);
6775 divshape(33) = ( 4. - 8.*z)*( 2. - 3.*x)*(-1. + 3.*y);
6776 divshape(34) = ( 4. - 8.*z)*(-1. + 3.*x)*( 2. - 3.*y);
6777 divshape(35) = ( 4. - 8.*z)*(-1. + 3.*x)*(-1. + 3.*y);
6778 }
6779
6780 const double RT1HexFiniteElement::nk[36][3] =
6781 {
6782 {0, 0,-1}, {0, 0,-1}, {0, 0,-1}, {0, 0,-1},
6783 {0,-1, 0}, {0,-1, 0}, {0,-1, 0}, {0,-1, 0},
6784 {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0},
6785 {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0},
6786 {-1,0, 0}, {-1,0, 0}, {-1,0, 0}, {-1,0, 0},
6787 {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1},
6788 {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0},
6789 {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0},
6790 {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}
6791 };
6792
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const6793 void RT1HexFiniteElement::GetLocalInterpolation (
6794 ElementTransformation &Trans, DenseMatrix &I) const
6795 {
6796 int k, j;
6797 #ifdef MFEM_THREAD_SAFE
6798 DenseMatrix vshape(dof, dim);
6799 DenseMatrix Jinv(dim);
6800 #endif
6801
6802 #ifdef MFEM_DEBUG
6803 for (k = 0; k < 36; k++)
6804 {
6805 CalcVShape (Nodes.IntPoint(k), vshape);
6806 for (j = 0; j < 36; j++)
6807 {
6808 double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] +
6809 vshape(j,2)*nk[k][2] );
6810 if (j == k) { d -= 1.0; }
6811 if (fabs(d) > 1.0e-12)
6812 {
6813 mfem::err << "RT0HexFiniteElement::GetLocalInterpolation (...)\n"
6814 " k = " << k << ", j = " << j << ", d = " << d << endl;
6815 mfem_error();
6816 }
6817 }
6818 }
6819 #endif
6820
6821 IntegrationPoint ip;
6822 ip.x = ip.y = ip.z = 0.0;
6823 Trans.SetIntPoint (&ip);
6824 // Trans must be linear
6825 // set Jinv = |J| J^{-t} = adj(J)^t
6826 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
6827 double vk[3];
6828 Vector xk (vk, 3);
6829
6830 for (k = 0; k < 36; k++)
6831 {
6832 Trans.Transform (Nodes.IntPoint (k), xk);
6833 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
6834 CalcVShape (ip, vshape);
6835 // vk = |J| J^{-t} nk
6836 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2];
6837 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2];
6838 vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2];
6839 for (j = 0; j < 36; j++)
6840 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
6841 vshape(j,2)*vk[2])) < 1.0e-12)
6842 {
6843 I(k,j) = 0.0;
6844 }
6845 }
6846 }
6847
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const6848 void RT1HexFiniteElement::Project (
6849 VectorCoefficient &vc, ElementTransformation &Trans,
6850 Vector &dofs) const
6851 {
6852 double vk[3];
6853 Vector xk (vk, 3);
6854 #ifdef MFEM_THREAD_SAFE
6855 DenseMatrix Jinv(dim);
6856 #endif
6857
6858 for (int k = 0; k < 36; k++)
6859 {
6860 Trans.SetIntPoint (&Nodes.IntPoint (k));
6861 // set Jinv = |J| J^{-t} = adj(J)^t
6862 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
6863
6864 vc.Eval (xk, Trans, Nodes.IntPoint (k));
6865 // xk^t |J| J^{-t} nk
6866 dofs(k) =
6867 vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) +
6868 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) +
6869 vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] );
6870 }
6871 }
6872
RT0TetFiniteElement()6873 RT0TetFiniteElement::RT0TetFiniteElement()
6874 : VectorFiniteElement(3, Geometry::TETRAHEDRON, 4, 1, H_DIV)
6875 {
6876 // not real nodes ...
6877 Nodes.IntPoint(0).x = 0.33333333333333333333;
6878 Nodes.IntPoint(0).y = 0.33333333333333333333;
6879 Nodes.IntPoint(0).z = 0.33333333333333333333;
6880
6881 Nodes.IntPoint(1).x = 0.0;
6882 Nodes.IntPoint(1).y = 0.33333333333333333333;
6883 Nodes.IntPoint(1).z = 0.33333333333333333333;
6884
6885 Nodes.IntPoint(2).x = 0.33333333333333333333;
6886 Nodes.IntPoint(2).y = 0.0;
6887 Nodes.IntPoint(2).z = 0.33333333333333333333;
6888
6889 Nodes.IntPoint(3).x = 0.33333333333333333333;
6890 Nodes.IntPoint(3).y = 0.33333333333333333333;
6891 Nodes.IntPoint(3).z = 0.0;
6892 }
6893
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const6894 void RT0TetFiniteElement::CalcVShape(const IntegrationPoint &ip,
6895 DenseMatrix &shape) const
6896 {
6897 double x2 = 2.0*ip.x, y2 = 2.0*ip.y, z2 = 2.0*ip.z;
6898
6899 shape(0,0) = x2;
6900 shape(0,1) = y2;
6901 shape(0,2) = z2;
6902
6903 shape(1,0) = x2 - 2.0;
6904 shape(1,1) = y2;
6905 shape(1,2) = z2;
6906
6907 shape(2,0) = x2;
6908 shape(2,1) = y2 - 2.0;
6909 shape(2,2) = z2;
6910
6911 shape(3,0) = x2;
6912 shape(3,1) = y2;
6913 shape(3,2) = z2 - 2.0;
6914 }
6915
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const6916 void RT0TetFiniteElement::CalcDivShape(const IntegrationPoint &ip,
6917 Vector &divshape) const
6918 {
6919 divshape(0) = 6.0;
6920 divshape(1) = 6.0;
6921 divshape(2) = 6.0;
6922 divshape(3) = 6.0;
6923 }
6924
6925 const double RT0TetFiniteElement::nk[4][3] =
6926 {{.5,.5,.5}, {-.5,0,0}, {0,-.5,0}, {0,0,-.5}};
6927
GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const6928 void RT0TetFiniteElement::GetLocalInterpolation (
6929 ElementTransformation &Trans, DenseMatrix &I) const
6930 {
6931 int k, j;
6932 #ifdef MFEM_THREAD_SAFE
6933 DenseMatrix vshape(dof, dim);
6934 DenseMatrix Jinv(dim);
6935 #endif
6936
6937 #ifdef MFEM_DEBUG
6938 for (k = 0; k < 4; k++)
6939 {
6940 CalcVShape (Nodes.IntPoint(k), vshape);
6941 for (j = 0; j < 4; j++)
6942 {
6943 double d = ( vshape(j,0)*nk[k][0] + vshape(j,1)*nk[k][1] +
6944 vshape(j,2)*nk[k][2] );
6945 if (j == k) { d -= 1.0; }
6946 if (fabs(d) > 1.0e-12)
6947 {
6948 mfem::err << "RT0TetFiniteElement::GetLocalInterpolation (...)\n"
6949 " k = " << k << ", j = " << j << ", d = " << d << endl;
6950 mfem_error();
6951 }
6952 }
6953 }
6954 #endif
6955
6956 IntegrationPoint ip;
6957 ip.x = ip.y = ip.z = 0.0;
6958 Trans.SetIntPoint (&ip);
6959 // Trans must be linear
6960 // set Jinv = |J| J^{-t} = adj(J)^t
6961 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
6962 double vk[3];
6963 Vector xk (vk, 3);
6964
6965 for (k = 0; k < 4; k++)
6966 {
6967 Trans.Transform (Nodes.IntPoint (k), xk);
6968 ip.x = vk[0]; ip.y = vk[1]; ip.z = vk[2];
6969 CalcVShape (ip, vshape);
6970 // vk = |J| J^{-t} nk
6971 vk[0] = Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2];
6972 vk[1] = Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2];
6973 vk[2] = Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2];
6974 for (j = 0; j < 4; j++)
6975 if (fabs (I(k,j) = (vshape(j,0)*vk[0]+vshape(j,1)*vk[1]+
6976 vshape(j,2)*vk[2])) < 1.0e-12)
6977 {
6978 I(k,j) = 0.0;
6979 }
6980 }
6981 }
6982
Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const6983 void RT0TetFiniteElement::Project (
6984 VectorCoefficient &vc, ElementTransformation &Trans,
6985 Vector &dofs) const
6986 {
6987 double vk[3];
6988 Vector xk (vk, 3);
6989 #ifdef MFEM_THREAD_SAFE
6990 DenseMatrix Jinv(dim);
6991 #endif
6992
6993 for (int k = 0; k < 4; k++)
6994 {
6995 Trans.SetIntPoint (&Nodes.IntPoint (k));
6996 // set Jinv = |J| J^{-t} = adj(J)^t
6997 CalcAdjugateTranspose (Trans.Jacobian(), Jinv);
6998
6999 vc.Eval (xk, Trans, Nodes.IntPoint (k));
7000 // xk^t |J| J^{-t} nk
7001 dofs(k) =
7002 vk[0] * ( Jinv(0,0)*nk[k][0]+Jinv(0,1)*nk[k][1]+Jinv(0,2)*nk[k][2] ) +
7003 vk[1] * ( Jinv(1,0)*nk[k][0]+Jinv(1,1)*nk[k][1]+Jinv(1,2)*nk[k][2] ) +
7004 vk[2] * ( Jinv(2,0)*nk[k][0]+Jinv(2,1)*nk[k][1]+Jinv(2,2)*nk[k][2] );
7005 }
7006 }
7007
RotTriLinearHexFiniteElement()7008 RotTriLinearHexFiniteElement::RotTriLinearHexFiniteElement()
7009 : NodalFiniteElement(3, Geometry::CUBE, 6, 2, FunctionSpace::Qk)
7010 {
7011 Nodes.IntPoint(0).x = 0.5;
7012 Nodes.IntPoint(0).y = 0.5;
7013 Nodes.IntPoint(0).z = 0.0;
7014
7015 Nodes.IntPoint(1).x = 0.5;
7016 Nodes.IntPoint(1).y = 0.0;
7017 Nodes.IntPoint(1).z = 0.5;
7018
7019 Nodes.IntPoint(2).x = 1.0;
7020 Nodes.IntPoint(2).y = 0.5;
7021 Nodes.IntPoint(2).z = 0.5;
7022
7023 Nodes.IntPoint(3).x = 0.5;
7024 Nodes.IntPoint(3).y = 1.0;
7025 Nodes.IntPoint(3).z = 0.5;
7026
7027 Nodes.IntPoint(4).x = 0.0;
7028 Nodes.IntPoint(4).y = 0.5;
7029 Nodes.IntPoint(4).z = 0.5;
7030
7031 Nodes.IntPoint(5).x = 0.5;
7032 Nodes.IntPoint(5).y = 0.5;
7033 Nodes.IntPoint(5).z = 1.0;
7034 }
7035
CalcShape(const IntegrationPoint & ip,Vector & shape) const7036 void RotTriLinearHexFiniteElement::CalcShape(const IntegrationPoint &ip,
7037 Vector &shape) const
7038 {
7039 double x = 2. * ip.x - 1.;
7040 double y = 2. * ip.y - 1.;
7041 double z = 2. * ip.z - 1.;
7042 double f5 = x * x - y * y;
7043 double f6 = y * y - z * z;
7044
7045 shape(0) = (1./6.) * (1. - 3. * z - f5 - 2. * f6);
7046 shape(1) = (1./6.) * (1. - 3. * y - f5 + f6);
7047 shape(2) = (1./6.) * (1. + 3. * x + 2. * f5 + f6);
7048 shape(3) = (1./6.) * (1. + 3. * y - f5 + f6);
7049 shape(4) = (1./6.) * (1. - 3. * x + 2. * f5 + f6);
7050 shape(5) = (1./6.) * (1. + 3. * z - f5 - 2. * f6);
7051 }
7052
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const7053 void RotTriLinearHexFiniteElement::CalcDShape(const IntegrationPoint &ip,
7054 DenseMatrix &dshape) const
7055 {
7056 const double a = 2./3.;
7057
7058 double xt = a * (1. - 2. * ip.x);
7059 double yt = a * (1. - 2. * ip.y);
7060 double zt = a * (1. - 2. * ip.z);
7061
7062 dshape(0,0) = xt;
7063 dshape(0,1) = yt;
7064 dshape(0,2) = -1. - 2. * zt;
7065
7066 dshape(1,0) = xt;
7067 dshape(1,1) = -1. - 2. * yt;
7068 dshape(1,2) = zt;
7069
7070 dshape(2,0) = 1. - 2. * xt;
7071 dshape(2,1) = yt;
7072 dshape(2,2) = zt;
7073
7074 dshape(3,0) = xt;
7075 dshape(3,1) = 1. - 2. * yt;
7076 dshape(3,2) = zt;
7077
7078 dshape(4,0) = -1. - 2. * xt;
7079 dshape(4,1) = yt;
7080 dshape(4,2) = zt;
7081
7082 dshape(5,0) = xt;
7083 dshape(5,1) = yt;
7084 dshape(5,2) = 1. - 2. * zt;
7085 }
7086
7087
Basis(const int p,const double * nodes,EvalType etype)7088 Poly_1D::Basis::Basis(const int p, const double *nodes, EvalType etype)
7089 : etype(etype), auxiliary_basis(NULL)
7090 {
7091 switch (etype)
7092 {
7093 case ChangeOfBasis:
7094 {
7095 x.SetSize(p + 1);
7096 w.SetSize(p + 1);
7097 DenseMatrix A(p + 1);
7098 for (int i = 0; i <= p; i++)
7099 {
7100 CalcBasis(p, nodes[i], A.GetColumn(i));
7101 }
7102 Ai.Factor(A);
7103 // mfem::out << "Poly_1D::Basis(" << p << ",...) : "; Ai.TestInversion();
7104 break;
7105 }
7106 case Barycentric:
7107 {
7108 x.SetSize(p + 1);
7109 w.SetSize(p + 1);
7110 x = nodes;
7111 w = 1.0;
7112 for (int i = 0; i <= p; i++)
7113 {
7114 for (int j = 0; j < i; j++)
7115 {
7116 double xij = x(i) - x(j);
7117 w(i) *= xij;
7118 w(j) *= -xij;
7119 }
7120 }
7121 for (int i = 0; i <= p; i++)
7122 {
7123 w(i) = 1.0/w(i);
7124 }
7125
7126 #ifdef MFEM_DEBUG
7127 // Make sure the nodes are increasing
7128 for (int i = 0; i < p; i++)
7129 {
7130 if (x(i) >= x(i+1))
7131 {
7132 mfem_error("Poly_1D::Basis::Basis : nodes are not increasing!");
7133 }
7134 }
7135 #endif
7136 break;
7137 }
7138 case Positive:
7139 x.SetDataAndSize(NULL, p + 1); // use x to store (p + 1)
7140 break;
7141 case Integrated:
7142 auxiliary_basis = new Basis(
7143 p+1, poly1d.GetPoints(p+1, BasisType::GaussLobatto), Barycentric);
7144 u_aux.SetSize(p+2);
7145 d_aux.SetSize(p+2);
7146 d2_aux.SetSize(p+2);
7147 break;
7148 default: break;
7149 }
7150 }
7151
Eval(const double y,Vector & u) const7152 void Poly_1D::Basis::Eval(const double y, Vector &u) const
7153 {
7154 switch (etype)
7155 {
7156 case ChangeOfBasis:
7157 {
7158 CalcBasis(Ai.Width() - 1, y, x);
7159 Ai.Mult(x, u);
7160 break;
7161 }
7162 case Barycentric:
7163 {
7164 int i, k, p = x.Size() - 1;
7165 double l, lk;
7166
7167 if (p == 0)
7168 {
7169 u(0) = 1.0;
7170 return;
7171 }
7172
7173 lk = 1.0;
7174 for (k = 0; k < p; k++)
7175 {
7176 if (y >= (x(k) + x(k+1))/2)
7177 {
7178 lk *= y - x(k);
7179 }
7180 else
7181 {
7182 for (i = k+1; i <= p; i++)
7183 {
7184 lk *= y - x(i);
7185 }
7186 break;
7187 }
7188 }
7189 l = lk * (y - x(k));
7190
7191 for (i = 0; i < k; i++)
7192 {
7193 u(i) = l * w(i) / (y - x(i));
7194 }
7195 u(k) = lk * w(k);
7196 for (i++; i <= p; i++)
7197 {
7198 u(i) = l * w(i) / (y - x(i));
7199 }
7200 break;
7201 }
7202 case Positive:
7203 CalcBernstein(x.Size() - 1, y, u);
7204 break;
7205 case Integrated:
7206 auxiliary_basis->Eval(y, u_aux, d_aux);
7207 EvalIntegrated(d_aux, u);
7208 break;
7209 default: break;
7210 }
7211 }
7212
Eval(const double y,Vector & u,Vector & d) const7213 void Poly_1D::Basis::Eval(const double y, Vector &u, Vector &d) const
7214 {
7215 switch (etype)
7216 {
7217 case ChangeOfBasis:
7218 {
7219 CalcBasis(Ai.Width() - 1, y, x, w);
7220 Ai.Mult(x, u);
7221 Ai.Mult(w, d);
7222 break;
7223 }
7224 case Barycentric:
7225 {
7226 int i, k, p = x.Size() - 1;
7227 double l, lp, lk, sk, si;
7228
7229 if (p == 0)
7230 {
7231 u(0) = 1.0;
7232 d(0) = 0.0;
7233 return;
7234 }
7235
7236 lk = 1.0;
7237 for (k = 0; k < p; k++)
7238 {
7239 if (y >= (x(k) + x(k+1))/2)
7240 {
7241 lk *= y - x(k);
7242 }
7243 else
7244 {
7245 for (i = k+1; i <= p; i++)
7246 {
7247 lk *= y - x(i);
7248 }
7249 break;
7250 }
7251 }
7252 l = lk * (y - x(k));
7253
7254 sk = 0.0;
7255 for (i = 0; i < k; i++)
7256 {
7257 si = 1.0/(y - x(i));
7258 sk += si;
7259 u(i) = l * si * w(i);
7260 }
7261 u(k) = lk * w(k);
7262 for (i++; i <= p; i++)
7263 {
7264 si = 1.0/(y - x(i));
7265 sk += si;
7266 u(i) = l * si * w(i);
7267 }
7268 lp = l * sk + lk;
7269
7270 for (i = 0; i < k; i++)
7271 {
7272 d(i) = (lp * w(i) - u(i))/(y - x(i));
7273 }
7274 d(k) = sk * u(k);
7275 for (i++; i <= p; i++)
7276 {
7277 d(i) = (lp * w(i) - u(i))/(y - x(i));
7278 }
7279 break;
7280 }
7281 case Positive:
7282 CalcBernstein(x.Size() - 1, y, u, d);
7283 break;
7284 case Integrated:
7285 auxiliary_basis->Eval(y, u_aux, d_aux, d2_aux);
7286 EvalIntegrated(d_aux,u);
7287 EvalIntegrated(d2_aux,d);
7288 break;
7289 default: break;
7290 }
7291 }
7292
Eval(const double y,Vector & u,Vector & d,Vector & d2) const7293 void Poly_1D::Basis::Eval(const double y, Vector &u, Vector &d,
7294 Vector &d2) const
7295 {
7296 MFEM_VERIFY(etype == Barycentric,
7297 "Basis::Eval with second order derivatives not implemented for"
7298 " etype = " << etype);
7299 switch (etype)
7300 {
7301 case ChangeOfBasis:
7302 {
7303 CalcBasis(Ai.Width() - 1, y, x, w);
7304 Ai.Mult(x, u);
7305 Ai.Mult(w, d);
7306 // set d2 (not implemented yet)
7307 break;
7308 }
7309 case Barycentric:
7310 {
7311 int i, k, p = x.Size() - 1;
7312 double l, lp, lp2, lk, sk, si, sk2;
7313
7314 if (p == 0)
7315 {
7316 u(0) = 1.0;
7317 d(0) = 0.0;
7318 d2(0) = 0.0;
7319 return;
7320 }
7321
7322 lk = 1.0;
7323 for (k = 0; k < p; k++)
7324 {
7325 if (y >= (x(k) + x(k+1))/2)
7326 {
7327 lk *= y - x(k);
7328 }
7329 else
7330 {
7331 for (i = k+1; i <= p; i++)
7332 {
7333 lk *= y - x(i);
7334 }
7335 break;
7336 }
7337 }
7338 l = lk * (y - x(k));
7339
7340 sk = 0.0;
7341 sk2 = 0.0;
7342 for (i = 0; i < k; i++)
7343 {
7344 si = 1.0/(y - x(i));
7345 sk += si;
7346 sk2 -= si * si;
7347 u(i) = l * si * w(i);
7348 }
7349 u(k) = lk * w(k);
7350 for (i++; i <= p; i++)
7351 {
7352 si = 1.0/(y - x(i));
7353 sk += si;
7354 sk2 -= si * si;
7355 u(i) = l * si * w(i);
7356 }
7357 lp = l * sk + lk;
7358 lp2 = lp * sk + l * sk2 + sk * lk;
7359
7360 for (i = 0; i < k; i++)
7361 {
7362 d(i) = (lp * w(i) - u(i))/(y - x(i));
7363 d2(i) = (lp2 * w(i) - 2 * d(i))/(y - x(i));
7364 }
7365 d(k) = sk * u(k);
7366 d2(k) = sk2 * u(k) + sk * d(k);
7367 for (i++; i <= p; i++)
7368 {
7369 d(i) = (lp * w(i) - u(i))/(y - x(i));
7370 d2(i) = (lp2 * w(i) - 2 * d(i))/(y - x(i));
7371 }
7372 break;
7373 }
7374 case Positive:
7375 CalcBernstein(x.Size() - 1, y, u, d);
7376 break;
7377 case Integrated:
7378 MFEM_ABORT("Integrated basis must be evaluated with EvalIntegrated");
7379 break;
7380 default: break;
7381 }
7382 }
7383
EvalIntegrated(const Vector & d_aux,Vector & u) const7384 void Poly_1D::Basis::EvalIntegrated(const Vector &d_aux, Vector &u) const
7385 {
7386 MFEM_VERIFY(etype == Integrated,
7387 "EvalIntegrated is only valid for Integrated basis type");
7388 int p = d_aux.Size() - 1;
7389 u[0] = -d_aux[0];
7390 for (int j=1; j<p; ++j)
7391 {
7392 u[j] = u[j-1] - d_aux[j];
7393 }
7394 }
7395
~Basis()7396 Poly_1D::Basis::~Basis()
7397 {
7398 delete auxiliary_basis;
7399 }
7400
Binom(const int p)7401 const int *Poly_1D::Binom(const int p)
7402 {
7403 if (binom.NumCols() <= p)
7404 {
7405 binom.SetSize(p + 1, p + 1);
7406 for (int i = 0; i <= p; i++)
7407 {
7408 binom(i,0) = binom(i,i) = 1;
7409 for (int j = 1; j < i; j++)
7410 {
7411 binom(i,j) = binom(i-1,j) + binom(i-1,j-1);
7412 }
7413 }
7414 }
7415 return binom[p];
7416 }
7417
ChebyshevPoints(const int p,double * x)7418 void Poly_1D::ChebyshevPoints(const int p, double *x)
7419 {
7420 for (int i = 0; i <= p; i++)
7421 {
7422 // x[i] = 0.5*(1. + cos(M_PI*(p - i + 0.5)/(p + 1)));
7423 double s = sin(M_PI_2*(i + 0.5)/(p + 1));
7424 x[i] = s*s;
7425 }
7426 }
7427
CalcMono(const int p,const double x,double * u)7428 void Poly_1D::CalcMono(const int p, const double x, double *u)
7429 {
7430 double xn;
7431 u[0] = xn = 1.;
7432 for (int n = 1; n <= p; n++)
7433 {
7434 u[n] = (xn *= x);
7435 }
7436 }
7437
CalcMono(const int p,const double x,double * u,double * d)7438 void Poly_1D::CalcMono(const int p, const double x, double *u, double *d)
7439 {
7440 double xn;
7441 u[0] = xn = 1.;
7442 d[0] = 0.;
7443 for (int n = 1; n <= p; n++)
7444 {
7445 d[n] = n * xn;
7446 u[n] = (xn *= x);
7447 }
7448 }
7449
CalcBinomTerms(const int p,const double x,const double y,double * u)7450 void Poly_1D::CalcBinomTerms(const int p, const double x, const double y,
7451 double *u)
7452 {
7453 if (p == 0)
7454 {
7455 u[0] = 1.;
7456 }
7457 else
7458 {
7459 int i;
7460 const int *b = Binom(p);
7461 double z = x;
7462
7463 for (i = 1; i < p; i++)
7464 {
7465 u[i] = b[i]*z;
7466 z *= x;
7467 }
7468 u[p] = z;
7469 z = y;
7470 for (i--; i > 0; i--)
7471 {
7472 u[i] *= z;
7473 z *= y;
7474 }
7475 u[0] = z;
7476 }
7477 }
7478
CalcBinomTerms(const int p,const double x,const double y,double * u,double * d)7479 void Poly_1D::CalcBinomTerms(const int p, const double x, const double y,
7480 double *u, double *d)
7481 {
7482 if (p == 0)
7483 {
7484 u[0] = 1.;
7485 d[0] = 0.;
7486 }
7487 else
7488 {
7489 int i;
7490 const int *b = Binom(p);
7491 const double xpy = x + y, ptx = p*x;
7492 double z = 1.;
7493
7494 for (i = 1; i < p; i++)
7495 {
7496 d[i] = b[i]*z*(i*xpy - ptx);
7497 z *= x;
7498 u[i] = b[i]*z;
7499 }
7500 d[p] = p*z;
7501 u[p] = z*x;
7502 z = 1.;
7503 for (i--; i > 0; i--)
7504 {
7505 d[i] *= z;
7506 z *= y;
7507 u[i] *= z;
7508 }
7509 d[0] = -p*z;
7510 u[0] = z*y;
7511 }
7512 }
7513
CalcDBinomTerms(const int p,const double x,const double y,double * d)7514 void Poly_1D::CalcDBinomTerms(const int p, const double x, const double y,
7515 double *d)
7516 {
7517 if (p == 0)
7518 {
7519 d[0] = 0.;
7520 }
7521 else
7522 {
7523 int i;
7524 const int *b = Binom(p);
7525 const double xpy = x + y, ptx = p*x;
7526 double z = 1.;
7527
7528 for (i = 1; i < p; i++)
7529 {
7530 d[i] = b[i]*z*(i*xpy - ptx);
7531 z *= x;
7532 }
7533 d[p] = p*z;
7534 z = 1.;
7535 for (i--; i > 0; i--)
7536 {
7537 d[i] *= z;
7538 z *= y;
7539 }
7540 d[0] = -p*z;
7541 }
7542 }
7543
CalcLegendre(const int p,const double x,double * u)7544 void Poly_1D::CalcLegendre(const int p, const double x, double *u)
7545 {
7546 // use the recursive definition for [-1,1]:
7547 // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z)
7548 double z;
7549 u[0] = 1.;
7550 if (p == 0) { return; }
7551 u[1] = z = 2.*x - 1.;
7552 for (int n = 1; n < p; n++)
7553 {
7554 u[n+1] = ((2*n + 1)*z*u[n] - n*u[n-1])/(n + 1);
7555 }
7556 }
7557
CalcLegendre(const int p,const double x,double * u,double * d)7558 void Poly_1D::CalcLegendre(const int p, const double x, double *u, double *d)
7559 {
7560 // use the recursive definition for [-1,1]:
7561 // (n+1)*P_{n+1}(z) = (2*n+1)*z*P_n(z)-n*P_{n-1}(z)
7562 // for the derivative use, z in [-1,1]:
7563 // P'_{n+1}(z) = (2*n+1)*P_n(z)+P'_{n-1}(z)
7564 double z;
7565 u[0] = 1.;
7566 d[0] = 0.;
7567 if (p == 0) { return; }
7568 u[1] = z = 2.*x - 1.;
7569 d[1] = 2.;
7570 for (int n = 1; n < p; n++)
7571 {
7572 u[n+1] = ((2*n + 1)*z*u[n] - n*u[n-1])/(n + 1);
7573 d[n+1] = (4*n + 2)*u[n] + d[n-1];
7574 }
7575 }
7576
CalcChebyshev(const int p,const double x,double * u)7577 void Poly_1D::CalcChebyshev(const int p, const double x, double *u)
7578 {
7579 // recursive definition, z in [-1,1]
7580 // T_0(z) = 1, T_1(z) = z
7581 // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z)
7582 double z;
7583 u[0] = 1.;
7584 if (p == 0) { return; }
7585 u[1] = z = 2.*x - 1.;
7586 for (int n = 1; n < p; n++)
7587 {
7588 u[n+1] = 2*z*u[n] - u[n-1];
7589 }
7590 }
7591
CalcChebyshev(const int p,const double x,double * u,double * d)7592 void Poly_1D::CalcChebyshev(const int p, const double x, double *u, double *d)
7593 {
7594 // recursive definition, z in [-1,1]
7595 // T_0(z) = 1, T_1(z) = z
7596 // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z)
7597 // T'_n(z) = n*U_{n-1}(z)
7598 // U_0(z) = 1 U_1(z) = 2*z
7599 // U_{n+1}(z) = 2*z*U_n(z) - U_{n-1}(z)
7600 // U_n(z) = z*U_{n-1}(z) + T_n(z) = z*T'_n(z)/n + T_n(z)
7601 // T'_{n+1}(z) = (n + 1)*(z*T'_n(z)/n + T_n(z))
7602 double z;
7603 u[0] = 1.;
7604 d[0] = 0.;
7605 if (p == 0) { return; }
7606 u[1] = z = 2.*x - 1.;
7607 d[1] = 2.;
7608 for (int n = 1; n < p; n++)
7609 {
7610 u[n+1] = 2*z*u[n] - u[n-1];
7611 d[n+1] = (n + 1)*(z*d[n]/n + 2*u[n]);
7612 }
7613 }
7614
CalcChebyshev(const int p,const double x,double * u,double * d,double * dd)7615 void Poly_1D::CalcChebyshev(const int p, const double x, double *u, double *d,
7616 double *dd)
7617 {
7618 // recursive definition, z in [-1,1]
7619 // T_0(z) = 1, T_1(z) = z
7620 // T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z)
7621 // T'_n(z) = n*U_{n-1}(z)
7622 // U_0(z) = 1 U_1(z) = 2*z
7623 // U_{n+1}(z) = 2*z*U_n(z) - U_{n-1}(z)
7624 // U_n(z) = z*U_{n-1}(z) + T_n(z) = z*T'_n(z)/n + T_n(z)
7625 // T'_{n+1}(z) = (n + 1)*(z*T'_n(z)/n + T_n(z))
7626 // T''_{n+1}(z) = (n + 1)*(2*(n + 1)*T'_n(z) + z*T''_n(z)) / n
7627 double z;
7628 u[0] = 1.;
7629 d[0] = 0.;
7630 dd[0]= 0.;
7631 if (p == 0) { return; }
7632 u[1] = z = 2.*x - 1.;
7633 d[1] = 2.;
7634 dd[1] = 0;
7635 for (int n = 1; n < p; n++)
7636 {
7637 u[n+1] = 2*z*u[n] - u[n-1];
7638 d[n+1] = (n + 1)*(z*d[n]/n + 2*u[n]);
7639 dd[n+1] = (n + 1)*(2.*(n + 1)*d[n] + z*dd[n])/n;
7640 }
7641 }
7642
GetPoints(const int p,const int btype)7643 const double *Poly_1D::GetPoints(const int p, const int btype)
7644 {
7645 BasisType::Check(btype);
7646 const int qtype = BasisType::GetQuadrature1D(btype);
7647
7648 if (qtype == Quadrature1D::Invalid) { return NULL; }
7649
7650 if (points_container.find(btype) == points_container.end())
7651 {
7652 points_container[btype] = new Array<double*>(h_mt);
7653 }
7654 Array<double*> &pts = *points_container[btype];
7655 if (pts.Size() <= p)
7656 {
7657 pts.SetSize(p + 1, NULL);
7658 }
7659 if (pts[p] == NULL)
7660 {
7661 pts[p] = new double[p + 1];
7662 quad_func.GivePolyPoints(p+1, pts[p], qtype);
7663 }
7664 return pts[p];
7665 }
7666
GetBasis(const int p,const int btype)7667 Poly_1D::Basis &Poly_1D::GetBasis(const int p, const int btype)
7668 {
7669 BasisType::Check(btype);
7670
7671 if ( bases_container.find(btype) == bases_container.end() )
7672 {
7673 // we haven't been asked for basis or points of this type yet
7674 bases_container[btype] = new Array<Basis*>(h_mt);
7675 }
7676 Array<Basis*> &bases = *bases_container[btype];
7677 if (bases.Size() <= p)
7678 {
7679 bases.SetSize(p + 1, NULL);
7680 }
7681 if (bases[p] == NULL)
7682 {
7683 EvalType etype;
7684 if (btype == BasisType::Positive) { etype = Positive; }
7685 else if (btype == BasisType::IntegratedGLL) { etype = Integrated; }
7686 else { etype = Barycentric; }
7687 bases[p] = new Basis(p, GetPoints(p, btype), etype);
7688 }
7689 return *bases[p];
7690 }
7691
~Poly_1D()7692 Poly_1D::~Poly_1D()
7693 {
7694 for (PointsMap::iterator it = points_container.begin();
7695 it != points_container.end() ; ++it)
7696 {
7697 Array<double*>& pts = *it->second;
7698 for ( int i = 0 ; i < pts.Size() ; ++i )
7699 {
7700 delete [] pts[i];
7701 }
7702 delete it->second;
7703 }
7704
7705 for (BasisMap::iterator it = bases_container.begin();
7706 it != bases_container.end() ; ++it)
7707 {
7708 Array<Basis*>& bases = *it->second;
7709 for ( int i = 0 ; i < bases.Size() ; ++i )
7710 {
7711 delete bases[i];
7712 }
7713 delete it->second;
7714 }
7715 }
7716
7717 Array2D<int> Poly_1D::binom;
7718 Poly_1D poly1d;
7719
7720
TensorBasisElement(const int dims,const int p,const int btype,const DofMapType dmtype)7721 TensorBasisElement::TensorBasisElement(const int dims, const int p,
7722 const int btype, const DofMapType dmtype)
7723 : b_type(btype),
7724 basis1d(poly1d.GetBasis(p, b_type))
7725 {
7726 if (dmtype == H1_DOF_MAP || dmtype == Sr_DOF_MAP)
7727 {
7728 switch (dims)
7729 {
7730 case 1:
7731 {
7732 dof_map.SetSize(p + 1);
7733 dof_map[0] = 0;
7734 dof_map[p] = 1;
7735 for (int i = 1; i < p; i++)
7736 {
7737 dof_map[i] = i+1;
7738 }
7739 break;
7740 }
7741 case 2:
7742 {
7743 const int p1 = p + 1;
7744 dof_map.SetSize(p1*p1);
7745
7746 // vertices
7747 dof_map[0 + 0*p1] = 0;
7748 dof_map[p + 0*p1] = 1;
7749 dof_map[p + p*p1] = 2;
7750 dof_map[0 + p*p1] = 3;
7751
7752 // edges
7753 int o = 4;
7754 for (int i = 1; i < p; i++)
7755 {
7756 dof_map[i + 0*p1] = o++;
7757 }
7758 for (int i = 1; i < p; i++)
7759 {
7760 dof_map[p + i*p1] = o++;
7761 }
7762 for (int i = 1; i < p; i++)
7763 {
7764 dof_map[(p-i) + p*p1] = o++;
7765 }
7766 for (int i = 1; i < p; i++)
7767 {
7768 dof_map[0 + (p-i)*p1] = o++;
7769 }
7770
7771 // interior
7772 for (int j = 1; j < p; j++)
7773 {
7774 for (int i = 1; i < p; i++)
7775 {
7776 dof_map[i + j*p1] = o++;
7777 }
7778 }
7779 break;
7780 }
7781 case 3:
7782 {
7783 const int p1 = p + 1;
7784 dof_map.SetSize(p1*p1*p1);
7785
7786 // vertices
7787 dof_map[0 + (0 + 0*p1)*p1] = 0;
7788 dof_map[p + (0 + 0*p1)*p1] = 1;
7789 dof_map[p + (p + 0*p1)*p1] = 2;
7790 dof_map[0 + (p + 0*p1)*p1] = 3;
7791 dof_map[0 + (0 + p*p1)*p1] = 4;
7792 dof_map[p + (0 + p*p1)*p1] = 5;
7793 dof_map[p + (p + p*p1)*p1] = 6;
7794 dof_map[0 + (p + p*p1)*p1] = 7;
7795
7796 // edges (see Hexahedron::edges in mesh/hexahedron.cpp).
7797 // edges (see Constants<Geometry::CUBE>::Edges in fem/geom.cpp).
7798 int o = 8;
7799 for (int i = 1; i < p; i++)
7800 {
7801 dof_map[i + (0 + 0*p1)*p1] = o++; // (0,1)
7802 }
7803 for (int i = 1; i < p; i++)
7804 {
7805 dof_map[p + (i + 0*p1)*p1] = o++; // (1,2)
7806 }
7807 for (int i = 1; i < p; i++)
7808 {
7809 dof_map[i + (p + 0*p1)*p1] = o++; // (3,2)
7810 }
7811 for (int i = 1; i < p; i++)
7812 {
7813 dof_map[0 + (i + 0*p1)*p1] = o++; // (0,3)
7814 }
7815 for (int i = 1; i < p; i++)
7816 {
7817 dof_map[i + (0 + p*p1)*p1] = o++; // (4,5)
7818 }
7819 for (int i = 1; i < p; i++)
7820 {
7821 dof_map[p + (i + p*p1)*p1] = o++; // (5,6)
7822 }
7823 for (int i = 1; i < p; i++)
7824 {
7825 dof_map[i + (p + p*p1)*p1] = o++; // (7,6)
7826 }
7827 for (int i = 1; i < p; i++)
7828 {
7829 dof_map[0 + (i + p*p1)*p1] = o++; // (4,7)
7830 }
7831 for (int i = 1; i < p; i++)
7832 {
7833 dof_map[0 + (0 + i*p1)*p1] = o++; // (0,4)
7834 }
7835 for (int i = 1; i < p; i++)
7836 {
7837 dof_map[p + (0 + i*p1)*p1] = o++; // (1,5)
7838 }
7839 for (int i = 1; i < p; i++)
7840 {
7841 dof_map[p + (p + i*p1)*p1] = o++; // (2,6)
7842 }
7843 for (int i = 1; i < p; i++)
7844 {
7845 dof_map[0 + (p + i*p1)*p1] = o++; // (3,7)
7846 }
7847
7848 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
7849 for (int j = 1; j < p; j++)
7850 {
7851 for (int i = 1; i < p; i++)
7852 {
7853 dof_map[i + ((p-j) + 0*p1)*p1] = o++; // (3,2,1,0)
7854 }
7855 }
7856 for (int j = 1; j < p; j++)
7857 {
7858 for (int i = 1; i < p; i++)
7859 {
7860 dof_map[i + (0 + j*p1)*p1] = o++; // (0,1,5,4)
7861 }
7862 }
7863 for (int j = 1; j < p; j++)
7864 {
7865 for (int i = 1; i < p; i++)
7866 {
7867 dof_map[p + (i + j*p1)*p1] = o++; // (1,2,6,5)
7868 }
7869 }
7870 for (int j = 1; j < p; j++)
7871 {
7872 for (int i = 1; i < p; i++)
7873 {
7874 dof_map[(p-i) + (p + j*p1)*p1] = o++; // (2,3,7,6)
7875 }
7876 }
7877 for (int j = 1; j < p; j++)
7878 {
7879 for (int i = 1; i < p; i++)
7880 {
7881 dof_map[0 + ((p-i) + j*p1)*p1] = o++; // (3,0,4,7)
7882 }
7883 }
7884 for (int j = 1; j < p; j++)
7885 {
7886 for (int i = 1; i < p; i++)
7887 {
7888 dof_map[i + (j + p*p1)*p1] = o++; // (4,5,6,7)
7889 }
7890 }
7891
7892 // interior
7893 for (int k = 1; k < p; k++)
7894 {
7895 for (int j = 1; j < p; j++)
7896 {
7897 for (int i = 1; i < p; i++)
7898 {
7899 dof_map[i + (j + k*p1)*p1] = o++;
7900 }
7901 }
7902 }
7903 break;
7904 }
7905 default:
7906 MFEM_ABORT("invalid dimension: " << dims);
7907 break;
7908 }
7909 }
7910 else if (dmtype == L2_DOF_MAP)
7911 {
7912 // leave dof_map empty, indicating that the dofs are ordered
7913 // lexicographically, i.e. the dof_map is identity
7914 }
7915 else
7916 {
7917 MFEM_ABORT("invalid DofMapType: " << dmtype);
7918 }
7919 }
7920
7921
NodalTensorFiniteElement(const int dims,const int p,const int btype,const DofMapType dmtype)7922 NodalTensorFiniteElement::NodalTensorFiniteElement(const int dims,
7923 const int p,
7924 const int btype,
7925 const DofMapType dmtype)
7926 : NodalFiniteElement(dims, GetTensorProductGeometry(dims), Pow(p + 1, dims),
7927 p, dims > 1 ? FunctionSpace::Qk : FunctionSpace::Pk),
7928 TensorBasisElement(dims, p, btype, dmtype)
7929 {
7930 lex_ordering = dof_map;
7931 }
7932
7933
PositiveTensorFiniteElement(const int dims,const int p,const DofMapType dmtype)7934 PositiveTensorFiniteElement::PositiveTensorFiniteElement(
7935 const int dims, const int p, const DofMapType dmtype)
7936 : PositiveFiniteElement(dims, GetTensorProductGeometry(dims),
7937 Pow(p + 1, dims), p,
7938 dims > 1 ? FunctionSpace::Qk : FunctionSpace::Pk),
7939 TensorBasisElement(dims, p, BasisType::Positive, dmtype) { }
7940
VectorTensorFiniteElement(const int dims,const int d,const int p,const int cbtype,const int obtype,const int M,const DofMapType dmtype)7941 VectorTensorFiniteElement::VectorTensorFiniteElement(const int dims,
7942 const int d,
7943 const int p,
7944 const int cbtype,
7945 const int obtype,
7946 const int M,
7947 const DofMapType dmtype)
7948 : VectorFiniteElement(dims, GetTensorProductGeometry(dims), d,
7949 p, M, FunctionSpace::Qk),
7950 TensorBasisElement(dims, p, VerifyNodal(cbtype), dmtype),
7951 cbasis1d(poly1d.GetBasis(p, VerifyClosed(cbtype))),
7952 obasis1d(poly1d.GetBasis(p - 1, VerifyOpen(obtype)))
7953 {
7954 MFEM_VERIFY(dims > 1, "Constructor for VectorTensorFiniteElement with both "
7955 "open and closed bases is not valid for 1D elements.");
7956 }
7957
VectorTensorFiniteElement(const int dims,const int d,const int p,const int obtype,const int M,const DofMapType dmtype)7958 VectorTensorFiniteElement::VectorTensorFiniteElement(const int dims,
7959 const int d,
7960 const int p,
7961 const int obtype,
7962 const int M,
7963 const DofMapType dmtype)
7964 : VectorFiniteElement(dims, GetTensorProductGeometry(dims), d,
7965 p, M, FunctionSpace::Pk),
7966 TensorBasisElement(dims, p, obtype, dmtype),
7967 cbasis1d(poly1d.GetBasis(p, VerifyOpen(obtype))),
7968 obasis1d(poly1d.GetBasis(p, VerifyOpen(obtype)))
7969 {
7970 MFEM_VERIFY(dims == 1, "Constructor for VectorTensorFiniteElement without "
7971 "closed basis is only valid for 1D elements.");
7972 }
7973
H1_SegmentElement(const int p,const int btype)7974 H1_SegmentElement::H1_SegmentElement(const int p, const int btype)
7975 : NodalTensorFiniteElement(1, p, VerifyClosed(btype), H1_DOF_MAP)
7976 {
7977 const double *cp = poly1d.ClosedPoints(p, b_type);
7978
7979 #ifndef MFEM_THREAD_SAFE
7980 shape_x.SetSize(p+1);
7981 dshape_x.SetSize(p+1);
7982 d2shape_x.SetSize(p+1);
7983 #endif
7984
7985 Nodes.IntPoint(0).x = cp[0];
7986 Nodes.IntPoint(1).x = cp[p];
7987 for (int i = 1; i < p; i++)
7988 {
7989 Nodes.IntPoint(i+1).x = cp[i];
7990 }
7991 }
7992
CalcShape(const IntegrationPoint & ip,Vector & shape) const7993 void H1_SegmentElement::CalcShape(const IntegrationPoint &ip,
7994 Vector &shape) const
7995 {
7996 const int p = order;
7997
7998 #ifdef MFEM_THREAD_SAFE
7999 Vector shape_x(p+1);
8000 #endif
8001
8002 basis1d.Eval(ip.x, shape_x);
8003
8004 shape(0) = shape_x(0);
8005 shape(1) = shape_x(p);
8006 for (int i = 1; i < p; i++)
8007 {
8008 shape(i+1) = shape_x(i);
8009 }
8010 }
8011
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8012 void H1_SegmentElement::CalcDShape(const IntegrationPoint &ip,
8013 DenseMatrix &dshape) const
8014 {
8015 const int p = order;
8016
8017 #ifdef MFEM_THREAD_SAFE
8018 Vector shape_x(p+1), dshape_x(p+1);
8019 #endif
8020
8021 basis1d.Eval(ip.x, shape_x, dshape_x);
8022
8023 dshape(0,0) = dshape_x(0);
8024 dshape(1,0) = dshape_x(p);
8025 for (int i = 1; i < p; i++)
8026 {
8027 dshape(i+1,0) = dshape_x(i);
8028 }
8029 }
8030
CalcHessian(const IntegrationPoint & ip,DenseMatrix & Hessian) const8031 void H1_SegmentElement::CalcHessian(const IntegrationPoint &ip,
8032 DenseMatrix &Hessian) const
8033 {
8034 const int p = order;
8035
8036 #ifdef MFEM_THREAD_SAFE
8037 Vector shape_x(p+1), dshape_x(p+1), d2shape_x(p+1);
8038 #endif
8039
8040 basis1d.Eval(ip.x, shape_x, dshape_x, d2shape_x);
8041
8042 Hessian(0,0) = d2shape_x(0);
8043 Hessian(1,0) = d2shape_x(p);
8044 for (int i = 1; i < p; i++)
8045 {
8046 Hessian(i+1,0) = d2shape_x(i);
8047 }
8048 }
8049
ProjectDelta(int vertex,Vector & dofs) const8050 void H1_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
8051 {
8052 const int p = order;
8053 const double *cp = poly1d.ClosedPoints(p, b_type);
8054
8055 switch (vertex)
8056 {
8057 case 0:
8058 dofs(0) = poly1d.CalcDelta(p, (1.0 - cp[0]));
8059 dofs(1) = poly1d.CalcDelta(p, (1.0 - cp[p]));
8060 for (int i = 1; i < p; i++)
8061 {
8062 dofs(i+1) = poly1d.CalcDelta(p, (1.0 - cp[i]));
8063 }
8064 break;
8065
8066 case 1:
8067 dofs(0) = poly1d.CalcDelta(p, cp[0]);
8068 dofs(1) = poly1d.CalcDelta(p, cp[p]);
8069 for (int i = 1; i < p; i++)
8070 {
8071 dofs(i+1) = poly1d.CalcDelta(p, cp[i]);
8072 }
8073 break;
8074 }
8075 }
8076
8077
H1_QuadrilateralElement(const int p,const int btype)8078 H1_QuadrilateralElement::H1_QuadrilateralElement(const int p, const int btype)
8079 : NodalTensorFiniteElement(2, p, VerifyClosed(btype), H1_DOF_MAP)
8080 {
8081 const double *cp = poly1d.ClosedPoints(p, b_type);
8082
8083 #ifndef MFEM_THREAD_SAFE
8084 const int p1 = p + 1;
8085
8086 shape_x.SetSize(p1);
8087 shape_y.SetSize(p1);
8088 dshape_x.SetSize(p1);
8089 dshape_y.SetSize(p1);
8090 d2shape_x.SetSize(p1);
8091 d2shape_y.SetSize(p1);
8092 #endif
8093
8094 int o = 0;
8095 for (int j = 0; j <= p; j++)
8096 {
8097 for (int i = 0; i <= p; i++)
8098 {
8099 Nodes.IntPoint(dof_map[o++]).Set2(cp[i], cp[j]);
8100 }
8101 }
8102 }
8103
CalcShape(const IntegrationPoint & ip,Vector & shape) const8104 void H1_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
8105 Vector &shape) const
8106 {
8107 const int p = order;
8108
8109 #ifdef MFEM_THREAD_SAFE
8110 Vector shape_x(p+1), shape_y(p+1);
8111 #endif
8112
8113 basis1d.Eval(ip.x, shape_x);
8114 basis1d.Eval(ip.y, shape_y);
8115
8116 for (int o = 0, j = 0; j <= p; j++)
8117 for (int i = 0; i <= p; i++)
8118 {
8119 shape(dof_map[o++]) = shape_x(i)*shape_y(j);
8120 }
8121 }
8122
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8123 void H1_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
8124 DenseMatrix &dshape) const
8125 {
8126 const int p = order;
8127
8128 #ifdef MFEM_THREAD_SAFE
8129 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
8130 #endif
8131
8132 basis1d.Eval(ip.x, shape_x, dshape_x);
8133 basis1d.Eval(ip.y, shape_y, dshape_y);
8134
8135 for (int o = 0, j = 0; j <= p; j++)
8136 {
8137 for (int i = 0; i <= p; i++)
8138 {
8139 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j);
8140 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j); o++;
8141 }
8142 }
8143 }
8144
CalcHessian(const IntegrationPoint & ip,DenseMatrix & Hessian) const8145 void H1_QuadrilateralElement::CalcHessian(const IntegrationPoint &ip,
8146 DenseMatrix &Hessian) const
8147 {
8148 const int p = order;
8149
8150 #ifdef MFEM_THREAD_SAFE
8151 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1),
8152 d2shape_x(p+1), d2shape_y(p+1);
8153 #endif
8154
8155 basis1d.Eval(ip.x, shape_x, dshape_x, d2shape_x);
8156 basis1d.Eval(ip.y, shape_y, dshape_y, d2shape_y);
8157
8158 for (int o = 0, j = 0; j <= p; j++)
8159 {
8160 for (int i = 0; i <= p; i++)
8161 {
8162 Hessian(dof_map[o],0) = d2shape_x(i)* shape_y(j);
8163 Hessian(dof_map[o],1) = dshape_x(i)* dshape_y(j);
8164 Hessian(dof_map[o],2) = shape_x(i)*d2shape_y(j); o++;
8165 }
8166 }
8167 }
8168
ProjectDelta(int vertex,Vector & dofs) const8169 void H1_QuadrilateralElement::ProjectDelta(int vertex, Vector &dofs) const
8170 {
8171 const int p = order;
8172 const double *cp = poly1d.ClosedPoints(p, b_type);
8173
8174 #ifdef MFEM_THREAD_SAFE
8175 Vector shape_x(p+1), shape_y(p+1);
8176 #endif
8177
8178 for (int i = 0; i <= p; i++)
8179 {
8180 shape_x(i) = poly1d.CalcDelta(p, (1.0 - cp[i]));
8181 shape_y(i) = poly1d.CalcDelta(p, cp[i]);
8182 }
8183
8184 switch (vertex)
8185 {
8186 case 0:
8187 for (int o = 0, j = 0; j <= p; j++)
8188 for (int i = 0; i <= p; i++)
8189 {
8190 dofs(dof_map[o++]) = shape_x(i)*shape_x(j);
8191 }
8192 break;
8193 case 1:
8194 for (int o = 0, j = 0; j <= p; j++)
8195 for (int i = 0; i <= p; i++)
8196 {
8197 dofs(dof_map[o++]) = shape_y(i)*shape_x(j);
8198 }
8199 break;
8200 case 2:
8201 for (int o = 0, j = 0; j <= p; j++)
8202 for (int i = 0; i <= p; i++)
8203 {
8204 dofs(dof_map[o++]) = shape_y(i)*shape_y(j);
8205 }
8206 break;
8207 case 3:
8208 for (int o = 0, j = 0; j <= p; j++)
8209 for (int i = 0; i <= p; i++)
8210 {
8211 dofs(dof_map[o++]) = shape_x(i)*shape_y(j);
8212 }
8213 break;
8214 }
8215 }
8216
8217
H1_HexahedronElement(const int p,const int btype)8218 H1_HexahedronElement::H1_HexahedronElement(const int p, const int btype)
8219 : NodalTensorFiniteElement(3, p, VerifyClosed(btype), H1_DOF_MAP)
8220 {
8221 const double *cp = poly1d.ClosedPoints(p, b_type);
8222
8223 #ifndef MFEM_THREAD_SAFE
8224 const int p1 = p + 1;
8225
8226 shape_x.SetSize(p1);
8227 shape_y.SetSize(p1);
8228 shape_z.SetSize(p1);
8229 dshape_x.SetSize(p1);
8230 dshape_y.SetSize(p1);
8231 dshape_z.SetSize(p1);
8232 d2shape_x.SetSize(p1);
8233 d2shape_y.SetSize(p1);
8234 d2shape_z.SetSize(p1);
8235 #endif
8236
8237 int o = 0;
8238 for (int k = 0; k <= p; k++)
8239 for (int j = 0; j <= p; j++)
8240 for (int i = 0; i <= p; i++)
8241 {
8242 Nodes.IntPoint(dof_map[o++]).Set3(cp[i], cp[j], cp[k]);
8243 }
8244 }
8245
CalcShape(const IntegrationPoint & ip,Vector & shape) const8246 void H1_HexahedronElement::CalcShape(const IntegrationPoint &ip,
8247 Vector &shape) const
8248 {
8249 const int p = order;
8250
8251 #ifdef MFEM_THREAD_SAFE
8252 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
8253 #endif
8254
8255 basis1d.Eval(ip.x, shape_x);
8256 basis1d.Eval(ip.y, shape_y);
8257 basis1d.Eval(ip.z, shape_z);
8258
8259 for (int o = 0, k = 0; k <= p; k++)
8260 for (int j = 0; j <= p; j++)
8261 for (int i = 0; i <= p; i++)
8262 {
8263 shape(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_z(k);
8264 }
8265 }
8266
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8267 void H1_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
8268 DenseMatrix &dshape) const
8269 {
8270 const int p = order;
8271
8272 #ifdef MFEM_THREAD_SAFE
8273 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
8274 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
8275 #endif
8276
8277 basis1d.Eval(ip.x, shape_x, dshape_x);
8278 basis1d.Eval(ip.y, shape_y, dshape_y);
8279 basis1d.Eval(ip.z, shape_z, dshape_z);
8280
8281 for (int o = 0, k = 0; k <= p; k++)
8282 for (int j = 0; j <= p; j++)
8283 for (int i = 0; i <= p; i++)
8284 {
8285 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j)* shape_z(k);
8286 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j)* shape_z(k);
8287 dshape(dof_map[o],2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
8288 }
8289 }
8290
CalcHessian(const IntegrationPoint & ip,DenseMatrix & Hessian) const8291 void H1_HexahedronElement::CalcHessian(const IntegrationPoint &ip,
8292 DenseMatrix &Hessian) const
8293 {
8294 const int p = order;
8295
8296 #ifdef MFEM_THREAD_SAFE
8297 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
8298 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
8299 Vector d2shape_x(p+1), d2shape_y(p+1), d2shape_z(p+1);
8300 #endif
8301
8302 basis1d.Eval(ip.x, shape_x, dshape_x, d2shape_x);
8303 basis1d.Eval(ip.y, shape_y, dshape_y, d2shape_y);
8304 basis1d.Eval(ip.z, shape_z, dshape_z, d2shape_z);
8305
8306 for (int o = 0, k = 0; k <= p; k++)
8307 for (int j = 0; j <= p; j++)
8308 for (int i = 0; i <= p; i++)
8309 {
8310 Hessian(dof_map[o],0) = d2shape_x(i)* shape_y(j)* shape_z(k);
8311 Hessian(dof_map[o],1) = dshape_x(i)* dshape_y(j)* shape_z(k);
8312 Hessian(dof_map[o],2) = dshape_x(i)* shape_y(j)* dshape_z(k);
8313 Hessian(dof_map[o],3) = shape_x(i)*d2shape_y(j)* shape_z(k);
8314 Hessian(dof_map[o],4) = shape_x(i)* dshape_y(j)* dshape_z(k);
8315 Hessian(dof_map[o],5) = shape_x(i)* shape_y(j)*d2shape_z(k);
8316 o++;
8317 }
8318 }
8319
ProjectDelta(int vertex,Vector & dofs) const8320 void H1_HexahedronElement::ProjectDelta(int vertex, Vector &dofs) const
8321 {
8322 const int p = order;
8323 const double *cp = poly1d.ClosedPoints(p,b_type);
8324
8325 #ifdef MFEM_THREAD_SAFE
8326 Vector shape_x(p+1), shape_y(p+1);
8327 #endif
8328
8329 for (int i = 0; i <= p; i++)
8330 {
8331 shape_x(i) = poly1d.CalcDelta(p, (1.0 - cp[i]));
8332 shape_y(i) = poly1d.CalcDelta(p, cp[i]);
8333 }
8334
8335 switch (vertex)
8336 {
8337 case 0:
8338 for (int o = 0, k = 0; k <= p; k++)
8339 for (int j = 0; j <= p; j++)
8340 for (int i = 0; i <= p; i++)
8341 {
8342 dofs(dof_map[o++]) = shape_x(i)*shape_x(j)*shape_x(k);
8343 }
8344 break;
8345 case 1:
8346 for (int o = 0, k = 0; k <= p; k++)
8347 for (int j = 0; j <= p; j++)
8348 for (int i = 0; i <= p; i++)
8349 {
8350 dofs(dof_map[o++]) = shape_y(i)*shape_x(j)*shape_x(k);
8351 }
8352 break;
8353 case 2:
8354 for (int o = 0, k = 0; k <= p; k++)
8355 for (int j = 0; j <= p; j++)
8356 for (int i = 0; i <= p; i++)
8357 {
8358 dofs(dof_map[o++]) = shape_y(i)*shape_y(j)*shape_x(k);
8359 }
8360 break;
8361 case 3:
8362 for (int o = 0, k = 0; k <= p; k++)
8363 for (int j = 0; j <= p; j++)
8364 for (int i = 0; i <= p; i++)
8365 {
8366 dofs(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_x(k);
8367 }
8368 break;
8369 case 4:
8370 for (int o = 0, k = 0; k <= p; k++)
8371 for (int j = 0; j <= p; j++)
8372 for (int i = 0; i <= p; i++)
8373 {
8374 dofs(dof_map[o++]) = shape_x(i)*shape_x(j)*shape_y(k);
8375 }
8376 break;
8377 case 5:
8378 for (int o = 0, k = 0; k <= p; k++)
8379 for (int j = 0; j <= p; j++)
8380 for (int i = 0; i <= p; i++)
8381 {
8382 dofs(dof_map[o++]) = shape_y(i)*shape_x(j)*shape_y(k);
8383 }
8384 break;
8385 case 6:
8386 for (int o = 0, k = 0; k <= p; k++)
8387 for (int j = 0; j <= p; j++)
8388 for (int i = 0; i <= p; i++)
8389 {
8390 dofs(dof_map[o++]) = shape_y(i)*shape_y(j)*shape_y(k);
8391 }
8392 break;
8393 case 7:
8394 for (int o = 0, k = 0; k <= p; k++)
8395 for (int j = 0; j <= p; j++)
8396 for (int i = 0; i <= p; i++)
8397 {
8398 dofs(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_y(k);
8399 }
8400 break;
8401 }
8402 }
8403
8404
H1Pos_SegmentElement(const int p)8405 H1Pos_SegmentElement::H1Pos_SegmentElement(const int p)
8406 : PositiveTensorFiniteElement(1, p, H1_DOF_MAP)
8407 {
8408 #ifndef MFEM_THREAD_SAFE
8409 // thread private versions; see class header.
8410 shape_x.SetSize(p+1);
8411 dshape_x.SetSize(p+1);
8412 #endif
8413
8414 // Endpoints need to be first in the list, so reorder them.
8415 Nodes.IntPoint(0).x = 0.0;
8416 Nodes.IntPoint(1).x = 1.0;
8417 for (int i = 1; i < p; i++)
8418 {
8419 Nodes.IntPoint(i+1).x = double(i)/p;
8420 }
8421 }
8422
CalcShape(const IntegrationPoint & ip,Vector & shape) const8423 void H1Pos_SegmentElement::CalcShape(const IntegrationPoint &ip,
8424 Vector &shape) const
8425 {
8426 const int p = order;
8427
8428 #ifdef MFEM_THREAD_SAFE
8429 Vector shape_x(p+1);
8430 #endif
8431
8432 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData() );
8433
8434 // Endpoints need to be first in the list, so reorder them.
8435 shape(0) = shape_x(0);
8436 shape(1) = shape_x(p);
8437 for (int i = 1; i < p; i++)
8438 {
8439 shape(i+1) = shape_x(i);
8440 }
8441 }
8442
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8443 void H1Pos_SegmentElement::CalcDShape(const IntegrationPoint &ip,
8444 DenseMatrix &dshape) const
8445 {
8446 const int p = order;
8447
8448 #ifdef MFEM_THREAD_SAFE
8449 Vector shape_x(p+1), dshape_x(p+1);
8450 #endif
8451
8452 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData(), dshape_x.GetData() );
8453
8454 // Endpoints need to be first in the list, so reorder them.
8455 dshape(0,0) = dshape_x(0);
8456 dshape(1,0) = dshape_x(p);
8457 for (int i = 1; i < p; i++)
8458 {
8459 dshape(i+1,0) = dshape_x(i);
8460 }
8461 }
8462
ProjectDelta(int vertex,Vector & dofs) const8463 void H1Pos_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
8464 {
8465 dofs = 0.0;
8466 dofs[vertex] = 1.0;
8467 }
8468
8469
H1Pos_QuadrilateralElement(const int p)8470 H1Pos_QuadrilateralElement::H1Pos_QuadrilateralElement(const int p)
8471 : PositiveTensorFiniteElement(2, p, H1_DOF_MAP)
8472 {
8473 #ifndef MFEM_THREAD_SAFE
8474 const int p1 = p + 1;
8475
8476 shape_x.SetSize(p1);
8477 shape_y.SetSize(p1);
8478 dshape_x.SetSize(p1);
8479 dshape_y.SetSize(p1);
8480 #endif
8481
8482 int o = 0;
8483 for (int j = 0; j <= p; j++)
8484 for (int i = 0; i <= p; i++)
8485 {
8486 Nodes.IntPoint(dof_map[o++]).Set2(double(i)/p, double(j)/p);
8487 }
8488 }
8489
CalcShape(const IntegrationPoint & ip,Vector & shape) const8490 void H1Pos_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
8491 Vector &shape) const
8492 {
8493 const int p = order;
8494
8495 #ifdef MFEM_THREAD_SAFE
8496 Vector shape_x(p+1), shape_y(p+1);
8497 #endif
8498
8499 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData() );
8500 Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData() );
8501
8502 // Reorder so that vertices are at the beginning of the list
8503 for (int o = 0, j = 0; j <= p; j++)
8504 for (int i = 0; i <= p; i++)
8505 {
8506 shape(dof_map[o++]) = shape_x(i)*shape_y(j);
8507 }
8508 }
8509
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8510 void H1Pos_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
8511 DenseMatrix &dshape) const
8512 {
8513 const int p = order;
8514
8515 #ifdef MFEM_THREAD_SAFE
8516 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
8517 #endif
8518
8519 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData(), dshape_x.GetData() );
8520 Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData(), dshape_y.GetData() );
8521
8522 // Reorder so that vertices are at the beginning of the list
8523 for (int o = 0, j = 0; j <= p; j++)
8524 for (int i = 0; i <= p; i++)
8525 {
8526 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j);
8527 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j); o++;
8528 }
8529 }
8530
ProjectDelta(int vertex,Vector & dofs) const8531 void H1Pos_QuadrilateralElement::ProjectDelta(int vertex, Vector &dofs) const
8532 {
8533 dofs = 0.0;
8534 dofs[vertex] = 1.0;
8535 }
8536
8537
H1Pos_HexahedronElement(const int p)8538 H1Pos_HexahedronElement::H1Pos_HexahedronElement(const int p)
8539 : PositiveTensorFiniteElement(3, p, H1_DOF_MAP)
8540 {
8541 #ifndef MFEM_THREAD_SAFE
8542 const int p1 = p + 1;
8543
8544 shape_x.SetSize(p1);
8545 shape_y.SetSize(p1);
8546 shape_z.SetSize(p1);
8547 dshape_x.SetSize(p1);
8548 dshape_y.SetSize(p1);
8549 dshape_z.SetSize(p1);
8550 #endif
8551
8552 int o = 0;
8553 for (int k = 0; k <= p; k++)
8554 for (int j = 0; j <= p; j++)
8555 for (int i = 0; i <= p; i++)
8556 Nodes.IntPoint(dof_map[o++]).Set3(double(i)/p, double(j)/p,
8557 double(k)/p);
8558 }
8559
CalcShape(const IntegrationPoint & ip,Vector & shape) const8560 void H1Pos_HexahedronElement::CalcShape(const IntegrationPoint &ip,
8561 Vector &shape) const
8562 {
8563 const int p = order;
8564
8565 #ifdef MFEM_THREAD_SAFE
8566 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
8567 #endif
8568
8569 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData() );
8570 Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData() );
8571 Poly_1D::CalcBernstein(p, ip.z, shape_z.GetData() );
8572
8573 for (int o = 0, k = 0; k <= p; k++)
8574 for (int j = 0; j <= p; j++)
8575 for (int i = 0; i <= p; i++)
8576 {
8577 shape(dof_map[o++]) = shape_x(i)*shape_y(j)*shape_z(k);
8578 }
8579 }
8580
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8581 void H1Pos_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
8582 DenseMatrix &dshape) const
8583 {
8584 const int p = order;
8585
8586 #ifdef MFEM_THREAD_SAFE
8587 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
8588 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
8589 #endif
8590
8591 Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData(), dshape_x.GetData() );
8592 Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData(), dshape_y.GetData() );
8593 Poly_1D::CalcBernstein(p, ip.z, shape_z.GetData(), dshape_z.GetData() );
8594
8595 for (int o = 0, k = 0; k <= p; k++)
8596 for (int j = 0; j <= p; j++)
8597 for (int i = 0; i <= p; i++)
8598 {
8599 dshape(dof_map[o],0) = dshape_x(i)* shape_y(j)* shape_z(k);
8600 dshape(dof_map[o],1) = shape_x(i)*dshape_y(j)* shape_z(k);
8601 dshape(dof_map[o],2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
8602 }
8603 }
8604
ProjectDelta(int vertex,Vector & dofs) const8605 void H1Pos_HexahedronElement::ProjectDelta(int vertex, Vector &dofs) const
8606 {
8607 dofs = 0.0;
8608 dofs[vertex] = 1.0;
8609 }
8610
8611
H1_TriangleElement(const int p,const int btype)8612 H1_TriangleElement::H1_TriangleElement(const int p, const int btype)
8613 : NodalFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
8614 FunctionSpace::Pk)
8615 {
8616 const double *cp = poly1d.ClosedPoints(p, VerifyNodal(VerifyClosed(btype)));
8617
8618 #ifndef MFEM_THREAD_SAFE
8619 shape_x.SetSize(p + 1);
8620 shape_y.SetSize(p + 1);
8621 shape_l.SetSize(p + 1);
8622 dshape_x.SetSize(p + 1);
8623 dshape_y.SetSize(p + 1);
8624 dshape_l.SetSize(p + 1);
8625 ddshape_x.SetSize(p + 1);
8626 ddshape_y.SetSize(p + 1);
8627 ddshape_l.SetSize(p + 1);
8628 u.SetSize(dof);
8629 du.SetSize(dof, dim);
8630 ddu.SetSize(dof, (dim * (dim + 1)) / 2 );
8631 #else
8632 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
8633 #endif
8634
8635 int p2p3 = 2*p + 3;
8636 auto idx = [p2p3](int i, int j) { return ((p2p3-j)*j)/2+i; };
8637 lex_ordering.SetSize(dof);
8638
8639 // vertices
8640 lex_ordering[idx(0,0)] = 0;
8641 Nodes.IntPoint(0).Set2(cp[0], cp[0]);
8642 lex_ordering[idx(p,0)] = 1;
8643 Nodes.IntPoint(1).Set2(cp[p], cp[0]);
8644 lex_ordering[idx(0,p)] = 2;
8645 Nodes.IntPoint(2).Set2(cp[0], cp[p]);
8646
8647 // edges
8648 int o = 3;
8649 for (int i = 1; i < p; i++)
8650 {
8651 lex_ordering[idx(i,0)] = o;
8652 Nodes.IntPoint(o++).Set2(cp[i], cp[0]);
8653 }
8654 for (int i = 1; i < p; i++)
8655 {
8656 lex_ordering[idx(p-i,i)] = o;
8657 Nodes.IntPoint(o++).Set2(cp[p-i], cp[i]);
8658 }
8659 for (int i = 1; i < p; i++)
8660 {
8661 lex_ordering[idx(0,p-i)] = o;
8662 Nodes.IntPoint(o++).Set2(cp[0], cp[p-i]);
8663 }
8664
8665 // interior
8666 for (int j = 1; j < p; j++)
8667 for (int i = 1; i + j < p; i++)
8668 {
8669 const double w = cp[i] + cp[j] + cp[p-i-j];
8670 lex_ordering[idx(i,j)] = o;
8671 Nodes.IntPoint(o++).Set2(cp[i]/w, cp[j]/w);
8672 }
8673
8674 DenseMatrix T(dof);
8675 for (int k = 0; k < dof; k++)
8676 {
8677 IntegrationPoint &ip = Nodes.IntPoint(k);
8678 poly1d.CalcBasis(p, ip.x, shape_x);
8679 poly1d.CalcBasis(p, ip.y, shape_y);
8680 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
8681
8682 o = 0;
8683 for (int j = 0; j <= p; j++)
8684 for (int i = 0; i + j <= p; i++)
8685 {
8686 T(o++, k) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
8687 }
8688 }
8689
8690 Ti.Factor(T);
8691 // mfem::out << "H1_TriangleElement(" << p << ") : "; Ti.TestInversion();
8692 }
8693
CalcShape(const IntegrationPoint & ip,Vector & shape) const8694 void H1_TriangleElement::CalcShape(const IntegrationPoint &ip,
8695 Vector &shape) const
8696 {
8697 const int p = order;
8698
8699 #ifdef MFEM_THREAD_SAFE
8700 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1), u(dof);
8701 #endif
8702
8703 poly1d.CalcBasis(p, ip.x, shape_x);
8704 poly1d.CalcBasis(p, ip.y, shape_y);
8705 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
8706
8707 for (int o = 0, j = 0; j <= p; j++)
8708 for (int i = 0; i + j <= p; i++)
8709 {
8710 u(o++) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
8711 }
8712
8713 Ti.Mult(u, shape);
8714 }
8715
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8716 void H1_TriangleElement::CalcDShape(const IntegrationPoint &ip,
8717 DenseMatrix &dshape) const
8718 {
8719 const int p = order;
8720
8721 #ifdef MFEM_THREAD_SAFE
8722 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
8723 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
8724 DenseMatrix du(dof, dim);
8725 #endif
8726
8727 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
8728 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
8729 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l);
8730
8731 for (int o = 0, j = 0; j <= p; j++)
8732 for (int i = 0; i + j <= p; i++)
8733 {
8734 int k = p - i - j;
8735 du(o,0) = ((dshape_x(i)* shape_l(k)) -
8736 ( shape_x(i)*dshape_l(k)))*shape_y(j);
8737 du(o,1) = ((dshape_y(j)* shape_l(k)) -
8738 ( shape_y(j)*dshape_l(k)))*shape_x(i);
8739 o++;
8740 }
8741
8742 Ti.Mult(du, dshape);
8743 }
8744
CalcHessian(const IntegrationPoint & ip,DenseMatrix & ddshape) const8745 void H1_TriangleElement::CalcHessian(const IntegrationPoint &ip,
8746 DenseMatrix &ddshape) const
8747 {
8748 const int p = order;
8749 #ifdef MFEM_THREAD_SAFE
8750 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
8751 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
8752 Vector ddshape_x(p + 1), ddshape_y(p + 1), ddshape_l(p + 1);
8753 DenseMatrix ddu(dof, dim);
8754 #endif
8755
8756 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x, ddshape_x);
8757 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y, ddshape_y);
8758 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l, ddshape_l);
8759
8760 for (int o = 0, j = 0; j <= p; j++)
8761 for (int i = 0; i + j <= p; i++)
8762 {
8763 int k = p - i - j;
8764 // u_xx, u_xy, u_yy
8765 ddu(o,0) = ((ddshape_x(i) * shape_l(k)) - 2. * (dshape_x(i) * dshape_l(k)) +
8766 (shape_x(i) * ddshape_l(k))) * shape_y(j);
8767 ddu(o,1) = (((shape_x(i) * ddshape_l(k)) - dshape_x(i) * dshape_l(k)) * shape_y(
8768 j)) + (((dshape_x(i) * shape_l(k)) - (shape_x(i) * dshape_l(k))) * dshape_y(j));
8769 ddu(o,2) = ((ddshape_y(j) * shape_l(k)) - 2. * (dshape_y(j) * dshape_l(k)) +
8770 (shape_y(j) * ddshape_l(k))) * shape_x(i);
8771 o++;
8772 }
8773
8774 Ti.Mult(ddu, ddshape);
8775 }
8776
8777
H1_TetrahedronElement(const int p,const int btype)8778 H1_TetrahedronElement::H1_TetrahedronElement(const int p, const int btype)
8779 : NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6,
8780 p, FunctionSpace::Pk)
8781 {
8782 const double *cp = poly1d.ClosedPoints(p, VerifyNodal(VerifyClosed(btype)));
8783
8784 #ifndef MFEM_THREAD_SAFE
8785 shape_x.SetSize(p + 1);
8786 shape_y.SetSize(p + 1);
8787 shape_z.SetSize(p + 1);
8788 shape_l.SetSize(p + 1);
8789 dshape_x.SetSize(p + 1);
8790 dshape_y.SetSize(p + 1);
8791 dshape_z.SetSize(p + 1);
8792 dshape_l.SetSize(p + 1);
8793 ddshape_x.SetSize(p + 1);
8794 ddshape_y.SetSize(p + 1);
8795 ddshape_z.SetSize(p + 1);
8796 ddshape_l.SetSize(p + 1);
8797 u.SetSize(dof);
8798 du.SetSize(dof, dim);
8799 ddu.SetSize(dof, (dim * (dim + 1)) / 2);
8800 #else
8801 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
8802 #endif
8803
8804 auto tri = [](int k) { return (k*(k + 1))/2; };
8805 auto tet = [](int k) { return (k*(k + 1)*(k + 2))/6; };
8806 int ndof = tet(p+1);
8807 auto idx = [tri, tet, p, ndof](int i, int j, int k)
8808 {
8809 return ndof - tet(p - k) - tri(p + 1 - k - j) + i;
8810 };
8811
8812 lex_ordering.SetSize(dof);
8813
8814 // vertices
8815 lex_ordering[idx(0,0,0)] = 0;
8816 Nodes.IntPoint(0).Set3(cp[0], cp[0], cp[0]);
8817 lex_ordering[idx(p,0,0)] = 1;
8818 Nodes.IntPoint(1).Set3(cp[p], cp[0], cp[0]);
8819 lex_ordering[idx(0,p,0)] = 2;
8820 Nodes.IntPoint(2).Set3(cp[0], cp[p], cp[0]);
8821 lex_ordering[idx(0,0,p)] = 3;
8822 Nodes.IntPoint(3).Set3(cp[0], cp[0], cp[p]);
8823
8824 // edges (see Tetrahedron::edges in mesh/tetrahedron.cpp)
8825 int o = 4;
8826 for (int i = 1; i < p; i++) // (0,1)
8827 {
8828 lex_ordering[idx(i,0,0)] = o;
8829 Nodes.IntPoint(o++).Set3(cp[i], cp[0], cp[0]);
8830 }
8831 for (int i = 1; i < p; i++) // (0,2)
8832 {
8833 lex_ordering[idx(0,i,0)] = o;
8834 Nodes.IntPoint(o++).Set3(cp[0], cp[i], cp[0]);
8835 }
8836 for (int i = 1; i < p; i++) // (0,3)
8837 {
8838 lex_ordering[idx(0,0,i)] = o;
8839 Nodes.IntPoint(o++).Set3(cp[0], cp[0], cp[i]);
8840 }
8841 for (int i = 1; i < p; i++) // (1,2)
8842 {
8843 lex_ordering[idx(p-i,i,0)] = o;
8844 Nodes.IntPoint(o++).Set3(cp[p-i], cp[i], cp[0]);
8845 }
8846 for (int i = 1; i < p; i++) // (1,3)
8847 {
8848 lex_ordering[idx(p-i,0,i)] = o;
8849 Nodes.IntPoint(o++).Set3(cp[p-i], cp[0], cp[i]);
8850 }
8851 for (int i = 1; i < p; i++) // (2,3)
8852 {
8853 lex_ordering[idx(0,p-i,i)] = o;
8854 Nodes.IntPoint(o++).Set3(cp[0], cp[p-i], cp[i]);
8855 }
8856
8857 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
8858 for (int j = 1; j < p; j++)
8859 for (int i = 1; i + j < p; i++) // (1,2,3)
8860 {
8861 lex_ordering[idx(p-i-j,i,j)] = o;
8862 double w = cp[i] + cp[j] + cp[p-i-j];
8863 Nodes.IntPoint(o++).Set3(cp[p-i-j]/w, cp[i]/w, cp[j]/w);
8864 }
8865 for (int j = 1; j < p; j++)
8866 for (int i = 1; i + j < p; i++) // (0,3,2)
8867 {
8868 lex_ordering[idx(0,j,i)] = o;
8869 double w = cp[i] + cp[j] + cp[p-i-j];
8870 Nodes.IntPoint(o++).Set3(cp[0], cp[j]/w, cp[i]/w);
8871 }
8872 for (int j = 1; j < p; j++)
8873 for (int i = 1; i + j < p; i++) // (0,1,3)
8874 {
8875 lex_ordering[idx(i,0,j)] = o;
8876 double w = cp[i] + cp[j] + cp[p-i-j];
8877 Nodes.IntPoint(o++).Set3(cp[i]/w, cp[0], cp[j]/w);
8878 }
8879 for (int j = 1; j < p; j++)
8880 for (int i = 1; i + j < p; i++) // (0,2,1)
8881 {
8882 lex_ordering[idx(j,i,0)] = o;
8883 double w = cp[i] + cp[j] + cp[p-i-j];
8884 Nodes.IntPoint(o++).Set3(cp[j]/w, cp[i]/w, cp[0]);
8885 }
8886
8887 // interior
8888 for (int k = 1; k < p; k++)
8889 for (int j = 1; j + k < p; j++)
8890 for (int i = 1; i + j + k < p; i++)
8891 {
8892 lex_ordering[idx(i,j,k)] = o;
8893 double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
8894 Nodes.IntPoint(o++).Set3(cp[i]/w, cp[j]/w, cp[k]/w);
8895 }
8896
8897 DenseMatrix T(dof);
8898 for (int m = 0; m < dof; m++)
8899 {
8900 IntegrationPoint &ip = Nodes.IntPoint(m);
8901 poly1d.CalcBasis(p, ip.x, shape_x);
8902 poly1d.CalcBasis(p, ip.y, shape_y);
8903 poly1d.CalcBasis(p, ip.z, shape_z);
8904 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
8905
8906 o = 0;
8907 for (int k = 0; k <= p; k++)
8908 for (int j = 0; j + k <= p; j++)
8909 for (int i = 0; i + j + k <= p; i++)
8910 {
8911 T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
8912 }
8913 }
8914
8915 Ti.Factor(T);
8916 // mfem::out << "H1_TetrahedronElement(" << p << ") : "; Ti.TestInversion();
8917 }
8918
CalcShape(const IntegrationPoint & ip,Vector & shape) const8919 void H1_TetrahedronElement::CalcShape(const IntegrationPoint &ip,
8920 Vector &shape) const
8921 {
8922 const int p = order;
8923
8924 #ifdef MFEM_THREAD_SAFE
8925 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
8926 Vector u(dof);
8927 #endif
8928
8929 poly1d.CalcBasis(p, ip.x, shape_x);
8930 poly1d.CalcBasis(p, ip.y, shape_y);
8931 poly1d.CalcBasis(p, ip.z, shape_z);
8932 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
8933
8934 for (int o = 0, k = 0; k <= p; k++)
8935 for (int j = 0; j + k <= p; j++)
8936 for (int i = 0; i + j + k <= p; i++)
8937 {
8938 u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
8939 }
8940
8941 Ti.Mult(u, shape);
8942 }
8943
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const8944 void H1_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
8945 DenseMatrix &dshape) const
8946 {
8947 const int p = order;
8948
8949 #ifdef MFEM_THREAD_SAFE
8950 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
8951 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
8952 DenseMatrix du(dof, dim);
8953 #endif
8954
8955 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
8956 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
8957 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
8958 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
8959
8960 for (int o = 0, k = 0; k <= p; k++)
8961 for (int j = 0; j + k <= p; j++)
8962 for (int i = 0; i + j + k <= p; i++)
8963 {
8964 int l = p - i - j - k;
8965 du(o,0) = ((dshape_x(i)* shape_l(l)) -
8966 ( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k);
8967 du(o,1) = ((dshape_y(j)* shape_l(l)) -
8968 ( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k);
8969 du(o,2) = ((dshape_z(k)* shape_l(l)) -
8970 ( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j);
8971 o++;
8972 }
8973
8974 Ti.Mult(du, dshape);
8975 }
8976
CalcHessian(const IntegrationPoint & ip,DenseMatrix & ddshape) const8977 void H1_TetrahedronElement::CalcHessian(const IntegrationPoint &ip,
8978 DenseMatrix &ddshape) const
8979 {
8980 const int p = order;
8981
8982 #ifdef MFEM_THREAD_SAFE
8983 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
8984 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
8985 Vector ddshape_x(p + 1), ddshape_y(p + 1), ddshape_z(p + 1), ddshape_l(p + 1);
8986 DenseMatrix ddu(dof, ((dim + 1) * dim) / 2);
8987 #endif
8988
8989 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x, ddshape_x);
8990 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y, ddshape_y);
8991 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z, ddshape_z);
8992 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l, ddshape_l);
8993
8994 for (int o = 0, k = 0; k <= p; k++)
8995 for (int j = 0; j + k <= p; j++)
8996 for (int i = 0; i + j + k <= p; i++)
8997 {
8998 // u_xx, u_xy, u_xz, u_yy, u_yz, u_zz
8999 int l = p - i - j - k;
9000 ddu(o,0) = ((ddshape_x(i) * shape_l(l)) - 2. * (dshape_x(i) * dshape_l(l)) +
9001 (shape_x(i) * ddshape_l(l))) * shape_y(j) * shape_z(k);
9002 ddu(o,1) = ((dshape_y(j) * ((dshape_x(i) * shape_l(l)) -
9003 (shape_x(i) * dshape_l(l)))) +
9004 (shape_y(j) * ((ddshape_l(l) * shape_x(i)) -
9005 (dshape_x(i) * dshape_l(l)))))* shape_z(k);
9006 ddu(o,2) = ((dshape_z(k) * ((dshape_x(i) * shape_l(l)) -
9007 (shape_x(i) * dshape_l(l)))) +
9008 (shape_z(k) * ((ddshape_l(l) * shape_x(i)) -
9009 (dshape_x(i) * dshape_l(l)))))* shape_y(j);
9010 ddu(o,3) = ((ddshape_y(j) * shape_l(l)) - 2. * (dshape_y(j) * dshape_l(l)) +
9011 (shape_y(j) * ddshape_l(l))) * shape_x(i) * shape_z(k);
9012 ddu(o,4) = ((dshape_z(k) * ((dshape_y(j) * shape_l(l)) -
9013 (shape_y(j)*dshape_l(l))) ) +
9014 (shape_z(k)* ((ddshape_l(l)*shape_y(j)) -
9015 (dshape_y(j) * dshape_l(l)) ) ) )* shape_x(i);
9016 ddu(o,5) = ((ddshape_z(k) * shape_l(l)) - 2. * (dshape_z(k) * dshape_l(l)) +
9017 (shape_z(k) * ddshape_l(l))) * shape_y(j) * shape_x(i);
9018 o++;
9019 }
9020 Ti.Mult(ddu, ddshape);
9021 }
9022
H1Pos_TriangleElement(const int p)9023 H1Pos_TriangleElement::H1Pos_TriangleElement(const int p)
9024 : PositiveFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
9025 FunctionSpace::Pk)
9026 {
9027 #ifndef MFEM_THREAD_SAFE
9028 m_shape.SetSize(dof);
9029 dshape_1d.SetSize(p + 1);
9030 m_dshape.SetSize(dof, dim);
9031 #endif
9032 dof_map.SetSize(dof);
9033
9034 struct Index
9035 {
9036 int p2p3;
9037 Index(int p) { p2p3 = 2*p + 3; }
9038 int operator()(int i, int j) { return ((p2p3-j)*j)/2+i; }
9039 };
9040 Index idx(p);
9041
9042 // vertices
9043 dof_map[idx(0,0)] = 0;
9044 Nodes.IntPoint(0).Set2(0., 0.);
9045 dof_map[idx(p,0)] = 1;
9046 Nodes.IntPoint(1).Set2(1., 0.);
9047 dof_map[idx(0,p)] = 2;
9048 Nodes.IntPoint(2).Set2(0., 1.);
9049
9050 // edges
9051 int o = 3;
9052 for (int i = 1; i < p; i++)
9053 {
9054 dof_map[idx(i,0)] = o;
9055 Nodes.IntPoint(o++).Set2(double(i)/p, 0.);
9056 }
9057 for (int i = 1; i < p; i++)
9058 {
9059 dof_map[idx(p-i,i)] = o;
9060 Nodes.IntPoint(o++).Set2(double(p-i)/p, double(i)/p);
9061 }
9062 for (int i = 1; i < p; i++)
9063 {
9064 dof_map[idx(0,p-i)] = o;
9065 Nodes.IntPoint(o++).Set2(0., double(p-i)/p);
9066 }
9067
9068 // interior
9069 for (int j = 1; j < p; j++)
9070 for (int i = 1; i + j < p; i++)
9071 {
9072 dof_map[idx(i,j)] = o;
9073 Nodes.IntPoint(o++).Set2(double(i)/p, double(j)/p);
9074 }
9075 }
9076
9077 // static method
CalcShape(const int p,const double l1,const double l2,double * shape)9078 void H1Pos_TriangleElement::CalcShape(
9079 const int p, const double l1, const double l2, double *shape)
9080 {
9081 const double l3 = 1. - l1 - l2;
9082
9083 // The (i,j) basis function is given by: T(i,j,p-i-j) l1^i l2^j l3^{p-i-j},
9084 // where T(i,j,k) = (i+j+k)! / (i! j! k!)
9085 // Another expression is given by the terms of the expansion:
9086 // (l1 + l2 + l3)^p =
9087 // \sum_{j=0}^p \binom{p}{j} l2^j
9088 // \sum_{i=0}^{p-j} \binom{p-j}{i} l1^i l3^{p-j-i}
9089 const int *bp = Poly_1D::Binom(p);
9090 double z = 1.;
9091 for (int o = 0, j = 0; j <= p; j++)
9092 {
9093 Poly_1D::CalcBinomTerms(p - j, l1, l3, &shape[o]);
9094 double s = bp[j]*z;
9095 for (int i = 0; i <= p - j; i++)
9096 {
9097 shape[o++] *= s;
9098 }
9099 z *= l2;
9100 }
9101 }
9102
9103 // static method
CalcDShape(const int p,const double l1,const double l2,double * dshape_1d,double * dshape)9104 void H1Pos_TriangleElement::CalcDShape(
9105 const int p, const double l1, const double l2,
9106 double *dshape_1d, double *dshape)
9107 {
9108 const int dof = ((p + 1)*(p + 2))/2;
9109 const double l3 = 1. - l1 - l2;
9110
9111 const int *bp = Poly_1D::Binom(p);
9112 double z = 1.;
9113 for (int o = 0, j = 0; j <= p; j++)
9114 {
9115 Poly_1D::CalcDBinomTerms(p - j, l1, l3, dshape_1d);
9116 double s = bp[j]*z;
9117 for (int i = 0; i <= p - j; i++)
9118 {
9119 dshape[o++] = s*dshape_1d[i];
9120 }
9121 z *= l2;
9122 }
9123 z = 1.;
9124 for (int i = 0; i <= p; i++)
9125 {
9126 Poly_1D::CalcDBinomTerms(p - i, l2, l3, dshape_1d);
9127 double s = bp[i]*z;
9128 for (int o = i, j = 0; j <= p - i; j++)
9129 {
9130 dshape[dof + o] = s*dshape_1d[j];
9131 o += p + 1 - j;
9132 }
9133 z *= l1;
9134 }
9135 }
9136
CalcShape(const IntegrationPoint & ip,Vector & shape) const9137 void H1Pos_TriangleElement::CalcShape(const IntegrationPoint &ip,
9138 Vector &shape) const
9139 {
9140 #ifdef MFEM_THREAD_SAFE
9141 Vector m_shape(dof);
9142 #endif
9143 CalcShape(order, ip.x, ip.y, m_shape.GetData());
9144 for (int i = 0; i < dof; i++)
9145 {
9146 shape(dof_map[i]) = m_shape(i);
9147 }
9148 }
9149
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9150 void H1Pos_TriangleElement::CalcDShape(const IntegrationPoint &ip,
9151 DenseMatrix &dshape) const
9152 {
9153 #ifdef MFEM_THREAD_SAFE
9154 Vector dshape_1d(order + 1);
9155 DenseMatrix m_dshape(dof, dim);
9156 #endif
9157 CalcDShape(order, ip.x, ip.y, dshape_1d.GetData(), m_dshape.Data());
9158 for (int d = 0; d < 2; d++)
9159 {
9160 for (int i = 0; i < dof; i++)
9161 {
9162 dshape(dof_map[i],d) = m_dshape(i,d);
9163 }
9164 }
9165 }
9166
9167
H1Pos_TetrahedronElement(const int p)9168 H1Pos_TetrahedronElement::H1Pos_TetrahedronElement(const int p)
9169 : PositiveFiniteElement(3, Geometry::TETRAHEDRON,
9170 ((p + 1)*(p + 2)*(p + 3))/6, p, FunctionSpace::Pk)
9171 {
9172 #ifndef MFEM_THREAD_SAFE
9173 m_shape.SetSize(dof);
9174 dshape_1d.SetSize(p + 1);
9175 m_dshape.SetSize(dof, dim);
9176 #endif
9177 dof_map.SetSize(dof);
9178
9179 struct Index
9180 {
9181 int p, dof;
9182 int tri(int k) { return (k*(k + 1))/2; }
9183 int tet(int k) { return (k*(k + 1)*(k + 2))/6; }
9184 Index(int p_) { p = p_; dof = tet(p + 1); }
9185 int operator()(int i, int j, int k)
9186 { return dof - tet(p - k) - tri(p + 1 - k - j) + i; }
9187 };
9188 Index idx(p);
9189
9190 // vertices
9191 dof_map[idx(0,0,0)] = 0;
9192 Nodes.IntPoint(0).Set3(0., 0., 0.);
9193 dof_map[idx(p,0,0)] = 1;
9194 Nodes.IntPoint(1).Set3(1., 0., 0.);
9195 dof_map[idx(0,p,0)] = 2;
9196 Nodes.IntPoint(2).Set3(0., 1., 0.);
9197 dof_map[idx(0,0,p)] = 3;
9198 Nodes.IntPoint(3).Set3(0., 0., 1.);
9199
9200 // edges (see Tetrahedron::edges in mesh/tetrahedron.cpp)
9201 int o = 4;
9202 for (int i = 1; i < p; i++) // (0,1)
9203 {
9204 dof_map[idx(i,0,0)] = o;
9205 Nodes.IntPoint(o++).Set3(double(i)/p, 0., 0.);
9206 }
9207 for (int i = 1; i < p; i++) // (0,2)
9208 {
9209 dof_map[idx(0,i,0)] = o;
9210 Nodes.IntPoint(o++).Set3(0., double(i)/p, 0.);
9211 }
9212 for (int i = 1; i < p; i++) // (0,3)
9213 {
9214 dof_map[idx(0,0,i)] = o;
9215 Nodes.IntPoint(o++).Set3(0., 0., double(i)/p);
9216 }
9217 for (int i = 1; i < p; i++) // (1,2)
9218 {
9219 dof_map[idx(p-i,i,0)] = o;
9220 Nodes.IntPoint(o++).Set3(double(p-i)/p, double(i)/p, 0.);
9221 }
9222 for (int i = 1; i < p; i++) // (1,3)
9223 {
9224 dof_map[idx(p-i,0,i)] = o;
9225 Nodes.IntPoint(o++).Set3(double(p-i)/p, 0., double(i)/p);
9226 }
9227 for (int i = 1; i < p; i++) // (2,3)
9228 {
9229 dof_map[idx(0,p-i,i)] = o;
9230 Nodes.IntPoint(o++).Set3(0., double(p-i)/p, double(i)/p);
9231 }
9232
9233 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp)
9234 for (int j = 1; j < p; j++)
9235 for (int i = 1; i + j < p; i++) // (1,2,3)
9236 {
9237 dof_map[idx(p-i-j,i,j)] = o;
9238 Nodes.IntPoint(o++).Set3(double(p-i-j)/p, double(i)/p, double(j)/p);
9239 }
9240 for (int j = 1; j < p; j++)
9241 for (int i = 1; i + j < p; i++) // (0,3,2)
9242 {
9243 dof_map[idx(0,j,i)] = o;
9244 Nodes.IntPoint(o++).Set3(0., double(j)/p, double(i)/p);
9245 }
9246 for (int j = 1; j < p; j++)
9247 for (int i = 1; i + j < p; i++) // (0,1,3)
9248 {
9249 dof_map[idx(i,0,j)] = o;
9250 Nodes.IntPoint(o++).Set3(double(i)/p, 0., double(j)/p);
9251 }
9252 for (int j = 1; j < p; j++)
9253 for (int i = 1; i + j < p; i++) // (0,2,1)
9254 {
9255 dof_map[idx(j,i,0)] = o;
9256 Nodes.IntPoint(o++).Set3(double(j)/p, double(i)/p, 0.);
9257 }
9258
9259 // interior
9260 for (int k = 1; k < p; k++)
9261 for (int j = 1; j + k < p; j++)
9262 for (int i = 1; i + j + k < p; i++)
9263 {
9264 dof_map[idx(i,j,k)] = o;
9265 Nodes.IntPoint(o++).Set3(double(i)/p, double(j)/p, double(k)/p);
9266 }
9267 }
9268
9269 // static method
CalcShape(const int p,const double l1,const double l2,const double l3,double * shape)9270 void H1Pos_TetrahedronElement::CalcShape(
9271 const int p, const double l1, const double l2, const double l3,
9272 double *shape)
9273 {
9274 const double l4 = 1. - l1 - l2 - l3;
9275
9276 // The basis functions are the terms in the expansion:
9277 // (l1 + l2 + l3 + l4)^p =
9278 // \sum_{k=0}^p \binom{p}{k} l3^k
9279 // \sum_{j=0}^{p-k} \binom{p-k}{j} l2^j
9280 // \sum_{i=0}^{p-k-j} \binom{p-k-j}{i} l1^i l4^{p-k-j-i}
9281 const int *bp = Poly_1D::Binom(p);
9282 double l3k = 1.;
9283 for (int o = 0, k = 0; k <= p; k++)
9284 {
9285 const int *bpk = Poly_1D::Binom(p - k);
9286 const double ek = bp[k]*l3k;
9287 double l2j = 1.;
9288 for (int j = 0; j <= p - k; j++)
9289 {
9290 Poly_1D::CalcBinomTerms(p - k - j, l1, l4, &shape[o]);
9291 double ekj = ek*bpk[j]*l2j;
9292 for (int i = 0; i <= p - k - j; i++)
9293 {
9294 shape[o++] *= ekj;
9295 }
9296 l2j *= l2;
9297 }
9298 l3k *= l3;
9299 }
9300 }
9301
9302 // static method
CalcDShape(const int p,const double l1,const double l2,const double l3,double * dshape_1d,double * dshape)9303 void H1Pos_TetrahedronElement::CalcDShape(
9304 const int p, const double l1, const double l2, const double l3,
9305 double *dshape_1d, double *dshape)
9306 {
9307 const int dof = ((p + 1)*(p + 2)*(p + 3))/6;
9308 const double l4 = 1. - l1 - l2 - l3;
9309
9310 // For the x derivatives, differentiate the terms of the expression:
9311 // \sum_{k=0}^p \binom{p}{k} l3^k
9312 // \sum_{j=0}^{p-k} \binom{p-k}{j} l2^j
9313 // \sum_{i=0}^{p-k-j} \binom{p-k-j}{i} l1^i l4^{p-k-j-i}
9314 const int *bp = Poly_1D::Binom(p);
9315 double l3k = 1.;
9316 for (int o = 0, k = 0; k <= p; k++)
9317 {
9318 const int *bpk = Poly_1D::Binom(p - k);
9319 const double ek = bp[k]*l3k;
9320 double l2j = 1.;
9321 for (int j = 0; j <= p - k; j++)
9322 {
9323 Poly_1D::CalcDBinomTerms(p - k - j, l1, l4, dshape_1d);
9324 double ekj = ek*bpk[j]*l2j;
9325 for (int i = 0; i <= p - k - j; i++)
9326 {
9327 dshape[o++] = dshape_1d[i]*ekj;
9328 }
9329 l2j *= l2;
9330 }
9331 l3k *= l3;
9332 }
9333 // For the y derivatives, differentiate the terms of the expression:
9334 // \sum_{k=0}^p \binom{p}{k} l3^k
9335 // \sum_{i=0}^{p-k} \binom{p-k}{i} l1^i
9336 // \sum_{j=0}^{p-k-i} \binom{p-k-i}{j} l2^j l4^{p-k-j-i}
9337 l3k = 1.;
9338 for (int ok = 0, k = 0; k <= p; k++)
9339 {
9340 const int *bpk = Poly_1D::Binom(p - k);
9341 const double ek = bp[k]*l3k;
9342 double l1i = 1.;
9343 for (int i = 0; i <= p - k; i++)
9344 {
9345 Poly_1D::CalcDBinomTerms(p - k - i, l2, l4, dshape_1d);
9346 double eki = ek*bpk[i]*l1i;
9347 int o = ok + i;
9348 for (int j = 0; j <= p - k - i; j++)
9349 {
9350 dshape[dof + o] = dshape_1d[j]*eki;
9351 o += p - k - j + 1;
9352 }
9353 l1i *= l1;
9354 }
9355 l3k *= l3;
9356 ok += ((p - k + 2)*(p - k + 1))/2;
9357 }
9358 // For the z derivatives, differentiate the terms of the expression:
9359 // \sum_{j=0}^p \binom{p}{j} l2^j
9360 // \sum_{i=0}^{p-j} \binom{p-j}{i} l1^i
9361 // \sum_{k=0}^{p-j-i} \binom{p-j-i}{k} l3^k l4^{p-k-j-i}
9362 double l2j = 1.;
9363 for (int j = 0; j <= p; j++)
9364 {
9365 const int *bpj = Poly_1D::Binom(p - j);
9366 const double ej = bp[j]*l2j;
9367 double l1i = 1.;
9368 for (int i = 0; i <= p - j; i++)
9369 {
9370 Poly_1D::CalcDBinomTerms(p - j - i, l3, l4, dshape_1d);
9371 double eji = ej*bpj[i]*l1i;
9372 int m = ((p + 2)*(p + 1))/2;
9373 int n = ((p - j + 2)*(p - j + 1))/2;
9374 for (int o = i, k = 0; k <= p - j - i; k++)
9375 {
9376 // m = ((p - k + 2)*(p - k + 1))/2;
9377 // n = ((p - k - j + 2)*(p - k - j + 1))/2;
9378 o += m;
9379 dshape[2*dof + o - n] = dshape_1d[k]*eji;
9380 m -= p - k + 1;
9381 n -= p - k - j + 1;
9382 }
9383 l1i *= l1;
9384 }
9385 l2j *= l2;
9386 }
9387 }
9388
CalcShape(const IntegrationPoint & ip,Vector & shape) const9389 void H1Pos_TetrahedronElement::CalcShape(const IntegrationPoint &ip,
9390 Vector &shape) const
9391 {
9392 #ifdef MFEM_THREAD_SAFE
9393 Vector m_shape(dof);
9394 #endif
9395 CalcShape(order, ip.x, ip.y, ip.z, m_shape.GetData());
9396 for (int i = 0; i < dof; i++)
9397 {
9398 shape(dof_map[i]) = m_shape(i);
9399 }
9400 }
9401
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9402 void H1Pos_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
9403 DenseMatrix &dshape) const
9404 {
9405 #ifdef MFEM_THREAD_SAFE
9406 Vector dshape_1d(order + 1);
9407 DenseMatrix m_dshape(dof, dim);
9408 #endif
9409 CalcDShape(order, ip.x, ip.y, ip.z, dshape_1d.GetData(), m_dshape.Data());
9410 for (int d = 0; d < 3; d++)
9411 {
9412 for (int i = 0; i < dof; i++)
9413 {
9414 dshape(dof_map[i],d) = m_dshape(i,d);
9415 }
9416 }
9417 }
9418
9419
H1_WedgeElement(const int p,const int btype)9420 H1_WedgeElement::H1_WedgeElement(const int p,
9421 const int btype)
9422 : NodalFiniteElement(3, Geometry::PRISM, ((p + 1)*(p + 1)*(p + 2))/2,
9423 p, FunctionSpace::Qk),
9424 TriangleFE(p, btype),
9425 SegmentFE(p, btype)
9426 {
9427 #ifndef MFEM_THREAD_SAFE
9428 t_shape.SetSize(TriangleFE.GetDof());
9429 s_shape.SetSize(SegmentFE.GetDof());
9430 t_dshape.SetSize(TriangleFE.GetDof(), 2);
9431 s_dshape.SetSize(SegmentFE.GetDof(), 1);
9432 #endif
9433
9434 t_dof.SetSize(dof);
9435 s_dof.SetSize(dof);
9436
9437 int p2p3 = 2*p + 3, ntri = ((p + 1)*(p + 2))/2;
9438 auto idx = [p2p3,ntri](int i, int j, int k)
9439 {
9440 return k*ntri + ((p2p3-j)*j)/2+i;
9441 };
9442
9443 lex_ordering.SetSize(dof);
9444 int o = 0;
9445
9446 // Nodal DoFs
9447 lex_ordering[idx(0,0,0)] = o++;
9448 lex_ordering[idx(p,0,0)] = o++;
9449 lex_ordering[idx(0,p,0)] = o++;
9450 lex_ordering[idx(0,0,p)] = o++;
9451 lex_ordering[idx(p,0,p)] = o++;
9452 lex_ordering[idx(0,p,p)] = o++;
9453 t_dof[0] = 0; s_dof[0] = 0;
9454 t_dof[1] = 1; s_dof[1] = 0;
9455 t_dof[2] = 2; s_dof[2] = 0;
9456 t_dof[3] = 0; s_dof[3] = 1;
9457 t_dof[4] = 1; s_dof[4] = 1;
9458 t_dof[5] = 2; s_dof[5] = 1;
9459
9460 // Edge DoFs
9461 int k = 0;
9462 int ne = p-1;
9463 for (int i=1; i<p; i++)
9464 {
9465 lex_ordering[idx(i,0,0)] = o + 0*ne + k;
9466 lex_ordering[idx(p-i,i,0)] = o + 1*ne + k;
9467 lex_ordering[idx(0,p-i,0)] = o + 2*ne + k;
9468 lex_ordering[idx(i,0,p)] = o + 3*ne + k;
9469 lex_ordering[idx(p-i,i,p)] = o + 4*ne + k;
9470 lex_ordering[idx(0,p-i,p)] = o + 5*ne + k;
9471 lex_ordering[idx(0,0,i)] = o + 6*ne + k;
9472 lex_ordering[idx(p,0,i)] = o + 7*ne + k;
9473 lex_ordering[idx(0,p,i)] = o + 8*ne + k;
9474 t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
9475 t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
9476 t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
9477 t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
9478 t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
9479 t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
9480 t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
9481 t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
9482 t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
9483 ++k;
9484 }
9485 o += 9*ne;
9486
9487 // Triangular Face DoFs
9488 k=0;
9489 int nt = (p-1)*(p-2)/2;
9490 for (int j=1; j<p; j++)
9491 {
9492 for (int i=1; i<p-j; i++)
9493 {
9494 int l = j - p + (((2 * p - 1) - i) * i) / 2;
9495 lex_ordering[idx(i,j,0)] = o+l;
9496 lex_ordering[idx(i,j,p)] = o+nt+k;
9497 t_dof[6 + 9 * ne + k] = 3 * p + l; s_dof[6 + 9 * ne + k] = 0;
9498 t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
9499 k++;
9500 }
9501 }
9502 o += 2*nt;
9503
9504 // Quadrilateral Face DoFs
9505 k=0;
9506 int nq = (p-1)*(p-1);
9507 for (int j=1; j<p; j++)
9508 {
9509 for (int i=1; i<p; i++)
9510 {
9511 lex_ordering[idx(i,0,j)] = o+k;
9512 lex_ordering[idx(p-i,i,j)] = o+nq+k;
9513 lex_ordering[idx(0,p-i,j)] = o+2*nq+k;
9514
9515 t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
9516 t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
9517 t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
9518
9519 s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
9520 s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
9521 s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
9522
9523 k++;
9524 }
9525 }
9526 o += 3*nq;
9527
9528 // Interior DoFs
9529 int m=0;
9530 for (int k=1; k<p; k++)
9531 {
9532 int l=0;
9533 for (int j=1; j<p; j++)
9534 {
9535 for (int i=1; i+j<p; i++)
9536 {
9537 lex_ordering[idx(i,j,k)] = o++;
9538 t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
9539 s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
9540 l++; m++;
9541 }
9542 }
9543 }
9544
9545 // Define Nodes
9546 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
9547 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
9548 for (int i=0; i<dof; i++)
9549 {
9550 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
9551 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
9552 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
9553 }
9554 }
9555
CalcShape(const IntegrationPoint & ip,Vector & shape) const9556 void H1_WedgeElement::CalcShape(const IntegrationPoint &ip,
9557 Vector &shape) const
9558 {
9559 #ifdef MFEM_THREAD_SAFE
9560 Vector t_shape(TriangleFE.GetDof());
9561 Vector s_shape(SegmentFE.GetDof());
9562 #endif
9563
9564 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
9565
9566 TriangleFE.CalcShape(ip, t_shape);
9567 SegmentFE.CalcShape(ipz, s_shape);
9568
9569 for (int i=0; i<dof; i++)
9570 {
9571 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
9572 }
9573 }
9574
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9575 void H1_WedgeElement::CalcDShape(const IntegrationPoint &ip,
9576 DenseMatrix &dshape) const
9577 {
9578 #ifdef MFEM_THREAD_SAFE
9579 Vector t_shape(TriangleFE.GetDof());
9580 DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
9581 Vector s_shape(SegmentFE.GetDof());
9582 DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
9583 #endif
9584
9585 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
9586
9587 TriangleFE.CalcShape(ip, t_shape);
9588 TriangleFE.CalcDShape(ip, t_dshape);
9589 SegmentFE.CalcShape(ipz, s_shape);
9590 SegmentFE.CalcDShape(ipz, s_dshape);
9591
9592 for (int i=0; i<dof; i++)
9593 {
9594 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
9595 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
9596 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
9597 }
9598 }
9599
9600
H1Pos_WedgeElement(const int p)9601 H1Pos_WedgeElement::H1Pos_WedgeElement(const int p)
9602 : PositiveFiniteElement(3, Geometry::PRISM,
9603 ((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
9604 TriangleFE(p),
9605 SegmentFE(p)
9606 {
9607 #ifndef MFEM_THREAD_SAFE
9608 t_shape.SetSize(TriangleFE.GetDof());
9609 s_shape.SetSize(SegmentFE.GetDof());
9610 t_dshape.SetSize(TriangleFE.GetDof(), 2);
9611 s_dshape.SetSize(SegmentFE.GetDof(), 1);
9612 #endif
9613
9614 t_dof.SetSize(dof);
9615 s_dof.SetSize(dof);
9616
9617 // Nodal DoFs
9618 t_dof[0] = 0; s_dof[0] = 0;
9619 t_dof[1] = 1; s_dof[1] = 0;
9620 t_dof[2] = 2; s_dof[2] = 0;
9621 t_dof[3] = 0; s_dof[3] = 1;
9622 t_dof[4] = 1; s_dof[4] = 1;
9623 t_dof[5] = 2; s_dof[5] = 1;
9624
9625 // Edge DoFs
9626 int ne = p-1;
9627 for (int i=1; i<p; i++)
9628 {
9629 t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
9630 t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
9631 t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
9632 t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
9633 t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
9634 t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
9635 t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
9636 t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
9637 t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
9638 }
9639
9640 // Triangular Face DoFs
9641 int k=0;
9642 int nt = (p-1)*(p-2)/2;
9643 for (int j=1; j<p; j++)
9644 {
9645 for (int i=1; i<j; i++)
9646 {
9647 t_dof[6 + 9 * ne + k] = 3 * p + k; s_dof[6 + 9 * ne + k] = 0;
9648 t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
9649 k++;
9650 }
9651 }
9652
9653 // Quadrilateral Face DoFs
9654 k=0;
9655 int nq = (p-1)*(p-1);
9656 for (int j=1; j<p; j++)
9657 {
9658 for (int i=1; i<p; i++)
9659 {
9660 t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
9661 t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
9662 t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
9663
9664 s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
9665 s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
9666 s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
9667
9668 k++;
9669 }
9670 }
9671
9672 // Interior DoFs
9673 int m=0;
9674 for (int k=1; k<p; k++)
9675 {
9676 int l=0;
9677 for (int j=1; j<p; j++)
9678 {
9679 for (int i=1; i<j; i++)
9680 {
9681 t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
9682 s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
9683 l++; m++;
9684 }
9685 }
9686 }
9687
9688 // Define Nodes
9689 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
9690 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
9691 for (int i=0; i<dof; i++)
9692 {
9693 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
9694 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
9695 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
9696 }
9697 }
9698
CalcShape(const IntegrationPoint & ip,Vector & shape) const9699 void H1Pos_WedgeElement::CalcShape(const IntegrationPoint &ip,
9700 Vector &shape) const
9701 {
9702 #ifdef MFEM_THREAD_SAFE
9703 Vector t_shape(TriangleFE.GetDof());
9704 Vector s_shape(SegmentFE.GetDof());
9705 #endif
9706
9707 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
9708
9709 TriangleFE.CalcShape(ip, t_shape);
9710 SegmentFE.CalcShape(ipz, s_shape);
9711
9712 for (int i=0; i<dof; i++)
9713 {
9714 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
9715 }
9716 }
9717
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9718 void H1Pos_WedgeElement::CalcDShape(const IntegrationPoint &ip,
9719 DenseMatrix &dshape) const
9720 {
9721 #ifdef MFEM_THREAD_SAFE
9722 Vector t_shape(TriangleFE.GetDof());
9723 DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
9724 Vector s_shape(SegmentFE.GetDof());
9725 DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
9726 #endif
9727
9728 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
9729
9730 TriangleFE.CalcShape(ip, t_shape);
9731 TriangleFE.CalcDShape(ip, t_dshape);
9732 SegmentFE.CalcShape(ipz, s_shape);
9733 SegmentFE.CalcDShape(ipz, s_dshape);
9734
9735 for (int i=0; i<dof; i++)
9736 {
9737 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
9738 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
9739 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
9740 }
9741 }
9742
9743
L2_SegmentElement(const int p,const int btype)9744 L2_SegmentElement::L2_SegmentElement(const int p, const int btype)
9745 : NodalTensorFiniteElement(1, p, VerifyOpen(btype), L2_DOF_MAP)
9746 {
9747 const double *op = poly1d.OpenPoints(p, btype);
9748
9749 #ifndef MFEM_THREAD_SAFE
9750 shape_x.SetSize(p + 1);
9751 dshape_x.SetDataAndSize(NULL, p + 1);
9752 #endif
9753
9754 for (int i = 0; i <= p; i++)
9755 {
9756 Nodes.IntPoint(i).x = op[i];
9757 }
9758 }
9759
CalcShape(const IntegrationPoint & ip,Vector & shape) const9760 void L2_SegmentElement::CalcShape(const IntegrationPoint &ip,
9761 Vector &shape) const
9762 {
9763 basis1d.Eval(ip.x, shape);
9764 }
9765
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9766 void L2_SegmentElement::CalcDShape(const IntegrationPoint &ip,
9767 DenseMatrix &dshape) const
9768 {
9769 #ifdef MFEM_THREAD_SAFE
9770 Vector shape_x(dof), dshape_x(dshape.Data(), dof);
9771 #else
9772 dshape_x.SetData(dshape.Data());
9773 #endif
9774 basis1d.Eval(ip.x, shape_x, dshape_x);
9775 }
9776
ProjectDelta(int vertex,Vector & dofs) const9777 void L2_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
9778 {
9779 const int p = order;
9780 const double *op = poly1d.OpenPoints(p, b_type);
9781
9782 switch (vertex)
9783 {
9784 case 0:
9785 for (int i = 0; i <= p; i++)
9786 {
9787 dofs(i) = poly1d.CalcDelta(p,(1.0 - op[i]));
9788 }
9789 break;
9790
9791 case 1:
9792 for (int i = 0; i <= p; i++)
9793 {
9794 dofs(i) = poly1d.CalcDelta(p,op[i]);
9795 }
9796 break;
9797 }
9798 }
9799
9800
L2Pos_SegmentElement(const int p)9801 L2Pos_SegmentElement::L2Pos_SegmentElement(const int p)
9802 : PositiveTensorFiniteElement(1, p, L2_DOF_MAP)
9803 {
9804 #ifndef MFEM_THREAD_SAFE
9805 shape_x.SetSize(p + 1);
9806 dshape_x.SetDataAndSize(NULL, p + 1);
9807 #endif
9808
9809 if (p == 0)
9810 {
9811 Nodes.IntPoint(0).x = 0.5;
9812 }
9813 else
9814 {
9815 for (int i = 0; i <= p; i++)
9816 {
9817 Nodes.IntPoint(i).x = double(i)/p;
9818 }
9819 }
9820 }
9821
CalcShape(const IntegrationPoint & ip,Vector & shape) const9822 void L2Pos_SegmentElement::CalcShape(const IntegrationPoint &ip,
9823 Vector &shape) const
9824 {
9825 Poly_1D::CalcBernstein(order, ip.x, shape);
9826 }
9827
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9828 void L2Pos_SegmentElement::CalcDShape(const IntegrationPoint &ip,
9829 DenseMatrix &dshape) const
9830 {
9831 #ifdef MFEM_THREAD_SAFE
9832 Vector shape_x(dof), dshape_x(dshape.Data(), dof);
9833 #else
9834 dshape_x.SetData(dshape.Data());
9835 #endif
9836 Poly_1D::CalcBernstein(order, ip.x, shape_x, dshape_x);
9837 }
9838
ProjectDelta(int vertex,Vector & dofs) const9839 void L2Pos_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
9840 {
9841 dofs = 0.0;
9842 dofs[vertex*order] = 1.0;
9843 }
9844
9845
L2_QuadrilateralElement(const int p,const int btype)9846 L2_QuadrilateralElement::L2_QuadrilateralElement(const int p, const int btype)
9847 : NodalTensorFiniteElement(2, p, VerifyOpen(btype), L2_DOF_MAP)
9848 {
9849 const double *op = poly1d.OpenPoints(p, b_type);
9850
9851 #ifndef MFEM_THREAD_SAFE
9852 shape_x.SetSize(p + 1);
9853 shape_y.SetSize(p + 1);
9854 dshape_x.SetSize(p + 1);
9855 dshape_y.SetSize(p + 1);
9856 #endif
9857
9858 for (int o = 0, j = 0; j <= p; j++)
9859 for (int i = 0; i <= p; i++)
9860 {
9861 Nodes.IntPoint(o++).Set2(op[i], op[j]);
9862 }
9863 }
9864
CalcShape(const IntegrationPoint & ip,Vector & shape) const9865 void L2_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
9866 Vector &shape) const
9867 {
9868 const int p = order;
9869
9870 #ifdef MFEM_THREAD_SAFE
9871 Vector shape_x(p+1), shape_y(p+1);
9872 #endif
9873
9874 basis1d.Eval(ip.x, shape_x);
9875 basis1d.Eval(ip.y, shape_y);
9876
9877 for (int o = 0, j = 0; j <= p; j++)
9878 for (int i = 0; i <= p; i++)
9879 {
9880 shape(o++) = shape_x(i)*shape_y(j);
9881 }
9882 }
9883
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9884 void L2_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
9885 DenseMatrix &dshape) const
9886 {
9887 const int p = order;
9888
9889 #ifdef MFEM_THREAD_SAFE
9890 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
9891 #endif
9892
9893 basis1d.Eval(ip.x, shape_x, dshape_x);
9894 basis1d.Eval(ip.y, shape_y, dshape_y);
9895
9896 for (int o = 0, j = 0; j <= p; j++)
9897 for (int i = 0; i <= p; i++)
9898 {
9899 dshape(o,0) = dshape_x(i)* shape_y(j);
9900 dshape(o,1) = shape_x(i)*dshape_y(j); o++;
9901 }
9902 }
9903
ProjectDelta(int vertex,Vector & dofs) const9904 void L2_QuadrilateralElement::ProjectDelta(int vertex, Vector &dofs) const
9905 {
9906 const int p = order;
9907 const double *op = poly1d.OpenPoints(p, b_type);
9908
9909 #ifdef MFEM_THREAD_SAFE
9910 Vector shape_x(p+1), shape_y(p+1);
9911 #endif
9912
9913 for (int i = 0; i <= p; i++)
9914 {
9915 shape_x(i) = poly1d.CalcDelta(p,(1.0 - op[i]));
9916 shape_y(i) = poly1d.CalcDelta(p,op[i]);
9917 }
9918
9919 switch (vertex)
9920 {
9921 case 0:
9922 for (int o = 0, j = 0; j <= p; j++)
9923 for (int i = 0; i <= p; i++)
9924 {
9925 dofs[o++] = shape_x(i)*shape_x(j);
9926 }
9927 break;
9928 case 1:
9929 for (int o = 0, j = 0; j <= p; j++)
9930 for (int i = 0; i <= p; i++)
9931 {
9932 dofs[o++] = shape_y(i)*shape_x(j);
9933 }
9934 break;
9935 case 2:
9936 for (int o = 0, j = 0; j <= p; j++)
9937 for (int i = 0; i <= p; i++)
9938 {
9939 dofs[o++] = shape_y(i)*shape_y(j);
9940 }
9941 break;
9942 case 3:
9943 for (int o = 0, j = 0; j <= p; j++)
9944 for (int i = 0; i <= p; i++)
9945 {
9946 dofs[o++] = shape_x(i)*shape_y(j);
9947 }
9948 break;
9949 }
9950 }
9951
9952
L2Pos_QuadrilateralElement(const int p)9953 L2Pos_QuadrilateralElement::L2Pos_QuadrilateralElement(const int p)
9954 : PositiveTensorFiniteElement(2, p, L2_DOF_MAP)
9955 {
9956 #ifndef MFEM_THREAD_SAFE
9957 shape_x.SetSize(p + 1);
9958 shape_y.SetSize(p + 1);
9959 dshape_x.SetSize(p + 1);
9960 dshape_y.SetSize(p + 1);
9961 #endif
9962
9963 if (p == 0)
9964 {
9965 Nodes.IntPoint(0).Set2(0.5, 0.5);
9966 }
9967 else
9968 {
9969 for (int o = 0, j = 0; j <= p; j++)
9970 for (int i = 0; i <= p; i++)
9971 {
9972 Nodes.IntPoint(o++).Set2(double(i)/p, double(j)/p);
9973 }
9974 }
9975 }
9976
CalcShape(const IntegrationPoint & ip,Vector & shape) const9977 void L2Pos_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
9978 Vector &shape) const
9979 {
9980 const int p = order;
9981
9982 #ifdef MFEM_THREAD_SAFE
9983 Vector shape_x(p+1), shape_y(p+1);
9984 #endif
9985
9986 Poly_1D::CalcBernstein(p, ip.x, shape_x);
9987 Poly_1D::CalcBernstein(p, ip.y, shape_y);
9988
9989 for (int o = 0, j = 0; j <= p; j++)
9990 for (int i = 0; i <= p; i++)
9991 {
9992 shape(o++) = shape_x(i)*shape_y(j);
9993 }
9994 }
9995
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const9996 void L2Pos_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
9997 DenseMatrix &dshape) const
9998 {
9999 const int p = order;
10000
10001 #ifdef MFEM_THREAD_SAFE
10002 Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
10003 #endif
10004
10005 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
10006 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
10007
10008 for (int o = 0, j = 0; j <= p; j++)
10009 for (int i = 0; i <= p; i++)
10010 {
10011 dshape(o,0) = dshape_x(i)* shape_y(j);
10012 dshape(o,1) = shape_x(i)*dshape_y(j); o++;
10013 }
10014 }
10015
ProjectDelta(int vertex,Vector & dofs) const10016 void L2Pos_QuadrilateralElement::ProjectDelta(int vertex, Vector &dofs) const
10017 {
10018 const int p = order;
10019
10020 dofs = 0.0;
10021 switch (vertex)
10022 {
10023 case 0: dofs[0] = 1.0; break;
10024 case 1: dofs[p] = 1.0; break;
10025 case 2: dofs[p*(p + 2)] = 1.0; break;
10026 case 3: dofs[p*(p + 1)] = 1.0; break;
10027 }
10028 }
10029
10030
L2_HexahedronElement(const int p,const int btype)10031 L2_HexahedronElement::L2_HexahedronElement(const int p, const int btype)
10032 : NodalTensorFiniteElement(3, p, VerifyOpen(btype), L2_DOF_MAP)
10033 {
10034 const double *op = poly1d.OpenPoints(p, btype);
10035
10036 #ifndef MFEM_THREAD_SAFE
10037 shape_x.SetSize(p + 1);
10038 shape_y.SetSize(p + 1);
10039 shape_z.SetSize(p + 1);
10040 dshape_x.SetSize(p + 1);
10041 dshape_y.SetSize(p + 1);
10042 dshape_z.SetSize(p + 1);
10043 #endif
10044
10045 for (int o = 0, k = 0; k <= p; k++)
10046 for (int j = 0; j <= p; j++)
10047 for (int i = 0; i <= p; i++)
10048 {
10049 Nodes.IntPoint(o++).Set3(op[i], op[j], op[k]);
10050 }
10051 }
10052
CalcShape(const IntegrationPoint & ip,Vector & shape) const10053 void L2_HexahedronElement::CalcShape(const IntegrationPoint &ip,
10054 Vector &shape) const
10055 {
10056 const int p = order;
10057
10058 #ifdef MFEM_THREAD_SAFE
10059 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
10060 #endif
10061
10062 basis1d.Eval(ip.x, shape_x);
10063 basis1d.Eval(ip.y, shape_y);
10064 basis1d.Eval(ip.z, shape_z);
10065
10066 for (int o = 0, k = 0; k <= p; k++)
10067 for (int j = 0; j <= p; j++)
10068 for (int i = 0; i <= p; i++)
10069 {
10070 shape(o++) = shape_x(i)*shape_y(j)*shape_z(k);
10071 }
10072 }
10073
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10074 void L2_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
10075 DenseMatrix &dshape) const
10076 {
10077 const int p = order;
10078
10079 #ifdef MFEM_THREAD_SAFE
10080 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
10081 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
10082 #endif
10083
10084 basis1d.Eval(ip.x, shape_x, dshape_x);
10085 basis1d.Eval(ip.y, shape_y, dshape_y);
10086 basis1d.Eval(ip.z, shape_z, dshape_z);
10087
10088 for (int o = 0, k = 0; k <= p; k++)
10089 for (int j = 0; j <= p; j++)
10090 for (int i = 0; i <= p; i++)
10091 {
10092 dshape(o,0) = dshape_x(i)* shape_y(j)* shape_z(k);
10093 dshape(o,1) = shape_x(i)*dshape_y(j)* shape_z(k);
10094 dshape(o,2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
10095 }
10096 }
10097
ProjectDelta(int vertex,Vector & dofs) const10098 void L2_HexahedronElement::ProjectDelta(int vertex, Vector &dofs) const
10099 {
10100 const int p = order;
10101 const double *op = poly1d.OpenPoints(p, b_type);
10102
10103 #ifdef MFEM_THREAD_SAFE
10104 Vector shape_x(p+1), shape_y(p+1);
10105 #endif
10106
10107 for (int i = 0; i <= p; i++)
10108 {
10109 shape_x(i) = poly1d.CalcDelta(p,(1.0 - op[i]));
10110 shape_y(i) = poly1d.CalcDelta(p,op[i]);
10111 }
10112
10113 switch (vertex)
10114 {
10115 case 0:
10116 for (int o = 0, k = 0; k <= p; k++)
10117 for (int j = 0; j <= p; j++)
10118 for (int i = 0; i <= p; i++)
10119 {
10120 dofs[o++] = shape_x(i)*shape_x(j)*shape_x(k);
10121 }
10122 break;
10123 case 1:
10124 for (int o = 0, k = 0; k <= p; k++)
10125 for (int j = 0; j <= p; j++)
10126 for (int i = 0; i <= p; i++)
10127 {
10128 dofs[o++] = shape_y(i)*shape_x(j)*shape_x(k);
10129 }
10130 break;
10131 case 2:
10132 for (int o = 0, k = 0; k <= p; k++)
10133 for (int j = 0; j <= p; j++)
10134 for (int i = 0; i <= p; i++)
10135 {
10136 dofs[o++] = shape_y(i)*shape_y(j)*shape_x(k);
10137 }
10138 break;
10139 case 3:
10140 for (int o = 0, k = 0; k <= p; k++)
10141 for (int j = 0; j <= p; j++)
10142 for (int i = 0; i <= p; i++)
10143 {
10144 dofs[o++] = shape_x(i)*shape_y(j)*shape_x(k);
10145 }
10146 break;
10147 case 4:
10148 for (int o = 0, k = 0; k <= p; k++)
10149 for (int j = 0; j <= p; j++)
10150 for (int i = 0; i <= p; i++)
10151 {
10152 dofs[o++] = shape_x(i)*shape_x(j)*shape_y(k);
10153 }
10154 break;
10155 case 5:
10156 for (int o = 0, k = 0; k <= p; k++)
10157 for (int j = 0; j <= p; j++)
10158 for (int i = 0; i <= p; i++)
10159 {
10160 dofs[o++] = shape_y(i)*shape_x(j)*shape_y(k);
10161 }
10162 break;
10163 case 6:
10164 for (int o = 0, k = 0; k <= p; k++)
10165 for (int j = 0; j <= p; j++)
10166 for (int i = 0; i <= p; i++)
10167 {
10168 dofs[o++] = shape_y(i)*shape_y(j)*shape_y(k);
10169 }
10170 break;
10171 case 7:
10172 for (int o = 0, k = 0; k <= p; k++)
10173 for (int j = 0; j <= p; j++)
10174 for (int i = 0; i <= p; i++)
10175 {
10176 dofs[o++] = shape_x(i)*shape_y(j)*shape_y(k);
10177 }
10178 break;
10179 }
10180 }
10181
10182
L2Pos_HexahedronElement(const int p)10183 L2Pos_HexahedronElement::L2Pos_HexahedronElement(const int p)
10184 : PositiveTensorFiniteElement(3, p, L2_DOF_MAP)
10185 {
10186 #ifndef MFEM_THREAD_SAFE
10187 shape_x.SetSize(p + 1);
10188 shape_y.SetSize(p + 1);
10189 shape_z.SetSize(p + 1);
10190 dshape_x.SetSize(p + 1);
10191 dshape_y.SetSize(p + 1);
10192 dshape_z.SetSize(p + 1);
10193 #endif
10194
10195 if (p == 0)
10196 {
10197 Nodes.IntPoint(0).Set3(0.5, 0.5, 0.5);
10198 }
10199 else
10200 {
10201 for (int o = 0, k = 0; k <= p; k++)
10202 for (int j = 0; j <= p; j++)
10203 for (int i = 0; i <= p; i++)
10204 {
10205 Nodes.IntPoint(o++).Set3(double(i)/p, double(j)/p, double(k)/p);
10206 }
10207 }
10208 }
10209
CalcShape(const IntegrationPoint & ip,Vector & shape) const10210 void L2Pos_HexahedronElement::CalcShape(const IntegrationPoint &ip,
10211 Vector &shape) const
10212 {
10213 const int p = order;
10214
10215 #ifdef MFEM_THREAD_SAFE
10216 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
10217 #endif
10218
10219 Poly_1D::CalcBernstein(p, ip.x, shape_x);
10220 Poly_1D::CalcBernstein(p, ip.y, shape_y);
10221 Poly_1D::CalcBernstein(p, ip.z, shape_z);
10222
10223 for (int o = 0, k = 0; k <= p; k++)
10224 for (int j = 0; j <= p; j++)
10225 for (int i = 0; i <= p; i++)
10226 {
10227 shape(o++) = shape_x(i)*shape_y(j)*shape_z(k);
10228 }
10229 }
10230
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10231 void L2Pos_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
10232 DenseMatrix &dshape) const
10233 {
10234 const int p = order;
10235
10236 #ifdef MFEM_THREAD_SAFE
10237 Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
10238 Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
10239 #endif
10240
10241 Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
10242 Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
10243 Poly_1D::CalcBernstein(p, ip.z, shape_z, dshape_z);
10244
10245 for (int o = 0, k = 0; k <= p; k++)
10246 for (int j = 0; j <= p; j++)
10247 for (int i = 0; i <= p; i++)
10248 {
10249 dshape(o,0) = dshape_x(i)* shape_y(j)* shape_z(k);
10250 dshape(o,1) = shape_x(i)*dshape_y(j)* shape_z(k);
10251 dshape(o,2) = shape_x(i)* shape_y(j)*dshape_z(k); o++;
10252 }
10253 }
10254
ProjectDelta(int vertex,Vector & dofs) const10255 void L2Pos_HexahedronElement::ProjectDelta(int vertex, Vector &dofs) const
10256 {
10257 const int p = order;
10258
10259 dofs = 0.0;
10260 switch (vertex)
10261 {
10262 case 0: dofs[0] = 1.0; break;
10263 case 1: dofs[p] = 1.0; break;
10264 case 2: dofs[p*(p + 2)] = 1.0; break;
10265 case 3: dofs[p*(p + 1)] = 1.0; break;
10266 case 4: dofs[p*(p + 1)*(p + 1)] = 1.0; break;
10267 case 5: dofs[p + p*(p + 1)*(p + 1)] = 1.0; break;
10268 case 6: dofs[dof - 1] = 1.0; break;
10269 case 7: dofs[dof - p - 1] = 1.0; break;
10270 }
10271 }
10272
10273
L2_TriangleElement(const int p,const int btype)10274 L2_TriangleElement::L2_TriangleElement(const int p, const int btype)
10275 : NodalFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
10276 FunctionSpace::Pk)
10277 {
10278 const double *op = poly1d.OpenPoints(p, VerifyOpen(btype));
10279
10280 #ifndef MFEM_THREAD_SAFE
10281 shape_x.SetSize(p + 1);
10282 shape_y.SetSize(p + 1);
10283 shape_l.SetSize(p + 1);
10284 dshape_x.SetSize(p + 1);
10285 dshape_y.SetSize(p + 1);
10286 dshape_l.SetSize(p + 1);
10287 u.SetSize(dof);
10288 du.SetSize(dof, dim);
10289 #else
10290 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
10291 #endif
10292
10293 for (int o = 0, j = 0; j <= p; j++)
10294 for (int i = 0; i + j <= p; i++)
10295 {
10296 double w = op[i] + op[j] + op[p-i-j];
10297 Nodes.IntPoint(o++).Set2(op[i]/w, op[j]/w);
10298 }
10299
10300 DenseMatrix T(dof);
10301 for (int k = 0; k < dof; k++)
10302 {
10303 IntegrationPoint &ip = Nodes.IntPoint(k);
10304 poly1d.CalcBasis(p, ip.x, shape_x);
10305 poly1d.CalcBasis(p, ip.y, shape_y);
10306 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
10307
10308 for (int o = 0, j = 0; j <= p; j++)
10309 for (int i = 0; i + j <= p; i++)
10310 {
10311 T(o++, k) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
10312 }
10313 }
10314
10315 Ti.Factor(T);
10316 // mfem::out << "L2_TriangleElement(" << p << ") : "; Ti.TestInversion();
10317 }
10318
CalcShape(const IntegrationPoint & ip,Vector & shape) const10319 void L2_TriangleElement::CalcShape(const IntegrationPoint &ip,
10320 Vector &shape) const
10321 {
10322 const int p = order;
10323
10324 #ifdef MFEM_THREAD_SAFE
10325 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1), u(dof);
10326 #endif
10327
10328 poly1d.CalcBasis(p, ip.x, shape_x);
10329 poly1d.CalcBasis(p, ip.y, shape_y);
10330 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
10331
10332 for (int o = 0, j = 0; j <= p; j++)
10333 for (int i = 0; i + j <= p; i++)
10334 {
10335 u(o++) = shape_x(i)*shape_y(j)*shape_l(p-i-j);
10336 }
10337
10338 Ti.Mult(u, shape);
10339 }
10340
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10341 void L2_TriangleElement::CalcDShape(const IntegrationPoint &ip,
10342 DenseMatrix &dshape) const
10343 {
10344 const int p = order;
10345
10346 #ifdef MFEM_THREAD_SAFE
10347 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
10348 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
10349 DenseMatrix du(dof, dim);
10350 #endif
10351
10352 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
10353 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
10354 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l);
10355
10356 for (int o = 0, j = 0; j <= p; j++)
10357 for (int i = 0; i + j <= p; i++)
10358 {
10359 int k = p - i - j;
10360 du(o,0) = ((dshape_x(i)* shape_l(k)) -
10361 ( shape_x(i)*dshape_l(k)))*shape_y(j);
10362 du(o,1) = ((dshape_y(j)* shape_l(k)) -
10363 ( shape_y(j)*dshape_l(k)))*shape_x(i);
10364 o++;
10365 }
10366
10367 Ti.Mult(du, dshape);
10368 }
10369
ProjectDelta(int vertex,Vector & dofs) const10370 void L2_TriangleElement::ProjectDelta(int vertex, Vector &dofs) const
10371 {
10372 switch (vertex)
10373 {
10374 case 0:
10375 for (int i = 0; i < dof; i++)
10376 {
10377 const IntegrationPoint &ip = Nodes.IntPoint(i);
10378 dofs[i] = pow(1.0 - ip.x - ip.y, order);
10379 }
10380 break;
10381 case 1:
10382 for (int i = 0; i < dof; i++)
10383 {
10384 const IntegrationPoint &ip = Nodes.IntPoint(i);
10385 dofs[i] = pow(ip.x, order);
10386 }
10387 break;
10388 case 2:
10389 for (int i = 0; i < dof; i++)
10390 {
10391 const IntegrationPoint &ip = Nodes.IntPoint(i);
10392 dofs[i] = pow(ip.y, order);
10393 }
10394 break;
10395 }
10396 }
10397
10398
L2Pos_TriangleElement(const int p)10399 L2Pos_TriangleElement::L2Pos_TriangleElement(const int p)
10400 : PositiveFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
10401 FunctionSpace::Pk)
10402 {
10403 #ifndef MFEM_THREAD_SAFE
10404 dshape_1d.SetSize(p + 1);
10405 #endif
10406
10407 if (p == 0)
10408 {
10409 Nodes.IntPoint(0).Set2(1./3, 1./3);
10410 }
10411 else
10412 {
10413 for (int o = 0, j = 0; j <= p; j++)
10414 for (int i = 0; i + j <= p; i++)
10415 {
10416 Nodes.IntPoint(o++).Set2(double(i)/p, double(j)/p);
10417 }
10418 }
10419 }
10420
CalcShape(const IntegrationPoint & ip,Vector & shape) const10421 void L2Pos_TriangleElement::CalcShape(const IntegrationPoint &ip,
10422 Vector &shape) const
10423 {
10424 H1Pos_TriangleElement::CalcShape(order, ip.x, ip.y, shape.GetData());
10425 }
10426
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10427 void L2Pos_TriangleElement::CalcDShape(const IntegrationPoint &ip,
10428 DenseMatrix &dshape) const
10429 {
10430 #ifdef MFEM_THREAD_SAFE
10431 Vector dshape_1d(order + 1);
10432 #endif
10433
10434 H1Pos_TriangleElement::CalcDShape(order, ip.x, ip.y, dshape_1d.GetData(),
10435 dshape.Data());
10436 }
10437
ProjectDelta(int vertex,Vector & dofs) const10438 void L2Pos_TriangleElement::ProjectDelta(int vertex, Vector &dofs) const
10439 {
10440 dofs = 0.0;
10441 switch (vertex)
10442 {
10443 case 0: dofs[0] = 1.0; break;
10444 case 1: dofs[order] = 1.0; break;
10445 case 2: dofs[dof-1] = 1.0; break;
10446 }
10447 }
10448
10449
L2_TetrahedronElement(const int p,const int btype)10450 L2_TetrahedronElement::L2_TetrahedronElement(const int p, const int btype)
10451 : NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6,
10452 p, FunctionSpace::Pk)
10453 {
10454 const double *op = poly1d.OpenPoints(p, VerifyNodal(VerifyOpen(btype)));
10455
10456 #ifndef MFEM_THREAD_SAFE
10457 shape_x.SetSize(p + 1);
10458 shape_y.SetSize(p + 1);
10459 shape_z.SetSize(p + 1);
10460 shape_l.SetSize(p + 1);
10461 dshape_x.SetSize(p + 1);
10462 dshape_y.SetSize(p + 1);
10463 dshape_z.SetSize(p + 1);
10464 dshape_l.SetSize(p + 1);
10465 u.SetSize(dof);
10466 du.SetSize(dof, dim);
10467 #else
10468 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
10469 #endif
10470
10471 for (int o = 0, k = 0; k <= p; k++)
10472 for (int j = 0; j + k <= p; j++)
10473 for (int i = 0; i + j + k <= p; i++)
10474 {
10475 double w = op[i] + op[j] + op[k] + op[p-i-j-k];
10476 Nodes.IntPoint(o++).Set3(op[i]/w, op[j]/w, op[k]/w);
10477 }
10478
10479 DenseMatrix T(dof);
10480 for (int m = 0; m < dof; m++)
10481 {
10482 IntegrationPoint &ip = Nodes.IntPoint(m);
10483 poly1d.CalcBasis(p, ip.x, shape_x);
10484 poly1d.CalcBasis(p, ip.y, shape_y);
10485 poly1d.CalcBasis(p, ip.z, shape_z);
10486 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
10487
10488 for (int o = 0, k = 0; k <= p; k++)
10489 for (int j = 0; j + k <= p; j++)
10490 for (int i = 0; i + j + k <= p; i++)
10491 {
10492 T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
10493 }
10494 }
10495
10496 Ti.Factor(T);
10497 // mfem::out << "L2_TetrahedronElement(" << p << ") : "; Ti.TestInversion();
10498 }
10499
CalcShape(const IntegrationPoint & ip,Vector & shape) const10500 void L2_TetrahedronElement::CalcShape(const IntegrationPoint &ip,
10501 Vector &shape) const
10502 {
10503 const int p = order;
10504
10505 #ifdef MFEM_THREAD_SAFE
10506 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
10507 Vector u(dof);
10508 #endif
10509
10510 poly1d.CalcBasis(p, ip.x, shape_x);
10511 poly1d.CalcBasis(p, ip.y, shape_y);
10512 poly1d.CalcBasis(p, ip.z, shape_z);
10513 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
10514
10515 for (int o = 0, k = 0; k <= p; k++)
10516 for (int j = 0; j + k <= p; j++)
10517 for (int i = 0; i + j + k <= p; i++)
10518 {
10519 u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
10520 }
10521
10522 Ti.Mult(u, shape);
10523 }
10524
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10525 void L2_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
10526 DenseMatrix &dshape) const
10527 {
10528 const int p = order;
10529
10530 #ifdef MFEM_THREAD_SAFE
10531 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
10532 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
10533 DenseMatrix du(dof, dim);
10534 #endif
10535
10536 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
10537 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
10538 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
10539 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
10540
10541 for (int o = 0, k = 0; k <= p; k++)
10542 for (int j = 0; j + k <= p; j++)
10543 for (int i = 0; i + j + k <= p; i++)
10544 {
10545 int l = p - i - j - k;
10546 du(o,0) = ((dshape_x(i)* shape_l(l)) -
10547 ( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k);
10548 du(o,1) = ((dshape_y(j)* shape_l(l)) -
10549 ( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k);
10550 du(o,2) = ((dshape_z(k)* shape_l(l)) -
10551 ( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j);
10552 o++;
10553 }
10554
10555 Ti.Mult(du, dshape);
10556 }
10557
ProjectDelta(int vertex,Vector & dofs) const10558 void L2_TetrahedronElement::ProjectDelta(int vertex, Vector &dofs) const
10559 {
10560 switch (vertex)
10561 {
10562 case 0:
10563 for (int i = 0; i < dof; i++)
10564 {
10565 const IntegrationPoint &ip = Nodes.IntPoint(i);
10566 dofs[i] = pow(1.0 - ip.x - ip.y - ip.z, order);
10567 }
10568 break;
10569 case 1:
10570 for (int i = 0; i < dof; i++)
10571 {
10572 const IntegrationPoint &ip = Nodes.IntPoint(i);
10573 dofs[i] = pow(ip.x, order);
10574 }
10575 break;
10576 case 2:
10577 for (int i = 0; i < dof; i++)
10578 {
10579 const IntegrationPoint &ip = Nodes.IntPoint(i);
10580 dofs[i] = pow(ip.y, order);
10581 }
10582 break;
10583 case 3:
10584 for (int i = 0; i < dof; i++)
10585 {
10586 const IntegrationPoint &ip = Nodes.IntPoint(i);
10587 dofs[i] = pow(ip.z, order);
10588 }
10589 break;
10590 }
10591 }
10592
10593
L2Pos_TetrahedronElement(const int p)10594 L2Pos_TetrahedronElement::L2Pos_TetrahedronElement(const int p)
10595 : PositiveFiniteElement(3, Geometry::TETRAHEDRON,
10596 ((p + 1)*(p + 2)*(p + 3))/6, p, FunctionSpace::Pk)
10597 {
10598 #ifndef MFEM_THREAD_SAFE
10599 dshape_1d.SetSize(p + 1);
10600 #endif
10601
10602 if (p == 0)
10603 {
10604 Nodes.IntPoint(0).Set3(0.25, 0.25, 0.25);
10605 }
10606 else
10607 {
10608 for (int o = 0, k = 0; k <= p; k++)
10609 for (int j = 0; j + k <= p; j++)
10610 for (int i = 0; i + j + k <= p; i++)
10611 {
10612 Nodes.IntPoint(o++).Set3(double(i)/p, double(j)/p, double(k)/p);
10613 }
10614 }
10615 }
10616
CalcShape(const IntegrationPoint & ip,Vector & shape) const10617 void L2Pos_TetrahedronElement::CalcShape(const IntegrationPoint &ip,
10618 Vector &shape) const
10619 {
10620 H1Pos_TetrahedronElement::CalcShape(order, ip.x, ip.y, ip.z,
10621 shape.GetData());
10622 }
10623
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10624 void L2Pos_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
10625 DenseMatrix &dshape) const
10626 {
10627 #ifdef MFEM_THREAD_SAFE
10628 Vector dshape_1d(order + 1);
10629 #endif
10630
10631 H1Pos_TetrahedronElement::CalcDShape(order, ip.x, ip.y, ip.z,
10632 dshape_1d.GetData(), dshape.Data());
10633 }
10634
ProjectDelta(int vertex,Vector & dofs) const10635 void L2Pos_TetrahedronElement::ProjectDelta(int vertex, Vector &dofs) const
10636 {
10637 dofs = 0.0;
10638 switch (vertex)
10639 {
10640 case 0: dofs[0] = 1.0; break;
10641 case 1: dofs[order] = 1.0; break;
10642 case 2: dofs[(order*(order+3))/2] = 1.0; break;
10643 case 3: dofs[dof-1] = 1.0; break;
10644 }
10645 }
10646
10647
L2_WedgeElement(const int p,const int btype)10648 L2_WedgeElement::L2_WedgeElement(const int p, const int btype)
10649 : NodalFiniteElement(3, Geometry::PRISM, ((p + 1)*(p + 1)*(p + 2))/2,
10650 p, FunctionSpace::Qk),
10651 TriangleFE(p, btype),
10652 SegmentFE(p, btype)
10653 {
10654 #ifndef MFEM_THREAD_SAFE
10655 t_shape.SetSize(TriangleFE.GetDof());
10656 s_shape.SetSize(SegmentFE.GetDof());
10657 t_dshape.SetSize(TriangleFE.GetDof(), 2);
10658 s_dshape.SetSize(SegmentFE.GetDof(), 1);
10659 #endif
10660
10661 t_dof.SetSize(dof);
10662 s_dof.SetSize(dof);
10663
10664 // Interior DoFs
10665 int m=0;
10666 for (int k=0; k<=p; k++)
10667 {
10668 int l=0;
10669 for (int j=0; j<=p; j++)
10670 {
10671 for (int i=0; i<=j; i++)
10672 {
10673 t_dof[m] = l;
10674 s_dof[m] = k;
10675 l++; m++;
10676 }
10677 }
10678 }
10679
10680 // Define Nodes
10681 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
10682 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
10683 for (int i=0; i<dof; i++)
10684 {
10685 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
10686 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
10687 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
10688 }
10689 }
10690
CalcShape(const IntegrationPoint & ip,Vector & shape) const10691 void L2_WedgeElement::CalcShape(const IntegrationPoint &ip,
10692 Vector &shape) const
10693 {
10694 #ifdef MFEM_THREAD_SAFE
10695 Vector t_shape(TriangleFE.GetDof());
10696 Vector s_shape(SegmentFE.GetDof());
10697 #endif
10698
10699 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
10700
10701 TriangleFE.CalcShape(ip, t_shape);
10702 SegmentFE.CalcShape(ipz, s_shape);
10703
10704 for (int i=0; i<dof; i++)
10705 {
10706 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
10707 }
10708 }
10709
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10710 void L2_WedgeElement::CalcDShape(const IntegrationPoint &ip,
10711 DenseMatrix &dshape) const
10712 {
10713 #ifdef MFEM_THREAD_SAFE
10714 Vector t_shape(TriangleFE.GetDof());
10715 DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
10716 Vector s_shape(SegmentFE.GetDof());
10717 DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
10718 #endif
10719
10720 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
10721
10722 TriangleFE.CalcShape(ip, t_shape);
10723 TriangleFE.CalcDShape(ip, t_dshape);
10724 SegmentFE.CalcShape(ipz, s_shape);
10725 SegmentFE.CalcDShape(ipz, s_dshape);
10726
10727 for (int i=0; i<dof; i++)
10728 {
10729 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
10730 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
10731 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
10732 }
10733 }
10734
10735
L2Pos_WedgeElement(const int p)10736 L2Pos_WedgeElement::L2Pos_WedgeElement(const int p)
10737 : PositiveFiniteElement(3, Geometry::PRISM,
10738 ((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
10739 TriangleFE(p),
10740 SegmentFE(p)
10741 {
10742 #ifndef MFEM_THREAD_SAFE
10743 t_shape.SetSize(TriangleFE.GetDof());
10744 s_shape.SetSize(SegmentFE.GetDof());
10745 t_dshape.SetSize(TriangleFE.GetDof(), 2);
10746 s_dshape.SetSize(SegmentFE.GetDof(), 1);
10747 #endif
10748
10749 t_dof.SetSize(dof);
10750 s_dof.SetSize(dof);
10751
10752 // Interior DoFs
10753 int m=0;
10754 for (int k=0; k<=p; k++)
10755 {
10756 int l=0;
10757 for (int j=0; j<=p; j++)
10758 {
10759 for (int i=0; i<=j; i++)
10760 {
10761 t_dof[m] = l;
10762 s_dof[m] = k;
10763 l++; m++;
10764 }
10765 }
10766 }
10767
10768 // Define Nodes
10769 const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
10770 const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
10771 for (int i=0; i<dof; i++)
10772 {
10773 Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
10774 Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
10775 Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
10776 }
10777 }
10778
CalcShape(const IntegrationPoint & ip,Vector & shape) const10779 void L2Pos_WedgeElement::CalcShape(const IntegrationPoint &ip,
10780 Vector &shape) const
10781 {
10782 #ifdef MFEM_THREAD_SAFE
10783 Vector t_shape(TriangleFE.GetDof());
10784 Vector s_shape(SegmentFE.GetDof());
10785 #endif
10786
10787 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
10788
10789 TriangleFE.CalcShape(ip, t_shape);
10790 SegmentFE.CalcShape(ipz, s_shape);
10791
10792 for (int i=0; i<dof; i++)
10793 {
10794 shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
10795 }
10796 }
10797
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const10798 void L2Pos_WedgeElement::CalcDShape(const IntegrationPoint &ip,
10799 DenseMatrix &dshape) const
10800 {
10801 #ifdef MFEM_THREAD_SAFE
10802 Vector t_shape(TriangleFE.GetDof());
10803 DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
10804 Vector s_shape(SegmentFE.GetDof());
10805 DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
10806 #endif
10807
10808 IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
10809
10810 TriangleFE.CalcShape(ip, t_shape);
10811 TriangleFE.CalcDShape(ip, t_dshape);
10812 SegmentFE.CalcShape(ipz, s_shape);
10813 SegmentFE.CalcDShape(ipz, s_dshape);
10814
10815 for (int i=0; i<dof; i++)
10816 {
10817 dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
10818 dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
10819 dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
10820 }
10821 }
10822
10823
10824 const double RT_QuadrilateralElement::nk[8] =
10825 { 0., -1., 1., 0., 0., 1., -1., 0. };
10826
RT_QuadrilateralElement(const int p,const int cb_type,const int ob_type)10827 RT_QuadrilateralElement::RT_QuadrilateralElement(const int p,
10828 const int cb_type,
10829 const int ob_type)
10830 : VectorTensorFiniteElement(2, 2*(p + 1)*(p + 2), p + 1, cb_type, ob_type,
10831 H_DIV, DofMapType::L2_DOF_MAP),
10832 dof2nk(dof),
10833 cp(poly1d.ClosedPoints(p + 1, cb_type))
10834 {
10835 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
10836
10837 dof_map.SetSize(dof);
10838
10839 const double *op = poly1d.OpenPoints(p, ob_type);
10840 const int dof2 = dof/2;
10841
10842 #ifndef MFEM_THREAD_SAFE
10843 shape_cx.SetSize(p + 2);
10844 shape_ox.SetSize(p + 1);
10845 shape_cy.SetSize(p + 2);
10846 shape_oy.SetSize(p + 1);
10847 dshape_cx.SetSize(p + 2);
10848 dshape_cy.SetSize(p + 2);
10849 #endif
10850
10851 // edges
10852 int o = 0;
10853 for (int i = 0; i <= p; i++) // (0,1)
10854 {
10855 dof_map[1*dof2 + i + 0*(p + 1)] = o++;
10856 }
10857 for (int i = 0; i <= p; i++) // (1,2)
10858 {
10859 dof_map[0*dof2 + (p + 1) + i*(p + 2)] = o++;
10860 }
10861 for (int i = 0; i <= p; i++) // (2,3)
10862 {
10863 dof_map[1*dof2 + (p - i) + (p + 1)*(p + 1)] = o++;
10864 }
10865 for (int i = 0; i <= p; i++) // (3,0)
10866 {
10867 dof_map[0*dof2 + 0 + (p - i)*(p + 2)] = o++;
10868 }
10869
10870 // interior
10871 for (int j = 0; j <= p; j++) // x-components
10872 for (int i = 1; i <= p; i++)
10873 {
10874 dof_map[0*dof2 + i + j*(p + 2)] = o++;
10875 }
10876 for (int j = 1; j <= p; j++) // y-components
10877 for (int i = 0; i <= p; i++)
10878 {
10879 dof_map[1*dof2 + i + j*(p + 1)] = o++;
10880 }
10881
10882 // dof orientations
10883 // x-components
10884 for (int j = 0; j <= p; j++)
10885 for (int i = 0; i <= p/2; i++)
10886 {
10887 int idx = 0*dof2 + i + j*(p + 2);
10888 dof_map[idx] = -1 - dof_map[idx];
10889 }
10890 if (p%2 == 1)
10891 for (int j = p/2 + 1; j <= p; j++)
10892 {
10893 int idx = 0*dof2 + (p/2 + 1) + j*(p + 2);
10894 dof_map[idx] = -1 - dof_map[idx];
10895 }
10896 // y-components
10897 for (int j = 0; j <= p/2; j++)
10898 for (int i = 0; i <= p; i++)
10899 {
10900 int idx = 1*dof2 + i + j*(p + 1);
10901 dof_map[idx] = -1 - dof_map[idx];
10902 }
10903 if (p%2 == 1)
10904 for (int i = 0; i <= p/2; i++)
10905 {
10906 int idx = 1*dof2 + i + (p/2 + 1)*(p + 1);
10907 dof_map[idx] = -1 - dof_map[idx];
10908 }
10909
10910 o = 0;
10911 for (int j = 0; j <= p; j++)
10912 for (int i = 0; i <= p + 1; i++)
10913 {
10914 int idx;
10915 if ((idx = dof_map[o++]) < 0)
10916 {
10917 idx = -1 - idx;
10918 dof2nk[idx] = 3;
10919 }
10920 else
10921 {
10922 dof2nk[idx] = 1;
10923 }
10924 Nodes.IntPoint(idx).Set2(cp[i], op[j]);
10925 }
10926 for (int j = 0; j <= p + 1; j++)
10927 for (int i = 0; i <= p; i++)
10928 {
10929 int idx;
10930 if ((idx = dof_map[o++]) < 0)
10931 {
10932 idx = -1 - idx;
10933 dof2nk[idx] = 0;
10934 }
10935 else
10936 {
10937 dof2nk[idx] = 2;
10938 }
10939 Nodes.IntPoint(idx).Set2(op[i], cp[j]);
10940 }
10941 }
10942
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const10943 void RT_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip,
10944 DenseMatrix &shape) const
10945 {
10946 const int pp1 = order;
10947
10948 #ifdef MFEM_THREAD_SAFE
10949 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
10950 #endif
10951
10952 if (obasis1d.IsIntegratedType())
10953 {
10954 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
10955 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
10956 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
10957 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
10958 }
10959 else
10960 {
10961 cbasis1d.Eval(ip.x, shape_cx);
10962 cbasis1d.Eval(ip.y, shape_cy);
10963 obasis1d.Eval(ip.x, shape_ox);
10964 obasis1d.Eval(ip.y, shape_oy);
10965 }
10966
10967 int o = 0;
10968 for (int j = 0; j < pp1; j++)
10969 for (int i = 0; i <= pp1; i++)
10970 {
10971 int idx, s;
10972 if ((idx = dof_map[o++]) < 0)
10973 {
10974 idx = -1 - idx, s = -1;
10975 }
10976 else
10977 {
10978 s = +1;
10979 }
10980 shape(idx,0) = s*shape_cx(i)*shape_oy(j);
10981 shape(idx,1) = 0.;
10982 }
10983 for (int j = 0; j <= pp1; j++)
10984 for (int i = 0; i < pp1; i++)
10985 {
10986 int idx, s;
10987 if ((idx = dof_map[o++]) < 0)
10988 {
10989 idx = -1 - idx, s = -1;
10990 }
10991 else
10992 {
10993 s = +1;
10994 }
10995 shape(idx,0) = 0.;
10996 shape(idx,1) = s*shape_ox(i)*shape_cy(j);
10997 }
10998 }
10999
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const11000 void RT_QuadrilateralElement::CalcDivShape(const IntegrationPoint &ip,
11001 Vector &divshape) const
11002 {
11003 const int pp1 = order;
11004
11005 #ifdef MFEM_THREAD_SAFE
11006 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
11007 Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1);
11008 #endif
11009
11010 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
11011 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
11012 if (obasis1d.IsIntegratedType())
11013 {
11014 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
11015 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
11016 }
11017 else
11018 {
11019 obasis1d.Eval(ip.x, shape_ox);
11020 obasis1d.Eval(ip.y, shape_oy);
11021 }
11022
11023 int o = 0;
11024 for (int j = 0; j < pp1; j++)
11025 for (int i = 0; i <= pp1; i++)
11026 {
11027 int idx, s;
11028 if ((idx = dof_map[o++]) < 0)
11029 {
11030 idx = -1 - idx, s = -1;
11031 }
11032 else
11033 {
11034 s = +1;
11035 }
11036 divshape(idx) = s*dshape_cx(i)*shape_oy(j);
11037 }
11038 for (int j = 0; j <= pp1; j++)
11039 for (int i = 0; i < pp1; i++)
11040 {
11041 int idx, s;
11042 if ((idx = dof_map[o++]) < 0)
11043 {
11044 idx = -1 - idx, s = -1;
11045 }
11046 else
11047 {
11048 s = +1;
11049 }
11050 divshape(idx) = s*shape_ox(i)*dshape_cy(j);
11051 }
11052 }
11053
ProjectIntegrated(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const11054 void RT_QuadrilateralElement::ProjectIntegrated(VectorCoefficient &vc,
11055 ElementTransformation &Trans,
11056 Vector &dofs) const
11057 {
11058 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
11059 double vk[Geometry::MaxDim];
11060 Vector xk(vk, vc.GetVDim());
11061
11062 const IntegrationRule &ir = IntRules.Get(Geometry::SEGMENT, order);
11063 const int nqpt = ir.GetNPoints();
11064
11065 IntegrationPoint ip2d;
11066
11067 int o = 0;
11068 for (int c = 0; c < 2; c++)
11069 {
11070 int im = (c == 0) ? order + 1 : order;
11071 int jm = (c == 1) ? order + 1 : order;
11072 for (int j = 0; j < jm; j++)
11073 for (int i = 0; i < im; i++)
11074 {
11075 int idx = dof_map[o++];
11076 if (idx < 0) { idx = -1 - idx; }
11077 int ic = (c == 0) ? j : i;
11078 const double h = cp[ic+1] - cp[ic];
11079 double val = 0.0;
11080 for (int k = 0; k < nqpt; k++)
11081 {
11082 const IntegrationPoint &ip1d = ir.IntPoint(k);
11083 if (c == 0) { ip2d.Set2(cp[i], cp[j] + (h*ip1d.x)); }
11084 else { ip2d.Set2(cp[i] + (h*ip1d.x), cp[j]); }
11085 Trans.SetIntPoint(&ip2d);
11086 vc.Eval(xk, Trans, ip2d);
11087 // nk^t adj(J) xk
11088 const double ipval = Trans.AdjugateJacobian().InnerProduct(vk,
11089 nk + dof2nk[idx]*dim);
11090 val += ip1d.weight*ipval;
11091 }
11092 dofs(idx) = val*h;
11093 }
11094 }
11095 }
11096
11097
11098 const double RT_HexahedronElement::nk[18] =
11099 { 0.,0.,-1., 0.,-1.,0., 1.,0.,0., 0.,1.,0., -1.,0.,0., 0.,0.,1. };
11100
RT_HexahedronElement(const int p,const int cb_type,const int ob_type)11101 RT_HexahedronElement::RT_HexahedronElement(const int p,
11102 const int cb_type,
11103 const int ob_type)
11104 : VectorTensorFiniteElement(3, 3*(p + 1)*(p + 1)*(p + 2), p + 1, cb_type,
11105 ob_type, H_DIV, DofMapType::L2_DOF_MAP),
11106 dof2nk(dof),
11107 cp(poly1d.ClosedPoints(p + 1, cb_type))
11108 {
11109 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
11110
11111 dof_map.SetSize(dof);
11112
11113 const double *op = poly1d.OpenPoints(p, ob_type);
11114 const int dof3 = dof/3;
11115
11116 #ifndef MFEM_THREAD_SAFE
11117 shape_cx.SetSize(p + 2);
11118 shape_ox.SetSize(p + 1);
11119 shape_cy.SetSize(p + 2);
11120 shape_oy.SetSize(p + 1);
11121 shape_cz.SetSize(p + 2);
11122 shape_oz.SetSize(p + 1);
11123 dshape_cx.SetSize(p + 2);
11124 dshape_cy.SetSize(p + 2);
11125 dshape_cz.SetSize(p + 2);
11126 #endif
11127
11128 // faces
11129 int o = 0;
11130 for (int j = 0; j <= p; j++) // (3,2,1,0) -- bottom
11131 for (int i = 0; i <= p; i++)
11132 {
11133 dof_map[2*dof3 + i + ((p - j) + 0*(p + 1))*(p + 1)] = o++;
11134 }
11135 for (int j = 0; j <= p; j++) // (0,1,5,4) -- front
11136 for (int i = 0; i <= p; i++)
11137 {
11138 dof_map[1*dof3 + i + (0 + j*(p + 2))*(p + 1)] = o++;
11139 }
11140 for (int j = 0; j <= p; j++) // (1,2,6,5) -- right
11141 for (int i = 0; i <= p; i++)
11142 {
11143 dof_map[0*dof3 + (p + 1) + (i + j*(p + 1))*(p + 2)] = o++;
11144 }
11145 for (int j = 0; j <= p; j++) // (2,3,7,6) -- back
11146 for (int i = 0; i <= p; i++)
11147 {
11148 dof_map[1*dof3 + (p - i) + ((p + 1) + j*(p + 2))*(p + 1)] = o++;
11149 }
11150 for (int j = 0; j <= p; j++) // (3,0,4,7) -- left
11151 for (int i = 0; i <= p; i++)
11152 {
11153 dof_map[0*dof3 + 0 + ((p - i) + j*(p + 1))*(p + 2)] = o++;
11154 }
11155 for (int j = 0; j <= p; j++) // (4,5,6,7) -- top
11156 for (int i = 0; i <= p; i++)
11157 {
11158 dof_map[2*dof3 + i + (j + (p + 1)*(p + 1))*(p + 1)] = o++;
11159 }
11160
11161 // interior
11162 // x-components
11163 for (int k = 0; k <= p; k++)
11164 for (int j = 0; j <= p; j++)
11165 for (int i = 1; i <= p; i++)
11166 {
11167 dof_map[0*dof3 + i + (j + k*(p + 1))*(p + 2)] = o++;
11168 }
11169 // y-components
11170 for (int k = 0; k <= p; k++)
11171 for (int j = 1; j <= p; j++)
11172 for (int i = 0; i <= p; i++)
11173 {
11174 dof_map[1*dof3 + i + (j + k*(p + 2))*(p + 1)] = o++;
11175 }
11176 // z-components
11177 for (int k = 1; k <= p; k++)
11178 for (int j = 0; j <= p; j++)
11179 for (int i = 0; i <= p; i++)
11180 {
11181 dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++;
11182 }
11183
11184 // dof orientations
11185 // for odd p, do not change the orientations in the mid-planes
11186 // {i = p/2 + 1}, {j = p/2 + 1}, {k = p/2 + 1} in the x, y, z-components
11187 // respectively.
11188 // x-components
11189 for (int k = 0; k <= p; k++)
11190 for (int j = 0; j <= p; j++)
11191 for (int i = 0; i <= p/2; i++)
11192 {
11193 int idx = 0*dof3 + i + (j + k*(p + 1))*(p + 2);
11194 dof_map[idx] = -1 - dof_map[idx];
11195 }
11196 // y-components
11197 for (int k = 0; k <= p; k++)
11198 for (int j = 0; j <= p/2; j++)
11199 for (int i = 0; i <= p; i++)
11200 {
11201 int idx = 1*dof3 + i + (j + k*(p + 2))*(p + 1);
11202 dof_map[idx] = -1 - dof_map[idx];
11203 }
11204 // z-components
11205 for (int k = 0; k <= p/2; k++)
11206 for (int j = 0; j <= p; j++)
11207 for (int i = 0; i <= p; i++)
11208 {
11209 int idx = 2*dof3 + i + (j + k*(p + 1))*(p + 1);
11210 dof_map[idx] = -1 - dof_map[idx];
11211 }
11212
11213 o = 0;
11214 // x-components
11215 for (int k = 0; k <= p; k++)
11216 for (int j = 0; j <= p; j++)
11217 for (int i = 0; i <= p + 1; i++)
11218 {
11219 int idx;
11220 if ((idx = dof_map[o++]) < 0)
11221 {
11222 idx = -1 - idx;
11223 dof2nk[idx] = 4;
11224 }
11225 else
11226 {
11227 dof2nk[idx] = 2;
11228 }
11229 Nodes.IntPoint(idx).Set3(cp[i], op[j], op[k]);
11230 }
11231 // y-components
11232 for (int k = 0; k <= p; k++)
11233 for (int j = 0; j <= p + 1; j++)
11234 for (int i = 0; i <= p; i++)
11235 {
11236 int idx;
11237 if ((idx = dof_map[o++]) < 0)
11238 {
11239 idx = -1 - idx;
11240 dof2nk[idx] = 1;
11241 }
11242 else
11243 {
11244 dof2nk[idx] = 3;
11245 }
11246 Nodes.IntPoint(idx).Set3(op[i], cp[j], op[k]);
11247 }
11248 // z-components
11249 for (int k = 0; k <= p + 1; k++)
11250 for (int j = 0; j <= p; j++)
11251 for (int i = 0; i <= p; i++)
11252 {
11253 int idx;
11254 if ((idx = dof_map[o++]) < 0)
11255 {
11256 idx = -1 - idx;
11257 dof2nk[idx] = 0;
11258 }
11259 else
11260 {
11261 dof2nk[idx] = 5;
11262 }
11263 Nodes.IntPoint(idx).Set3(op[i], op[j], cp[k]);
11264 }
11265 }
11266
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const11267 void RT_HexahedronElement::CalcVShape(const IntegrationPoint &ip,
11268 DenseMatrix &shape) const
11269 {
11270 const int pp1 = order;
11271
11272 #ifdef MFEM_THREAD_SAFE
11273 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
11274 Vector shape_cz(pp1 + 1), shape_oz(pp1);
11275 #endif
11276
11277 if (obasis1d.IsIntegratedType())
11278 {
11279 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
11280 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
11281 cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
11282 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
11283 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
11284 obasis1d.EvalIntegrated(dshape_cz, shape_oz);
11285 }
11286 else
11287 {
11288 cbasis1d.Eval(ip.x, shape_cx);
11289 cbasis1d.Eval(ip.y, shape_cy);
11290 cbasis1d.Eval(ip.z, shape_cz);
11291 obasis1d.Eval(ip.x, shape_ox);
11292 obasis1d.Eval(ip.y, shape_oy);
11293 obasis1d.Eval(ip.z, shape_oz);
11294 }
11295
11296 int o = 0;
11297 // x-components
11298 for (int k = 0; k < pp1; k++)
11299 for (int j = 0; j < pp1; j++)
11300 for (int i = 0; i <= pp1; i++)
11301 {
11302 int idx, s;
11303 if ((idx = dof_map[o++]) < 0)
11304 {
11305 idx = -1 - idx, s = -1;
11306 }
11307 else
11308 {
11309 s = +1;
11310 }
11311 shape(idx,0) = s*shape_cx(i)*shape_oy(j)*shape_oz(k);
11312 shape(idx,1) = 0.;
11313 shape(idx,2) = 0.;
11314 }
11315 // y-components
11316 for (int k = 0; k < pp1; k++)
11317 for (int j = 0; j <= pp1; j++)
11318 for (int i = 0; i < pp1; i++)
11319 {
11320 int idx, s;
11321 if ((idx = dof_map[o++]) < 0)
11322 {
11323 idx = -1 - idx, s = -1;
11324 }
11325 else
11326 {
11327 s = +1;
11328 }
11329 shape(idx,0) = 0.;
11330 shape(idx,1) = s*shape_ox(i)*shape_cy(j)*shape_oz(k);
11331 shape(idx,2) = 0.;
11332 }
11333 // z-components
11334 for (int k = 0; k <= pp1; k++)
11335 for (int j = 0; j < pp1; j++)
11336 for (int i = 0; i < pp1; i++)
11337 {
11338 int idx, s;
11339 if ((idx = dof_map[o++]) < 0)
11340 {
11341 idx = -1 - idx, s = -1;
11342 }
11343 else
11344 {
11345 s = +1;
11346 }
11347 shape(idx,0) = 0.;
11348 shape(idx,1) = 0.;
11349 shape(idx,2) = s*shape_ox(i)*shape_oy(j)*shape_cz(k);
11350 }
11351 }
11352
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const11353 void RT_HexahedronElement::CalcDivShape(const IntegrationPoint &ip,
11354 Vector &divshape) const
11355 {
11356 const int pp1 = order;
11357
11358 #ifdef MFEM_THREAD_SAFE
11359 Vector shape_cx(pp1 + 1), shape_ox(pp1), shape_cy(pp1 + 1), shape_oy(pp1);
11360 Vector shape_cz(pp1 + 1), shape_oz(pp1);
11361 Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1), dshape_cz(pp1 + 1);
11362 #endif
11363
11364 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
11365 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
11366 cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
11367 if (obasis1d.IsIntegratedType())
11368 {
11369 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
11370 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
11371 obasis1d.EvalIntegrated(dshape_cz, shape_oz);
11372 }
11373 else
11374 {
11375 obasis1d.Eval(ip.x, shape_ox);
11376 obasis1d.Eval(ip.y, shape_oy);
11377 obasis1d.Eval(ip.z, shape_oz);
11378 }
11379
11380 int o = 0;
11381 // x-components
11382 for (int k = 0; k < pp1; k++)
11383 for (int j = 0; j < pp1; j++)
11384 for (int i = 0; i <= pp1; i++)
11385 {
11386 int idx, s;
11387 if ((idx = dof_map[o++]) < 0)
11388 {
11389 idx = -1 - idx, s = -1;
11390 }
11391 else
11392 {
11393 s = +1;
11394 }
11395 divshape(idx) = s*dshape_cx(i)*shape_oy(j)*shape_oz(k);
11396 }
11397 // y-components
11398 for (int k = 0; k < pp1; k++)
11399 for (int j = 0; j <= pp1; j++)
11400 for (int i = 0; i < pp1; i++)
11401 {
11402 int idx, s;
11403 if ((idx = dof_map[o++]) < 0)
11404 {
11405 idx = -1 - idx, s = -1;
11406 }
11407 else
11408 {
11409 s = +1;
11410 }
11411 divshape(idx) = s*shape_ox(i)*dshape_cy(j)*shape_oz(k);
11412 }
11413 // z-components
11414 for (int k = 0; k <= pp1; k++)
11415 for (int j = 0; j < pp1; j++)
11416 for (int i = 0; i < pp1; i++)
11417 {
11418 int idx, s;
11419 if ((idx = dof_map[o++]) < 0)
11420 {
11421 idx = -1 - idx, s = -1;
11422 }
11423 else
11424 {
11425 s = +1;
11426 }
11427 divshape(idx) = s*shape_ox(i)*shape_oy(j)*dshape_cz(k);
11428 }
11429 }
11430
ProjectIntegrated(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const11431 void RT_HexahedronElement::ProjectIntegrated(VectorCoefficient &vc,
11432 ElementTransformation &Trans,
11433 Vector &dofs) const
11434 {
11435 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
11436 double vq[Geometry::MaxDim];
11437 Vector xq(vq, vc.GetVDim());
11438
11439 const IntegrationRule &ir2d = IntRules.Get(Geometry::SQUARE, order);
11440 const int nqpt = ir2d.GetNPoints();
11441
11442 IntegrationPoint ip3d;
11443
11444 int o = 0;
11445 for (int c = 0; c < 3; c++)
11446 {
11447 int im = (c == 0) ? order + 1 : order;
11448 int jm = (c == 1) ? order + 1 : order;
11449 int km = (c == 2) ? order + 1 : order;
11450 for (int k = 0; k < km; k++)
11451 for (int j = 0; j < jm; j++)
11452 for (int i = 0; i < im; i++)
11453 {
11454 int idx = dof_map[o++];
11455 if (idx < 0) { idx = -1 - idx; }
11456 int ic1, ic2;
11457 if (c == 0) { ic1 = j; ic2 = k; }
11458 else if (c == 1) { ic1 = i; ic2 = k; }
11459 else { ic1 = i; ic2 = j; }
11460 const double h1 = cp[ic1+1] - cp[ic1];
11461 const double h2 = cp[ic2+1] - cp[ic2];
11462 double val = 0.0;
11463 for (int q = 0; q < nqpt; q++)
11464 {
11465 const IntegrationPoint &ip2d = ir2d.IntPoint(q);
11466 if (c == 0) { ip3d.Set3(cp[i], cp[j] + h1*ip2d.x, cp[k] + h2*ip2d.y); }
11467 else if (c == 1) { ip3d.Set3(cp[i] + h1*ip2d.x, cp[j], cp[k] + h2*ip2d.y); }
11468 else { ip3d.Set3(cp[i] + h1*ip2d.x, cp[j] + h2*ip2d.y, cp[k]); }
11469 Trans.SetIntPoint(&ip3d);
11470 vc.Eval(xq, Trans, ip3d);
11471 // nk^t adj(J) xq
11472 const double ipval
11473 = Trans.AdjugateJacobian().InnerProduct(vq, nk + dof2nk[idx]*dim);
11474 val += ip2d.weight*ipval;
11475 }
11476 dofs(idx) = val*h1*h2;
11477 }
11478 }
11479 }
11480
11481
11482 const double RT_TriangleElement::nk[6] =
11483 { 0., -1., 1., 1., -1., 0. };
11484
11485 const double RT_TriangleElement::c = 1./3.;
11486
RT_TriangleElement(const int p)11487 RT_TriangleElement::RT_TriangleElement(const int p)
11488 : VectorFiniteElement(2, Geometry::TRIANGLE, (p + 1)*(p + 3), p + 1,
11489 H_DIV, FunctionSpace::Pk),
11490 dof2nk(dof)
11491 {
11492 const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL;
11493 const double *bop = poly1d.OpenPoints(p);
11494
11495 #ifndef MFEM_THREAD_SAFE
11496 shape_x.SetSize(p + 1);
11497 shape_y.SetSize(p + 1);
11498 shape_l.SetSize(p + 1);
11499 dshape_x.SetSize(p + 1);
11500 dshape_y.SetSize(p + 1);
11501 dshape_l.SetSize(p + 1);
11502 u.SetSize(dof, dim);
11503 divu.SetSize(dof);
11504 #else
11505 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
11506 #endif
11507
11508 // edges
11509 int o = 0;
11510 for (int i = 0; i <= p; i++) // (0,1)
11511 {
11512 Nodes.IntPoint(o).Set2(bop[i], 0.);
11513 dof2nk[o++] = 0;
11514 }
11515 for (int i = 0; i <= p; i++) // (1,2)
11516 {
11517 Nodes.IntPoint(o).Set2(bop[p-i], bop[i]);
11518 dof2nk[o++] = 1;
11519 }
11520 for (int i = 0; i <= p; i++) // (2,0)
11521 {
11522 Nodes.IntPoint(o).Set2(0., bop[p-i]);
11523 dof2nk[o++] = 2;
11524 }
11525
11526 // interior
11527 for (int j = 0; j < p; j++)
11528 for (int i = 0; i + j < p; i++)
11529 {
11530 double w = iop[i] + iop[j] + iop[p-1-i-j];
11531 Nodes.IntPoint(o).Set2(iop[i]/w, iop[j]/w);
11532 dof2nk[o++] = 0;
11533 Nodes.IntPoint(o).Set2(iop[i]/w, iop[j]/w);
11534 dof2nk[o++] = 2;
11535 }
11536
11537 DenseMatrix T(dof);
11538 for (int k = 0; k < dof; k++)
11539 {
11540 const IntegrationPoint &ip = Nodes.IntPoint(k);
11541 poly1d.CalcBasis(p, ip.x, shape_x);
11542 poly1d.CalcBasis(p, ip.y, shape_y);
11543 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
11544 const double *n_k = nk + 2*dof2nk[k];
11545
11546 o = 0;
11547 for (int j = 0; j <= p; j++)
11548 for (int i = 0; i + j <= p; i++)
11549 {
11550 double s = shape_x(i)*shape_y(j)*shape_l(p-i-j);
11551 T(o++, k) = s*n_k[0];
11552 T(o++, k) = s*n_k[1];
11553 }
11554 for (int i = 0; i <= p; i++)
11555 {
11556 double s = shape_x(i)*shape_y(p-i);
11557 T(o++, k) = s*((ip.x - c)*n_k[0] + (ip.y - c)*n_k[1]);
11558 }
11559 }
11560
11561 Ti.Factor(T);
11562 // mfem::out << "RT_TriangleElement(" << p << ") : "; Ti.TestInversion();
11563 }
11564
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const11565 void RT_TriangleElement::CalcVShape(const IntegrationPoint &ip,
11566 DenseMatrix &shape) const
11567 {
11568 const int p = order - 1;
11569
11570 #ifdef MFEM_THREAD_SAFE
11571 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
11572 DenseMatrix u(dof, dim);
11573 #endif
11574
11575 poly1d.CalcBasis(p, ip.x, shape_x);
11576 poly1d.CalcBasis(p, ip.y, shape_y);
11577 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l);
11578
11579 int o = 0;
11580 for (int j = 0; j <= p; j++)
11581 for (int i = 0; i + j <= p; i++)
11582 {
11583 double s = shape_x(i)*shape_y(j)*shape_l(p-i-j);
11584 u(o,0) = s; u(o,1) = 0; o++;
11585 u(o,0) = 0; u(o,1) = s; o++;
11586 }
11587 for (int i = 0; i <= p; i++)
11588 {
11589 double s = shape_x(i)*shape_y(p-i);
11590 u(o,0) = (ip.x - c)*s;
11591 u(o,1) = (ip.y - c)*s;
11592 o++;
11593 }
11594
11595 Ti.Mult(u, shape);
11596 }
11597
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const11598 void RT_TriangleElement::CalcDivShape(const IntegrationPoint &ip,
11599 Vector &divshape) const
11600 {
11601 const int p = order - 1;
11602
11603 #ifdef MFEM_THREAD_SAFE
11604 Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
11605 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
11606 Vector divu(dof);
11607 #endif
11608
11609 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
11610 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
11611 poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l);
11612
11613 int o = 0;
11614 for (int j = 0; j <= p; j++)
11615 for (int i = 0; i + j <= p; i++)
11616 {
11617 int k = p - i - j;
11618 divu(o++) = (dshape_x(i)*shape_l(k) -
11619 shape_x(i)*dshape_l(k))*shape_y(j);
11620 divu(o++) = (dshape_y(j)*shape_l(k) -
11621 shape_y(j)*dshape_l(k))*shape_x(i);
11622 }
11623 for (int i = 0; i <= p; i++)
11624 {
11625 int j = p - i;
11626 divu(o++) = ((shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j) +
11627 (shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i));
11628 }
11629
11630 Ti.Mult(divu, divshape);
11631 }
11632
11633
11634 const double RT_TetrahedronElement::nk[12] =
11635 { 1,1,1, -1,0,0, 0,-1,0, 0,0,-1 };
11636 // { .5,.5,.5, -.5,0,0, 0,-.5,0, 0,0,-.5}; // n_F |F|
11637
11638 const double RT_TetrahedronElement::c = 1./4.;
11639
RT_TetrahedronElement(const int p)11640 RT_TetrahedronElement::RT_TetrahedronElement(const int p)
11641 : VectorFiniteElement(3, Geometry::TETRAHEDRON, (p + 1)*(p + 2)*(p + 4)/2,
11642 p + 1, H_DIV, FunctionSpace::Pk),
11643 dof2nk(dof)
11644 {
11645 const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL;
11646 const double *bop = poly1d.OpenPoints(p);
11647
11648 #ifndef MFEM_THREAD_SAFE
11649 shape_x.SetSize(p + 1);
11650 shape_y.SetSize(p + 1);
11651 shape_z.SetSize(p + 1);
11652 shape_l.SetSize(p + 1);
11653 dshape_x.SetSize(p + 1);
11654 dshape_y.SetSize(p + 1);
11655 dshape_z.SetSize(p + 1);
11656 dshape_l.SetSize(p + 1);
11657 u.SetSize(dof, dim);
11658 divu.SetSize(dof);
11659 #else
11660 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
11661 #endif
11662
11663 int o = 0;
11664 // faces (see Mesh::GenerateFaces in mesh/mesh.cpp,
11665 // the constructor of H1_TetrahedronElement)
11666 for (int j = 0; j <= p; j++)
11667 for (int i = 0; i + j <= p; i++) // (1,2,3)
11668 {
11669 double w = bop[i] + bop[j] + bop[p-i-j];
11670 Nodes.IntPoint(o).Set3(bop[p-i-j]/w, bop[i]/w, bop[j]/w);
11671 dof2nk[o++] = 0;
11672 }
11673 for (int j = 0; j <= p; j++)
11674 for (int i = 0; i + j <= p; i++) // (0,3,2)
11675 {
11676 double w = bop[i] + bop[j] + bop[p-i-j];
11677 Nodes.IntPoint(o).Set3(0., bop[j]/w, bop[i]/w);
11678 dof2nk[o++] = 1;
11679 }
11680 for (int j = 0; j <= p; j++)
11681 for (int i = 0; i + j <= p; i++) // (0,1,3)
11682 {
11683 double w = bop[i] + bop[j] + bop[p-i-j];
11684 Nodes.IntPoint(o).Set3(bop[i]/w, 0., bop[j]/w);
11685 dof2nk[o++] = 2;
11686 }
11687 for (int j = 0; j <= p; j++)
11688 for (int i = 0; i + j <= p; i++) // (0,2,1)
11689 {
11690 double w = bop[i] + bop[j] + bop[p-i-j];
11691 Nodes.IntPoint(o).Set3(bop[j]/w, bop[i]/w, 0.);
11692 dof2nk[o++] = 3;
11693 }
11694
11695 // interior
11696 for (int k = 0; k < p; k++)
11697 for (int j = 0; j + k < p; j++)
11698 for (int i = 0; i + j + k < p; i++)
11699 {
11700 double w = iop[i] + iop[j] + iop[k] + iop[p-1-i-j-k];
11701 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
11702 dof2nk[o++] = 1;
11703 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
11704 dof2nk[o++] = 2;
11705 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
11706 dof2nk[o++] = 3;
11707 }
11708
11709 DenseMatrix T(dof);
11710 for (int m = 0; m < dof; m++)
11711 {
11712 const IntegrationPoint &ip = Nodes.IntPoint(m);
11713 poly1d.CalcBasis(p, ip.x, shape_x);
11714 poly1d.CalcBasis(p, ip.y, shape_y);
11715 poly1d.CalcBasis(p, ip.z, shape_z);
11716 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
11717 const double *nm = nk + 3*dof2nk[m];
11718
11719 o = 0;
11720 for (int k = 0; k <= p; k++)
11721 for (int j = 0; j + k <= p; j++)
11722 for (int i = 0; i + j + k <= p; i++)
11723 {
11724 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
11725 T(o++, m) = s * nm[0];
11726 T(o++, m) = s * nm[1];
11727 T(o++, m) = s * nm[2];
11728 }
11729 for (int j = 0; j <= p; j++)
11730 for (int i = 0; i + j <= p; i++)
11731 {
11732 double s = shape_x(i)*shape_y(j)*shape_z(p-i-j);
11733 T(o++, m) = s*((ip.x - c)*nm[0] + (ip.y - c)*nm[1] +
11734 (ip.z - c)*nm[2]);
11735 }
11736 }
11737
11738 Ti.Factor(T);
11739 // mfem::out << "RT_TetrahedronElement(" << p << ") : "; Ti.TestInversion();
11740 }
11741
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const11742 void RT_TetrahedronElement::CalcVShape(const IntegrationPoint &ip,
11743 DenseMatrix &shape) const
11744 {
11745 const int p = order - 1;
11746
11747 #ifdef MFEM_THREAD_SAFE
11748 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
11749 DenseMatrix u(dof, dim);
11750 #endif
11751
11752 poly1d.CalcBasis(p, ip.x, shape_x);
11753 poly1d.CalcBasis(p, ip.y, shape_y);
11754 poly1d.CalcBasis(p, ip.z, shape_z);
11755 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l);
11756
11757 int o = 0;
11758 for (int k = 0; k <= p; k++)
11759 for (int j = 0; j + k <= p; j++)
11760 for (int i = 0; i + j + k <= p; i++)
11761 {
11762 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(p-i-j-k);
11763 u(o,0) = s; u(o,1) = 0; u(o,2) = 0; o++;
11764 u(o,0) = 0; u(o,1) = s; u(o,2) = 0; o++;
11765 u(o,0) = 0; u(o,1) = 0; u(o,2) = s; o++;
11766 }
11767 for (int j = 0; j <= p; j++)
11768 for (int i = 0; i + j <= p; i++)
11769 {
11770 double s = shape_x(i)*shape_y(j)*shape_z(p-i-j);
11771 u(o,0) = (ip.x - c)*s; u(o,1) = (ip.y - c)*s; u(o,2) = (ip.z - c)*s;
11772 o++;
11773 }
11774
11775 Ti.Mult(u, shape);
11776 }
11777
CalcDivShape(const IntegrationPoint & ip,Vector & divshape) const11778 void RT_TetrahedronElement::CalcDivShape(const IntegrationPoint &ip,
11779 Vector &divshape) const
11780 {
11781 const int p = order - 1;
11782
11783 #ifdef MFEM_THREAD_SAFE
11784 Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
11785 Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
11786 Vector divu(dof);
11787 #endif
11788
11789 poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
11790 poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
11791 poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
11792 poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
11793
11794 int o = 0;
11795 for (int k = 0; k <= p; k++)
11796 for (int j = 0; j + k <= p; j++)
11797 for (int i = 0; i + j + k <= p; i++)
11798 {
11799 int l = p - i - j - k;
11800 divu(o++) = (dshape_x(i)*shape_l(l) -
11801 shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k);
11802 divu(o++) = (dshape_y(j)*shape_l(l) -
11803 shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k);
11804 divu(o++) = (dshape_z(k)*shape_l(l) -
11805 shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j);
11806 }
11807 for (int j = 0; j <= p; j++)
11808 for (int i = 0; i + j <= p; i++)
11809 {
11810 int k = p - i - j;
11811 divu(o++) =
11812 (shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j)*shape_z(k) +
11813 (shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i)*shape_z(k) +
11814 (shape_z(k) + (ip.z - c)*dshape_z(k))*shape_x(i)*shape_y(j);
11815 }
11816
11817 Ti.Mult(divu, divshape);
11818 }
11819
11820
11821 const double ND_HexahedronElement::tk[18] =
11822 { 1.,0.,0., 0.,1.,0., 0.,0.,1., -1.,0.,0., 0.,-1.,0., 0.,0.,-1. };
11823
ND_HexahedronElement(const int p,const int cb_type,const int ob_type)11824 ND_HexahedronElement::ND_HexahedronElement(const int p,
11825 const int cb_type, const int ob_type)
11826 : VectorTensorFiniteElement(3, 3*p*(p + 1)*(p + 1), p, cb_type, ob_type,
11827 H_CURL, DofMapType::L2_DOF_MAP),
11828 dof2tk(dof), cp(poly1d.ClosedPoints(p, cb_type))
11829 {
11830 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
11831
11832 dof_map.SetSize(dof);
11833
11834 const double *op = poly1d.OpenPoints(p - 1, ob_type);
11835 const int dof3 = dof/3;
11836
11837 #ifndef MFEM_THREAD_SAFE
11838 shape_cx.SetSize(p + 1);
11839 shape_ox.SetSize(p);
11840 shape_cy.SetSize(p + 1);
11841 shape_oy.SetSize(p);
11842 shape_cz.SetSize(p + 1);
11843 shape_oz.SetSize(p);
11844 dshape_cx.SetSize(p + 1);
11845 dshape_cy.SetSize(p + 1);
11846 dshape_cz.SetSize(p + 1);
11847 #endif
11848
11849 // edges
11850 int o = 0;
11851 for (int i = 0; i < p; i++) // (0,1)
11852 {
11853 dof_map[0*dof3 + i + (0 + 0*(p + 1))*p] = o++;
11854 }
11855 for (int i = 0; i < p; i++) // (1,2)
11856 {
11857 dof_map[1*dof3 + p + (i + 0*p)*(p + 1)] = o++;
11858 }
11859 for (int i = 0; i < p; i++) // (3,2)
11860 {
11861 dof_map[0*dof3 + i + (p + 0*(p + 1))*p] = o++;
11862 }
11863 for (int i = 0; i < p; i++) // (0,3)
11864 {
11865 dof_map[1*dof3 + 0 + (i + 0*p)*(p + 1)] = o++;
11866 }
11867 for (int i = 0; i < p; i++) // (4,5)
11868 {
11869 dof_map[0*dof3 + i + (0 + p*(p + 1))*p] = o++;
11870 }
11871 for (int i = 0; i < p; i++) // (5,6)
11872 {
11873 dof_map[1*dof3 + p + (i + p*p)*(p + 1)] = o++;
11874 }
11875 for (int i = 0; i < p; i++) // (7,6)
11876 {
11877 dof_map[0*dof3 + i + (p + p*(p + 1))*p] = o++;
11878 }
11879 for (int i = 0; i < p; i++) // (4,7)
11880 {
11881 dof_map[1*dof3 + 0 + (i + p*p)*(p + 1)] = o++;
11882 }
11883 for (int i = 0; i < p; i++) // (0,4)
11884 {
11885 dof_map[2*dof3 + 0 + (0 + i*(p + 1))*(p + 1)] = o++;
11886 }
11887 for (int i = 0; i < p; i++) // (1,5)
11888 {
11889 dof_map[2*dof3 + p + (0 + i*(p + 1))*(p + 1)] = o++;
11890 }
11891 for (int i = 0; i < p; i++) // (2,6)
11892 {
11893 dof_map[2*dof3 + p + (p + i*(p + 1))*(p + 1)] = o++;
11894 }
11895 for (int i = 0; i < p; i++) // (3,7)
11896 {
11897 dof_map[2*dof3 + 0 + (p + i*(p + 1))*(p + 1)] = o++;
11898 }
11899
11900 // faces
11901 // (3,2,1,0) -- bottom
11902 for (int j = 1; j < p; j++) // x - components
11903 for (int i = 0; i < p; i++)
11904 {
11905 dof_map[0*dof3 + i + ((p - j) + 0*(p + 1))*p] = o++;
11906 }
11907 for (int j = 0; j < p; j++) // y - components
11908 for (int i = 1; i < p; i++)
11909 {
11910 dof_map[1*dof3 + i + ((p - 1 - j) + 0*p)*(p + 1)] = -1 - (o++);
11911 }
11912 // (0,1,5,4) -- front
11913 for (int k = 1; k < p; k++) // x - components
11914 for (int i = 0; i < p; i++)
11915 {
11916 dof_map[0*dof3 + i + (0 + k*(p + 1))*p] = o++;
11917 }
11918 for (int k = 0; k < p; k++) // z - components
11919 for (int i = 1; i < p; i++ )
11920 {
11921 dof_map[2*dof3 + i + (0 + k*(p + 1))*(p + 1)] = o++;
11922 }
11923 // (1,2,6,5) -- right
11924 for (int k = 1; k < p; k++) // y - components
11925 for (int j = 0; j < p; j++)
11926 {
11927 dof_map[1*dof3 + p + (j + k*p)*(p + 1)] = o++;
11928 }
11929 for (int k = 0; k < p; k++) // z - components
11930 for (int j = 1; j < p; j++)
11931 {
11932 dof_map[2*dof3 + p + (j + k*(p + 1))*(p + 1)] = o++;
11933 }
11934 // (2,3,7,6) -- back
11935 for (int k = 1; k < p; k++) // x - components
11936 for (int i = 0; i < p; i++)
11937 {
11938 dof_map[0*dof3 + (p - 1 - i) + (p + k*(p + 1))*p] = -1 - (o++);
11939 }
11940 for (int k = 0; k < p; k++) // z - components
11941 for (int i = 1; i < p; i++)
11942 {
11943 dof_map[2*dof3 + (p - i) + (p + k*(p + 1))*(p + 1)] = o++;
11944 }
11945 // (3,0,4,7) -- left
11946 for (int k = 1; k < p; k++) // y - components
11947 for (int j = 0; j < p; j++)
11948 {
11949 dof_map[1*dof3 + 0 + ((p - 1 - j) + k*p)*(p + 1)] = -1 - (o++);
11950 }
11951 for (int k = 0; k < p; k++) // z - components
11952 for (int j = 1; j < p; j++)
11953 {
11954 dof_map[2*dof3 + 0 + ((p - j) + k*(p + 1))*(p + 1)] = o++;
11955 }
11956 // (4,5,6,7) -- top
11957 for (int j = 1; j < p; j++) // x - components
11958 for (int i = 0; i < p; i++)
11959 {
11960 dof_map[0*dof3 + i + (j + p*(p + 1))*p] = o++;
11961 }
11962 for (int j = 0; j < p; j++) // y - components
11963 for (int i = 1; i < p; i++)
11964 {
11965 dof_map[1*dof3 + i + (j + p*p)*(p + 1)] = o++;
11966 }
11967
11968 // interior
11969 // x-components
11970 for (int k = 1; k < p; k++)
11971 for (int j = 1; j < p; j++)
11972 for (int i = 0; i < p; i++)
11973 {
11974 dof_map[0*dof3 + i + (j + k*(p + 1))*p] = o++;
11975 }
11976 // y-components
11977 for (int k = 1; k < p; k++)
11978 for (int j = 0; j < p; j++)
11979 for (int i = 1; i < p; i++)
11980 {
11981 dof_map[1*dof3 + i + (j + k*p)*(p + 1)] = o++;
11982 }
11983 // z-components
11984 for (int k = 0; k < p; k++)
11985 for (int j = 1; j < p; j++)
11986 for (int i = 1; i < p; i++)
11987 {
11988 dof_map[2*dof3 + i + (j + k*(p + 1))*(p + 1)] = o++;
11989 }
11990
11991 // set dof2tk and Nodes
11992 o = 0;
11993 // x-components
11994 for (int k = 0; k <= p; k++)
11995 for (int j = 0; j <= p; j++)
11996 for (int i = 0; i < p; i++)
11997 {
11998 int idx;
11999 if ((idx = dof_map[o++]) < 0)
12000 {
12001 dof2tk[idx = -1 - idx] = 3;
12002 }
12003 else
12004 {
12005 dof2tk[idx] = 0;
12006 }
12007 Nodes.IntPoint(idx).Set3(op[i], cp[j], cp[k]);
12008 }
12009 // y-components
12010 for (int k = 0; k <= p; k++)
12011 for (int j = 0; j < p; j++)
12012 for (int i = 0; i <= p; i++)
12013 {
12014 int idx;
12015 if ((idx = dof_map[o++]) < 0)
12016 {
12017 dof2tk[idx = -1 - idx] = 4;
12018 }
12019 else
12020 {
12021 dof2tk[idx] = 1;
12022 }
12023 Nodes.IntPoint(idx).Set3(cp[i], op[j], cp[k]);
12024 }
12025 // z-components
12026 for (int k = 0; k < p; k++)
12027 for (int j = 0; j <= p; j++)
12028 for (int i = 0; i <= p; i++)
12029 {
12030 int idx;
12031 if ((idx = dof_map[o++]) < 0)
12032 {
12033 dof2tk[idx = -1 - idx] = 5;
12034 }
12035 else
12036 {
12037 dof2tk[idx] = 2;
12038 }
12039 Nodes.IntPoint(idx).Set3(cp[i], cp[j], op[k]);
12040 }
12041 }
12042
ProjectIntegrated(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const12043 void ND_HexahedronElement::ProjectIntegrated(VectorCoefficient &vc,
12044 ElementTransformation &Trans,
12045 Vector &dofs) const
12046 {
12047 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
12048 double vk[Geometry::MaxDim];
12049 Vector xk(vk, vc.GetVDim());
12050
12051 const IntegrationRule &ir = IntRules.Get(Geometry::SEGMENT, order);
12052 const int nqpt = ir.GetNPoints();
12053
12054 IntegrationPoint ip3d;
12055
12056 int o = 0;
12057 for (int c = 0; c < 3; ++c) // loop over x, y, z components
12058 {
12059 const int im = c == 0 ? order - 1 : order;
12060 const int jm = c == 1 ? order - 1 : order;
12061 const int km = c == 2 ? order - 1 : order;
12062
12063 for (int k = 0; k <= km; k++)
12064 for (int j = 0; j <= jm; j++)
12065 for (int i = 0; i <= im; i++)
12066 {
12067 int idx;
12068 if ((idx = dof_map[o++]) < 0)
12069 {
12070 idx = -1 - idx;
12071 }
12072
12073 const int id1 = c == 0 ? i : (c == 1 ? j : k);
12074 const double h = cp[id1+1] - cp[id1];
12075
12076 double val = 0.0;
12077
12078 for (int q = 0; q < nqpt; q++)
12079 {
12080 const IntegrationPoint &ip1d = ir.IntPoint(q);
12081
12082 if (c == 0)
12083 {
12084 ip3d.Set3(cp[i] + (h*ip1d.x), cp[j], cp[k]);
12085 }
12086 else if (c == 1)
12087 {
12088 ip3d.Set3(cp[i], cp[j] + (h*ip1d.x), cp[k]);
12089 }
12090 else
12091 {
12092 ip3d.Set3(cp[i], cp[j], cp[k] + (h*ip1d.x));
12093 }
12094
12095 Trans.SetIntPoint(&ip3d);
12096 vc.Eval(xk, Trans, ip3d);
12097
12098 // xk^t J tk
12099 const double ipval = Trans.Jacobian().InnerProduct(tk + dof2tk[idx]*dim, vk);
12100 val += ip1d.weight * ipval;
12101 }
12102
12103 dofs(idx) = val*h;
12104 }
12105 }
12106 }
12107
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const12108 void ND_HexahedronElement::CalcVShape(const IntegrationPoint &ip,
12109 DenseMatrix &shape) const
12110 {
12111 const int p = order;
12112
12113 #ifdef MFEM_THREAD_SAFE
12114 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
12115 Vector shape_cz(p + 1), shape_oz(p);
12116 #endif
12117
12118 if (obasis1d.IsIntegratedType())
12119 {
12120 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
12121 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
12122 cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
12123 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
12124 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
12125 obasis1d.EvalIntegrated(dshape_cz, shape_oz);
12126 }
12127 else
12128 {
12129 cbasis1d.Eval(ip.x, shape_cx);
12130 cbasis1d.Eval(ip.y, shape_cy);
12131 cbasis1d.Eval(ip.z, shape_cz);
12132 obasis1d.Eval(ip.x, shape_ox);
12133 obasis1d.Eval(ip.y, shape_oy);
12134 obasis1d.Eval(ip.z, shape_oz);
12135 }
12136
12137 int o = 0;
12138 // x-components
12139 for (int k = 0; k <= p; k++)
12140 for (int j = 0; j <= p; j++)
12141 for (int i = 0; i < p; i++)
12142 {
12143 int idx, s;
12144 if ((idx = dof_map[o++]) < 0)
12145 {
12146 idx = -1 - idx, s = -1;
12147 }
12148 else
12149 {
12150 s = +1;
12151 }
12152 shape(idx,0) = s*shape_ox(i)*shape_cy(j)*shape_cz(k);
12153 shape(idx,1) = 0.;
12154 shape(idx,2) = 0.;
12155 }
12156 // y-components
12157 for (int k = 0; k <= p; k++)
12158 for (int j = 0; j < p; j++)
12159 for (int i = 0; i <= p; i++)
12160 {
12161 int idx, s;
12162 if ((idx = dof_map[o++]) < 0)
12163 {
12164 idx = -1 - idx, s = -1;
12165 }
12166 else
12167 {
12168 s = +1;
12169 }
12170 shape(idx,0) = 0.;
12171 shape(idx,1) = s*shape_cx(i)*shape_oy(j)*shape_cz(k);
12172 shape(idx,2) = 0.;
12173 }
12174 // z-components
12175 for (int k = 0; k < p; k++)
12176 for (int j = 0; j <= p; j++)
12177 for (int i = 0; i <= p; i++)
12178 {
12179 int idx, s;
12180 if ((idx = dof_map[o++]) < 0)
12181 {
12182 idx = -1 - idx, s = -1;
12183 }
12184 else
12185 {
12186 s = +1;
12187 }
12188 shape(idx,0) = 0.;
12189 shape(idx,1) = 0.;
12190 shape(idx,2) = s*shape_cx(i)*shape_cy(j)*shape_oz(k);
12191 }
12192 }
12193
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const12194 void ND_HexahedronElement::CalcCurlShape(const IntegrationPoint &ip,
12195 DenseMatrix &curl_shape) const
12196 {
12197 const int p = order;
12198
12199 #ifdef MFEM_THREAD_SAFE
12200 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
12201 Vector shape_cz(p + 1), shape_oz(p);
12202 Vector dshape_cx(p + 1), dshape_cy(p + 1), dshape_cz(p + 1);
12203 #endif
12204
12205 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
12206 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
12207 cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
12208 if (obasis1d.IsIntegratedType())
12209 {
12210 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
12211 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
12212 obasis1d.EvalIntegrated(dshape_cz, shape_oz);
12213 }
12214 else
12215 {
12216 obasis1d.Eval(ip.x, shape_ox);
12217 obasis1d.Eval(ip.y, shape_oy);
12218 obasis1d.Eval(ip.z, shape_oz);
12219 }
12220
12221 int o = 0;
12222 // x-components
12223 for (int k = 0; k <= p; k++)
12224 for (int j = 0; j <= p; j++)
12225 for (int i = 0; i < p; i++)
12226 {
12227 int idx, s;
12228 if ((idx = dof_map[o++]) < 0)
12229 {
12230 idx = -1 - idx, s = -1;
12231 }
12232 else
12233 {
12234 s = +1;
12235 }
12236 curl_shape(idx,0) = 0.;
12237 curl_shape(idx,1) = s*shape_ox(i)* shape_cy(j)*dshape_cz(k);
12238 curl_shape(idx,2) = -s*shape_ox(i)*dshape_cy(j)* shape_cz(k);
12239 }
12240 // y-components
12241 for (int k = 0; k <= p; k++)
12242 for (int j = 0; j < p; j++)
12243 for (int i = 0; i <= p; i++)
12244 {
12245 int idx, s;
12246 if ((idx = dof_map[o++]) < 0)
12247 {
12248 idx = -1 - idx, s = -1;
12249 }
12250 else
12251 {
12252 s = +1;
12253 }
12254 curl_shape(idx,0) = -s* shape_cx(i)*shape_oy(j)*dshape_cz(k);
12255 curl_shape(idx,1) = 0.;
12256 curl_shape(idx,2) = s*dshape_cx(i)*shape_oy(j)* shape_cz(k);
12257 }
12258 // z-components
12259 for (int k = 0; k < p; k++)
12260 for (int j = 0; j <= p; j++)
12261 for (int i = 0; i <= p; i++)
12262 {
12263 int idx, s;
12264 if ((idx = dof_map[o++]) < 0)
12265 {
12266 idx = -1 - idx, s = -1;
12267 }
12268 else
12269 {
12270 s = +1;
12271 }
12272 curl_shape(idx,0) = s* shape_cx(i)*dshape_cy(j)*shape_oz(k);
12273 curl_shape(idx,1) = -s*dshape_cx(i)* shape_cy(j)*shape_oz(k);
12274 curl_shape(idx,2) = 0.;
12275 }
12276 }
12277
GetDofToQuad(const IntegrationRule & ir,DofToQuad::Mode mode) const12278 const DofToQuad &VectorTensorFiniteElement::GetDofToQuad(
12279 const IntegrationRule &ir,
12280 DofToQuad::Mode mode) const
12281 {
12282 MFEM_VERIFY(mode != DofToQuad::FULL, "invalid mode requested");
12283
12284 return GetTensorDofToQuad(ir, mode, true);
12285 }
12286
GetDofToQuadOpen(const IntegrationRule & ir,DofToQuad::Mode mode) const12287 const DofToQuad &VectorTensorFiniteElement::GetDofToQuadOpen(
12288 const IntegrationRule &ir,
12289 DofToQuad::Mode mode) const
12290 {
12291 MFEM_VERIFY(mode != DofToQuad::FULL, "invalid mode requested");
12292
12293 return GetTensorDofToQuad(ir, mode, false);
12294 }
12295
GetTensorDofToQuad(const IntegrationRule & ir,DofToQuad::Mode mode,const bool closed) const12296 const DofToQuad &VectorTensorFiniteElement::GetTensorDofToQuad(
12297 const IntegrationRule &ir,
12298 DofToQuad::Mode mode,
12299 const bool closed) const
12300 {
12301 MFEM_VERIFY(mode == DofToQuad::TENSOR, "invalid mode requested");
12302
12303 for (int i = 0;
12304 i < (closed ? dof2quad_array.Size() : dof2quad_array_open.Size());
12305 i++)
12306 {
12307 const DofToQuad &d2q = closed ? *dof2quad_array[i] : *dof2quad_array_open[i];
12308 if (d2q.IntRule == &ir && d2q.mode == mode) { return d2q; }
12309 }
12310
12311 DofToQuad *d2q = new DofToQuad;
12312 const int ndof = closed ? order + 1 : order;
12313 const int nqpt = (int)floor(pow(ir.GetNPoints(), 1.0/dim) + 0.5);
12314 d2q->FE = this;
12315 d2q->IntRule = &ir;
12316 d2q->mode = mode;
12317 d2q->ndof = ndof;
12318 d2q->nqpt = nqpt;
12319 d2q->B.SetSize(nqpt*ndof);
12320 d2q->Bt.SetSize(ndof*nqpt);
12321 d2q->G.SetSize(nqpt*ndof);
12322 d2q->Gt.SetSize(ndof*nqpt);
12323 Vector val(ndof), grad(ndof);
12324 for (int i = 0; i < nqpt; i++)
12325 {
12326 // The first 'nqpt' points in 'ir' have the same x-coordinates as those
12327 // of the 1D rule.
12328
12329 if (closed)
12330 {
12331 cbasis1d.Eval(ir.IntPoint(i).x, val, grad);
12332 }
12333 else
12334 {
12335 obasis1d.Eval(ir.IntPoint(i).x, val, grad);
12336 }
12337
12338 for (int j = 0; j < ndof; j++)
12339 {
12340 d2q->B[i+nqpt*j] = d2q->Bt[j+ndof*i] = val(j);
12341 d2q->G[i+nqpt*j] = d2q->Gt[j+ndof*i] = grad(j);
12342 }
12343 }
12344
12345 if (closed)
12346 {
12347 dof2quad_array.Append(d2q);
12348 }
12349 else
12350 {
12351 dof2quad_array_open.Append(d2q);
12352 }
12353
12354 return *d2q;
12355 }
12356
~VectorTensorFiniteElement()12357 VectorTensorFiniteElement::~VectorTensorFiniteElement()
12358 {
12359 for (int i = 0; i < dof2quad_array_open.Size(); i++)
12360 {
12361 delete dof2quad_array_open[i];
12362 }
12363 }
12364
12365 const double ND_QuadrilateralElement::tk[8] =
12366 { 1.,0., 0.,1., -1.,0., 0.,-1. };
12367
ND_QuadrilateralElement(const int p,const int cb_type,const int ob_type)12368 ND_QuadrilateralElement::ND_QuadrilateralElement(const int p,
12369 const int cb_type,
12370 const int ob_type)
12371 : VectorTensorFiniteElement(2, 2*p*(p + 1), p, cb_type, ob_type,
12372 H_CURL, DofMapType::L2_DOF_MAP),
12373 dof2tk(dof),
12374 cp(poly1d.ClosedPoints(p, cb_type))
12375 {
12376 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
12377
12378 dof_map.SetSize(dof);
12379
12380 const double *op = poly1d.OpenPoints(p - 1, ob_type);
12381 const int dof2 = dof/2;
12382
12383 #ifndef MFEM_THREAD_SAFE
12384 shape_cx.SetSize(p + 1);
12385 shape_ox.SetSize(p);
12386 shape_cy.SetSize(p + 1);
12387 shape_oy.SetSize(p);
12388 dshape_cx.SetSize(p + 1);
12389 dshape_cy.SetSize(p + 1);
12390 #endif
12391
12392 // edges
12393 int o = 0;
12394 for (int i = 0; i < p; i++) // (0,1)
12395 {
12396 dof_map[0*dof2 + i + 0*p] = o++;
12397 }
12398 for (int j = 0; j < p; j++) // (1,2)
12399 {
12400 dof_map[1*dof2 + p + j*(p + 1)] = o++;
12401 }
12402 for (int i = 0; i < p; i++) // (2,3)
12403 {
12404 dof_map[0*dof2 + (p - 1 - i) + p*p] = -1 - (o++);
12405 }
12406 for (int j = 0; j < p; j++) // (3,0)
12407 {
12408 dof_map[1*dof2 + 0 + (p - 1 - j)*(p + 1)] = -1 - (o++);
12409 }
12410
12411 // interior
12412 // x-components
12413 for (int j = 1; j < p; j++)
12414 for (int i = 0; i < p; i++)
12415 {
12416 dof_map[0*dof2 + i + j*p] = o++;
12417 }
12418 // y-components
12419 for (int j = 0; j < p; j++)
12420 for (int i = 1; i < p; i++)
12421 {
12422 dof_map[1*dof2 + i + j*(p + 1)] = o++;
12423 }
12424
12425 // set dof2tk and Nodes
12426 o = 0;
12427 // x-components
12428 for (int j = 0; j <= p; j++)
12429 for (int i = 0; i < p; i++)
12430 {
12431 int idx;
12432 if ((idx = dof_map[o++]) < 0)
12433 {
12434 dof2tk[idx = -1 - idx] = 2;
12435 }
12436 else
12437 {
12438 dof2tk[idx] = 0;
12439 }
12440 Nodes.IntPoint(idx).Set2(op[i], cp[j]);
12441 }
12442 // y-components
12443 for (int j = 0; j < p; j++)
12444 for (int i = 0; i <= p; i++)
12445 {
12446 int idx;
12447 if ((idx = dof_map[o++]) < 0)
12448 {
12449 dof2tk[idx = -1 - idx] = 3;
12450 }
12451 else
12452 {
12453 dof2tk[idx] = 1;
12454 }
12455 Nodes.IntPoint(idx).Set2(cp[i], op[j]);
12456 }
12457 }
12458
ProjectIntegrated(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const12459 void ND_QuadrilateralElement::ProjectIntegrated(VectorCoefficient &vc,
12460 ElementTransformation &Trans,
12461 Vector &dofs) const
12462 {
12463 MFEM_ASSERT(obasis1d.IsIntegratedType(), "Not integrated type");
12464 double vk[Geometry::MaxDim];
12465 Vector xk(vk, vc.GetVDim());
12466
12467 const IntegrationRule &ir = IntRules.Get(Geometry::SEGMENT, order);
12468 const int nqpt = ir.GetNPoints();
12469
12470 IntegrationPoint ip2d;
12471
12472 int o = 0;
12473 // x-components
12474 for (int j = 0; j <= order; j++)
12475 for (int i = 0; i < order; i++)
12476 {
12477 int idx;
12478 if ((idx = dof_map[o++]) < 0)
12479 {
12480 idx = -1 - idx;
12481 }
12482
12483 const double h = cp[i+1] - cp[i];
12484
12485 double val = 0.0;
12486
12487 for (int k = 0; k < nqpt; k++)
12488 {
12489 const IntegrationPoint &ip1d = ir.IntPoint(k);
12490
12491 ip2d.Set2(cp[i] + (h*ip1d.x), cp[j]);
12492
12493 Trans.SetIntPoint(&ip2d);
12494 vc.Eval(xk, Trans, ip2d);
12495
12496 // xk^t J tk
12497 const double ipval = Trans.Jacobian().InnerProduct(tk + dof2tk[idx]*dim, vk);
12498 val += ip1d.weight * ipval;
12499 }
12500
12501 dofs(idx) = val*h;
12502 }
12503 // y-components
12504 for (int j = 0; j < order; j++)
12505 for (int i = 0; i <= order; i++)
12506 {
12507 int idx;
12508 if ((idx = dof_map[o++]) < 0)
12509 {
12510 idx = -1 - idx;
12511 }
12512
12513 const double h = cp[j+1] - cp[j];
12514
12515 double val = 0.0;
12516
12517 for (int k = 0; k < nqpt; k++)
12518 {
12519 const IntegrationPoint &ip1d = ir.IntPoint(k);
12520
12521 ip2d.Set2(cp[i], cp[j] + (h*ip1d.x));
12522
12523 Trans.SetIntPoint(&ip2d);
12524 vc.Eval(xk, Trans, ip2d);
12525
12526 // xk^t J tk
12527 const double ipval = Trans.Jacobian().InnerProduct(tk + dof2tk[idx]*dim, vk);
12528 val += ip1d.weight * ipval;
12529 }
12530
12531 dofs(idx) = val*h;
12532 }
12533 }
12534
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const12535 void ND_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip,
12536 DenseMatrix &shape) const
12537 {
12538 const int p = order;
12539
12540 #ifdef MFEM_THREAD_SAFE
12541 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
12542 #endif
12543
12544 if (obasis1d.IsIntegratedType())
12545 {
12546 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
12547 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
12548 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
12549 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
12550 }
12551 else
12552 {
12553 cbasis1d.Eval(ip.x, shape_cx);
12554 cbasis1d.Eval(ip.y, shape_cy);
12555 obasis1d.Eval(ip.x, shape_ox);
12556 obasis1d.Eval(ip.y, shape_oy);
12557 }
12558
12559 int o = 0;
12560 // x-components
12561 for (int j = 0; j <= p; j++)
12562 for (int i = 0; i < p; i++)
12563 {
12564 int idx, s;
12565 if ((idx = dof_map[o++]) < 0)
12566 {
12567 idx = -1 - idx, s = -1;
12568 }
12569 else
12570 {
12571 s = +1;
12572 }
12573 shape(idx,0) = s*shape_ox(i)*shape_cy(j);
12574 shape(idx,1) = 0.;
12575 }
12576 // y-components
12577 for (int j = 0; j < p; j++)
12578 for (int i = 0; i <= p; i++)
12579 {
12580 int idx, s;
12581 if ((idx = dof_map[o++]) < 0)
12582 {
12583 idx = -1 - idx, s = -1;
12584 }
12585 else
12586 {
12587 s = +1;
12588 }
12589 shape(idx,0) = 0.;
12590 shape(idx,1) = s*shape_cx(i)*shape_oy(j);
12591 }
12592 }
12593
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const12594 void ND_QuadrilateralElement::CalcCurlShape(const IntegrationPoint &ip,
12595 DenseMatrix &curl_shape) const
12596 {
12597 const int p = order;
12598
12599 #ifdef MFEM_THREAD_SAFE
12600 Vector shape_cx(p + 1), shape_ox(p), shape_cy(p + 1), shape_oy(p);
12601 Vector dshape_cx(p + 1), dshape_cy(p + 1);
12602 #endif
12603
12604 cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
12605 cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
12606 if (obasis1d.IsIntegratedType())
12607 {
12608 obasis1d.EvalIntegrated(dshape_cx, shape_ox);
12609 obasis1d.EvalIntegrated(dshape_cy, shape_oy);
12610 }
12611 else
12612 {
12613 obasis1d.Eval(ip.x, shape_ox);
12614 obasis1d.Eval(ip.y, shape_oy);
12615 }
12616
12617 int o = 0;
12618 // x-components
12619 for (int j = 0; j <= p; j++)
12620 for (int i = 0; i < p; i++)
12621 {
12622 int idx, s;
12623 if ((idx = dof_map[o++]) < 0)
12624 {
12625 idx = -1 - idx, s = -1;
12626 }
12627 else
12628 {
12629 s = +1;
12630 }
12631 curl_shape(idx,0) = -s*shape_ox(i)*dshape_cy(j);
12632 }
12633 // y-components
12634 for (int j = 0; j < p; j++)
12635 for (int i = 0; i <= p; i++)
12636 {
12637 int idx, s;
12638 if ((idx = dof_map[o++]) < 0)
12639 {
12640 idx = -1 - idx, s = -1;
12641 }
12642 else
12643 {
12644 s = +1;
12645 }
12646 curl_shape(idx,0) = s*dshape_cx(i)*shape_oy(j);
12647 }
12648 }
12649
12650
12651 const double ND_TetrahedronElement::tk[18] =
12652 { 1.,0.,0., 0.,1.,0., 0.,0.,1., -1.,1.,0., -1.,0.,1., 0.,-1.,1. };
12653
12654 const double ND_TetrahedronElement::c = 1./4.;
12655
ND_TetrahedronElement(const int p)12656 ND_TetrahedronElement::ND_TetrahedronElement(const int p)
12657 : VectorFiniteElement(3, Geometry::TETRAHEDRON, p*(p + 2)*(p + 3)/2, p,
12658 H_CURL, FunctionSpace::Pk), dof2tk(dof)
12659 {
12660 const double *eop = poly1d.OpenPoints(p - 1);
12661 const double *fop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
12662 const double *iop = (p > 2) ? poly1d.OpenPoints(p - 3) : NULL;
12663
12664 const int pm1 = p - 1, pm2 = p - 2, pm3 = p - 3;
12665
12666 #ifndef MFEM_THREAD_SAFE
12667 shape_x.SetSize(p);
12668 shape_y.SetSize(p);
12669 shape_z.SetSize(p);
12670 shape_l.SetSize(p);
12671 dshape_x.SetSize(p);
12672 dshape_y.SetSize(p);
12673 dshape_z.SetSize(p);
12674 dshape_l.SetSize(p);
12675 u.SetSize(dof, dim);
12676 #else
12677 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
12678 #endif
12679
12680 int o = 0;
12681 // edges
12682 for (int i = 0; i < p; i++) // (0,1)
12683 {
12684 Nodes.IntPoint(o).Set3(eop[i], 0., 0.);
12685 dof2tk[o++] = 0;
12686 }
12687 for (int i = 0; i < p; i++) // (0,2)
12688 {
12689 Nodes.IntPoint(o).Set3(0., eop[i], 0.);
12690 dof2tk[o++] = 1;
12691 }
12692 for (int i = 0; i < p; i++) // (0,3)
12693 {
12694 Nodes.IntPoint(o).Set3(0., 0., eop[i]);
12695 dof2tk[o++] = 2;
12696 }
12697 for (int i = 0; i < p; i++) // (1,2)
12698 {
12699 Nodes.IntPoint(o).Set3(eop[pm1-i], eop[i], 0.);
12700 dof2tk[o++] = 3;
12701 }
12702 for (int i = 0; i < p; i++) // (1,3)
12703 {
12704 Nodes.IntPoint(o).Set3(eop[pm1-i], 0., eop[i]);
12705 dof2tk[o++] = 4;
12706 }
12707 for (int i = 0; i < p; i++) // (2,3)
12708 {
12709 Nodes.IntPoint(o).Set3(0., eop[pm1-i], eop[i]);
12710 dof2tk[o++] = 5;
12711 }
12712
12713 // faces
12714 for (int j = 0; j <= pm2; j++) // (1,2,3)
12715 for (int i = 0; i + j <= pm2; i++)
12716 {
12717 double w = fop[i] + fop[j] + fop[pm2-i-j];
12718 Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w);
12719 dof2tk[o++] = 3;
12720 Nodes.IntPoint(o).Set3(fop[pm2-i-j]/w, fop[i]/w, fop[j]/w);
12721 dof2tk[o++] = 4;
12722 }
12723 for (int j = 0; j <= pm2; j++) // (0,3,2)
12724 for (int i = 0; i + j <= pm2; i++)
12725 {
12726 double w = fop[i] + fop[j] + fop[pm2-i-j];
12727 Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w);
12728 dof2tk[o++] = 2;
12729 Nodes.IntPoint(o).Set3(0., fop[j]/w, fop[i]/w);
12730 dof2tk[o++] = 1;
12731 }
12732 for (int j = 0; j <= pm2; j++) // (0,1,3)
12733 for (int i = 0; i + j <= pm2; i++)
12734 {
12735 double w = fop[i] + fop[j] + fop[pm2-i-j];
12736 Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w);
12737 dof2tk[o++] = 0;
12738 Nodes.IntPoint(o).Set3(fop[i]/w, 0., fop[j]/w);
12739 dof2tk[o++] = 2;
12740 }
12741 for (int j = 0; j <= pm2; j++) // (0,2,1)
12742 for (int i = 0; i + j <= pm2; i++)
12743 {
12744 double w = fop[i] + fop[j] + fop[pm2-i-j];
12745 Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.);
12746 dof2tk[o++] = 1;
12747 Nodes.IntPoint(o).Set3(fop[j]/w, fop[i]/w, 0.);
12748 dof2tk[o++] = 0;
12749 }
12750
12751 // interior
12752 for (int k = 0; k <= pm3; k++)
12753 for (int j = 0; j + k <= pm3; j++)
12754 for (int i = 0; i + j + k <= pm3; i++)
12755 {
12756 double w = iop[i] + iop[j] + iop[k] + iop[pm3-i-j-k];
12757 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
12758 dof2tk[o++] = 0;
12759 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
12760 dof2tk[o++] = 1;
12761 Nodes.IntPoint(o).Set3(iop[i]/w, iop[j]/w, iop[k]/w);
12762 dof2tk[o++] = 2;
12763 }
12764
12765 DenseMatrix T(dof);
12766 for (int m = 0; m < dof; m++)
12767 {
12768 const IntegrationPoint &ip = Nodes.IntPoint(m);
12769 const double *tm = tk + 3*dof2tk[m];
12770 o = 0;
12771
12772 poly1d.CalcBasis(pm1, ip.x, shape_x);
12773 poly1d.CalcBasis(pm1, ip.y, shape_y);
12774 poly1d.CalcBasis(pm1, ip.z, shape_z);
12775 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l);
12776
12777 for (int k = 0; k <= pm1; k++)
12778 for (int j = 0; j + k <= pm1; j++)
12779 for (int i = 0; i + j + k <= pm1; i++)
12780 {
12781 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k);
12782 T(o++, m) = s * tm[0];
12783 T(o++, m) = s * tm[1];
12784 T(o++, m) = s * tm[2];
12785 }
12786 for (int k = 0; k <= pm1; k++)
12787 for (int j = 0; j + k <= pm1; j++)
12788 {
12789 double s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k);
12790 T(o++, m) = s*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]);
12791 T(o++, m) = s*((ip.z - c)*tm[0] - (ip.x - c)*tm[2]);
12792 }
12793 for (int k = 0; k <= pm1; k++)
12794 {
12795 T(o++, m) =
12796 shape_y(pm1-k)*shape_z(k)*((ip.z - c)*tm[1] - (ip.y - c)*tm[2]);
12797 }
12798 }
12799
12800 Ti.Factor(T);
12801 // mfem::out << "ND_TetrahedronElement(" << p << ") : "; Ti.TestInversion();
12802 }
12803
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const12804 void ND_TetrahedronElement::CalcVShape(const IntegrationPoint &ip,
12805 DenseMatrix &shape) const
12806 {
12807 const int pm1 = order - 1;
12808
12809 #ifdef MFEM_THREAD_SAFE
12810 const int p = order;
12811 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
12812 DenseMatrix u(dof, dim);
12813 #endif
12814
12815 poly1d.CalcBasis(pm1, ip.x, shape_x);
12816 poly1d.CalcBasis(pm1, ip.y, shape_y);
12817 poly1d.CalcBasis(pm1, ip.z, shape_z);
12818 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l);
12819
12820 int n = 0;
12821 for (int k = 0; k <= pm1; k++)
12822 for (int j = 0; j + k <= pm1; j++)
12823 for (int i = 0; i + j + k <= pm1; i++)
12824 {
12825 double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_l(pm1-i-j-k);
12826 u(n,0) = s; u(n,1) = 0.; u(n,2) = 0.; n++;
12827 u(n,0) = 0.; u(n,1) = s; u(n,2) = 0.; n++;
12828 u(n,0) = 0.; u(n,1) = 0.; u(n,2) = s; n++;
12829 }
12830 for (int k = 0; k <= pm1; k++)
12831 for (int j = 0; j + k <= pm1; j++)
12832 {
12833 double s = shape_x(pm1-j-k)*shape_y(j)*shape_z(k);
12834 u(n,0) = s*(ip.y - c); u(n,1) = -s*(ip.x - c); u(n,2) = 0.; n++;
12835 u(n,0) = s*(ip.z - c); u(n,1) = 0.; u(n,2) = -s*(ip.x - c); n++;
12836 }
12837 for (int k = 0; k <= pm1; k++)
12838 {
12839 double s = shape_y(pm1-k)*shape_z(k);
12840 u(n,0) = 0.; u(n,1) = s*(ip.z - c); u(n,2) = -s*(ip.y - c); n++;
12841 }
12842
12843 Ti.Mult(u, shape);
12844 }
12845
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const12846 void ND_TetrahedronElement::CalcCurlShape(const IntegrationPoint &ip,
12847 DenseMatrix &curl_shape) const
12848 {
12849 const int pm1 = order - 1;
12850
12851 #ifdef MFEM_THREAD_SAFE
12852 const int p = order;
12853 Vector shape_x(p), shape_y(p), shape_z(p), shape_l(p);
12854 Vector dshape_x(p), dshape_y(p), dshape_z(p), dshape_l(p);
12855 DenseMatrix u(dof, dim);
12856 #endif
12857
12858 poly1d.CalcBasis(pm1, ip.x, shape_x, dshape_x);
12859 poly1d.CalcBasis(pm1, ip.y, shape_y, dshape_y);
12860 poly1d.CalcBasis(pm1, ip.z, shape_z, dshape_z);
12861 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l);
12862
12863 int n = 0;
12864 for (int k = 0; k <= pm1; k++)
12865 for (int j = 0; j + k <= pm1; j++)
12866 for (int i = 0; i + j + k <= pm1; i++)
12867 {
12868 int l = pm1-i-j-k;
12869 const double dx = (dshape_x(i)*shape_l(l) -
12870 shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k);
12871 const double dy = (dshape_y(j)*shape_l(l) -
12872 shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k);
12873 const double dz = (dshape_z(k)*shape_l(l) -
12874 shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j);
12875
12876 u(n,0) = 0.; u(n,1) = dz; u(n,2) = -dy; n++;
12877 u(n,0) = -dz; u(n,1) = 0.; u(n,2) = dx; n++;
12878 u(n,0) = dy; u(n,1) = -dx; u(n,2) = 0.; n++;
12879 }
12880 for (int k = 0; k <= pm1; k++)
12881 for (int j = 0; j + k <= pm1; j++)
12882 {
12883 int i = pm1 - j - k;
12884 // s = shape_x(i)*shape_y(j)*shape_z(k);
12885 // curl of s*(ip.y - c, -(ip.x - c), 0):
12886 u(n,0) = shape_x(i)*(ip.x - c)*shape_y(j)*dshape_z(k);
12887 u(n,1) = shape_x(i)*shape_y(j)*(ip.y - c)*dshape_z(k);
12888 u(n,2) =
12889 -((dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k) +
12890 (dshape_y(j)*(ip.y - c) + shape_y(j))*shape_x(i)*shape_z(k));
12891 n++;
12892 // curl of s*(ip.z - c, 0, -(ip.x - c)):
12893 u(n,0) = -shape_x(i)*(ip.x - c)*dshape_y(j)*shape_z(k);
12894 u(n,1) = (shape_x(i)*shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)) +
12895 (dshape_x(i)*(ip.x - c) + shape_x(i))*shape_y(j)*shape_z(k));
12896 u(n,2) = -shape_x(i)*dshape_y(j)*shape_z(k)*(ip.z - c);
12897 n++;
12898 }
12899 for (int k = 0; k <= pm1; k++)
12900 {
12901 int j = pm1 - k;
12902 // curl of shape_y(j)*shape_z(k)*(0, ip.z - c, -(ip.y - c)):
12903 u(n,0) = -((dshape_y(j)*(ip.y - c) + shape_y(j))*shape_z(k) +
12904 shape_y(j)*(dshape_z(k)*(ip.z - c) + shape_z(k)));
12905 u(n,1) = 0.;
12906 u(n,2) = 0.; n++;
12907 }
12908
12909 Ti.Mult(u, curl_shape);
12910 }
12911
12912
12913 const double ND_TriangleElement::tk[8] =
12914 { 1.,0., -1.,1., 0.,-1., 0.,1. };
12915
12916 const double ND_TriangleElement::c = 1./3.;
12917
ND_TriangleElement(const int p)12918 ND_TriangleElement::ND_TriangleElement(const int p)
12919 : VectorFiniteElement(2, Geometry::TRIANGLE, p*(p + 2), p,
12920 H_CURL, FunctionSpace::Pk),
12921 dof2tk(dof)
12922 {
12923 const double *eop = poly1d.OpenPoints(p - 1);
12924 const double *iop = (p > 1) ? poly1d.OpenPoints(p - 2) : NULL;
12925
12926 const int pm1 = p - 1, pm2 = p - 2;
12927
12928 #ifndef MFEM_THREAD_SAFE
12929 shape_x.SetSize(p);
12930 shape_y.SetSize(p);
12931 shape_l.SetSize(p);
12932 dshape_x.SetSize(p);
12933 dshape_y.SetSize(p);
12934 dshape_l.SetSize(p);
12935 u.SetSize(dof, dim);
12936 curlu.SetSize(dof);
12937 #else
12938 Vector shape_x(p), shape_y(p), shape_l(p);
12939 #endif
12940
12941 int n = 0;
12942 // edges
12943 for (int i = 0; i < p; i++) // (0,1)
12944 {
12945 Nodes.IntPoint(n).Set2(eop[i], 0.);
12946 dof2tk[n++] = 0;
12947 }
12948 for (int i = 0; i < p; i++) // (1,2)
12949 {
12950 Nodes.IntPoint(n).Set2(eop[pm1-i], eop[i]);
12951 dof2tk[n++] = 1;
12952 }
12953 for (int i = 0; i < p; i++) // (2,0)
12954 {
12955 Nodes.IntPoint(n).Set2(0., eop[pm1-i]);
12956 dof2tk[n++] = 2;
12957 }
12958
12959 // interior
12960 for (int j = 0; j <= pm2; j++)
12961 for (int i = 0; i + j <= pm2; i++)
12962 {
12963 double w = iop[i] + iop[j] + iop[pm2-i-j];
12964 Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w);
12965 dof2tk[n++] = 0;
12966 Nodes.IntPoint(n).Set2(iop[i]/w, iop[j]/w);
12967 dof2tk[n++] = 3;
12968 }
12969
12970 DenseMatrix T(dof);
12971 for (int m = 0; m < dof; m++)
12972 {
12973 const IntegrationPoint &ip = Nodes.IntPoint(m);
12974 const double *tm = tk + 2*dof2tk[m];
12975 n = 0;
12976
12977 poly1d.CalcBasis(pm1, ip.x, shape_x);
12978 poly1d.CalcBasis(pm1, ip.y, shape_y);
12979 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l);
12980
12981 for (int j = 0; j <= pm1; j++)
12982 for (int i = 0; i + j <= pm1; i++)
12983 {
12984 double s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j);
12985 T(n++, m) = s * tm[0];
12986 T(n++, m) = s * tm[1];
12987 }
12988 for (int j = 0; j <= pm1; j++)
12989 {
12990 T(n++, m) =
12991 shape_x(pm1-j)*shape_y(j)*((ip.y - c)*tm[0] - (ip.x - c)*tm[1]);
12992 }
12993 }
12994
12995 Ti.Factor(T);
12996 // mfem::out << "ND_TriangleElement(" << p << ") : "; Ti.TestInversion();
12997 }
12998
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const12999 void ND_TriangleElement::CalcVShape(const IntegrationPoint &ip,
13000 DenseMatrix &shape) const
13001 {
13002 const int pm1 = order - 1;
13003
13004 #ifdef MFEM_THREAD_SAFE
13005 const int p = order;
13006 Vector shape_x(p), shape_y(p), shape_l(p);
13007 DenseMatrix u(dof, dim);
13008 #endif
13009
13010 poly1d.CalcBasis(pm1, ip.x, shape_x);
13011 poly1d.CalcBasis(pm1, ip.y, shape_y);
13012 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l);
13013
13014 int n = 0;
13015 for (int j = 0; j <= pm1; j++)
13016 for (int i = 0; i + j <= pm1; i++)
13017 {
13018 double s = shape_x(i)*shape_y(j)*shape_l(pm1-i-j);
13019 u(n,0) = s; u(n,1) = 0; n++;
13020 u(n,0) = 0; u(n,1) = s; n++;
13021 }
13022 for (int j = 0; j <= pm1; j++)
13023 {
13024 double s = shape_x(pm1-j)*shape_y(j);
13025 u(n,0) = s*(ip.y - c);
13026 u(n,1) = -s*(ip.x - c);
13027 n++;
13028 }
13029
13030 Ti.Mult(u, shape);
13031 }
13032
CalcCurlShape(const IntegrationPoint & ip,DenseMatrix & curl_shape) const13033 void ND_TriangleElement::CalcCurlShape(const IntegrationPoint &ip,
13034 DenseMatrix &curl_shape) const
13035 {
13036 const int pm1 = order - 1;
13037
13038 #ifdef MFEM_THREAD_SAFE
13039 const int p = order;
13040 Vector shape_x(p), shape_y(p), shape_l(p);
13041 Vector dshape_x(p), dshape_y(p), dshape_l(p);
13042 Vector curlu(dof);
13043 #endif
13044
13045 poly1d.CalcBasis(pm1, ip.x, shape_x, dshape_x);
13046 poly1d.CalcBasis(pm1, ip.y, shape_y, dshape_y);
13047 poly1d.CalcBasis(pm1, 1. - ip.x - ip.y, shape_l, dshape_l);
13048
13049 int n = 0;
13050 for (int j = 0; j <= pm1; j++)
13051 for (int i = 0; i + j <= pm1; i++)
13052 {
13053 int l = pm1-i-j;
13054 const double dx = (dshape_x(i)*shape_l(l) -
13055 shape_x(i)*dshape_l(l)) * shape_y(j);
13056 const double dy = (dshape_y(j)*shape_l(l) -
13057 shape_y(j)*dshape_l(l)) * shape_x(i);
13058
13059 curlu(n++) = -dy;
13060 curlu(n++) = dx;
13061 }
13062
13063 for (int j = 0; j <= pm1; j++)
13064 {
13065 int i = pm1 - j;
13066 // curl of shape_x(i)*shape_y(j) * (ip.y - c, -(ip.x - c), 0):
13067 curlu(n++) = -((dshape_x(i)*(ip.x - c) + shape_x(i)) * shape_y(j) +
13068 (dshape_y(j)*(ip.y - c) + shape_y(j)) * shape_x(i));
13069 }
13070
13071 Vector curl2d(curl_shape.Data(),dof);
13072 Ti.Mult(curlu, curl2d);
13073 }
13074
13075
13076 const double ND_SegmentElement::tk[1] = { 1. };
13077
ND_SegmentElement(const int p,const int ob_type)13078 ND_SegmentElement::ND_SegmentElement(const int p, const int ob_type)
13079 : VectorTensorFiniteElement(1, p, p - 1, ob_type, H_CURL,
13080 DofMapType::L2_DOF_MAP),
13081 dof2tk(dof)
13082 {
13083 if (obasis1d.IsIntegratedType()) { is_nodal = false; }
13084
13085 const double *op = poly1d.OpenPoints(p - 1, ob_type);
13086
13087 // set dof2tk and Nodes
13088 for (int i = 0; i < p; i++)
13089 {
13090 dof2tk[i] = 0;
13091 Nodes.IntPoint(i).x = op[i];
13092 }
13093 }
13094
CalcVShape(const IntegrationPoint & ip,DenseMatrix & shape) const13095 void ND_SegmentElement::CalcVShape(const IntegrationPoint &ip,
13096 DenseMatrix &shape) const
13097 {
13098 Vector vshape(shape.Data(), dof);
13099
13100 obasis1d.Eval(ip.x, vshape);
13101 }
13102
SetOrder() const13103 void NURBS1DFiniteElement::SetOrder() const
13104 {
13105 order = kv[0]->GetOrder();
13106 dof = order + 1;
13107
13108 weights.SetSize(dof);
13109 shape_x.SetSize(dof);
13110 }
13111
CalcShape(const IntegrationPoint & ip,Vector & shape) const13112 void NURBS1DFiniteElement::CalcShape(const IntegrationPoint &ip,
13113 Vector &shape) const
13114 {
13115 kv[0]->CalcShape(shape, ijk[0], ip.x);
13116
13117 double sum = 0.0;
13118 for (int i = 0; i <= order; i++)
13119 {
13120 sum += (shape(i) *= weights(i));
13121 }
13122
13123 shape /= sum;
13124 }
13125
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const13126 void NURBS1DFiniteElement::CalcDShape(const IntegrationPoint &ip,
13127 DenseMatrix &dshape) const
13128 {
13129 Vector grad(dshape.Data(), dof);
13130
13131 kv[0]->CalcShape (shape_x, ijk[0], ip.x);
13132 kv[0]->CalcDShape(grad, ijk[0], ip.x);
13133
13134 double sum = 0.0, dsum = 0.0;
13135 for (int i = 0; i <= order; i++)
13136 {
13137 sum += (shape_x(i) *= weights(i));
13138 dsum += ( grad(i) *= weights(i));
13139 }
13140
13141 sum = 1.0/sum;
13142 add(sum, grad, -dsum*sum*sum, shape_x, grad);
13143 }
13144
CalcHessian(const IntegrationPoint & ip,DenseMatrix & hessian) const13145 void NURBS1DFiniteElement::CalcHessian (const IntegrationPoint &ip,
13146 DenseMatrix &hessian) const
13147 {
13148 Vector grad(dof);
13149 Vector hess(hessian.Data(), dof);
13150
13151 kv[0]->CalcShape (shape_x, ijk[0], ip.x);
13152 kv[0]->CalcDShape(grad, ijk[0], ip.x);
13153 kv[0]->CalcD2Shape(hess, ijk[0], ip.x);
13154
13155 double sum = 0.0, dsum = 0.0, d2sum = 0.0;
13156 for (int i = 0; i <= order; i++)
13157 {
13158 sum += (shape_x(i) *= weights(i));
13159 dsum += ( grad(i) *= weights(i));
13160 d2sum += ( hess(i) *= weights(i));
13161 }
13162
13163 sum = 1.0/sum;
13164 add(sum, hess, -2*dsum*sum*sum, grad, hess);
13165 add(1.0, hess, (-d2sum + 2*dsum*dsum*sum)*sum*sum, shape_x, hess);
13166 }
13167
13168
SetOrder() const13169 void NURBS2DFiniteElement::SetOrder() const
13170 {
13171 orders[0] = kv[0]->GetOrder();
13172 orders[1] = kv[1]->GetOrder();
13173 shape_x.SetSize(orders[0]+1);
13174 shape_y.SetSize(orders[1]+1);
13175 dshape_x.SetSize(orders[0]+1);
13176 dshape_y.SetSize(orders[1]+1);
13177 d2shape_x.SetSize(orders[0]+1);
13178 d2shape_y.SetSize(orders[1]+1);
13179
13180 order = max(orders[0], orders[1]);
13181 dof = (orders[0] + 1)*(orders[1] + 1);
13182 u.SetSize(dof);
13183 du.SetSize(dof);
13184 weights.SetSize(dof);
13185 }
13186
CalcShape(const IntegrationPoint & ip,Vector & shape) const13187 void NURBS2DFiniteElement::CalcShape(const IntegrationPoint &ip,
13188 Vector &shape) const
13189 {
13190 kv[0]->CalcShape(shape_x, ijk[0], ip.x);
13191 kv[1]->CalcShape(shape_y, ijk[1], ip.y);
13192
13193 double sum = 0.0;
13194 for (int o = 0, j = 0; j <= orders[1]; j++)
13195 {
13196 const double sy = shape_y(j);
13197 for (int i = 0; i <= orders[0]; i++, o++)
13198 {
13199 sum += ( shape(o) = shape_x(i)*sy*weights(o) );
13200 }
13201 }
13202
13203 shape /= sum;
13204 }
13205
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const13206 void NURBS2DFiniteElement::CalcDShape(const IntegrationPoint &ip,
13207 DenseMatrix &dshape) const
13208 {
13209 double sum, dsum[2];
13210
13211 kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
13212 kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
13213
13214 kv[0]->CalcDShape(dshape_x, ijk[0], ip.x);
13215 kv[1]->CalcDShape(dshape_y, ijk[1], ip.y);
13216
13217 sum = dsum[0] = dsum[1] = 0.0;
13218 for (int o = 0, j = 0; j <= orders[1]; j++)
13219 {
13220 const double sy = shape_y(j), dsy = dshape_y(j);
13221 for (int i = 0; i <= orders[0]; i++, o++)
13222 {
13223 sum += ( u(o) = shape_x(i)*sy*weights(o) );
13224
13225 dsum[0] += ( dshape(o,0) = dshape_x(i)*sy *weights(o) );
13226 dsum[1] += ( dshape(o,1) = shape_x(i)*dsy*weights(o) );
13227 }
13228 }
13229
13230 sum = 1.0/sum;
13231 dsum[0] *= sum*sum;
13232 dsum[1] *= sum*sum;
13233
13234 for (int o = 0; o < dof; o++)
13235 {
13236 dshape(o,0) = dshape(o,0)*sum - u(o)*dsum[0];
13237 dshape(o,1) = dshape(o,1)*sum - u(o)*dsum[1];
13238 }
13239 }
13240
CalcHessian(const IntegrationPoint & ip,DenseMatrix & hessian) const13241 void NURBS2DFiniteElement::CalcHessian (const IntegrationPoint &ip,
13242 DenseMatrix &hessian) const
13243 {
13244 double sum, dsum[2], d2sum[3];
13245
13246 kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
13247 kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
13248
13249 kv[0]->CalcDShape(dshape_x, ijk[0], ip.x);
13250 kv[1]->CalcDShape(dshape_y, ijk[1], ip.y);
13251
13252 kv[0]->CalcD2Shape(d2shape_x, ijk[0], ip.x);
13253 kv[1]->CalcD2Shape(d2shape_y, ijk[1], ip.y);
13254
13255 sum = dsum[0] = dsum[1] = 0.0;
13256 d2sum[0] = d2sum[1] = d2sum[2] = 0.0;
13257 for (int o = 0, j = 0; j <= orders[1]; j++)
13258 {
13259 const double sy = shape_y(j), dsy = dshape_y(j), d2sy = d2shape_y(j);
13260 for (int i = 0; i <= orders[0]; i++, o++)
13261 {
13262 const double sx = shape_x(i), dsx = dshape_x(i), d2sx = d2shape_x(i);
13263 sum += ( u(o) = sx*sy*weights(o) );
13264
13265 dsum[0] += ( du(o,0) = dsx*sy*weights(o) );
13266 dsum[1] += ( du(o,1) = sx*dsy*weights(o) );
13267
13268 d2sum[0] += ( hessian(o,0) = d2sx*sy*weights(o) );
13269 d2sum[1] += ( hessian(o,1) = dsx*dsy*weights(o) );
13270 d2sum[2] += ( hessian(o,2) = sx*d2sy*weights(o) );
13271 }
13272 }
13273
13274 sum = 1.0/sum;
13275 dsum[0] *= sum;
13276 dsum[1] *= sum;
13277
13278 d2sum[0] *= sum;
13279 d2sum[1] *= sum;
13280 d2sum[2] *= sum;
13281
13282 for (int o = 0; o < dof; o++)
13283 {
13284 hessian(o,0) = hessian(o,0)*sum
13285 - 2*du(o,0)*sum*dsum[0]
13286 + u[o]*sum*(2*dsum[0]*dsum[0] - d2sum[0]);
13287
13288 hessian(o,1) = hessian(o,1)*sum
13289 - du(o,0)*sum*dsum[1]
13290 - du(o,1)*sum*dsum[0]
13291 + u[o]*sum*(2*dsum[0]*dsum[1] - d2sum[1]);
13292
13293 hessian(o,2) = hessian(o,2)*sum
13294 - 2*du(o,1)*sum*dsum[1]
13295 + u[o]*sum*(2*dsum[1]*dsum[1] - d2sum[2]);
13296 }
13297 }
13298
13299
SetOrder() const13300 void NURBS3DFiniteElement::SetOrder() const
13301 {
13302 orders[0] = kv[0]->GetOrder();
13303 orders[1] = kv[1]->GetOrder();
13304 orders[2] = kv[2]->GetOrder();
13305 shape_x.SetSize(orders[0]+1);
13306 shape_y.SetSize(orders[1]+1);
13307 shape_z.SetSize(orders[2]+1);
13308
13309 dshape_x.SetSize(orders[0]+1);
13310 dshape_y.SetSize(orders[1]+1);
13311 dshape_z.SetSize(orders[2]+1);
13312
13313 d2shape_x.SetSize(orders[0]+1);
13314 d2shape_y.SetSize(orders[1]+1);
13315 d2shape_z.SetSize(orders[2]+1);
13316
13317 order = max(max(orders[0], orders[1]), orders[2]);
13318 dof = (orders[0] + 1)*(orders[1] + 1)*(orders[2] + 1);
13319 u.SetSize(dof);
13320 du.SetSize(dof);
13321 weights.SetSize(dof);
13322 }
13323
CalcShape(const IntegrationPoint & ip,Vector & shape) const13324 void NURBS3DFiniteElement::CalcShape(const IntegrationPoint &ip,
13325 Vector &shape) const
13326 {
13327 kv[0]->CalcShape(shape_x, ijk[0], ip.x);
13328 kv[1]->CalcShape(shape_y, ijk[1], ip.y);
13329 kv[2]->CalcShape(shape_z, ijk[2], ip.z);
13330
13331 double sum = 0.0;
13332 for (int o = 0, k = 0; k <= orders[2]; k++)
13333 {
13334 const double sz = shape_z(k);
13335 for (int j = 0; j <= orders[1]; j++)
13336 {
13337 const double sy_sz = shape_y(j)*sz;
13338 for (int i = 0; i <= orders[0]; i++, o++)
13339 {
13340 sum += ( shape(o) = shape_x(i)*sy_sz*weights(o) );
13341 }
13342 }
13343 }
13344
13345 shape /= sum;
13346 }
13347
CalcDShape(const IntegrationPoint & ip,DenseMatrix & dshape) const13348 void NURBS3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
13349 DenseMatrix &dshape) const
13350 {
13351 double sum, dsum[3];
13352
13353 kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
13354 kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
13355 kv[2]->CalcShape ( shape_z, ijk[2], ip.z);
13356
13357 kv[0]->CalcDShape(dshape_x, ijk[0], ip.x);
13358 kv[1]->CalcDShape(dshape_y, ijk[1], ip.y);
13359 kv[2]->CalcDShape(dshape_z, ijk[2], ip.z);
13360
13361 sum = dsum[0] = dsum[1] = dsum[2] = 0.0;
13362 for (int o = 0, k = 0; k <= orders[2]; k++)
13363 {
13364 const double sz = shape_z(k), dsz = dshape_z(k);
13365 for (int j = 0; j <= orders[1]; j++)
13366 {
13367 const double sy_sz = shape_y(j)* sz;
13368 const double dsy_sz = dshape_y(j)* sz;
13369 const double sy_dsz = shape_y(j)*dsz;
13370 for (int i = 0; i <= orders[0]; i++, o++)
13371 {
13372 sum += ( u(o) = shape_x(i)*sy_sz*weights(o) );
13373
13374 dsum[0] += ( dshape(o,0) = dshape_x(i)* sy_sz *weights(o) );
13375 dsum[1] += ( dshape(o,1) = shape_x(i)*dsy_sz *weights(o) );
13376 dsum[2] += ( dshape(o,2) = shape_x(i)* sy_dsz*weights(o) );
13377 }
13378 }
13379 }
13380
13381 sum = 1.0/sum;
13382 dsum[0] *= sum*sum;
13383 dsum[1] *= sum*sum;
13384 dsum[2] *= sum*sum;
13385
13386 for (int o = 0; o < dof; o++)
13387 {
13388 dshape(o,0) = dshape(o,0)*sum - u(o)*dsum[0];
13389 dshape(o,1) = dshape(o,1)*sum - u(o)*dsum[1];
13390 dshape(o,2) = dshape(o,2)*sum - u(o)*dsum[2];
13391 }
13392 }
13393
CalcHessian(const IntegrationPoint & ip,DenseMatrix & hessian) const13394 void NURBS3DFiniteElement::CalcHessian (const IntegrationPoint &ip,
13395 DenseMatrix &hessian) const
13396 {
13397 double sum, dsum[3], d2sum[6];
13398
13399 kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
13400 kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
13401 kv[2]->CalcShape ( shape_z, ijk[2], ip.z);
13402
13403 kv[0]->CalcDShape(dshape_x, ijk[0], ip.x);
13404 kv[1]->CalcDShape(dshape_y, ijk[1], ip.y);
13405 kv[2]->CalcDShape(dshape_z, ijk[2], ip.z);
13406
13407 kv[0]->CalcD2Shape(d2shape_x, ijk[0], ip.x);
13408 kv[1]->CalcD2Shape(d2shape_y, ijk[1], ip.y);
13409 kv[2]->CalcD2Shape(d2shape_z, ijk[2], ip.z);
13410
13411 sum = dsum[0] = dsum[1] = dsum[2] = 0.0;
13412 d2sum[0] = d2sum[1] = d2sum[2] = d2sum[3] = d2sum[4] = d2sum[5] = 0.0;
13413
13414 for (int o = 0, k = 0; k <= orders[2]; k++)
13415 {
13416 const double sz = shape_z(k), dsz = dshape_z(k), d2sz = d2shape_z(k);
13417 for (int j = 0; j <= orders[1]; j++)
13418 {
13419 const double sy = shape_y(j), dsy = dshape_y(j), d2sy = d2shape_y(j);
13420 for (int i = 0; i <= orders[0]; i++, o++)
13421 {
13422 const double sx = shape_x(i), dsx = dshape_x(i), d2sx = d2shape_x(i);
13423 sum += ( u(o) = sx*sy*sz*weights(o) );
13424
13425 dsum[0] += ( du(o,0) = dsx*sy*sz*weights(o) );
13426 dsum[1] += ( du(o,1) = sx*dsy*sz*weights(o) );
13427 dsum[2] += ( du(o,2) = sx*sy*dsz*weights(o) );
13428
13429 d2sum[0] += ( hessian(o,0) = d2sx*sy*sz*weights(o) );
13430 d2sum[1] += ( hessian(o,1) = dsx*dsy*sz*weights(o) );
13431 d2sum[2] += ( hessian(o,2) = dsx*sy*dsz*weights(o) );
13432
13433 d2sum[3] += ( hessian(o,3) = sx*dsy*dsz*weights(o) );
13434
13435 d2sum[4] += ( hessian(o,4) = sx*sy*d2sz*weights(o) );
13436 d2sum[5] += ( hessian(o,5) = sx*d2sy*sz*weights(o) );
13437 }
13438 }
13439 }
13440
13441 sum = 1.0/sum;
13442 dsum[0] *= sum;
13443 dsum[1] *= sum;
13444 dsum[2] *= sum;
13445
13446 d2sum[0] *= sum;
13447 d2sum[1] *= sum;
13448 d2sum[2] *= sum;
13449
13450 d2sum[3] *= sum;
13451 d2sum[4] *= sum;
13452 d2sum[5] *= sum;
13453
13454 for (int o = 0; o < dof; o++)
13455 {
13456 hessian(o,0) = hessian(o,0)*sum
13457 - 2*du(o,0)*sum*dsum[0]
13458 + u[o]*sum*(2*dsum[0]*dsum[0] - d2sum[0]);
13459
13460 hessian(o,1) = hessian(o,1)*sum
13461 - du(o,0)*sum*dsum[1]
13462 - du(o,1)*sum*dsum[0]
13463 + u[o]*sum*(2*dsum[0]*dsum[1] - d2sum[1]);
13464
13465 hessian(o,2) = hessian(o,2)*sum
13466 - du(o,0)*sum*dsum[2]
13467 - du(o,2)*sum*dsum[0]
13468 + u[o]*sum*(2*dsum[0]*dsum[2] - d2sum[2]);
13469
13470 hessian(o,3) = hessian(o,3)*sum
13471 - du(o,1)*sum*dsum[2]
13472 - du(o,2)*sum*dsum[1]
13473 + u[o]*sum*(2*dsum[1]*dsum[2] - d2sum[3]);
13474
13475 hessian(o,4) = hessian(o,4)*sum
13476 - 2*du(o,2)*sum*dsum[2]
13477 + u[o]*sum*(2*dsum[2]*dsum[2] - d2sum[4]);
13478
13479 hessian(o,5) = hessian(o,5)*sum
13480 - 2*du(o,1)*sum*dsum[1]
13481 + u[o]*sum*(2*dsum[1]*dsum[1] - d2sum[5]);
13482
13483 }
13484 }
13485
13486 // Global object definitions
13487
13488 // Object declared in mesh/triangle.hpp.
13489 // Defined here to ensure it is constructed before 'Geometries'.
13490 Linear2DFiniteElement TriangleFE;
13491
13492 // Object declared in mesh/tetrahedron.hpp.
13493 // Defined here to ensure it is constructed before 'Geometries'.
13494 Linear3DFiniteElement TetrahedronFE;
13495
13496 // Object declared in mesh/wedge.hpp.
13497 // Defined here to ensure it is constructed after 'poly1d' and before
13498 // 'Geometries'.
13499 // TODO: define as thread_local to prevent race conditions in GLVis, because
13500 // there is no "LinearWedgeFiniteElement" and WedgeFE is in turn used from two
13501 // different threads for different things in GLVis. We also don't want to turn
13502 // MFEM_THREAD_SAFE on globally. (See PR #731)
13503 H1_WedgeElement WedgeFE(1);
13504
13505 // Object declared in geom.hpp.
13506 // Construct 'Geometries' after 'TriangleFE', 'TetrahedronFE', and 'WedgeFE'.
13507 Geometry Geometries;
13508
13509 }
13510