Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

octLaplacian.C

Go to the documentation of this file.
00001 
00007 #include "mpi.h"
00008 #include "petsc.h"
00009 #include "sys.h"
00010 #include "petscmat.h"
00011 #include "petscvec.h"
00012 #include "petscksp.h"
00013 #include "oda.h"
00014 #include <cstdlib>
00015 #include "massMatrix.h"
00016 #include "stiffnessMatrix.h"
00017 #include "externVars.h"
00018 
00019 static char help[] = "Driver for a variable coefficient Laplacian problem on octrees";
00020 
00021 #ifdef MPI_WTIME_IS_GLOBAL
00022 #undef MPI_WTIME_IS_GLOBAL
00023 #endif
00024 
00025 PetscErrorCode LaplacianMatMult(Mat J , Vec in, Vec out);
00026 PetscErrorCode InitializeData(ot::DA* da, Vec nu, Vec inc);
00027 
00028 typedef struct {
00029   massMatrix* Mass;
00030   stiffnessMatrix* Stiffness;
00031 } AppCtx;
00032 
00033 int main(int argc, char **argv)
00034 {
00035   unsigned int dof = 1;
00036   double nuval = 1.0;
00037 
00038   Vec nu;   /* Coefficient vector for the laplacian */
00039   Vec rhs, inc, sol;
00040 
00041   int size, rank;
00042 
00043   // Parameters for the balancing algorithm.
00044   // Refer to manual for details ... 
00045   bool incCorner = 1; // balance across corners = true  
00046   unsigned int maxNumPts= 1; // maximum number of points per octant
00047   unsigned int dim=3; // spatial dimensions 
00048   unsigned int maxDepth=30; // maximum depth of the octree, has to be <= 30
00049 
00050   char filePrefix[PETSC_MAX_PATH_LEN];
00051   char filename[PETSC_MAX_PATH_LEN];
00052 
00053   // The global domain size
00054   double gSize[3];
00055   gSize[0] = 1.; gSize[1] = 1.; gSize[2] = 1.;
00056 
00057   std::vector<ot::TreeNode> linOct, balOct;
00058   std::vector<double> pts;
00059 
00060   PetscInitialize(&argc, &argv, "options", NULL);
00061   ot::RegisterEvents();
00062   ot::DA_Initialize(MPI_COMM_WORLD);
00063 
00064   MPI_Comm_size(MPI_COMM_WORLD, &size);
00065   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
00066 
00067   if(argc < 3) {
00068     std::cerr << "Usage: " << argv[0] << "-pfx file_prefix" << std::endl;
00069     return -1;
00070   }
00071 
00072   CHKERRQ ( PetscOptionsGetString(PETSC_NULL, "-pfx", filePrefix, PETSC_MAX_PATH_LEN-1, PETSC_NULL));
00073 
00074   /*********************************************************************** */
00075   // READ: Read pts from file ...
00076   /*********************************************************************** */
00077   sprintf(filename, "%s.%d.pts", filePrefix, rank); 
00078   ot::readPtsFromFile(filename, pts);
00079 
00080   MPI_Barrier(MPI_COMM_WORLD);  
00081 
00082   /*********************************************************************** */
00083   // CONSTRUCT: Construct the linear octree from the points ...
00084   /*********************************************************************** */
00085   ot::points2Octree(pts, gSize, linOct, dim, maxDepth, maxNumPts, MPI_COMM_WORLD);
00086 
00087   // The points are not needed anymore, and can be cleared to free memory.
00088   pts.clear();
00089 
00090   /*********************************************************************** */
00091   // BALANCE: Balance the linear octree to enforce the 2:1 balance conditions.
00092   /*********************************************************************** */
00093   ot::balanceOctree (linOct, balOct, dim, maxDepth, incCorner, MPI_COMM_WORLD, NULL, NULL);
00094 
00095   // The linear octree (unbalanced) can be cleared to free memory.
00096   linOct.clear();
00097 
00098   // If desired the octree can be written to a file using the supplied routine ...
00099   //  ot::writeNodesToFile("filename.rank", balOct);
00100 
00101   /*********************************************************************** */
00102   // MESH : Construct the octree-based Distruted Array.
00103   /*********************************************************************** */
00104   assert(!(balOct.empty()));
00105   ot::DA da(balOct,MPI_COMM_WORLD, MPI_COMM_WORLD);
00106   balOct.clear();
00107 
00108   MPI_Barrier(MPI_COMM_WORLD);
00109 
00110   if (!rank)
00111     std::cout <<"Finshed Meshing" << std::endl;
00112 
00113   /*********************************************************************** */
00114   // Laplacian
00115   /*********************************************************************** */
00116 
00117   PetscOptionsGetScalar(0,"-nu",&nuval,0);
00118 
00119   // Use the ot::DA to create PETSc Vec objects
00120   da.createVector(inc, false, false, dof);
00121   da.createVector(nu, false, false, dof);
00122   da.createVector(rhs, false, false, dof);
00123   da.createVector(sol, false, false, dof);
00124 
00125   // Simple PETSc based initialization
00126   CHKERRQ( VecSet(nu, nuval ) );
00127   CHKERRQ( VecSet(inc, 1.0) );   
00128 
00129   // We can use elemental and nodal loops using the DA to initialize elemental 
00130   // and nodal properties.
00131   InitializeData(&da, nu, inc);
00132 
00133   /* ********************************************************************** */
00134   // create the Matrix objects
00135   massMatrix *Mass = new massMatrix(ot::fem::feMat::OCT); // Mass Matrix
00136   stiffnessMatrix *Stiffness = new stiffnessMatrix(ot::fem::feMat::OCT); // Stiffness matrix
00137 
00138   // set Matrix parameters
00139   Mass->setProblemDimensions(1.0,1.0,1.0);
00140   Mass->setDA(&da);
00141   Mass->setDof(dof);
00142 
00143   Stiffness->setProblemDimensions(1.0,1.0,1.0);
00144   Stiffness->setDA(&da);
00145   Stiffness->setNuVec(nu);
00146   Stiffness->setDof(dof);
00147 
00148   // The RHS
00149   Mass->MatVec(inc, rhs);
00150 
00151   // Create the user context
00152   AppCtx user;
00153   user.Stiffness = Stiffness;
00154   user.Mass = Mass;
00155 
00156   unsigned int Nx = da.getNodeSize();
00157   
00158   Mat J;
00159   MatCreateShell(PETSC_COMM_WORLD,dof*Nx, dof*Nx, PETSC_DETERMINE,PETSC_DETERMINE,&user,&J);
00160   MatShellSetOperation(J,MATOP_MULT,(void(*)(void))LaplacianMatMult);
00161 
00162   KSP ksp;
00163   KSPCreate(PETSC_COMM_WORLD,&ksp);
00164   KSPSetOperators(ksp,J,J,SAME_NONZERO_PATTERN);
00165   KSPSetType(ksp,KSPCG);
00166   KSPSetFromOptions(ksp);
00167 
00168   // Solve 
00169   KSPSolve(ksp, rhs, sol);
00170 
00171   ot::DA_Finalize();
00172   PetscFinalize();
00173 
00174   return 0;
00175 }
00176 
00177 #undef __FUNCT__
00178 #define __FUNCT__ "LaplacianMatMult"
00179 PetscErrorCode LaplacianMatMult(Mat J , Vec in, Vec out)
00180 {
00181   PetscFunctionBegin;
00182   AppCtx *data;
00183 
00184   MatShellGetContext( J, (void **)&data);  
00185 
00186   VecZeroEntries(out);
00187   data->Mass->MatVec(in,out);
00188   data->Stiffness->MatVec(in,out,-1.0);
00189   PetscFunctionReturn(0);
00190 }
00191 
00192 
00193 #undef __FUNCT__
00194 #define __FUNCT__ "InitializeData"
00195 PetscErrorCode InitializeData(ot::DA* da, Vec nu, Vec inc) {
00196   PetscScalar *inarray;
00197   PetscScalar *nuarray;
00198 
00199   unsigned int dof = 1;
00200 
00201   // Get pointers to the data buffers 
00202   da->vecGetBuffer(inc, inarray,false,false,false,dof);
00203   da->vecGetBuffer(nu, nuarray,false,false,false,dof);
00204   
00205   unsigned int maxD = da->getMaxDepth();
00206   unsigned int balOctmaxD = maxD - 1;
00207   unsigned int Nx = da->getNodeSize();
00208 
00209   double facsol = 1.0;
00210 
00211   for( da->init<ot::DA_FLAGS::ALL>(), da->init<ot::DA_FLAGS::WRITABLE>(); da->curr() < da->end<ot::DA_FLAGS::ALL>(); da->next<ot::DA_FLAGS::ALL>()) {
00212     
00213     Point pt;
00214     pt = da->getCurrentOffset();
00215     unsigned levelhere = da->getLevel(da->curr()) - 1;
00216     double hxOct = (double)((double)(1u << (balOctmaxD - levelhere))/(double)(1u << balOctmaxD));
00217     
00218     double x = (double)(pt.xint())/((double)(1u << (maxD-1)));
00219     double y = (double)(pt.yint())/((double)(1u << (maxD-1)));
00220     double z = (double)(pt.zint())/((double)(1u << (maxD-1)));
00221 
00222     int xindx = (static_cast<int>(x+y+z))%2;
00223     unsigned int indices[8];
00224     da->getNodeIndices(indices); 
00225     double coord[8][3] = {
00226       {0.0,0.0,0.0},
00227       {1.0,0.0,0.0},
00228       {0.0,1.0,0.0},
00229       {1.0,1.0,0.0},
00230       {0.0,0.0,1.0},
00231       {1.0,0.0,1.0},
00232       {0.0,1.0,1.0},
00233       {1.0,1.0,1.0}
00234     };
00235 
00236     unsigned char hn = da->getHangingNodeIndex(da->curr());
00237 
00238     for(int i = 0; i < 8; i++) {
00239       if (!(hn & (1 << i))) {
00240         double xhere, yhere, zhere;
00241         xhere = x + coord[i][0]*hxOct ; 
00242         yhere = y + coord[i][1]*hxOct; 
00243         zhere = z + coord[i][2]*hxOct; 
00244         
00245         nuarray[dof*indices[i]] = cos(facsol*M_PI*xhere)*cos(facsol*M_PI*yhere)*cos(facsol*M_PI*zhere);
00246         inarray[dof*indices[i]] = (1.0 + 3.0*facsol*facsol*M_PI*M_PI)*cos(facsol*M_PI*xhere)*cos(facsol*M_PI*yhere)*cos(facsol*M_PI*zhere);
00247       }
00248     }
00249   }
00250 
00251   da->vecRestoreBuffer(inc,inarray,false,false,false,dof);
00252   da->vecRestoreBuffer(nu,nuarray,false,false,false,dof);
00253 
00254   PetscFunctionReturn(0);
00255 }
00256 

Generated on Tue Mar 24 16:13:59 2009 for DENDRO by  doxygen 1.3.9.1