SundanceRefIntegral.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 "SundanceRefIntegral.hpp"
00032 #include "SundanceGaussianQuadrature.hpp"
00033 #include "SundanceGaussianQuadratureType.hpp"
00034 #include "SundanceQuadratureType.hpp"
00035 #include "SundanceSpatialDerivSpecifier.hpp"
00036 #include "SundanceOut.hpp"
00037 #include "SundanceTabs.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& refIntegrationTimer() 
00059 {
00060   static RCP<Time> rtn
00061     = TimeMonitor::getNewTimer("ref integration"); 
00062   return *rtn;
00063 }
00064 
00065 
00066 
00067 RefIntegral::RefIntegral(int spatialDim,
00068   const CellType& maxCellType,
00069   int dim, 
00070   const CellType& cellType,
00071   const QuadratureFamily& quad_in,
00072   bool isInternalBdry,
00073   const ParametrizedCurve& globalCurve,
00074   const Mesh& mesh,
00075   int verb)
00076   : ElementIntegral(spatialDim, maxCellType, dim, cellType, isInternalBdry, globalCurve , mesh,
00077     verb), W_()
00078 {
00079   Tabs tab0(0);
00080 
00081   SUNDANCE_MSG1(setupVerb(),
00082     tab0 << "************* creating reference 0-form integrals ********");
00083   if (setupVerb()) describe(Out::os());
00084   
00085   /* we need to sum the quadrature weights 
00086      to compute the volume of the reference cell */
00087   QuadratureFamily quad = new GaussianQuadrature(2);
00088   /* If we have a valid curve (in case of Adaptive Cell Integration)
00089    * then we have to choose the quadrature which the user specified*/
00090   if (globalCurve.isCurveValid()){
00091    quad = quad_in;
00092    Tabs tab1;
00093    SUNDANCE_MSG1(setupVerb(),tab1 << "ACI change quadrature to Quadrature of order: "<<quad.order());
00094   }
00095   quad_ = quad;
00096 
00097   Array<Point> quadPts;
00098   Array<double> quadWeights;
00099 
00100   W_.resize(1);
00101   W_[0].resize(1);
00102 
00103   quad.getPoints(cellType, quadPts, quadWeights);  
00104 
00105   quadWeights_ = quadWeights;
00106 
00107   for (int q=0; q<quadWeights.size(); q++) {
00108     W_[0][0] += quadWeights[q];
00109   }
00110 }
00111 
00112 RefIntegral::RefIntegral(int spatialDim,
00113   const CellType& maxCellType,
00114   int dim, 
00115   const CellType& cellType,
00116   const BasisFamily& testBasis,
00117   int alpha,
00118   int testDerivOrder,
00119   const QuadratureFamily& quad_in,
00120   bool isInternalBdry,
00121   const ParametrizedCurve& globalCurve,
00122   const Mesh& mesh,
00123   int verb)
00124   : ElementIntegral(spatialDim, maxCellType, dim, cellType, 
00125     testBasis, alpha, testDerivOrder, isInternalBdry, globalCurve , mesh , verb), W_()
00126 {
00127   Tabs tab0(0);
00128   SUNDANCE_MSG1(setupVerb(),
00129     tab0 << "************* creating reference 1-form integrals ********");
00130   if (setupVerb()) describe(Out::os());
00131   assertLinearForm();
00132 
00133   W_.resize(nFacetCases());
00134   W_ACI_F1_.resize(nFacetCases());
00135 
00136   /* Determine the quadrature order needed for exact integrations */
00137   QuadratureType qType = new GaussianQuadratureType();
00138   int reqOrder = qType.findValidOrder(cellType, 
00139     std::max(1, testBasis.order()));
00140 
00141   SUNDANCE_MSG2(setupVerb(),
00142     tab0 << "using quadrature order=" << reqOrder);
00143    
00144   /* Create a quadrature family of the required order */
00145   QuadratureFamily quad = qType.createQuadFamily(reqOrder);
00146   
00147   /* If we have a valid curve (in case of Adaptive Cell Integration)
00148    * then we have to choose the quadrature which the user specified*/
00149   if (globalCurve.isCurveValid()){
00150    quad = quad_in;
00151    Tabs tab1;
00152    SUNDANCE_MSG1(setupVerb(),tab1 << "ACI change quadrature to Quadrature of order: "<<quad.order());
00153   }
00154   quad_ = quad;
00155 
00156   /* We now loop over the different evaluation cases, integrating the
00157    * basis functions for each. Because this is a reference integral,
00158    * we can actually do the untransformed integrals here. */
00159   for (int fc=0; fc<nFacetCases(); fc++)
00160   {
00161     Tabs tab1;
00162     SUNDANCE_MSG2(setupVerb(),
00163       tab1 << "evaluation case=" << fc << " of " << nFacetCases());
00164     /* initialize size of untransformed integral results array */
00165     W_[fc].resize(nRefDerivTest() * nNodesTest());
00166 
00167     /* initialize values of integrals to zero */
00168     for (int i=0; i<W_[fc].size(); i++) { W_[fc][i]=0.0; }
00169 
00170     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00171   
00172     /* get quadrature points */
00173 
00174     getQuad(quad, fc, quadPts_, quadWeights_);
00175 
00176     int nQuad = quadPts_.size();
00177 
00178     /* compute the basis functions */
00179     for (int r=0; r<nRefDerivTest(); r++)
00180     {
00181       Tabs tab2;
00182       SUNDANCE_MSG2(setupVerb(), tab2 << "evaluating basis derivative " 
00183         << r << " of " << nRefDerivTest());
00184 
00185       testBasisVals[r].resize(testBasis.dim());
00186       MultiIndex mi;
00187       if (testDerivOrder==1) mi[r] = 1;
00188       SpatialDerivSpecifier deriv(mi);
00189       testBasis.refEval(evalCellType(), quadPts_, deriv,
00190         testBasisVals[r], setupVerb());
00191     }
00192 
00193     /* do the quadrature */
00194     SUNDANCE_MSG2(setupVerb(), tab1 << "doing quadrature");
00195     int vecComp = 0;
00196     W_ACI_F1_[fc].resize(nQuad);
00197     for (int q=0; q<nQuad; q++)
00198     {
00199       W_ACI_F1_[fc][q].resize(nRefDerivTest());
00200       for (int t=0; t<nRefDerivTest(); t++)
00201       {
00202       W_ACI_F1_[fc][q][t].resize(nNodesTest());
00203         for (int nt=0; nt<nNodesTest(); nt++)
00204         {
00205           value(fc, t, nt) 
00206             += chop(quadWeights_[q] * testBasisVals[t][vecComp][q][nt]) ;
00207           W_ACI_F1_[fc][q][t][nt] = chop(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 << "reference 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 reference linear form ctor");
00252 }
00253 
00254 
00255 
00256 
00257 RefIntegral::RefIntegral(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 reference 2-form integrals ********");
00280   if (setupVerb()) describe(Out::os());
00281 
00282   assertBilinearForm();
00283 
00284   W_.resize(nFacetCases());
00285   W_ACI_F2_.resize(nFacetCases());
00286 
00287   QuadratureType qType = new GaussianQuadratureType();
00288   int reqOrder = qType.findValidOrder(cellType,
00289       std::max(1, unkBasis.order() + testBasis.order()));
00290 
00291   SUNDANCE_MSG2(setupVerb(),
00292       tab0 << "using quadrature order=" << reqOrder);
00293   QuadratureFamily quad = qType.createQuadFamily(reqOrder);
00294 
00295   /* If we have a valid curve (in case of Adaptive Cell Integration)
00296    * then we have to choose the quadrature which the user specified*/
00297   if (globalCurve.isCurveValid()){
00298    quad = quad_in;
00299    Tabs tab1;
00300    SUNDANCE_MSG1(setupVerb(),tab1 << "ACI change quadrature to Quadrature of order: "<<quad.order());
00301   }
00302   quad_ = quad;
00303 
00304   SUNDANCE_MSG2(setupVerb(),
00305     tab0 << "processing evaluation cases");
00306 
00307   for (int fc=0; fc<nFacetCases(); fc++)
00308   {
00309     Tabs tab1;
00310     SUNDANCE_MSG1(setupVerb(), tab1 << "------ evaluation case " << fc << " of "
00311       << nFacetCases() << "-------");
00312     
00313     W_[fc].resize(nRefDerivTest() * nNodesTest()  * nRefDerivUnk() * nNodesUnk());
00314     for (int i=0; i<W_[fc].size(); i++) W_[fc][i]=0.0;
00315 
00316     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00317     Array<Array<Array<Array<double> > > > unkBasisVals(nRefDerivUnk());
00318         
00319     getQuad(quad, fc, quadPts_, quadWeights_);
00320     int nQuad = quadPts_.size();
00321 
00322     for (int r=0; r<nRefDerivTest(); r++)
00323     {
00324       Tabs tab2;
00325       SUNDANCE_MSG2(setupVerb(), tab2 
00326         << "evaluating test function basis derivative " 
00327         << r << " of " << nRefDerivTest());
00328       testBasisVals[r].resize(testBasis.dim());
00329       MultiIndex mi;
00330       if (testDerivOrder==1) mi[r] = 1;
00331       SpatialDerivSpecifier deriv(mi);
00332       testBasis.refEval(evalCellType(), quadPts_, deriv,
00333         testBasisVals[r], setupVerb());
00334     }
00335 
00336     for (int r=0; r<nRefDerivUnk(); r++)
00337     {
00338       Tabs tab2;
00339       SUNDANCE_MSG2(setupVerb(), tab2 
00340         << "evaluating unknown function basis derivative " 
00341         << r << " of " << nRefDerivUnk());
00342       unkBasisVals[r].resize(unkBasis.dim());
00343       MultiIndex mi;
00344       if (unkDerivOrder==1) mi[r] = 1;
00345       SpatialDerivSpecifier deriv(mi);
00346       unkBasis.refEval(evalCellType(), 
00347       quadPts_, deriv, unkBasisVals[r], setupVerb());
00348     }
00349 
00350     SUNDANCE_MSG2(setupVerb(), tab1 << "doing quadrature...");
00351     int vecComp = 0;
00352     W_ACI_F2_[fc].resize(nQuad);
00353     for (int q=0; q<nQuad; q++)
00354     {
00355       W_ACI_F2_[fc][q].resize(nRefDerivTest());
00356       for (int t=0; t<nRefDerivTest(); t++)
00357       {
00358         W_ACI_F2_[fc][q][t].resize(nNodesTest());
00359         for (int nt=0; nt<nNodesTest(); nt++)
00360         {
00361           W_ACI_F2_[fc][q][t][nt].resize(nRefDerivUnk());
00362           for (int u=0; u<nRefDerivUnk(); u++)
00363           {
00364             W_ACI_F2_[fc][q][t][nt][u].resize(nNodesUnk());
00365             for (int nu=0; nu<nNodesUnk(); nu++)
00366             {
00367               value(fc, t, nt, u, nu) 
00368                 += chop(quadWeights_[q] * testBasisVals[t][vecComp][q][nt]
00369                   * unkBasisVals[u][vecComp][q][nu]);
00370               W_ACI_F2_[fc][q][t][nt][u][nu] = chop( testBasisVals[t][vecComp][q][nt]
00371                                                * unkBasisVals[u][vecComp][q][nu] );
00372             }
00373           }
00374         }
00375       }
00376     }
00377     SUNDANCE_MSG2(setupVerb(), tab1 << "...done");
00378     addFlops(4*nQuad*nRefDerivTest()*nNodesTest()*nRefDerivUnk()*nNodesUnk()
00379       + W_[fc].size());
00380     for (int i=0; i<W_[fc].size(); i++) W_[fc][i] = chop(W_[fc][i]);
00381   }
00382 
00383   SUNDANCE_MSG1(setupVerb(), tab0 
00384     << "----------------------------------------");
00385   SUNDANCE_MSG4(setupVerb(), tab0 
00386     << "reference bilinear form integral results");
00387   if (setupVerb() >= 4)
00388   {
00389     for (int fc=0; fc<nFacetCases(); fc++)
00390     {
00391       Tabs tab1;
00392       SUNDANCE_MSG4(setupVerb(), tab1 << "evaluation case " << fc << " of "
00393         << nFacetCases());
00394       
00395       for (int rt=0; rt<nRefDerivTest(); rt++)
00396       {
00397         for (int ru=0; ru<nRefDerivUnk(); ru++)
00398         {
00399           Tabs tab2;
00400           MultiIndex miTest;
00401           if (testDerivOrder==1) miTest[rt] = 1;
00402           MultiIndex miUnk;
00403           if (unkDerivOrder==1) miUnk[ru] = 1;
00404           SUNDANCE_MSG1(setupVerb(), tab2 << "test multiindex=" << miTest
00405             << " unk multiindex=" << miUnk);
00406           
00407           ios_base::fmtflags oldFlags = Out::os().flags();
00408           Out::os().setf(ios_base::right);    
00409           Out::os().setf(ios_base::showpoint);
00410           for (int nt=0; nt<nNodesTest(); nt++)
00411           {
00412             Tabs tab3;
00413             Out::os() << tab3 << setw(10) << nt;
00414             for (int nu=0; nu<nNodesUnk(); nu++)
00415             {
00416               Out::os() << setw(12) << std::setprecision(5)
00417                         << value(fc, rt, nt, ru, nu) ;
00418             }
00419             Out::os() << std::endl;
00420           }
00421           Out::os().flags(oldFlags);
00422         }
00423       }
00424     }
00425   }
00426 
00427   SUNDANCE_MSG1(setupVerb(), tab0 << "done reference bilinear form ctor");
00428 }
00429 
00430 
00431 
00432 
00433 void RefIntegral::transformZeroForm(const CellJacobianBatch& JVol,
00434   const Array<int>& isLocalFlag,  
00435   const RCP<Array<int> >& cellLIDs,
00436   const double& coeff,
00437   RCP<Array<double> >& A) const
00438 {
00439   TimeMonitor timer(refIntegrationTimer());
00440 
00441   TEST_FOR_EXCEPTION(order() != 0, InternalError,
00442     "RefIntegral::transformZeroForm() called "
00443     "for form of order " << order());
00444 
00445   Tabs tabs;  
00446   SUNDANCE_MSG1(integrationVerb(), tabs << "doing zero form by reference");
00447 
00448   double& a = (*A)[0];
00449   int flops = 0;
00450   const Array<int>* cellLID = cellLIDs.get();
00451 
00452   /* if we don't need to check whether elements are local, we
00453    * can streamline the loop. This will be the case when
00454    * we are evaluating a functional but not its gradient */
00455   double w = coeff * W_[0][0];
00456   if ((int) isLocalFlag.size()==0)
00457   {
00458       if (globalCurve().isCurveValid())
00459       {     /* ---------- ACI logic ----------- */
00460 
00461         Array<double> quadWeightsTmp = quadWeights_;
00462         Array<Point> quadPointsTmp = quadPts_;
00463         bool isCutByCurve;
00464 
00465         for (int c=0; c<JVol.numCells(); c++)
00466         {
00467           int fc = 0;
00468           /* call the special integration routine */
00469           quadWeightsTmp = quadWeights_;
00470           quadPointsTmp = quadPts_;
00471           quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc ,mesh(),
00472               globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00473           /* if we have special weights then do the same as before */
00474           if (isCutByCurve){
00475             double sumweights = 0;
00476             for (int j=0; j < quadWeightsTmp.size(); j++) sumweights += chop(quadWeightsTmp[j]);
00477             flops+=3+quadWeightsTmp.size();  //Todo: the curve stuff not counted
00478             a += coeff * sumweights * fabs(JVol.detJ()[c]);
00479           } else {
00480             flops+=2;  //Todo: the curve stuff not counted
00481             a += w * fabs(JVol.detJ()[c]);
00482           }
00483         }
00484       }
00485       else /* -------- NO ACI logic ------- */
00486       {
00487         for (int c=0; c<JVol.numCells(); c++)
00488         {
00489         flops+=2;
00490         a += w * fabs(JVol.detJ()[c]);
00491         }
00492       }
00493 
00494   }
00495   else
00496   {
00497     TEST_FOR_EXCEPTION( (int) isLocalFlag.size() != JVol.numCells(),
00498       RuntimeError,
00499       "mismatch between isLocalFlag.size()=" 
00500       << isLocalFlag.size()
00501       << " and JVol.numCells()=" << JVol.numCells());
00502 
00503       int fc = 0;
00504       if (globalCurve().isCurveValid())
00505       {   /* ---------- ACI logic ----------- */
00506         Array<double> quadWeightsTmp = quadWeights_;
00507         Array<Point> quadPointsTmp = quadPts_;
00508         bool isCutByCurve;
00509 
00510         for (int c=0; c<JVol.numCells(); c++)
00511         {
00512           if (isLocalFlag[c])
00513           {
00514 
00515           /* call the special integration routine */
00516           quadWeightsTmp = quadWeights_;
00517           quadPointsTmp = quadPts_;
00518           quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc , mesh(),
00519               globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00520           /* if we do not have special weights then do the same as before */
00521           if (isCutByCurve){
00522             double sumweights = 0;
00523             for (int j=0; j < quadWeightsTmp.size(); j++) sumweights += chop(quadWeightsTmp[j]);
00524             flops+=3+quadWeightsTmp.size();  //Todo: the curve stuff not counted
00525             a += coeff * sumweights * fabs(JVol.detJ()[c]);
00526           } else {
00527             flops+=2;  //Todo: the curve stuff not counted
00528             a += w * fabs(JVol.detJ()[c]);
00529           }
00530           }
00531         }
00532       }
00533         else         /* ---------- NO ACI logic ----------- */
00534       {
00535         for (int c=0; c<JVol.numCells(); c++)
00536         {
00537             if (isLocalFlag[c])
00538             {
00539           flops+=2;
00540           a += w * fabs(JVol.detJ()[c]);
00541             }
00542         }
00543       }
00544   }
00545   addFlops(flops);
00546 }
00547 
00548 void RefIntegral::transformOneForm(const CellJacobianBatch& JTrans,  
00549   const CellJacobianBatch& JVol,
00550   const Array<int>& facetIndex,
00551   const RCP<Array<int> >& cellLIDs,
00552   const double& coeff,
00553   RCP<Array<double> >& A) const
00554 {
00555   TimeMonitor timer(refIntegrationTimer());
00556   TEST_FOR_EXCEPTION(order() != 1, InternalError,
00557     "RefIntegral::transformOneForm() called for form "
00558     "of order " << order());
00559   Tabs tabs;  
00560   SUNDANCE_MSG1(integrationVerb(),
00561     tabs << "doing one form by reference");
00562 
00563   int nfc = nFacetCases();
00564 
00565   /* If the derivative order is zero, the only transformation to be done 
00566    * is to multiply by the cell's Jacobian determinant */
00567   if (testDerivOrder() == 0)
00568   {
00569     double* aPtr = &((*A)[0]);
00570     int count = 0;
00571     if (globalCurve().isCurveValid())
00572     {    /* ---------- ACI logic ----------- */
00573 
00574        Array<double> quadWeightsTmp = quadWeights_;
00575        Array<Point> quadPointsTmp = quadPts_;
00576        bool isCutByCurve = false;
00577 
00578        for (int c=0; c<JVol.numCells(); c++)
00579        {
00580          double detJ = coeff * fabs(JVol.detJ()[c]);
00581          int fc = 0;
00582          if (nfc != 1) fc = facetIndex[c];
00583 
00584          quadWeightsTmp = quadWeights_;
00585          quadPointsTmp = quadPts_;
00586          /* call the special integration routine */
00587          quad_.getAdaptedWeights(cellType(), dim(), (*cellLIDs)[c] , fc ,
00588              mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00589          if (isCutByCurve)
00590          {
00591            Array<double> w;
00592            w.resize(nNodesTest()); //recalculate the special weights
00593            for (int nt = 0 ; nt < nNodesTest() ; nt++){
00594              w[nt] = 0.0;
00595              for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00596                w[nt] += chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][0][nt]);
00597            }
00598            // do the integration here
00599            for (int n=0; n<nNodes(); n++, count++)
00600            {
00601              aPtr[count] += detJ*w[n];
00602            }
00603           }
00604           else
00605           {
00606             const Array<double>& w = W_[fc];
00607             for (int n=0; n<nNodes(); n++, count++)
00608             {
00609               aPtr[count] += detJ*w[n];
00610             }
00611           }
00612        }
00613     }
00614     else         /* ---------- NO ACI logic ----------- */
00615     {
00616        for (int c=0; c<JVol.numCells(); c++)
00617        {
00618           double detJ = coeff * fabs(JVol.detJ()[c]);
00619           int fc = 0;
00620           if (nfc != 1) fc = facetIndex[c];
00621 
00622         const Array<double>& w = W_[fc];
00623         for (int n=0; n<nNodes(); n++, count++)
00624         {
00625           aPtr[count] += detJ*w[n];
00626         }
00627        }
00628     }
00629     addFlops(JVol.numCells() * (nNodes() + 1));
00630   }
00631   else
00632   {
00633     /* If the derivative order is nonzero, then we have to do a transformation. 
00634      * If we're also on a cell of dimension lower than maximal, we need to refer
00635      * to the facet index of the facet being integrated. */
00636     int nCells = JVol.numCells();
00637     double one = 1.0;
00638     int nTransRows = nRefDerivTest();
00639 
00640     createOneFormTransformationMatrix(JTrans, JVol);
00641 
00642     SUNDANCE_MSG3(transformVerb(),
00643       Tabs() << "transformation matrix=" << G(alpha()));
00644     int nNodes0 = nNodes();
00645       
00646     if (nFacetCases()==1)
00647     {
00648       /* if we're on a maximal cell, we can do transformations 
00649        * for all cells in a single batch. 
00650        */
00651       if (globalCurve().isCurveValid())
00652       {   /* ---------- ACI logic ----------- */
00653 
00654        Array<double> quadWeightsTmp = quadWeights_;
00655        Array<Point> quadPointsTmp = quadPts_;
00656        bool isCutByCurve = false;
00657 
00658        double* aPtr_tmp = &((*A)[0]);
00659        int count = 0;
00660        const int oneI = 1;
00661        for (int c=0; c<JVol.numCells(); c++)
00662        {
00663            int fc = 0;
00664            if (nfc != 1) fc = facetIndex[c];
00665          /* call the special integration routine */
00666            quadWeightsTmp = quadWeights_;
00667            quadPointsTmp = quadPts_;
00668          quad_.getAdaptedWeights(cellType(), dim(), (*cellLIDs)[c], fc ,
00669            mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve);
00670          if (isCutByCurve){
00671            Array<double> w;
00672            w.resize(nRefDerivTest()*nNodes()); //recalculate the special weights
00673          for (int i = 0 ; i < nRefDerivTest()*nNodes() ; w[i] = 0.0 , i++);
00674              for (int t=0; t<nRefDerivTest(); t++)
00675              for (int nt = 0 ; nt < nNodesTest() ; nt++){
00676              for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00677                //Index formula: nNodesTest()*testDerivDir + testNode
00678                w[nNodesTest()*t + nt] += chop(quadWeightsTmp[q] * W_ACI_F1_[0][q][t][nt]);
00679              }
00680    		         ::dgemm_("N", "N", &nNodes0, &oneI , &nTransRows, &coeff, &(w[0]),
00681                   &nNodes0, &(G(alpha())[0]), &nTransRows, &one,
00682                   &(aPtr_tmp[count]), &nNodes0);
00683          }else{
00684     		     ::dgemm_("N", "N", &nNodes0, &oneI , &nTransRows, &coeff, &(W_[0][0]),
00685                 &nNodes0, &(G(alpha())[0]), &nTransRows, &one,
00686                 &(aPtr_tmp[count]), &nNodes0);
00687          }
00688              count += nNodes();
00689        } // end from the for loop over the cells
00690       }
00691       else           /* ---------- NO ACI logic----------- */
00692       {
00693       ::dgemm_("N", "N", &nNodes0, &nCells, &nTransRows, &coeff, &(W_[0][0]),
00694         &nNodes0, &(G(alpha())[0]), &nTransRows, &one, 
00695         &((*A)[0]), &nNodes0);
00696       }
00697     }
00698     else
00699     {
00700       /* If we're on a lower-dimensional cell and have to transform, 
00701        * we've got to do each transformation using a different facet case */
00702         if (globalCurve().isCurveValid())
00703         {                 /* ---------- ACI logic ----------- */
00704 
00705           Array<double> quadWeightsTmp = quadWeights_;
00706           Array<Point> quadPointsTmp = quadPts_;
00707           bool isCutByCurve = false;
00708 
00709             int N = 1;
00710             for (int c=0; c<JVol.numCells(); c++)
00711             {
00712                 int fc = 0;
00713                 if (nfc != 1) fc = facetIndex[c];
00714                 double* aPtr = &((*A)[c*nNodes0]);
00715               /* call the special integration routine */
00716               quadWeightsTmp = quadWeights_;
00717               quadPointsTmp = quadPts_;
00718               quad_.getAdaptedWeights(cellType(), dim(), (*cellLIDs)[c], fc ,
00719                   mesh() , globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00720               if (isCutByCurve){
00721                 Array<double> w;
00722                 w.resize(nRefDerivTest()*nNodes()); //recalculate the special weights
00723                 for (int i = 0 ; i < nRefDerivTest()*nNodes() ; w[i] = 0.0 , i++);
00724                 for (int t=0; t<nRefDerivTest(); t++)
00725                   for (int nt = 0 ; nt < nNodesTest() ; nt++){
00726                     for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00727                       //Index formula: nNodesTest()*testDerivDir + testNode
00728                       w[nNodesTest()*t + nt] += chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][t][nt]);
00729                   }
00730             		::dgemm_("N", "N", &nNodes0, &N , &nTransRows, &coeff, &(w[0]),
00731                     &nNodes0, &(G(alpha())[0]), &nTransRows, &one,
00732                     aPtr, &nNodes0);
00733               }else{
00734             		::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &coeff, &(W_[fc][0]),
00735                     &nNodes0, &(G(alpha())[c*nTransRows]), &nTransRows, &one,
00736                     aPtr, &nNodes0);
00737               }
00738             }
00739         }
00740         else  /* ---------- NO ACI logic ----------- */
00741         {
00742             int N = 1;
00743             for (int c=0; c<JVol.numCells(); c++)
00744             {
00745                 int fc = 0;
00746                 if (nfc != 1) fc = facetIndex[c];
00747                 double* aPtr = &((*A)[c*nNodes0]);
00748                 ::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &coeff, &(W_[fc][0]),
00749                     &nNodes0, &(G(alpha())[c*nTransRows]), &nTransRows, &one,
00750                     aPtr, &nNodes0);
00751             }
00752         }
00753     }
00754       
00755     addFlops(2 * nNodes0 * nCells * nTransRows);
00756   }
00757 }
00758 
00759 void RefIntegral::transformTwoForm(const CellJacobianBatch& JTrans,
00760   const CellJacobianBatch& JVol,
00761   const Array<int>& facetIndex, 
00762   const RCP<Array<int> >& cellLIDs,
00763   const double& coeff,
00764   RCP<Array<double> >& A) const
00765 {
00766   TimeMonitor timer(refIntegrationTimer());
00767   TEST_FOR_EXCEPTION(order() != 2, InternalError,
00768     "RefIntegral::transformTwoForm() called for form "
00769     "of order " << order());
00770   
00771   Tabs tabs;  
00772   SUNDANCE_MSG1(transformVerb(), tabs << "doing two form by reference");
00773 
00774   int nfc = nFacetCases();
00775 
00776     SUNDANCE_MSG1(transformVerb(), tabs << "doing two form by reference ... ");
00777   /* If the derivative orders are zero, the only transformation to be done 
00778    * is to multiply by the cell's Jacobian determinant */
00779   if (testDerivOrder() == 0 && unkDerivOrder() == 0)
00780   {
00781       if (globalCurve().isCurveValid())
00782       {     /* ----------- ACI logic ------------ */
00783 
00784          Array<double> quadWeightsTmp = quadWeights_;
00785          Array<Point> quadPointsTmp = quadPts_;
00786          bool isCutByCurve = false;
00787 
00788          double* aPtr = &((*A)[0]);
00789          int count = 0;
00790          for (int c=0; c<JVol.numCells(); c++)
00791          {
00792            int fc = 0;
00793            if (nFacetCases() != 1) fc = facetIndex[c];
00794 
00795            /* ---------- ACI ----------- */
00796            /* call the special integration routine */
00797            quadWeightsTmp = quadWeights_;
00798            quadPointsTmp = quadPts_;
00799            quad_.getAdaptedWeights(cellType(), dim(), (*cellLIDs)[c] , fc ,
00800                mesh(), globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00801            if (isCutByCurve){
00802              Array<double> w;
00803              int ci = 0;
00804              w.resize(nNodesTest()*nNodesUnk()); //recalculate the special weights
00805              for (int nt = 0 ; nt < nNodesTest() ; nt++)
00806                for(int nu=0 ; nu < nNodesUnk() ; nu++ , ci++){
00807                  w[ci] = 0.0;
00808                  for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00809                    w[ci] += chop( quadWeightsTmp[q] * W_ACI_F2_[fc][q][0][nt][0][nu] );
00810                }
00811              // do the integration here
00812              double detJ = coeff * fabs(JVol.detJ()[c]);
00813              for (int n=0; n<nNodes(); n++, count++)
00814              {
00815                aPtr[count] += detJ*w[n];
00816              }
00817            }
00818            else
00819            {
00820               const Array<double>& w = W_[fc];
00821               double detJ = coeff * fabs(JVol.detJ()[c]);
00822               for (int n=0; n<nNodes(); n++, count++)
00823               {
00824                 aPtr[count] += detJ*w[n];
00825               }
00826            }
00827          }
00828       }
00829       else        /* ---------- NO ACI logic----------- */
00830       {
00831         double* aPtr = &((*A)[0]);
00832         int count = 0;
00833         for (int c=0; c<JVol.numCells(); c++)
00834         {
00835           int fc = 0;
00836           if (nFacetCases() != 1) fc = facetIndex[c];
00837 
00838           const Array<double>& w = W_[fc];
00839           double detJ = coeff * fabs(JVol.detJ()[c]);
00840           for (int n=0; n<nNodes(); n++, count++)
00841           {
00842             aPtr[count] += detJ*w[n];
00843           }
00844         }
00845       }
00846     addFlops(JVol.numCells() * (nNodes() + 1));
00847   }
00848   else
00849   {
00850     /* If the derivative order is nonzero, then we have to do a transformation. 
00851      * If we're also on a cell of dimension lower than maximal, we need to refer
00852      * to the facet index of the facet being integrated. */
00853     int nCells = JVol.numCells();
00854     double one = 1.0;
00855     int nTransRows = nRefDerivUnk()*nRefDerivTest();
00856 
00857     createTwoFormTransformationMatrix(JTrans, JVol);
00858       
00859     double* GPtr;
00860     if (testDerivOrder() == 0)
00861     {
00862       GPtr = &(G(beta())[0]);
00863       SUNDANCE_MSG2(transformVerb(),
00864         Tabs() << "transformation matrix=" << G(beta()));
00865     }
00866     else if (unkDerivOrder() == 0)
00867     {
00868       GPtr = &(G(alpha())[0]);
00869       SUNDANCE_MSG2(transformVerb(),
00870         Tabs() << "transformation matrix=" << G(alpha()));
00871     }
00872     else
00873     {
00874       GPtr = &(G(alpha(), beta())[0]);
00875       SUNDANCE_MSG2(transformVerb(),
00876         Tabs() << "transformation matrix=" 
00877         << G(alpha(),beta()));
00878     }
00879       
00880     int nNodes0 = nNodes();
00881 
00882     if (nFacetCases()==1)
00883     {
00884       /* if we're on a maximal cell, we can do transformations 
00885        * for all cells in a single batch. 
00886        */
00887       if (globalCurve().isCurveValid())
00888       {          /* ---------- ACI logic ----------- */
00889 
00890        Array<double> quadWeightsTmp = quadWeights_;
00891        Array<Point> quadPointsTmp = quadPts_;
00892        bool isCutByCurve = false;
00893 
00894          for (int c=0; c<JVol.numCells(); c++)
00895          {
00896              int fc = 0;
00897              if (nfc != 1) fc = facetIndex[c];
00898 
00899              double* aPtr = &((*A)[c*nNodes0]);
00900              double* gPtr = &(GPtr[c*nTransRows]);
00901              int oneI = 1;
00902            /* call the special integration routine */
00903           //SUNDANCE_MSG1(transformVerb(), tabs << "before quad_.getAdaptedWeights");
00904            quadWeightsTmp = quadWeights_;
00905              quadPointsTmp = quadPts_;
00906            quad_.getAdaptedWeights(cellType(), dim(), (*cellLIDs)[c], fc ,
00907              mesh(),globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00908           //SUNDANCE_MSG1(transformVerb(), tabs << "after quad_.getAdaptedWeights");
00909            if (isCutByCurve){
00910              Array<double> w;
00911              w.resize(nNodesUnk()*nNodesTest()*nRefDerivUnk()*nRefDerivTest());
00912              for ( int i = 0 ; i < w.size() ; i++) w[i] = 0.0;
00913              //recalculate the special weights
00914                for (int t=0; t<nRefDerivTest(); t++){
00915                   for (int nt=0; nt<nNodesTest(); nt++)
00916                     for (int u=0; u<nRefDerivUnk(); u++)
00917                       for (int nu=0; nu<nNodesUnk(); nu++)
00918                         for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00919                           // unkNode + nNodesUnk()*testNode  + nNodes()*(unkDerivDir + nRefDerivUnk()*testDerivDir)
00920                               w[nu + nNodesUnk()*nt  + nNodes()*(u + nRefDerivUnk()*t)] +=
00921                                   chop(quadWeightsTmp[q]*W_ACI_F2_[0][q][t][nt][u][nu]);
00922                }
00923       		      ::dgemm_("N", "N", &nNodes0, &oneI , &nTransRows, &coeff, &(w[0]),
00924                   &nNodes0, &(gPtr[0]), &nTransRows, &one,
00925                   &(aPtr[0]), &nNodes0);
00926             }else{
00927        		     ::dgemm_("N", "N", &nNodes0, &oneI , &nTransRows, &coeff, &(W_[0][0]),
00928                   &nNodes0, &(gPtr[0]), &nTransRows, &one,
00929                   &(aPtr[0]), &nNodes0);
00930             }
00931          } // end from the for loop over the cells
00932       }
00933       else /* ---------- NO ACI ----------- */
00934       {
00935         	 ::dgemm_("N", "N", &nNodes0, &nCells, &nTransRows, &coeff, &(W_[0][0]),
00936              &nNodes0, GPtr, &nTransRows, &one,
00937              &((*A)[0]), &nNodes0);
00938       }
00939     }
00940     else
00941     {
00942       /* If we're on a lower-dimensional cell and have to transform, 
00943        * we've got to do each transformation using a different facet case */
00944         if (globalCurve().isCurveValid())
00945         {   /* ---------- ACI logic ----------- */
00946             int oneI = 1;
00947             Array<double> quadWeightsTmp = quadWeights_;
00948             Array<Point> quadPointsTmp = quadPts_;
00949             bool isCutByCurve = false;
00950 
00951             for (int c=0; c<JVol.numCells(); c++)
00952             {
00953               int fc = 0;
00954               if (nfc != 1) fc = facetIndex[c];
00955               double* aPtr = &((*A)[c*nNodes0]);
00956               double* gPtr = &(GPtr[c*nTransRows]);
00957               SUNDANCE_MSG2(integrationVerb(),
00958                 tabs << "c=" << c << ", facet case=" << fc
00959                 << " W=" << W_[fc]);
00960 
00961               /* call the special integration routine */
00962               quadWeightsTmp = quadWeights_;
00963               quadPointsTmp = quadPts_;
00964               quad_.getAdaptedWeights(cellType(), dim(), (*cellLIDs)[c], fc ,
00965                   mesh(), globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00966               if (isCutByCurve){
00967                 Array<double> w;
00968                 w.resize(nNodesUnk()*nNodesTest()*nRefDerivUnk()*nRefDerivTest());
00969                 for ( int i = 0 ; i < w.size() ; i++) w[i] = 0.0;
00970                 //recalculate the special weights
00971                 for (int t=0; t<nRefDerivTest(); t++){
00972                   for (int nt=0; nt<nNodesTest(); nt++)
00973                     for (int u=0; u<nRefDerivUnk(); u++)
00974                       for (int nu=0; nu<nNodesUnk(); nu++)
00975                         for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00976                           // unkNode + nNodesUnk()*testNode  + nNodes()*(unkDerivDir + nRefDerivUnk()*testDerivDir)
00977                           w[nu + nNodesUnk()*nt  + nNodes()*(u + nRefDerivUnk()*t)] +=
00978                               chop( quadWeightsTmp[q]*W_ACI_F2_[fc][q][t][nt][u][nu] );
00979                 }
00980             	  ::dgemm_("N", "N", &nNodes0, &oneI , &nTransRows, &coeff, &(w[0]),
00981                     &nNodes0, &(gPtr[0]), &nTransRows, &one,
00982                     &(aPtr[0]), &nNodes0);
00983           }else{
00984 					  ::dgemm_("N", "N", &nNodes0, &oneI , &nTransRows, &coeff, &(W_[fc][0]),
00985                 &nNodes0, &(gPtr[0]), &nTransRows, &one,
00986                 &(aPtr[0]), &nNodes0);
00987           }
00988             }
00989         }
00990         else         /* ---------- NO ACI ----------- */
00991         {
00992             int N = 1;
00993             for (int c=0; c<JVol.numCells(); c++)
00994             {
00995               int fc = 0;
00996               if (nfc != 1) fc = facetIndex[c];
00997               double* aPtr = &((*A)[c*nNodes0]);
00998               double* gPtr = &(GPtr[c*nTransRows]);
00999               SUNDANCE_MSG2(integrationVerb(),
01000                 tabs << "c=" << c << ", facet case=" << fc
01001                 << " W=" << W_[fc]);
01002 
01003               ::dgemm_("N", "N", &nNodes0, &N, &nTransRows, &coeff, &(W_[fc][0]),
01004                   &nNodes0, gPtr, &nTransRows, &one,
01005                   aPtr, &nNodes0);
01006             }
01007         }
01008     }// from else of (nFacetCases()==1)
01009       
01010     addFlops(2 * nNodes0 * nCells * nTransRows);
01011   }
01012 }

Site Contact