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

omgNeumann.C

Go to the documentation of this file.
00001 
00005 #include <mpi.h>
00006 #include <cstdio>
00007 #include "oda.h"
00008 #include "omg.h"
00009 #include "Point.h"
00010 #include "parUtils.h"
00011 #include "octUtils.h"
00012 #include "TreeNode.h"
00013 #include "handleStencils.h"
00014 #include <cstdlib>
00015 #include "sys.h"
00016 #include <sstream>
00017 #include "omgNeumann.h"
00018 #include "dendro.h"
00019 
00020 #ifdef PETSC_USE_LOG
00021 extern int Jac2MultEvent;
00022 extern int Jac2DiagEvent;
00023 extern int Jac2FinestMultEvent;
00024 extern int Jac2FinestDiagEvent;
00025 #endif
00026 
00027 static double**** LaplacianType2Stencil; 
00028 static double**** MassType2Stencil; 
00029 static double*** RHSType2Stencil; 
00030 static std::vector<double> force_values; // value of RHS at centers of "ALL" octants on this process;  global since ComputeRHS needs it
00031 
00032 struct Jac2MFreeData {
00033   std::vector<double>* matProp;
00034   bool isFinestLevel;
00035   Mat Jmat_private;
00036   Vec inTmp;
00037   Vec outTmp;
00038 };
00039 
00040 #define CHK_AND_SCATTER_FINE_TO_COARSE_BLOCK {\
00041   if( damg_i->da_aux == NULL ) {\
00042     daf = da;\
00043     fMatPropVec = matPropVecPtr;\
00044     changedPartition  = false;\
00045   }else {\
00046     daf = damg_i->da_aux;\
00047     /*Need to Scatter Values*/\
00048     fMatPropVec = new std::vector<double>;\
00049     changedPartition  = true;\
00050     /*elemental - non-ghosted*/\
00051     std::vector<double> tmpVec1;\
00052     da->createVector<double>(tmpVec1,true,false,2);\
00053     double *vec1Arr = NULL;\
00054     /*Elemental,non-Ghosted,Write,2 Dof.*/\
00055     da->vecGetBuffer<double>(tmpVec1,vec1Arr,true,false,false,2);\
00056     matPropArr = NULL;\
00057     /*Elemental,Ghosted,Read-only,2 Dof.*/\
00058     da->vecGetBuffer<double>((*matPropVecPtr), matPropArr, true, true, true, 2);\
00059     if(da->iAmActive()) {\
00060       for(da->init<ot::DA_FLAGS::WRITABLE>(); da->curr() < da->end<ot::DA_FLAGS::WRITABLE>(); da->next<ot::DA_FLAGS::WRITABLE>()) {\
00061         unsigned int idx = da->curr();\
00062         vec1Arr[2*idx] = matPropArr[2*idx];\
00063         vec1Arr[2*idx+1] = matPropArr[2*idx+1];\
00064       }\
00065     }\
00066     da->vecRestoreBuffer<double>((*matPropVecPtr), matPropArr, true, true, true, 2);\
00067     da->vecRestoreBuffer<double>(tmpVec1,vec1Arr,true,false,false,2);\
00068     par::scatterValues<double>(tmpVec1, (*fMatPropVec), (2*(daf->getElementSize())), da->getComm());\
00069     tmpVec1.clear();\
00070   }\
00071 }
00072 
00073 #define ASSIGN_MAT_PROP_FINE_TO_COARSE_ELEM_BLOCK {\
00074   /*The fine loop is always Writable, but the coarse loop*/\
00075   /*could be Independent or W_Dependent. Hence the fine counter must*/\
00076   /*be incremented properly to align with the coarse.*/\
00077   unsigned int idxC= da->curr();\
00078   Point Cpt = da->getCurrentOffset();\
00079   assert(daf->curr() < daf->end<ot::DA_FLAGS::WRITABLE>());\
00080   while(daf->getCurrentOffset() != Cpt) {\
00081     daf->next<ot::DA_FLAGS::WRITABLE>();\
00082     assert(daf->curr() < daf->end<ot::DA_FLAGS::WRITABLE>());\
00083   }\
00084   if(daf->getLevel(daf->curr()) == da->getLevel(idxC)) {\
00085     /*The coarse and fine elements are the same,*/\
00086     assert(daf->curr() < daf->end<ot::DA_FLAGS::WRITABLE>());\
00087     unsigned int idxF = daf->curr();\
00088     matPropArr[2*idxC] = fMatArr[2*idxF];\
00089     matPropArr[2*idxC+1] = fMatArr[2*idxF+1];\
00090     daf->next<ot::DA_FLAGS::WRITABLE>();\
00091   }else {\
00092     double cLapVal = 0.0;\
00093     double cMassVal = 0.0;\
00094     for(unsigned char cNumFine = 0; cNumFine < 8; cNumFine++) {\
00095       /*The coarse and fine elements are NOT the same. */\
00096       /*Loop over each of the 8 children of the coarse element.*/\
00097       /*These are the underlying fine elements.*/\
00098       assert(daf->curr() < daf->end<ot::DA_FLAGS::WRITABLE>());\
00099       unsigned int idxF = daf->curr();\
00100       cLapVal += fMatArr[2*idxF];\
00101       cMassVal += fMatArr[2*idxF+1];\
00102       daf->next<ot::DA_FLAGS::WRITABLE>();\
00103     }\
00104     matPropArr[2*idxC] = (cLapVal/8.0);\
00105     matPropArr[2*idxC+1] = (cMassVal/8.0);\
00106   }\
00107   if(matPropArr[2*idxC] > maxCoeff) {\
00108     maxCoeff = matPropArr[2*idxC];\
00109   }\
00110   if(matPropArr[2*idxC] < minCoeff) {\
00111     minCoeff = matPropArr[2*idxC];\
00112   }\
00113 }
00114 
00115 #define FINE_TO_COARSE_BLOCK {\
00116   damg_i = damg[i];\
00117   damg_i->user = ctx;\
00118   da = damg_i->da;\
00119   assert(da->iAmActive() == daf->iAmActive());\
00120   da->createVector<double>((*matPropVecPtr), true, true, 2);\
00121   for(unsigned int j = 0; j < matPropVecPtr->size(); j++) {\
00122     (*matPropVecPtr)[j] = 0.0;\
00123   }\
00124   comm = da->getCommActive();\
00125   MPI_Comm_rank(comm,&rank);\
00126   /*Elemental,Ghosted,Write,2 Dof.*/\
00127   matPropArr = NULL;\
00128   da->vecGetBuffer<double>((*matPropVecPtr), matPropArr,\
00129       true, true, false, 2);\
00130   double *fMatArr = NULL;\
00131   if(changedPartition) {\
00132     /*Elemental, non-Ghosted, Read-only, 2 Dof.*/\
00133     daf->vecGetBuffer<double>((*fMatPropVec), fMatArr,\
00134         true, false, true, 2);\
00135   }else {\
00136     /*Elemental, Ghosted, Read-only, 2 Dof.*/\
00137     daf->vecGetBuffer<double>((*fMatPropVec), fMatArr,\
00138         true, true, true, 2);\
00139   }\
00140   if(da->iAmActive()) {\
00141     double maxCoeff = 0.0;\
00142     double minCoeff = 1.0e+8;\
00143     double globalMaxCoeff;\
00144     double globalMinCoeff;\
00145     /*Loop through the coarse and fine simultaneously*/\
00146     /*Note: If Coarse is Independent, then the*/\
00147     /*corresponding Fine is also independent.*/\
00148     /*Hence, overlapping comm with comp is possible.*/\
00149     /*First, we loop though the dependent elements.*/\
00150     /*Then we begin the communication and simulatenously*/\
00151     /*loop over the independent elements.*/\
00152     for(da->init<ot::DA_FLAGS::W_DEPENDENT>(),\
00153         daf->init<ot::DA_FLAGS::WRITABLE>();\
00154         da->curr() < da->end<ot::DA_FLAGS::W_DEPENDENT>();\
00155         da->next<ot::DA_FLAGS::W_DEPENDENT>()) {\
00156       ASSIGN_MAT_PROP_FINE_TO_COARSE_ELEM_BLOCK \
00157     } /*end dependent loop*/\
00158     da->ReadFromGhostElemsBegin<double>(matPropArr,2);\
00159     for(da->init<ot::DA_FLAGS::INDEPENDENT>(),\
00160         daf->init<ot::DA_FLAGS::WRITABLE>();\
00161         da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();\
00162         da->next<ot::DA_FLAGS::INDEPENDENT>()) {\
00163       ASSIGN_MAT_PROP_FINE_TO_COARSE_ELEM_BLOCK \
00164     } /*end Independent loop */\
00165     da->ReadFromGhostElemsEnd<double>(matPropArr);\
00166     par::Mpi_Reduce<double>(&maxCoeff, &globalMaxCoeff, 1, MPI_MAX, 0, comm);\
00167     par::Mpi_Reduce<double>(&minCoeff, &globalMinCoeff, 1, MPI_MIN, 0, comm);\
00168     if(!rank) {\
00169       std::cout<<"Level: "<<i<<" Max Lap. Coeff: "\
00170       <<globalMaxCoeff<<" Min Lap. Coeff: "\
00171       <<globalMinCoeff<<std::endl;\
00172     }\
00173     MPI_Barrier(comm);\
00174   } /*end check if active*/\
00175   da->vecRestoreBuffer<double>((*matPropVecPtr),\
00176       matPropArr, true, true, false, 2);\
00177   if(changedPartition) {\
00178     /*Elemental, non-Ghosted, Read-only, 2 Dof.*/\
00179     daf->vecRestoreBuffer<double>((*fMatPropVec),\
00180         fMatArr, true, false, true, 2);\
00181   }else {\
00182     /*Elemental, Ghosted, Read-only, 2 Dof.*/\
00183     daf->vecRestoreBuffer<double>((*fMatPropVec),\
00184         fMatArr, true, true, true, 2);\
00185   }\
00186 }
00187 
00188 void SetPDECoefFromPts(
00189     ot::DAMG* damg,
00190     const std::vector<double>& centers,
00191     void (*CalcCoef)(const std::vector<double> & pts, std::vector<double> & values)
00192     )
00193 {
00194   int nlevels = damg[0]->nlevels; //number of mg levels
00195   ot::DAMG damg_i = damg[nlevels-1];
00196 
00197   //Set Mat Props Finest to Coarsest...
00198   void * ctx;
00199 
00200   // Set for the finest level first
00201   ctx = new Jac2MFreeData;
00202 
00203   std::vector<double> * matPropVecPtr = new std::vector<double>;
00204 
00205   (static_cast<Jac2MFreeData*>(ctx))->matProp = matPropVecPtr;
00206   (static_cast<Jac2MFreeData*>(ctx))->isFinestLevel = true;
00207   (static_cast<Jac2MFreeData*>(ctx))->Jmat_private = NULL;
00208   (static_cast<Jac2MFreeData*>(ctx))->inTmp = NULL;
00209   (static_cast<Jac2MFreeData*>(ctx))->outTmp = NULL;
00210 
00211   double *matPropArr = NULL;
00212   ot::DA* da;
00213   int rank;
00214   MPI_Comm comm;
00215 
00216   damg_i->user = ctx;
00217   da = damg_i->da;
00218   comm = da->getCommActive();
00219   MPI_Comm_rank(comm,&rank);
00220   /*Elem,Ghosted, 2-dof vector.*/
00221   /*Note: I am creating a ghosted vector only*/
00222   /*because the mat-vec will need it.*/
00223   /*So this way, I can avoid mallocs inside the mat-vec.*/
00224   da->createVector<double>((*matPropVecPtr), true, true, 2);
00225   for(unsigned int i = 0; i < matPropVecPtr->size(); i++) {
00226     (*matPropVecPtr)[i] = 0.0;
00227   }
00228   /*Elemental,Ghosted,Write,2 Dof.*/
00229   da->vecGetBuffer<double>((*matPropVecPtr), matPropArr,
00230       true, true, false, 2);
00231   if(da->iAmActive()) {
00232     double maxCoeff = 0.0;
00233     double minCoeff = 1.0e+80;
00234     double globalMaxCoeff;
00235     double globalMinCoeff;
00236 
00237     // call user-provided routine to calculate the coefficients
00238     // we can use here *matPropVectPtr since this vector is both elemental and ghosted
00239     CalcCoef(centers, *matPropVecPtr);
00240 
00241     // calculate min and max "alpha" for debugging
00242     for(da->init<ot::DA_FLAGS::ALL>();
00243         da->curr() < da->end<ot::DA_FLAGS::ALL>();
00244         da->next<ot::DA_FLAGS::ALL>()) {
00245       unsigned int idx = da->curr();
00246 
00247       if(matPropArr[2*idx] > maxCoeff) 
00248         maxCoeff = matPropArr[2*idx];
00249 
00250       if(matPropArr[2*idx] < minCoeff) 
00251         minCoeff = matPropArr[2*idx];
00252     }
00253 
00254     par::Mpi_Reduce<double>(&maxCoeff, &globalMaxCoeff, 1, MPI_MAX, 0, comm);
00255     par::Mpi_Reduce<double>(&minCoeff, &globalMinCoeff, 1, MPI_MIN, 0, comm);
00256     if(!rank) {
00257       std::cout<<"Level: "<<(nlevels-(damg_i->nlevels))<<
00258         " Max Lap. Coeff: "<<globalMaxCoeff<<
00259         " Min Lap. Coeff: "<<globalMinCoeff<<std::endl;
00260     }
00261   } /*end if active*/
00262   da->vecRestoreBuffer<double>((*matPropVecPtr), matPropArr,
00263       true, true, false, 2);
00264 
00265   //The coarser levels...
00266   ot::DA* daf;
00267   std::vector<double>* fMatPropVec = NULL;
00268   bool changedPartition;
00269 
00270   if(nlevels > 1) {
00271     CHK_AND_SCATTER_FINE_TO_COARSE_BLOCK 
00272   }
00273 
00274   //Coarser levels
00275   for(int i = (nlevels-2); i >= 0; i--) {
00276       ctx = new Jac2MFreeData;
00277 
00278     matPropVecPtr = new std::vector<double>;
00279 
00280     (static_cast<Jac2MFreeData*>(ctx))->matProp = matPropVecPtr;
00281     (static_cast<Jac2MFreeData*>(ctx))->isFinestLevel = false;
00282     (static_cast<Jac2MFreeData*>(ctx))->Jmat_private = NULL;
00283     (static_cast<Jac2MFreeData*>(ctx))->inTmp = NULL;
00284     (static_cast<Jac2MFreeData*>(ctx))->outTmp = NULL;
00285 
00286     FINE_TO_COARSE_BLOCK
00287 
00288       if(changedPartition) {
00289         fMatPropVec->clear();
00290         delete fMatPropVec;
00291       }
00292 
00293     if(i) {     
00294       CHK_AND_SCATTER_FINE_TO_COARSE_BLOCK 
00295     }
00296   }//end for i
00297 }//end fn.
00298 
00299 
00300 void DestroyUserContexts(ot::DAMG* damg) {
00301   
00302   int       nlevels = damg[0]->nlevels; //number of multigrid levels
00303 
00304   for(int i = 0; i < nlevels; i++) {
00305     Jac2MFreeData* ctx = (static_cast<Jac2MFreeData*>(damg[i]->user));
00306     ctx->matProp->clear();
00307     delete ctx->matProp;
00308     if(ctx->Jmat_private) {
00309       MatDestroy(ctx->Jmat_private);
00310       ctx->Jmat_private = NULL;
00311     }
00312     if(ctx->inTmp) {
00313       VecDestroy(ctx->inTmp);
00314       ctx->inTmp = NULL;
00315     }
00316     if(ctx->outTmp) {
00317       VecDestroy(ctx->outTmp);
00318       ctx->outTmp = NULL;
00319     }
00320     delete ctx;
00321   }
00322 }//end fn.
00323 
00324 PetscErrorCode Jacobian2ShellMatMult(Mat J, Vec in, Vec out) {
00325   PetscFunctionBegin;
00326 
00327   ot::DAMG damg;
00328 
00329   MatShellGetContext(J, (void**)(&damg));
00330 
00331   Jac2MFreeData* ctx = static_cast<Jac2MFreeData*>(damg->user);
00332 
00333   if(damg->da->iAmActive()) {      
00334     PetscScalar* inArray;
00335     PetscScalar* outArray;
00336 
00337     VecGetArray(in, &inArray);
00338     VecGetArray(out, &outArray);
00339 
00340     VecPlaceArray(ctx->inTmp, inArray);
00341     VecPlaceArray(ctx->outTmp, outArray);
00342 
00343     MatMult(ctx->Jmat_private, ctx->inTmp, ctx->outTmp);
00344 
00345     VecResetArray(ctx->inTmp);
00346     VecResetArray(ctx->outTmp);
00347 
00348     VecRestoreArray(in, &inArray);
00349     VecRestoreArray(out, &outArray);
00350   }
00351 
00352   PetscFunctionReturn(0);
00353 }
00354 
00355 
00356 
00357 void getActiveStateAndActiveCommForKSP_Shell_Jac2or3(Mat mat,
00358     bool & activeState, MPI_Comm & activeComm) {
00359   PetscTruth isshell;
00360   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
00361   assert(isshell);
00362   ot::DAMG damg;
00363   MatShellGetContext(mat, (void**)(&damg));
00364   ot::DA* da = damg->da;
00365   activeState = da->iAmActive();
00366   activeComm = da->getCommActive();
00367 }
00368 
00369 
00370 void getPrivateMatricesForKSP_Shell_Jac2(Mat mat,
00371     Mat *AmatPrivate, Mat *PmatPrivate, MatStructure* pFlag) {
00372   PetscTruth isshell;
00373   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
00374   assert(isshell);
00375   ot::DAMG damg;
00376   MatShellGetContext(mat, (void**)(&damg));
00377   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
00378   *AmatPrivate = data->Jmat_private;
00379   *PmatPrivate = data->Jmat_private;
00380   *pFlag = DIFFERENT_NONZERO_PATTERN;
00381 }
00382 
00383 
00384 
00385 
00386 
00387 PetscErrorCode Jacobian2MatDestroy(Mat J) {
00388   PetscFunctionBegin;
00389   //Nothing to be done here. No new pointers were created during creation. 
00390   //The pointer were created in setUSerContext. So they will be destroyed in
00391   //DestroyUserContexts.
00392   PetscFunctionReturn(0);
00393 }
00394 
00395 
00396 #define JAC_TYPE2_ELEM_DIAG_BLOCK {\
00397   unsigned int idx = da->curr();\
00398   unsigned int lev = da->getLevel(idx);\
00399   double h = hFac*(1u << (maxD - lev));\
00400   double matP1 = matPropArr[2*idx];\
00401   double matP2 = matPropArr[2*idx+1];\
00402   double fac1 = matP1*h/2.0;\
00403   double fac2 = matP2*h*h*h/8.0;\
00404   unsigned int indices[8];\
00405   da->getNodeIndices(indices);\
00406   unsigned char childNum = da->getChildNumber();\
00407   unsigned char hnMask = da->getHangingNodeIndex(idx);\
00408   unsigned char elemType = 0;\
00409   GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
00410   for(int k = 0; k < 8; k++) {\
00411     diagArr[indices[k]] +=  ((fac1*(LaplacianType2Stencil[childNum][elemType][k][k])) +\
00412         (fac2*(MassType2Stencil[childNum][elemType][k][k])));\
00413   } /*end k*/\
00414 }
00415 
00416 #define JAC_TYPE2_DIAG_BLOCK {\
00417   ot::DA* da = damg->da;\
00418   iC(VecZeroEntries(diag));\
00419   double *matPropArr;\
00420   /*Elem,Ghost,Read-only,1 dof*/\
00421   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
00422   PetscScalar *diagArr;\
00423   /*Nodal,Non-Ghosted,Write,1 dof*/\
00424   da->vecGetBuffer(diag,diagArr,false,false,false,1);\
00425   unsigned int maxD;\
00426   double hFac;\
00427   if(da->iAmActive()) {\
00428     maxD = (da->getMaxDepth());\
00429     hFac = 1.0/((double)(1u << (maxD-1)));\
00430     /*Loop through All Elements including ghosted*/\
00431     for(da->init<ot::DA_FLAGS::ALL>(); da->curr() < da->end<ot::DA_FLAGS::ALL>(); da->next<ot::DA_FLAGS::ALL>()) {\
00432       JAC_TYPE2_ELEM_DIAG_BLOCK\
00433     } /*end i*/\
00434   } /*end if active*/\
00435   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
00436   da->vecRestoreBuffer(diag,diagArr,false,false,false,1);\
00437   PetscLogFlops(44*(da->getGhostedElementSize()));\
00438 }
00439 
00440 
00441 
00442 PetscErrorCode Jacobian2MatGetDiagonal(Mat J, Vec diag) {
00443   PetscFunctionBegin;
00444 
00445   PetscLogEventBegin(Jac2DiagEvent,diag,0,0,0);
00446 
00447   ot::DAMG damg;
00448   iC(MatShellGetContext(J, (void**)(&damg)));
00449 
00450   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
00451 
00452   if(data->isFinestLevel) {
00453     PetscLogEventBegin(Jac2FinestDiagEvent,diag,0,0,0);
00454   }
00455 
00456   JAC_TYPE2_DIAG_BLOCK 
00457 
00458     if(data->isFinestLevel) {
00459       PetscLogEventEnd(Jac2FinestDiagEvent,diag,0,0,0);
00460     }
00461 
00462   PetscLogEventEnd(Jac2DiagEvent,diag,0,0,0);
00463 
00464   PetscFunctionReturn(0);
00465 }
00466 
00467 
00468 #define JAC_TYPE2_ELEM_MULT_BLOCK {\
00469   unsigned int idx = da->curr();\
00470   unsigned int lev = da->getLevel(idx);\
00471   double h = hFac*(1u << (maxD - lev));\
00472   double matP1 = matPropArr[2*idx];\
00473   double matP2 = matPropArr[2*idx+1];\
00474   double fac1 = matP1*h/2.0;\
00475   double fac2 = matP2*h*h*h/8.0;\
00476   unsigned int indices[8];\
00477   da->getNodeIndices(indices);\
00478   unsigned char childNum = da->getChildNumber();\
00479   unsigned char hnMask = da->getHangingNodeIndex(idx);\
00480   unsigned char elemType = 0;\
00481   GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
00482   for(int k = 0;k < 8;k++) {\
00483     for(int j=0;j<8;j++) {\
00484       outArr[indices[k]] +=  (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
00485             (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);\
00486     }/*end for j*/\
00487   }/*end for k*/\
00488 }
00489 
00490 
00491 #define JAC_TYPE2_MULT_BLOCK {\
00492   ot::DA* da = damg->da;\
00493   iC(VecZeroEntries(out));\
00494   unsigned int maxD;\
00495   double hFac;\
00496   if(da->iAmActive()) {\
00497     maxD = da->getMaxDepth();\
00498     hFac = 1.0/((double)(1u << (maxD-1)));\
00499   }\
00500   double *matPropArr = NULL;\
00501   /*Elem,Ghost,Read-only,2 dof*/\
00502   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
00503   PetscScalar *outArr=NULL;\
00504   PetscScalar *inArr=NULL;\
00505   /*Nodal,Non-Ghosted,Read,1 dof*/\
00506   da->vecGetBuffer(in,inArr,false,false,true,1);\
00507   da->ReadFromGhostsBegin<PetscScalar>(inArr,1);\
00508   /*Nodal,Non-Ghosted,Write,1 dof*/\
00509   da->vecGetBuffer(out,outArr,false,false,false,1);\
00510   /*Loop through All Independent Elements*/\
00511   if(da->iAmActive()) {\
00512     for(da->init<ot::DA_FLAGS::INDEPENDENT>(); da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>(); da->next<ot::DA_FLAGS::INDEPENDENT>() ) {\
00513       JAC_TYPE2_ELEM_MULT_BLOCK\
00514     } /*end independent*/\
00515   } /*end if active*/\
00516   da->ReadFromGhostsEnd<PetscScalar>(inArr);\
00517   /*Loop through All Dependent Elements,*/\
00518   /*i.e. Elements which have atleast one*/\
00519   /*vertex owned by this processor and at least one*/\
00520   /*vertex not owned by this processor.*/\
00521   if(da->iAmActive()) {\
00522     for(da->init<ot::DA_FLAGS::DEPENDENT>(); da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>();  da->next<ot::DA_FLAGS::DEPENDENT>() ) {\
00523       JAC_TYPE2_ELEM_MULT_BLOCK\
00524     } /*end loop for dependent elems*/\
00525   } /*end if active*/\
00526   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
00527   da->vecRestoreBuffer(in,inArr,false,false,true,1);\
00528   da->vecRestoreBuffer(out,outArr,false,false,false,1);\
00529   PetscLogFlops(332*(da->getGhostedElementSize()));\
00530 }
00531 
00532 
00533 PetscErrorCode Jacobian2MatMult(Mat J, Vec in, Vec out)
00534 {
00535   PetscFunctionBegin;
00536 
00537   PetscLogEventBegin(Jac2MultEvent,in,out,0,0);
00538 
00539   ot::DAMG damg;
00540   iC(MatShellGetContext(J, (void**)(&damg)));
00541 
00542   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
00543 
00544   if(data->isFinestLevel) {
00545     PetscLogEventBegin(Jac2FinestMultEvent,in,out,0,0);
00546   }
00547 
00548   JAC_TYPE2_MULT_BLOCK 
00549 
00550     if(data->isFinestLevel) {
00551       PetscLogEventEnd(Jac2FinestMultEvent,in,out,0,0);
00552     }
00553 
00554   PetscLogEventEnd(Jac2MultEvent,in,out,0,0);
00555 
00556   PetscFunctionReturn(0);
00557 }
00558 
00559 
00560 #define BUILD_FULL_JAC_TYPE2_BLOCK(B) {\
00561   ot::DA* da = damg->da;\
00562   MatZeroEntries(B);\
00563   std::vector<ot::MatRecord> records;\
00564   unsigned int maxD;\
00565   double hFac;\
00566   if(da->iAmActive()) {\
00567     maxD = da->getMaxDepth();\
00568     hFac = 1.0/((double)(1u << (maxD-1)));\
00569   }\
00570   double *matPropArr = NULL;\
00571   /*Elem,Ghost,Read-only,2 dof*/\
00572   /*Note: All the flags are used for describing*/\
00573   /*the type of input vector, not*/\
00574   /*the type of the buffer.*/\
00575   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
00576   if(da->iAmActive()) {\
00577     for(da->init<ot::DA_FLAGS::WRITABLE>(); da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();  da->next<ot::DA_FLAGS::WRITABLE>()) {\
00578       unsigned int idx = da->curr();\
00579       unsigned int lev = da->getLevel(idx);\
00580       double h = hFac*(1u << (maxD - lev));\
00581       double matP1 = matPropArr[2*idx];\
00582       double matP2 = matPropArr[2*idx+1];\
00583       double fac1 = matP1*h/2.0;\
00584       double fac2 = matP2*h*h*h/8.0;\
00585       unsigned int indices[8];\
00586       da->getNodeIndices(indices);\
00587       unsigned char childNum = da->getChildNumber();\
00588       unsigned char hnMask = da->getHangingNodeIndex(idx);\
00589       unsigned char elemType = 0;\
00590       GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
00591       for(int k = 0;k < 8;k++) {\
00592         for(int j=0;j<8;j++) {\
00593           ot::MatRecord currRec;\
00594           currRec.rowIdx = indices[k];\
00595           currRec.colIdx = indices[j];\
00596           currRec.rowDim = 0;\
00597           currRec.colDim = 0;\
00598           currRec.val = ((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
00599               (fac2*(MassType2Stencil[childNum][elemType][k][j])));\
00600           records.push_back(currRec);\
00601         } /*end for j*/\
00602       } /*end for k*/\
00603       if(records.size() > 1000) {\
00604         /*records will be cleared inside the function*/\
00605         da->setValuesInMatrix(B, records, 1, ADD_VALUES);\
00606       }\
00607     } /*end writable*/\
00608   } /*end if active*/\
00609   da->setValuesInMatrix(B, records, 1, ADD_VALUES);\
00610   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);\
00611   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
00612   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);\
00613 }
00614 
00615 
00616 PetscErrorCode ComputeJacobian2(ot::DAMG damg, Mat J, Mat B) {
00617   //For matShells nothing to be done here.
00618   PetscFunctionBegin;
00619 
00620   PetscTruth isshell;
00621   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
00622 
00623   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
00624 
00625   assert(B == J);
00626 
00627   if(isshell) {
00628     if( data->Jmat_private == NULL ) {
00629       PetscFunctionReturn(0);
00630     } else {
00631       J = data->Jmat_private;
00632       B = data->Jmat_private;
00633     }
00634   }
00635 
00636   //Assuming that B and J are the same.
00637 
00638   BUILD_FULL_JAC_TYPE2_BLOCK(B) 
00639 
00640     PetscFunctionReturn(0);
00641 }
00642 
00643 PetscErrorCode CreateJacobian2(ot::DAMG damg, Mat *jac) {
00644   PetscFunctionBegin;
00645   int totalLevels;
00646   PetscTruth flg;
00647   PetscInt buildFullCoarseMat;
00648   PetscInt buildFullMatAll;
00649   PetscOptionsGetInt(PETSC_NULL,"-buildFullMatAll",&buildFullMatAll,&flg);
00650   PetscOptionsGetInt(PETSC_NULL,"-buildFullCoarseMat",&buildFullCoarseMat,&flg);
00651   if(buildFullMatAll) {
00652     buildFullCoarseMat = 1;
00653   }
00654   totalLevels = damg->totalLevels;
00655   ot::DA* da = damg->da;
00656   int myRank;
00657   MPI_Comm_rank(da->getComm(),&myRank);
00658   //The size this processor owns ( without ghosts).
00659   unsigned int  m,n;
00660   m=n=da->getNodeSize();
00661   if(totalLevels == damg->nlevels) {
00662     //This is the coarsest.
00663     if( (!myRank) && buildFullCoarseMat ) {
00664       std::cout<<"Building Full Coarse Mat."<<std::endl;
00665     }
00666     char matType[30];
00667     if(buildFullCoarseMat) {
00668       if(!(da->computedLocalToGlobal())) {
00669         da->computeLocalToGlobalMappings();
00670       }
00671       PetscTruth typeFound;
00672       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00673       if(!typeFound) {
00674         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00675         assert(false);
00676       } 
00677     }
00678     bool requirePrivateMats = (da->getNpesActive() != da->getNpesAll());    
00679     if(requirePrivateMats ) {
00680       Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
00681       if(da->iAmActive()) {
00682         if(buildFullCoarseMat) {
00683           da->createActiveMatrix(data->Jmat_private, matType, 1);
00684         } else {
00685           MatCreateShell(da->getCommActive(), m, n, PETSC_DETERMINE,
00686               PETSC_DETERMINE, damg, &(data->Jmat_private));
00687           MatShellSetOperation(data->Jmat_private, MATOP_MULT,
00688               (void (*)(void)) Jacobian2MatMult);
00689           MatShellSetOperation(data->Jmat_private, MATOP_GET_DIAGONAL,
00690               (void (*)(void)) Jacobian2MatGetDiagonal);
00691           MatShellSetOperation(data->Jmat_private, MATOP_DESTROY,
00692               (void (*)(void)) Jacobian2MatDestroy);
00693         }
00694         MatGetVecs(data->Jmat_private, &(data->inTmp), &(data->outTmp));
00695       } else {
00696         data->Jmat_private = NULL;
00697         data->inTmp = NULL;
00698         data->outTmp = NULL;
00699       }
00700       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00701       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian2MatDestroy);
00702       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian2ShellMatMult);
00703     } else {
00704       if(buildFullCoarseMat) {
00705         da->createMatrix(*jac, matType, 1);
00706       } else {
00707         MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00708         MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) Jacobian2MatMult);
00709         MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) Jacobian2MatGetDiagonal);
00710         MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian2MatDestroy);
00711       }
00712     }
00713     if((!myRank) && buildFullCoarseMat) {
00714       std::cout<<"Finished Building Full Coarse Mat."<<std::endl;
00715     }
00716   } else {
00717     //This is some finer level.
00718     if(buildFullMatAll) {
00719       if(!myRank) {
00720         std::cout<<"Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
00721       }
00722       if(!(da->computedLocalToGlobal())) {
00723         da->computeLocalToGlobalMappings();
00724       }
00725       char matType[30];
00726       PetscTruth typeFound;
00727       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00728       if(!typeFound) {
00729         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00730         assert(false);
00731       } 
00732       da->createMatrix(*jac, matType, 1);
00733       if(!myRank) {
00734         std::cout<<"Finished Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
00735       }
00736     } else {
00737       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00738       MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) Jacobian2MatMult);
00739       MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) Jacobian2MatGetDiagonal);
00740       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian2MatDestroy);
00741     }
00742   }
00743 
00744   PetscFunctionReturn(0);
00745 }//end fn.
00746 
00747 /*
00748  * This function computes the right-hand side for FEM system. The load (force) is sampled at the center of each octant. These sample values are read from the global variable force_values */
00749 PetscErrorCode ComputeRHS_omgNeumann(ot::DAMG damg,Vec in) {
00750   PetscFunctionBegin;            
00751   ot::DA* da = damg->da;
00752   PetscScalar *inarray;
00753   VecZeroEntries(in);
00754   da->vecGetBuffer(in,inarray,false,false,false,1);
00755 
00756   if(da->iAmActive()) {
00757     for(da->init<ot::DA_FLAGS::ALL>();
00758         da->curr() < da->end<ot::DA_FLAGS::ALL>();
00759         da->next<ot::DA_FLAGS::ALL>())  
00760     {
00761       unsigned int idx = da->curr();
00762       unsigned levelhere = (da->getLevel(idx) - 1);
00763       
00764       double hxOct = ldexp(1.0,-levelhere);
00765       assert(hxOct==1.0/(1u<<levelhere));
00766       double fac = ((hxOct*hxOct*hxOct)/8.0);
00767       
00768       unsigned int indices[8];
00769       da->getNodeIndices(indices); 
00770       
00771       unsigned char childNum = da->getChildNumber();
00772       unsigned char hnMask = da->getHangingNodeIndex(idx);
00773       unsigned char elemType = 0;
00774       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00775       
00776       for(unsigned int j = 0; j < 8; j++) 
00777         inarray[indices[j]] += force_values[idx]*RHSType2Stencil[childNum][elemType][j]*fac;
00778     
00779     }//end looping over octants
00780     
00781   }//end if active
00782 
00783   da->vecRestoreBuffer(in,inarray,false,false,false,1);
00784   PetscFunctionReturn(0);
00785 }
00786 
00787 
00788 static void CalculateCenters(ot::DA* da, std::vector<double> & centers)
00789 {
00790   // this only resizes "centers"
00791   // also, since vector is both elemental and ghosted, we don't need the "getbuffer" function for access
00792   da->createVector<double>(centers, true/*elemental*/, true/*ghosted*/, 3/*values per octant*/);
00793 
00794   // initialize all entries to zero (loop over elements might not touch some entries)
00795   // maybe this can be skipped. but then some function will have to calculate garbage from garbage
00796   centers.assign(centers.size(),0.0);
00797   
00798   if(da->iAmActive()) {
00799     unsigned maxD = da->getMaxDepth();
00800     
00801     for(da->init<ot::DA_FLAGS::ALL>();
00802         da->curr() < da->end<ot::DA_FLAGS::ALL>();
00803         da->next<ot::DA_FLAGS::ALL>())  
00804     {
00805       Point pt = da->getCurrentOffset();
00806       unsigned int idx = da->curr();
00807       
00808       double x = ldexp( static_cast<double>(pt.xint()) , 1-maxD );
00809       double y = ldexp( static_cast<double>(pt.yint()) , 1-maxD );
00810       double z = ldexp( static_cast<double>(pt.zint()) , 1-maxD );
00811       unsigned levelhere = (da->getLevel(idx) - 1);
00812       double halfSide = ldexp(0.5, -levelhere);
00813       
00814       centers[3*idx]=x+halfSide;
00815       centers[3*idx+1]=y+halfSide;
00816       centers[3*idx+2]=z+halfSide;
00817     }//end looping over octants
00818     
00819   }//end if active
00820 }
00821 
00832 void solve_neumann(
00833     /* input parameters: */
00834      std::vector<double>& pts,
00835      void (*CalcCoef)(const std::vector<double> & pts, std::vector<double> & values),
00836      void (*CalcRHS)(const std::vector<double> & pts, std::vector<double> & values),
00837      int numMultigridLevels,
00838      /* output parameters */
00839      Vec& sol,
00840      ot::DAMG * & damg
00841     )
00842 {
00843   using namespace std;
00844   
00845   const int dim = 3;
00846   double gSize[3]={1.0, 1.0, 1.0};
00847   const double mgLoadFac = 1.5;
00848   const bool compressLut = false;
00849   const bool incCorner = true; 
00850   const int maxNumPts=1;  // we want at most 1 point per octant
00851   const int maxDepth = 30;
00852   const int dof=1;
00853 
00854   int size, rank;
00855   MPI_Comm_size(MPI_COMM_WORLD,&size);
00856   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
00857 
00858   
00859   // enforce that all points are inside [0,1)^3
00860   for(size_t i=0;i<pts.size();i++) 
00861     if (pts[i]<0)
00862       pts[i]=0;
00863     else if (pts[i]>=1)
00864       pts[i]=1-ldexp(0.5,-maxDepth);
00865 
00866   // now convert points to octree 
00867   // "pts" is cleared inside this function
00868   vector<ot::TreeNode> linOct;
00869   ot::points2Octree(pts, gSize, linOct, dim, maxDepth, maxNumPts, MPI_COMM_WORLD);
00870 
00871   //now balance the octree; "linOct" is cleared inside this function
00872   vector<ot::TreeNode> balOct;
00873   ot::balanceOctree (linOct, balOct, dim, maxDepth, true, MPI_COMM_WORLD, NULL, NULL);
00874   
00875   /*
00876   for(int i = 0; i < 1; i++) {
00877     std::vector<ot::TreeNode> tmpOct = balOct;
00878     balOct.clear();
00879     ot::refineOctree(tmpOct, balOct); 
00880   }
00881   */
00882 
00883   // createRegularOctree(balOct,5,3,maxDepth,MPI_COMM_WORLD);
00884 
00885   // print how many finest-level octants we have
00886   DendroIntL locBalSize = balOct.size();
00887   DendroIntL totBalSize;
00888   par::Mpi_Reduce<DendroIntL>(&locBalSize, &totBalSize, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00889   if(!rank) {
00890     cout << "# of octants on finest level: "<< totBalSize << endl; 
00891   }
00892   
00893   // create multigrid solver object, coarser octrees, finite element meshes and the interpolation
00894   // balOct is cleared inside this function
00895   // numMultigridLevels might be modified inside this function
00896   ot::DAMGCreateAndSetDA(MPI_COMM_WORLD,numMultigridLevels, NULL, &damg, balOct,
00897       dof, mgLoadFac, compressLut, incCorner);
00898  
00899   // set some options to make "CreateJacobian2" and "ComputeJacobian2" work. These routines are related to matrix-vector multiplication on all levels.
00900   PetscOptionsSetValue("-jacType","2");
00901   
00902   // load stencils, i.e. integrals of: products of gradients of shape functions, product of shape functions and shape functions themselves
00903   createLmatType2(LaplacianType2Stencil);
00904   createMmatType2(MassType2Stencil);
00905   createRHSType2(RHSType2Stencil);
00906 
00907   // here will be stored centers of "ALL" octants on this process;
00908   vector<double> centers;   
00909   
00910   // calculate centers for "ALL" octants (both pre-ghost and writable)
00911   CalculateCenters(damg[numMultigridLevels-1]->da, centers);
00912   
00913   // call user-provided function to sample the right-hand-side
00914   force_values.resize(centers.size()/3);
00915   CalcRHS(centers, force_values);
00916   
00917   // calculate PDE coef. for all levels. This calls user-provided function CalcCoef
00918   SetPDECoefFromPts(damg, centers,CalcCoef); 
00919   
00920   // set up functions which do matvecs and compute right hand side
00921   ot::DAMGSetKSP(damg, CreateJacobian2,ComputeJacobian2,ComputeRHS_omgNeumann);
00922   
00923   // solve (using zero initial guess -- this is the default)
00924   ot::DAMGSolve(damg);
00925 
00926   // get the solution
00927   sol = DAMGGetx(damg);
00928   
00929   // destroy objects 
00930   destroyLmatType2(LaplacianType2Stencil);
00931   destroyMmatType2(MassType2Stencil);
00932   destroyRHSType2(RHSType2Stencil);
00933   DestroyUserContexts(damg);
00934 
00935   return;
00936 }
00937 
00949 void solve_neumann_oct(
00950     /* input parameters: */
00951      std::vector<ot::TreeNode>& octs,
00952      void (*CalcCoef)(const std::vector<double> & pts, std::vector<double> & values),
00953      void (*CalcRHS)(const std::vector<double> & pts, std::vector<double> & values),
00954      int numMultigridLevels,
00955      /* output parameters */
00956      Vec& sol,
00957      ot::DAMG * & damg
00958     )
00959 {
00960   using namespace std;
00961   
00962   const int dim = 3;
00963   double gSize[3]={1.0, 1.0, 1.0};
00964   const double mgLoadFac = 1.5;
00965   const bool compressLut = false;
00966   const bool incCorner = true; 
00967   const int maxDepth = octs[0].getMaxDepth();
00968   const int dof=1;
00969 
00970 
00971   int size, rank;
00972   MPI_Comm_size(MPI_COMM_WORLD,&size);
00973   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
00974   
00975   // complete the octree 
00976   vector<ot::TreeNode> linOct;
00977   ot::completeOctree(octs, linOct, 3 /*dim*/,
00978       maxDepth,
00979       true, /* isUnique */
00980       false, /* isSorted */
00981       false, /* assertNoEmptyProcs */
00982       MPI_COMM_WORLD);
00983   octs.clear();
00984     
00985   //now balance the octree; "linOct" is cleared inside this function
00986   vector<ot::TreeNode> balOct;
00987   ot::balanceOctree (linOct, balOct, dim, maxDepth, true, MPI_COMM_WORLD, NULL, NULL);
00988   
00989   // debug 
00990   // balOct.clear();
00991   // createRegularOctree(balOct,7,3,maxDepth,MPI_COMM_WORLD);
00992   
00993   // debug -- print octree to file
00994   // writeNodesToFile ("the_tree.ot", balOct);
00995   
00996   // print how many finest-level octants we have
00997   DendroIntL locBalSize = balOct.size();
00998   DendroIntL totBalSize;
00999   par::Mpi_Reduce<DendroIntL>(&locBalSize, &totBalSize, 1, MPI_SUM, 0, MPI_COMM_WORLD);
01000   if(!rank) {
01001     cout << "# of octants on finest level: "<< totBalSize << endl; 
01002   }
01003   
01004   // create multigrid solver object, coarser octrees, finite element meshes and the interpolation
01005   // balOct is cleared inside this function
01006   // numMultigridLevels might be modified inside this function
01007   ot::DAMGCreateAndSetDA(MPI_COMM_WORLD,numMultigridLevels, NULL, &damg, balOct,
01008       dof, mgLoadFac, compressLut, incCorner);
01009 
01010   // set some options to make "CreateJacobian2" and "ComputeJacobian2" work. These routines are related to matrix-vector multiplication on all levels.
01011   PetscOptionsSetValue("-jacType","2");
01012   
01013   // load stencils, i.e. integrals of: products of gradients of shape functions, product of shape functions and shape functions themselves
01014   createLmatType2(LaplacianType2Stencil);
01015   createMmatType2(MassType2Stencil);
01016   createRHSType2(RHSType2Stencil);
01017 
01018   // here will be stored centers of "ALL" octants on this process;
01019   vector<double> centers;   
01020   
01021   // calculate centers for "ALL" octants (both pre-ghost and writable)
01022   CalculateCenters(damg[numMultigridLevels-1]->da, centers);
01023   
01024   // call user-provided function to sample the right-hand-side
01025   force_values.resize(centers.size()/3);
01026   CalcRHS(centers, force_values);
01027   
01028   // calculate PDE coef. for all levels. This calls user-provided function CalcCoef
01029   SetPDECoefFromPts(damg, centers,CalcCoef); 
01030   
01031   // set up functions which do matvecs and compute right hand side
01032   ot::DAMGSetKSP(damg, CreateJacobian2,ComputeJacobian2,ComputeRHS_omgNeumann);
01033   
01034   // solve (using zero initial guess -- this is the default)
01035   ot::DAMGSolve(damg);
01036 
01037   // get the solution
01038   sol = DAMGGetx(damg);
01039   
01040   // destroy objects 
01041   destroyLmatType2(LaplacianType2Stencil);
01042   destroyMmatType2(MassType2Stencil);
01043   destroyRHSType2(RHSType2Stencil);
01044   DestroyUserContexts(damg);
01045 
01046   return;
01047 }
01048 

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