SundanceCubicHermite.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #include "SundanceCubicHermite.hpp"
00043 #include "SundanceADReal.hpp"
00044 #include "PlayaExceptions.hpp"
00045 #include "SundanceSpatialDerivSpecifier.hpp"
00046 #include "SundancePoint.hpp"
00047 #include "SundanceObjectWithVerbosity.hpp"
00048 #include "SundanceOut.hpp"
00049 
00050 using namespace Sundance;
00051 using namespace Teuchos;
00052 
00053 
00054 
00055 bool CubicHermite::supportsCellTypePair(
00056   const CellType& maximalCellType,
00057   const CellType& cellType
00058   ) const
00059 {
00060   switch(maximalCellType)
00061   {
00062     case LineCell:
00063       switch(cellType)
00064       {
00065         case LineCell:
00066         case PointCell:
00067           return true;
00068         default:
00069           return false;
00070       }
00071     case TriangleCell:
00072       switch(cellType)
00073       {
00074         case TriangleCell:
00075         case LineCell:
00076         case PointCell:
00077           return true;
00078         default:
00079           return false;
00080       }
00081 //     case TetCell:
00082 //       switch(cellType)
00083 //       {
00084 //         case TetCell:
00085 //         case TriangleCell:
00086 //         case LineCell:
00087 //         case PointCell:
00088 //           return true;
00089 //         default:
00090 //           return false;
00091 //       }
00092     default:
00093       return false;
00094   }
00095 }
00096 
00097 void CubicHermite::print(std::ostream& os) const 
00098 {
00099   os << "CubicHermite";
00100 }
00101 
00102 int CubicHermite::nReferenceDOFsWithoutFacets(
00103   const CellType& maximalCellType,
00104   const CellType& cellType
00105   ) const
00106 {
00107   switch(maximalCellType)
00108   {
00109     case LineCell:
00110       switch(cellType)
00111       {
00112         case PointCell:
00113           return 2;
00114         case LineCell:
00115           return 0;
00116         default:
00117           TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument , "illegal combination of cell type and maximal cell type" );
00118           return -1;
00119       }
00120       break;
00121     case TriangleCell:
00122       switch(cellType)
00123       {
00124         case PointCell:
00125           return 3;
00126         case LineCell:
00127           return 0;
00128         case TriangleCell:
00129           return 1;
00130         default:
00131           TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument , "illegal combination of cell type and maximal cell type" );
00132           return -1;
00133       }
00134       break;
00135     default:
00136       TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument , "illegal combination of cell type and maximal cell type" );
00137       return -1;
00138   }
00139   
00140 }
00141 
00142 void CubicHermite::getReferenceDOFs(
00143   const CellType& maximalCellType,
00144   const CellType& cellType,
00145   Array<Array<Array<int> > >& dofs) const 
00146 {
00147   typedef Array<int> Aint;
00148   switch(cellType)
00149   {
00150     case PointCell:
00151     {
00152       dofs.resize(1);
00153       if (maximalCellType==LineCell)
00154         dofs[0] = tuple<Aint>(tuple(0,1));
00155       else if (maximalCellType==TriangleCell)
00156         dofs[0] = tuple<Aint>(tuple(0,1,2));
00157       else TEUCHOS_TEST_FOR_EXCEPT(1);
00158       return;
00159     }
00160     break;
00161     case LineCell:
00162     {
00163       dofs.resize(2);
00164       dofs[0].resize(2);
00165       if (maximalCellType==LineCell)
00166       {
00167         dofs[0][0].resize(2);
00168         dofs[0][0][0] = 0;
00169         dofs[0][0][1] = 1;
00170         dofs[0][1].resize(2);
00171         dofs[0][1][0] = 2;
00172         dofs[0][1][1] = 3;
00173       }
00174       else if (maximalCellType==TriangleCell)
00175       {
00176         dofs[0][0].resize(3);
00177         dofs[0][0][0] = 0;
00178         dofs[0][0][1] = 1;
00179         dofs[0][0][2] = 2;
00180         dofs[0][1].resize(3);
00181         dofs[0][1][0] = 3;
00182         dofs[0][1][1] = 4;
00183         dofs[0][1][1] = 5;
00184       }
00185       else
00186       {
00187         TEUCHOS_TEST_FOR_EXCEPT(1);
00188       }
00189       dofs[1].resize(1);
00190       dofs[1][0].resize(0);
00191       return;
00192     }
00193     break;
00194     case TriangleCell:
00195     {
00196       dofs.resize(3);
00197       dofs[0].resize(3);
00198       dofs[0][0] = tuple(0,1,2);
00199       dofs[0][1] = tuple(3,4,5);
00200       dofs[0][2] = tuple(6,7,8);
00201       dofs[1].resize(3);
00202       dofs[1][0].resize(0);
00203       dofs[1][1].resize(0);
00204       dofs[1][2].resize(0);
00205       dofs[2].resize(1);
00206       dofs[2][0].resize(1);
00207       dofs[2][0][0] = 9;
00208     }
00209     break;
00210     default:
00211       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00212         << cellType << " not implemented in CubicHermite basis");
00213   }
00214 }
00215 
00216 
00217 void CubicHermite::refEval(
00218   const CellType& cellType,
00219   const Array<Point>& pts,
00220   const SpatialDerivSpecifier& sds,
00221   Array<Array<Array<double> > >& result,
00222   int verbosity) const
00223 {
00224   TEUCHOS_TEST_FOR_EXCEPTION(!(sds.isPartial() || sds.isIdentity()), 
00225     std::runtime_error,
00226     "cannot evaluate spatial derivative " << sds << " on CubicHermite basis");
00227   const MultiIndex& deriv = sds.mi();
00228   typedef Array<double> Adouble;
00229   result.resize(1);
00230   result[0].resize(pts.length());
00231 
00232   switch(cellType)
00233   {
00234     case PointCell:
00235       result[0] = tuple<Adouble>(tuple(1.0));
00236       return;
00237     case LineCell:
00238       for (int i=0; i<pts.length(); i++)
00239       {
00240         evalOnLine(pts[i], deriv, result[0][i]);
00241       }
00242       return;
00243     case TriangleCell:
00244       for (int i=0; i<pts.length(); i++)
00245       {
00246         evalOnTriangle(pts[i], deriv, result[0][i]);
00247       }
00248       return;
00249     default:
00250       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00251         "CubicHermite::refEval() unimplemented for cell type "
00252         << cellType);
00253 
00254   }
00255 }
00256 
00257 /* ---------- evaluation on different cell types -------------- */
00258 
00259 void CubicHermite::evalOnLine(const Point& pt, 
00260   const MultiIndex& deriv,
00261   Array<double>& result) const
00262 {
00263   result.resize(4);
00264   ADReal x = ADReal(pt[0],0,1);
00265   Array<ADReal> tmp(4);
00266 
00267   tmp[0] = 1 + x * x * ( -3 + 2 * x );
00268   tmp[1] = x * ( 1 + (x - 2 ) * x );
00269   tmp[2] = ( 3 - 2*x ) * x * x;
00270   tmp[3] = (-1+x)*x*x;
00271 
00272   for (int i=0; i<tmp.length(); i++)
00273   {
00274     if (deriv.order()==0) 
00275     {
00276       result[i] = tmp[i].value();
00277     }
00278     else 
00279     {
00280       result[i] = tmp[i].gradient()[0];
00281     }
00282   }  
00283   return;
00284 }
00285 
00286 void CubicHermite::evalOnTriangle(const Point& pt, 
00287   const MultiIndex& deriv,
00288   Array<double>& result) const
00289 
00290 {
00291   result.resize(10);
00292   ADReal x = ADReal(pt[0], 0, 2);
00293   ADReal y = ADReal(pt[1], 1, 2);
00294   ADReal one(1.0, 2);
00295   
00296   Array<ADReal> tmp(10);
00297 
00298   SUNDANCE_OUT(this->verb() > 3, "x=" << x.value() << " y="
00299     << y.value());
00300  
00301   tmp[0] = 1 - 3*x*x + 2 * x*x*x - 13*x*y + 13*x*x*y - 3*y*y + 13 *x*y*y + 2 *y*y*y;
00302   tmp[1] = x - 2 *x*x + x*x*x - 3*x*y + 3*x*x*y + 2*x*y*y;
00303   tmp[2] = y - 3 *x *y + 2* x*x* y - 2* y*y + 3* x*y*y + y*y*y;
00304   tmp[3] = 3 * x*x - 2* x*x*x - 7* x* y + 7* x*x *y + 7* x*y*y;
00305   tmp[4] = -x*x + x*x*x + 2*x *y - 2* x*x* y - 2* x* y*y;
00306   tmp[5] = -x* y + 2* x*x* y + x* y*y;
00307   tmp[6] = -7* x* y + 7* x*x*y + 3* y*y + 7* x* y*y - 2* y*y*y;
00308   tmp[7] = -x *y + x*x* y + 2* x* y*y;
00309   tmp[8] = 2 *x *y - 2* x*x* y - y*y - 2* x* y*y + y*y*y;
00310   tmp[9] = 27* x *y - 27* x*x* y - 27* x* y*y;
00311 
00312   for (int i=0; i<tmp.length(); i++)
00313   {
00314     if (deriv.order()==0) result[i] = tmp[i].value();
00315     else 
00316       result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00317   }
00318 }
00319 
00320 void CubicHermite::evalOnTet(const Point& pt, 
00321   const MultiIndex& deriv,
00322   Array<double>& result) const
00323 {
00324   ADReal x = ADReal(pt[0], 0, 3);
00325   ADReal y = ADReal(pt[1], 1, 3);
00326   ADReal z = ADReal(pt[2], 2, 3);
00327   ADReal one(1.0, 3);
00328   
00329   TEUCHOS_TEST_FOR_EXCEPT(true);
00330 }
00331 
00332 void CubicHermite::preApplyTransformation( const CellType &maxCellType ,
00333              const Mesh &mesh, 
00334              const Array<int> &cellLIDs,
00335              const CellJacobianBatch& JVol,
00336              RCP<Array<double> >& A ) const
00337   {
00338     switch(maxCellType)
00339       {
00340       case TriangleCell:
00341   preApplyTransformationTriangle( mesh , cellLIDs, JVol , A );
00342   break;
00343       default:
00344   TEUCHOS_TEST_FOR_EXCEPT(1);
00345   break;
00346       }
00347     return;
00348   }
00349 
00350 void CubicHermite::postApplyTransformation( const CellType &maxCellType ,
00351               const Mesh &mesh, 
00352               const Array<int> &cellLIDs,
00353               const CellJacobianBatch& JVol,
00354               RCP<Array<double> >& A ) const
00355   {
00356     switch(maxCellType)
00357       {
00358       case TriangleCell:
00359   postApplyTransformationTriangle( mesh , cellLIDs, JVol , A );
00360   break;
00361       default:
00362   TEUCHOS_TEST_FOR_EXCEPT(1);
00363   break;
00364       }
00365     return;
00366   }
00367 
00368 void CubicHermite::preApplyTransformationTranspose( const CellType &maxCellType ,
00369                 const Mesh &mesh, 
00370                 const Array<int> &cellLIDs,
00371                 const CellJacobianBatch& JVol ,
00372                 Array<double> & A ) const
00373 {
00374   switch(maxCellType)
00375     {
00376     case TriangleCell:
00377       preApplyTransformationTransposeTriangle( mesh , cellLIDs, JVol , A );
00378       break;
00379     default:
00380       TEUCHOS_TEST_FOR_EXCEPT(1);
00381       break;
00382     }
00383   return;
00384 }
00385 
00386 
00387 void CubicHermite::preApplyTransformationTriangle( const Mesh &mesh, 
00388                const Array<int> &cellLIDs,
00389                const CellJacobianBatch& JVol,
00390                RCP<Array<double> >& A) const
00391 {
00392   Array<double> &Anoptr = *A;
00393   
00394   Array<double> cellVertH;
00395   getVertexH( mesh , cellLIDs , cellVertH );
00396   
00397   
00398   // this applies M from the left on each cell
00399   // A for each cell has 10 rows because it is Hermite
00400   // so, this gives the number of columns per cell
00401   const int numCols = Anoptr.size() / JVol.numCells() / 10;
00402   
00403   for (int i=0;i<JVol.numCells();i++) 
00404     {
00405       const int cell_start = i * numCols * 10;
00406       const double *invJ = JVol.jVals(i);
00407       
00408       for (int j=0;j<numCols;j++) 
00409   {
00410     const int col_start = cell_start + 10 * j;
00411     const double a1 = Anoptr[col_start + 1];
00412     const double a2 = Anoptr[col_start + 2];
00413     const double a4 = Anoptr[col_start + 4];
00414     const double a5 = Anoptr[col_start + 5];
00415     const double a7 = Anoptr[col_start + 7];
00416     const double a8 = Anoptr[col_start + 8];
00417     Anoptr[col_start+1] = (invJ[0]*a1 + invJ[1]*a2)/cellVertH[3*i];
00418     Anoptr[col_start+2] = (invJ[2]*a1 + invJ[3]*a2)/cellVertH[3*i];
00419     Anoptr[col_start+4] = (invJ[0]*a4 + invJ[1]*a5)/cellVertH[3*i+1];
00420     Anoptr[col_start+5] = (invJ[2]*a4 + invJ[3]*a5)/cellVertH[3*i+1];
00421     Anoptr[col_start+7] = (invJ[0]*a7 + invJ[1]*a8)/cellVertH[3*i+2];
00422     Anoptr[col_start+8] = (invJ[2]*a7 + invJ[3]*a8)/cellVertH[3*i+2];
00423   }
00424     }
00425   
00426 }
00427 
00428 void CubicHermite::postApplyTransformationTriangle( const Mesh &mesh,
00429                 const Array<int> &cellLIDs , 
00430                 const CellJacobianBatch& JVol,
00431                 RCP<Array<double> >& A ) const
00432 {
00433   Array<double> &Anoptr = *A;
00434   
00435   Array<double> cellVertH;
00436   getVertexH( mesh , cellLIDs , cellVertH );
00437   
00438   
00439   const int numRows = Anoptr.size() / 10 / JVol.numCells();
00440   
00441   for (int i=0;i<JVol.numCells();i++) 
00442     {
00443       const double *invJ = JVol.jVals(i);
00444       
00445       const int cell_start = i * numRows * 10;
00446       // handle columns 1 and 2
00447       for (int j=0;j<numRows;j++) 
00448   {
00449     const double a = Anoptr[cell_start + numRows + j];
00450     const double b = Anoptr[cell_start + 2*numRows + j];
00451     Anoptr[cell_start + numRows + j] = (invJ[0] * a + invJ[1] * b)/cellVertH[3*i];
00452     Anoptr[cell_start + 2*numRows + j] = (invJ[2] * a + invJ[3] * b)/cellVertH[3*i];
00453   }
00454       
00455       // handle columns 4 and 5
00456       for (int j=0;j<numRows;j++) 
00457   {
00458     const double a = Anoptr[cell_start + 4*numRows + j];
00459     const double b = Anoptr[cell_start + 5*numRows + j];
00460     Anoptr[cell_start + 4*numRows + j] = (invJ[0] * a + invJ[1] * b)/cellVertH[3*i+1];
00461     Anoptr[cell_start + 5*numRows + j] = (invJ[2] * a + invJ[3] * b)/cellVertH[3*i+1];
00462   }
00463       
00464       // handle columns 7 and 8
00465       for (int j=0;j<numRows;j++) 
00466   {
00467     const double a = Anoptr[cell_start + 7*numRows + j];
00468     const double b = Anoptr[cell_start + 8*numRows + j];
00469     Anoptr[cell_start + 7*numRows + j] = (invJ[0] * a + invJ[1] * b)/cellVertH[3*i+2];
00470     Anoptr[cell_start + 8*numRows + j] = (invJ[2] * a + invJ[3] * b)/cellVertH[3*i+2];
00471   }
00472       
00473     }
00474   
00475   return;
00476 }
00477 
00478 void CubicHermite::preApplyTransformationTransposeTriangle( const Mesh &mesh,
00479                   const Array<int> &cellLIDs,
00480                   const CellJacobianBatch& JVol,
00481                   Array<double>& A ) const
00482 {
00483   // this applies M from the left on each cell
00484   // A for each cell has 10 rows because it is Hermite
00485   // so, this gives the number of columns per cell
00486   const int numCols = A.size() / JVol.numCells() / 10;
00487   
00488   
00489   Array<double> cellVertH;
00490   getVertexH( mesh , cellLIDs , cellVertH );
00491   
00492   for (int i=0;i<JVol.numCells();i++) 
00493     {
00494       const int cell_start = i * numCols * 10;
00495       const double *invJ = JVol.jVals(i);
00496       
00497       for (int j=0;j<numCols;j++) 
00498   {
00499     const int col_start = cell_start + 10 * j;
00500     const double a1 = A[col_start + 1];
00501     const double a2 = A[col_start + 2];
00502     const double a4 = A[col_start + 4];
00503     const double a5 = A[col_start + 5];
00504     const double a7 = A[col_start + 7];
00505     const double a8 = A[col_start + 8];
00506     A[col_start+1] = (invJ[0]*a1 + invJ[2]*a2)/cellVertH[3*i];
00507     A[col_start+2] = (invJ[1]*a1 + invJ[3]*a2)/cellVertH[3*i];
00508     A[col_start+4] = (invJ[0]*a4 + invJ[2]*a5)/cellVertH[3*i+1];
00509     A[col_start+5] = (invJ[1]*a4 + invJ[3]*a5)/cellVertH[3*i+1];
00510     A[col_start+7] = (invJ[0]*a7 + invJ[2]*a8)/cellVertH[3*i+2];
00511     A[col_start+8] = (invJ[1]*a7 + invJ[3]*a8)/cellVertH[3*i+2];
00512   }
00513     }
00514   
00515 }
00516 
00517 // cellVertexH is 3 * cellLIDs.size and has the appropriate h for each
00518 // vertex of each cell
00519 void CubicHermite::getVertexH( const Mesh &mesh, 
00520              const Array<int> &cellLIDs ,
00521              Array<double> &cellVertexH ) const
00522 {
00523   cellVertexH.resize(3*cellLIDs.size());
00524   const int N = mesh.numCells(2);
00525   const double h = 1.0 / sqrtl( N );
00526   for (int i=0;i<cellVertexH.size();i++) 
00527     {
00528       cellVertexH[i] = h;
00529     }
00530 //     // now I get the vertices that are included in the batch of cells
00531 
00532 
00533 //     map<int,double> vert_h;
00534 
00535 //     Array<int> cellVertLIDs(3);
00536 //     Array<int> vertOrient(3);
00537 //     const int cellDim = mesh.spatialDim();
00538 //     // set up map structure
00539 //     for (int i=0;i<cellLIDs.size();i++) 
00540 //       {
00541 //  const int cellLID = cellLIDs[i];
00542 //  mesh.getFacetArray( cellDim , cellLID , 0 , cellVertLIDs , vertOrient );
00543 //  for (int j=0;j<3;j++)
00544 //    {
00545 //      map<int,double>::iterator vert_h_cur = vert_h.find(cellVertLIDs[j]);
00546 //      if (vert_h_cur == vert_h.end())
00547 //        {
00548 //    vert_h[cellVertLIDs[j]] = 0.0;
00549 //        }
00550 //    }
00551 //       }
00552     
00553 //     // fill in numbers
00554 //     for (map<int,double>::iterator it=vert_h.begin();it!=vert_h.end();++it)
00555 //       {
00556 //  const int vert = it->first;
00557 //  it->second = 0.0;
00558 //  // loop over maximal cofacets of each vertex
00559 //  Array<int> incident_cells;
00560 //  Array<double> cell_diams;
00561 //  mesh.getCofacets( 0 , vert , cellDim , incident_cells );
00562 //  mesh.getCellDiameters( 2 , incident_cells , cell_diams );
00563 //  for (int i=0;i<cell_diams.size();i++) 
00564 //    {
00565 //      it->second += cell_diams[i];
00566 //    }
00567 //  it->second /= cell_diams.size();
00568 
00569 //       }
00570 
00571 //     cellVertexH.resize( 3 * cellLIDs.size() );
00572 
00573 //     for (int i=0;i<cellLIDs.size();i++) 
00574 //       {
00575 //  const int cellLID = cellLIDs[i];
00576 //  mesh.getFacetArray( cellDim , cellLID , 0 , cellVertLIDs , vertOrient );
00577 //  for (int j=0;j<3;j++) 
00578 //    {
00579 //      cellVertexH[3*i+j] = 1./vert_h[cellVertLIDs[j]];
00580 //    }
00581 //       }
00582 
00583 
00584 
00585 
00586     return;
00587 
00588 }

Site Contact