SundanceMaximalQuadratureIntegral.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #include "SundanceMaximalQuadratureIntegral.hpp"
00043 #include "SundanceGaussianQuadrature.hpp"
00044 #include "SundanceSpatialDerivSpecifier.hpp"
00045 #include "SundanceOut.hpp"
00046 #include "PlayaTabs.hpp"
00047 #include "Teuchos_TimeMonitor.hpp"
00048 
00049 using namespace Sundance;
00050 using namespace Teuchos;
00051 
00052 using std::endl;
00053 using std::setw;
00054 using std::setprecision;
00055 
00056 extern "C" 
00057 {
00058 int dgemm_(const char* transA, const char* transB,
00059   const int* M, const int *N, const int* K,
00060   const double* alpha, 
00061   const double* A, const int* ldA,
00062   const double* B, const int* ldB,
00063   const double* beta,
00064   double* C, const int* ldC);
00065 }
00066 
00067 static Time& maxCellQuadrature0Timer() 
00068 {
00069   static RCP<Time> rtn
00070     = TimeMonitor::getNewTimer("max cell 0-form quadrature"); 
00071   return *rtn;
00072 }
00073 
00074 static Time& maxCellQuadrature1Timer() 
00075 {
00076   static RCP<Time> rtn
00077     = TimeMonitor::getNewTimer("max cell 1-form quadrature"); 
00078   return *rtn;
00079 }
00080 
00081 static Time& maxCellQuadrature2Timer() 
00082 {
00083   static RCP<Time> rtn
00084     = TimeMonitor::getNewTimer("max cell 2-form quadrature"); 
00085   return *rtn;
00086 }
00087 
00088 
00089 MaximalQuadratureIntegral::MaximalQuadratureIntegral(
00090   const CellType& cellType,
00091   const QuadratureFamily& quad,
00092   const ParametrizedCurve& globalCurve,
00093   const Mesh& mesh,
00094   int verb)
00095   : ElementIntegral(dimension(cellType), cellType, dimension(cellType),
00096     cellType, true, globalCurve, mesh, verb),
00097     quad_(quad),
00098     quadPts_(),
00099     quadWeights_(),
00100     W_(),
00101     useSumFirstMethod_(true)
00102 {
00103   Tabs tab0(0);
00104   
00105   SUNDANCE_MSG1(setupVerb(), tab0 << "MaximalQuadratureIntegral ctor for 0-form");
00106   if (setupVerb()) describe(Out::os());
00107   
00108   SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);  
00109 
00110   /* create the quad points and weights */
00111   quad.getPoints(cellType, quadPts_, quadWeights_);
00112   int nQuad = quadPts_.size();
00113       
00114   W_.resize(nQuad);
00115       
00116   for (int q=0; q<nQuad; q++)
00117   {
00118     W_[q] = quadWeights_[q];
00119   }
00120 }
00121 
00122 
00123 MaximalQuadratureIntegral::MaximalQuadratureIntegral(
00124   const CellType& cellType,
00125   const BasisFamily& testBasis,
00126   int alpha,
00127   int testDerivOrder,
00128   const QuadratureFamily& quad,
00129   const ParametrizedCurve& globalCurve,
00130   const Mesh& mesh,
00131   int verb)
00132   : ElementIntegral(dimension(cellType), cellType, dimension(cellType),
00133     cellType, testBasis,
00134     alpha, testDerivOrder, true, globalCurve, mesh, verb),
00135     quad_(quad),
00136     quadPts_(),
00137     quadWeights_(),
00138     W_(),
00139     useSumFirstMethod_(true)
00140 {
00141   Tabs tab0(0);
00142   
00143   SUNDANCE_MSG1(setupVerb(), tab0 << "MaximalQuadratureIntegral ctor for 1-form");
00144   if (setupVerb()) describe(Out::os());
00145   assertLinearForm();
00146 
00147   
00148   SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);  
00149   
00150   quad.getPoints(cellType, quadPts_, quadWeights_);
00151   int nQuad = quadPts_.size();
00152       
00153   W_.resize(nQuad * nRefDerivTest() * nNodesTest());
00154 
00155   SUNDANCE_MSG1(setupVerb(), tab0 << "num nodes for test function " << nNodesTest());
00156 
00157   Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00158 
00159   for (int r=0; r<nRefDerivTest(); r++)
00160   {
00161     Tabs tab3;
00162     SUNDANCE_MSG1(setupVerb(), tab3 
00163       << "evaluating basis functions for ref deriv direction " << r);
00164     MultiIndex mi;
00165     testBasisVals[r].resize(testBasis.dim());
00166     if (testDerivOrder==1) mi[r] = 1;
00167     SpatialDerivSpecifier deriv(mi);
00168     testBasis.refEval(evalCellType(), quadPts_, deriv, 
00169       testBasisVals[r], setupVerb());
00170   }
00171 
00172   int vecComp = 0;
00173   W_ACI_F1_.resize(nQuad);
00174   for (int q=0; q<nQuad; q++)
00175   {
00176     W_ACI_F1_[q].resize(nRefDerivTest());
00177     for (int t=0; t<nRefDerivTest(); t++)
00178     {
00179       W_ACI_F1_[q][t].resize(nNodesTest());
00180       for (int nt=0; nt<nNodesTest(); nt++)
00181       {
00182         wValue(q, t, nt) 
00183           = chop(quadWeights_[q] * testBasisVals[t][vecComp][q][nt]) ;
00184         W_ACI_F1_[q][t][nt] = chop(testBasisVals[t][vecComp][q][nt]);
00185       }
00186     }
00187   }
00188 
00189   addFlops(2*nQuad*nRefDerivTest()*nNodesTest());
00190 }
00191 
00192 
00193 
00194 
00195 MaximalQuadratureIntegral::MaximalQuadratureIntegral(
00196   const CellType& cellType,
00197   const BasisFamily& testBasis,
00198   int alpha,
00199   int testDerivOrder,
00200   const BasisFamily& unkBasis,
00201   int beta,
00202   int unkDerivOrder,
00203   const QuadratureFamily& quad,
00204   const ParametrizedCurve& globalCurve,
00205   const Mesh& mesh,
00206   int verb)
00207   : ElementIntegral(dimension(cellType), cellType, dimension(cellType),
00208     cellType, testBasis,
00209     alpha, testDerivOrder, unkBasis, beta, unkDerivOrder, true,
00210     globalCurve, mesh, 
00211     verb),
00212     quad_(quad),
00213     quadPts_(),
00214     quadWeights_(),
00215     W_(),
00216     useSumFirstMethod_(true)
00217 {
00218   Tabs tab0(0);
00219   
00220   SUNDANCE_MSG1(setupVerb(), tab0 << "MaximalQuadratureIntegral ctor for 2-form");
00221   if (setupVerb()) describe(Out::os());
00222   assertBilinearForm();
00223 
00224   // store the quadrature points and weights  
00225   quad.getPoints(cellType, quadPts_, quadWeights_);
00226   int nQuad = quadPts_.size();
00227 
00228   W_.resize(nQuad * nRefDerivTest() * nNodesTest()  
00229     * nRefDerivUnk() * nNodesUnk());
00230 
00231 
00232   /* compute the basis functions */
00233   Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00234   Array<Array<Array<Array<double> > > > unkBasisVals(nRefDerivUnk());
00235   
00236 
00237   for (int r=0; r<nRefDerivTest(); r++)
00238   {
00239     testBasisVals[r].resize(testBasis.dim());
00240     MultiIndex mi;
00241     if (testDerivOrder==1) mi[r] = 1;
00242     SpatialDerivSpecifier deriv(mi);
00243     testBasis.refEval(evalCellType(), quadPts_, deriv, 
00244       testBasisVals[r], setupVerb());
00245   }
00246   
00247   for (int r=0; r<nRefDerivUnk(); r++)
00248   {
00249     unkBasisVals[r].resize(unkBasis.dim());
00250     MultiIndex mi;
00251     if (unkDerivOrder==1) mi[r] = 1;
00252     SpatialDerivSpecifier deriv(mi);
00253     unkBasis.refEval(evalCellType(), 
00254       quadPts_, deriv, unkBasisVals[r], setupVerb());
00255   }
00256   
00257 
00258   int vecComp = 0;
00259   /* form the products of basis functions at each quad pt */
00260   W_ACI_F2_.resize(nQuad);
00261   for (int q=0; q<nQuad; q++)
00262   {
00263     W_ACI_F2_[q].resize(nRefDerivTest());
00264     for (int t=0; t<nRefDerivTest(); t++)
00265     {
00266       W_ACI_F2_[q][t].resize(nNodesTest());
00267       for (int nt=0; nt<nNodesTest(); nt++)
00268       {
00269         W_ACI_F2_[q][t][nt].resize(nRefDerivUnk());
00270         for (int u=0; u<nRefDerivUnk(); u++)
00271         {
00272           W_ACI_F2_[q][t][nt][u].resize(nNodesUnk());
00273           for (int nu=0; nu<nNodesUnk(); nu++)
00274           {
00275             wValue(q, t, nt, u, nu)
00276               = chop(quadWeights_[q] * testBasisVals[t][vecComp][q][nt] 
00277                 * unkBasisVals[u][vecComp][q][nu]);
00278             W_ACI_F2_[q][t][nt][u][nu] =
00279               chop(testBasisVals[t][vecComp][q][nt] * unkBasisVals[u][vecComp][q][nu]);
00280           }
00281         }
00282       }
00283     }
00284   }
00285 
00286   addFlops(3*nQuad*nRefDerivTest()*nNodesTest()*nRefDerivUnk()*nNodesUnk()
00287     + W_.size());
00288   for (int i=0; i<W_.size(); i++) W_[i] = chop(W_[i]);
00289 
00290 }
00291 
00292 
00293 void MaximalQuadratureIntegral
00294 ::transformZeroForm(const CellJacobianBatch& JTrans,  
00295   const CellJacobianBatch& JVol,
00296   const Array<int>& isLocalFlag,
00297   const Array<int>& facetIndex,
00298   const RCP<Array<int> >& cellLIDs,
00299   const double* const coeff,
00300   RCP<Array<double> >& A) const
00301 {
00302   TimeMonitor timer(maxCellQuadrature0Timer());
00303   Tabs tabs;
00304   SUNDANCE_MSG1(integrationVerb(), tabs << "doing zero form by quadrature");
00305 
00306   TEUCHOS_TEST_FOR_EXCEPTION(order() != 0, std::logic_error,
00307     "MaximalQuadratureIntegral::transformZeroForm() called "
00308     "for form of order " << order());
00309 
00310   TEUCHOS_TEST_FOR_EXCEPTION( (int) isLocalFlag.size() != 0 
00311     && (int) isLocalFlag.size() != JVol.numCells(),
00312     std::runtime_error,
00313     "mismatch between isLocalFlag.size()=" << isLocalFlag.size()
00314     << " and JVol.numCells()=" << JVol.numCells());
00315 
00316   bool checkLocalFlag = (int) isLocalFlag.size() != 0;
00317 
00318   const Array<int>* cellLID = cellLIDs.get();
00319   int nQuad = quadWeights_.size();
00320 
00321 
00322   double& a = (*A)[0];
00323   SUNDANCE_MSG5(integrationVerb(), tabs << "input A=");
00324   if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00325   double* coeffPtr = (double*) coeff;
00326   const Array<double>& w = W_;
00327 
00328   if (globalCurve().isCurveValid()) /* ---------- ACI ------------- */
00329   {
00330     Array<double> quadWeightsTmp = quadWeights_;
00331     Array<Point> quadPointsTmp = quadPts_;
00332     int fc = 0;
00333     bool isCutByCurve;
00334 
00335     for (int c=0; c<JVol.numCells(); c++)
00336     {
00337       if (checkLocalFlag && !isLocalFlag[c]) 
00338       {
00339         coeffPtr += nQuad;
00340         continue;
00341       }
00342       double detJ = fabs(JVol.detJ()[c]);
00343       
00344       quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc ,mesh(),
00345         globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00346       /* if we have special weights then do the same as before */
00347       if (isCutByCurve)
00348       {
00349         for (int q=0; q<nQuad; q++, coeffPtr++)
00350         {
00351           a += quadWeightsTmp[q]*(*coeffPtr)*detJ;
00352         }
00353       } // end cut by curve
00354       else
00355       {
00356         for (int q=0; q<nQuad; q++, coeffPtr++)
00357         {
00358           a += w[q]*(*coeffPtr)*detJ;
00359         }
00360       }
00361     }
00362   }
00363   else /* --------- No ACI ------------- */
00364   {
00365     for (int c=0; c<JVol.numCells(); c++)
00366     {
00367       if (checkLocalFlag && !isLocalFlag[c]) 
00368       {
00369         coeffPtr += nQuad;
00370         continue;
00371       }
00372       double detJ = fabs(JVol.detJ()[c]);
00373       
00374       for (int q=0; q<nQuad; q++, coeffPtr++)
00375       {
00376         a += w[q]*(*coeffPtr)*detJ;
00377       }
00378     }
00379   }
00380   SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00381   if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00382 
00383   SUNDANCE_MSG1(integrationVerb(), tabs << "done zero form");
00384 }
00385 
00386 
00387 void MaximalQuadratureIntegral::transformOneForm(const CellJacobianBatch& JTrans,  
00388   const CellJacobianBatch& JVol,
00389   const Array<int>& facetIndex,
00390   const RCP<Array<int> >& cellLIDs,
00391   const double* const coeff,
00392   RCP<Array<double> >& A) const
00393 {
00394   TimeMonitor timer(maxCellQuadrature1Timer());
00395   Tabs tabs;
00396   TEUCHOS_TEST_FOR_EXCEPTION(order() != 1, std::logic_error,
00397     "MaximalQuadratureIntegral::transformOneForm() called for form "
00398     "of order " << order());
00399   SUNDANCE_MSG2(integrationVerb(), tabs << "doing one form by quadrature");
00400   int flops = 0;
00401   const Array<int>* cellLID = cellLIDs.get();
00402 
00403   int nQuad = quadWeights_.size();
00404 
00405   /* If the derivative order is zero, the only thing to be done 
00406    * is to multiply by the cell's Jacobian determinant and sum over the
00407    * quad points */
00408   if (testDerivOrder() == 0)
00409   {
00410     double* aPtr = &((*A)[0]);
00411     SUNDANCE_MSG5(integrationVerb(), tabs << "input A = ");
00412     if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00413   
00414     double* coeffPtr = (double*) coeff;
00415     int offset = 0 ;
00416     const Array<double>& w = W_;
00417 
00418     if (globalCurve().isCurveValid()) /* ----- ACI logic ---- */
00419     {
00420       Array<double> quadWeightsTmp = quadWeights_;
00421       Array<Point> quadPointsTmp = quadPts_; 
00422       bool isCutByCurve;
00423 
00424       for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00425       {
00426         Tabs tab2;
00427         double detJ = fabs(JVol.detJ()[c]);
00428         int fc = 0;
00429 
00430         SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << detJ);
00431         
00432         /* call the special integration routine */
00433         quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00434           mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00435         if (isCutByCurve)
00436         {
00437           Array<double> wi;
00438           wi.resize(nQuad * nNodes()); //recalculate the special weights
00439           for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00440           for (int n = 0 ; n < nNodes() ; n++)
00441           {
00442             for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00443             {
00444               //Indexing: testNode + nNodesTest()*(testDerivDir + nRefDerivTest()*q)
00445               wi[n + nNodes()*q] +=
00446                 chop(quadWeightsTmp[q] * W_ACI_F1_[q][0][n]);
00447             }
00448           }
00449           // if it is cut by curve then use this vector
00450           for (int q=0; q<nQuad; q++, coeffPtr++)
00451           {
00452             double f = (*coeffPtr)*detJ;
00453             for (int n=0; n<nNodes(); n++)
00454             {
00455               aPtr[offset+n] += f*wi[n + nNodes()*q];
00456             }
00457           }
00458         } // end isCutByCurve
00459         else 
00460         {
00461           for (int q=0; q<nQuad; q++, coeffPtr++)
00462           {
00463             double f = (*coeffPtr)*detJ;
00464             for (int n=0; n<nNodes(); n++)
00465             {
00466               aPtr[offset+n] += f*w[n + nNodes()*q];
00467             }
00468           }
00469         }
00470 
00471         if (integrationVerb() >= 4)
00472         {
00473           Out::os() << tab2 << "integration results on cell:" << std::endl;
00474           Out::os() << tab2 << setw(10) << "n" << setw(12) << "I_n" << std::endl;
00475           for (int n=0; n<nNodes(); n++) 
00476           {
00477             Out::os() << tab2 << setw(10) << n 
00478                       << setw(12) << setprecision(6) << aPtr[offset+n] << std::endl;
00479           }
00480         }
00481       }
00482     } 
00483     else /* -------- No ACI -------- */ 
00484     {
00485       for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00486       {
00487         Tabs tab2;
00488         double detJ = fabs(JVol.detJ()[c]);
00489         SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << detJ);
00490 
00491         for (int q=0; q<nQuad; q++, coeffPtr++)
00492         {
00493           Tabs tab3;
00494           double f = (*coeffPtr)*detJ;
00495           SUNDANCE_MSG4(integrationVerb(), tab3 << "q=" << q << " coeff=" <<
00496             *coeffPtr << " coeff*detJ=" << f);
00497           for (int n=0; n<nNodes(); n++)
00498           {
00499             Tabs tab4;
00500             SUNDANCE_MSG4(integrationVerb(), tab4 << "n=" << n << " w=" <<
00501               w[n + nNodes()*q]);
00502             aPtr[offset+n] += f*w[n + nNodes()*q];
00503           }
00504         }
00505 
00506         if (integrationVerb() >= 4)
00507         {
00508           Out::os() << tab2 << "integration results on cell:" << std::endl;
00509           Out::os() << tab2 << setw(10) << "n" << setw(12) << "I_n" << std::endl;
00510           for (int n=0; n<nNodes(); n++) 
00511           {
00512             Out::os() << tab2 << setw(10) << n 
00513                       << setw(12) << setprecision(6) << aPtr[offset+n] << std::endl;
00514           }
00515         }
00516         
00517       }
00518     }
00519 
00520     SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00521     if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00522   }
00523   else
00524   {
00525     /* If the derivative order is nonzero, then we have to do a transformation. */
00526     
00527     createOneFormTransformationMatrix(JTrans, JVol);
00528     
00529     SUNDANCE_MSG4(transformVerb(), 
00530       Tabs() << "transformation matrix=" << G(alpha()));
00531     
00532     double* GPtr = &(G(alpha())[0]);      
00533     
00534     transformSummingFirst(JVol.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00535   }
00536   addFlops(flops);
00537 }
00538 
00539 
00540 void MaximalQuadratureIntegral::transformTwoForm(const CellJacobianBatch& JTrans,
00541   const CellJacobianBatch& JVol,
00542   const Array<int>& facetIndex,
00543   const RCP<Array<int> >& cellLIDs,
00544   const double* const coeff,
00545   RCP<Array<double> >& A) const
00546 {
00547   TimeMonitor timer(maxCellQuadrature2Timer());
00548   Tabs tabs;
00549   TEUCHOS_TEST_FOR_EXCEPTION(order() != 2, std::logic_error,
00550     "MaximalQuadratureIntegral::transformTwoForm() called for form "
00551     "of order " << order());
00552   SUNDANCE_MSG2(integrationVerb(), tabs << "doing one form by quadrature");
00553 
00554   int nQuad = quadWeights_.size();
00555   const Array<int>* cellLID = cellLIDs.get();
00556 
00557 
00558   /* If the derivative orders are zero, the only thing to be done 
00559    * is to multiply by the cell's Jacobian determinant and sum over the
00560    * quad points */
00561   if (testDerivOrder() == 0 && unkDerivOrder() == 0)
00562   {
00563     double* aPtr = &((*A)[0]);
00564     double* coeffPtr = (double*) coeff;
00565     int offset = 0 ;
00566     const Array<double>& w = W_;
00567     if (globalCurve().isCurveValid())
00568     {
00569       int fc = 0;
00570       Array<double> quadWeightsTmp = quadWeights_;
00571       Array<Point> quadPointsTmp = quadPts_;
00572       bool isCutByCurve;
00573 
00574       for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00575       {
00576         double detJ = fabs(JVol.detJ()[c]);
00577         quadWeightsTmp = quadWeights_;
00578         quadPointsTmp = quadPts_;
00579         /* call the special integration routine */
00580         quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00581           mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00582         if (isCutByCurve)
00583         {
00584           Array<double> wi;
00585           wi.resize(nQuad * nNodesTest() *nNodesUnk() ); //recalculate the special weights
00586           for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00587           /* Good coding practice: always use braces { } when nesting loops even if
00588            * there's only one line. Otherwise, if someone inserts a new line 
00589            * (e.g., a print statement) it can totally change the code logic */
00590           for (int nt = 0 ; nt < nNodesTest() ; nt++)
00591           {
00592             for (int nu=0; nu<nNodesUnk(); nu++)
00593             { 
00594               for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00595               {
00596                 //Indexing: unkNode + nNodesUnk()*(testNode + nNodesTest()*(unkDerivDir + nRefDerivUnk()*(testDerivDir + nRefDerivTest()*q)))
00597                 wi[nu + nNodesUnk()*(nt + nNodesTest()*q)] +=
00598                   chop(quadWeightsTmp[q] * W_ACI_F2_[q][0][nt][0][nu]);
00599               }
00600             }
00601           }
00602           for (int q=0; q<nQuad; q++, coeffPtr++)
00603           {
00604             double f = (*coeffPtr)*detJ;
00605             for (int n=0; n<nNodes(); n++)
00606             {
00607               aPtr[offset+n] += f*wi[n + nNodes()*q];
00608             }
00609           }
00610         }// end isCutByCurve
00611         else
00612         {
00613           for (int q=0; q<nQuad; q++, coeffPtr++)
00614           {
00615             double f = (*coeffPtr)*detJ;
00616             for (int n=0; n<nNodes(); n++)
00617             {
00618               aPtr[offset+n] += f*w[n + nNodes()*q];
00619             }
00620           }
00621         }
00622       }
00623     }
00624     else  // No ACI
00625     {
00626       for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00627       {
00628         double detJ = fabs(JVol.detJ()[c]);
00629         for (int q=0; q<nQuad; q++, coeffPtr++)
00630         {
00631           double f = (*coeffPtr)*detJ;
00632           for (int n=0; n<nNodes(); n++)
00633           {
00634             aPtr[offset+n] += f*w[n + nNodes()*q];
00635           }
00636         }
00637       }
00638     }
00639 
00640     addFlops( JVol.numCells() * (1 + nQuad * (1 + 2*nNodes())) );
00641   }
00642   else
00643   {
00644     createTwoFormTransformationMatrix(JTrans, JVol);
00645     double* GPtr;
00646 
00647     if (testDerivOrder() == 0)
00648     {
00649       GPtr = &(G(beta())[0]);
00650       SUNDANCE_MSG2(transformVerb(),
00651         Tabs() << "transformation matrix=" << G(beta()));
00652     }
00653     else if (unkDerivOrder() == 0)
00654     {
00655       GPtr = &(G(alpha())[0]);
00656       SUNDANCE_MSG2(transformVerb(),
00657         Tabs() << "transformation matrix=" << G(alpha()));
00658     }
00659     else
00660     {
00661       GPtr = &(G(alpha(), beta())[0]);
00662       SUNDANCE_MSG2(transformVerb(),
00663         Tabs() << "transformation matrix=" 
00664         << G(alpha(),beta()));
00665     }
00666         
00667       
00668     transformSummingFirst(JTrans.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00669   }
00670 }
00671 
00672 void MaximalQuadratureIntegral
00673 ::transformSummingFirst(int nCells,
00674   const Array<int>& facetIndex,
00675   const RCP<Array<int> >& cellLIDs,
00676   const double* const GPtr,
00677   const double* const coeff,
00678   RCP<Array<double> >& A) const
00679 {
00680   double* aPtr = &((*A)[0]);
00681   double* coeffPtr = (double*) coeff;
00682   const Array<int>* cellLID = cellLIDs.get();
00683   int nQuad = quadWeights_.size();
00684   
00685   int transSize = 0; 
00686   if (order()==2)
00687   {
00688     transSize = nRefDerivTest() * nRefDerivUnk();
00689   }
00690   else
00691   {
00692     transSize = nRefDerivTest();
00693   }
00694 
00695   /* The sum workspace is used to store the sum of untransformed quantities */
00696   static Array<double> sumWorkspace;
00697 
00698   int swSize = transSize * nNodes();
00699   sumWorkspace.resize(swSize);
00700   const Array<double>& w = W_;  
00701   
00702   /*
00703    * The number of operations for the sum-first method is 
00704    * 
00705    * Adds: (N_c * nNodes * transSize) * (N_q + 1) 
00706    * Multiplies: same as number of adds
00707    * Total: 2*(N_c * nNodes * transSize) * (N_q + 1) 
00708    */
00709   if (globalCurve().isCurveValid()) /* -------- ACI --------- */
00710   {
00711     Array<double> quadWeightsTmp = quadWeights_;
00712     Array<Point> quadPointsTmp = quadPts_;
00713     bool isCutByCurve;
00714 
00715     for (int c=0; c<nCells; c++)
00716     {
00717       /* sum untransformed basis combinations over quad points */
00718       for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00719       int fc = 0;
00720 
00721       /* call the special integration routine */
00722       quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00723         mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00724       if (isCutByCurve)
00725       {
00726         Array<double> wi;
00727         if (order()==1)
00728         { // one form integral
00729           wi.resize(nQuad * nRefDerivTest() * nNodesTest()); //recalculate the special weights
00730           for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00731 
00732           for (int n = 0 ; n < nNodes() ; n++)
00733           {
00734             for (int t=0; t<nRefDerivTest(); t++)
00735             {
00736               for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00737               {
00738                 //Indexing: testNode + nNodesTest()*(testDerivDir + nRefDerivTest()*q)
00739                 wi[n + nNodes()*(t + nRefDerivTest()*q)] +=
00740                   chop(quadWeightsTmp[q] * W_ACI_F1_[q][t][n]);
00741               }
00742             }
00743           }
00744         }
00745         else
00746         { // two from integrals
00747           wi.resize(nQuad * nRefDerivTest() * nNodesTest()
00748             * nRefDerivUnk() * nNodesUnk() ); //recalculate the special weights
00749           for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00750 
00751           for (int t=0; t<nRefDerivTest(); t++)
00752           {
00753             for (int nt = 0 ; nt < nNodesTest() ; nt++)
00754             {
00755               for (int u=0; u<nRefDerivUnk(); u++)
00756               {
00757                 for (int nu=0; nu<nNodesUnk(); nu++)
00758                 {
00759                   for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00760                   {
00761                     //Indexing: unkNode + nNodesUnk()*(testNode + nNodesTest()*
00762                     //(unkDerivDir + nRefDerivUnk()*(testDerivDir + nRefDerivTest()*q)))
00763                     wi[nu + nNodesUnk()*(nt + nNodesTest()*(u + nRefDerivUnk()*(t + nRefDerivTest()*q)))] +=
00764                       chop(quadWeightsTmp[q] * W_ACI_F2_[q][t][nt][u][nu]);
00765                   }
00766                 }
00767               }
00768             }
00769           }
00770         }// end two form integral
00771         
00772         for (int q=0; q<nQuad; q++, coeffPtr++)
00773         {
00774           double f = (*coeffPtr);
00775           for (int n=0; n<swSize; n++)
00776           {
00777             sumWorkspace[n] += f*wi[n + q*swSize];
00778           }
00779         }
00780         
00781       }
00782       else /* Cell not cut by curve */
00783       {
00784         for (int q=0; q<nQuad; q++, coeffPtr++)
00785         {
00786           double f = (*coeffPtr);
00787           for (int n=0; n<swSize; n++)
00788           {
00789             sumWorkspace[n] += f*w[n + q*swSize];
00790           }
00791         }
00792       }
00793     
00794       /* transform the sum for this cell */
00795       const double * const gCell = &(GPtr[transSize*c]);
00796       double* aCell = aPtr + nNodes()*c;
00797       for (int i=0; i<nNodes(); i++)
00798       {
00799         for (int j=0; j<transSize; j++)
00800         {
00801           aCell[i] += sumWorkspace[nNodes()*j + i] * gCell[j];
00802         }
00803       }
00804     }
00805   }
00806   else /* no ACI */
00807   {
00808     /* Sum */
00809     for (int c=0; c<nCells; c++)
00810     {
00811       /* sum untransformed basis combinations over quad points */
00812       for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00813       
00814       for (int q=0; q<nQuad; q++, coeffPtr++)
00815       {
00816         double f = (*coeffPtr);
00817         for (int n=0; n<swSize; n++)
00818         {
00819           sumWorkspace[n] += f*w[n + q*swSize];
00820         }
00821       }
00822     
00823       /* transform the sum */
00824       const double * const gCell = &(GPtr[transSize*c]);
00825       double* aCell = aPtr + nNodes()*c;
00826       for (int i=0; i<nNodes(); i++)
00827       {
00828         for (int j=0; j<transSize; j++)
00829         {
00830           aCell[i] += sumWorkspace[nNodes()*j + i] * gCell[j];
00831         }
00832       }
00833     }
00834   }
00835 }
00836 

Site Contact