Basis_HGRAD_LINE_Hermite_FEM<Scalar,ArrayScalar>::Basis_HGRAD_LINE_Hermite_FEM() : latticePts_(2,1) { this->basisCardinality_ = 4; // Four basis functions this->basisDegree_ = 3; // Cubic polynomials this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ); this->basisType_ = BASIS_FEM_DEFAULT; this->basisCoordinates_ = COORDINATES_CARTESIAN; this->basisTagsAreSet_ = false; latticePts_(0,0) = -1.0; latticePts_(1,0) = 1.0; setupVandermonde(); } // no-arg constructor
void Basis_HGRAD_LINE_Cn_FEM<Scalar,ArrayScalar>::getDofCoords( ArrayScalar & dofCoords ) const { for (int i=0;i<latticePts_.dimension(0);i++) { for (int j=0;j<latticePts_.dimension(1);j++) { dofCoords(i,j) = latticePts_(i,j); } } return; }
Basis_HGRAD_LINE_Hermite_FEM<Scalar,ArrayScalar>::Basis_HGRAD_LINE_Hermite_FEM( const ArrayScalar &pts) : latticePts_( pts.dimension(0), 1 ) { int n = pts.dimension(0); this->basisCardinality_ = 2*n; this->basisDegree_ = 2*n-1; this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ); this->basisType_ = BASIS_FEM_DEFAULT; this->basisCoordinates_ = COORDINATES_CARTESIAN; this->basisTagsAreSet_ = false; for( int i=0; i<n-1; ++i ) { TEUCHOS_TEST_FOR_EXCEPTION( pts(i,0) >= pts(i+1,0), std::runtime_error , "Intrepid::Basis_HGRAD_LINE_Hermite_FEM Illegal points given to constructor" ); } // copy points int latticePts, correcting endpoints if needed if (std::abs(pts(0,0)+1.0) < INTREPID_TOL) { latticePts_(0,0) = -1.0; } else { latticePts_(0,0) = pts(0,0); } for (int i=1;i<n-1;i++) { latticePts_(i,0) = pts(i,0); } if (std::abs(pts(n-1,0)-1.0) < INTREPID_TOL) { latticePts_(n-1,0) = 1.0; } else { latticePts_(n-1,0) = pts(n-1,0); } setupVandermonde(); } // Constructor with points given
void Basis_HGRAD_LINE_Hermite_FEM<Scalar,ArrayScalar>::setupVandermonde( bool factor ) { initializeTags(); int nBf = this->getCardinality(); int n = nBf/2; V_.shape(nBf,nBf); // Make containers to store the Legendre polynomials and their derivatives // at a given point ArrayScalar P ( nBf ); ArrayScalar Px( nBf ); // Loop over grid points for( int i=0; i<n; ++i ) { recurrence(P,Px,latticePts_(i,0)); // Loop over basis functions for(int j=0; j<nBf; ++j ) { V_(j, i ) = P (j); V_(j, i+n) = Px(j); } } solver_.setMatrix(Teuchos::rcpFromRef(V_)); if(factor) { solver_.factorWithEquilibration(true); solver_.factor(); isFactored_ = true; } else { isFactored_ = false; } }
Basis_HGRAD_LINE_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_LINE_Cn_FEM( const int n , const ArrayScalar &pts ): latticePts_( n+1 , 1 ), Phis_( n ), V_(n+1,n+1), Vinv_(n+1,n+1) { const int N = n+1; this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; // check validity of points for (int i=0;i<n;i++) { TEUCHOS_TEST_FOR_EXCEPTION( pts(i,0) >= pts(i+1,0) , std::runtime_error , "Intrepid2::Basis_HGRAD_LINE_Cn_FEM Illegal points given to constructor" ); } // copy points int latticePts, correcting endpoints if needed if (std::abs(pts(0,0)+1.0) < INTREPID_TOL) { latticePts_(0,0) = -1.0; } else { latticePts_(0,0) = pts(0,0); } for (int i=1;i<n;i++) { latticePts_(i,0) = pts(i,0); } if (std::abs(pts(n,0)-1.0) < INTREPID_TOL) { latticePts_(n,0) = 1.0; } else { latticePts_(n,0) = pts(n,0); } // form Vandermonde matrix. Actually, this is the transpose of the VDM, // so we transpose on copy below. Phis_.getValues( V_ , latticePts_ , OPERATOR_VALUE ); // now I need to copy V into a Teuchos array to do the inversion Teuchos::SerialDenseMatrix<int,Scalar> Vsdm(N,N); for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vsdm(i,j) = V_(i,j); } } // invert the matrix Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); // now I need to copy the inverse into Vinv for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vinv_(i,j) = Vsdm(j,i); } } }
void Basis_HGRAD_LINE_Cn_FEM<Scalar, ArrayScalar>::initializeTags() { // Basis-dependent initializations int tagSize = 4; // size of DoF tag, i.e., number of fields in the tag int posScDim = 0; // position in the tag, counting from 0, of the subcell dim int posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal int posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration int *tags = new int[ tagSize * this->getCardinality() ]; int internal_dof; int edge_dof; const int n = this->getDegree(); // now we check the points for association if (latticePts_(0,0) == -1.0) { tags[0] = 0; tags[1] = 0; tags[2] = 0; tags[3] = 1; edge_dof = 1; internal_dof = n-1; } else { tags[0] = 1; tags[1] = 0; tags[2] = 0; tags[3] = n+1; edge_dof = 0; internal_dof = n+1; } for (int i=1;i<n;i++) { tags[4*i] = 1; tags[4*i+1] = 0; tags[4*i+2] = -edge_dof + i; tags[4*i+3] = internal_dof; } if (latticePts_(n,0) == 1.0) { tags[4*n] = 0; tags[4*n+1] = 1; tags[4*n+2] = 0; tags[4*n+3] = 1; } else { tags[4*n] = 1; tags[4*n+1] = 0; tags[4*n+2] = n; tags[4*n+3] = n; } Intrepid2::setOrdinalTagData(this -> tagToOrdinal_, this -> ordinalToTag_, tags, this -> basisCardinality_, tagSize, posScDim, posScOrd, posDfOrd); delete []tags; }
void Basis_HGRAD_LINE_Hermite_FEM<Scalar, ArrayScalar>::initializeTags() { // Basis-dependent intializations int tagSize = 4; // size of DoF tag, i.e., number of fields in the tag int posScDim = 0; // position in the tag, counting from 0, of the subcell dim int posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal int posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration int C = this->getCardinality(); tags_.reserve( tagSize * C ); int n = C/2; int hasLeftVertex = static_cast<int>( latticePts_(0 , 0) == -1.0 ); int hasRightVertex = static_cast<int>( latticePts_(n-1, 0) == 1.0 ); int internal_dof = C - 2*(hasLeftVertex+hasRightVertex); if( hasLeftVertex ) { // Value interpolant tags_[0] = 0; // this is a vertex (interval end point) tags_[1] = 0; // this is the first subcell tags_[2] = 0; // this is the first DoF for this vertex tags_[3] = 2; // this vertex has 2 DoF // Derivative interpolant tags_[4] = 0; // this is a vertex (interval end point) tags_[5] = 0; // this is the first subcell tags_[6] = 1; // this is the second DoF for this vertex tags_[7] = 2; // this vertex has 2 DoF } else { // no left vertex // Value interpolant tags_[0] = 1; // this point is on a line tags_[1] = 0; // no subcells tags_[2] = 0; // this is the first DoF for this line tags_[3] = C-2*hasRightVertex; // this cell has 2n DoF // Derivative interpolant tags_[4] = 1; // this point is on a line tags_[5] = 0; // no subcells tags_[6] = 1; // this is the second DoF for this line tags_[7] = C-2*hasRightVertex; // this cell has 2n DoF } if( hasRightVertex ) { int i0 = C-2; int i1 = C-1; // Value interpolant tags_[4*i0 ] = 0; tags_[4*i0+1] = hasLeftVertex; tags_[4*i0+2] = 0; tags_[4*i0+3] = 2; // Derivative interpolant tags_[4*i1 ] = 0; tags_[4*i1+1] = hasLeftVertex; tags_[4*i1+2] = 1; tags_[4*i1+3] = 2; } else { // no right vertex int i0 = C-2; int i1 = C-1; // Value interpolant tags_[4*i0 ] = 1; tags_[4*i0+1] = 0; tags_[4*i0+2] = internal_dof-2; tags_[4*i0+3] = internal_dof; // Derivative interpolant tags_[4*i1 ] = 1; tags_[4*i1+1] = 0; tags_[4*i1+2] = internal_dof-1; tags_[4*i1+3] = internal_dof; } for( int i=1; i<n-1; ++i ) { int i0 = 2*i; int i1 = 2*i+1; // Value interpolant tags_[4*i0 ] = 1; // Points on a line (1 dimensional) tags_[4*i0+1] = 0; tags_[4*i0+2] = i0 - 2*hasLeftVertex; tags_[4*i0+3] = internal_dof; // Derivative interpolant tags_[4*i1 ] = 1; tags_[4*i1+1] = 0; tags_[4*i1+2] = i1 - 2*hasLeftVertex; tags_[4*i1+3] = internal_dof; } // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays: Intrepid::setOrdinalTagData(this -> tagToOrdinal_, this -> ordinalToTag_, tags_.data(), this -> basisCardinality_, tagSize, posScDim, posScOrd, posDfOrd); }