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