Intrepid
/usr/src/RPM/BUILD/trilinos10-10.6.4/packages/intrepid/example/Drivers/example_08.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ************************************************************************
00003 //
00004 //                           Intrepid Package
00005 //                 Copyright (2007) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Pavel Bochev  (pbboche@sandia.gov),
00025 //                    Denis Ridzal  (dridzal@sandia.gov),
00026 //                    Kara Peterson (kjpeter@sandia.gov).
00027 //
00028 // ************************************************************************
00029 // @HEADER
00030 
00068 // Intrepid includes
00069 #include "Intrepid_FunctionSpaceTools.hpp"
00070 #include "Intrepid_FieldContainer.hpp"
00071 #include "Intrepid_CellTools.hpp"
00072 #include "Intrepid_ArrayTools.hpp"
00073 #include "Intrepid_HGRAD_QUAD_Cn_FEM.hpp"
00074 #include "Intrepid_RealSpaceTools.hpp"
00075 #include "Intrepid_DefaultCubatureFactory.hpp"
00076 #include "Intrepid_Utils.hpp"
00077 
00078 // Epetra includes
00079 #include "Epetra_Time.h"
00080 #include "Epetra_Map.h"
00081 #include "Epetra_FECrsMatrix.h"
00082 #include "Epetra_FEVector.h"
00083 #include "Epetra_SerialComm.h"
00084 
00085 // Teuchos includes
00086 #include "Teuchos_oblackholestream.hpp"
00087 #include "Teuchos_RCP.hpp"
00088 #include "Teuchos_BLAS.hpp"
00089 
00090 // Shards includes
00091 #include "Shards_CellTopology.hpp"
00092 
00093 // EpetraExt includes
00094 #include "EpetraExt_RowMatrixOut.h"
00095 #include "EpetraExt_MultiVectorOut.h"
00096 
00097 using namespace std;
00098 using namespace Intrepid;
00099 
00100 // Functions to evaluate exact solution and derivatives
00101 double evalu(double & x, double & y, double & z);
00102 int evalGradu(double & x, double & y, double & z, double & gradu1, double & gradu2, double & gradu3);
00103 double evalDivGradu(double & x, double & y, double & z);
00104 
00105 int main(int argc, char *argv[]) {
00106 
00107   //Check number of arguments
00108    if (argc < 4) {
00109       std::cout <<"\n>>> ERROR: Invalid number of arguments.\n\n";
00110       std::cout <<"Usage:\n\n";
00111       std::cout <<"  ./Intrepid_example_Drivers_Example_05.exe deg NX NY verbose\n\n";
00112       std::cout <<" where \n";
00113       std::cout <<"   int deg             - polynomial degree to be used (assumed > 1) \n";
00114       std::cout <<"   int NX              - num intervals in x direction (assumed box domain, 0,1) \n";
00115       std::cout <<"   int NY              - num intervals in y direction (assumed box domain, 0,1) \n";
00116       std::cout <<"   verbose (optional)  - any character, indicates verbose output \n\n";
00117       exit(1);
00118    }
00119   
00120   // This little trick lets us print to std::cout only if
00121   // a (dummy) command-line argument is provided.
00122   int iprint     = argc - 1;
00123   Teuchos::RCP<std::ostream> outStream;
00124   Teuchos::oblackholestream bhs; // outputs nothing
00125   if (iprint > 2)
00126     outStream = Teuchos::rcp(&std::cout, false);
00127   else
00128     outStream = Teuchos::rcp(&bhs, false);
00129   
00130   // Save the format state of the original std::cout.
00131   Teuchos::oblackholestream oldFormatState;
00132   oldFormatState.copyfmt(std::cout);
00133   
00134   *outStream \
00135     << "===============================================================================\n" \
00136     << "|                                                                             |\n" \
00137     << "|  Example: Generate Stiffness Matrix and Right Hand Side Vector for          |\n" \
00138     << "|                   Poisson Equation on Quadrilateral Mesh                    |\n" \
00139     << "|                                                                             |\n" \
00140     << "|  Questions? Contact  Pavel Bochev  (pbboche@sandia.gov),                    |\n" \
00141     << "|                      Denis Ridzal  (dridzal@sandia.gov),                    |\n" \
00142     << "|                      Kara Peterson (kjpeter@sandia.gov).                    |\n" \
00143     << "|                                                                             |\n" \
00144     << "|  Intrepid's website: http://trilinos.sandia.gov/packages/intrepid           |\n" \
00145     << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
00146     << "|                                                                             |\n" \
00147     << "===============================================================================\n";
00148 
00149   
00150   // ************************************ GET INPUTS **************************************
00151   
00152   int deg          = atoi(argv[1]);  // polynomial degree to use
00153   int NX            = atoi(argv[2]);  // num intervals in x direction (assumed box domain, 0,1)
00154   int NY            = atoi(argv[3]);  // num intervals in y direction (assumed box domain, 0,1)
00155   
00156 
00157   // *********************************** CELL TOPOLOGY **********************************
00158   
00159   // Get cell topology for base hexahedron
00160   typedef shards::CellTopology    CellTopology;
00161   CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
00162   
00163   // Get dimensions 
00164   int numNodesPerElem = quad_4.getNodeCount();
00165   int spaceDim = quad_4.getDimension();
00166   
00167   // *********************************** GENERATE MESH ************************************
00168   
00169   *outStream << "Generating mesh ... \n\n";
00170   
00171   *outStream << "   NX" << "   NY\n";
00172   *outStream << std::setw(5) << NX <<
00173     std::setw(5) << NY << "\n\n";
00174   
00175   // Print mesh information
00176   int numElems = NX*NY;
00177   int numNodes = (NX+1)*(NY+1);
00178   *outStream << " Number of Elements: " << numElems << " \n";
00179   *outStream << "    Number of Nodes: " << numNodes << " \n\n";
00180   
00181   // Square
00182   double leftX = 0.0, rightX = 1.0;
00183   double leftY = 0.0, rightY = 1.0;
00184 
00185   // Mesh spacing
00186   double hx = (rightX-leftX)/((double)NX);
00187   double hy = (rightY-leftY)/((double)NY);
00188 
00189   // Get nodal coordinates
00190   FieldContainer<double> nodeCoord(numNodes, spaceDim);
00191   FieldContainer<int> nodeOnBoundary(numNodes);
00192   int inode = 0;
00193   for (int j=0; j<NY+1; j++) {
00194     for (int i=0; i<NX+1; i++) {
00195       nodeCoord(inode,0) = leftX + (double)i*hx;
00196       nodeCoord(inode,1) = leftY + (double)j*hy;
00197       if (j==0 || i==0 || j==NY || i==NX){
00198         nodeOnBoundary(inode)=1;
00199       }
00200       else {
00201         nodeOnBoundary(inode)=0;
00202       }
00203       inode++;
00204     }
00205   }
00206 #define DUMP_DATA
00207 #ifdef DUMP_DATA
00208   // Print nodal coords
00209   ofstream fcoordout("coords.dat");
00210   for (int i=0; i<numNodes; i++) {
00211     fcoordout << nodeCoord(i,0) <<" ";
00212     fcoordout << nodeCoord(i,1) <<"\n";
00213   }
00214   fcoordout.close();
00215 #endif
00216   
00217   
00218   // Element to Node map
00219   // We'll keep it around, but this is only the DOFMap if you are in the lowest order case.
00220   FieldContainer<int> elemToNode(numElems, numNodesPerElem);
00221   int ielem = 0;
00222   for (int j=0; j<NY; j++) {
00223     for (int i=0; i<NX; i++) {
00224       elemToNode(ielem,0) = (NX + 1)*j + i;
00225       elemToNode(ielem,1) = (NX + 1)*j + i + 1;
00226       elemToNode(ielem,2) = (NX + 1)*(j + 1) + i + 1;
00227       elemToNode(ielem,3) = (NX + 1)*(j + 1) + i;
00228       ielem++;
00229     }
00230   }
00231 #ifdef DUMP_DATA
00232   // Output connectivity
00233   ofstream fe2nout("elem2node.dat");
00234   for (int j=0; j<NY; j++) {
00235     for (int i=0; i<NX; i++) {
00236       int ielem = i + j * NX;
00237       for (int m=0; m<numNodesPerElem; m++){
00238         fe2nout << elemToNode(ielem,m) <<"  ";
00239       }
00240       fe2nout <<"\n";
00241     }
00242   }
00243   fe2nout.close();
00244 #endif
00245   
00246 
00247   // ************************************ CUBATURE ************************************** 
00248   *outStream << "Getting cubature ... \n\n";
00249   
00250   // Get numerical integration points and weights
00251   DefaultCubatureFactory<double>  cubFactory;                                   
00252   int cubDegree = 2*deg;
00253   Teuchos::RCP<Cubature<double> > quadCub = cubFactory.create(quad_4, cubDegree); 
00254   
00255   int cubDim       = quadCub->getDimension();
00256   int numCubPoints = quadCub->getNumPoints();
00257   
00258   FieldContainer<double> cubPoints(numCubPoints, cubDim);
00259   FieldContainer<double> cubWeights(numCubPoints);
00260   
00261   quadCub->getCubature(cubPoints, cubWeights);
00262   
00263 
00264   // ************************************** BASIS ***************************************
00265   
00266   *outStream << "Getting basis ... \n\n";
00267   
00268   // Define basis 
00269   Basis_HGRAD_QUAD_Cn_FEM<double, FieldContainer<double> > quadHGradBasis(deg,POINTTYPE_SPECTRAL);
00270   int numFieldsG = quadHGradBasis.getCardinality();
00271   FieldContainer<double> quadGVals(numFieldsG, numCubPoints); 
00272   FieldContainer<double> quadGrads(numFieldsG, numCubPoints, spaceDim); 
00273   
00274   // Evaluate basis values and gradients at cubature points
00275   quadHGradBasis.getValues(quadGVals, cubPoints, OPERATOR_VALUE);
00276   quadHGradBasis.getValues(quadGrads, cubPoints, OPERATOR_GRAD);
00277 
00278   // create the local-global mapping for higher order elements
00279   FieldContainer<int> ltgMapping(numElems,numFieldsG);
00280   const int numDOF = (NX*deg+1)*(NY*deg+1);
00281   ielem=0;
00282   for (int j=0;j<NY;j++) {
00283     for (int i=0;i<NX;i++) {
00284       const int start = deg * j * ( NX * deg + 1 ) + i * deg;
00285       // loop over local dof on this cell
00286       int local_dof_cur=0;
00287       for (int vertical=0;vertical<=deg;vertical++) {
00288         for (int horizontal=0;horizontal<=deg;horizontal++) {
00289           ltgMapping(ielem,local_dof_cur) = start + vertical*(NX*deg+1)+horizontal;
00290           local_dof_cur++;
00291         }
00292       }
00293       ielem++;
00294     }
00295   }
00296 #ifdef DUMP_DATA
00297   // Output ltg mapping
00298   ofstream ltgout("ltg.dat");
00299   for (int j=0; j<NY; j++) {
00300     for (int i=0; i<NX; i++) {
00301       int ielem = i + j * NX;
00302       for (int m=0; m<numFieldsG; m++){
00303         ltgout << ltgMapping(ielem,m) <<"  ";
00304       }
00305       ltgout <<"\n";
00306     }
00307   }
00308   ltgout.close();
00309 #endif
00310   
00311   // ******** CREATE ALL LOCAL STIFFNESS MATRICES *********
00312   *outStream << "Building stiffness matrix and right hand side ... \n\n";
00313 
00314   // Settings and data structures for mass and stiffness matrices
00315   typedef CellTools<double>  CellTools;
00316   typedef FunctionSpaceTools fst;
00317   int numCells = numElems; 
00318 
00319   // Container for nodes
00320   FieldContainer<double> cellVertices(numCells,numNodesPerElem,spaceDim);
00321 
00322   // Containers for Jacobian
00323   FieldContainer<double> cellJacobian(numCells, numCubPoints, spaceDim, spaceDim);
00324   FieldContainer<double> cellJacobInv(numCells, numCubPoints, spaceDim, spaceDim);
00325   FieldContainer<double> cellJacobDet(numCells, numCubPoints);
00326 
00327   // Containers for element HGRAD stiffness matrices
00328   FieldContainer<double> localStiffMatrices(numCells, numFieldsG, numFieldsG);
00329   FieldContainer<double> transformedBasisGradients(numCells,numFieldsG,numCubPoints,spaceDim);
00330   FieldContainer<double> weightedTransformedBasisGradients(numCells,numFieldsG,numCubPoints,spaceDim);
00331   FieldContainer<double> weightedMeasure(numCells, numCubPoints);
00332 
00333   
00334   // Global arrays in Epetra format 
00335   Epetra_SerialComm Comm;
00336   Epetra_Map globalMapG(numDOF, 0, Comm);
00337 
00338   Epetra_Time graphTimer(Comm);
00339   Epetra_CrsGraph grph( Copy , globalMapG , 4 * numFieldsG );
00340   for (int k=0;k<numElems;k++) 
00341     {
00342       for (int i=0;i<numFieldsG;i++)
00343         {
00344           grph.InsertGlobalIndices(ltgMapping(k,i),numFieldsG,&ltgMapping(k,0));
00345         }
00346     }
00347   grph.FillComplete();
00348 
00349   const double graphTime = graphTimer.ElapsedTime();
00350   std::cout << "Graph computed in " << graphTime << "\n";
00351 
00352   Epetra_Time instantiateTimer( Comm );
00353   Epetra_FECrsMatrix StiffMatrix( Copy , grph );
00354   const double instantiateTime = instantiateTimer.ElapsedTime(  );
00355   std::cout << "Matrix instantiated in " << instantiateTime << "\n";
00356 
00357   Epetra_FEVector u(globalMapG);
00358   Epetra_FEVector Ku(globalMapG);
00359 
00360   u.Random();
00361     
00362   // ************************** Compute element HGrad stiffness matrices *******************************  
00363   // Get vertices of all the cells
00364 
00365   for (int i=0;i<numElems;i++)
00366     {
00367       for (int j=0;j<4;j++)
00368         {
00369           const int nodeCur = elemToNode(i,j);
00370           for (int k=0;k<spaceDim;k++) 
00371             {
00372               cellVertices(i,j,k) = nodeCoord(nodeCur,k);
00373             }
00374         }
00375     }
00376 
00377   Epetra_Time localConstructTimer(Comm);
00378 
00379   // Compute all cell Jacobians, their inverses and their determinants
00380   CellTools::setJacobian(cellJacobian, cubPoints, cellVertices, quad_4);
00381   CellTools::setJacobianInv(cellJacobInv, cellJacobian );
00382   CellTools::setJacobianDet(cellJacobDet, cellJacobian );
00383   
00384   // transform reference element gradients to each cell
00385   fst::HGRADtransformGRAD<double>(transformedBasisGradients, cellJacobInv, quadGrads);
00386       
00387   // compute weighted measure
00388   fst::computeCellMeasure<double>(weightedMeasure, cellJacobDet, cubWeights);
00389 
00390   // multiply values with weighted measure
00391   fst::multiplyMeasure<double>(weightedTransformedBasisGradients,
00392                                weightedMeasure, transformedBasisGradients);
00393 
00394   // integrate to compute element stiffness matrix
00395   fst::integrate<double>(localStiffMatrices,
00396                          transformedBasisGradients, weightedTransformedBasisGradients , COMP_BLAS);
00397 
00398   const double localConstructTime = localConstructTimer.ElapsedTime();
00399   std::cout << "Time to build local matrices (including Jacobian computation): "<< localConstructTime << "\n";
00400 
00401   Epetra_Time insertionTimer(Comm);
00402 
00403   // *** Element loop ***
00404    for (int k=0; k<numElems; k++) 
00405      {
00406        // assemble into global matrix
00407        StiffMatrix.InsertGlobalValues(numFieldsG,&ltgMapping(k,0),numFieldsG,&ltgMapping(k,0),&localStiffMatrices(k,0,0));
00408 
00409      }
00410    StiffMatrix.GlobalAssemble(); StiffMatrix.FillComplete();
00411    const double insertionTime = insertionTimer.ElapsedTime( );
00412    
00413    std::cout << "Time to assemble global matrix from local matrices: " << insertionTime << "\n";
00414 
00415 
00416 #ifdef DUMP_DATA
00417    // Dump matrices to disk
00418 //    EpetraExt::RowMatrixToMatlabFile("stiff_matrix.dat",StiffMatrix);
00419 //    EpetraExt::MultiVectorToMatrixMarketFile("rhs_vector.dat",rhs,0,0,false);
00420 #endif
00421 
00422    
00423    std::cout << "End Result: TEST PASSED\n";
00424 
00425    // reset format state of std::cout
00426    std::cout.copyfmt(oldFormatState);
00427    
00428    return 0;
00429 }
00430