SundanceElementIntegral.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 "SundanceElementIntegral.hpp"
00043 #include "SundanceOut.hpp"
00044 #include "PlayaTabs.hpp"
00045 #include "Teuchos_TimeMonitor.hpp"
00046 
00047 using namespace Sundance;
00048 using namespace Teuchos;
00049 
00050 using std::endl;
00051 
00052 static Time& transCreationTimer() 
00053 {
00054   static RCP<Time> rtn 
00055     = TimeMonitor::getNewTimer("building integral transformation matrices"); 
00056   return *rtn;
00057 }
00058 
00059 
00060 bool& ElementIntegral::alwaysUseCofacets()
00061 {
00062   static bool rtn = true;
00063   return rtn;
00064 }
00065 
00066 ElementIntegral::ElementIntegral(int spatialDim,
00067   const CellType& maxCellType,
00068   int dim, 
00069   const CellType& cellType,
00070   bool isInternalBdry,
00071   const ParametrizedCurve& globalCurve,
00072   const Mesh& mesh,
00073   int verb)
00074   : setupVerb_(verb),
00075     integrationVerb_(0),
00076     transformVerb_(0),
00077     spatialDim_(spatialDim),
00078     dim_(dim),
00079     isInternalBdry_(isInternalBdry),
00080     nFacetCases_(1),
00081     testDerivOrder_(-1), 
00082     nRefDerivTest_(-1),
00083     nNodesTest_(-1),
00084     unkDerivOrder_(-1), 
00085     nRefDerivUnk_(-1),
00086     nNodesUnk_(-1),
00087     nNodes_(-1),
00088     order_(0),
00089     alpha_(),
00090     beta_(),
00091     cellType_(cellType),
00092     maxCellType_(maxCellType),
00093     evalCellType_(cellType),
00094     testBasis_(),
00095     unkBasis_(),
00096     globalCurve_(globalCurve),
00097     mesh_(mesh)
00098 {
00099   Tabs tab0;
00100   SUNDANCE_MSG2(setupVerb(), tab0 << "constructing 0-form ElementIntegral");
00101   /* if we're integrating a derivative along a facet, we need to refer back
00102    * to the maximal cell. */
00103   if (alwaysUseCofacets() || (dim != spatialDim && !isInternalBdry))
00104   {
00105     evalCellType_ = maxCellType_;
00106     nFacetCases_ = numFacets(maxCellType, dim);
00107   }
00108 }
00109 
00110 ElementIntegral::ElementIntegral(int spatialDim,
00111   const CellType& maxCellType,
00112   int dim, 
00113   const CellType& cellType,
00114   const BasisFamily& testBasis,
00115   int alpha,
00116   int testDerivOrder,
00117   bool isInternalBdry,
00118   const ParametrizedCurve& globalCurve,
00119   const Mesh& mesh,
00120   int verb)
00121   : setupVerb_(verb),
00122     integrationVerb_(0),
00123     transformVerb_(0),
00124     spatialDim_(spatialDim),
00125     dim_(dim),
00126     isInternalBdry_(isInternalBdry),
00127     nFacetCases_(1),
00128     testDerivOrder_(testDerivOrder), 
00129     nRefDerivTest_(ipow(spatialDim, testDerivOrder)),
00130     nNodesTest_(testBasis.nReferenceDOFsWithFacets(maxCellType, cellType)),
00131     unkDerivOrder_(-1), 
00132     nRefDerivUnk_(-1),
00133     nNodesUnk_(-1),
00134     nNodes_(nNodesTest_),
00135     order_(1),
00136     alpha_(alpha),
00137     beta_(-1),
00138     cellType_(cellType),
00139     maxCellType_(maxCellType),
00140     evalCellType_(cellType),
00141     testBasis_(testBasis),
00142     unkBasis_(),
00143     globalCurve_(globalCurve),
00144     mesh_(mesh)
00145 {
00146   Tabs tab0(0);
00147   SUNDANCE_MSG2(setupVerb(), tab0 << "constructing 1-form ElementIntegral");
00148   /* if we're integrating a derivative along a facet, we 
00149    * may need to refer back to the maximal cell. */
00150   bool okToRestrictTestToBdry = basisRestrictableToBoundary(testBasis);
00151     
00152   Tabs tab1;
00153   SUNDANCE_MSG2(setupVerb(), tab1 << "dim=" << dim << " spatialDim=" << spatialDim);
00154   if (dim != spatialDim)
00155   {
00156     if (isInternalBdry)
00157     {
00158       TEUCHOS_TEST_FOR_EXCEPT(!okToRestrictTestToBdry);
00159     }
00160     if (alwaysUseCofacets() || testDerivOrder>0)
00161     {
00162       Tabs tab2;
00163       evalCellType_ = maxCellType_;
00164       nFacetCases_ = numFacets(maxCellType, dim);
00165       nNodesTest_ = testBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
00166       SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesTest=" << nNodesTest_);
00167       nNodes_ = nNodesTest_;
00168       TEUCHOS_TEST_FOR_EXCEPT(nNodes_ == 0);
00169     }
00170     else
00171     {
00172       TEUCHOS_TEST_FOR_EXCEPT(!okToRestrictTestToBdry);
00173     }
00174   }
00175 
00176   SUNDANCE_MSG2(setupVerb(), tab1 << "nNodes=" << nNodes_);
00177 }
00178 
00179 
00180 
00181 ElementIntegral::ElementIntegral(int spatialDim,
00182   const CellType& maxCellType,
00183   int dim,
00184   const CellType& cellType,
00185   const BasisFamily& testBasis,
00186   int alpha,
00187   int testDerivOrder,
00188   const BasisFamily& unkBasis,
00189   int beta,
00190   int unkDerivOrder,
00191   bool isInternalBdry,
00192   const ParametrizedCurve& globalCurve,
00193   const Mesh& mesh,
00194   int verb)
00195   : setupVerb_(verb),
00196     integrationVerb_(0),
00197     transformVerb_(0),
00198     spatialDim_(spatialDim),
00199     dim_(dim),
00200     isInternalBdry_(isInternalBdry),
00201     nFacetCases_(1),
00202     testDerivOrder_(testDerivOrder), 
00203     nRefDerivTest_(ipow(spatialDim, testDerivOrder)),
00204     nNodesTest_(testBasis.nReferenceDOFsWithFacets(maxCellType, cellType)), 
00205     unkDerivOrder_(unkDerivOrder), 
00206     nRefDerivUnk_(ipow(spatialDim, unkDerivOrder)),
00207     nNodesUnk_(unkBasis.nReferenceDOFsWithFacets(maxCellType, cellType)), 
00208     nNodes_(nNodesTest_*nNodesUnk_),
00209     order_(2),
00210     alpha_(alpha),
00211     beta_(beta),
00212     cellType_(cellType),
00213     maxCellType_(maxCellType),
00214     evalCellType_(cellType),
00215     testBasis_(testBasis),
00216     unkBasis_(unkBasis),
00217     globalCurve_(globalCurve),
00218     mesh_(mesh)
00219 {
00220   Tabs tab0(0);
00221   SUNDANCE_MSG2(setupVerb(), tab0 
00222     << "***** constructing 2-form ElementIntegral");
00223   /* if we're integrating a derivative along a facet, we may need to refer back
00224    * to the maximal cell. */
00225   bool okToRestrictTestToBdry = basisRestrictableToBoundary(testBasis);
00226   bool okToRestrictUnkToBdry = basisRestrictableToBoundary(unkBasis);
00227 
00228     
00229   Tabs tab1;
00230   SUNDANCE_MSG2(setupVerb(), tab1 << "dim=" << dim << " spatialDim=" << spatialDim);
00231   if (dim != spatialDim)
00232   {
00233     if (isInternalBdry)
00234     {
00235       TEUCHOS_TEST_FOR_EXCEPT(!(okToRestrictTestToBdry && okToRestrictUnkToBdry));   
00236     }
00237     if (alwaysUseCofacets() || testDerivOrder>0 || unkDerivOrder>0)
00238     {
00239       Tabs tab2;
00240       evalCellType_ = maxCellType_;
00241       nFacetCases_ = numFacets(maxCellType, dim);
00242       nNodesTest_ = testBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
00243       SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesTest=" << nNodesTest_);
00244       nNodesUnk_ = unkBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
00245       SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesUnk=" << nNodesUnk_);
00246       nNodes_ = nNodesTest_ * nNodesUnk_;
00247       TEUCHOS_TEST_FOR_EXCEPT(nNodes_ == 0);
00248     }
00249     else
00250     {
00251       TEUCHOS_TEST_FOR_EXCEPT(okToRestrictTestToBdry != okToRestrictUnkToBdry);
00252     }
00253   }
00254 
00255   SUNDANCE_MSG2(setupVerb(), tab1 << "nNodes=" << nNodes_);
00256 }
00257 
00258 
00259 void ElementIntegral::setVerb(
00260   int integrationVerb,
00261   int transformVerb)
00262 {
00263   integrationVerb_ = integrationVerb;
00264   transformVerb_ = transformVerb;
00265 }
00266 
00267 void ElementIntegral::describe(std::ostream& os) const 
00268 {
00269   Tabs tab(0);
00270   bool hasTest = testDerivOrder() >= 0;
00271   bool hasUnk = unkDerivOrder() >= 0;
00272 
00273   if (hasTest)
00274   {
00275     os << tab << "Test functions:" << std::endl;
00276     Tabs tab1;
00277     os << tab1 << "test basis = " << testBasis() << std::endl;
00278     os << tab1 << "test differentiation order = " << testDerivOrder() << std::endl;
00279     os << tab1 << "alpha = " << alpha() << std::endl;
00280     os << tab1 << "num test gradient components=" << nRefDerivTest() << std::endl;
00281   }
00282   if (hasUnk)
00283   {
00284     os << tab << "Unknown functions:" << std::endl;
00285     Tabs tab1;
00286     os << tab1 << "unk basis = " << unkBasis() << std::endl;
00287     os << tab1 << "unk differentiation order = " << unkDerivOrder() << std::endl;
00288     os << tab1 << "beta = " << beta() << std::endl;
00289     os << tab1  << "num unk gradient components=" << nRefDerivUnk() << std::endl;
00290   }
00291   os << tab << "Geometry:" << std::endl;
00292   Tabs tab1;
00293   os << tab1 << "cell type on which integral is defined: " << cellType()
00294      << std::endl;
00295   os << tab1 << "maximal cell type: " << maxCellType() << std::endl;
00296   os << tab1 << "cell type on which quad pts defined: " << evalCellType()
00297      << std::endl;
00298   os << tab << "Number of evaluation cases: " << nFacetCases() << std::endl;
00299 }
00300 
00301 
00302 void ElementIntegral::assertBilinearForm() const 
00303 {
00304   TEUCHOS_TEST_FOR_EXCEPTION(testDerivOrder() < 0 || testDerivOrder() > 1,
00305     std::logic_error,
00306     "Test function derivative order=" << testDerivOrder()
00307     << " must be 0 or 1");
00308   
00309   TEUCHOS_TEST_FOR_EXCEPTION(unkDerivOrder() < 0 || unkDerivOrder() > 1,
00310     std::logic_error,
00311     "Unknown function derivative order=" << unkDerivOrder()
00312     << " must be 0 or 1");
00313 }
00314 
00315 void ElementIntegral::assertLinearForm() const 
00316 {
00317   TEUCHOS_TEST_FOR_EXCEPTION(testDerivOrder() < 0 || testDerivOrder() > 1,
00318     std::logic_error,
00319     "Test function derivative order=" << testDerivOrder()
00320     << " must be 0 or 1");
00321 }
00322 
00323 
00324 void ElementIntegral::getQuad(const QuadratureFamily& quad,
00325   int evalCase, Array<Point>& quadPts, Array<double>& quadWeights) const 
00326 {
00327   Tabs tab(0);
00328 
00329   SUNDANCE_MSG2(setupVerb(), tab << "getting quad points for rule "
00330     << quad);
00331 
00332   if (nFacetCases()==1) 
00333   {
00334     quad.getPoints(cellType(), quadPts, quadWeights);
00335   }
00336   else 
00337   {
00338     int dim = dimension(cellType());
00339     quad.getFacetPoints(maxCellType(), dim, evalCase, 
00340       quadPts, quadWeights);
00341   }
00342 
00343   if (setupVerb() >= 4)
00344   {
00345     Tabs tab1;
00346     SUNDANCE_MSG4(setupVerb(), 
00347       tab1 << "quadrature points on ref cell are:");
00348     printQuad(Out::os(), quadPts, quadWeights);
00349   }
00350 }
00351   
00352 
00353 
00354 Array<double>& ElementIntegral::G(int alpha)
00355 {
00356   static Array<Array<double> > rtn(3);
00357 
00358   return rtn[alpha];
00359 }
00360 
00361 Array<double>& ElementIntegral::G(int alpha, int beta)
00362 {
00363   static Array<Array<double> > rtn(9);
00364 
00365   return rtn[3*alpha + beta];
00366 }
00367 
00368 int& ElementIntegral::transformationMatrixIsValid(int alpha, int beta)
00369 {
00370   static Array<int> rtn(9, false);
00371   return rtn[3*alpha + beta];
00372 }
00373 
00374 int& ElementIntegral::transformationMatrixIsValid(int alpha)
00375 {
00376   static Array<int> rtn(3, false);
00377   return rtn[alpha];
00378 }
00379 
00380 void ElementIntegral::invalidateTransformationMatrices()
00381 {
00382   for (int i=0; i<3; i++)
00383   {
00384     transformationMatrixIsValid(i) = false;
00385     for (int j=0; j<3; j++)
00386     {
00387       transformationMatrixIsValid(i, j) = false;
00388     }
00389   }
00390 }
00391 
00392 
00393 
00394 
00395 int ElementIntegral::ipow(int base, int power) 
00396 {
00397   int rtn = 1;
00398   for (int i=0; i<power; i++) rtn *= base;
00399   return rtn;
00400 }
00401 
00402 void ElementIntegral
00403 ::createTwoFormTransformationMatrix(const CellJacobianBatch& JTrans,
00404   const CellJacobianBatch& JVol) const
00405 {
00406   TimeMonitor timer(transCreationTimer());
00407   Tabs tab;
00408 
00409   int flops = 0;
00410 
00411   int maxDim = JTrans.cellDim();
00412   //int cellDim = JVol.cellDim();
00413 
00414   if (testDerivOrder() == 1 && unkDerivOrder() == 1)
00415   {
00416     Tabs tab2;
00417     if (transformationMatrixIsValid(alpha(), beta())) return;
00418     transformationMatrixIsValid(alpha(), beta()) = true;
00419 
00420     G(alpha(), beta()).resize(JTrans.numCells() * JTrans.cellDim() * JTrans.cellDim());
00421 
00422     double* GPtr = &(G(alpha(),beta())[0]);
00423     int k = 0;
00424 
00425     for (int c=0; c<JTrans.numCells(); c++)
00426     {
00427       static Array<double> invJ;
00428       JTrans.getInvJ(c, invJ);
00429       double detJ = fabs(JVol.detJ()[c]);
00430       for (int gamma=0; gamma<maxDim; gamma++)
00431       {
00432         for (int delta=0; delta<maxDim; delta++, k++)
00433         {
00434           GPtr[k] =  detJ*invJ[alpha() + gamma*maxDim]
00435             * invJ[beta() + maxDim*delta];
00436         }
00437       }
00438     }
00439     flops = 2 * JTrans.numCells() * maxDim * maxDim + JTrans.numCells();
00440   }
00441 
00442   else if (testDerivOrder() == 1 && unkDerivOrder() == 0)
00443   {
00444     if (transformationMatrixIsValid(alpha())) return;
00445     transformationMatrixIsValid(alpha()) = true;
00446 
00447     G(alpha()).resize(JTrans.numCells() * JTrans.cellDim());
00448 
00449     int k = 0;
00450     double* GPtr = &(G(alpha())[0]);
00451 
00452     for (int c=0; c<JTrans.numCells(); c++)
00453     {
00454       static Array<double> invJ;
00455       JTrans.getInvJ(c, invJ);
00456       double detJ = fabs(JVol.detJ()[c]);
00457       for (int gamma=0; gamma<maxDim; gamma++,k++)
00458       {
00459         GPtr[k] = detJ*invJ[alpha() + maxDim * gamma];
00460       }
00461     }
00462     flops = JTrans.numCells() * maxDim + JTrans.numCells();
00463   }
00464 
00465   else 
00466   {
00467     if (transformationMatrixIsValid(beta())) return;
00468     transformationMatrixIsValid(beta()) = true;
00469 
00470     G(beta()).resize(JTrans.numCells() * JTrans.cellDim());
00471 
00472     int k = 0;
00473     double* GPtr = &(G(beta())[0]);
00474 
00475     for (int c=0; c<JTrans.numCells(); c++)
00476     {
00477       static Array<double> invJ;
00478       JTrans.getInvJ(c, invJ);
00479       double detJ = fabs(JVol.detJ()[c]);
00480       for (int gamma=0; gamma<maxDim; gamma++,k++)
00481       {
00482         GPtr[k] = detJ*invJ[beta() + maxDim * gamma];
00483       }
00484     }
00485     flops = JTrans.numCells() * maxDim + JTrans.numCells();
00486   }
00487 
00488   addFlops(flops);
00489 }
00490 
00491 
00492 void ElementIntegral
00493 ::createOneFormTransformationMatrix(const CellJacobianBatch& JTrans,
00494   const CellJacobianBatch& JVol) const 
00495 {
00496   TimeMonitor timer(transCreationTimer());
00497   Tabs tab;
00498   SUNDANCE_MSG2(transformVerb(), 
00499     tab << "ElementIntegral creating linear form trans matrices");
00500 
00501   int maxDim = JTrans.cellDim();
00502 
00503   if (transformationMatrixIsValid(alpha())) return;
00504   transformationMatrixIsValid(alpha()) = true;
00505 
00506   int flops = JTrans.numCells() * maxDim + JTrans.numCells();
00507 
00508   G(alpha()).resize(JTrans.numCells() * JTrans.cellDim());
00509 
00510   int k = 0;
00511   double* GPtr = &(G(alpha())[0]);
00512 
00513   for (int c=0; c<JTrans.numCells(); c++)
00514   {
00515     Array<double> invJ;
00516     JTrans.getInvJ(c, invJ);
00517     double detJ = fabs(JVol.detJ()[c]);
00518     for (int gamma=0; gamma<maxDim; gamma++, k++)
00519     {
00520       GPtr[k] = detJ*invJ[alpha() + maxDim * gamma]; 
00521     }
00522   }
00523   
00524   addFlops(flops);
00525 }
00526 

Site Contact