SundanceLagrange.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 "SundanceLagrange.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 Sundance;
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054 
00055 
00056 Lagrange::Lagrange(int order)
00057   : order_(order) , doFInfromationCalculated_(false)
00058 {
00059 TEUCHOS_TEST_FOR_EXCEPTION(order < 0, std::runtime_error,
00060                      "invalid polynomial order=" << order
00061                      << " in Lagrange ctor");
00062 }
00063 
00064 bool Lagrange::supportsCellTypePair(
00065   const CellType& maximalCellType,
00066   const CellType& cellType
00067   ) const
00068 {
00069   switch(maximalCellType)
00070   {
00071     case LineCell:
00072       switch(cellType)
00073       {
00074         case LineCell:
00075         case PointCell:
00076           return true;
00077         default:
00078           return false;
00079       }
00080     case TriangleCell:
00081       switch(cellType)
00082       {
00083         case TriangleCell:
00084         case LineCell:
00085         case PointCell:
00086           return true;
00087         default:
00088           return false;
00089       }
00090     case QuadCell:
00091         switch(cellType){
00092           case QuadCell:
00093           case LineCell:
00094           case PointCell:
00095              return true;
00096           default:
00097              return false;
00098         }
00099     case TetCell:
00100       switch(cellType)
00101       {
00102         case TetCell:
00103         case TriangleCell:
00104         case LineCell:
00105         case PointCell:
00106           return true;
00107         default:
00108           return false;
00109       }
00110     case BrickCell:
00111       switch(cellType)
00112       {
00113         case BrickCell:
00114         case QuadCell:
00115         case LineCell:
00116         case PointCell:
00117           return true;
00118         default:
00119           return false;
00120       }
00121     default:
00122       return false;
00123   }
00124 }
00125 
00126 void Lagrange::print(std::ostream& os) const 
00127 {
00128   os << "Lagrange(" << order_ << ")";
00129 }
00130 
00131 int Lagrange::nReferenceDOFsWithoutFacets(
00132   const CellType& maximalCellType,
00133   const CellType& cellType
00134   ) const
00135 {
00136   if (order_==0)
00137   {
00138     if (maximalCellType != cellType) return 0;
00139     return 1;
00140   }
00141 
00142   switch(cellType)
00143   {
00144     case PointCell:
00145       return 1;
00146     case LineCell:
00147       return order_-1;
00148     case TriangleCell:
00149       if (order_ < 3) return 0;
00150       if (order_ == 3) return 1;
00151       TEUCHOS_TEST_FOR_EXCEPTION(order_>3, std::runtime_error, 
00152         "Lagrange order > 3 not implemented "
00153         "for triangle cells");
00154       return 0;
00155     case QuadCell:
00156       if (order_==1) return 0;
00157       if (order_==2) return 1;
00158       TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error, 
00159         "Lagrange order > 2 not implemented "
00160         "for quad cells");
00161     case TetCell:
00162       if (order_<=2) return 0;
00163       TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error, 
00164         "Lagrange order > 2 not implemented "
00165         "for tet cells");
00166     case BrickCell:
00167       if (order_<=1) return 0;
00168       if (order_==2) return 1;
00169       TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error, 
00170         "Lagrange order > 2 not implemented "
00171         "for brick cells");
00172     default:
00173       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00174         << cellType << " not implemented in Lagrange basis");
00175       return -1; // -Wall
00176   }
00177 }
00178 
00179 void Lagrange::getReferenceDOFs(
00180   const CellType& maximalCellType,
00181   const CellType& cellType,
00182   Array<Array<Array<int> > >& dofs) const 
00183 {
00184   typedef Array<int> Aint;
00185 
00186   if (order_==0)
00187   {
00188     int dim = dimension(cellType);
00189     dofs.resize(dim+1);
00190     for (int d=0; d<dim; d++)
00191     {
00192       Array<Array<int> > dd;
00193       for (int f=0; f<numFacets(cellType, d); f++) dd.append(Array<int>());
00194       dofs[d] = dd;
00195     }
00196     if (cellType==maximalCellType) dofs[dim] = tuple<Aint>(tuple(0));
00197     else dofs[dim] = tuple<Aint>(Array<int>());
00198     return;
00199   }
00200 
00201   switch(cellType)
00202     {
00203     case PointCell:
00204       dofs.resize(1);
00205       dofs[0] = tuple<Aint>(tuple(0));
00206       return;
00207     case LineCell:
00208       dofs.resize(2);
00209       dofs[0] = tuple<Aint>(tuple(0), tuple(1));
00210       dofs[1] = tuple<Aint>(makeRange(2, order()));
00211       return;
00212     case TriangleCell:
00213       {
00214         int n = order()-1;
00215         dofs.resize(3);
00216         dofs[0] = tuple<Aint>(tuple(0), tuple(1), tuple(2));
00217         dofs[1] = tuple<Aint>(makeRange(3,2+n), 
00218                         makeRange(3+n, 2+2*n),
00219                         makeRange(3+2*n, 2+3*n));
00220         if (order()<3)
00221           {
00222             dofs[2] = tuple(Array<int>());
00223           }
00224         else 
00225           {
00226             dofs[2] = tuple<Aint>(makeRange(3+3*n, 3+3*n));
00227           }
00228         return;
00229       }
00230     case QuadCell:{ // TODO: ask Kevin about Q0 (P0)
00231          dofs.resize(3);
00232        // dofs[0] are DOFs at Points
00233        dofs[0] = tuple<Aint>(tuple(0), tuple(1), tuple(2), tuple(3));
00234        if (order() == 2)
00235        {
00236          // dofs[1] are the DOFs on the line
00237          dofs[1] = tuple<Aint>(tuple(4), tuple(5), tuple(6), tuple(7));
00238          //dofs[2] are DOFs inside the Cell
00239 
00240          //dofs[2] = tuple(Array<int>());
00241            dofs[2] = tuple<Aint>(tuple(8));
00242        } else {
00243          dofs[1] = tuple(Array<int>(), Array<int>(),
00244                          Array<int>(), Array<int>());
00245            dofs[2] = tuple(Array<int>());
00246        }
00247          return;
00248       }
00249     case TetCell:
00250       {
00251         dofs.resize(4);
00252         dofs[0] = tuple<Aint>(tuple(0), tuple(1), tuple(2), tuple(3));
00253         if (order() == 2)
00254           {
00255             dofs[1] = tuple<Aint>(tuple(4), tuple(5), tuple(6), 
00256                             tuple(7), tuple(8), tuple(9));
00257           }
00258         else
00259           {
00260             dofs[1] = tuple(Array<int>(), Array<int>(),
00261                             Array<int>(), Array<int>(), 
00262                             Array<int>(), Array<int>());
00263           }
00264         dofs[2] = tuple(Array<int>(), Array<int>(), 
00265                         Array<int>(), Array<int>());
00266         dofs[3] = tuple(Array<int>());
00267         return;
00268       }
00269     case BrickCell:{
00270          dofs.resize(4);
00271        // dofs[0] are DOFs at Points
00272        dofs[0] = tuple<Aint>(tuple(0), tuple(1), tuple(2), tuple(3),
00273                          tuple(4), tuple(5), tuple(6), tuple(7));
00274        if (order() == 2)
00275        {
00276          // dofs[1] are the DOFs on the line
00277          dofs[1] = tuple<Aint>( tuple(8), tuple(9) , tuple(10), tuple(11),
00278                            tuple(12), tuple(13), tuple(14), tuple(15),
00279                            tuple(16), tuple(17), tuple(18), tuple(19));
00280          //dofs[2] are DOFs on the faces
00281            dofs[2] = tuple<Aint>(tuple(20), tuple(21), tuple(22), tuple(23),
00282                        tuple(24), tuple(25) );
00283            dofs[3] = tuple<Aint>(tuple(26));
00284        } else {
00285          dofs[1] = tuple(Array<int>(), Array<int>(), Array<int>(), Array<int>(),
00286                      Array<int>(), Array<int>(), Array<int>(), Array<int>(),
00287                      Array<int>(), Array<int>(), Array<int>(), Array<int>());
00288            dofs[2] = tuple(Array<int>(), Array<int>(), Array<int>(), Array<int>(),
00289                            Array<int>(), Array<int>() );
00290            dofs[3] = tuple(Array<int>());
00291        }
00292          return;
00293       }
00294     default:
00295       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00296                          << cellType << " not implemented in Lagrange basis");
00297     }
00298 }
00299 
00300 
00301 
00302 Array<int> Lagrange::makeRange(int low, int high)
00303 {
00304   if (high < low) return Array<int>();
00305 
00306   Array<int> rtn(high-low+1);
00307   for (int i=0; i<rtn.length(); i++) rtn[i] = low+i;
00308   return rtn;
00309 }
00310 
00311 void Lagrange::refEval(
00312   const CellType& cellType,
00313   const Array<Point>& pts,
00314   const SpatialDerivSpecifier& sds,
00315   Array<Array<Array<double> > >& result,
00316   int verbosity) const
00317 {
00318   TEUCHOS_TEST_FOR_EXCEPTION(!(sds.isPartial() || sds.isIdentity()), 
00319     std::runtime_error,
00320     "cannot evaluate spatial derivative " << sds << " on Lagrange basis");
00321   const MultiIndex& deriv = sds.mi();
00322   typedef Array<double> Adouble;
00323   result.resize(1);
00324   result[0].resize(pts.length());
00325 
00326   switch(cellType)
00327     {
00328     case PointCell:
00329       result[0] = tuple<Adouble>(tuple(1.0));
00330       return;
00331     case LineCell:
00332       for (int i=0; i<pts.length(); i++)
00333         {
00334           evalOnLine(pts[i], deriv, result[0][i]);
00335         }
00336       return;
00337     case TriangleCell:
00338       for (int i=0; i<pts.length(); i++)
00339         {
00340           evalOnTriangle(pts[i], deriv, result[0][i]);
00341         }
00342       return;
00343     case QuadCell:
00344       for (int i=0; i<pts.length(); i++)
00345        {
00346           evalOnquad(pts[i], deriv, result[0][i]);
00347        }
00348        return;
00349     case TetCell:
00350       for (int i=0; i<pts.length(); i++)
00351         {
00352           evalOnTet(pts[i], deriv, result[0][i]);
00353         }
00354       return;
00355     case BrickCell:
00356         for (int i=0; i<pts.length(); i++)
00357           {
00358             evalOnBrick(pts[i], deriv, result[0][i]);
00359           }
00360       return;
00361     default:
00362       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00363                          "Lagrange::refEval() unimplemented for cell type "
00364                          << cellType);
00365 
00366     }
00367 }
00368 
00369 /* ---------- evaluation on different cell types -------------- */
00370 
00371 void Lagrange::evalOnLine(const Point& pt, 
00372                           const MultiIndex& deriv,
00373                           Array<double>& result) const
00374 {
00375   ADReal x = ADReal(pt[0], 0, 1);
00376   ADReal one(1.0, 1);
00377   
00378   result.resize(order()+1);
00379   Array<ADReal> tmp(result.length());
00380   Array<double> x0(order()+1);
00381 
00382   if (order_ == 0)
00383     {
00384       tmp[0] = one;
00385     }
00386   else
00387     {
00388       x0[0] = 0.0;
00389       x0[1] = 1.0;
00390       for (int i=0; i<order_-1; i++)
00391         {
00392           x0[i+2] = (i+1.0)/order_;
00393         }
00394 
00395       for (int i=0; i<=order_; i++)
00396         {
00397           tmp[i] = one;
00398           for (int j=0; j<=order_; j++)
00399             {
00400               if (i==j) continue;
00401               tmp[i] *= (x - x0[j])/(x0[i]-x0[j]);
00402             }
00403         }
00404     }
00405   /*
00406   switch(order_)
00407     {
00408     case 0:
00409       tmp[0] = one;
00410       break;
00411     case 1:
00412       tmp[0] = 1.0 - x;
00413       tmp[1] = x;
00414       break;
00415     case 2:
00416       tmp[0] = 2.0*(1.0-x)*(0.5-x);
00417       tmp[1] = 2.0*x*(x-0.5);
00418       tmp[2] = 4.0*x*(1.0-x);
00419       break;
00420     case 3:
00421       tmp[0] = 9.0/2.0 * (1.0 - x) * (1.0/3.0 - x) * (2.0/3.0 - x);
00422       tmp[1] = 9.0/2.0 * x * (x - 1.0/3.0) * (x - 2.0/3.0);
00423       tmp[2] = 27.0/2.0 * x * (1.0 - x) * (2.0/3.0 - x);
00424       tmp[3] = 27.0/2.0 * x * (1.0 - x) * (x - 1.0/3.0);
00425 
00426       break;
00427     default:
00428       SUNDANCE_ERROR("Lagrange::evalOnLine polynomial order > 2 has not been"
00429                      " implemented");
00430     }
00431   */
00432   for (int i=0; i<tmp.length(); i++)
00433     {
00434       if (deriv.order()==0) result[i] = tmp[i].value();
00435       else result[i] = tmp[i].gradient()[0];
00436     }
00437 }
00438 
00439 void Lagrange::evalOnTriangle(const Point& pt, 
00440                               const MultiIndex& deriv,
00441                               Array<double>& result) const
00442 
00443 
00444 
00445 {
00446   ADReal x = ADReal(pt[0], 0, 2);
00447   ADReal y = ADReal(pt[1], 1, 2);
00448   ADReal one(1.0, 2);
00449 
00450   Array<ADReal> tmp;
00451 
00452   SUNDANCE_OUT(this->verb() > 3, "x=" << x.value() << " y="
00453                << y.value());
00454 
00455   switch(order_)
00456     {
00457     case 0:
00458       result.resize(1);
00459       tmp.resize(1);
00460       tmp[0] = one;
00461       break;
00462     case 1:
00463       result.resize(3);
00464       tmp.resize(3);
00465       tmp[0] = 1.0 - x - y;
00466       tmp[1] = x;
00467       tmp[2] = y;
00468       break;
00469     case 2:
00470       result.resize(6);
00471       tmp.resize(6);
00472       tmp[0] = (1.0-x-y)*(1.0-2.0*x-2.0*y);
00473       tmp[1] = 2.0*x*(x-0.5);
00474       tmp[2] = 2.0*y*(y-0.5);
00475       tmp[5] = 4.0*x*(1.0-x-y); 
00476       tmp[3] = 4.0*x*y;
00477       tmp[4] = 4.0*y*(1.0-x-y);
00478       break;
00479     case 3:
00480       result.resize(10);
00481       tmp.resize(10);
00482       {
00483         ADReal q1 = 1.0 - x - y;
00484         ADReal q2 = x;
00485         ADReal q3 = y;
00486         tmp[0] = 9.0/2.0 * q1 * (q1 - 2.0/3.0) * (q1 - 1.0/3.0);
00487         tmp[1] = 9.0/2.0 * q2 * (q2 - 2.0/3.0) * (q2 - 1.0/3.0);
00488         tmp[2] = 9.0/2.0 * q3 * (q3 - 2.0/3.0) * (q3 - 1.0/3.0);
00489         tmp[7] = 27.0/2.0 * q1 * q2   * (q1 - 1.0/3.0);
00490         tmp[8] = 27.0/2.0 * q1 * q2   * (q2 - 1.0/3.0);
00491         tmp[3] = 27.0/2.0 * q2 * q3   * (q2 - 1.0/3.0);
00492         tmp[4] = 27.0/2.0 * q2 * q3   * (q3 - 1.0/3.0);
00493         tmp[6] = 27.0/2.0 * q3 * q1   * (q3 - 1.0/3.0);
00494         tmp[5] = 27.0/2.0 * q3 * q1   * (q1 - 1.0/3.0);
00495         tmp[9] = 27.0 * q1 * q2 * q3;
00496       }
00497       break;
00498     default:
00499 #ifndef TRILINOS_7
00500       SUNDANCE_ERROR("Lagrange::evalOnTriangle poly order > 2");
00501 #else
00502       SUNDANCE_ERROR7("Lagrange::evalOnTriangle poly order > 2");
00503 #endif
00504     }
00505 
00506   for (int i=0; i<tmp.length(); i++)
00507     {
00508       SUNDANCE_OUT(this->verb() > 3,
00509                    "tmp[" << i << "]=" << tmp[i].value() 
00510                    << " grad=" << tmp[i].gradient());
00511       if (deriv.order()==0) result[i] = tmp[i].value();
00512       else 
00513           result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00514     }
00515 }
00516 
00517 void Lagrange::evalOnquad(const Point& pt,
00518       const MultiIndex& deriv,
00519       Array<double>& result) const {
00520 
00521   ADReal x = ADReal(pt[0], 0, 2);
00522   ADReal y = ADReal(pt[1], 1, 2);
00523   ADReal one(1.0, 2);
00524 
00525   Array<ADReal> tmp;
00526 
00527   SUNDANCE_OUT(this->verb() > 3, "x=" << x.value() << " y="
00528                << y.value());
00529 
00530   switch(order_)
00531     {
00532     case 0:
00533             result.resize(1);
00534             tmp.resize(1);
00535       tmp[0] = one;
00536       break;
00537     case 1:
00538             result.resize(4);
00539             tmp.resize(4);
00540       tmp[0] = (1.0 - x)*(1.0 - y);
00541       tmp[1] = x*(1.0 - y);
00542       tmp[2] = (1.0 - x)*y;
00543       tmp[3] = x*y; //These are the 4 basis functions for the first order
00544       break;
00545     case 2: //The basis functions calculated with Octave / Matlab
00546 
00547             result.resize(9);
00548             tmp.resize(9);
00549       tmp[0] = 9.0 - 9.0*x - 9.0*y + 9.0*x*y - 6.0*(x*x -1)*(y-1)
00550           - 6.0*(x-1)*(y*y-1)                     + 4.0*(x*x-1)*(y*y-1);
00551       tmp[1] = 6.0 - 3.0*x - 6.0*y + 3.0*x*y - 6.0*(x*x -1)*(y-1)
00552                     - 3.0*(x-1)*(y*y-1) + 1.0*(x+1)*(y*y-1) + 4.0*(x*x-1)*(y*y-1);
00553       tmp[2] = 6.0 - 6.0*x - 3.0*y + 3.0*x*y - 3.0*(x*x -1)*(y-1) + 1.0*(x*x -1)*(y+1)
00554           -6.0*(x-1)*(y*y-1) +                    + 4.0*(x*x-1)*(y*y-1);
00555       tmp[3] = 4.0 - 2.0*x - 2.0*y + 1.0*x*y - 3.0*(x*x -1)*(y-1) + 1.0*(x*x -1)*(y+1)
00556           - 3.0*(x-1)*(y*y-1) + 1.0*(x+1)*(y*y-1) + 4.0*(x*x-1)*(y*y-1);
00557       tmp[4] = -12.0 + 12.0*x + 12.0*y - 12.0*x*y + 12.0*(x*x -1)*(y-1)
00558           + 8.0*(x-1)*(y*y-1)                     - 8.0*(x*x-1)*(y*y-1);
00559       tmp[5] = -12.0 + 12.0*x + 12.0*y - 12.0*x*y + 8.0*(x*x -1)*(y-1)
00560           + 12.0*(x-1)*(y*y-1)                    - 8.0*(x*x-1)*(y*y-1);
00561       tmp[6] = -8.0 + 4.0*x + 8.0*y - 4.0*x*y + 8.0*(x*x -1)*(y-1)
00562           + 6.0*(x-1)*(y*y-1) - 2.0*(x+1)*(y*y-1) - 8.0*(x*x-1)*(y*y-1);
00563       tmp[7] = -8.0 + 8.0*x + 4.0*y - 4.0*x*y + 6.0*(x*x -1)*(y-1) - 2.0*(x*x -1)*(y+1)
00564           + 8.0*(x-1)*(y*y-1)                     - 8.0*(x*x-1)*(y*y-1);
00565       tmp[8] = 16.0 - 16.0*x - 16.0*y + 16.0*x*y - 16.0*(x*x -1)*(y-1)
00566           - 16.0*(x-1)*(y*y-1)                    + 16.0*(x*x-1)*(y*y-1);
00567       break;
00568     default:{}
00569     }
00570 
00571    for (int i=0; i<tmp.length(); i++) {
00572      SUNDANCE_OUT(this->verb() > 3 ,
00573                    "tmp[" << i << "]=" << tmp[i].value()
00574                    << " grad=" << tmp[i].gradient());
00575     if (deriv.order()==0)
00576         result[i] = tmp[i].value();
00577     else
00578                 result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00579   }
00580 }
00581 
00582 void Lagrange::evalOnTet(const Point& pt, 
00583                          const MultiIndex& deriv,
00584                          Array<double>& result) const
00585 {
00586   ADReal x = ADReal(pt[0], 0, 3);
00587   ADReal y = ADReal(pt[1], 1, 3);
00588   ADReal z = ADReal(pt[2], 2, 3);
00589   ADReal one(1.0, 3);
00590 
00591 
00592   Array<ADReal> tmp(result.length());
00593 
00594   switch(order_)
00595     {
00596     case 0:
00597       tmp.resize(1);
00598       result.resize(1);
00599       tmp[0] = one;
00600       break;
00601     case 1:
00602       result.resize(4);
00603       tmp.resize(4);
00604       tmp[0] = 1.0 - x - y - z;
00605       tmp[1] = x;
00606       tmp[2] = y;
00607       tmp[3] = z;
00608       break;
00609     case 2:
00610       result.resize(10);
00611       tmp.resize(10);
00612       tmp[0] = (1.0-x-y-z)*(1.0-2.0*x-2.0*y-2.0*z);
00613       tmp[1] = 2.0*x*(x-0.5);
00614       tmp[2] = 2.0*y*(y-0.5);
00615       tmp[3] = 2.0*z*(z-0.5);
00616       tmp[9] = 4.0*x*(1.0-x-y-z);
00617       tmp[6] = 4.0*x*y;
00618       tmp[8] = 4.0*y*(1.0-x-y-z);
00619       tmp[7] = 4.0*z*(1.0-x-y-z);
00620       tmp[5] = 4.0*x*z;
00621       tmp[4] = 4.0*y*z;
00622       break;
00623     default:
00624 #ifndef TRILINOS_7
00625       SUNDANCE_ERROR("Lagrange::evalOnTet poly order > 2");
00626 #else
00627       SUNDANCE_ERROR7("Lagrange::evalOnTet poly order > 2");
00628 #endif
00629     }
00630 
00631   for (int i=0; i<tmp.length(); i++)
00632     {
00633       if (deriv.order()==0) result[i] = tmp[i].value();
00634       else 
00635         result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00636     }
00637 }
00638 
00639 void Lagrange::evalOnBrick(const Point& pt,
00640                          const MultiIndex& deriv,
00641                          Array<double>& result) const
00642 {
00643   ADReal x = ADReal(pt[0], 0, 3);
00644   ADReal y = ADReal(pt[1], 1, 3);
00645   ADReal z = ADReal(pt[2], 2, 3);
00646   ADReal one(1.0, 3);
00647 
00648 
00649   Array<ADReal> tmp(result.length());
00650 
00651   switch(order_)
00652     {
00653     case 0:
00654             tmp.resize(1);
00655             result.resize(1);
00656       tmp[0] = one;
00657       break;
00658     case 1: // tri linear basis functions for bricks
00659             result.resize(8);
00660             tmp.resize(8);
00661       tmp[0] = (1.0 - x)*(1.0 - y)*(1.0 - z);
00662       tmp[1] = (x)*(1.0 - y)*(1.0 - z);
00663       tmp[2] = (1.0 - x)*(y)*(1.0 - z);
00664       tmp[3] = (x)*(y)*(1.0 - z);
00665       tmp[4] = (1.0 - x)*(1.0 - y)*(z);
00666       tmp[5] = (x)*(1.0 - y)*(z);
00667       tmp[6] = (1.0 - x)*(y)*(z);
00668       tmp[7] = (x)*(y)*(z);
00669       break;
00670     case 2: // second order function in 3D
00671           result.resize(27);
00672           tmp.resize(27);
00673                    // 0.0 + 0.0*x + 0.0*y + 0.0*z + 0.0*x*y + 0.0*x*z + 0.0*y*z + 0.0*x*y*z
00674                    //+ 0.0*(x*x - 1)*(y-1)*(z-1) + 0.0*(x*x - 1)*(y-1)*(z+1) + 0.0*(x*x - 1)*(y+1)*(z-1) + 0.0*(x*x - 1)*(y+1)*(z+1)
00675                    //+ 0.0*(y*y - 1)*(x-1)*(z-1) + 0.0*(y*y - 1)*(x-1)*(z+1) + 0.0*(y*y - 1)*(x+1)*(z-1) + 0.0*(y*y - 1)*(x+1)*(z+1)
00676                    //+ 0.0*(z*z - 1)*(x-1)*(y-1) + 0.0*(z*z - 1)*(x-1)*(y+1) + 0.0*(z*z - 1)*(x+1)*(y-1) + 0.0*(z*z - 1)*(x+1)*(y+1)
00677                    //+ 0.0*(x*x - 1)*(y*y - 1)*(z-1) + 0.0*(x*x - 1)*(y*y - 1)*(z+1)
00678                    //+ 0.0*(x*x - 1)*(z*z - 1)*(y-1) + 0.0*(x*x - 1)*(z*z - 1)*(y+1)
00679                    //+ 0.0*(y*y - 1)*(z*z - 1)*(x-1) + 0.0*(y*y - 1)*(z*z - 1)*(x+1)
00680                    //+ 0.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00681 
00682 
00683             tmp[0] = 27.0 - 27.0*x - 27.0*y - 27.0*z + 27.0*x*y + 27.0*x*z + 27.0*y*z - 27.0*x*y*z
00684             + 18.0*(x*x - 1)*(y-1)*(z-1)
00685             + 18.0*(y*y - 1)*(x-1)*(z-1)
00686             + 18.0*(z*z - 1)*(x-1)*(y-1)
00687             - 12.0*(x*x - 1)*(y*y - 1)*(z-1)
00688             - 12.0*(x*x - 1)*(z*z - 1)*(y-1)
00689             - 12.0*(y*y - 1)*(z*z - 1)*(x-1)
00690             + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00691 
00692             tmp[1] = 18.0 - 9.0*x - 18.0*y - 18.0*z + 9.0*x*y + 9.0*x*z + 18.0*y*z - 9.0*x*y*z
00693             + 18.0*(x*x - 1)*(y-1)*(z-1)
00694             + 9.0*(y*y - 1)*(x-1)*(z-1) - 3.0*(y*y - 1)*(x+1)*(z-1)
00695             + 9.0*(z*z - 1)*(x-1)*(y-1) - 3.0*(z*z - 1)*(x+1)*(y-1)
00696             - 12.0*(x*x - 1)*(y*y - 1)*(z-1)
00697             - 12.0*(x*x - 1)*(z*z - 1)*(y-1)
00698             - 6.0*(y*y - 1)*(z*z - 1)*(x-1) + 2.0*(y*y - 1)*(z*z - 1)*(x+1)
00699             + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00700 
00701             tmp[2] = 18.0 - 18.0*x - 9.0*y - 18.0*z + 9.0*x*y + 18.0*x*z + 9.0*y*z - 9.0*x*y*z
00702              + 9.0*(x*x - 1)*(y-1)*(z-1) - 3.0*(x*x - 1)*(y+1)*(z-1)
00703              + 18.0*(y*y - 1)*(x-1)*(z-1)
00704              + 9.0*(z*z - 1)*(x-1)*(y-1) - 3.0*(z*z - 1)*(x-1)*(y+1)
00705              - 12.0*(x*x - 1)*(y*y - 1)*(z-1)
00706              - 6.0*(x*x - 1)*(z*z - 1)*(y-1) + 2.0*(x*x - 1)*(z*z - 1)*(y+1)
00707              - 12.0*(y*y - 1)*(z*z - 1)*(x-1)
00708              + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00709 
00710             tmp[3] =  12.0 - 6.0*x - 6.0*y - 12.0*z + 3.0*x*y + 6.0*x*z + 6.0*y*z - 3.0*x*y*z
00711             + 9.0*(x*x - 1)*(y-1)*(z-1) - 3.0*(x*x - 1)*(y+1)*(z-1)
00712             + 9.0*(y*y - 1)*(x-1)*(z-1) - 3.0*(y*y - 1)*(x+1)*(z-1)
00713             + 4.5*(z*z - 1)*(x-1)*(y-1) - 1.5*(z*z - 1)*(x-1)*(y+1) - 1.5*(z*z - 1)*(x+1)*(y-1) + 0.5*(z*z - 1)*(x+1)*(y+1)
00714             - 12.0*(x*x - 1)*(y*y - 1)*(z-1)
00715             - 6.0*(x*x - 1)*(z*z - 1)*(y-1) + 2.0*(x*x - 1)*(z*z - 1)*(y+1)
00716             - 6.0*(y*y - 1)*(z*z - 1)*(x-1) + 2.0*(y*y - 1)*(z*z - 1)*(x+1)
00717             + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00718 
00719             tmp[4] = 18.0 - 18.0*x - 18.0*y - 9.0*z + 18.0*x*y + 9.0*x*z + 9.0*y*z - 9.0*x*y*z
00720              + 9.0*(x*x - 1)*(y-1)*(z-1) - 3.0*(x*x - 1)*(y-1)*(z+1)
00721              + 9.0*(y*y - 1)*(x-1)*(z-1) - 3.0*(y*y - 1)*(x-1)*(z+1)
00722              + 18.0*(z*z - 1)*(x-1)*(y-1)
00723              - 6.0*(x*x - 1)*(y*y - 1)*(z-1) + 2.0*(x*x - 1)*(y*y - 1)*(z+1)
00724              - 12.0*(x*x - 1)*(z*z - 1)*(y-1)
00725              - 12.0*(y*y - 1)*(z*z - 1)*(x-1)
00726              + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00727 
00728             tmp[5] =  12.0 - 6.0*x - 12.0*y - 6.0*z + 6.0*x*y + 3.0*x*z + 6.0*y*z - 3.0*x*y*z
00729             + 9.0*(x*x - 1)*(y-1)*(z-1) - 3.0*(x*x - 1)*(y-1)*(z+1)
00730             + 4.5*(y*y - 1)*(x-1)*(z-1) - 1.5*(y*y - 1)*(x-1)*(z+1) - 1.5*(y*y - 1)*(x+1)*(z-1) + 0.5*(y*y - 1)*(x+1)*(z+1)
00731             + 9.0*(z*z - 1)*(x-1)*(y-1) - 3.0*(z*z - 1)*(x+1)*(y-1)
00732             - 6.0*(x*x - 1)*(y*y - 1)*(z-1) + 2.0*(x*x - 1)*(y*y - 1)*(z+1)
00733             - 12.0*(x*x - 1)*(z*z - 1)*(y-1)
00734             - 6.0*(y*y - 1)*(z*z - 1)*(x-1) + 2.0*(y*y - 1)*(z*z - 1)*(x+1)
00735             + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00736 
00737             tmp[6] = 12.0 - 12.0*x - 6.0*y - 6.0*z + 6.0*x*y + 6.0*x*z + 3.0*y*z - 3.0*x*y*z
00738             + 4.5*(x*x - 1)*(y-1)*(z-1) - 1.5*(x*x - 1)*(y-1)*(z+1) - 1.5*(x*x - 1)*(y+1)*(z-1) + 0.5*(x*x - 1)*(y+1)*(z+1)
00739             + 9.0*(y*y - 1)*(x-1)*(z-1) - 3.0*(y*y - 1)*(x-1)*(z+1)
00740             + 9.0*(z*z - 1)*(x-1)*(y-1) - 3.0*(z*z - 1)*(x-1)*(y+1)
00741             - 6.0*(x*x - 1)*(y*y - 1)*(z-1) + 2.0*(x*x - 1)*(y*y - 1)*(z+1)
00742             - 6.0*(x*x - 1)*(z*z - 1)*(y-1) + 2.0*(x*x - 1)*(z*z - 1)*(y+1)
00743             - 12.0*(y*y - 1)*(z*z - 1)*(x-1)
00744             + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00745 
00746             tmp[7] = 8.0 - 4.0*x - 4.0*y - 4.0*z + 2.0*x*y + 2.0*x*z + 2.0*y*z - 1.0*x*y*z
00747              + 4.5*(x*x - 1)*(y-1)*(z-1) - 1.5*(x*x - 1)*(y-1)*(z+1) - 1.5*(x*x - 1)*(y+1)*(z-1) + 0.5*(x*x - 1)*(y+1)*(z+1)
00748              + 4.5*(y*y - 1)*(x-1)*(z-1) - 1.5*(y*y - 1)*(x-1)*(z+1) - 1.5*(y*y - 1)*(x+1)*(z-1) + 0.5*(y*y - 1)*(x+1)*(z+1)
00749              + 4.5*(z*z - 1)*(x-1)*(y-1) - 1.5*(z*z - 1)*(x-1)*(y+1) - 1.5*(z*z - 1)*(x+1)*(y-1) + 0.5*(z*z - 1)*(x+1)*(y+1)
00750              - 6.0*(x*x - 1)*(y*y - 1)*(z-1) + 2.0*(x*x - 1)*(y*y - 1)*(z+1)
00751              - 6.0*(x*x - 1)*(z*z - 1)*(y-1) + 2.0*(x*x - 1)*(z*z - 1)*(y+1)
00752              - 6.0*(y*y - 1)*(z*z - 1)*(x-1) + 2.0*(y*y - 1)*(z*z - 1)*(x+1)
00753              + 8.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00754 
00755             tmp[8] =  -36.0 + 36.0*x + 36.0*y + 36.0*z - 36.0*x*y - 36.0*x*z - 36.0*y*z + 36.0*x*y*z
00756              - 36.0*(x*x - 1)*(y-1)*(z-1)
00757              - 24.0*(y*y - 1)*(x-1)*(z-1)
00758              - 24.0*(z*z - 1)*(x-1)*(y-1)
00759              + 24.0*(x*x - 1)*(y*y - 1)*(z-1)
00760              + 24.0*(x*x - 1)*(z*z - 1)*(y-1)
00761              + 16.0*(y*y - 1)*(z*z - 1)*(x-1)
00762              - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00763 
00764             tmp[9] = -36.0 + 36.0*x + 36.0*y + 36.0*z - 36.0*x*y - 36.0*x*z - 36.0*y*z + 36.0*x*y*z
00765             - 24.0*(x*x - 1)*(y-1)*(z-1)
00766             - 36.0*(y*y - 1)*(x-1)*(z-1)
00767             - 24.0*(z*z - 1)*(x-1)*(y-1)
00768             + 24.0*(x*x - 1)*(y*y - 1)*(z-1)
00769             + 16.0*(x*x - 1)*(z*z - 1)*(y-1)
00770             + 24.0*(y*y - 1)*(z*z - 1)*(x-1)
00771             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00772 
00773             tmp[10] = -36.0 + 36.0*x + 36.0*y + 36.0*z - 36.0*x*y - 36.0*x*z - 36.0*y*z + 36.0*x*y*z
00774             - 24.0*(x*x - 1)*(y-1)*(z-1)
00775             - 24.0*(y*y - 1)*(x-1)*(z-1)
00776             - 36.0*(z*z - 1)*(x-1)*(y-1)
00777             + 16.0*(x*x - 1)*(y*y - 1)*(z-1)
00778             + 24.0*(x*x - 1)*(z*z - 1)*(y-1)
00779             + 24.0*(y*y - 1)*(z*z - 1)*(x-1)
00780             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00781 
00782             tmp[11] = -24.0 + 12.0*x + 24.0*y + 24.0*z - 12.0*x*y - 12.0*x*z - 24.0*y*z + 12.0*x*y*z
00783             - 24.0*(x*x - 1)*(y-1)*(z-1)
00784             - 18.0*(y*y - 1)*(x-1)*(z-1) + 6.0*(y*y - 1)*(x+1)*(z-1)
00785             - 12.0*(z*z - 1)*(x-1)*(y-1) + 4.0*(z*z - 1)*(x+1)*(y-1)
00786             + 24.0*(x*x - 1)*(y*y - 1)*(z-1)
00787             + 16.0*(x*x - 1)*(z*z - 1)*(y-1)
00788             + 12.0*(y*y - 1)*(z*z - 1)*(x-1) - 4.0*(y*y - 1)*(z*z - 1)*(x+1)
00789             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00790 
00791             tmp[12] = -24.0 + 12.0*x + 24.0*y + 24.0*z - 12.0*x*y - 12.0*x*z - 24.0*y*z + 12.0*x*y*z
00792             - 24.0*(x*x - 1)*(y-1)*(z-1)
00793             - 12.0*(y*y - 1)*(x-1)*(z-1) + 4.0*(y*y - 1)*(x+1)*(z-1)
00794             - 18.0*(z*z - 1)*(x-1)*(y-1) + 6.0*(z*z - 1)*(x+1)*(y-1)
00795             + 16.0*(x*x - 1)*(y*y - 1)*(z-1)
00796             + 24.0*(x*x - 1)*(z*z - 1)*(y-1)
00797             + 12.0*(y*y - 1)*(z*z - 1)*(x-1) - 4.0*(y*y - 1)*(z*z - 1)*(x+1)
00798             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00799 
00800             tmp[13] = -24.0 + 24.0*x + 12.0*y + 24.0*z - 12.0*x*y - 24.0*x*z - 12.0*y*z + 12.0*x*y*z
00801             - 18.0*(x*x - 1)*(y-1)*(z-1) + 6.0*(x*x - 1)*(y+1)*(z-1)
00802             - 24.0*(y*y - 1)*(x-1)*(z-1)
00803             - 12.0*(z*z - 1)*(x-1)*(y-1) + 4.0*(z*z - 1)*(x-1)*(y+1)
00804             + 24.0*(x*x - 1)*(y*y - 1)*(z-1)
00805             + 12.0*(x*x - 1)*(z*z - 1)*(y-1) - 4.0*(x*x - 1)*(z*z - 1)*(y+1)
00806             + 16.0*(y*y - 1)*(z*z - 1)*(x-1)
00807             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00808 
00809             tmp[14] = -24.0 + 24.0*x + 12.0*y + 24.0*z - 12.0*x*y - 24.0*x*z - 12.0*y*z + 12.0*x*y*z
00810             - 12.0*(x*x - 1)*(y-1)*(z-1) + 4.0*(x*x - 1)*(y+1)*(z-1)
00811             - 24.0*(y*y - 1)*(x-1)*(z-1)
00812             - 18.0*(z*z - 1)*(x-1)*(y-1) + 6.0*(z*z - 1)*(x-1)*(y+1)
00813             + 16.0*(x*x - 1)*(y*y - 1)*(z-1)
00814             + 12.0*(x*x - 1)*(z*z - 1)*(y-1) - 4.0*(x*x - 1)*(z*z - 1)*(y+1)
00815             + 24.0*(y*y - 1)*(z*z - 1)*(x-1)
00816             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00817 
00818             tmp[15] = -16.0 + 8.0*x + 8.0*y + 16.0*z - 4.0*x*y - 8.0*x*z - 8.0*y*z + 4.0*x*y*z
00819             - 12.0*(x*x - 1)*(y-1)*(z-1) + 4.0*(x*x - 1)*(y+1)*(z-1)
00820             - 12.0*(y*y - 1)*(x-1)*(z-1) + 4.0*(y*y - 1)*(x+1)*(z-1)
00821             - 9.0*(z*z - 1)*(x-1)*(y-1) + 3.0*(z*z - 1)*(x-1)*(y+1) + 3.0*(z*z - 1)*(x+1)*(y-1) - 1.0*(z*z - 1)*(x+1)*(y+1)
00822             + 16.0*(x*x - 1)*(y*y - 1)*(z-1)
00823             + 12.0*(x*x - 1)*(z*z - 1)*(y-1) - 4.0*(x*x - 1)*(z*z - 1)*(y+1)
00824             + 12.0*(y*y - 1)*(z*z - 1)*(x-1) - 4.0*(y*y - 1)*(z*z - 1)*(x+1)
00825             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00826 
00827             tmp[16] = -24.0 + 24.0*x + 24.0*y + 12.0*z - 24.0*x*y - 12.0*x*z - 12.0*y*z + 12.0*x*y*z
00828             - 18.0*(x*x - 1)*(y-1)*(z-1) + 6.0*(x*x - 1)*(y-1)*(z+1)
00829             - 12.0*(y*y - 1)*(x-1)*(z-1) + 4.0*(y*y - 1)*(x-1)*(z+1)
00830             - 24.0*(z*z - 1)*(x-1)*(y-1)
00831             + 12.0*(x*x - 1)*(y*y - 1)*(z-1) - 4.0*(x*x - 1)*(y*y - 1)*(z+1)
00832             + 24.0*(x*x - 1)*(z*z - 1)*(y-1)
00833             + 16.0*(y*y - 1)*(z*z - 1)*(x-1)
00834             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00835 
00836             tmp[17] = -24.0 + 24.0*x + 24.0*y + 12.0*z - 24.0*x*y - 12.0*x*z - 12.0*y*z + 12.0*x*y*z
00837             - 12.0*(x*x - 1)*(y-1)*(z-1) + 4.0*(x*x - 1)*(y-1)*(z+1)
00838             - 18.0*(y*y - 1)*(x-1)*(z-1) + 6.0*(y*y - 1)*(x-1)*(z+1)
00839             - 24.0*(z*z - 1)*(x-1)*(y-1)
00840             + 12.0*(x*x - 1)*(y*y - 1)*(z-1) - 4.0*(x*x - 1)*(y*y - 1)*(z+1)
00841             + 16.0*(x*x - 1)*(z*z - 1)*(y-1)
00842             + 24.0*(y*y - 1)*(z*z - 1)*(x-1)
00843             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00844 
00845             tmp[18] = -16.0 + 8.0*x + 16.0*y + 8.0*z - 8.0*x*y - 4.0*x*z - 8.0*y*z + 4.0*x*y*z
00846             - 12.0*(x*x - 1)*(y-1)*(z-1) + 4.0*(x*x - 1)*(y-1)*(z+1)
00847             - 9.0*(y*y - 1)*(x-1)*(z-1) + 3.0*(y*y - 1)*(x-1)*(z+1) + 3.0*(y*y - 1)*(x+1)*(z-1) - 1.0*(y*y - 1)*(x+1)*(z+1)
00848             - 12.0*(z*z - 1)*(x-1)*(y-1) + 4.0*(z*z - 1)*(x+1)*(y-1)
00849             + 12.0*(x*x - 1)*(y*y - 1)*(z-1) - 4.0*(x*x - 1)*(y*y - 1)*(z+1)
00850             + 16.0*(x*x - 1)*(z*z - 1)*(y-1)
00851             + 12.0*(y*y - 1)*(z*z - 1)*(x-1) - 4.0*(y*y - 1)*(z*z - 1)*(x+1)
00852             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00853 
00854             tmp[19] = -16.0 + 16.0*x + 8.0*y + 8.0*z - 8.0*x*y - 8.0*x*z - 4.0*y*z + 4.0*x*y*z
00855             - 9.0*(x*x - 1)*(y-1)*(z-1) + 3.0*(x*x - 1)*(y-1)*(z+1) + 3.0*(x*x - 1)*(y+1)*(z-1) - 1.0*(x*x - 1)*(y+1)*(z+1)
00856             - 12.0*(y*y - 1)*(x-1)*(z-1) + 4.0*(y*y - 1)*(x-1)*(z+1)
00857             - 12.0*(z*z - 1)*(x-1)*(y-1) + 4.0*(z*z - 1)*(x-1)*(y+1)
00858             + 12.0*(x*x - 1)*(y*y - 1)*(z-1) - 4.0*(x*x - 1)*(y*y - 1)*(z+1)
00859             + 12.0*(x*x - 1)*(z*z - 1)*(y-1) - 4.0*(x*x - 1)*(z*z - 1)*(y+1)
00860             + 16.0*(y*y - 1)*(z*z - 1)*(x-1)
00861             - 16.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00862 
00863             tmp[20] = 48.0 - 48.0*x - 48.0*y - 48.0*z + 48.0*x*y + 48.0*x*z + 48.0*y*z - 48.0*x*y*z
00864             + 48.0*(x*x - 1)*(y-1)*(z-1)
00865             + 48.0*(y*y - 1)*(x-1)*(z-1)
00866             + 32.0*(z*z - 1)*(x-1)*(y-1)
00867             - 48.0*(x*x - 1)*(y*y - 1)*(z-1)
00868             - 32.0*(x*x - 1)*(z*z - 1)*(y-1)
00869             - 32.0*(y*y - 1)*(z*z - 1)*(x-1)
00870             + 32.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00871 
00872             tmp[21] = 48.0 - 48.0*x - 48.0*y - 48.0*z + 48.0*x*y + 48.0*x*z + 48.0*y*z - 48.0*x*y*z
00873             + 48.0*(x*x - 1)*(y-1)*(z-1)
00874             + 32.0*(y*y - 1)*(x-1)*(z-1)
00875             + 48.0*(z*z - 1)*(x-1)*(y-1)
00876             - 32.0*(x*x - 1)*(y*y - 1)*(z-1)
00877             - 48.0*(x*x - 1)*(z*z - 1)*(y-1)
00878             - 32.0*(y*y - 1)*(z*z - 1)*(x-1)
00879             + 32.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00880 
00881             tmp[22] = 48.0 - 48.0*x - 48.0*y - 48.0*z + 48.0*x*y + 48.0*x*z + 48.0*y*z - 48.0*x*y*z
00882             + 32.0*(x*x - 1)*(y-1)*(z-1)
00883             + 48.0*(y*y - 1)*(x-1)*(z-1)
00884             + 48.0*(z*z - 1)*(x-1)*(y-1)
00885             - 32.0*(x*x - 1)*(y*y - 1)*(z-1)
00886             - 32.0*(x*x - 1)*(z*z - 1)*(y-1)
00887             - 48.0*(y*y - 1)*(z*z - 1)*(x-1)
00888             + 32.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00889 
00890             tmp[23] = 32.0 - 16.0*x - 32.0*y - 32.0*z + 16.0*x*y + 16.0*x*z + 32.0*y*z - 16.0*x*y*z
00891             + 32.0*(x*x - 1)*(y-1)*(z-1)
00892             + 24.0*(y*y - 1)*(x-1)*(z-1) - 8.0*(y*y - 1)*(x+1)*(z-1)
00893             + 24.0*(z*z - 1)*(x-1)*(y-1) - 8.0*(z*z - 1)*(x+1)*(y-1)
00894             - 32.0*(x*x - 1)*(y*y - 1)*(z-1)
00895             - 32.0*(x*x - 1)*(z*z - 1)*(y-1)
00896             - 24.0*(y*y - 1)*(z*z - 1)*(x-1) + 8.0*(y*y - 1)*(z*z - 1)*(x+1)
00897             + 32.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00898 
00899             tmp[24] = 32.0 - 32.0*x - 16.0*y - 32.0*z + 16.0*x*y + 32.0*x*z + 16.0*y*z - 16.0*x*y*z
00900             + 24.0*(x*x - 1)*(y-1)*(z-1)- 8.0*(x*x - 1)*(y+1)*(z-1)
00901             + 32.0*(y*y - 1)*(x-1)*(z-1)
00902             + 24.0*(z*z - 1)*(x-1)*(y-1) - 8.0*(z*z - 1)*(x-1)*(y+1)
00903             - 32.0*(x*x - 1)*(y*y - 1)*(z-1)
00904             - 24.0*(x*x - 1)*(z*z - 1)*(y-1) + 8.0*(x*x - 1)*(z*z - 1)*(y+1)
00905             - 32.0*(y*y - 1)*(z*z - 1)*(x-1)
00906             + 32.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00907 
00908             tmp[25] = 32.0 - 32.0*x - 32.0*y - 16.0*z + 32.0*x*y + 16.0*x*z + 16.0*y*z - 16.0*x*y*z
00909             + 24.0*(x*x - 1)*(y-1)*(z-1) - 8.0*(x*x - 1)*(y-1)*(z+1)
00910             + 24.0*(y*y - 1)*(x-1)*(z-1) - 8.0*(y*y - 1)*(x-1)*(z+1)
00911             + 32.0*(z*z - 1)*(x-1)*(y-1)
00912             - 24.0*(x*x - 1)*(y*y - 1)*(z-1) + 8.0*(x*x - 1)*(y*y - 1)*(z+1)
00913             - 32.0*(x*x - 1)*(z*z - 1)*(y-1)
00914             - 32.0*(y*y - 1)*(z*z - 1)*(x-1)
00915             + 32.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00916 
00917             tmp[26] = -64.0 + 64.0*x + 64.0*y + 64.0*z - 64.0*x*y - 64.0*x*z - 64.0*y*z + 64.0*x*y*z
00918             - 64.0*(x*x - 1)*(y-1)*(z-1)
00919             - 64.0*(y*y - 1)*(x-1)*(z-1)
00920             - 64.0*(z*z - 1)*(x-1)*(y-1)
00921             + 64.0*(x*x - 1)*(y*y - 1)*(z-1)
00922             + 64.0*(x*x - 1)*(z*z - 1)*(y-1)
00923             + 64.0*(y*y - 1)*(z*z - 1)*(x-1)
00924             - 64.0*(x*x - 1)*(y*y - 1)*(z*z - 1);
00925 
00926       break;
00927     default:
00928 #ifndef TRILINOS_7
00929       SUNDANCE_ERROR("Lagrange::evalOnBrick poly order > 2");
00930 #else
00931       SUNDANCE_ERROR7("Lagrange::evalOnBrick poly order > 2");
00932 #endif
00933     }
00934 
00935   for (int i=0; i<tmp.length(); i++)
00936     {
00937       if (deriv.order()==0) result[i] = tmp[i].value();
00938       else
00939         result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00940     }
00941 }
00942 
00943 void Lagrange::getConstrainsForHNDoF(
00944   const int indexInParent,
00945   const int maxCellDim,
00946   const int maxNrChild,
00947   const int facetDim,
00948   const int facetIndex,
00949   const int nodeIndex,
00950   Array<int>& localDoFs,
00951     Array<int>& parentFacetDim,
00952     Array<int>& parentFacetIndex,
00953     Array<int>& parentFacetNode,
00954   Array<double>& coefs
00955   ) {
00956 
00957   // the index in the Parent is very important
00958   // - in case of Lagrange first get the position of the evaluation
00959   // - then evaluate the refElement at that point
00960   // - see which local DoFs are not zero and return them
00961 
00962   Array<Array<Array<double> > >    result;
00963   const SpatialDerivSpecifier      deriv;
00964   int                              index = 0;
00965 
00966   //setVerb(6);
00967 
00968   localDoFs.resize(0);
00969   coefs.resize(0);
00970   parentFacetDim.resize(0);
00971   parentFacetIndex.resize(0);
00972   parentFacetNode.resize(0);
00973 
00974   CellType maximalCellType;
00975 
00976   switch (maxCellDim){
00977   case 2:{ // 2D
00978     maximalCellType = QuadCell;
00979 
00980     switch (maxNrChild){
00981     case 9:{ //trisection on quads
00982       Point dofPos( 0.0 , 0.0 );
00983             // get the position of the DoF on the refCell
00984       SUNDANCE_OUT(this->verb() > 3 , ",maxCellDim=" << maxCellDim << ",facetDim="
00985           << facetDim << ",facetIndex=" << facetIndex << ",nodeIndex=" << nodeIndex
00986           << ",dofPos=" << dofPos);
00987       returnDoFPositionOnRef( maxCellDim,
00988         facetDim, facetIndex, nodeIndex, dofPos);
00989       dofPos = dofPos/3.0;
00990       SUNDANCE_OUT(this->verb() > 3 ,  "dofPos=" << dofPos );
00991 
00992       // shitf the position of the DOFs according to the position of the child in the parent cell
00993       switch (indexInParent){
00994         case 0: {/* nothing to add */  break;}
00995         case 1: {dofPos[0] += 1.0/3.0; break;}
00996         case 2: {dofPos[0] += 2.0/3.0; break;}
00997         case 3: {dofPos[0] += 2.0/3.0; dofPos[1] += 1.0/3.0; break;}
00998         case 5: {dofPos[1] += 1.0/3.0; break;}
00999         case 6: {dofPos[1] += 2.0/3.0; break;}
01000         case 7: {dofPos[0] += 1.0/3.0; dofPos[1] += 2.0/3.0; break;}
01001         case 8: {dofPos[0] += 2.0/3.0; dofPos[1] += 2.0/3.0; break;}
01002       }
01003 
01004       SUNDANCE_OUT(this->verb() > 3 , "dofPos=" << dofPos );
01005       Array<Point> tmp_points(1);
01006       tmp_points[0] = dofPos;
01007       refEval( maximalCellType , tmp_points ,
01008            deriv,  result , 4);
01009 
01010        break;}
01011     case 4:{ // bisection on quads
01012       Point dofPos( 0.0 , 0.0 );
01013         // get the position of the DoF on the refCell
01014       SUNDANCE_OUT(this->verb() > 3 , ",maxCellDim=" << maxCellDim << ",facetDim="
01015           << facetDim << ",facetIndex=" << facetIndex << ",nodeIndex=" << nodeIndex
01016           << ",dofPos=" << dofPos);
01017       returnDoFPositionOnRef( maxCellDim,
01018         facetDim, facetIndex, nodeIndex, dofPos);
01019       dofPos = dofPos/2.0;
01020       SUNDANCE_OUT(this->verb() > 3 ,  "dofPos=" << dofPos );
01021       // shitf the position of the DOFs according to the position of the child in the parent cell
01022       switch (indexInParent){
01023         case 0: {/* nothing to add */  break;}
01024         case 1: {dofPos[0] += 1.0/2.0; break;}
01025         case 2: {dofPos[1] += 1.0/2.0; break;}
01026         case 3: {dofPos[0] += 1.0/2.0; dofPos[1] += 1.0/2.0; break;}
01027       }
01028 
01029       SUNDANCE_OUT(this->verb() > 3 , "dofPos=" << dofPos );
01030       Array<Point> tmp_points(1);
01031       tmp_points[0] = dofPos;
01032       refEval( maximalCellType , tmp_points ,
01033              deriv,  result , 4);
01034        break;
01035        }
01036     }
01037   break;} // ------ end 2D -------
01038   case 3:{ //  ----- 3D ------------
01039 
01040     maximalCellType = BrickCell;
01041 
01042     Point dofPos( 0.0 , 0.0 , 0.0);
01043         // get the position of the DoF on the refCell
01044     SUNDANCE_OUT(this->verb() > 3 , ",maxCellDim=" << maxCellDim << ",facetDim="
01045         << facetDim << ",facetIndex=" << facetIndex << ",nodeIndex=" << nodeIndex
01046         << ",dofPos=" << dofPos);
01047     returnDoFPositionOnRef( maxCellDim,
01048       facetDim, facetIndex, nodeIndex, dofPos);
01049 
01050     // shitf the position of the DOFs according to the position of the child in the parent cell
01051     switch (maxNrChild){
01052     case 27:{ // tri section on bricks
01053       dofPos = dofPos/3.0;
01054       SUNDANCE_OUT(this->verb() > 3 ,  "dofPos=" << dofPos );
01055       switch (indexInParent){
01056         case 0:  {dofPos[0] += 0.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 0.0/3.0; break;}
01057         case 1:  {dofPos[0] += 1.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 0.0/3.0; break;}
01058         case 2:  {dofPos[0] += 2.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 0.0/3.0; break;}
01059         case 3:  {dofPos[0] += 0.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 0.0/3.0; break;}
01060         case 4:  {dofPos[0] += 1.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 0.0/3.0; break;}
01061         case 5:  {dofPos[0] += 2.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 0.0/3.0; break;}
01062         case 6:  {dofPos[0] += 0.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 0.0/3.0; break;}
01063         case 7:  {dofPos[0] += 1.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 0.0/3.0; break;}
01064         case 8:  {dofPos[0] += 2.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 0.0/3.0; break;}
01065         case 9:  {dofPos[0] += 0.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 1.0/3.0; break;}
01066         case 10: {dofPos[0] += 1.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 1.0/3.0; break;}
01067         case 11: {dofPos[0] += 2.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 1.0/3.0; break;}
01068         case 12: {dofPos[0] += 0.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 1.0/3.0; break;}
01069         // 13 should never occur !!!!
01070         case 13: {dofPos[0] += 1.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 1.0/3.0; break;}
01071         case 14: {dofPos[0] += 2.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 1.0/3.0; break;}
01072         case 15: {dofPos[0] += 0.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 1.0/3.0; break;}
01073         case 16: {dofPos[0] += 1.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 1.0/3.0; break;}
01074         case 17: {dofPos[0] += 2.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 1.0/3.0; break;}
01075         case 18: {dofPos[0] += 0.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 2.0/3.0; break;}
01076         case 19: {dofPos[0] += 1.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 2.0/3.0; break;}
01077         case 20: {dofPos[0] += 2.0/3.0; dofPos[1] += 0.0/3.0; dofPos[2] += 2.0/3.0; break;}
01078         case 21: {dofPos[0] += 0.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 2.0/3.0; break;}
01079         case 22: {dofPos[0] += 1.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 2.0/3.0; break;}
01080         case 23: {dofPos[0] += 2.0/3.0; dofPos[1] += 1.0/3.0; dofPos[2] += 2.0/3.0; break;}
01081         case 24: {dofPos[0] += 0.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 2.0/3.0; break;}
01082         case 25: {dofPos[0] += 1.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 2.0/3.0; break;}
01083         case 26: {dofPos[0] += 2.0/3.0; dofPos[1] += 2.0/3.0; dofPos[2] += 2.0/3.0; break;}
01084       }
01085     break;}
01086     case 8:{ // bisection on bricks
01087       dofPos = dofPos/2.0;
01088       SUNDANCE_OUT(this->verb() > 3 ,  "dofPos=" << dofPos );
01089       switch (indexInParent){
01090         case 0:  {dofPos[0] += 0.0/2.0; dofPos[1] += 0.0/2.0; dofPos[2] += 0.0/2.0; break;}
01091         case 1:  {dofPos[0] += 1.0/2.0; dofPos[1] += 0.0/2.0; dofPos[2] += 0.0/2.0; break;}
01092         case 2:  {dofPos[0] += 0.0/2.0; dofPos[1] += 1.0/2.0; dofPos[2] += 0.0/2.0; break;}
01093         case 3:  {dofPos[0] += 1.0/2.0; dofPos[1] += 1.0/2.0; dofPos[2] += 0.0/2.0; break;}
01094         case 4:  {dofPos[0] += 0.0/2.0; dofPos[1] += 0.0/2.0; dofPos[2] += 1.0/2.0; break;}
01095         case 5:  {dofPos[0] += 1.0/2.0; dofPos[1] += 0.0/2.0; dofPos[2] += 1.0/2.0; break;}
01096         case 6:  {dofPos[0] += 0.0/2.0; dofPos[1] += 1.0/2.0; dofPos[2] += 1.0/2.0; break;}
01097         case 7:  {dofPos[0] += 1.0/2.0; dofPos[1] += 1.0/2.0; dofPos[2] += 1.0/2.0; break;}
01098       }
01099     break;}
01100     }
01101 
01102     SUNDANCE_OUT(this->verb() > 3 , "dofPos=" << dofPos );
01103     Array<Point> tmp_points(1);
01104     tmp_points[0] = dofPos;
01105     refEval( maximalCellType , tmp_points ,
01106          deriv,  result , 4);
01107 
01108   break;} //end 3D
01109   }
01110 
01111     // evalute the results from the bi or trisection
01112   Array<double>& res = result[0][0];
01113   //SUNDANCE_OUT(this->verb() > 3 , "res=" << res );
01114 
01115   // get those data only once (since it is rather costly)
01116   if (doFInfromationCalculated_ == false)
01117   {
01118     getDoFsOrdered( maximalCellType, res.size() , facetD_, facetI_, facetN_);
01119     doFInfromationCalculated_ = true;
01120   }
01121 
01122   // here take the "result" array and get the nonzero elements
01123   index = 0;
01124   for ( int i=0 ; i < res.size() ; i++){
01125     // take only those DoFs which are non zero
01126     if ( fabs(res[i]) > 1e-5 ){
01127       SUNDANCE_OUT(this->verb() > 3 , "found DoF i=" << i );
01128       localDoFs.resize(index+1);
01129       coefs.resize(index+1);
01130       parentFacetDim.resize(index+1);
01131       parentFacetIndex.resize(index+1);
01132       parentFacetNode.resize(index+1);
01133       localDoFs[index] = i;
01134       coefs[index] = res[i];
01135       parentFacetDim[index] = facetD_[i];
01136       parentFacetIndex[index] = facetI_[i];
01137       parentFacetNode[index] = facetN_[i];
01138       index++;
01139     }
01140   }
01141 
01142   SUNDANCE_OUT(this->verb() > 3 , "localDoFs=" << localDoFs );
01143   SUNDANCE_OUT(this->verb() > 3 , "coefs=" << coefs );
01144   SUNDANCE_OUT(this->verb() > 3 , "parentFacetDim=" << parentFacetDim );
01145   SUNDANCE_OUT(this->verb() > 3 , "parentFacetIndex=" << parentFacetIndex );
01146   SUNDANCE_OUT(this->verb() > 3 , "parentFacetNode=" << parentFacetNode );
01147 
01148 }
01149 
01150 /* -------------- Get the position of one DoF ----------------------- */
01151 void Lagrange::returnDoFPositionOnRef(
01152   const int maxCellDim,
01153   const int facetDim,
01154   const int facetIndex,
01155   const int nodeIndex,
01156   Point& pos) const {
01157 
01158   switch (facetDim){
01159   case 0:{  // Point DoFs
01160     switch (maxCellDim){
01161     case 2:{
01162       switch (facetIndex){
01163       case 0: {pos[0] = 0.0; pos[1] = 0.0; break;}
01164       case 1: {pos[0] = 1.0; pos[1] = 0.0; break;}
01165       case 2: {pos[0] = 0.0; pos[1] = 1.0; break;}
01166       case 3: {pos[0] = 1.0; pos[1] = 1.0; break;}
01167       }
01168       break;}
01169     case 3:{
01170       switch (facetIndex){
01171       case 0: {pos[0] = 0.0; pos[1] = 0.0; pos[2] = 0.0; break;}
01172       case 1: {pos[0] = 1.0; pos[1] = 0.0; pos[2] = 0.0; break;}
01173       case 2: {pos[0] = 0.0; pos[1] = 1.0; pos[2] = 0.0; break;}
01174       case 3: {pos[0] = 1.0; pos[1] = 1.0; pos[2] = 0.0; break;}
01175       case 4: {pos[0] = 0.0; pos[1] = 0.0; pos[2] = 1.0; break;}
01176       case 5: {pos[0] = 1.0; pos[1] = 0.0; pos[2] = 1.0; break;}
01177       case 6: {pos[0] = 0.0; pos[1] = 1.0; pos[2] = 1.0; break;}
01178       case 7: {pos[0] = 1.0; pos[1] = 1.0; pos[2] = 1.0; break;}
01179       }
01180       break;}
01181     }
01182     break;}
01183   case 1:{  // Edge DoFs
01184     switch (maxCellDim){
01185     case 2:{
01186       // here we calculate the position of the DoF on the edge
01187       double posOnEdge = (1.0/ (double)(order())) +(double)(nodeIndex) / (double)(order()-1);
01188       switch (facetIndex){
01189       case 0: {pos[0] = 0.0+posOnEdge; pos[1] = 0.0; break;}
01190       case 1: {pos[0] = 0.0; pos[1] = 0.0+posOnEdge; break;}
01191       case 2: {pos[0] = 1.0; pos[1] = 0.0+posOnEdge; break;}
01192       case 3: {pos[0] = 0.0+posOnEdge; pos[1] = 1.0; break;}
01193       }
01194       break;}
01195     case 3:{ // Edge in the brick test this
01196       double posOnEdge = (1.0/ (double)(order())) +(double)(nodeIndex) / (double)(order()-1);
01197       switch (facetIndex){
01198       case 0: {pos[0] = 0.0+posOnEdge; pos[1] = 0.0; pos[2] = 0.0; break;}
01199       case 1: {pos[0] = 0.0; pos[1] = 0.0+posOnEdge; pos[2] = 0.0; break;}
01200       case 2: {pos[0] = 0.0; pos[1] = 0.0; pos[2] = 0.0+posOnEdge; break;}
01201       case 3: {pos[0] = 1.0; pos[1] = 0.0+posOnEdge; pos[2] = 0.0; break;}
01202       case 4: {pos[0] = 1.0; pos[1] = 0.0; pos[2] = 0.0+posOnEdge; break;}
01203       case 5: {pos[0] = 0.0+posOnEdge; pos[1] = 1.0; pos[2] = 0.0; break;}
01204       case 6: {pos[0] = 0.0; pos[1] = 1.0; pos[2] = 0.0+posOnEdge; break;}
01205       case 7: {pos[0] = 1.0; pos[1] = 1.0; pos[2] = 0.0+posOnEdge; break;}
01206       case 8: {pos[0] = 0.0+posOnEdge; pos[1] = 0.0; pos[2] = 1.0; break;}
01207       case 9: {pos[0] = 0.0; pos[1] = 0.0+posOnEdge; pos[2] = 1.0; break;}
01208       case 10: {pos[0] = 1.0; pos[1] = 0.0+posOnEdge; pos[2] = 1.0; break;}
01209       case 11: {pos[0] = 0.0+posOnEdge; pos[1] = 1.0; pos[2] = 1.0; break;}
01210       }
01211       break;}
01212     }
01213     break;}
01214   case 2:{ //face DoFs only in 3D
01215     // DoFs position on the face
01216     int nrDoFoFace = (order()-1)*(order()-1);
01217     double posOnFace1 = (1.0/ (double)(order())) +(double)(nodeIndex % nrDoFoFace) / (double)(order()-1);
01218     double posOnFace2 = (1.0/ (double)(order())) +(double)(nodeIndex / nrDoFoFace) / (double)(order()-1);
01219     switch (facetIndex){
01220     case 0: {pos[0] = 0.0+posOnFace1; pos[1] = 0.0+posOnFace2; pos[2] = 0.0; break;}
01221     case 1: {pos[0] = 0.0+posOnFace1; pos[1] = 0.0; pos[2] = 0.0+posOnFace2; break;}
01222     case 2: {pos[0] = 0.0; pos[1] = 0.0+posOnFace1; pos[2] = 0.0+posOnFace2; break;}
01223     case 3: {pos[0] = 1.0; pos[1] = 0.0+posOnFace1; pos[2] = 0.0+posOnFace2; break;}
01224     case 4: {pos[0] = 0.0+posOnFace1; pos[1] = 1.0; pos[2] = 0.0+posOnFace2; break;}
01225     case 5: {pos[0] = 0.0+posOnFace1; pos[1] = 0.0+posOnFace2; pos[2] = 1.0; break;}
01226     }
01227     break;}
01228   }
01229 
01230 }
01231 
01232 void Lagrange::getDoFsOrdered(
01233     const CellType maxCellDim,
01234     int nrDoF,
01235     Array<int>& facetD,
01236     Array<int>& facetI,
01237     Array<int>& facetN)
01238 {
01239   // this could be done once at initialization
01240   // ----------------------------------------------------------------
01241   Array<Array<Array<int> > > dofs_struct;
01242   getReferenceDOFs(maxCellDim , maxCellDim , dofs_struct);
01243   bool getNext;
01244   facetD.resize(nrDoF); facetI.resize(nrDoF); facetN.resize(nrDoF);
01245   int dimo=0 , indexo=0 , nodo=0;
01246   for ( int i=0 ; i < nrDoF ; i++){
01247     facetD[i] = dimo;
01248     facetI[i] = indexo;
01249     facetN[i] = nodo;
01250     // found the next DoF and change the variables
01251     // nodo,indexo,dimo
01252     getNext = true;
01253     while ( (getNext) && (dimo < dofs_struct.size() )){
01254       //SUNDANCE_OUT(this->verb() > 3, "dimo=" << dimo << " ,indexo:" << indexo << ",nodo:" << nodo <<
01255       //    ",maxCellDim:" << maxCellDim << " ,nrDoF:" << nrDoF);
01256       if (dofs_struct[dimo].size() > (indexo+1))
01257       {
01258           if (dofs_struct[dimo][indexo].size() > (nodo+1)){
01259           nodo++; getNext = false;
01260          }else{
01261           nodo = 0;
01262           if (dofs_struct[dimo].size() > (indexo+1)){
01263             indexo++; getNext = false;
01264           }else{
01265             indexo = 0;
01266             if (dofs_struct.size() > (dimo+1)){
01267               dimo++; getNext = false;
01268             }else{
01269               // actually we should not arrived here
01270               getNext = false;
01271             }
01272           }
01273          }
01274         }
01275         else
01276         {
01277                dimo++; indexo = 0; nodo = 0; getNext = false;
01278       }
01279       //SUNDANCE_OUT(this->verb() > 3, "dofs_struct.size()=" << dofs_struct.size() << " ,dofs_struct[dimo].size():"
01280       //    << dofs_struct[dimo].size() << ",dofs_struct[dimo][indexo].size():" << dofs_struct[dimo][indexo].size());
01281       if (dofs_struct.size() <= dimo ) {dimo++; getNext = true; continue;}
01282       if (dofs_struct[dimo].size() <= indexo ) {dimo++; getNext = true; continue;}
01283       if (dofs_struct[dimo][indexo].size() <= nodo ) {dimo++; getNext = true; continue;}
01284     }
01285   }
01286   SUNDANCE_OUT(this->verb() > 3, "facetD=" << facetD );
01287   SUNDANCE_OUT(this->verb() > 3, "facetI=" << facetI );
01288   SUNDANCE_OUT(this->verb() > 3, "facetN=" << facetN );
01289     // ------------------------------------------------
01290 }

Site Contact