SundanceLegendre.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 "SundanceLegendre.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 // ctor
00054 Legendre::Legendre(int order):order_(order)
00055 {
00056 
00057   // set the nr DOFs
00058 
00059   if (order_ > 1) nrDOF_edge_ = order_ - 1;
00060   else nrDOF_edge_ = 0;
00061 
00062   if (order_ > 3) nrDOF_face_ = ((order_-2)*(order_-3))/2;
00063   else nrDOF_face_ = 0;
00064 
00065   nrDOF_brick_ = 0;
00066 
00067   //SUNDANCE_OUT( true , "Legendre ctor nrDOF_edge_:" << nrDOF_edge_ << " , nrDOF_face_:" << nrDOF_face_ << " , nrDOF_brick_:"<<nrDOF_brick_);
00068 }
00069 
00070 bool Legendre::supportsCellTypePair(
00071   const CellType& maximalCellType,
00072   const CellType& cellType
00073   ) const
00074 {
00075   switch(maximalCellType)
00076   {
00077     case LineCell:
00078       switch(cellType)
00079       {
00080         case LineCell:
00081         case PointCell:
00082           return true;
00083         default:
00084           return false;
00085       }
00086     case QuadCell:
00087       switch(cellType)
00088       {
00089         case QuadCell:
00090         case LineCell:
00091         case PointCell:
00092           return true;
00093         default:
00094           return false;
00095       }
00096      case BrickCell:
00097        switch(cellType)
00098        {
00099          case BrickCell:
00100          case QuadCell:
00101          case LineCell:
00102          case PointCell:
00103            return true;
00104          default:
00105            return false;
00106       }
00107     default:
00108       return false;
00109   }
00110 }
00111 
00112 void Legendre::print(std::ostream& os) const
00113 {
00114   os << "Legendre";
00115 }
00116 
00117 int Legendre::nReferenceDOFsWithoutFacets(
00118   const CellType& maximalCellType,
00119   const CellType& cellType
00120   ) const
00121 {
00122       switch(cellType)
00123       {
00124         case PointCell:
00125           return 1;
00126         case LineCell:
00127           return nrDOF_edge_;
00128         case QuadCell:
00129             return nrDOF_face_;
00130         case BrickCell:
00131             return nrDOF_brick_;
00132         default:
00133             TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument , "illegal combination of cell type and maximal cell type" );
00134             return -1;
00135       }
00136 }
00137 
00138 Array<int> Legendre::makeRange(int low, int high)
00139 {
00140   if (high < low) return Array<int>();
00141 
00142   Array<int> rtn(high-low+1);
00143   for (int i=0; i<rtn.length(); i++) rtn[i] = low+i;
00144   return rtn;
00145 }
00146 
00147 void Legendre::getReferenceDOFs(
00148   const CellType& maximalCellType,
00149   const CellType& cellType,
00150   Array<Array<Array<int> > >& dofs) const 
00151 {
00152 
00153   typedef Array<int> Aint;
00154 
00155   //switch(order_)
00156 
00157   switch(cellType)
00158   {
00159     case PointCell:
00160     {
00161         dofs.resize(1);
00162         dofs[0] = tuple<Aint>(tuple(0));
00163         return;
00164     }
00165     break;
00166     case LineCell:
00167     {
00168         dofs.resize(2);
00169         dofs[0] = tuple<Aint>(tuple(0), tuple(1));
00170         if (nrDOF_edge_>0)
00171         {
00172           dofs[1] = tuple<Aint>(makeRange(2, 2+nrDOF_edge_-1));
00173         }
00174         else
00175         {
00176           dofs[1] = tuple(Array<int>());
00177         }
00178       return;
00179     }
00180     break;
00181     case QuadCell:
00182     {
00183       int offs = 0;
00184         dofs.resize(3);
00185         // dofs[0] are DOFs at Points
00186         dofs[0] = tuple<Aint>(tuple(0), tuple(1), tuple(2), tuple(3));
00187         offs = 4;
00188         if (nrDOF_edge_>0)
00189         {
00190           dofs[1].resize(4);
00191           dofs[1][0] = makeRange(offs, offs+nrDOF_edge_-1);  offs += nrDOF_edge_;
00192           dofs[1][1] = makeRange(offs, offs+nrDOF_edge_-1);  offs += nrDOF_edge_;
00193           dofs[1][2] = makeRange(offs, offs+nrDOF_edge_-1);  offs += nrDOF_edge_;
00194           dofs[1][3] = makeRange(offs, offs+nrDOF_edge_-1);  offs += nrDOF_edge_;
00195         }
00196         else
00197         {
00198           dofs[1] = tuple(Array<int>(), Array<int>(),
00199                    Array<int>(), Array<int>());
00200         }
00201 
00202         if (nrDOF_edge_>0)
00203         {
00204           dofs[2].resize(1);
00205           dofs[2][0] = makeRange(offs, offs+nrDOF_face_-1);  offs += nrDOF_face_;
00206         }
00207         else
00208         {
00209           dofs[2] = tuple(Array<int>());
00210         }
00211         //SUNDANCE_OUT( true , "Legendre::getReferenceDOFs offs:" << offs );
00212     }
00213     break;
00214     default:
00215       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00216         << cellType << " not implemented in Legendre basis");
00217   }
00218 }
00219 
00220 
00221 void Legendre::refEval(
00222   const CellType& cellType,
00223   const Array<Point>& pts,
00224   const SpatialDerivSpecifier& sds,
00225   Array<Array<Array<double> > >& result,
00226   int verbosity) const
00227 {
00228   TEUCHOS_TEST_FOR_EXCEPTION(!(sds.isPartial() || sds.isIdentity()), 
00229     std::runtime_error,
00230     "cannot evaluate spatial derivative " << sds << " on Legendre basis");
00231   const MultiIndex& deriv = sds.mi();
00232   typedef Array<double> Adouble;
00233   result.resize(1);
00234   result[0].resize(pts.length());
00235 
00236   switch(cellType)
00237   {
00238     case PointCell:
00239       result[0] = tuple<Adouble>(tuple(1.0));
00240       return;
00241     case LineCell:
00242       for (int i=0; i<pts.length(); i++)
00243       {
00244         evalOnLine(pts[i], deriv, result[0][i]);
00245       }
00246       return;
00247     case QuadCell:
00248       for (int i=0; i<pts.length(); i++)
00249       {
00250         evalOnQuad(pts[i], deriv, result[0][i]);
00251       }
00252       return;
00253     case BrickCell:
00254       for (int i=0; i<pts.length(); i++)
00255       {
00256         evalOnBrick(pts[i], deriv, result[0][i]);
00257       }
00258       return;
00259     default:
00260       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00261         "Legendre::refEval() unimplemented for cell type "
00262         << cellType);
00263 
00264   }
00265 }
00266 
00267 /* ---------- evaluation on different cell types -------------- */
00268 
00269 void Legendre::evalOnLine(const Point& pt,
00270   const MultiIndex& deriv,
00271   Array<double>& result) const
00272 {
00273   result.resize(2+nrDOF_edge_);
00274   ADReal x = ADReal(pt[0],0,1);
00275 
00276   Array<ADReal> refAll(7);
00277 
00278   refAll[0] = 1-x;
00279   refAll[1] = x;
00280   refAll[2] = 2.44948974278318 * ( (2*x-1)*(2*x-1) - 1 ) / 4;
00281   refAll[3] = 3.16227766016838 * ( (2*x-1)*(2*x-1) - 1 ) * (2*x-1) / 4;
00282   refAll[4] = 3.74165738677394 * ( 5*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) - 6*(2*x-1)*(2*x-1) + 1) / 16;
00283   refAll[5] = 4.24264068711929 * (2*x-1) * (7*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) - 10*(2*x-1)*(2*x-1) + 3) / 16;
00284   refAll[6] = 4.69041575982343 * (21*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) -
00285                               35*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) + 15*(2*x-1)*(2*x-1) - 1) / 32;
00286 
00287 
00288   for (int i=0; i<result.length(); i++)
00289   {
00290     if (deriv.order()==0) 
00291     {
00292       result[i] = refAll[i].value();
00293     }
00294     else 
00295     {
00296       result[i] = refAll[i].gradient()[0];
00297     }
00298   }  
00299   //SUNDANCE_OUT( true , "Legendre::evalOnLine result.length():" << result.length() );
00300   return;
00301 }
00302 
00303 void Legendre::evalOnQuad(const Point& pt,
00304   const MultiIndex& deriv,
00305   Array<double>& result) const
00306 
00307 {
00308   result.resize( 4 + 4*nrDOF_edge_ + nrDOF_face_);
00309   ADReal x = ADReal(pt[0], 0, 2);
00310   ADReal y = ADReal(pt[1], 1, 2);
00311   ADReal one(1.0, 2);
00312   
00313   Array<ADReal> refAllx(7);
00314   Array<ADReal> refAlly(7);
00315 
00316   refAllx[0] = 1-x;
00317   refAllx[1] = x;
00318   refAllx[2] = 2.44948974278318 * ( (2*x-1)*(2*x-1) - 1 ) / 4;
00319   refAllx[3] = 3.16227766016838 * ( (2*x-1)*(2*x-1) - 1 ) * (2*x-1) / 4;
00320   refAllx[4] = 3.74165738677394 * ( 5*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) - 6*(2*x-1)*(2*x-1) + 1) / 16;
00321   refAllx[5] = 4.24264068711929 * (2*x-1) * (7*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) - 10*(2*x-1)*(2*x-1) + 3) / 16;
00322   refAllx[6] = 4.69041575982343 * (21*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) -
00323                               35*(2*x-1)*(2*x-1)*(2*x-1)*(2*x-1) + 15*(2*x-1)*(2*x-1) - 1) / 32;
00324 
00325   refAlly[0] = 1-y;
00326   refAlly[1] = y;
00327   refAlly[2] = 2.44948974278318 * ( (2*y-1)*(2*y-1) - 1 ) / 4;
00328   refAlly[3] = 3.16227766016838 * ( (2*y-1)*(2*y-1) - 1 ) * (2*y-1) / 4;
00329   refAlly[4] = 3.74165738677394 * ( 5*(2*y-1)*(2*y-1)*(2*y-1)*(2*y-1) - 6*(2*y-1)*(2*y-1) + 1) / 16;
00330   refAlly[5] = 4.24264068711929 * (2*y-1) * (7*(2*y-1)*(2*y-1)*(2*y-1)*(2*y-1) - 10*(2*y-1)*(2*y-1) + 3) / 16;
00331   refAlly[6] = 4.69041575982343 * (21*(2*y-1)*(2*y-1)*(2*y-1)*(2*y-1)*(2*y-1) -
00332                               35*(2*y-1)*(2*y-1)*(2*y-1)*(2*y-1) + 15*(2*y-1)*(2*y-1) - 1) / 32;
00333 
00334   SUNDANCE_OUT(this->verb() > 3, "x=" << x.value() << " y="
00335     << y.value());
00336 
00337   int sideIndex[4][2] = { {0,0} , {1,0} , {0,1} , {1,1}};
00338   int edgeIndex[4]    = { 0 , 1 , 1 , 0};
00339   int edgeMultI[4]    = { 0 , 0 , 1 , 1};
00340   int offs = 0;
00341   Array<ADReal> tmp(4 + 4*nrDOF_edge_ + nrDOF_face_);
00342 
00343   // loop over vertexes
00344   for (int i=0; i < 4 ; i++, offs++){
00345     tmp[offs] = refAllx[sideIndex[i][0]] * refAlly[sideIndex[i][1]];
00346   }
00347 
00348   // loop over edges
00349   for (int i=0; i < 4 ; i++){
00350     // loop over each DOF on the edge
00351     if (edgeIndex[i] == 0){
00352       for (int j = 0 ; j < nrDOF_edge_ ; j++ , offs++){
00353         tmp[offs] = refAllx[2+j] * refAlly[edgeMultI[i]];
00354       }
00355     }
00356     else
00357     {
00358       for (int j = 0 ; j < nrDOF_edge_ ; j++ , offs++){
00359         tmp[offs] = refAllx[edgeMultI[i]] * refAlly[2+j];
00360       }
00361     }
00362   }
00363 
00364   // loop over all internal DOFs
00365   if ( nrDOF_face_ > 0 ){
00366     // loop for each hierarchical layer
00367     for (int hierarch = 0 ; hierarch < order_ - 3 ; hierarch++)
00368     {
00369       //SUNDANCE_OUT( true , "Legendre::evalOnQuad hierarch:" << hierarch );
00370       // for each layer add the basis function
00371       for (int i=0 ; i < hierarch+1 ; i++ , offs++)
00372       {
00373         //SUNDANCE_OUT( true , "Legendre::evalOnQuad offs:" << offs << " 2+i:" << 2+i << " , 2+(hierarch-1-i):" << 2+(hierarch-i));
00374         tmp[offs] = refAllx[2+i] * refAlly[2+(hierarch-i)];
00375       }
00376     }
00377   }
00378 
00379   // compute the results
00380   for (int i=0; i<result.length(); i++)
00381   {
00382     if (deriv.order()==0) result[i] = tmp[i].value();
00383     else 
00384       result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00385   }
00386   //SUNDANCE_OUT( true , "Legendre::evalOnQuad result.length():" << result.length() );
00387 }
00388 
00389 void Legendre::evalOnBrick(const Point& pt,
00390   const MultiIndex& deriv,
00391   Array<double>& result) const
00392 {
00393   ADReal x = ADReal(pt[0], 0, 3);
00394   ADReal y = ADReal(pt[1], 1, 3);
00395   ADReal z = ADReal(pt[2], 2, 3);
00396   ADReal one(1.0, 3);
00397   
00398   TEUCHOS_TEST_FOR_EXCEPT(true);
00399 }

Site Contact