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),
 
   59     latticePts( (n+1)*(n+2)/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 
Basis_HGRAD_TRI_Cn_FEM(const int n, const EPointType pointType)
Constructor. 
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
Implementation of the default H(grad)-compatible Lagrange basis of arbitrary degree on Triangle cell...