SundanceReducedIntegral.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 "SundanceReducedIntegral.hpp"
00032 #include "SundanceGaussianQuadrature.hpp"
00033 #include "SundanceGaussianQuadratureType.hpp"
00034 #include "SundanceQuadratureType.hpp"
00035 #include "SundanceSpatialDerivSpecifier.hpp"
00036 #include "SundanceOut.hpp"
00037 #include "PlayaTabs.hpp"
00038 #include "Teuchos_TimeMonitor.hpp"
00039 
00040 using namespace Sundance;
00041 using namespace Teuchos;
00042 
00043 using std::ios_base;
00044 using std::setw;
00045 using std::endl;
00046 
00047 extern "C" 
00048 {
00049 int dgemm_(const char* transA, const char* transB,
00050   const int* M, const int *N, const int* K,
00051   const double* alpha, 
00052   const double* A, const int* ldA,
00053   const double* B, const int* ldB,
00054   const double* beta,
00055   double* C, const int* ldC);
00056 }
00057 
00058 static Time& reduced0IntegrationTimer() 
00059 {
00060   static RCP<Time> rtn
00061     = TimeMonitor::getNewTimer("reduced 0-form integration"); 
00062   return *rtn;
00063 }
00064 
00065 
00066 static Time& reduced1IntegrationTimer() 
00067 {
00068   static RCP<Time> rtn
00069     = TimeMonitor::getNewTimer("reduced 1-form integration"); 
00070   return *rtn;
00071 }
00072 
00073 
00074 static Time& reduced2IntegrationTimer() 
00075 {
00076   static RCP<Time> rtn
00077     = TimeMonitor::getNewTimer("reduced 2-form integration"); 
00078   return *rtn;
00079 }
00080 
00081 
00082 
00083 ReducedIntegral::ReducedIntegral(int spatialDim,
00084   const CellType& maxCellType,
00085   int dim, 
00086   const CellType& cellType,
00087   const QuadratureFamily& quad_in,
00088   bool isInternalBdry,
00089   const ParametrizedCurve& globalCurve,
00090   const Mesh& mesh,
00091   int verb)
00092   : ElementIntegral(spatialDim, maxCellType, dim, cellType, isInternalBdry, globalCurve , mesh,
00093     verb), W_()
00094 {
00095   Tabs tab0(0);
00096 
00097   SUNDANCE_MSG1(setupVerb(),
00098     tab0 << "************* creating reduced 0-form integrals ********");
00099   if (setupVerb()) describe(Out::os());
00100   
00101   /* we need to sum the quadrature weights 
00102      to compute the volume of the reference cell */
00103   QuadratureFamily quad = new GaussianQuadrature(1);
00104 
00105   /* not supporting ACI for now */
00106   TEUCHOS_TEST_FOR_EXCEPT(globalCurve.isCurveValid());
00107 
00108   Array<Point> quadPts;
00109   Array<double> quadWeights;
00110 
00111   W_.resize(1);
00112   W_[0].resize(1);
00113 
00114   quad.getPoints(cellType, quadPts, quadWeights);  
00115 
00116   for (int q=0; q<quadWeights.size(); q++) {
00117     W_[0][0] += quadWeights[q];
00118   }
00119 }
00120 
00121 ReducedIntegral::ReducedIntegral(int spatialDim,
00122   const CellType& maxCellType,
00123   int dim, 
00124   const CellType& cellType,
00125   const BasisFamily& testBasis,
00126   int alpha,
00127   int testDerivOrder,
00128   const QuadratureFamily& quad_in,
00129   bool isInternalBdry,
00130   const ParametrizedCurve& globalCurve,
00131   const Mesh& mesh,
00132   int verb)
00133   : ElementIntegral(spatialDim, maxCellType, dim, cellType, 
00134     testBasis, alpha, testDerivOrder, isInternalBdry, globalCurve , mesh , verb), W_()
00135 {
00136   Tabs tab0(0);
00137   SUNDANCE_MSG1(setupVerb(),
00138     tab0 << "************* creating reduced 1-form integrals ********");
00139   if (setupVerb()) describe(Out::os());
00140   assertLinearForm();
00141 
00142   W_.resize(nFacetCases());
00143 
00144   /* Determine the quadrature order needed for exact integrations */
00145   QuadratureType qType = new GaussianQuadratureType();
00146   int reqOrder = qType.findValidOrder(cellType, 
00147     std::max(1, testBasis.order()));
00148 
00149   SUNDANCE_MSG2(setupVerb(),
00150     tab0 << "using quadrature order=" << reqOrder);
00151    
00152   /* Create a quadrature family of the required order */
00153   QuadratureFamily quad = qType.createQuadFamily(reqOrder);
00154 
00155   /* not supporting ACI for now */
00156   TEUCHOS_TEST_FOR_EXCEPT(globalCurve.isCurveValid());
00157 
00158   /* We now loop over the different evaluation cases, integrating the
00159    * basis functions for each. Because this is a reference integral,
00160    * we can actually do the untransformed integrals here. */
00161   for (int fc=0; fc<nFacetCases(); fc++)
00162   {
00163     Tabs tab1;
00164     SUNDANCE_MSG2(setupVerb(),
00165       tab1 << "evaluation case=" << fc << " of " << nFacetCases());
00166     /* initialize size of untransformed integral results array */
00167     W_[fc].resize(nRefDerivTest() * nNodesTest());
00168 
00169     /* initialize values of integrals to zero */
00170     for (int i=0; i<W_[fc].size(); i++) { W_[fc][i]=0.0; }
00171 
00172     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00173   
00174     /* get quadrature points */
00175 
00176     Array<Point> quadPts;
00177     Array<double> quadWeights;
00178     getQuad(quad, fc, quadPts, quadWeights);
00179 
00180     int nQuad = quadPts.size();
00181 
00182     /* compute the basis functions */
00183     for (int r=0; r<nRefDerivTest(); r++)
00184     {
00185       Tabs tab2;
00186       SUNDANCE_MSG2(setupVerb(), tab2 << "evaluating basis derivative " 
00187         << r << " of " << nRefDerivTest());
00188 
00189       testBasisVals[r].resize(testBasis.dim());
00190       MultiIndex mi;
00191       if (testDerivOrder==1) mi[r] = 1;
00192       SpatialDerivSpecifier deriv(mi);
00193       testBasis.refEval(evalCellType(), quadPts, deriv,
00194         testBasisVals[r], setupVerb());
00195     }
00196 
00197     /* do the quadrature */
00198     SUNDANCE_MSG2(setupVerb(), tab1 << "doing quadrature");
00199     int vecComp = 0;
00200     for (int q=0; q<nQuad; q++)
00201     {
00202       for (int t=0; t<nRefDerivTest(); t++)
00203       {
00204         for (int nt=0; nt<nNodesTest(); nt++)
00205         {
00206           value(fc, t, nt) 
00207             += chop(quadWeights[q] * testBasisVals[t][vecComp][q][nt]) ;
00208         }
00209       }
00210     }    
00211 
00212     for (int i=0; i<W_[fc].size(); i++) W_[fc][i] = chop(W_[fc][i]);
00213 
00214     addFlops(3*nQuad*nRefDerivTest()*nNodesTest() + W_[fc].size());
00215   }
00216 
00217   /* print the result */
00218   SUNDANCE_MSG4(setupVerb(), tab0 << "--------------------------------------");
00219   SUNDANCE_MSG4(setupVerb(), tab0 << "reduced linear form integral results");
00220   if (setupVerb() >= 4)
00221   {
00222     for (int fc=0; fc<nFacetCases(); fc++)
00223     {
00224       Tabs tab1;
00225       SUNDANCE_MSG4(setupVerb(), tab1 << "------ evaluation case " << fc << " of "
00226         << nFacetCases() << "-------");
00227       
00228       for (int r=0; r<nRefDerivTest(); r++)
00229       {
00230         Tabs tab2;
00231 
00232         MultiIndex mi;
00233         if (testDerivOrder==1) mi[r] = 1;
00234         SUNDANCE_MSG1(setupVerb(), tab2 << "multiindex=" << mi);
00235 
00236         ios_base::fmtflags oldFlags = Out::os().flags();
00237         Out::os().setf(ios_base::right);    
00238         Out::os().setf(ios_base::showpoint);
00239         for (int nt=0; nt<nNodesTest(); nt++)
00240         {
00241           Tabs tab3;
00242           Out::os() << tab3 << setw(10) << nt 
00243                     << setw(12) << std::setprecision(5) << value(fc, r, nt) 
00244                     << std::endl;
00245         }
00246         Out::os().flags(oldFlags);
00247       }
00248     }
00249   }
00250 
00251   SUNDANCE_MSG1(setupVerb(), tab0 << "done reduced linear form ctor");
00252 }
00253 
00254 
00255 
00256 
00257 ReducedIntegral::ReducedIntegral(int spatialDim,
00258   const CellType& maxCellType,
00259   int dim,
00260   const CellType& cellType,
00261   const BasisFamily& testBasis,
00262   int alpha,
00263   int testDerivOrder,
00264   const BasisFamily& unkBasis,
00265   int beta,
00266   int unkDerivOrder, 
00267   const QuadratureFamily& quad_in,
00268   bool isInternalBdry,
00269   const ParametrizedCurve& globalCurve,
00270   const Mesh& mesh,
00271   int verb)
00272   : ElementIntegral(spatialDim, maxCellType,  dim, cellType,
00273     testBasis, alpha, testDerivOrder, 
00274     unkBasis, beta, unkDerivOrder, isInternalBdry, globalCurve , mesh ,verb), W_()
00275 
00276 {
00277   Tabs tab0(0);
00278   SUNDANCE_MSG1(setupVerb(),
00279     tab0 << "************* creating reduced 2-form integrals ********");
00280   if (setupVerb()) describe(Out::os());
00281 
00282   assertBilinearForm();
00283 
00284   W_.resize(nFacetCases());
00285 
00286   QuadratureType qType = new GaussianQuadratureType();
00287   int reqOrder = qType.findValidOrder(cellType,
00288     std::max(1, unkBasis.order() + testBasis.order()));
00289 
00290   SUNDANCE_MSG2(setupVerb(),
00291     tab0 << "using quadrature order=" << reqOrder);
00292   QuadratureFamily quad = qType.createQuadFamily(reqOrder);
00293 
00294   /* not supporting ACI for now */
00295   TEUCHOS_TEST_FOR_EXCEPT(globalCurve.isCurveValid());
00296 
00297 
00298   SUNDANCE_MSG2(setupVerb(),
00299     tab0 << "processing evaluation cases");
00300 
00301   for (int fc=0; fc<nFacetCases(); fc++)
00302   {
00303     Tabs tab1;
00304     SUNDANCE_MSG1(setupVerb(), tab1 << "------ evaluation case " << fc << " of "
00305       << nFacetCases() << "-------");
00306     
00307     W_[fc].resize(nRefDerivTest() * nNodesTest()  * nRefDerivUnk() * nNodesUnk());
00308     for (int i=0; i<W_[fc].size(); i++) W_[fc][i]=0.0;
00309 
00310     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00311     Array<Array<Array<Array<double> > > > unkBasisVals(nRefDerivUnk());
00312 
00313     Array<Point> quadPts;
00314     Array<double> quadWeights;
00315     getQuad(quad, fc, quadPts, quadWeights);
00316 
00317     int nQuad = quadPts.size();
00318 
00319     for (int r=0; r<nRefDerivTest(); r++)
00320     {
00321       Tabs tab2;
00322       SUNDANCE_MSG2(setupVerb(), tab2 
00323         << "evaluating test function basis derivative " 
00324         << r << " of " << nRefDerivTest());
00325       testBasisVals[r].resize(testBasis.dim());
00326       MultiIndex mi;
00327       if (testDerivOrder==1) mi[r] = 1;
00328       SpatialDerivSpecifier deriv(mi);
00329       testBasis.refEval(evalCellType(), quadPts, deriv,
00330         testBasisVals[r], setupVerb());
00331     }
00332 
00333     for (int r=0; r<nRefDerivUnk(); r++)
00334     {
00335       Tabs tab2;
00336       SUNDANCE_MSG2(setupVerb(), tab2 
00337         << "evaluating unknown function basis derivative " 
00338         << r << " of " << nRefDerivUnk());
00339       unkBasisVals[r].resize(unkBasis.dim());
00340       MultiIndex mi;
00341       if (unkDerivOrder==1) mi[r] = 1;
00342       SpatialDerivSpecifier deriv(mi);
00343       unkBasis.refEval(evalCellType(), 
00344         quadPts, deriv, unkBasisVals[r], setupVerb());
00345     }
00346 
00347     SUNDANCE_MSG2(setupVerb(), tab1 << "doing quadrature...");
00348     int vecComp = 0;
00349     for (int q=0; q<nQuad; q++)
00350     {
00351       for (int t=0; t<nRefDerivTest(); t++)
00352       {
00353         for (int nt=0; nt<nNodesTest(); nt++)
00354         {
00355           for (int u=0; u<nRefDerivUnk(); u++)
00356           {
00357             for (int nu=0; nu<nNodesUnk(); nu++)
00358             {
00359               value(fc, t, nt, u, nu) 
00360                 += chop(quadWeights[q] * testBasisVals[t][vecComp][q][nt]
00361                   * unkBasisVals[u][vecComp][q][nu]);
00362             }
00363           }
00364         }
00365       }
00366     }
00367     SUNDANCE_MSG2(setupVerb(), tab1 << "...done");
00368     addFlops(4*nQuad*nRefDerivTest()*nNodesTest()*nRefDerivUnk()*nNodesUnk()
00369       + W_[fc].size());
00370     for (int i=0; i<W_[fc].size(); i++) W_[fc][i] = chop(W_[fc][i]);
00371   }
00372 
00373   SUNDANCE_MSG1(setupVerb(), tab0 
00374     << "----------------------------------------");
00375   SUNDANCE_MSG4(setupVerb(), tab0 
00376     << "reduced bilinear form integral results");
00377   if (setupVerb() >= 4)
00378   {
00379     for (int fc=0; fc<nFacetCases(); fc++)
00380     {
00381       Tabs tab1;
00382       SUNDANCE_MSG4(setupVerb(), tab1 << "evaluation case " << fc << " of "
00383         << nFacetCases());
00384       
00385       for (int rt=0; rt<nRefDerivTest(); rt++)
00386       {
00387         for (int ru=0; ru<nRefDerivUnk(); ru++)
00388         {
00389           Tabs tab2;
00390           MultiIndex miTest;
00391           if (testDerivOrder==1) miTest[rt] = 1;
00392           MultiIndex miUnk;
00393           if (unkDerivOrder==1) miUnk[ru] = 1;
00394           SUNDANCE_MSG1(setupVerb(), tab2 << "test multiindex=" << miTest
00395             << " unk multiindex=" << miUnk);
00396           
00397           ios_base::fmtflags oldFlags = Out::os().flags();
00398           Out::os().setf(ios_base::right);    
00399           Out::os().setf(ios_base::showpoint);
00400           for (int nt=0; nt<nNodesTest(); nt++)
00401           {
00402             Tabs tab3;
00403             Out::os() << tab3 << setw(10) << nt;
00404             for (int nu=0; nu<nNodesUnk(); nu++)
00405             {
00406               Out::os() << setw(12) << std::setprecision(5)
00407                         << value(fc, rt, nt, ru, nu) ;
00408             }
00409             Out::os() << std::endl;
00410           }
00411           Out::os().flags(oldFlags);
00412         }
00413       }
00414     }
00415   }
00416 
00417   SUNDANCE_MSG1(setupVerb(), tab0 << "done reduced bilinear form ctor");
00418 }
00419 
00420 
00421 
00422 
00423 void ReducedIntegral::transformZeroForm(const CellJacobianBatch& JTrans,
00424   const CellJacobianBatch& JVol,
00425   const Array<int>& isLocalFlag,  
00426   const Array<int>& facetIndex,
00427   const RCP<Array<int> >& cellLIDs,
00428   const double* const coeffs,
00429   RCP<Array<double> >& A) const
00430 {
00431   TimeMonitor timer(reduced0IntegrationTimer());
00432 
00433   TEUCHOS_TEST_FOR_EXCEPTION(order() != 0, std::logic_error,
00434     "ReducedIntegral::transformZeroForm() called "
00435     "for form of order " << order());
00436 
00437   Tabs tabs;  
00438   SUNDANCE_MSG1(integrationVerb(), tabs << "doing zero form by reduced integration");
00439 
00440   double& a = (*A)[0];
00441   int flops = 0;
00442 
00443   /* if we don't need to check whether elements are local, we
00444    * can streamline the loop. This will be the case when
00445    * we are evaluating a functional but not its gradient */
00446   double w = W_[0][0];
00447   if ((int) isLocalFlag.size()==0)
00448   {
00449     /* not supporting ACI for now */
00450     if (globalCurve().isCurveValid())
00451     {
00452       TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid());
00453     }
00454     else
00455     {
00456       for (int c=0; c<JVol.numCells(); c++)
00457       {
00458         flops+=3;
00459         a += w * coeffs[c] * fabs(JVol.detJ()[c]);
00460       }
00461     }
00462 
00463   }
00464   else
00465   {
00466     TEUCHOS_TEST_FOR_EXCEPTION( (int) isLocalFlag.size() != JVol.numCells(),
00467       std::runtime_error,
00468       "mismatch between isLocalFlag.size()=" 
00469       << isLocalFlag.size()
00470       << " and JVol.numCells()=" << JVol.numCells());
00471 
00472     if (globalCurve().isCurveValid())
00473     {  
00474       TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid());
00475     }
00476     else         /* ---------- NO ACI logic ----------- */
00477     {
00478       for (int c=0; c<JVol.numCells(); c++)
00479       {
00480         if (isLocalFlag[c])
00481         {
00482           flops+=3;
00483           a += w * coeffs[c] * fabs(JVol.detJ()[c]);
00484         }
00485       }
00486     }
00487   }
00488   addFlops(flops);
00489 }
00490 
00491 void ReducedIntegral::transformOneForm(const CellJacobianBatch& JTrans,  
00492   const CellJacobianBatch& JVol,
00493   const Array<int>& facetIndex,
00494   const RCP<Array<int> >& cellLIDs,
00495   const double* const coeffs,
00496   RCP<Array<double> >& A) const
00497 {
00498   TimeMonitor timer(reduced1IntegrationTimer());
00499   TEUCHOS_TEST_FOR_EXCEPTION(order() != 1, std::logic_error,
00500     "ReducedIntegral::transformOneForm() called for form "
00501     "of order " << order());
00502   Tabs tabs;  
00503   SUNDANCE_MSG1(integrationVerb(),
00504     tabs << "doing one form by reduced integration");
00505 
00506   int nfc = nFacetCases();
00507 
00508   /* If the derivative order is zero, the only transformation to be done 
00509    * is to multiply by the cell's Jacobian determinant.  Each entry also needs
00510    * to be multiplied by the coefficient for the current cell. */
00511   if (testDerivOrder() == 0)
00512   {
00513     double* aPtr = &((*A)[0]);
00514     int count = 0;
00515     if (globalCurve().isCurveValid())
00516     {    /* ---------- ACI logic ----------- */
00517       TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid());      
00518     }
00519     else         /* ---------- NO ACI logic ----------- */
00520     {
00521       for (int c=0; c<JVol.numCells(); c++)
00522       {
00523         double w_cell = coeffs[c] * fabs(JVol.detJ()[c]);
00524         int fc = 0;
00525         if (nfc != 1) fc = facetIndex[c];
00526 
00527         const Array<double>& w = W_[fc];
00528         for (int n=0; n<nNodes(); n++, count++)
00529         {
00530           aPtr[count] += w_cell*w[n];
00531         }
00532       }
00533     }
00534     addFlops(JVol.numCells() * (nNodes() + 2));
00535   }
00536   else
00537   {
00538     /* If the derivative order is nonzero, then we have to do a transformation. 
00539      * If we're also on a cell of dimension lower than maximal, we need to refer
00540      * to the facet index of the facet being integrated. */
00541     int nCells = JVol.numCells();
00542     double one = 1.0;
00543     int nTransRows = nRefDerivTest();
00544 
00545     createOneFormTransformationMatrix(JTrans, JVol);
00546 
00547     SUNDANCE_MSG3(transformVerb(),
00548       Tabs() << "transformation matrix=" << G(alpha()));
00549     int nNodes0 = nNodes();
00550       
00551     if (nFacetCases()==1)
00552     {
00553       /* 
00554        * on maximal cell
00555        */
00556       if (globalCurve().isCurveValid())
00557       {   /* ---------- ACI logic ----------- */
00558         TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid()); 
00559       }
00560       else           /* ---------- NO ACI logic----------- */
00561       {
00562         int N = 1;
00563         for (int c=0; c<JVol.numCells(); c++)
00564         {
00565           double* aPtr = &((*A)[c*nNodes0]);
00566           ::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &(coeffs[c]), &(W_[0][0]),
00567             &nNodes0, &(G(alpha())[c*nTransRows]), &nTransRows, &one,
00568             aPtr, &nNodes0);
00569         }
00570       }
00571     }
00572     else
00573     {
00574       /* If we're on a lower-dimensional cell and have to transform, 
00575        * we've got to do each transformation using a different facet case */
00576       if (globalCurve().isCurveValid())
00577       {                 /* ---------- ACI logic ----------- */
00578         TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid()); 
00579       }
00580       else  /* ---------- NO ACI logic ----------- */
00581       {
00582         int N = 1;
00583         for (int c=0; c<JVol.numCells(); c++)
00584         {
00585           int fc = 0;
00586           if (nfc != 1) fc = facetIndex[c];
00587           double* aPtr = &((*A)[c*nNodes0]);
00588           ::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &(coeffs[c]), &(W_[fc][0]),
00589             &nNodes0, &(G(alpha())[c*nTransRows]), &nTransRows, &one,
00590             aPtr, &nNodes0);
00591         }
00592       }
00593     }
00594       
00595     addFlops(2 * nNodes0 * nCells * nTransRows);
00596   }
00597 }
00598 
00599 void ReducedIntegral::transformTwoForm(const CellJacobianBatch& JTrans,
00600   const CellJacobianBatch& JVol,
00601   const Array<int>& facetIndex, 
00602   const RCP<Array<int> >& cellLIDs,
00603   const double* const coeffs,
00604   RCP<Array<double> >& A) const
00605 {
00606   TimeMonitor timer(reduced2IntegrationTimer());
00607   TEUCHOS_TEST_FOR_EXCEPTION(order() != 2, std::logic_error,
00608     "ReducedIntegral::transformTwoForm() called for form "
00609     "of order " << order());
00610   
00611   Tabs tabs;  
00612   SUNDANCE_MSG1(transformVerb(), tabs << "doing two form by reduced integration");
00613 
00614   int nfc = nFacetCases();
00615 
00616   /* If the derivative orders are zero, the only transformation to be done 
00617    * is to multiply by the cell's Jacobian determinant */
00618   if (testDerivOrder() == 0 && unkDerivOrder() == 0)
00619   {
00620     if (globalCurve().isCurveValid())
00621     {     /* ----------- ACI logic ------------ */
00622       TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid()); 
00623     }
00624     else        /* ---------- NO ACI logic----------- */
00625     {
00626       double* aPtr = &((*A)[0]);
00627       int count = 0;
00628       for (int c=0; c<JVol.numCells(); c++)
00629       {
00630         int fc = 0;
00631         if (nFacetCases() != 1) fc = facetIndex[c];
00632 
00633         const Array<double>& w = W_[fc];
00634         double w_cell = coeffs[c] * fabs(JVol.detJ()[c]);
00635         for (int n=0; n<nNodes(); n++, count++)
00636         {
00637           aPtr[count] += w_cell*w[n];
00638         }
00639       }
00640     }
00641     addFlops(JVol.numCells() * (nNodes() + 1));
00642   }
00643   else
00644   {
00645     /* If the derivative order is nonzero, then we have to do a transformation. 
00646      * If we're also on a cell of dimension lower than maximal, we need to refer
00647      * to the facet index of the facet being integrated. */
00648     int nCells = JVol.numCells();
00649     double one = 1.0;
00650     int nTransRows = nRefDerivUnk()*nRefDerivTest();
00651 
00652     createTwoFormTransformationMatrix(JTrans, JVol);
00653       
00654     double* GPtr;
00655     if (testDerivOrder() == 0)
00656     {
00657       GPtr = &(G(beta())[0]);
00658       SUNDANCE_MSG2(transformVerb(),
00659         Tabs() << "transformation matrix=" << G(beta()));
00660     }
00661     else if (unkDerivOrder() == 0)
00662     {
00663       GPtr = &(G(alpha())[0]);
00664       SUNDANCE_MSG2(transformVerb(),
00665         Tabs() << "transformation matrix=" << G(alpha()));
00666     }
00667     else
00668     {
00669       GPtr = &(G(alpha(), beta())[0]);
00670       SUNDANCE_MSG2(transformVerb(),
00671         Tabs() << "transformation matrix=" 
00672         << G(alpha(),beta()));
00673     }
00674       
00675     int nNodes0 = nNodes();
00676 
00677     if (nFacetCases()==1)
00678     {
00679       /* 
00680        * on maximal cell
00681        */
00682       if (globalCurve().isCurveValid())
00683       {          /* ---------- ACI logic ----------- */
00684         TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid());         
00685       }
00686       else /* ---------- NO ACI ----------- */
00687       {
00688         int N = 1;
00689         for (int c=0; c<JVol.numCells(); c++)
00690         {
00691           double* aPtr = &((*A)[c*nNodes0]);
00692           double* gPtr = &(GPtr[c*nTransRows]);
00693           SUNDANCE_MSG2(integrationVerb(),
00694             tabs << "transforming c=" << c << ", W=" << W_[0]);
00695           
00696           ::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &(coeffs[c]), &(W_[0][0]),
00697             &nNodes0, gPtr, &nTransRows, &one,
00698             aPtr, &nNodes0);
00699         }
00700       }
00701     }
00702     else
00703     {
00704       /* If we're on a lower-dimensional cell and have to transform, 
00705        * we've got to do each transformation using a different facet case */
00706       if (globalCurve().isCurveValid())
00707       {   /* ---------- ACI logic ----------- */
00708         TEUCHOS_TEST_FOR_EXCEPT(globalCurve().isCurveValid());         
00709       }
00710       else         /* ---------- NO ACI ----------- */
00711       {
00712         int N = 1;
00713         for (int c=0; c<JVol.numCells(); c++)
00714         {
00715           int fc = 0;
00716           if (nfc != 1) fc = facetIndex[c];
00717           double* aPtr = &((*A)[c*nNodes0]);
00718           double* gPtr = &(GPtr[c*nTransRows]);
00719           SUNDANCE_MSG2(integrationVerb(),
00720             tabs << "c=" << c << ", facet case=" << fc
00721             << " W=" << W_[fc]);
00722 
00723           ::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &(coeffs[c]), &(W_[fc][0]),
00724             &nNodes0, gPtr, &nTransRows, &one,
00725             aPtr, &nNodes0);
00726         }
00727       }
00728     }// from else of (nFacetCases()==1)
00729       
00730     addFlops(2 * nNodes0 * nCells * nTransRows);
00731   }
00732 }
00733 

Site Contact