SundanceQuadratureIntegral.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 "SundanceQuadratureIntegral.hpp"
00032 #include "SundanceGaussianQuadrature.hpp"
00033 #include "SundanceSpatialDerivSpecifier.hpp"
00034 #include "SundanceOut.hpp"
00035 #include "PlayaTabs.hpp"
00036 #include "Teuchos_TimeMonitor.hpp"
00037 
00038 using namespace Sundance;
00039 using namespace Teuchos;
00040 
00041 using std::endl;
00042 using std::setw;
00043 using std::setprecision;
00044 
00045 extern "C" 
00046 {
00047 int dgemm_(const char* transA, const char* transB,
00048   const int* M, const int *N, const int* K,
00049   const double* alpha, 
00050   const double* A, const int* ldA,
00051   const double* B, const int* ldB,
00052   const double* beta,
00053   double* C, const int* ldC);
00054 }
00055 
00056 static Time& quadrature0Timer() 
00057 {
00058   static RCP<Time> rtn
00059     = TimeMonitor::getNewTimer("0-form quadrature"); 
00060   return *rtn;
00061 }
00062 
00063 static Time& quadrature1Timer() 
00064 {
00065   static RCP<Time> rtn
00066     = TimeMonitor::getNewTimer("1-form quadrature"); 
00067   return *rtn;
00068 }
00069 
00070 static Time& quadrature2Timer() 
00071 {
00072   static RCP<Time> rtn
00073     = TimeMonitor::getNewTimer("2-form quadrature"); 
00074   return *rtn;
00075 }
00076 
00077 
00078 QuadratureIntegral::QuadratureIntegral(int spatialDim,
00079   const CellType& maxCellType,
00080   int dim, 
00081   const CellType& cellType,
00082   const QuadratureFamily& quad,
00083   bool isInternalBdry,
00084   const ParametrizedCurve& globalCurve,
00085   const Mesh& mesh,
00086   int verb)
00087   : QuadratureIntegralBase(spatialDim, maxCellType, dim, cellType, quad, 
00088     isInternalBdry, globalCurve, mesh, verb),
00089     W_(),
00090     useSumFirstMethod_(true)
00091 {
00092   Tabs tab0(0);
00093   
00094   SUNDANCE_MSG1(setupVerb(), tab0 << "QuadratureIntegral ctor for 0-form");
00095   if (setupVerb()) describe(Out::os());
00096   
00097   SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);  
00098 
00099 
00100   W_.resize(nFacetCases());
00101   quadPts_.resize(nFacetCases());
00102   quadWeights_.resize(nFacetCases());
00103   quad_ = quad;
00104 
00105   for (int fc=0; fc<nFacetCases(); fc++)
00106   {
00107     Tabs tab2;
00108     SUNDANCE_MSG1(setupVerb(), tab2 << "facet case=" << fc
00109       << " of " << nFacetCases());        
00110     Tabs tab3;
00111     /* create the quad points and weights */
00112     Array<double> quadWeights;
00113     Array<Point> quadPts;
00114     getQuad(quad, fc, quadPts, quadWeights);
00115     nQuad_ = quadPts.size();
00116     quadPts_[fc] = quadPts;
00117     quadWeights_[fc] = quadWeights;
00118       
00119     W_[fc].resize(nQuad());
00120       
00121     for (int q=0; q<nQuad(); q++)
00122     {
00123       W_[fc][q] = quadWeights[q];
00124     }
00125   }    
00126 }
00127 
00128 
00129 QuadratureIntegral::QuadratureIntegral(int spatialDim,
00130   const CellType& maxCellType,
00131   int dim, 
00132   const CellType& cellType,
00133   const BasisFamily& testBasis,
00134   int alpha,
00135   int testDerivOrder,
00136   const QuadratureFamily& quad,
00137   bool isInternalBdry,
00138   const ParametrizedCurve& globalCurve,
00139   const Mesh& mesh,
00140   int verb)
00141   : QuadratureIntegralBase(spatialDim, maxCellType, dim, cellType, 
00142     testBasis, alpha, testDerivOrder, quad , isInternalBdry, globalCurve , mesh, verb),
00143     W_(),
00144     useSumFirstMethod_(true)
00145 {
00146   Tabs tab0;
00147   
00148   SUNDANCE_MSG1(setupVerb(), tab0 << "QuadratureIntegral ctor for 1-form");
00149   if (setupVerb()) describe(Out::os());
00150   assertLinearForm();
00151 
00152   
00153   SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);  
00154   
00155   quad_ = quad;
00156   W_.resize(nFacetCases());
00157   // store the quadrature points and weights
00158   quadPts_.resize(nFacetCases());
00159   quadWeights_.resize(nFacetCases());
00160   W_ACI_F1_.resize(nFacetCases());
00161 
00162   for (int fc=0; fc<nFacetCases(); fc++)
00163   {
00164     Tabs tab2;
00165 
00166     SUNDANCE_MSG1(setupVerb(), tab2 << "facet case=" << fc
00167       << " of " << nFacetCases());        
00168 
00169     /* create the quad points and weights */
00170     Array<double> quadWeights;
00171     Array<Point> quadPts;
00172     getQuad(quad, fc, quadPts, quadWeights);
00173     nQuad_ = quadPts.size();
00174     quadPts_[fc] = quadPts;
00175     quadWeights_[fc] = quadWeights;
00176       
00177     W_[fc].resize(nQuad() * nRefDerivTest() * nNodesTest());
00178 
00179     SUNDANCE_MSG1(setupVerb(), tab2 << "num nodes for test function " << nNodesTest());
00180 
00181     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00182 
00183     for (int r=0; r<nRefDerivTest(); r++)
00184     {
00185       Tabs tab3;
00186       SUNDANCE_MSG1(setupVerb(), tab3 
00187         << "evaluating basis functions for ref deriv direction " << r);
00188       MultiIndex mi;
00189       testBasisVals[r].resize(testBasis.dim());
00190       if (testDerivOrder==1) mi[r] = 1;
00191       SpatialDerivSpecifier deriv(mi);
00192       testBasis.refEval(evalCellType(), quadPts, deriv, 
00193         testBasisVals[r], setupVerb());
00194     }
00195 
00196       
00197 
00198     int vecComp = 0;
00199     W_ACI_F1_[fc].resize(nQuad());
00200     for (int q=0; q<nQuad(); q++)
00201     {
00202       W_ACI_F1_[fc][q].resize(nRefDerivTest());
00203       for (int t=0; t<nRefDerivTest(); t++)
00204       {
00205         W_ACI_F1_[fc][q][t].resize(nNodesTest());
00206         for (int nt=0; nt<nNodesTest(); nt++)
00207         {
00208           wValue(fc, q, t, nt) 
00209             = chop(quadWeights[q] * testBasisVals[t][vecComp][q][nt]) ;
00210           W_ACI_F1_[fc][q][t][nt] = chop(testBasisVals[t][vecComp][q][nt]);
00211         }
00212       }
00213     }
00214 
00215     addFlops(2*nQuad()*nRefDerivTest()*nNodesTest());
00216   }
00217 }
00218 
00219 
00220 
00221 
00222 QuadratureIntegral::QuadratureIntegral(int spatialDim,
00223   const CellType& maxCellType,
00224   int dim,
00225   const CellType& cellType,
00226   const BasisFamily& testBasis,
00227   int alpha,
00228   int testDerivOrder,
00229   const BasisFamily& unkBasis,
00230   int beta,
00231   int unkDerivOrder,
00232   const QuadratureFamily& quad,
00233   bool isInternalBdry,
00234   const ParametrizedCurve& globalCurve,
00235   const Mesh& mesh,
00236   int verb)
00237   : QuadratureIntegralBase(spatialDim, maxCellType, dim, cellType, 
00238     testBasis, alpha, testDerivOrder, 
00239     unkBasis, beta, unkDerivOrder, quad , isInternalBdry, globalCurve , mesh , verb),
00240     W_(),
00241     useSumFirstMethod_(true)
00242 {
00243   Tabs tab0;
00244   
00245   SUNDANCE_MSG1(setupVerb(), tab0 << "QuadratureIntegral ctor for 2-form");
00246   if (setupVerb()) describe(Out::os());
00247   assertBilinearForm();
00248   quad_ = quad;
00249 
00250   W_.resize(nFacetCases());
00251   W_ACI_F2_.resize(nFacetCases());
00252   // store the quadrature points and weights
00253   quadPts_.resize(nFacetCases());
00254   quadWeights_.resize(nFacetCases());
00255 
00256   for (int fc=0; fc<nFacetCases(); fc++)
00257   {
00258     /* get the quad pts and weights */
00259     Array<double> quadWeights;
00260     Array<Point> quadPts;
00261     getQuad(quad, fc, quadPts, quadWeights);
00262     // store the points for each facet case
00263     quadPts_[fc] = quadPts;
00264     quadWeights_[fc] = quadWeights;
00265     nQuad_ = quadPts.size();
00266 
00267     W_[fc].resize(nQuad() * nRefDerivTest() * nNodesTest()  
00268       * nRefDerivUnk() * nNodesUnk());
00269 
00270 
00271     /* compute the basis functions */
00272     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00273     Array<Array<Array<Array<double> > > > unkBasisVals(nRefDerivUnk());
00274 
00275 
00276     for (int r=0; r<nRefDerivTest(); r++)
00277     {
00278       testBasisVals[r].resize(testBasis.dim());
00279       MultiIndex mi;
00280       if (testDerivOrder==1) mi[r] = 1;
00281       SpatialDerivSpecifier deriv(mi);
00282       testBasis.refEval(evalCellType(), quadPts, deriv, 
00283         testBasisVals[r], setupVerb());
00284     }
00285 
00286     for (int r=0; r<nRefDerivUnk(); r++)
00287     {
00288       unkBasisVals[r].resize(unkBasis.dim());
00289       MultiIndex mi;
00290       if (unkDerivOrder==1) mi[r] = 1;
00291       SpatialDerivSpecifier deriv(mi);
00292       unkBasis.refEval(evalCellType(), 
00293         quadPts, deriv, unkBasisVals[r], setupVerb());
00294     }
00295 
00296 
00297     int vecComp = 0;
00298     /* form the products of basis functions at each quad pt */
00299     W_ACI_F2_[fc].resize(nQuad());
00300     for (int q=0; q<nQuad(); q++)
00301     {
00302       W_ACI_F2_[fc][q].resize(nRefDerivTest());
00303       for (int t=0; t<nRefDerivTest(); t++)
00304       {
00305         W_ACI_F2_[fc][q][t].resize(nNodesTest());
00306         for (int nt=0; nt<nNodesTest(); nt++)
00307         {
00308           W_ACI_F2_[fc][q][t][nt].resize(nRefDerivUnk());
00309           for (int u=0; u<nRefDerivUnk(); u++)
00310           {
00311             W_ACI_F2_[fc][q][t][nt][u].resize(nNodesUnk());
00312             for (int nu=0; nu<nNodesUnk(); nu++)
00313             {
00314               wValue(fc, q, t, nt, u, nu)
00315                 = chop(quadWeights[q] * testBasisVals[t][vecComp][q][nt] 
00316                   * unkBasisVals[u][vecComp][q][nu]);
00317               W_ACI_F2_[fc][q][t][nt][u][nu] =
00318                 chop(testBasisVals[t][vecComp][q][nt] * unkBasisVals[u][vecComp][q][nu]);
00319             }
00320           }
00321         }
00322       }
00323     }
00324 
00325     addFlops(3*nQuad()*nRefDerivTest()*nNodesTest()*nRefDerivUnk()*nNodesUnk()
00326       + W_[fc].size());
00327     for (int i=0; i<W_[fc].size(); i++) W_[fc][i] = chop(W_[fc][i]);
00328     
00329   }
00330 
00331 }
00332 
00333 
00334 void QuadratureIntegral::transformZeroForm(const CellJacobianBatch& JTrans,  
00335   const CellJacobianBatch& JVol,
00336   const Array<int>& isLocalFlag,
00337   const Array<int>& facetIndex,
00338   const RCP<Array<int> >& cellLIDs,
00339   const double* const coeff,
00340   RCP<Array<double> >& A) const
00341 {
00342   TimeMonitor timer(quadrature0Timer());
00343   Tabs tabs;
00344   TEUCHOS_TEST_FOR_EXCEPTION(order() != 0, std::logic_error,
00345     "QuadratureIntegral::transformZeroForm() called "
00346     "for form of order " << order());
00347 
00348   TEUCHOS_TEST_FOR_EXCEPTION( (int) isLocalFlag.size() != 0 
00349     && (int) isLocalFlag.size() != JVol.numCells(),
00350     std::runtime_error,
00351     "mismatch between isLocalFlag.size()=" << isLocalFlag.size()
00352     << " and JVol.numCells()=" << JVol.numCells());
00353 
00354   bool checkLocalFlag = (int) isLocalFlag.size() != 0;
00355 
00356   const Array<int>* cellLID = cellLIDs.get();
00357   
00358   SUNDANCE_MSG1(integrationVerb(), tabs << "doing zero form by quadrature");
00359   double& a = (*A)[0];
00360   SUNDANCE_MSG5(integrationVerb(), tabs << "input A=");
00361   if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00362   double* coeffPtr = (double*) coeff;
00363 
00364   int flops = 0;
00365   if (nFacetCases()==1)
00366   {
00367       if (globalCurve().isCurveValid())
00368       {       /* ---------- ACI logic ----------- */
00369 
00370       Array<double> quadWeightsTmp = quadWeights_[0];
00371       Array<Point> quadPointsTmp = quadPts_[0];
00372       bool isCutByCurve;
00373 
00374         const Array<double>& w = W_[0];
00375         for (int c=0; c<JVol.numCells(); c++)
00376         {
00377           if (checkLocalFlag && !isLocalFlag[c])
00378           {
00379             coeffPtr += nQuad();
00380             continue;
00381           }
00382           double detJ = fabs(JVol.detJ()[c]);
00383           int fc = 0;
00384 
00385           quadWeightsTmp = quadWeights_[fc];
00386           quadPointsTmp = quadPts_[fc];
00387           quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc ,mesh(),
00388                globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00389            /* if we have special weights then do the same as before */
00390           if (isCutByCurve)
00391           {
00392                for (int q=0; q<nQuad(); q++, coeffPtr++)
00393                {
00394                  a += quadWeightsTmp[q]*(*coeffPtr)*detJ;
00395                }
00396                flops += 3*nQuad();
00397            }
00398            else
00399            {
00400                for (int q=0; q<nQuad(); q++, coeffPtr++)
00401                {
00402                  a += w[q]*(*coeffPtr)*detJ;
00403                }
00404                flops += 3*nQuad();
00405          }
00406 
00407          }
00408       }
00409       else        /* ---------- NO ACI logic ----------- */
00410       {
00411           const Array<double>& w = W_[0];
00412           for (int c=0; c<JVol.numCells(); c++)
00413           {
00414             if (checkLocalFlag && !isLocalFlag[c])
00415             {
00416               coeffPtr += nQuad();
00417               continue;
00418             }
00419             double detJ = fabs(JVol.detJ()[c]);
00420 
00421             for (int q=0; q<nQuad(); q++, coeffPtr++)
00422             {
00423               a += w[q]*(*coeffPtr)*detJ;
00424             }
00425             flops += 3*nQuad();
00426           }
00427       }
00428   }
00429   else
00430   {
00431       if (globalCurve().isCurveValid())
00432       {     /* ---------- ACI logic ----------- */
00433       Array<double> quadWeightsTmp = quadWeights_[0];
00434       Array<Point> quadPointsTmp = quadPts_[0];
00435       bool isCutByCurve;
00436 
00437           for (int c=0; c<JVol.numCells(); c++)
00438           {
00439             if (checkLocalFlag && !isLocalFlag[c])
00440             {
00441               coeffPtr += nQuad();
00442               continue;
00443             }
00444             double detJ = fabs(JVol.detJ()[c]);
00445             int fc = facetIndex[c];
00446             const Array<double>& w = W_[facetIndex[c]];
00447 
00448 
00449             quadWeightsTmp = quadWeights_[fc];
00450             quadPointsTmp = quadPts_[fc];
00451             quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc ,mesh(),
00452                 globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00453             /* if we have special weights then do the same as before */
00454             if (isCutByCurve){
00455               for (int q=0; q<nQuad(); q++, coeffPtr++)
00456                 a += quadWeightsTmp[q]*(*coeffPtr)*detJ;
00457               flops += 3*nQuad();
00458             } // end cut by curve
00459             else{
00460               for (int q=0; q<nQuad(); q++, coeffPtr++)
00461                 a += w[q]*(*coeffPtr)*detJ;
00462               flops += 3*nQuad();
00463             }
00464           }
00465       }
00466       else         /* ---------- NO ACI logic----------- */
00467       {
00468           for (int c=0; c<JVol.numCells(); c++)
00469           {
00470         Tabs tab1;
00471         SUNDANCE_MSG4(integrationVerb(), tab1 << "cell #" << c
00472           << " of " << JVol.numCells());
00473             if (checkLocalFlag && !isLocalFlag[c])
00474             {
00475     Tabs tab2;
00476     SUNDANCE_MSG4(integrationVerb(), tab2 
00477             << "skipped -- is not local cell");
00478               coeffPtr += nQuad();
00479               continue;
00480             }
00481             double detJ = fabs(JVol.detJ()[c]);
00482             const Array<double>& w = W_[facetIndex[c]];
00483 
00484             for (int q=0; q<nQuad(); q++, coeffPtr++)
00485             {
00486     Tabs tab3;
00487     SUNDANCE_MSG4(integrationVerb(), 
00488             tab3 << "q=" << q << "\t w=" << w[q]
00489             << "\t\t coeff=" << *coeffPtr << "\t\t |J|=" << detJ);
00490     a += w[q]*(*coeffPtr)*detJ;
00491             }
00492             flops += 3*nQuad();
00493           }
00494       }
00495   }
00496   SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00497   if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00498 
00499   addFlops(flops);
00500 }
00501 
00502 
00503 void QuadratureIntegral::transformOneForm(const CellJacobianBatch& JTrans,  
00504   const CellJacobianBatch& JVol,
00505   const Array<int>& facetIndex,
00506   const RCP<Array<int> >& cellLIDs,
00507   const double* const coeff,
00508   RCP<Array<double> >& A) const
00509 {
00510   TimeMonitor timer(quadrature1Timer());
00511   Tabs tabs;
00512   TEUCHOS_TEST_FOR_EXCEPTION(order() != 1, std::logic_error,
00513     "QuadratureIntegral::transformOneForm() called for form "
00514     "of order " << order());
00515   SUNDANCE_MSG2(integrationVerb(), tabs << "doing one form by quadrature");
00516   int flops = 0;
00517 
00518   const Array<int>* cellLID = cellLIDs.get();
00519 
00520   /* If the derivative order is zero, the only thing to be done 
00521    * is to multiply by the cell's Jacobian determinant and sum over the
00522    * quad points */
00523   if (testDerivOrder() == 0)
00524   {
00525     double* aPtr = &((*A)[0]);
00526     SUNDANCE_MSG5(integrationVerb(), tabs << "input A = ");
00527     if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00528   
00529     double* coeffPtr = (double*) coeff;
00530     int offset = 0 ;
00531 
00532       if (globalCurve().isCurveValid())
00533       {         /* ---------- ACI logic ----------- */
00534 
00535           Array<double> quadWeightsTmp = quadWeights_[0];
00536           Array<Point> quadPointsTmp = quadPts_[0];
00537           bool isCutByCurve;
00538 
00539           for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00540           {
00541             Tabs tab2;
00542             double detJ = fabs(JVol.detJ()[c]);
00543             int fc = 0;
00544             if (nFacetCases() != 1) fc = facetIndex[c];
00545             const Array<double>& w = W_[fc];
00546             SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << detJ);
00547 
00548             quadWeightsTmp = quadWeights_[fc];
00549             quadPointsTmp = quadPts_[fc];
00550             /* call the special integration routine */
00551             quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00552                 mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00553             if (isCutByCurve){
00554               Array<double> wi;
00555               wi.resize(nQuad() * nNodes()); //recalculate the special weights
00556               for (int ii = 0 ; ii < wi.size() ; ii++ ) { wi[ii] = 0.0; }
00557               for (int n = 0 ; n < nNodes() ; n++)
00558                 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00559                   //Indexing: testNode + nNodesTest()*(testDerivDir + nRefDerivTest()*q)
00560                   wi[n + nNodes()*q] +=
00561                       chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][0][n]);
00562               // if it is cut by curve then use this vector
00563               for (int q=0; q<nQuad(); q++, coeffPtr++){
00564                 double f = (*coeffPtr)*detJ;
00565                 for (int n=0; n<nNodes(); n++){
00566                   aPtr[offset+n] += f*wi[n + nNodes()*q];
00567                 }
00568               }
00569             } // end isCutByCurve
00570             else
00571             {
00572               for (int q=0; q<nQuad(); q++, coeffPtr++){
00573                 double f = (*coeffPtr)*detJ;
00574                 for (int n=0; n<nNodes(); n++){
00575                   aPtr[offset+n] += f*w[n + nNodes()*q];
00576                 }
00577               }
00578             }
00579          } // from cell loop
00580       }
00581       else    /* ---------- NO ACI logic ----------- */
00582       {
00583         for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00584         {
00585           Tabs tab2;
00586           double detJ = fabs(JVol.detJ()[c]);
00587           int fc = 0;
00588           if (nFacetCases() != 1) fc = facetIndex[c];
00589           const Array<double>& w = W_[fc];
00590           SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << detJ);
00591 
00592         for (int q=0; q<nQuad(); q++, coeffPtr++)
00593         {
00594           Tabs tab3;
00595           double f = (*coeffPtr)*detJ;
00596           SUNDANCE_MSG4(integrationVerb(), tab3 << "q=" << q << " coeff=" <<
00597             *coeffPtr << " coeff*detJ=" << f);
00598           for (int n=0; n<nNodes(); n++)
00599           {
00600             Tabs tab4;
00601             SUNDANCE_MSG4(integrationVerb(), tab4 << "n=" << n << " w=" <<
00602               w[n + nNodes()*q]);
00603             aPtr[offset+n] += f*w[n + nNodes()*q];
00604           }
00605         }
00606         } // from for loop over cells
00607       }
00608       if (integrationVerb() >= 4)
00609       {
00610       Tabs tab2;
00611         Out::os() << tab2 << "integration results on cell:" << std::endl;
00612         Out::os() << tab2 << setw(10) << "n" << setw(12) << "I_n" << std::endl;
00613         for (int n=0; n<nNodes(); n++) 
00614         {
00615           Out::os() << tab2 << setw(10) << n 
00616                     << setw(12) << setprecision(6) << aPtr[offset+n] << std::endl;
00617         }
00618       }
00619       
00620     SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00621     if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00622     addFlops( JVol.numCells() * (1 + nQuad() * (1 + 2*nNodes())) );
00623   }
00624   else
00625   {
00626     /* If the derivative order is nonzero, then we have to do a transformation. 
00627      * If we're also on a cell of dimension lower than maximal, we need to refer
00628      * to the facet index of the facet being integrated. */
00629 
00630     createOneFormTransformationMatrix(JTrans, JVol);
00631 
00632     SUNDANCE_MSG4(transformVerb(), 
00633       Tabs() << "transformation matrix=" << G(alpha()));
00634 
00635     double* GPtr = &(G(alpha())[0]);      
00636 
00637     if (useSumFirstMethod())
00638     {
00639       transformSummingFirst(JVol.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00640     }
00641     else
00642     {
00643       transformSummingLast(JVol.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00644     }
00645   }
00646   addFlops(flops);
00647 }
00648 
00649 
00650 void QuadratureIntegral::transformTwoForm(const CellJacobianBatch& JTrans,
00651   const CellJacobianBatch& JVol,
00652   const Array<int>& facetIndex,
00653   const RCP<Array<int> >& cellLIDs,
00654   const double* const coeff,
00655   RCP<Array<double> >& A) const
00656 {
00657   TimeMonitor timer(quadrature2Timer());
00658   Tabs tabs;
00659   TEUCHOS_TEST_FOR_EXCEPTION(order() != 2, std::logic_error,
00660     "QuadratureIntegral::transformTwoForm() called for form "
00661     "of order " << order());
00662   SUNDANCE_MSG2(integrationVerb(), tabs << "doing two form by quadrature");
00663 
00664   const Array<int>* cellLID = cellLIDs.get();
00665 
00666   /* If the derivative orders are zero, the only thing to be done 
00667    * is to multiply by the cell's Jacobian determinant and sum over the
00668    * quad points */
00669   if (testDerivOrder() == 0 && unkDerivOrder() == 0)
00670   {
00671     double* aPtr = &((*A)[0]);
00672     double* coeffPtr = (double*) coeff;
00673     int offset = 0 ;
00674 
00675     if (globalCurve().isCurveValid())
00676     {        /* ---------- ACI logic ----------- */
00677 
00678         Array<double> quadWeightsTmp = quadWeights_[0];
00679         Array<Point> quadPointsTmp = quadPts_[0];
00680         bool isCutByCurve;
00681 
00682         for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00683         {
00684             double detJ = fabs(JVol.detJ()[c]);
00685             int fc = 0;
00686             if (nFacetCases() != 1) fc = facetIndex[c];
00687             const Array<double>& w = W_[fc];
00688 
00689             quadWeightsTmp = quadWeights_[fc];
00690             quadPointsTmp = quadPts_[fc];
00691             /* call the special integration routine */
00692             quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00693                 mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00694             if (isCutByCurve){
00695               Array<double> wi;
00696               wi.resize(nQuad() * nNodesTest() *nNodesUnk() ); //recalculate the special weights
00697               for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00698               for (int nt = 0 ; nt < nNodesTest() ; nt++){
00699                 for (int nu=0; nu<nNodesUnk(); nu++)
00700                   for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00701                     //Indexing: unkNode + nNodesUnk()*(testNode + nNodesTest()*(unkDerivDir + nRefDerivUnk()*(testDerivDir + nRefDerivTest()*q)))
00702                     wi[nu + nNodesUnk()*(nt + nNodesTest()*q)] +=
00703                         chop(quadWeightsTmp[q] * W_ACI_F2_[fc][q][0][nt][0][nu]);
00704               }
00705               for (int q=0; q<nQuad(); q++, coeffPtr++){
00706                 double f = (*coeffPtr)*detJ;
00707                 for (int n=0; n<nNodes(); n++){
00708                   aPtr[offset+n] += f*wi[n + nNodes()*q];
00709                 }
00710               }
00711             }// end isCutByCurve
00712             else
00713             {
00714               for (int q=0; q<nQuad(); q++, coeffPtr++){
00715                 double f = (*coeffPtr)*detJ;
00716                 for (int n=0; n<nNodes(); n++){
00717                   aPtr[offset+n] += f*w[n + nNodes()*q];
00718                 }
00719               }
00720             }
00721         }
00722       }
00723       else         /* ---------- NO ACI logic ----------- */
00724       {
00725 
00726         for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00727         {
00728             double detJ = fabs(JVol.detJ()[c]);
00729             int fc = 0;
00730             if (nFacetCases() != 1) fc = facetIndex[c];
00731             const Array<double>& w = W_[fc];
00732             for (int q=0; q<nQuad(); q++, coeffPtr++)
00733             {
00734               double f = (*coeffPtr)*detJ;
00735               for (int n=0; n<nNodes(); n++)
00736               {
00737                 aPtr[offset+n] += f*w[n + nNodes()*q];
00738               }
00739             }
00740         }
00741       }
00742     addFlops( JVol.numCells() * (1 + nQuad() * (1 + 2*nNodes())) );
00743   }
00744   else
00745   {
00746     createTwoFormTransformationMatrix(JTrans, JVol);
00747     double* GPtr;
00748 
00749     if (testDerivOrder() == 0)
00750     {
00751       GPtr = &(G(beta())[0]);
00752       SUNDANCE_MSG2(transformVerb(),
00753         Tabs() << "transformation matrix=" << G(beta()));
00754     }
00755     else if (unkDerivOrder() == 0)
00756     {
00757       GPtr = &(G(alpha())[0]);
00758       SUNDANCE_MSG2(transformVerb(),
00759         Tabs() << "transformation matrix=" << G(alpha()));
00760     }
00761     else
00762     {
00763       GPtr = &(G(alpha(), beta())[0]);
00764       SUNDANCE_MSG2(transformVerb(),
00765         Tabs() << "transformation matrix=" 
00766         << G(alpha(),beta()));
00767     }
00768         
00769       
00770     if (useSumFirstMethod())
00771     {
00772       transformSummingFirst(JTrans.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00773     }
00774     else
00775     {
00776       transformSummingLast(JTrans.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00777     }
00778   }
00779 }
00780 
00781 void QuadratureIntegral
00782 ::transformSummingFirst(int nCells,
00783   const Array<int>& facetIndex,
00784   const RCP<Array<int> >& cellLIDs,
00785   const double* const GPtr,
00786   const double* const coeff,
00787   RCP<Array<double> >& A) const
00788 {
00789   double* aPtr = &((*A)[0]);
00790   double* coeffPtr = (double*) coeff;
00791   const Array<int>* cellLID = cellLIDs.get();
00792   
00793   int transSize = 0; 
00794   if (order()==2)
00795   {
00796     transSize = nRefDerivTest() * nRefDerivUnk();
00797   }
00798   else
00799   {
00800     transSize = nRefDerivTest();
00801   }
00802 
00803   /* The sum workspace is used to store the sum of untransformed quantities */
00804   static Array<double> sumWorkspace;
00805 
00806   int swSize = transSize * nNodes();
00807   sumWorkspace.resize(swSize);
00808   
00809   
00810   /*
00811    * The number of operations for the sum-first method is 
00812    * 
00813    * Adds: (N_c * nNodes * transSize) * (N_q + 1) 
00814    * Multiplies: same as number of adds
00815    * Total: 2*(N_c * nNodes * transSize) * (N_q + 1) 
00816    */
00817   
00818 
00819     if (globalCurve().isCurveValid())
00820     {       /* ---------- ACI logic ----------- */
00821 
00822        Array<double> quadWeightsTmp = quadWeights_[0];
00823        Array<Point> quadPointsTmp = quadPts_[0];
00824        bool isCutByCurve;
00825 
00826       for (int c=0; c<nCells; c++)
00827       {
00828           /* sum untransformed basis combinations over quad points */
00829           for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00830           int fc = 0;
00831           if (nFacetCases() > 1) fc = facetIndex[c];
00832 
00833           const Array<double>& w = W_[fc];
00834 
00835           quadWeightsTmp = quadWeights_[fc];
00836           quadPointsTmp = quadPts_[fc];
00837           /* call the special integration routine */
00838           quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00839               mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00840           if (isCutByCurve){
00841             Array<double> wi;
00842             if (order()==1){ // one form integral
00843               wi.resize(nQuad() * nRefDerivTest() * nNodesTest()); //recalculate the special weights
00844               for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00845               for (int n = 0 ; n < nNodes() ; n++)
00846                 for (int t=0; t<nRefDerivTest(); t++)
00847                   for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00848                     //Indexing: testNode + nNodesTest()*(testDerivDir + nRefDerivTest()*q)
00849                     wi[n + nNodes()*(t + nRefDerivTest()*q)] +=
00850                         chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][t][n]);
00851             }else{ // two from integrals
00852               wi.resize(nQuad() * nRefDerivTest() * nNodesTest()
00853                   * nRefDerivUnk() * nNodesUnk() ); //recalculate the special weights
00854               for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00855 
00856               for (int t=0; t<nRefDerivTest(); t++)
00857                 for (int nt = 0 ; nt < nNodesTest() ; nt++){
00858                   for (int u=0; u<nRefDerivUnk(); u++)
00859                     for (int nu=0; nu<nNodesUnk(); nu++)
00860                       for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00861                         //Indexing: unkNode + nNodesUnk()*(testNode + nNodesTest()*
00862                         //(unkDerivDir + nRefDerivUnk()*(testDerivDir + nRefDerivTest()*q)))
00863                         wi[nu + nNodesUnk()*(nt + nNodesTest()*(u + nRefDerivUnk()*(t + nRefDerivTest()*q)))] +=
00864                             chop(quadWeightsTmp[q] * W_ACI_F2_[fc][q][t][nt][u][nu]);
00865                 }
00866             }// end two form integral
00867             for (int q=0; q<nQuad(); q++, coeffPtr++){
00868               double f = (*coeffPtr);
00869               for (int n=0; n<swSize; n++){
00870                 sumWorkspace[n] += f*wi[n + q*swSize];
00871               }
00872             }
00873           }// end cut by curve
00874           else{
00875             for (int q=0; q<nQuad(); q++, coeffPtr++)
00876             {
00877               double f = (*coeffPtr);
00878               for (int n=0; n<swSize; n++)
00879               {
00880                 sumWorkspace[n] += f*w[n + q*swSize];
00881               }
00882             }
00883           }
00884       }// end from for loop over cells
00885     }
00886     else
00887     {           /* ---------- NO ACI logic ----------- */
00888       for (int c=0; c<nCells; c++)
00889       {
00890           /* sum untransformed basis combinations over quad points */
00891           for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00892           int fc = 0;
00893           if (nFacetCases() > 1) fc = facetIndex[c];
00894 
00895           const Array<double>& w = W_[fc];
00896 
00897           for (int q=0; q<nQuad(); q++, coeffPtr++)
00898           {
00899             double f = (*coeffPtr);
00900             for (int n=0; n<swSize; n++)
00901             {
00902               sumWorkspace[n] += f*w[n + q*swSize];
00903             }
00904           }
00905 
00906           /* transform the sum */
00907           const double * const gCell = &(GPtr[transSize*c]);
00908           double* aCell = aPtr + nNodes()*c;
00909           for (int i=0; i<nNodes(); i++)
00910           {
00911             for (int j=0; j<transSize; j++)
00912             {
00913               aCell[i] += sumWorkspace[nNodes()*j + i] * gCell[j];
00914             }
00915           }
00916       }// for loop over cells
00917     }
00918   int flops = 2*(nCells * nNodes() * transSize) * (nQuad() + 1) ;
00919   addFlops(flops);
00920 }
00921 
00922 void QuadratureIntegral
00923 ::transformSummingLast(int nCells,
00924   const Array<int>& facetIndex,
00925   const RCP<Array<int> >& cellLIDs,
00926   const double* const GPtr,
00927   const double* const coeff,
00928   RCP<Array<double> >& A) const
00929 {
00930   double* aPtr = &((*A)[0]);
00931   int transSize = 0; 
00932   const Array<int>* cellLID = cellLIDs.get();
00933   
00934   if (order()==2)
00935   {
00936     transSize = nRefDerivTest() * nRefDerivUnk();
00937   }
00938   else
00939   {
00940     transSize = nRefDerivTest();
00941   }
00942 
00943   /* This workspace is used to store the jacobian values scaled by the coeff
00944    * at that quad point */
00945   static Array<double> jWorkspace;
00946   jWorkspace.resize(transSize);
00947 
00948 
00949   /*
00950    * The number of operations for the sum-last method is 
00951    * 
00952    * Adds: N_c * N_q * transSize * nNodes
00953    * Multiplies: numAdds + N_c * N_q * transSize
00954    * Total: N_c * N_q * transSize * (1 +  2*nNodes)
00955    */
00956 
00957     if (globalCurve().isCurveValid()){
00958         /* ---------- ACI logic ----------- */
00959       Array<double> quadWeightsTmp = quadWeights_[0];
00960       Array<Point> quadPointsTmp = quadPts_[0];
00961       bool isCutByCurve;
00962 
00963       for (int c=0; c<nCells; c++)
00964       {
00965           const double* const gCell = &(GPtr[transSize*c]);
00966           double* aCell = aPtr + nNodes()*c;
00967           int fc = 0;
00968           if (nFacetCases() > 1) fc = facetIndex[c];
00969           const Array<double>& w = W_[fc];
00970 
00971           quadWeightsTmp = quadWeights_[fc];
00972           quadPointsTmp = quadPts_[fc];
00973           /* call the special integration routine */
00974           quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00975               mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00976           if (isCutByCurve){
00977             Array<double> wi;
00978             if (order()==1){ // one form integral
00979               wi.resize(nQuad() * nRefDerivTest() * nNodesTest()); //recalculate the special weights
00980               for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00981               for (int n = 0 ; n < nNodes() ; n++)
00982                 for (int t=0; t<nRefDerivTest(); t++)
00983                   for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00984                     //Indexing: testNode + nNodesTest()*(testDerivDir + nRefDerivTest()*q)
00985                     wi[n + nNodes()*(t + nRefDerivTest()*q)] +=
00986                         chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][t][n]);
00987             }else{ // two from integrals
00988               wi.resize(nQuad() * nRefDerivTest() * nNodesTest()
00989                   * nRefDerivUnk() * nNodesUnk() ); //recalculate the special weights
00990               for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00991 
00992               for (int t=0; t<nRefDerivTest(); t++)
00993                 for (int nt = 0 ; nt < nNodesTest() ; nt++){
00994                   for (int u=0; u<nRefDerivUnk(); u++)
00995                     for (int nu=0; nu<nNodesUnk(); nu++)
00996                       for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00997                         //Indexing: unkNode + nNodesUnk()*(testNode + nNodesTest()*
00998                         //(unkDerivDir + nRefDerivUnk()*(testDerivDir + nRefDerivTest()*q)))
00999                         wi[nu + nNodesUnk()*(nt + nNodesTest()*(u + nRefDerivUnk()*(t + nRefDerivTest()*q)))] +=
01000                             chop(quadWeightsTmp[q] * W_ACI_F2_[fc][q][t][nt][u][nu]);
01001                 }
01002             }// end two form integral
01003             for (int q=0; q<nQuad(); q++){
01004               double f = coeff[c*nQuad() + q];
01005               for (int t=0; t<transSize; t++) jWorkspace[t]=f*gCell[t];
01006 
01007               for (int n=0; n<nNodes(); n++){
01008                 for (int t=0; t<transSize; t++){
01009                   aCell[n] += jWorkspace[t]*wi[n + nNodes()*(t + transSize*q)];
01010                 }
01011               }
01012             }
01013           }// end cut by curve
01014           else{
01015             for (int q=0; q<nQuad(); q++){
01016               double f = coeff[c*nQuad() + q];
01017               for (int t=0; t<transSize; t++) jWorkspace[t]=f*gCell[t];
01018 
01019               for (int n=0; n<nNodes(); n++){
01020                 for (int t=0; t<transSize; t++){
01021                   aCell[n] += jWorkspace[t]*w[n + nNodes()*(t + transSize*q)];
01022                 }
01023               }
01024             }
01025           }
01026     }// loop over cells
01027     }
01028     else       /* ---------- NO ACI logic ----------- */
01029     {
01030         for (int c=0; c<nCells; c++)
01031         {
01032               const double* const gCell = &(GPtr[transSize*c]);
01033               double* aCell = aPtr + nNodes()*c;
01034               int fc = 0;
01035               if (nFacetCases() > 1) fc = facetIndex[c];
01036               const Array<double>& w = W_[fc];
01037               for (int q=0; q<nQuad(); q++)
01038               {
01039                 double f = coeff[c*nQuad() + q];
01040                 for (int t=0; t<transSize; t++) jWorkspace[t]=f*gCell[t];
01041 
01042                 for (int n=0; n<nNodes(); n++)
01043                 {
01044                   for (int t=0; t<transSize; t++)
01045                   {
01046                     aCell[n] += jWorkspace[t]*w[n + nNodes()*(t + transSize*q)];
01047                   }
01048                 }
01049               }
01050         }
01051   }
01052   int flops = nCells * nQuad() * transSize * (1 + 2*nNodes()) ;
01053   addFlops(flops);
01054 }

Site Contact