SundanceCurveQuadratureIntegral.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 "SundanceCurveQuadratureIntegral.hpp"
00032 
00033 #include "SundanceCurveIntegralCalc.hpp"
00034 #include "SundanceGaussianQuadrature.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::endl;
00044 using std::setw;
00045 using std::setprecision;
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& maxCellQuadratureTimer() 
00059 {
00060   static RCP<Time> rtn
00061     = TimeMonitor::getNewTimer("max cell quadrature"); 
00062   return *rtn;
00063 }
00064 
00065 
00066 CurveQuadratureIntegral::CurveQuadratureIntegral(
00067   const CellType& cellType,
00068   const bool isConstantIntegral,
00069   const QuadratureFamily& quad,
00070   const ParametrizedCurve& globalCurve,
00071   const Mesh& mesh,
00072   int verb)
00073   : ElementIntegral(dimension(cellType), cellType, dimension(cellType),
00074     cellType, true, globalCurve, mesh, verb),
00075     quad_(quad),
00076     quadPts_(),
00077     quadWeights_(),
00078     W_(),
00079     useSumFirstMethod_(true),
00080     useConstCoeff_(isConstantIntegral)
00081 {
00082   Tabs tab0(0);
00083   
00084   TEUCHOS_TEST_FOR_EXCEPTION( cellType != mesh.cellType(mesh.spatialDim()) , std::runtime_error, " CurveQuadratureIntegral::CurveQuadratureIntegral , only on MAXcell!!");
00085 
00086   SUNDANCE_MSG1(setupVerb(), tab0 << "CurveQuadratureIntegral ctor for 0-form");
00087   if (setupVerb()) describe(Out::os());
00088   
00089   SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);  
00090 
00091   /* create the quad points and weights */
00092   quad.getPoints(mesh.cellType(mesh.spatialDim()-1), quadPts_, quadWeights_);
00093   int nQuad = quadPts_.size();
00094       
00095   W_.resize(nQuad);
00096   quadCurveDerivs_.resize(nQuad);
00097   quadCurveNormals_.resize(nQuad);
00098       
00099   for (int q=0; q<nQuad; q++)
00100   {
00101     W_[q] = quadWeights_[q];
00102   }
00103 }
00104 
00105 
00106 CurveQuadratureIntegral::CurveQuadratureIntegral(
00107   const CellType& cellType,
00108   const bool isConstantIntegral,
00109   const BasisFamily& testBasis,
00110   int alpha,
00111   int testDerivOrder,
00112   const QuadratureFamily& quad,
00113   const ParametrizedCurve& globalCurve,
00114   const Mesh& mesh,
00115   int verb)
00116   : ElementIntegral(dimension(cellType), cellType, dimension(cellType),
00117     cellType, testBasis,
00118     alpha, testDerivOrder, true, globalCurve, mesh, verb),
00119     quad_(quad),
00120     quadPts_(),
00121     quadWeights_(),
00122     W_(),
00123     useSumFirstMethod_(true),
00124     useConstCoeff_(isConstantIntegral)
00125 {
00126   Tabs tab0(0);
00127   
00128   TEUCHOS_TEST_FOR_EXCEPTION( cellType != mesh.cellType(mesh.spatialDim()) , std::runtime_error, " CurveQuadratureIntegral::CurveQuadratureIntegral , only on MAXcell!!");
00129 
00130   SUNDANCE_MSG1(setupVerb(), tab0 << "CurveQuadratureIntegral ctor for 1-form");
00131   if (setupVerb()) describe(Out::os());
00132   assertLinearForm();
00133 
00134   
00135   SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);  
00136   
00137   quad.getPoints(mesh.cellType(mesh.spatialDim()-1), quadPts_, quadWeights_);
00138   int nQuad = quadPts_.size();
00139       
00140   W_.resize(nQuad * nRefDerivTest() * nNodesTest());
00141   quadCurveDerivs_.resize(nQuad);
00142   quadCurveNormals_.resize(nQuad);
00143 
00144   SUNDANCE_MSG1(setupVerb(), tab0 << "num nodes for test function " << nNodesTest());
00145 }
00146 
00147 
00148 
00149 
00150 CurveQuadratureIntegral::CurveQuadratureIntegral(
00151   const CellType& cellType,
00152   const bool isConstantIntegral,
00153   const BasisFamily& testBasis,
00154   int alpha,
00155   int testDerivOrder,
00156   const BasisFamily& unkBasis,
00157   int beta,
00158   int unkDerivOrder,
00159   const QuadratureFamily& quad,
00160   const ParametrizedCurve& globalCurve,
00161   const Mesh& mesh,
00162   int verb)
00163   : ElementIntegral(dimension(cellType), cellType, dimension(cellType),
00164     cellType, testBasis,
00165     alpha, testDerivOrder, unkBasis, beta, unkDerivOrder, true,
00166     globalCurve, mesh, 
00167     verb),
00168     quad_(quad),
00169     quadPts_(),
00170     quadWeights_(),
00171     W_(),
00172     useSumFirstMethod_(true),
00173     useConstCoeff_(isConstantIntegral)
00174 {
00175   Tabs tab0(0);
00176 
00177   TEUCHOS_TEST_FOR_EXCEPTION( cellType != mesh.cellType(mesh.spatialDim()) , std::runtime_error, " CurveQuadratureIntegral::CurveQuadratureIntegral , only on MAXcell!!");
00178   
00179   SUNDANCE_MSG1(setupVerb(), tab0 << "CurveQuadratureIntegral ctor for 2-form");
00180   if (setupVerb()) describe(Out::os());
00181   assertBilinearForm();
00182 
00183   // store the quadrature points and weights  
00184   quad.getPoints(mesh.cellType(mesh.spatialDim()-1), quadPts_, quadWeights_);
00185   int nQuad = quadPts_.size();
00186 
00187   W_.resize(nQuad * nRefDerivTest() * nNodesTest()  
00188     * nRefDerivUnk() * nNodesUnk());
00189 
00190   quadCurveDerivs_.resize(nQuad);
00191   quadCurveNormals_.resize(nQuad);
00192 }
00193 
00194 
00195 
00196 void CurveQuadratureIntegral::updateRefCellInformation(int maxCellLID , const ParametrizedCurve& curve) const{
00197 
00198   //get the points on the reference cell, instead of "quadPts_" ,  and update "quadCurveDerivs_"
00199   Tabs tabs;
00200     SUNDANCE_MSG3(integrationVerb(), tabs << "CurveQuadratureIntegral::updateRefCellInformation, "
00201         "Update Cell LID: " << maxCellLID << "  curve.myID():" << curve.myID());
00202 
00203   if ( mesh().hasCurvePoints( maxCellLID , curve.myID() ))
00204   {
00205       SUNDANCE_MSG3(integrationVerb(), tabs << "CurveQuadratureIntegral::updateRefCellInformation, has Points, just returning them");
00206     mesh().getCurvePoints( maxCellLID , curve.myID() , quadPts_ , quadCurveDerivs_ , quadCurveNormals_ );
00207   }
00208   else // we have to calculate now the points
00209   {
00210     // calculate the intersection points
00211       SUNDANCE_MSG3(integrationVerb(), tabs << "CurveQuadratureIntegral::updateRefCellInformation, computing the intersection points");
00212     CurveIntegralCalc::getCurveQuadPoints( mesh().cellType(mesh().spatialDim()) , maxCellLID , mesh() , curve ,
00213         quad_ , quadPts_ , quadCurveDerivs_ , quadCurveNormals_ );
00214     // store the intersection point in the mesh
00215       SUNDANCE_MSG3(integrationVerb(), tabs << "CurveQuadratureIntegral::updateRefCellInformation, storing the intersection points in the mesh");
00216     mesh().setCurvePoints( maxCellLID , curve.myID() , quadPts_ , quadCurveDerivs_ , quadCurveNormals_ );
00217   }
00218 }
00219 
00220 
00221 void CurveQuadratureIntegral::updateRefCellIntegralOneForm(int maxCellLID , int cellInBatch) const {
00222 
00223     /* compute the test functions */
00224     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00225 
00226     Tabs tabs;
00227       SUNDANCE_MSG2(integrationVerb(), tabs << "CurveQuadratureIntegral::updateRefCellIntegralTwoForm, "
00228           "Update Cell LID: " << maxCellLID);
00229 
00230     // get the points on the reference cell, instead of "quadPts_" ,  and update "quadCurveDerivs_"
00231     updateRefCellInformation( maxCellLID , globalCurve() );
00232 
00233     for (int r=0; r<nRefDerivTest(); r++)
00234     {
00235       Tabs tab3;
00236       SUNDANCE_MSG1(setupVerb(), tab3
00237         << "evaluating basis functions for ref deriv direction " << r);
00238       MultiIndex mi;
00239       testBasisVals[r].resize(testBasis().dim());
00240       if (testDerivOrder()==1) mi[r] = 1;
00241       SpatialDerivSpecifier deriv(mi);
00242       testBasis().refEval(evalCellType(), quadPts_, deriv,
00243         testBasisVals[r], setupVerb());
00244     }
00245 
00246     int vecComp = 0;
00247     int nQuad = quadPts_.size();
00248     for (int q=0; q<nQuad; q++)
00249     {
00250       for (int t=0; t<nRefDerivTest(); t++)
00251       {
00252         for (int nt=0; nt<nNodesTest(); nt++)
00253         {
00254           wValue(q, t, nt)
00255             = chop(quadWeights_[q] * testBasisVals[t][vecComp][q][nt]) ;
00256         }
00257       }
00258     }
00259 
00260       // chop the numerical zero values
00261     for (int i=0; i<W_.size(); i++) W_[i] = chop(W_[i]);
00262 }
00263 
00264 
00265 void CurveQuadratureIntegral::updateRefCellIntegralTwoForm(int maxCellLID , int cellInBatch) const {
00266 
00267     /* compute the basis functions */
00268     Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00269     Array<Array<Array<Array<double> > > > unkBasisVals(nRefDerivUnk());
00270 
00271     Tabs tabs;
00272       SUNDANCE_MSG2(integrationVerb(), tabs << "CurveQuadratureIntegral::updateRefCellIntegralTwoForm, "
00273           "Update Cell LID: " << maxCellLID);
00274 
00275     // get the points on the reference cell, instead of "quadPts_" and update "quadCurveDerivs_"
00276     updateRefCellInformation( maxCellLID , globalCurve() );
00277 
00278     for (int r=0; r<nRefDerivTest(); r++)
00279     {
00280       testBasisVals[r].resize(testBasis().dim());
00281       MultiIndex mi;
00282       if (testDerivOrder()==1) mi[r] = 1;
00283       SpatialDerivSpecifier deriv(mi);
00284       SUNDANCE_MSG1(setupVerb(), tabs
00285         << "evaluating basis functions for ref deriv direction " << r);
00286       testBasis().refEval(evalCellType(), quadPts_, deriv,
00287         testBasisVals[r], setupVerb());
00288     }
00289 
00290     for (int r=0; r<nRefDerivUnk(); r++)
00291     {
00292       unkBasisVals[r].resize(unkBasis().dim());
00293       MultiIndex mi;
00294       if (unkDerivOrder()==1) mi[r] = 1;
00295       SpatialDerivSpecifier deriv(mi);
00296       SUNDANCE_MSG1(setupVerb(), tabs
00297         << "evaluating basis functions for ref deriv direction " << r);
00298       unkBasis().refEval(evalCellType(),
00299         quadPts_, deriv, unkBasisVals[r], setupVerb());
00300     }
00301 
00302 
00303     int vecComp = 0;
00304     int nQuad = quadPts_.size();
00305     /* form the products of basis functions at each quad pt */
00306     for (int q=0; q<nQuad; q++)
00307     {
00308       for (int t=0; t<nRefDerivTest(); t++)
00309       {
00310         for (int nt=0; nt<nNodesTest(); nt++)
00311         {
00312           for (int u=0; u<nRefDerivUnk(); u++)
00313           {
00314             for (int nu=0; nu<nNodesUnk(); nu++)
00315             {
00316               wValue(q, t, nt, u, nu)
00317                 = chop(quadWeights_[q] * testBasisVals[t][vecComp][q][nt]
00318                   * unkBasisVals[u][vecComp][q][nu]);
00319             }
00320           }
00321         }
00322       }
00323     }
00324 
00325       // chop the numerical zero values
00326     for (int i=0; i<W_.size(); i++) W_[i] = chop(W_[i]);
00327 }
00328 
00329 void CurveQuadratureIntegral
00330 ::transformZeroForm(const CellJacobianBatch& JTrans,  
00331   const CellJacobianBatch& JVol,
00332   const Array<int>& isLocalFlag,
00333   const Array<int>& facetIndex,
00334   const RCP<Array<int> >& cellLIDs,
00335   const double constCoeff,
00336   const double* const coeff,
00337   RCP<Array<double> >& A) const
00338 {
00339   TimeMonitor timer(maxCellQuadratureTimer());
00340   Tabs tabs;
00341   SUNDANCE_MSG1(integrationVerb(), tabs << "doing zero form by quadrature , isLocalFlag.size():" << isLocalFlag.size() );
00342 
00343   TEUCHOS_TEST_FOR_EXCEPTION(order() != 0, std::logic_error,
00344     "CurveQuadratureIntegral::transformZeroForm() called "
00345     "for form of order " << order());
00346 
00347   int nQuad = quadWeights_.size();
00348 
00349   // if we have constant coefficients then copy the constant value in the array
00350   double* coeffPtr = (double*) coeff;
00351   Array<double> constCoeff_arr( JVol.numCells() * nQuad);
00352   if (useConstCoeff_){
00353     for (int jk=0; jk < JVol.numCells() * nQuad ; jk++ ) { constCoeff_arr[jk] = constCoeff; };
00354     coeffPtr = &(constCoeff_arr[0]);
00355   }
00356 
00357   double& a = (*A)[0];
00358   SUNDANCE_MSG5(integrationVerb(), tabs << "input A=");
00359   if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00360   const Array<double>& w = W_;
00361   double curveDerivNorm = 0.0;
00362 
00363   if ( (int)isLocalFlag.size() == 0 )
00364   {
00365    for (int c=0; c<JVol.numCells(); c++)
00366    {
00367        // get the points on the reference cell, instead of "quadPts_" ,  and update "quadCurveDerivs_"
00368      updateRefCellInformation( (*cellLIDs)[c] , globalCurve() );
00369 
00370        // here we do not have to update W_ since it is only the weight of the quadrature points
00371      for (int q=0; q<nQuad; q++, coeffPtr++)
00372      {
00373         // no multiplication with the Jacobian!!!
00374         // multiply with the norm of the derivative of the curve (this should be stored in the mesh)
00375         curveDerivNorm = sqrt(quadCurveDerivs_[q]*quadCurveDerivs_[q]);
00376         a += w[q]*(*coeffPtr)*curveDerivNorm;
00377       }
00378     }
00379   }
00380   else
00381   {
00382   TEUCHOS_TEST_FOR_EXCEPTION( (int) isLocalFlag.size() != JVol.numCells(),
00383       std::runtime_error,
00384         "mismatch between isLocalFlag.size()="
00385         << isLocalFlag.size()
00386         << " and JVol.numCells()=" << JVol.numCells());
00387 
00388     for (int c=0; c<JVol.numCells(); c++)
00389     {
00390       // only if this cell is local on the processor
00391       if ( isLocalFlag[c] )
00392       {
00393         // get the points on the reference cell, instead of "quadPts_" ,  and update "quadCurveDerivs_"
00394         updateRefCellInformation( (*cellLIDs)[c] , globalCurve() );
00395 
00396         // here we pass the evaluated points(coeffPtr) for the interface (polygon or 3D surface), in case to set the values on the interface
00397         // in this place it should be only evaluated for functional, since isLocalFlag.size() > 0
00398         SUNDANCE_MSG1(integrationVerb(), " call .addEvaluationPointValues for cellLID: " << (*cellLIDs)[c] << " curveID:" << globalCurve().myID() );
00399         globalCurve().addEvaluationPointValues( mesh() , (*cellLIDs)[c] , nQuad , coeffPtr , quadPts_ );
00400       
00401         // here we do not have to update W_ since it is only the weight of the quadrature points
00402         for (int q=0; q<nQuad; q++, coeffPtr++)
00403         {
00404         // no multiplication with the Jacobian!!!
00405         // multiply with the norm of the derivative of the curve (this should be stored in the mesh)
00406         curveDerivNorm = sqrt(quadCurveDerivs_[q]*quadCurveDerivs_[q]);
00407           a += w[q]*(*coeffPtr)*curveDerivNorm;
00408         }
00409       }
00410       else {
00411        // increment the coeff vector, if this cell does not count
00412        coeffPtr += nQuad;
00413       }
00414     }
00415   }
00416 
00417   SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00418   if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00419 
00420   SUNDANCE_MSG1(integrationVerb(), tabs << "done zero form");
00421 }
00422 
00423 
00424 void CurveQuadratureIntegral::transformOneForm(const CellJacobianBatch& JTrans,
00425   const CellJacobianBatch& JVol,
00426   const Array<int>& facetIndex,
00427   const RCP<Array<int> >& cellLIDs,
00428   const double constCoeff,
00429   const double* const coeff,
00430   RCP<Array<double> >& A) const
00431 {
00432   TimeMonitor timer(maxCellQuadratureTimer());
00433   Tabs tabs;
00434   TEUCHOS_TEST_FOR_EXCEPTION(order() != 1, std::logic_error,
00435     "CurveQuadratureIntegral::transformOneForm() called for form "
00436     "of order " << order());
00437   SUNDANCE_MSG2(integrationVerb(), tabs << "doing one form by quadrature");
00438   int flops = 0;
00439 
00440   int nQuad = quadWeights_.size();
00441 
00442   /* If the derivative order is zero, the only thing to be done 
00443    * is to multiply by the cell's Jacobian determinant and sum over the
00444    * quad points */
00445   if (testDerivOrder() == 0)
00446   {
00447     double* aPtr = &((*A)[0]);
00448     SUNDANCE_MSG5(integrationVerb(), tabs << "input A = ");
00449     if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00450   
00451     int offset = 0 ;
00452     const Array<double>& w = W_;
00453     double* coeffPtr = (double*) coeff;
00454     double curveDerivNorm = 0.0 , f = 0.0;
00455     // if we have constant coefficient then copy the constant value into one array
00456     Array<double> constCoeff_arr( JVol.numCells() * nQuad);
00457     if (useConstCoeff_){
00458       for (int jk=0; jk < JVol.numCells() * nQuad ; jk++ ) { constCoeff_arr[jk] = constCoeff; };
00459       coeffPtr = &(constCoeff_arr[0]);
00460     }
00461 
00462     for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00463     {
00464       Tabs tab2;
00465         SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << JVol.detJ()[c] );
00466 
00467         // update W_
00468         updateRefCellIntegralOneForm( (*cellLIDs)[c] , c );
00469 
00470         for (int q=0; q<nQuad; q++, coeffPtr++)
00471         {
00472           Tabs tab3;
00473           // multiply with the norm of the derivative , (not with the determinant)
00474           curveDerivNorm = sqrt(quadCurveDerivs_[q]*quadCurveDerivs_[q]);
00475           f = (*coeffPtr) * curveDerivNorm;
00476           SUNDANCE_MSG4(integrationVerb(), tab3 << "q=" << q << " coeff=" <<
00477             *coeffPtr << " coeff*detJ=" << f);
00478           for (int n=0; n<nNodes(); n++)
00479           {
00480             Tabs tab4;
00481             SUNDANCE_MSG4(integrationVerb(), tab4 << "n=" << n << " w=" <<
00482               w[n + nNodes()*q]);
00483             aPtr[offset+n] += f*w[n + nNodes()*q];
00484           }
00485         }
00486 
00487         if (integrationVerb() >= 4)
00488         {
00489           Out::os() << tab2 << "integration results on cell:" << std::endl;
00490           Out::os() << tab2 << setw(10) << "n" << setw(12) << "I_n" << std::endl;
00491           for (int n=0; n<nNodes(); n++) 
00492           {
00493             Out::os() << tab2 << setw(10) << n 
00494                       << setw(12) << setprecision(6) << aPtr[offset+n] << std::endl;
00495           }
00496         }
00497         
00498     } // -- end cell iteration
00499 
00500     SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00501     if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00502   }
00503   else
00504   {
00505     /* If the derivative order is nonzero, then we have to do a transformation. */
00506     
00507     createOneFormTransformationMatrix(JTrans, JVol);
00508     
00509     SUNDANCE_MSG4(transformVerb(), 
00510       Tabs() << "transformation matrix=" << G(alpha()));
00511     
00512     double* GPtr = &(G(alpha())[0]);      
00513     
00514     transformSummingFirst(JVol.numCells(), JVol ,facetIndex, cellLIDs, constCoeff , GPtr, coeff, A);
00515 
00516   }
00517   addFlops(flops);
00518 }
00519 
00520 
00521 void CurveQuadratureIntegral::transformTwoForm(const CellJacobianBatch& JTrans,
00522   const CellJacobianBatch& JVol,
00523   const Array<int>& facetIndex,
00524   const RCP<Array<int> >& cellLIDs,
00525   const double constCoeff,
00526   const double* const coeff,
00527   RCP<Array<double> >& A) const
00528 {
00529   TimeMonitor timer(maxCellQuadratureTimer());
00530   Tabs tabs;
00531   TEUCHOS_TEST_FOR_EXCEPTION(order() != 2, std::logic_error,
00532     "CurveQuadratureIntegral::transformTwoForm() called for form "
00533     "of order " << order());
00534   SUNDANCE_MSG2(integrationVerb(), tabs << "doing one form by quadrature");
00535 
00536   int nQuad = quadWeights_.size();
00537 
00538   /* If the derivative orders are zero, the only thing to be done 
00539    * is to multiply by the cell's Jacobian determinant and sum over the
00540    * quad points */
00541   if (testDerivOrder() == 0 && unkDerivOrder() == 0)
00542   {
00543     double* aPtr = &((*A)[0]);
00544     int offset = 0 ;
00545     const Array<double>& w = W_;
00546     double* coeffPtr = (double*) coeff;
00547     double curveDerivNorm = 0.0 , f = 0.0;
00548 
00549     // if we have constant coefficient then copy the constant value into one array
00550     Array<double> constCoeff_arr( JVol.numCells() * nQuad);
00551     SUNDANCE_MSG2(integrationVerb(), tabs << "CurveQuadratureIntegral::transformTwoForm , use const variabl: " << useConstCoeff_ );
00552     if (useConstCoeff_){
00553       SUNDANCE_MSG2(integrationVerb(), tabs << "CurveQuadratureIntegral::transformTwoForm , "
00554           "Using constant coeff: " << constCoeff);
00555       for (int jk=0; jk < JVol.numCells() * nQuad ; jk++ ) { constCoeff_arr[jk] = constCoeff; };
00556       coeffPtr = &(constCoeff_arr[0]);
00557     }
00558 
00559     for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00560     {
00561         // ---- update W_ ---
00562         updateRefCellIntegralTwoForm( (*cellLIDs)[c] , c );
00563 
00564         for (int q=0; q<nQuad; q++, coeffPtr++)
00565         {
00566           // multiply with the norm of the derivative , (not with the determinant)
00567           curveDerivNorm = sqrt(quadCurveDerivs_[q]*quadCurveDerivs_[q]);
00568           f = (*coeffPtr)*curveDerivNorm;
00569           for (int n=0; n<nNodes(); n++)
00570           {
00571             aPtr[offset+n] += f*w[n + nNodes()*q];
00572           }
00573         }
00574     } // -- end cell iteration
00575 
00576   }
00577   else
00578   {
00579     createTwoFormTransformationMatrix(JTrans, JVol);
00580     double* GPtr;
00581 
00582     if (testDerivOrder() == 0)
00583     {
00584       GPtr = &(G(beta())[0]);
00585       SUNDANCE_MSG2(transformVerb(),
00586         Tabs() << "transformation matrix=" << G(beta()));
00587     }
00588     else if (unkDerivOrder() == 0)
00589     {
00590       GPtr = &(G(alpha())[0]);
00591       SUNDANCE_MSG2(transformVerb(),
00592         Tabs() << "transformation matrix=" << G(alpha()));
00593     }
00594     else
00595     {
00596       GPtr = &(G(alpha(), beta())[0]);
00597       SUNDANCE_MSG2(transformVerb(),
00598         Tabs() << "transformation matrix=" 
00599         << G(alpha(),beta()));
00600     }
00601         
00602     transformSummingFirst(JTrans.numCells(), JVol , facetIndex, cellLIDs, constCoeff , GPtr, coeff, A);
00603 
00604   }
00605 }
00606 
00607 void CurveQuadratureIntegral
00608 ::transformSummingFirst(int nCells,
00609   const CellJacobianBatch& JVol,
00610   const Array<int>& facetIndex,
00611   const RCP<Array<int> >& cellLIDs,
00612   const double constCoeff,
00613   const double* const GPtr,
00614   const double* const coeff,
00615   RCP<Array<double> >& A) const
00616 {
00617   double* aPtr = &((*A)[0]);
00618   int nQuad = quadWeights_.size();
00619   double* coeffPtr = (double*) coeff;
00620 
00621   // if we have constant coefficient then copy the constant value into one array
00622   Array<double> constCoeff_arr( JVol.numCells() * nQuad);
00623   if (useConstCoeff_){
00624     for (int jk=0; jk < JVol.numCells() * nQuad ; jk++ ) { constCoeff_arr[jk] = constCoeff; };
00625     coeffPtr = &(constCoeff_arr[0]);
00626   }
00627   
00628   int transSize = 0; 
00629   if (order()==2)
00630   {
00631     transSize = nRefDerivTest() * nRefDerivUnk();
00632   }
00633   else
00634   {
00635     transSize = nRefDerivTest();
00636   }
00637 
00638   /* The sum workspace is used to store the sum of untransformed quantities */
00639   static Array<double> sumWorkspace;
00640 
00641   int swSize = transSize * nNodes();
00642   sumWorkspace.resize(swSize);
00643   const Array<double>& w = W_;
00644   double curveDerivNorm = 0.0 , f = 0.0;
00645   
00646   /*
00647    * The number of operations for the sum-first method is 
00648    * 
00649    * Adds: (N_c * nNodes * transSize) * (N_q + 1) 
00650    * Multiplies: same as number of adds
00651    * Total: 2*(N_c * nNodes * transSize) * (N_q + 1) 
00652    */
00653 
00654     /* Sum */
00655     for (int c=0; c<nCells; c++)
00656     {
00657       /* sum untransformed basis combinations over quad points */
00658       for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00659       
00660       // ---- update W_ ----
00661       if (order() == 2) {
00662         updateRefCellIntegralTwoForm( (*cellLIDs)[c] , c );
00663       }
00664       if (order() == 1) {
00665         updateRefCellIntegralOneForm( (*cellLIDs)[c] , c );
00666       }
00667 
00668       for (int q=0; q<nQuad; q++, coeffPtr++)
00669       {
00670         // multiply with the norm of the derivative ,(not with the determinant)
00671         curveDerivNorm = sqrt(quadCurveDerivs_[q]*quadCurveDerivs_[q]);
00672         f = (*coeffPtr);
00673         for (int n=0; n<swSize; n++)
00674         {
00675           sumWorkspace[n] += f*w[n + q*swSize] * curveDerivNorm;
00676         }
00677       }
00678     
00679       /* transform the sum */
00680       const double * const gCell = &(GPtr[transSize*c]);
00681       double* aCell = aPtr + nNodes()*c;
00682       // since the trafo matrix is multiplied by the determinant, we have to multiply this by 1/det(J)
00683       double detJInv = 1/fabs(JVol.detJ()[c]);
00684       for (int i=0; i<nNodes(); i++)
00685       {
00686         for (int j=0; j<transSize; j++)
00687         {
00688           aCell[i] += sumWorkspace[nNodes()*j + i] * gCell[j] * detJInv;
00689         }
00690       }
00691     }
00692 }
00693 

Site Contact