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
00034 #ifdef _MSC_VER
00035 #include "winmath.h"
00036 #endif
00037
00038
00039 namespace Intrepid {
00040
00041 int PointTools::getLatticeSize( const shards::CellTopology& cellType ,
00042 const int order ,
00043 const int offset )
00044 {
00045 switch( cellType.getKey() ) {
00046 case shards::Tetrahedron<4>::key:
00047 case shards::Tetrahedron<8>::key:
00048 case shards::Tetrahedron<10>::key:
00049 {
00050 const int effectiveOrder = order - 4 * offset;
00051 if (effectiveOrder < 0) return 0;
00052 else return (effectiveOrder+1)*(effectiveOrder+2)*(effectiveOrder+3)/6;
00053 }
00054 break;
00055 case shards::Triangle<3>::key:
00056 case shards::Triangle<4>::key:
00057 case shards::Triangle<6>::key:
00058 {
00059 const int effectiveOrder = order - 3 * offset;
00060 if (effectiveOrder < 0) return 0;
00061 else return (effectiveOrder+1)*(effectiveOrder+2)/2;
00062 }
00063 break;
00064 case shards::Line<2>::key:
00065 case shards::Line<3>::key:
00066 {
00067 const int effectiveOrder = order - 2 * offset;
00068 if (effectiveOrder < 0) return 0;
00069 else return (effectiveOrder+1);
00070 }
00071 break;
00072 default:
00073 TEST_FOR_EXCEPTION( true , std::invalid_argument ,
00074 ">>> ERROR (Intrepid::PointTools::getLatticeSize): Illegal cell type" );
00075
00076 }
00077 }
00078
00079 template<class Scalar, class ArrayType>
00080 void PointTools::getLattice(ArrayType &pts ,
00081 const shards::CellTopology& cellType ,
00082 const int order ,
00083 const int offset ,
00084 const EPointType pointType )
00085 {
00086 switch (pointType) {
00087 case POINTTYPE_EQUISPACED:
00088 getEquispacedLattice<Scalar,ArrayType>( cellType , pts , order , offset );
00089 break;
00090 case POINTTYPE_WARPBLEND:
00091 getWarpBlendLattice<Scalar,ArrayType>( cellType , pts , order , offset );
00092 break;
00093 }
00094 return;
00095 }
00096
00097
00098 template<class Scalar, class ArrayType>
00099 void PointTools::getEquispacedLattice(const shards::CellTopology& cellType ,
00100 ArrayType &points ,
00101 const int order ,
00102 const int offset )
00103
00104 {
00105 switch (cellType.getKey()) {
00106 case shards::Tetrahedron<4>::key:
00107 case shards::Tetrahedron<8>::key:
00108 case shards::Tetrahedron<10>::key:
00109 TEST_FOR_EXCEPTION( ( points.dimension(0) != getLatticeSize( cellType , order , offset ) )
00110 || points.dimension(1) != 3 ,
00111 std::invalid_argument ,
00112 ">>> ERROR(PointTools::getEquispacedLattice): points argument is ill-sized." );
00113 getEquispacedLatticeTetrahedron<Scalar,ArrayType>( points , order , offset );
00114 break;
00115 case shards::Triangle<3>::key:
00116 case shards::Triangle<4>::key:
00117 case shards::Triangle<6>::key:
00118 TEST_FOR_EXCEPTION( ( points.dimension(0) != getLatticeSize( cellType , order , offset ) )
00119 || points.dimension(1) != 2 ,
00120 std::invalid_argument ,
00121 ">>> ERROR(PointTools::getEquispacedLattice): points argument is ill-sized." );
00122 getEquispacedLatticeTriangle<Scalar,ArrayType>( points , order , offset );
00123 break;
00124 case shards::Line<2>::key:
00125 case shards::Line<3>::key:
00126 TEST_FOR_EXCEPTION( ( points.dimension(0) != getLatticeSize( cellType , order , offset ) )
00127 || points.dimension(1) != 1 ,
00128 std::invalid_argument ,
00129 ">>> ERROR(PointTools::getEquispacedLattice): points argument is ill-sized." );
00130 getEquispacedLatticeLine<Scalar,ArrayType>( points , order , offset );
00131 break;
00132 default:
00133 TEST_FOR_EXCEPTION( true , std::invalid_argument ,
00134 ">>> ERROR (Intrepid::PointTools::getEquispacedLattice): Illegal cell type" );
00135 }
00136
00137 }
00138
00139 template<class Scalar, class ArrayType>
00140 void PointTools::getWarpBlendLattice( const shards::CellTopology& cellType ,
00141 ArrayType &points ,
00142 const int order ,
00143 const int offset )
00144
00145 {
00146 switch (cellType.getKey()) {
00147 case shards::Tetrahedron<4>::key:
00148 case shards::Tetrahedron<8>::key:
00149 case shards::Tetrahedron<10>::key:
00150 TEST_FOR_EXCEPTION( ( points.dimension(0) != getLatticeSize( cellType , order , offset ) )
00151 || points.dimension(1) != 3 ,
00152 std::invalid_argument ,
00153 ">>> ERROR(PointTools::getWarpBlendLattice): points argument is ill-sized." );
00154 getWarpBlendLatticeTetrahedron<Scalar,ArrayType>( points , order , offset );
00155 break;
00156 case shards::Triangle<3>::key:
00157 case shards::Triangle<4>::key:
00158 case shards::Triangle<6>::key:
00159 TEST_FOR_EXCEPTION( ( points.dimension(0) != getLatticeSize( cellType , order , offset ) )
00160 || points.dimension(1) != 2 ,
00161 std::invalid_argument ,
00162 ">>> ERROR(PointTools::getWarpBlendLattice): points argument is ill-sized." );
00163 getWarpBlendLatticeTriangle<Scalar,ArrayType>( points , order , offset );
00164 break;
00165 case shards::Line<2>::key:
00166 case shards::Line<3>::key:
00167 TEST_FOR_EXCEPTION( ( points.dimension(0) != getLatticeSize( cellType , order , offset ) )
00168 || points.dimension(1) != 1 ,
00169 std::invalid_argument ,
00170 ">>> ERROR(PointTools::getWarpBlendLattice): points argument is ill-sized." );
00171 getWarpBlendLatticeLine<Scalar,ArrayType>( points , order , offset );
00172 break;
00173 default:
00174 TEST_FOR_EXCEPTION( true , std::invalid_argument ,
00175 ">>> ERROR (Intrepid::PointTools::getWarpBlendLattice): Illegal cell type" );
00176 }
00177
00178 }
00179
00180 template<class Scalar, class ArrayType>
00181 void PointTools::getEquispacedLatticeLine( ArrayType &points ,
00182 const int order ,
00183 const int offset )
00184 {
00185 TEST_FOR_EXCEPTION( order <= 0 ,
00186 std::invalid_argument ,
00187 ">>> ERROR (Intrepid::PointTools::getEquispacedLatticeLine): order must be positive" );
00188 const Scalar h = 2.0 / order;
00189
00190 for (int i=offset;i<=order-offset;i++) {
00191 points(i-offset,0) = -1.0 + h * (Scalar) i;
00192 }
00193
00194 return;
00195 }
00196
00197 template<class Scalar, class ArrayType>
00198 void PointTools::getEquispacedLatticeTriangle( ArrayType &points ,
00199 const int order ,
00200 const int offset )
00201 {
00202 TEST_FOR_EXCEPTION( order <= 0 ,
00203 std::invalid_argument ,
00204 ">>> ERROR (Intrepid::PointTools::getEquispacedLatticeLine): order must be positive" );
00205
00206 const Scalar h = 1.0 / order;
00207 int cur = 0;
00208
00209 for (int i=offset;i<=order-offset;i++) {
00210 for (int j=offset;j<=order-i-offset;j++) {
00211 points(cur,0) = (Scalar)0.0 + (Scalar) j * h ;
00212 points(cur,1) = (Scalar)0.0 + (Scalar) i * h;
00213 cur++;
00214 }
00215 }
00216
00217 return;
00218 }
00219
00220 template<class Scalar, class ArrayType>
00221 void PointTools::getEquispacedLatticeTetrahedron( ArrayType &points ,
00222 const int order ,
00223 const int offset )
00224 {
00225 TEST_FOR_EXCEPTION( (order <= 0) ,
00226 std::invalid_argument ,
00227 ">>> ERROR (Intrepid::PointTools::getEquispacedLatticeTetrahedron): order must be positive" );
00228
00229 const Scalar h = 1.0 / order;
00230 int cur = 0;
00231
00232 for (int i=offset;i<=order-offset;i++) {
00233 for (int j=offset;j<=order-i-offset;j++) {
00234 for (int k=offset;k<=order-i-j-offset;k++) {
00235 points(cur,0) = (Scalar) k * h;
00236 points(cur,1) = (Scalar) j * h;
00237 points(cur,2) = (Scalar) i * h;
00238 cur++;
00239 }
00240 }
00241 }
00242
00243 return;
00244 }
00245
00246 template<class Scalar, class ArrayType>
00247 void PointTools::getWarpBlendLatticeLine( ArrayType &points ,
00248 const int order ,
00249 const int offset )
00250 {
00251 Scalar *z = new Scalar[order+1];
00252 Scalar *w = new Scalar[order+1];
00253
00254 IntrepidPolylib::zwglj( z , w , order + 1 , 0.0 , 0.0 );
00255
00256 for (int i=offset;i<=order-offset;i++) {
00257 points(i-offset) = z[i];
00258 }
00259
00260 delete []z;
00261 delete []w;
00262
00263 return;
00264 }
00265
00266 template<class Scalar, class ArrayType>
00267 void PointTools::warpFactor( const int order ,
00268 const ArrayType &xnodes ,
00269 const ArrayType &xout ,
00270 ArrayType &warp)
00271 {
00272 TEST_FOR_EXCEPTION( ( warp.dimension(0) != xout.dimension(0) ) ,
00273 std::invalid_argument ,
00274 ">>> ERROR (PointTools::warpFactor): xout and warp must be same size." );
00275
00276 warp.initialize();
00277
00278 FieldContainer<Scalar> d( xout.dimension(0) );
00279 d.initialize();
00280
00281 FieldContainer<Scalar> xeq( order + 1 ,1);
00282 PointTools::getEquispacedLatticeLine<Scalar,ArrayType>( xeq , order , 0 );
00283 xeq.resize( order + 1 );
00284
00285 TEST_FOR_EXCEPTION( ( xeq.dimension(0) != xnodes.dimension(0) ) ,
00286 std::invalid_argument ,
00287 ">>> ERROR (PointTools::warpFactor): xeq and xnodes must be same size." );
00288
00289 for (int i=0;i<=order;i++) {
00290
00291 for (int k=0;k<d.dimension(0);k++) {
00292 d(k) = xnodes(i) - xeq(i);
00293 }
00294
00295 for (int j=1;j<order;j++) {
00296 if (i != j) {
00297 for (int k=0;k<d.dimension(0);k++) {
00298 d(k) = d(k) * ( (xout(k)-xeq(j)) / (xeq(i)-xeq(j)) );
00299 }
00300 }
00301 }
00302
00303
00304 if ( i != 0 ) {
00305 for (int k=0;k<d.dimension(0);k++) {
00306 d(k) = -d(k) / (xeq(i) - xeq(0));
00307 }
00308 }
00309
00310 if (i != order ) {
00311 for (int k=0;k<d.dimension(0);k++) {
00312 d(k) = d(k) / (xeq(i) - xeq(order));
00313 }
00314 }
00315
00316 for (int k=0;k<d.dimension(0);k++) {
00317 warp(k) += d(k);
00318 }
00319
00320 }
00321
00322
00323 return;
00324 }
00325
00326 template<class Scalar, class ArrayType>
00327 void PointTools::getWarpBlendLatticeTriangle( ArrayType &points ,
00328 const int order ,
00329 const int offset )
00330 {
00331
00332 Intrepid::FieldContainer<Scalar> gaussX( order + 1 );
00333
00334 PointTools::getWarpBlendLatticeLine<Scalar,FieldContainer<Scalar> >( gaussX , order , 0 );
00335
00336 Scalar alpopt[] = {0.0000,0.0000,1.4152,0.1001,0.2751,0.9800,1.0999,
00337 1.2832,1.3648, 1.4773, 1.4959, 1.5743, 1.5770, 1.6223, 1.6258};
00338
00339 Scalar alpha;
00340
00341 if (order >= 1 && order < 16) {
00342 alpha = alpopt[order-1];
00343 }
00344 else {
00345 alpha = 5.0 / 3.0;
00346 }
00347
00348 const int p = order;
00349 int N = (p+1)*(p+2)/2;
00350
00351
00352 Intrepid::FieldContainer<Scalar> L1( N );
00353 Intrepid::FieldContainer<Scalar> L2( N );
00354 Intrepid::FieldContainer<Scalar> L3( N );
00355 Intrepid::FieldContainer<Scalar> X(N);
00356 Intrepid::FieldContainer<Scalar> Y(N);
00357
00358 int sk = 0;
00359 for (int n=1;n<=p+1;n++) {
00360 for (int m=1;m<=p+2-n;m++) {
00361 L1(sk) = (n-1) / (Scalar)p;
00362 L3(sk) = (m-1) / (Scalar)p;
00363 L2(sk) = 1.0 - L1(sk) - L3(sk);
00364 sk++;
00365 }
00366 }
00367
00368 for (int n=0;n<N;n++) {
00369 X(n) = -L2(n) + L3(n);
00370 Y(n) = (-L2(n) - L3(n) + 2*L1(n))/1.7320508075688772;
00371 }
00372
00373
00374 Intrepid::FieldContainer<Scalar> blend1(N);
00375 Intrepid::FieldContainer<Scalar> blend2(N);
00376 Intrepid::FieldContainer<Scalar> blend3(N);
00377
00378 for (int n=0;n<N;n++) {
00379 blend1(n) = 4.0 * L2(n) * L3(n);
00380 blend2(n) = 4.0 * L1(n) * L3(n);
00381 blend3(n) = 4.0 * L1(n) * L2(n);
00382 }
00383
00384
00385 Intrepid::FieldContainer<Scalar> L3mL2(N);
00386 Intrepid::FieldContainer<Scalar> L1mL3(N);
00387 Intrepid::FieldContainer<Scalar> L2mL1(N);
00388
00389 for (int k=0;k<N;k++) {
00390 L3mL2(k) = L3(k)-L2(k);
00391 L1mL3(k) = L1(k)-L3(k);
00392 L2mL1(k) = L2(k)-L1(k);
00393 }
00394
00395 FieldContainer<Scalar> warpfactor1(N);
00396 FieldContainer<Scalar> warpfactor2(N);
00397 FieldContainer<Scalar> warpfactor3(N);
00398
00399 warpFactor<Scalar,FieldContainer<Scalar> >( order , gaussX , L3mL2 , warpfactor1 );
00400 warpFactor<Scalar,FieldContainer<Scalar> >( order , gaussX , L1mL3 , warpfactor2 );
00401 warpFactor<Scalar,FieldContainer<Scalar> >( order , gaussX , L2mL1 , warpfactor3 );
00402
00403 FieldContainer<Scalar> warp1(N);
00404 FieldContainer<Scalar> warp2(N);
00405 FieldContainer<Scalar> warp3(N);
00406
00407 for (int k=0;k<N;k++) {
00408 warp1(k) = blend1(k) * warpfactor1(k) *
00409 ( 1.0 + alpha * alpha * L1(k) * L1(k) );
00410 warp2(k) = blend2(k) * warpfactor2(k) *
00411 ( 1.0 + alpha * alpha * L2(k) * L2(k) );
00412 warp3(k) = blend3(k) * warpfactor3(k) *
00413 ( 1.0 + alpha * alpha * L3(k) * L3(k) );
00414 }
00415
00416 for (int k=0;k<N;k++) {
00417 X(k) += 1.0 * warp1(k) + cos( 2.0 * M_PI / 3.0 ) * warp2(k) + cos(4*M_PI/3.0) * warp3(k);
00418 Y(k) += 0.0 * warp1(k) + sin( 2.0 * M_PI / 3.0 ) * warp2(k) + sin( 4*M_PI/3.0) * warp3(k);
00419 }
00420
00421 FieldContainer<Scalar> warXY(N,2);
00422
00423 for (int k=0;k<N;k++) {
00424 warXY(k,0) = X(k);
00425 warXY(k,1) = Y(k);
00426 }
00427
00428
00429
00430 FieldContainer<Scalar> warburtonVerts(1,3,2);
00431 warburtonVerts(0,0,0) = -1.0;
00432 warburtonVerts(0,0,1) = -1.0/sqrt(3.0);
00433 warburtonVerts(0,1,0) = 1.0;
00434 warburtonVerts(0,1,1) = -1.0/sqrt(3.0);
00435 warburtonVerts(0,2,0) = 0.0;
00436 warburtonVerts(0,2,1) = 2.0/sqrt(3.0);
00437
00438 FieldContainer<Scalar> refPts(N,2);
00439
00440 Intrepid::CellTools<Scalar>::mapToReferenceFrame( refPts ,
00441 warXY ,
00442 warburtonVerts ,
00443 shards::getCellTopologyData< shards::Triangle<3> >(),
00444 0 );
00445
00446
00447 int noffcur = 0;
00448 int offcur = 0;
00449 for (int i=0;i<=order;i++) {
00450 for (int j=0;j<=order-i;j++) {
00451 if ( (i >= offset) && (i <= order-offset) &&
00452 (j >= offset) && (j <= order-i-offset) ) {
00453 points(offcur,0) = refPts(noffcur,0);
00454 points(offcur,1) = refPts(noffcur,1);
00455 offcur++;
00456 }
00457 noffcur++;
00458 }
00459 }
00460
00461 return;
00462 }
00463
00464
00465 template<class Scalar, class ArrayType>
00466 void PointTools::warpShiftFace3D( const int order ,
00467 const Scalar pval ,
00468 const ArrayType &L1,
00469 const ArrayType &L2,
00470 const ArrayType &L3,
00471 const ArrayType &L4,
00472 ArrayType &dxy)
00473 {
00474 evalshift<Scalar,ArrayType>(order,pval,L2,L3,L4,dxy);
00475 return;
00476 }
00477
00478 template<class Scalar, class ArrayType>
00479 void PointTools::evalshift( const int order ,
00480 const Scalar pval ,
00481 const ArrayType &L1 ,
00482 const ArrayType &L2 ,
00483 const ArrayType &L3 ,
00484 ArrayType &dxy )
00485 {
00486
00487 FieldContainer<Scalar> gaussX(order+1);
00488 PointTools::getWarpBlendLatticeLine<Scalar,FieldContainer<Scalar> >( gaussX , order , 0 );
00489
00490 const int N = L1.dimension(0);
00491
00492
00493 for (int k=0;k<=order;k++) {
00494 gaussX(k) *= -1.0;
00495 }
00496
00497
00498 FieldContainer<Scalar> blend1(N);
00499 FieldContainer<Scalar> blend2(N);
00500 FieldContainer<Scalar> blend3(N);
00501
00502 for (int i=0;i<N;i++) {
00503 blend1(i) = L2(i) * L3(i);
00504 blend2(i) = L1(i) * L3(i);
00505 blend3(i) = L1(i) * L2(i);
00506 }
00507
00508
00509 FieldContainer<Scalar> warpfactor1(N);
00510 FieldContainer<Scalar> warpfactor2(N);
00511 FieldContainer<Scalar> warpfactor3(N);
00512
00513
00514 FieldContainer<Scalar> L3mL2(N);
00515 FieldContainer<Scalar> L1mL3(N);
00516 FieldContainer<Scalar> L2mL1(N);
00517
00518 for (int k=0;k<N;k++) {
00519 L3mL2(k) = L3(k)-L2(k);
00520 L1mL3(k) = L1(k)-L3(k);
00521 L2mL1(k) = L2(k)-L1(k);
00522 }
00523
00524 evalwarp<Scalar,FieldContainer<Scalar> >( warpfactor1 , order , gaussX , L3mL2 );
00525 evalwarp<Scalar,FieldContainer<Scalar> >( warpfactor2 , order , gaussX , L1mL3 );
00526 evalwarp<Scalar,FieldContainer<Scalar> >( warpfactor3 , order , gaussX , L2mL1 );
00527
00528 for (int k=0;k<N;k++) {
00529 warpfactor1(k) *= 4.0;
00530 warpfactor2(k) *= 4.0;
00531 warpfactor3(k) *= 4.0;
00532 }
00533
00534 FieldContainer<Scalar> warp1(N);
00535 FieldContainer<Scalar> warp2(N);
00536 FieldContainer<Scalar> warp3(N);
00537
00538 for (int k=0;k<N;k++) {
00539 warp1(k) = blend1(k) * warpfactor1(k) *
00540 ( 1.0 + pval * pval * L1(k) * L1(k) );
00541 warp2(k) = blend2(k) * warpfactor2(k) *
00542 ( 1.0 + pval * pval * L2(k) * L2(k) );
00543 warp3(k) = blend3(k) * warpfactor3(k) *
00544 ( 1.0 + pval * pval * L3(k) * L3(k) );
00545 }
00546
00547 for (int k=0;k<N;k++) {
00548 dxy(k,0) = 1.0 * warp1(k) + cos( 2.0 * M_PI / 3.0 ) * warp2(k) + cos( 4.0*M_PI/3.0 ) * warp3(k);
00549 dxy(k,1) = 0.0 * warp1(k) + sin( 2.0 * M_PI / 3.0 ) * warp2(k) + sin( 4.0*M_PI/3.0 ) * warp3(k);
00550 }
00551
00552 return;
00553
00554 }
00555
00556
00557 template<class Scalar, class ArrayType>
00558 void PointTools::evalwarp( ArrayType &warp ,
00559 const int order ,
00560 const ArrayType &xnodes ,
00561 const ArrayType &xout )
00562 {
00563 FieldContainer<Scalar> xeq(order+1);
00564 FieldContainer<Scalar> d(xout.dimension(0));
00565
00566 d.initialize();
00567
00568 for (int i=0;i<=order;i++) {
00569 xeq(i) = -1.0 + 2.0 * ( order - i ) / order;
00570 }
00571
00572
00573
00574 for (int i=0;i<=order;i++) {
00575 d.initialize( xnodes(i) - xeq(i) );
00576 for (int j=1;j<order;j++) {
00577 if (i!=j) {
00578 for (int k=0;k<d.dimension(0);k++) {
00579 d(k) = d(k) * (xout(k)-xeq(j))/(xeq(i)-xeq(j));
00580 }
00581 }
00582 }
00583 if (i!=0) {
00584 for (int k=0;k<d.dimension(0);k++) {
00585 d(k) = -d(k)/(xeq(i)-xeq(0));
00586 }
00587 }
00588 if (i!=order) {
00589 for (int k=0;k<d.dimension(0);k++) {
00590 d(k) = d(k)/(xeq(i)-xeq(order));
00591 }
00592 }
00593
00594 for (int k=0;k<d.dimension(0);k++) {
00595 warp(k) += d(k);
00596 }
00597 }
00598
00599 return;
00600 }
00601
00602
00603 template<class Scalar, class ArrayType>
00604 void PointTools::getWarpBlendLatticeTetrahedron(ArrayType &points ,
00605 const int order ,
00606 const int offset )
00607 {
00608 Scalar alphastore[] = { 0,0,0,0.1002, 1.1332,1.5608,1.3413,1.2577,1.1603,
00609 1.10153,0.6080,0.4523,0.8856,0.8717,0.9655};
00610 Scalar alpha;
00611
00612 if (order <= 15) {
00613 alpha = alphastore[order-1];
00614 }
00615 else {
00616 alpha = 1.0;
00617 }
00618
00619 const int N = (order+1)*(order+2)*(order+3)/6;
00620 Scalar tol = 1.e-10;
00621
00622 FieldContainer<Scalar> shift(N,3);
00623 shift.initialize();
00624
00625
00626 FieldContainer<Scalar> equipoints(N,3);
00627 int sk = 0;
00628 for (int n=0;n<=order;n++) {
00629 for (int m=0;m<=order-n;m++) {
00630 for (int q=0;q<=order-n-m;q++) {
00631 equipoints(sk,0) = -1.0 + (q * 2.0 ) / order;
00632 equipoints(sk,1) = -1.0 + (m * 2.0 ) / order;
00633 equipoints(sk,2) = -1.0 + (n * 2.0 ) / order;
00634 sk++;
00635 }
00636 }
00637 }
00638
00639
00640
00641 FieldContainer<Scalar> L1(N);
00642 FieldContainer<Scalar> L2(N);
00643 FieldContainer<Scalar> L3(N);
00644 FieldContainer<Scalar> L4(N);
00645 for (int i=0;i<N;i++) {
00646 L1(i) = (1.0 + equipoints(i,2)) / 2.0;
00647 L2(i) = (1.0 + equipoints(i,1)) / 2.0;
00648 L3(i) = -(1.0 + equipoints(i,0) + equipoints(i,1) + equipoints(i,2)) / 2.0;
00649 L4(i) = (1.0 + equipoints(i,0)) / 2.0;
00650 }
00651
00652
00653
00654 FieldContainer<Scalar> warVerts(4,3);
00655 warVerts(0,0) = -1.0;
00656 warVerts(0,1) = -1.0/sqrt(3.0);
00657 warVerts(0,2) = -1.0/sqrt(6.0);
00658 warVerts(1,0) = 1.0;
00659 warVerts(1,1) = -1.0/sqrt(3.0);
00660 warVerts(1,2) = -1.0/sqrt(6.0);
00661 warVerts(2,0) = 0.0;
00662 warVerts(2,1) = 2.0 / sqrt(3.0);
00663 warVerts(2,2) = -1.0/sqrt(6.0);
00664 warVerts(3,0) = 0.0;
00665 warVerts(3,1) = 0.0;
00666 warVerts(3,2) = 3.0 / sqrt(6.0);
00667
00668
00669
00670 FieldContainer<Scalar> t1(4,3);
00671 FieldContainer<Scalar> t2(4,3);
00672 for (int i=0;i<3;i++) {
00673 t1(0,i) = warVerts(1,i) - warVerts(0,i);
00674 t1(1,i) = warVerts(1,i) - warVerts(0,i);
00675 t1(2,i) = warVerts(2,i) - warVerts(1,i);
00676 t1(3,i) = warVerts(2,i) - warVerts(0,i);
00677 t2(0,i) = warVerts(2,i) - 0.5 * ( warVerts(0,i) + warVerts(1,i) );
00678 t2(1,i) = warVerts(3,i) - 0.5 * ( warVerts(0,i) + warVerts(1,i) );
00679 t2(2,i) = warVerts(3,i) - 0.5 * ( warVerts(1,i) + warVerts(2,i) );
00680 t2(3,i) = warVerts(3,i) - 0.5 * ( warVerts(0,i) + warVerts(2,i) );
00681 }
00682
00683
00684 for (int n=0;n<4;n++) {
00685
00686 Scalar normt1n = 0.0;
00687 Scalar normt2n = 0.0;
00688 for (int i=0;i<3;i++) {
00689 normt1n += (t1(n,i) * t1(n,i));
00690 normt2n += (t2(n,i) * t2(n,i));
00691 }
00692 normt1n = sqrt(normt1n);
00693 normt2n = sqrt(normt2n);
00694
00695 for (int i=0;i<3;i++) {
00696 t1(n,i) /= normt1n;
00697 t2(n,i) /= normt2n;
00698 }
00699 }
00700
00701
00702 FieldContainer<Scalar> XYZ(N,3);
00703 for (int i=0;i<N;i++) {
00704 for (int j=0;j<3;j++) {
00705 XYZ(i,j) = L3(i)*warVerts(0,j) + L4(i)*warVerts(1,j) + L2(i)*warVerts(2,j) + L1(i)*warVerts(3,j);
00706 }
00707 }
00708
00709 for (int face=1;face<=4;face++) {
00710 FieldContainer<Scalar> La, Lb, Lc, Ld;
00711 FieldContainer<Scalar> warp(N,2);
00712 FieldContainer<Scalar> blend(N);
00713 FieldContainer<Scalar> denom(N);
00714 switch (face) {
00715 case 1:
00716 La = L1; Lb = L2; Lc = L3; Ld = L4; break;
00717 case 2:
00718 La = L2; Lb = L1; Lc = L3; Ld = L4; break;
00719 case 3:
00720 La = L3; Lb = L1; Lc = L4; Ld = L2; break;
00721 case 4:
00722 La = L4; Lb = L1; Lc = L3; Ld = L2; break;
00723 }
00724
00725
00726 warpShiftFace3D<Scalar,ArrayType>(order,alpha,La,Lb,Lc,Ld,warp);
00727
00728 for (int k=0;k<N;k++) {
00729 blend(k) = Lb(k) * Lc(k) * Ld(k);
00730 }
00731
00732 for (int k=0;k<N;k++) {
00733 denom(k) = (Lb(k) + 0.5 * La(k)) * (Lc(k) + 0.5*La(k)) * (Ld(k) + 0.5 * La(k));
00734 }
00735
00736 for (int k=0;k<N;k++) {
00737 if (denom(k) > tol) {
00738 blend(k) *= ( 1.0 + alpha * alpha * La(k) * La(k) ) / denom(k);
00739 }
00740 }
00741
00742
00743
00744 for (int k=0;k<N;k++) {
00745 for (int j=0;j<3;j++) {
00746 shift(k,j) = shift(k,j) + blend(k) * warp(k,0) * t1(face-1,j)
00747 + blend(k) * warp(k,1) * t2(face-1,j);
00748 }
00749 }
00750
00751 for (int k=0;k<N;k++) {
00752 if (La(k) < tol && ( Lb(k) < tol || Lc(k) < tol || Ld(k) < tol )) {
00753 for (int j=0;j<3;j++) {
00754 shift(k,j) = warp(k,0) * t1(face-1,j) + warp(k,1) * t2(face-1,j);
00755 }
00756 }
00757 }
00758
00759 }
00760
00761 FieldContainer<Scalar> updatedPoints(N,3);
00762 for (int k=0;k<N;k++) {
00763 for (int j=0;j<3;j++) {
00764 updatedPoints(k,j) = XYZ(k,j) + shift(k,j);
00765 }
00766 }
00767
00768 warVerts.resize( 1 , 4 , 3 );
00769
00770
00771 FieldContainer<Scalar> refPts(N,3);
00772 CellTools<Scalar>::mapToReferenceFrame( refPts ,updatedPoints ,
00773 warVerts ,
00774 shards::getCellTopologyData<shards::Tetrahedron<4> >() ,
00775 0 );
00776
00777
00778 int noffcur = 0;
00779 int offcur = 0;
00780 for (int i=0;i<=order;i++) {
00781 for (int j=0;j<=order-i;j++) {
00782 for (int k=0;k<=order-i-j;k++) {
00783 if ( (i >= offset) && (i <= order-offset) &&
00784 (j >= offset) && (j <= order-i-offset) &&
00785 (k >= offset) && (k <= order-i-j-offset) ) {
00786 points(offcur,0) = refPts(noffcur,0);
00787 points(offcur,1) = refPts(noffcur,1);
00788 points(offcur,2) = refPts(noffcur,2);
00789 offcur++;
00790 }
00791 noffcur++;
00792 }
00793 }
00794 }
00795
00796
00797
00798 }
00799
00800
00801 }