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
00044 static int idx(int p, int q,int r);
00045
00063 template<typename Scalar>
00064 static void jrc( const Scalar &alpha , const Scalar &beta ,
00065 const int &n ,
00066 Scalar &an , Scalar &bn, Scalar &cn );
00067
00068 template<class Scalar, class ArrayScalar>
00069 Basis_HGRAD_TET_Cn_FEM_ORTH<Scalar,ArrayScalar>::Basis_HGRAD_TET_Cn_FEM_ORTH( int degree )
00070 {
00071 this -> basisCardinality_ = (degree+1)*(degree+2)*(degree+3)/6;
00072 this -> basisDegree_ = degree;
00073 this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Tetrahedron<4> >() );
00074 this -> basisType_ = BASIS_FEM_HIERARCHICAL;
00075 this -> basisCoordinates_ = COORDINATES_CARTESIAN;
00076 this -> basisTagsAreSet_ = false;
00077 }
00078
00079
00080
00081 template<class Scalar, class ArrayScalar>
00082 void Basis_HGRAD_TET_Cn_FEM_ORTH<Scalar, ArrayScalar>::initializeTags() {
00083
00084
00085 int tagSize = 4;
00086 int posScDim = 0;
00087 int posScOrd = 1;
00088 int posDfOrd = 2;
00089
00090
00091 int *tags = new int[tagSize * this->getCardinality()];
00092 for (int i=0;i<this->getCardinality();i++) {
00093 tags[4*i] = 2;
00094 tags[4*i+1] = 0;
00095 tags[4*i+2] = i;
00096 tags[4*i+3] = this->getCardinality();
00097 }
00098
00099
00100 Intrepid::setOrdinalTagData(this -> tagToOrdinal_,
00101 this -> ordinalToTag_,
00102 tags,
00103 this -> basisCardinality_,
00104 tagSize,
00105 posScDim,
00106 posScOrd,
00107 posDfOrd);
00108 }
00109
00110
00111
00112 template<class Scalar, class ArrayScalar>
00113 void Basis_HGRAD_TET_Cn_FEM_ORTH<Scalar, ArrayScalar>::getValues(ArrayScalar & outputValues,
00114 const ArrayScalar & inputPoints,
00115 const EOperator operatorType) const {
00116
00117
00118 #ifdef HAVE_INTREPID_DEBUG
00119 Intrepid::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
00120 inputPoints,
00121 operatorType,
00122 this -> getBaseCellTopology(),
00123 this -> getCardinality() );
00124 #endif
00125 const int deg = this->getDegree();
00126
00127 switch (operatorType) {
00128 case OPERATOR_VALUE:
00129 {
00130 TabulatorTet<Scalar,ArrayScalar,0>::tabulate( outputValues ,
00131 deg ,
00132 inputPoints );
00133 }
00134 break;
00135 case OPERATOR_GRAD:
00136 case OPERATOR_D1:
00137 {
00138 TabulatorTet<Scalar,ArrayScalar,1>::tabulate( outputValues ,
00139 deg ,
00140 inputPoints );
00141 }
00142 break;
00143 default:
00144 TEST_FOR_EXCEPTION( true , std::invalid_argument,
00145 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM_ORTH): invalid or unsupported operator" );
00146 }
00147
00148 return;
00149 }
00150
00151 template<class Scalar, class ArrayScalar>
00152 void Basis_HGRAD_TET_Cn_FEM_ORTH<Scalar, ArrayScalar>::getValues(ArrayScalar& outputValues,
00153 const ArrayScalar & inputPoints,
00154 const ArrayScalar & cellVertices,
00155 const EOperator operatorType) const {
00156 TEST_FOR_EXCEPTION( (true), std::logic_error,
00157 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM_ORTH): FEM Basis calling an FVD member function");
00158 }
00159
00160 template<class Scalar, class ArrayScalar>
00161 void TabulatorTet<Scalar,ArrayScalar,0>::tabulate( ArrayScalar &outputValues ,
00162 const int deg ,
00163 const ArrayScalar &z )
00164 {
00165 const int np = z.dimension( 0 );
00166 int idxcur;
00167
00168
00169
00170
00171
00172
00173 Teuchos::Array<Scalar> f1(np),f2(np),f3(np),f4(np),f5(np);
00174
00175 for (int i=0;i<np;i++) {
00176 f1[i] = 0.5 * ( 2.0 + 2.0*(2.0*z(i,0)-1.0) + (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) );
00177 Scalar foo = 0.5 * ( (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) );
00178 f2[i] = foo * foo;
00179 f3[i] = 0.5 * ( 1.0 + 2.0 * (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) );
00180 f4[i] = 0.5 * ( 1.0 - (2.0*z(i,2)-1.0) );
00181 f5[i] = f4[i] * f4[i];
00182 }
00183
00184
00185 idxcur = idx(0,0,0);
00186 for (int i=0;i<np;i++) {
00187 outputValues(idxcur,i) = 1.0 + z(i,0) - z(i,0) + z(i,1) - z(i,1) + z(i,2) - z(i,2);
00188 }
00189
00190 if (deg > 0) {
00191
00192
00193 idxcur = idx(1,0,0);
00194 for (int i=0;i<np;i++) {
00195 outputValues(idxcur,i) = f1[i];
00196 }
00197
00198
00199 for (int p=1;p<deg;p++) {
00200 Scalar a1 = (2.0 * p + 1.0) / ( p + 1.0);
00201 Scalar a2 = p / ( p + 1.0 );
00202 int idxp = idx(p,0,0);
00203 int idxpp1 = idx(p+1,0,0);
00204 int idxpm1 = idx(p-1,0,0);
00205 for (int i=0;i<np;i++) {
00206 outputValues(idxpp1,i) = a1 * f1[i] * outputValues(idxp,i) - a2 * f2[i] * outputValues(idxpm1,i);
00207 }
00208 }
00209
00210 for (int p=0;p<deg;p++) {
00211 int idx0 = idx(p,0,0);
00212 int idx1 = idx(p,1,0);
00213 for (int i=0;i<np;i++) {
00214 outputValues(idx1,i) = outputValues(idx0,i) * ( p * ( 1.0 + (2.0*z(i,1)-1.0) ) +
00215 0.5 * ( 2.0 + 3.0 * (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) ) );
00216 }
00217 }
00218
00219
00220 for (int p=0;p<deg-1;p++) {
00221 for (int q=1;q<deg-p;q++) {
00222 Scalar aq,bq,cq;
00223
00224 jrc((Scalar)(2.0*p+1.0),(Scalar)(0),q,aq,bq,cq);
00225 int idxpqp1 = idx(p,q+1,0);
00226 int idxpq = idx(p,q,0);
00227 int idxpqm1 = idx(p,q-1,0);
00228 for (int i=0;i<np;i++) {
00229 outputValues(idxpqp1,i) = ( aq * f3[i] + bq * f4[i] ) * outputValues(idxpq,i)
00230 - ( cq * f5[i] ) * outputValues(idxpqm1,i);
00231 }
00232 }
00233 }
00234
00235
00236 for (int p=0;p<deg;p++) {
00237 for (int q=0;q<deg-p;q++) {
00238 int idxpq1 = idx(p,q,1);
00239 int idxpq0 = idx(p,q,0);
00240 for (int i=0;i<np;i++) {
00241 outputValues(idxpq1,i) = outputValues(idxpq0,i) * ( 1.0 + p + q + ( 2.0 + q +
00242 p ) * (2.0*z(i,2)-1.0) );
00243 }
00244 }
00245 }
00246
00247 for (int p=0;p<deg-1;p++) {
00248 for (int q=0;q<deg-p-1;q++) {
00249 for (int r=1;r<deg-p-q;r++) {
00250 Scalar ar,br,cr;
00251 int idxpqrp1 = idx(p,q,r+1);
00252 int idxpqr = idx(p,q,r);
00253 int idxpqrm1 = idx(p,q,r-1);
00254 jrc((Scalar)(2.0*p+2.0*q+2.0),(Scalar)(0.0),r,ar,br,cr);
00255 for (int i=0;i<np;i++) {
00256 outputValues(idxpqrp1,i) = (ar * (2.0*z(i,2)-1.0) + br) * outputValues( idxpqr , i ) - cr * outputValues(idxpqrm1,i);
00257 }
00258 }
00259 }
00260 }
00261
00262 }
00263
00264 for (int p=0;p<=deg;p++) {
00265 for (int q=0;q<=deg-p;q++) {
00266 for (int r=0;r<=deg-p-q;r++) {
00267 int idxcur = idx(p,q,r);
00268 Scalar scal = sqrt( (p+0.5)*(p+q+1.0)*(p+q+r+1.5) );
00269 for (int i=0;i<np;i++) {
00270 outputValues(idxcur,i) *= scal;
00271 }
00272 }
00273 }
00274 }
00275
00276 return;
00277
00278 }
00279
00280
00281 template<typename Scalar, typename ArrayScalar>
00282 void TabulatorTet<Scalar,ArrayScalar,1>::tabulate( ArrayScalar &outputValues ,
00283 const int deg ,
00284 const ArrayScalar &z )
00285 {
00286 const int np = z.dimension(0);
00287 const int card = outputValues.dimension(0);
00288 FieldContainer<Sacado::Fad::DFad<Scalar> > dZ( z.dimension(0) , z.dimension(1) );
00289 for (int i=0;i<np;i++) {
00290 for (int j=0;j<3;j++) {
00291 dZ(i,j) = Sacado::Fad::DFad<Scalar>( z(i,j) );
00292 dZ(i,j).diff(j,3);
00293 }
00294 }
00295 FieldContainer<Sacado::Fad::DFad<Scalar> > dResult(card,np);
00296
00297 TabulatorTet<Sacado::Fad::DFad<Scalar>,FieldContainer<Sacado::Fad::DFad<Scalar> >,0>::tabulate( dResult ,
00298 deg ,
00299 dZ );
00300
00301 for (int i=0;i<card;i++) {
00302 for (int j=0;j<np;j++) {
00303 for (int k=0;k<3;k++) {
00304 outputValues(i,j,k) = dResult(i,j).dx(k);
00305 }
00306 }
00307 }
00308
00309 return;
00310
00311 }
00312
00313 int idx(int p , int q, int r)
00314 {
00315 return (p+q+r)*(p+q+r+1)*(p+q+r+2)/6+(q+r)*(q+r+1)/2+r;
00316 }
00317
00318
00319 template<class Scalar>
00320 void jrc( const Scalar &alpha , const Scalar &beta ,
00321 const int &n ,
00322 Scalar &an , Scalar &bn, Scalar &cn )
00323 {
00324 an = (2.0 * n + 1.0 + alpha + beta) * ( 2.0 * n + 2.0 + alpha + beta )
00325 / ( 2.0 * ( n + 1 ) * ( n + 1 + alpha + beta ) );
00326 bn = (alpha*alpha-beta*beta)*(2.0*n+1.0+alpha+beta)
00327 / ( 2.0*(n+1.0)*(2.0*n+alpha+beta)*(n+1.0+alpha+beta) );
00328 cn = (n+alpha)*(n+beta)*(2.0*n+2.0+alpha+beta)
00329 / ( (n+1.0)*(n+1.0+alpha+beta)*(2.0*n+alpha+beta) );
00330
00331 return;
00332 }
00333
00334 }