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