00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00037 namespace Intrepid {
00038
00039 template<class Scalar, class ArrayScalar>
00040 Basis_HDIV_TET_In_FEM<Scalar,ArrayScalar>::Basis_HDIV_TET_In_FEM( const int n ,
00041 const EPointType pointType ):
00042 Phis_( n ),
00043 coeffs_( (n+1)*(n+2)*(n+3)/2 , n*(n+1)*(n+3)/2 )
00044 {
00045 const int N = n*(n+1)*(n+3)/2;
00046 this -> basisCardinality_ = N;
00047 this -> basisDegree_ = n;
00048 this -> basisCellTopology_
00049 = shards::CellTopology(shards::getCellTopologyData<shards::Tetrahedron<4> >() );
00050 this -> basisType_ = BASIS_FEM_FIAT;
00051 this -> basisCoordinates_ = COORDINATES_CARTESIAN;
00052 this -> basisTagsAreSet_ = false;
00053
00054
00055 const int littleN = n*(n+1)*(n+2)/2;
00056 const int bigN = (n+1)*(n+2)*(n+3)/2;
00057 const int start_PkH = (n-1)*n*(n+1)/6;
00058 const int dim_PkH = n*(n+1)*(n+2)/6 - start_PkH;
00059 const int scalarLittleN = littleN/3;
00060 const int scalarBigN = bigN/3;
00061
00062
00063
00064
00065
00066 Teuchos::SerialDenseMatrix<int,Scalar> V1(bigN, N);
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 for (int i=0;i<scalarLittleN;i++) {
00079 for (int k=0;k<3;k++) {
00080 V1(i+k*scalarBigN,i+k*scalarLittleN) = 1.0;
00081 }
00082 }
00083
00084
00085
00086 CubatureDirectTetDefault<Scalar,FieldContainer<Scalar> > myCub( 2 * n );
00087 FieldContainer<Scalar> cubPoints( myCub.getNumPoints() , 3 );
00088 FieldContainer<Scalar> cubWeights( myCub.getNumPoints() );
00089 myCub.getCubature( cubPoints , cubWeights );
00090
00091
00092 FieldContainer<Scalar> phisAtCubPoints( scalarBigN , myCub.getNumPoints() );
00093 Phis_.getValues( phisAtCubPoints , cubPoints , OPERATOR_VALUE );
00094
00095
00096
00097 for (int i=0;i<dim_PkH;i++) {
00098 for (int j=0;j<scalarBigN;j++) {
00099 V1(j,littleN+i) = 0.0;
00100 for (int d=0;d<3;d++) {
00101 for (int k=0;k<myCub.getNumPoints();k++) {
00102 V1(j+d*scalarBigN,littleN+i) +=
00103 cubWeights(k) * cubPoints(k,d)
00104 * phisAtCubPoints(start_PkH+i,k)
00105 * phisAtCubPoints(j,k);
00106 }
00107 }
00108 }
00109 }
00110
00111
00112
00113 Teuchos::SerialDenseMatrix<int,Scalar> V2(N , bigN);
00114
00115 shards::CellTopology faceTop(shards::getCellTopologyData<shards::Triangle<3> >() );
00116 const int numPtsPerFace = PointTools::getLatticeSize( faceTop ,
00117 n+2 ,
00118 1 );
00119
00120 FieldContainer<Scalar> twoDPts( numPtsPerFace , 2 );
00121 PointTools::getLattice<Scalar,FieldContainer<Scalar> >( twoDPts ,
00122 faceTop ,
00123 n+2 ,
00124 1 ,
00125 pointType );
00126
00127
00128 FieldContainer<Scalar> facePts( numPtsPerFace , 3 );
00129 FieldContainer<Scalar> phisAtFacePoints( scalarBigN ,
00130 numPtsPerFace );
00131
00132
00133
00134
00135
00136
00137
00138 Scalar normal[][4] = { {0.0,0.5,-0.5,0.0},
00139 {-0.5,0.5,0.0,0.0},
00140 {0.0,0.5,0.0,-0.5} };
00141
00142 for (int i=0;i<4;i++) {
00143 CellTools<Scalar>::mapToReferenceSubcell( facePts ,
00144 twoDPts ,
00145 2 ,
00146 i ,
00147 this->basisCellTopology_ );
00148
00149 Phis_.getValues( phisAtFacePoints , facePts , OPERATOR_VALUE );
00150
00151
00152 for (int j=0;j<numPtsPerFace;j++) {
00153
00154 for (int k=0;k<scalarBigN;k++) {
00155 for (int l=0;l<3;l++) {
00156 V2(numPtsPerFace*i+j,k+l*scalarBigN) = normal[l][i] * phisAtFacePoints(k,j);
00157 }
00158 }
00159 }
00160 }
00161
00162
00163
00164
00165
00166 if (n > 1) {
00167 const int numInternalPoints = PointTools::getLatticeSize( this->getBaseCellTopology() ,
00168 n + 2 ,
00169 1 );
00170
00171 FieldContainer<Scalar> internalPoints( numInternalPoints , 3 );
00172 PointTools::getLattice<Scalar,FieldContainer<Scalar> >( internalPoints ,
00173 this->getBaseCellTopology() ,
00174 n + 2 ,
00175 1 ,
00176 pointType );
00177
00178 FieldContainer<Scalar> phisAtInternalPoints( scalarBigN , numInternalPoints );
00179 Phis_.getValues( phisAtInternalPoints , internalPoints , OPERATOR_VALUE );
00180
00181
00182 for (int i=0;i<numInternalPoints;i++) {
00183 for (int j=0;j<scalarBigN;j++) {
00184 for (int k=0;k<3;k++) {
00185 V2(4*numPtsPerFace+k*numInternalPoints+i,k*scalarBigN+j) = phisAtInternalPoints(j,i);
00186 }
00187 }
00188 }
00189 }
00190
00191 Teuchos::SerialDenseMatrix<int,Scalar> Vsdm( N , N );
00192
00193
00194 Vsdm.multiply( Teuchos::NO_TRANS , Teuchos::NO_TRANS , 1.0 , V2 , V1 , 0.0 );
00195
00196
00197
00198
00199
00200 Teuchos::SerialDenseSolver<int,Scalar> solver;
00201 solver.setMatrix( rcp( &Vsdm , false ) );
00202 solver.invert( );
00203
00204
00205 Teuchos::SerialDenseMatrix<int,Scalar> Csdm( bigN , N );
00206 Csdm.multiply( Teuchos::NO_TRANS , Teuchos::NO_TRANS , 1.0 , V1 , Vsdm , 0.0 );
00207
00208
00209
00210 for (int i=0;i<bigN;i++) {
00211 for (int j=0;j<N;j++) {
00212 coeffs_(i,j) = Csdm(i,j);
00213 }
00214 }
00215 }
00216
00217 template<class Scalar, class ArrayScalar>
00218 void Basis_HDIV_TET_In_FEM<Scalar, ArrayScalar>::initializeTags() {
00219
00220
00221 int tagSize = 4;
00222 int posScDim = 0;
00223 int posScOrd = 1;
00224 int posDfOrd = 2;
00225
00226
00227
00228 int *tags = new int[ tagSize * this->getCardinality() ];
00229 int *tag_cur = tags;
00230 const int deg = this->getDegree();
00231
00232 const int numPtsPerFace = deg*(deg+1)/2;
00233
00234
00235 for (int f=0;f<4;f++) {
00236 for (int i=0;i<numPtsPerFace;i++) {
00237 tag_cur[0] = 2; tag_cur[1] = f; tag_cur[2] = i; tag_cur[3] = numPtsPerFace;
00238 tag_cur += tagSize;
00239 }
00240 }
00241
00242
00243
00244 const int numInternalDof = this->getCardinality() - 4 * numPtsPerFace;
00245 int internalDofCur=0;
00246 for (int i=4*numPtsPerFace;i<this->getCardinality();i++) {
00247 tag_cur[0] = 3; tag_cur[1] = 0; tag_cur[2] = internalDofCur; tag_cur[3] = numInternalDof;
00248 tag_cur += tagSize;
00249 internalDofCur++;
00250 }
00251
00252
00253 Intrepid::setOrdinalTagData(this -> tagToOrdinal_,
00254 this -> ordinalToTag_,
00255 tags,
00256 this -> basisCardinality_,
00257 tagSize,
00258 posScDim,
00259 posScOrd,
00260 posDfOrd);
00261
00262 delete []tags;
00263
00264 }
00265
00266
00267
00268 template<class Scalar, class ArrayScalar>
00269 void Basis_HDIV_TET_In_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar & outputValues,
00270 const ArrayScalar & inputPoints,
00271 const EOperator operatorType) const {
00272
00273
00274 #ifdef HAVE_INTREPID_DEBUG
00275 Intrepid::getValues_HDIV_Args<Scalar, ArrayScalar>(outputValues,
00276 inputPoints,
00277 operatorType,
00278 this -> getBaseCellTopology(),
00279 this -> getCardinality() );
00280 #endif
00281 const int numPts = inputPoints.dimension(0);
00282 const int deg = this -> getDegree();
00283 const int scalarBigN = (deg+1)*(deg+2)*(deg+3)/6;
00284
00285 try {
00286 switch (operatorType) {
00287 case OPERATOR_VALUE:
00288 {
00289 FieldContainer<Scalar> phisCur( scalarBigN , numPts );
00290 Phis_.getValues( phisCur , inputPoints , OPERATOR_VALUE );
00291
00292 for (int i=0;i<outputValues.dimension(0);i++) {
00293 for (int j=0;j<outputValues.dimension(1);j++) {
00294 for (int l=0;l<3;l++) {
00295 outputValues(i,j,l) = 0.0;
00296 }
00297 for (int k=0;k<scalarBigN;k++) {
00298 for (int l=0;l<3;l++) {
00299 outputValues(i,j,l) += coeffs_(k+l*scalarBigN,i) * phisCur(k,j);
00300 }
00301 }
00302 }
00303 }
00304 }
00305 break;
00306 case OPERATOR_DIV:
00307 {
00308 FieldContainer<Scalar> phisCur( scalarBigN , numPts , 3 );
00309 Phis_.getValues( phisCur , inputPoints , OPERATOR_GRAD );
00310 for (int i=0;i<outputValues.dimension(0);i++) {
00311 for (int j=0;j<outputValues.dimension(1);j++) {
00312 outputValues(i,j) = 0.0;
00313 for (int k=0;k<scalarBigN;k++) {
00314 outputValues(i,j) += coeffs_(k,i) * phisCur(k,j,0);
00315 outputValues(i,j) += coeffs_(k+scalarBigN,i) * phisCur(k,j,1);
00316 outputValues(i,j) += coeffs_(k+2*scalarBigN,i) * phisCur(k,j,2);
00317 }
00318 }
00319 }
00320 }
00321 break;
00322 default:
00323 TEST_FOR_EXCEPTION( true , std::invalid_argument,
00324 ">>> ERROR (Basis_HDIV_TET_In_FEM): Operator type not implemented");
00325 break;
00326 }
00327 }
00328 catch (std::invalid_argument &exception){
00329 TEST_FOR_EXCEPTION( true , std::invalid_argument,
00330 ">>> ERROR (Basis_HDIV_TET_In_FEM): Operator type not implemented");
00331 }
00332
00333 }
00334
00335
00336
00337 template<class Scalar, class ArrayScalar>
00338 void Basis_HDIV_TET_In_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar& outputValues,
00339 const ArrayScalar & inputPoints,
00340 const ArrayScalar & cellVertices,
00341 const EOperator operatorType) const {
00342 TEST_FOR_EXCEPTION( (true), std::logic_error,
00343 ">>> ERROR (Basis_HDIV_TET_In_FEM): FEM Basis calling an FVD member function");
00344 }
00345
00346
00347 }