1#ifndef INTREPID_HGRAD_TRI_CN_FEMDEF_HPP
2#define INTREPID_HGRAD_TRI_CN_FEMDEF_HPP
53 template<
class Scalar,
class ArrayScalar>
55 const EPointType pointType ):
57 V((n+1)*(n+2)/2,(n+1)*(n+2)/2),
58 Vinv((n+1)*(n+2)/2,(n+1)*(n+2)/2),
61 TEUCHOS_TEST_FOR_EXCEPTION( n <= 0, std::invalid_argument, "polynomial order must be >= 1
");
63 const int N = (n+1)*(n+2)/2;
64 this -> basisCardinality_ = N;
65 this -> basisDegree_ = n;
66 this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() );
67 this -> basisType_ = BASIS_FEM_FIAT;
68 this -> basisCoordinates_ = COORDINATES_CARTESIAN;
69 this -> basisTagsAreSet_ = false;
73 shards::CellTopology myTri_3( shards::getCellTopologyData< shards::Triangle<3> >() );
75 PointTools::getLattice<Scalar,FieldContainer<Scalar> >( latticePts ,
82 // form Vandermonde matrix. Actually, this is the transpose of the VDM,
83 // so we transpose on copy below.
85 Phis.getValues( V , latticePts , OPERATOR_VALUE );
87 // now I need to copy V into a Teuchos array to do the inversion
88 Teuchos::SerialDenseMatrix<int,Scalar> Vsdm(N,N);
89 for (int i=0;i<N;i++) {
90 for (int j=0;j<N;j++) {
96 Teuchos::SerialDenseSolver<int,Scalar> solver;
97 solver.setMatrix( rcp( &Vsdm , false ) );
100 // now I need to copy the inverse into Vinv
101 for (int i=0;i<N;i++) {
102 for (int j=0;j<N;j++) {
103 Vinv(i,j) = Vsdm(j,i);
110 template<class Scalar, class ArrayScalar>
111 void Basis_HGRAD_TRI_Cn_FEM<Scalar, ArrayScalar>::initializeTags() {
113 // Basis-dependent initializations
114 int tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
115 int posScDim = 0; // position in the tag, counting from 0, of the subcell dim
116 int posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
117 int posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
119 // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
121 int *tags = new int[ tagSize * this->getCardinality() ];
123 const int degree = this->getDegree();
125 // BEGIN DOF ALONG BOTTOM EDGE
127 // the first dof is on vertex 0
128 tag_cur[0] = 0; tag_cur[1] = 0; tag_cur[2] = 0; tag_cur[3] = 1;
131 // next degree-1 dof are on edge 0
132 for (int i=1;i<degree;i++) {
133 tag_cur[0] = 1; tag_cur[1] = 0; tag_cur[2] = i-1; tag_cur[3] = degree-1;
137 // last dof is on vertex 1
138 tag_cur[0] = 0; tag_cur[1] = 1; tag_cur[2] = 0; tag_cur[3] = 1;
141 // END DOF ALONG BOTTOM EDGE
143 int num_internal_dof = PointTools::getLatticeSize( this->getBaseCellTopology() ,
147 int internal_dof_cur = 0;
149 // BEGIN DOF ALONG INTERNAL HORIZONTAL LINES
150 for (int i=1;i<degree;i++) {
151 // first dof along line is on edge #2
152 tag_cur[0] = 1; tag_cur[1] = 2; tag_cur[2] = i-1; tag_cur[3] = degree-1;
155 // next dof are internal
156 for (int j=1;j<degree-i;j++) {
157 tag_cur[0] = 2; tag_cur[1] = 0; tag_cur[2] = internal_dof_cur; tag_cur[3] = num_internal_dof;
162 // last dof along line is on edge 1
163 tag_cur[0] = 1; tag_cur[1] = 1; tag_cur[2] = i-1; tag_cur[3] = degree-1;
167 // END DOF ALONG INTERNAL HORIZONTAL LINES
169 // LAST DOF IS ON VERTEX 2
170 tag_cur[0] = 0; tag_cur[1] = 2; tag_cur[2] = 0; tag_cur[3] = 1;
174 Intrepid::setOrdinalTagData(this -> tagToOrdinal_,
175 this -> ordinalToTag_,
177 this -> basisCardinality_,
189 template<class Scalar, class ArrayScalar>
190 void Basis_HGRAD_TRI_Cn_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar & outputValues,
191 const ArrayScalar & inputPoints,
192 const EOperator operatorType) const {
195#ifdef HAVE_INTREPID_DEBUG
196 Intrepid::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
199 this -> getBaseCellTopology(),
200 this -> getCardinality() );
202 const int numPts = inputPoints.dimension(0);
203 const int numBf = this->getCardinality();
206 switch (operatorType) {
209 FieldContainer<Scalar> phisCur( numBf , numPts );
210 Phis.getValues( phisCur , inputPoints , operatorType );
211 for (int i=0;i<outputValues.dimension(0);i++) {
212 for (int j=0;j<outputValues.dimension(1);j++) {
213 outputValues(i,j) = 0.0;
214 for (int k=0;k<this->getCardinality();k++) {
215 outputValues(i,j) += this->Vinv(k,i) * phisCur(k,j);
234 (operatorType == OPERATOR_GRAD)? getDkCardinality(OPERATOR_D1,2): getDkCardinality(operatorType,2);
236 FieldContainer<Scalar> phisCur( numBf , numPts , dkcard );
237 Phis.getValues( phisCur , inputPoints , operatorType );
239 for (int i=0;i<outputValues.dimension(0);i++) {
240 for (int j=0;j<outputValues.dimension(1);j++) {
241 for (int k=0;k<outputValues.dimension(2);k++) {
242 outputValues(i,j,k) = 0.0;
243 for (int l=0;l<this->getCardinality();l++) {
244 outputValues(i,j,k) += this->Vinv(l,i) * phisCur(l,j,k);
251 case OPERATOR_CURL: // only works in 2d. first component is -d/dy, second is d/dx
253 FieldContainer<Scalar> phisCur( numBf , numPts , getDkCardinality( OPERATOR_D1 , 2 ) );
254 Phis.getValues( phisCur , inputPoints , OPERATOR_D1 );
256 for (int i=0;i<outputValues.dimension(0);i++) {
257 for (int j=0;j<outputValues.dimension(1);j++) {
258 outputValues(i,j,0) = 0.0;
259 outputValues(i,j,1) = 0.0;
260 for (int k=0;k<this->getCardinality();k++) {
261 outputValues(i,j,0) += this->Vinv(k,i) * phisCur(k,j,1);
263 for (int k=0;k<this->getCardinality();k++) {
264 outputValues(i,j,1) -= this->Vinv(k,i) * phisCur(k,j,0);
271 TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
276 catch (std::invalid_argument &exception){
277 TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
285 template<class Scalar, class ArrayScalar>
286 void Basis_HGRAD_TRI_Cn_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar& outputValues,
287 const ArrayScalar & inputPoints,
288 const ArrayScalar & cellVertices,
289 const EOperator operatorType) const {
290 TEUCHOS_TEST_FOR_EXCEPTION( (true), std::logic_error,
295}// namespace Intrepid
298#if defined(Intrepid_SHOW_DEPRECATED_WARNINGS)
300#warning "The Intrepid package is deprecated
"
Basis_HGRAD_TRI_Cn_FEM(const int n, const EPointType pointType)
Constructor.
Basis_HGRAD_TRI_Cn_FEM_ORTH< Scalar, FieldContainer< Scalar > > Phis
The orthogonal basis on triangles, out of which the nodal basis is constructed.
FieldContainer< Scalar > latticePts
stores the points at which degrees of freedom are located.
FieldContainer< Scalar > V
The Vandermonde matrix with V_{ij} = phi_i(x_j), where x_j is the j_th point in the lattice.
FieldContainer< Scalar > Vinv
The inverse of V. The columns of Vinv express the Lagrange basis in terms of the orthogonal basis.
An abstract base class that defines interface for concrete basis implementations for Finite Element (...