SundanceBernstein.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceBernstein.hpp"
00032 #include "SundanceADReal.hpp"
00033 #include "PlayaExceptions.hpp"
00034 #include "SundanceSpatialDerivSpecifier.hpp"
00035 #include "SundancePoint.hpp"
00036 #include "SundanceObjectWithVerbosity.hpp"
00037 #include "SundanceOut.hpp"
00038 
00039 using namespace Sundance;
00040 using namespace Teuchos;
00041 
00042 
00043 Bernstein::Bernstein(int order)
00044   : order_(order)
00045 {
00046   TEUCHOS_TEST_FOR_EXCEPTION(order < 0, std::runtime_error,
00047     "invalid polynomial order=" << order
00048     << " in Bernstein ctor");
00049 }
00050 
00051 bool Bernstein::supportsCellTypePair(
00052   const CellType& maximalCellType,
00053   const CellType& cellType
00054   ) const
00055 {
00056   switch(maximalCellType)
00057   {
00058     case LineCell:
00059       switch(cellType)
00060       {
00061         case LineCell:
00062         case PointCell:
00063           return true;
00064         default:
00065           return false;
00066       }
00067     case TriangleCell:
00068       switch(cellType)
00069       {
00070         case TriangleCell:
00071         case LineCell:
00072         case PointCell:
00073           return true;
00074         default:
00075           return false;
00076       }
00077     case TetCell:
00078       switch(cellType)
00079       {
00080         case TetCell:
00081         case TriangleCell:
00082         case LineCell:
00083         case PointCell:
00084           return true;
00085         default:
00086           return false;
00087       }
00088     default:
00089       return false;
00090   }
00091 }
00092 
00093 void Bernstein::print(std::ostream& os) const 
00094 {
00095   os << "Bernstein(" << order_ << ")";
00096 }
00097 
00098 int Bernstein::nReferenceDOFsWithoutFacets(
00099   const CellType& maximalCellType,
00100   const CellType& cellType
00101   ) const
00102 {
00103   if (order_==0)
00104   {
00105     if (maximalCellType != cellType) return 0;
00106     return 1;
00107   }
00108 
00109   switch(cellType)
00110   {
00111     case PointCell:
00112       return 1;
00113     case LineCell:
00114       return order_-1;
00115     case TriangleCell:
00116       if (order_ < 3) return 0;
00117       if (order_ >= 3) return (order_-1)*(order_-2)/2;
00118       break;
00119     case QuadCell:
00120       if (order_==1) return 0;
00121       if (order_==2) return 1;
00122       TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error, 
00123         "Bernstein order > 2 not implemented "
00124         "for quad cells");
00125     case TetCell:
00126       if (order_<=2) return 0;
00127       TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error, 
00128         "Bernstein order > 2 not implemented "
00129         "for tet cells");
00130     case BrickCell:
00131       if (order_<=1) return 0;
00132       if (order_==2) return 1;
00133       TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error, 
00134         "Bernstein order > 2 not implemented "
00135         "for brick cells");
00136     default:
00137       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00138         << cellType << " not implemented in Bernstein basis");
00139       return -1; // -Wall
00140   }
00141   return -1; // -Wall
00142 }
00143 
00144 void Bernstein::getReferenceDOFs(
00145   const CellType& maximalCellType,
00146   const CellType& cellType,
00147   Array<Array<Array<int> > >& dofs) const 
00148 {
00149   const int N=(order()+1)*(order()+2)/2;
00150   typedef Array<int> Aint;
00151   switch(cellType)
00152   {
00153     case PointCell:
00154       dofs.resize(1);
00155       dofs[0] = tuple<Aint>(tuple(0));
00156       return;
00157     case LineCell:
00158       dofs.resize(2);
00159       dofs[0] = tuple<Aint>(tuple(0), tuple(order()));
00160       dofs[1] = tuple<Aint>(makeRange(1, order()-1));
00161       return;
00162     case TriangleCell:
00163     {
00164       dofs.resize(3);
00165       dofs[0] = tuple<Aint>(tuple(0),tuple(N-order()-1),tuple(N-1));
00166       if (order()>1)
00167       {
00168         // order() - 1 dof per edge
00169         Aint dof0(order()-1);
00170         Aint dof1; // will fill in with range
00171         Aint dof2(order()-1);
00172 
00173         // first edge (from vertex 0 to 1
00174         int inc = 2;
00175         dof0[0] = 1;
00176         for (int i=1;i<order()-1;i++) 
00177         {
00178           dof0[i] = dof0[i-1]+inc;
00179           inc++;
00180         }
00181 
00182         // second edge runs from vertex 1 to 2
00183         dof1 = makeRange(N-order(),N-2);
00184 
00185         // third edge runs from vertex 2 to vertex 0
00186         inc = 3;
00187         dof2[order()-2] = 2;
00188         for (int i=order()-3;i>=0;i--)
00189         {
00190           dof2[i] = dof2[i+1]+inc;
00191           inc++;
00192         }
00193         /** permuted from (0,1,2) to (1,2,0) for UFC ordering */
00194         dofs[1] = tuple<Aint>(dof1,dof2,dof0);
00195       }
00196       else
00197       {
00198         dofs[1] = tuple(Array<int>());
00199       }
00200       if (order()>2)
00201       {
00202         Array<int> internaldofs;
00203         int bfcur = 0;
00204         //int internalbfcur=0; // Commented out unused variable -- KL
00205         for (int alpha1=order();alpha1>=0;alpha1--)
00206         {
00207           for (int alpha2=order()-alpha1;alpha2>=0;alpha2--)
00208           {
00209             int alpha3 = order()-alpha1-alpha2;
00210             if (alpha1*alpha2*alpha3>0) {
00211               internaldofs.append(bfcur);
00212             }
00213             bfcur++;
00214           }
00215         }
00216         dofs[2] = tuple(internaldofs);
00217       }
00218       else
00219       {
00220         dofs[2] = tuple(Array<int>());
00221       }
00222       return;
00223     }
00224     case TetCell:
00225     {
00226     }
00227     default:
00228       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00229         << cellType << " not implemented in Bernstein basis");
00230   }
00231 }
00232 
00233 
00234 
00235 Array<int> Bernstein::makeRange(int low, int high)
00236 {
00237   if (high < low) return Array<int>();
00238 
00239   Array<int> rtn(high-low+1);
00240   for (int i=0; i<rtn.length(); i++) rtn[i] = low+i;
00241   return rtn;
00242 }
00243 
00244 void Bernstein::refEval(
00245   const CellType& cellType,
00246   const Array<Point>& pts,
00247   const SpatialDerivSpecifier& sds,
00248   Array<Array<Array<double> > >& result,
00249   int verbosity) const
00250 {
00251   TEUCHOS_TEST_FOR_EXCEPTION(!(sds.isPartial() || sds.isIdentity()), 
00252     std::runtime_error,
00253     "cannot evaluate spatial derivative " << sds << " on Bernstein basis");
00254   const MultiIndex& deriv = sds.mi();
00255   typedef Array<double> Adouble;
00256   result.resize(1);
00257   result[0].resize(pts.length());
00258 
00259   switch(cellType)
00260   {
00261     case PointCell:
00262       result[0] = tuple<Adouble>(tuple(1.0));
00263       return;
00264     case LineCell:
00265       for (int i=0; i<pts.length(); i++)
00266       {
00267         evalOnLine(pts[i], deriv, result[0][i]);
00268       }
00269       return;
00270     case TriangleCell:
00271       for (int i=0; i<pts.length(); i++)
00272       {
00273         evalOnTriangle(pts[i], deriv, result[0][i]);
00274       }
00275       return;
00276     case TetCell:
00277       for (int i=0; i<pts.length(); i++)
00278       {
00279         evalOnTet(pts[i], deriv, result[0][i]);
00280       }
00281       return;
00282     default:
00283       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00284         "Bernstein::refEval() unimplemented for cell type "
00285         << cellType);
00286 
00287   }
00288 }
00289 
00290 /* ---------- evaluation on different cell types -------------- */
00291 
00292 void Bernstein::evalOnLine(const Point& pt, 
00293   const MultiIndex& deriv,
00294   Array<double>& result) const
00295 {
00296   ADReal x = ADReal(pt[0], 0, 1);
00297   ADReal one(1.0, 1);
00298   
00299   result.resize(order()+1);
00300   Array<ADReal> tmp(result.length());
00301   Array<double> x0(order()+1);
00302   
00303   if (order_ == 0)
00304   {
00305     tmp[0] = one;
00306   }
00307   else
00308   {
00309     double binom_cur = 1.0;
00310     for (int i=0; i<=order_; i++)
00311     {
00312       tmp[i] = one;
00313 
00314       for (int j=0;j<order_-i;j++) 
00315       {
00316         tmp[i] *= (1-x);
00317       }
00318       for (int j=0;j<i;j++) 
00319       {
00320         tmp[i] *= x;
00321       }
00322       tmp[i] *= binom_cur;
00323       binom_cur *= double(order()-i) / double(i+1);
00324     }
00325   }
00326   
00327   for (int i=0; i<tmp.length(); i++)
00328   {
00329     if (deriv.order()==0) result[i] = tmp[i].value();
00330     else result[i] = tmp[i].gradient()[0];
00331   }
00332 }
00333 
00334 void Bernstein::evalOnTriangle(const Point& pt, 
00335   const MultiIndex& deriv,
00336   Array<double>& result) const
00337 
00338 {
00339   ADReal x = ADReal(pt[0], 0, 2);
00340   ADReal y = ADReal(pt[1], 1, 2);
00341   ADReal one(1.0, 2);
00342   
00343   Array<ADReal> tmp;
00344 
00345   SUNDANCE_OUT(this->verb() > 3, "x=" << x.value() << " y="
00346     << y.value());
00347  
00348   if(order_==0) {
00349     result.resize(1);
00350     tmp.resize(1);
00351     tmp[0] = one;
00352   }
00353   else {
00354     int N = (order()+1)*(order()+2)/2;
00355     result.resize(N);
00356     tmp.resize(N);
00357     // these are the barycentric coordinates
00358     ADReal b1 = 1.0 - x - y;
00359     ADReal b2 = x;
00360     ADReal b3 = y;
00361 
00362     // will hold \binom{n}{\alpha_1}
00363     int bfcur = 0;
00364 
00365     for (int alpha1=order();alpha1>=0;alpha1--) 
00366     {
00367       for (int alpha2 = order()-alpha1;alpha2>=0;alpha2--)
00368       {
00369         int alpha3 = order() - alpha1 - alpha2;
00370         tmp[bfcur] = one;
00371         for (int i=0;i<alpha1;i++)
00372         {
00373           tmp[bfcur] *= b1;
00374         }
00375         for (int i=0;i<alpha2;i++) 
00376         {
00377           tmp[bfcur] *= b2;
00378         }
00379         for (int i=0;i<alpha3;i++)
00380         {
00381           tmp[bfcur] *= b3;
00382         }
00383         for (int i=2;i<=order();i++)
00384         {
00385           tmp[bfcur] *= (double) i;
00386         }
00387         for (int i=2;i<=alpha1;i++) 
00388         {
00389           tmp[bfcur] /= (double) i;
00390         }
00391         for (int i=2;i<=alpha2;i++) 
00392         {
00393           tmp[bfcur] /= (double) i;
00394         }
00395         for (int i=2;i<=alpha3;i++) 
00396         {
00397           tmp[bfcur] /= (double) i;
00398         }
00399         bfcur++;
00400       }
00401     }
00402   }
00403 
00404   for (int i=0; i<tmp.length(); i++)
00405   {
00406     if (deriv.order()==0) result[i] = tmp[i].value();
00407     else 
00408       result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00409   }
00410 }
00411 
00412 void Bernstein::evalOnTet(const Point& pt, 
00413   const MultiIndex& deriv,
00414   Array<double>& result) const
00415 {
00416   ADReal x = ADReal(pt[0], 0, 3);
00417   ADReal y = ADReal(pt[1], 1, 3);
00418   ADReal z = ADReal(pt[2], 2, 3);
00419   ADReal one(1.0, 3);
00420   
00421   Array<ADReal> tmp(result.length());
00422 
00423   if(order_==0)
00424   {
00425     tmp.resize(1);
00426     result.resize(1);
00427     tmp[0] = one;
00428   }
00429   else
00430   {
00431   }
00432 
00433   for (int i=0; i<tmp.length(); i++)
00434   {
00435     if (deriv.order()==0) result[i] = tmp[i].value();
00436     else 
00437       result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00438   }
00439 }
00440 
00441 
00442 
00443 

Site Contact