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

omgJac.C

Go to the documentation of this file.
00001 
00007 #include "petsc.h"
00008 #include "petscmat.h"
00009 #include "petscvec.h"
00010 #include "omg.h"
00011 #include "oda.h"
00012 #include "omgJac.h"
00013 #include "odaJac.h"
00014 
00015 #ifdef PETSC_USE_LOG
00016 extern int Jac2MultEvent;
00017 extern int Jac2DiagEvent;
00018 extern int Jac2FinestMultEvent;
00019 extern int Jac2FinestDiagEvent;
00020 
00021 extern int Jac3MultEvent;
00022 extern int Jac3DiagEvent;
00023 extern int Jac3FinestMultEvent;
00024 extern int Jac3FinestDiagEvent;
00025 #endif
00026 
00027 extern double***** LaplacianType1Stencil; 
00028 extern double***** MassType1Stencil; 
00029 
00030 extern double**** LaplacianType2Stencil; 
00031 extern double**** MassType2Stencil; 
00032 
00033 PetscErrorCode CreateTmpDirichletLaplacian(ot::DAMG damg, Mat *jac) {
00034   PetscFunctionBegin;
00035   ot::DA* da = damg->da;
00036   //The size this processor owns ( without ghosts).
00037   unsigned int  m,n;
00038   m=n=da->getNodeSize();
00039 
00040   MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00041   MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) TmpDirichletLaplacianMatMult);
00042   MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletLaplacianMatDestroy);
00043 
00044   PetscFunctionReturn(0);
00045 }//end fn.
00046 
00047 PetscErrorCode CreateTmpDirichletJacobian(ot::DAMG damg, Mat *jac) {
00048   PetscFunctionBegin;
00049   ot::DA* da = damg->da;
00050   //The size this processor owns ( without ghosts).
00051   unsigned int  m,n;
00052   m=n=da->getNodeSize();
00053 
00054   MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00055   MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) TmpDirichletJacobianMatMult);
00056   MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletJacobianMatDestroy);
00057 
00058   PetscFunctionReturn(0);
00059 }//end fn.
00060 
00061 PetscErrorCode CreateDirichletLaplacian(ot::DAMG damg, Mat *jac) {
00062   PetscFunctionBegin;
00063   int totalLevels;
00064   PetscTruth flg;
00065   PetscInt buildFullCoarseMat;
00066   PetscInt buildFullMatAll;
00067   PetscOptionsGetInt(PETSC_NULL,"-buildFullMatAll",&buildFullMatAll,&flg);
00068   PetscOptionsGetInt(PETSC_NULL,"-buildFullCoarseMat",&buildFullCoarseMat,&flg);
00069   if(buildFullMatAll) {
00070     buildFullCoarseMat = 1;
00071   }
00072   totalLevels = damg->totalLevels;
00073   ot::DA* da = damg->da;
00074   int myRank;
00075   MPI_Comm_rank(da->getComm(),&myRank);
00076   //The size this processor owns ( without ghosts).
00077   unsigned int  m,n;
00078   m=n=da->getNodeSize();
00079   if(totalLevels == damg->nlevels) {
00080     //This is the coarsest.
00081     if( (!myRank) && buildFullCoarseMat ) {
00082       std::cout<<"Building Full Coarse Mat."<<std::endl;
00083     }
00084     char matType[30];
00085     if(buildFullCoarseMat) {
00086       if(!(da->computedLocalToGlobal())) {
00087         da->computeLocalToGlobalMappings();
00088       }
00089       PetscTruth typeFound;
00090       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00091       if(!typeFound) {
00092         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00093         assert(false);
00094       } 
00095     }
00096     bool requirePrivateMats = (da->getNpesActive() != da->getNpesAll());    
00097     if(requirePrivateMats ) {
00098       DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00099       if(da->iAmActive()) {
00100         if(buildFullCoarseMat) {
00101           da->createActiveMatrix(data->Jmat_private, matType, 1);
00102         } else {
00103           MatCreateShell(da->getCommActive(), m, n, PETSC_DETERMINE,
00104               PETSC_DETERMINE, damg, &(data->Jmat_private));
00105           MatShellSetOperation(data->Jmat_private, MATOP_MULT,
00106               (void (*)(void)) DirichletLaplacianMatMult);
00107           MatShellSetOperation(data->Jmat_private, MATOP_GET_DIAGONAL,
00108               (void (*)(void)) DirichletLaplacianMatGetDiagonal);
00109           MatShellSetOperation(data->Jmat_private, MATOP_DESTROY,
00110               (void (*)(void)) DirichletLaplacianMatDestroy);
00111         }
00112         MatGetVecs(data->Jmat_private, &(data->inTmp), &(data->outTmp));
00113       } else {
00114         data->Jmat_private = NULL;
00115         data->inTmp = NULL;
00116         data->outTmp = NULL;
00117       }
00118       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00119       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletLaplacianMatDestroy);
00120       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) DirichletLaplacianShellMatMult);
00121     } else {
00122       if(buildFullCoarseMat) {
00123         da->createMatrix(*jac, matType, 1);
00124       } else {
00125         MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00126         MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) DirichletLaplacianMatMult);
00127         MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) DirichletLaplacianMatGetDiagonal);
00128         MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletLaplacianMatDestroy);
00129       }
00130     }
00131     if((!myRank) && buildFullCoarseMat) {
00132       std::cout<<"Finished Building Full Coarse Mat."<<std::endl;
00133     }
00134   } else {
00135     //This is some finer level.
00136     if(buildFullMatAll) {
00137       if(!myRank) {
00138         std::cout<<"Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
00139       }
00140       if(!(da->computedLocalToGlobal())) {
00141         da->computeLocalToGlobalMappings();
00142       }
00143       char matType[30];
00144       PetscTruth typeFound;
00145       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00146       if(!typeFound) {
00147         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00148         assert(false);
00149       } 
00150       da->createMatrix(*jac, matType, 1);
00151       if(!myRank) {
00152         std::cout<<"Finished Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
00153       }
00154     } else {
00155       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00156       MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) DirichletLaplacianMatMult);
00157       MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) DirichletLaplacianMatGetDiagonal);
00158       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletLaplacianMatDestroy);
00159     }
00160   }
00161 
00162   PetscFunctionReturn(0);
00163 }//end fn.
00164 
00165 
00166 PetscErrorCode CreateDirichletJacobian(ot::DAMG damg, Mat *jac) {
00167   PetscFunctionBegin;
00168   int totalLevels;
00169   PetscTruth flg;
00170   PetscInt buildFullCoarseMat;
00171   PetscInt buildFullMatAll;
00172   PetscOptionsGetInt(PETSC_NULL,"-buildFullMatAll",&buildFullMatAll,&flg);
00173   PetscOptionsGetInt(PETSC_NULL,"-buildFullCoarseMat",&buildFullCoarseMat,&flg);
00174   if(buildFullMatAll) {
00175     buildFullCoarseMat = 1;
00176   }
00177   totalLevels = damg->totalLevels;
00178   ot::DA* da = damg->da;
00179   int myRank;
00180   MPI_Comm_rank(da->getComm(),&myRank);
00181   //The size this processor owns ( without ghosts).
00182   unsigned int  m,n;
00183   m=n=da->getNodeSize();
00184   if(totalLevels == damg->nlevels) {
00185     //This is the coarsest.
00186     if( (!myRank) && buildFullCoarseMat ) {
00187       std::cout<<"Building Full Coarse Mat."<<std::endl;
00188     }
00189     char matType[30];
00190     if(buildFullCoarseMat) {
00191       if(!(da->computedLocalToGlobal())) {
00192         da->computeLocalToGlobalMappings();
00193       }
00194       PetscTruth typeFound;
00195       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00196       if(!typeFound) {
00197         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00198         assert(false);
00199       } 
00200     }
00201     bool requirePrivateMats = (da->getNpesActive() != da->getNpesAll());    
00202     if(requirePrivateMats ) {
00203       DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00204       if(da->iAmActive()) {
00205         if(buildFullCoarseMat) {
00206           da->createActiveMatrix(data->Jmat_private, matType, 1);
00207         } else {
00208           MatCreateShell(da->getCommActive(), m, n, PETSC_DETERMINE,
00209               PETSC_DETERMINE, damg, &(data->Jmat_private));
00210           MatShellSetOperation(data->Jmat_private, MATOP_MULT,
00211               (void (*)(void)) DirichletJacobianMatMult);
00212           MatShellSetOperation(data->Jmat_private, MATOP_GET_DIAGONAL,
00213               (void (*)(void)) DirichletJacobianMatGetDiagonal);
00214           MatShellSetOperation(data->Jmat_private, MATOP_DESTROY,
00215               (void (*)(void)) DirichletJacobianMatDestroy);
00216         }
00217         MatGetVecs(data->Jmat_private, &(data->inTmp), &(data->outTmp));
00218       } else {
00219         data->Jmat_private = NULL;
00220         data->inTmp = NULL;
00221         data->outTmp = NULL;
00222       }
00223       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00224       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletJacobianMatDestroy);
00225       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) DirichletJacobianShellMatMult);
00226     } else {
00227       if(buildFullCoarseMat) {
00228         da->createMatrix(*jac, matType, 1);
00229       } else {
00230         MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00231         MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) DirichletJacobianMatMult);
00232         MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) DirichletJacobianMatGetDiagonal);
00233         MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletJacobianMatDestroy);
00234       }
00235     }
00236     if((!myRank) && buildFullCoarseMat) {
00237       std::cout<<"Finished Building Full Coarse Mat."<<std::endl;
00238     }
00239   } else {
00240     //This is some finer level.
00241     if(buildFullMatAll) {
00242       if(!myRank) {
00243         std::cout<<"Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
00244       }
00245       if(!(da->computedLocalToGlobal())) {
00246         da->computeLocalToGlobalMappings();
00247       }
00248       char matType[30];
00249       PetscTruth typeFound;
00250       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00251       if(!typeFound) {
00252         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00253         assert(false);
00254       } 
00255       da->createMatrix(*jac, matType, 1);
00256       if(!myRank) {
00257         std::cout<<"Finished Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
00258       }
00259     } else {
00260       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
00261       MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) DirichletJacobianMatMult);
00262       MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) DirichletJacobianMatGetDiagonal);
00263       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) DirichletJacobianMatDestroy);
00264     }
00265   }
00266 
00267   PetscFunctionReturn(0);
00268 }//end fn.
00269 
00270 PetscErrorCode ComputeDirichletLaplacian(ot::DAMG damg, Mat J, Mat B) {
00271   //For matShells nothing to be done here.
00272   PetscFunctionBegin;
00273 
00274   PetscTruth isshell;
00275   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
00276 
00277   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00278 
00279   assert(B == J);
00280 
00281   if(isshell) {
00282     if( data->Jmat_private == NULL ) {
00283       PetscFunctionReturn(0);
00284     } else {
00285       J = data->Jmat_private;
00286       B = data->Jmat_private;
00287     }
00288   }
00289 
00290   //B and J are the same.
00291 
00292   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
00293   if(isshell) {
00294     //Nothing to be done here.
00295     PetscFunctionReturn(0);
00296   }
00297 
00298   ot::DA* da = damg->da;
00299 
00300   MatZeroEntries(B);
00301 
00302   std::vector<ot::MatRecord> records;
00303 
00304   unsigned int maxD;
00305   double hFac;
00306   if(da->iAmActive()) {
00307     maxD = da->getMaxDepth();
00308     hFac = 1.0/((double)(1u << (maxD-1)));
00309   }
00310 
00311   unsigned char* bdyArr = data->bdyArr;
00312 
00313   if(da->iAmActive()) {
00314     for(da->init<ot::DA_FLAGS::WRITABLE>();
00315         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();
00316         da->next<ot::DA_FLAGS::WRITABLE>()) {
00317       unsigned int idx = da->curr();
00318       unsigned int lev = da->getLevel(idx);
00319       double h = hFac*(1u << (maxD - lev));
00320       double fac1 = h/2.0;
00321       unsigned int indices[8];
00322       da->getNodeIndices(indices);
00323       unsigned char childNum = da->getChildNumber();
00324       unsigned char hnMask = da->getHangingNodeIndex(idx);
00325       unsigned char elemType = 0;
00326       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00327         for(int k = 0; k < 8; k++) {
00328           if(!(bdyArr[indices[k]])) {
00329             for(int j = 0; j < 8; j++) {
00330               if(!(bdyArr[indices[j]])) {
00331                 ot::MatRecord currRec;
00332                 currRec.rowIdx = indices[k];
00333                 currRec.colIdx = indices[j];
00334                 currRec.rowDim = 0;
00335                 currRec.colDim = 0;
00336                 currRec.val = (fac1*(LaplacianType2Stencil[childNum][elemType][k][j]));
00337                 records.push_back(currRec);
00338               }
00339             } /*end for j*/
00340           }
00341         } /*end for k*/
00342       if(records.size() > 1000) {
00343         /*records will be cleared inside the function*/
00344         da->setValuesInMatrix(B, records, 1, ADD_VALUES);
00345       }
00346     } /*end writable*/
00347   } /*end if active*/
00348   da->setValuesInMatrix(B, records, 1, ADD_VALUES);
00349   MatAssemblyBegin(B, MAT_FLUSH_ASSEMBLY);
00350   MatAssemblyEnd(B, MAT_FLUSH_ASSEMBLY);
00351 
00352   if(da->iAmActive()) {
00353     for(da->init<ot::DA_FLAGS::WRITABLE>();
00354         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();
00355         da->next<ot::DA_FLAGS::WRITABLE>()) {
00356       unsigned int indices[8];
00357       da->getNodeIndices(indices);
00358       for(int k = 0; k < 8; k++) {
00359         if(bdyArr[indices[k]]) {
00360           ot::MatRecord currRec;
00361           currRec.rowIdx = indices[k];
00362           currRec.colIdx = indices[k];
00363           currRec.rowDim = 0;
00364           currRec.colDim = 0;
00365           currRec.val = 1.0;
00366           records.push_back(currRec);
00367         }
00368       } /*end for k*/
00369       if(records.size() > 1000) {
00370         /*records will be cleared inside the function*/
00371         da->setValuesInMatrix(B, records, 1, INSERT_VALUES);
00372       }
00373     } /*end writable*/
00374   } /*end if active*/
00375   da->setValuesInMatrix(B, records, 1, INSERT_VALUES);
00376   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
00377   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
00378 
00379   PetscFunctionReturn(0);
00380 }
00381 
00382 PetscErrorCode ComputeDirichletJacobian(ot::DAMG damg, Mat J, Mat B) {
00383   //For matShells nothing to be done here.
00384   PetscFunctionBegin;
00385 
00386   PetscTruth isshell;
00387   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
00388 
00389   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00390 
00391   assert(B == J);
00392 
00393   if(isshell) {
00394     if( data->Jmat_private == NULL ) {
00395       PetscFunctionReturn(0);
00396     } else {
00397       J = data->Jmat_private;
00398       B = data->Jmat_private;
00399     }
00400   }
00401 
00402   //B and J are the same.
00403 
00404   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
00405   if(isshell) {
00406     //Nothing to be done here.
00407     PetscFunctionReturn(0);
00408   }
00409 
00410   ot::DA* da = damg->da;
00411 
00412   MatZeroEntries(B);
00413 
00414   std::vector<ot::MatRecord> records;
00415 
00416   unsigned int maxD;
00417   double hFac;
00418   if(da->iAmActive()) {
00419     maxD = da->getMaxDepth();
00420     hFac = 1.0/((double)(1u << (maxD-1)));
00421   }
00422 
00423   unsigned char* bdyArr = data->bdyArr;
00424 
00425   if(da->iAmActive()) {
00426     for(da->init<ot::DA_FLAGS::WRITABLE>();
00427         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();
00428         da->next<ot::DA_FLAGS::WRITABLE>()) {
00429       unsigned int idx = da->curr();
00430       unsigned int lev = da->getLevel(idx);
00431       double h = hFac*(1u << (maxD - lev));
00432       double fac1 = h/2.0;
00433       double fac2 = h*h*h/8.0;
00434       unsigned int indices[8];
00435       da->getNodeIndices(indices);
00436       unsigned char childNum = da->getChildNumber();
00437       unsigned char hnMask = da->getHangingNodeIndex(idx);
00438       unsigned char elemType = 0;
00439       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00440         for(int k = 0; k < 8; k++) {
00441           if(!(bdyArr[indices[k]])) {
00442             for(int j = 0; j < 8; j++) {
00443               if(!(bdyArr[indices[j]])) {
00444                 ot::MatRecord currRec;
00445                 currRec.rowIdx = indices[k];
00446                 currRec.colIdx = indices[j];
00447                 currRec.rowDim = 0;
00448                 currRec.colDim = 0;
00449                 currRec.val = ((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
00450                     (fac2*(MassType2Stencil[childNum][elemType][k][j])));
00451                 records.push_back(currRec);
00452               }
00453             } /*end for j*/
00454           }
00455         } /*end for k*/
00456       if(records.size() > 1000) {
00457         /*records will be cleared inside the function*/
00458         da->setValuesInMatrix(B, records, 1, ADD_VALUES);
00459       }
00460     } /*end writable*/
00461   } /*end if active*/
00462   da->setValuesInMatrix(B, records, 1, ADD_VALUES);
00463   MatAssemblyBegin(B, MAT_FLUSH_ASSEMBLY);
00464   MatAssemblyEnd(B, MAT_FLUSH_ASSEMBLY);
00465 
00466   if(da->iAmActive()) {
00467     for(da->init<ot::DA_FLAGS::WRITABLE>();
00468         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();
00469         da->next<ot::DA_FLAGS::WRITABLE>()) {
00470       unsigned int indices[8];
00471       da->getNodeIndices(indices);
00472       for(int k = 0; k < 8; k++) {
00473         if(bdyArr[indices[k]]) {
00474           ot::MatRecord currRec;
00475           currRec.rowIdx = indices[k];
00476           currRec.colIdx = indices[k];
00477           currRec.rowDim = 0;
00478           currRec.colDim = 0;
00479           currRec.val = 1.0;
00480           records.push_back(currRec);
00481         }
00482       } /*end for k*/
00483       if(records.size() > 1000) {
00484         /*records will be cleared inside the function*/
00485         da->setValuesInMatrix(B, records, 1, INSERT_VALUES);
00486       }
00487     } /*end writable*/
00488   } /*end if active*/
00489   da->setValuesInMatrix(B, records, 1, INSERT_VALUES);
00490   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);
00491   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);
00492 
00493   PetscFunctionReturn(0);
00494 }
00495 
00496 PetscErrorCode DirichletLaplacianMatDestroy(Mat J) {
00497   PetscFunctionBegin;
00498   //Nothing to be done here. 
00499   PetscFunctionReturn(0);
00500 }
00501 
00502 PetscErrorCode DirichletJacobianMatDestroy(Mat J) {
00503   PetscFunctionBegin;
00504   //Nothing to be done here. 
00505   PetscFunctionReturn(0);
00506 }
00507 
00508 void SetDirichletJacContexts(ot::DAMG* damg) {
00509   int       nlevels = damg[0]->nlevels; //number of multigrid levels
00510   for(int i = 0; i < nlevels; i++) {
00511     DirichletJacData* ctx= new DirichletJacData;
00512     ctx->bdyArr = NULL;
00513     ctx->Jmat_private = NULL;
00514     ctx->inTmp = NULL;
00515     ctx->outTmp = NULL;
00516 
00517     std::vector<unsigned char> tmpBdyFlags;
00518     std::vector<unsigned char> tmpBdyFlagsAux;
00519     unsigned char* bdyArrAux = NULL;
00520 
00521     //This will create a nodal, non-ghosted, 1 dof array
00522     assignBoundaryFlags(damg[i]->da, tmpBdyFlags);
00523     ((damg[i])->da)->vecGetBuffer<unsigned char>(tmpBdyFlags, ctx->bdyArr, false, false, true, 1);
00524     if(damg[i]->da->iAmActive()) {
00525       ((damg[i])->da)->ReadFromGhostsBegin<unsigned char>(ctx->bdyArr, 1);
00526     }
00527 
00528     if(damg[i]->da_aux) {
00529       assignBoundaryFlags( damg[i]->da_aux, tmpBdyFlagsAux);
00530       ((damg[i])->da_aux)->vecGetBuffer<unsigned char>(tmpBdyFlagsAux, bdyArrAux,
00531         false, false, true, 1);
00532       if(damg[i]->da_aux->iAmActive()) {
00533         ((damg[i])->da_aux)->ReadFromGhostsBegin<unsigned char>(bdyArrAux, 1);
00534       }
00535     }
00536 
00537     tmpBdyFlags.clear();
00538     tmpBdyFlagsAux.clear();
00539 
00540     if(damg[i]->da->iAmActive()) {
00541       ((damg[i])->da)->ReadFromGhostsEnd<unsigned char>(ctx->bdyArr);
00542     }
00543 
00544     if((damg[i])->da_aux) {
00545       if(damg[i]->da_aux->iAmActive()) {
00546         ((damg[i])->da_aux)->ReadFromGhostsEnd<unsigned char>(bdyArrAux);
00547       }
00548     }
00549 
00550     for(int loopCtr = 0; loopCtr < 2; loopCtr++) {
00551       ot::DA* da = NULL;
00552       unsigned char* suppressedDOFptr = NULL;
00553       unsigned char* bdyArrPtr = NULL;
00554       if(loopCtr == 0) {
00555         da = damg[i]->da;
00556         suppressedDOFptr = damg[i]->suppressedDOF;
00557         bdyArrPtr = ctx->bdyArr;
00558       } else {
00559         da = damg[i]->da_aux;
00560         suppressedDOFptr = damg[i]->suppressedDOFaux;
00561         bdyArrPtr = bdyArrAux;
00562       }
00563       if(da) {
00564         if(da->iAmActive()) {
00565           for(da->init<ot::DA_FLAGS::ALL>(); 
00566               da->curr() < da->end<ot::DA_FLAGS::ALL>();
00567               da->next<ot::DA_FLAGS::ALL>()) {
00568             unsigned int indices[8];
00569             da->getNodeIndices(indices);
00570             for(unsigned int k = 0; k < 8; k++) {
00571               suppressedDOFptr[indices[k]] = bdyArrPtr[indices[k]];
00572             }
00573           }
00574         }
00575       }
00576     }
00577 
00578     if(bdyArrAux) {
00579       delete [] bdyArrAux;
00580       bdyArrAux = NULL;
00581     }
00582 
00583     (damg[i])->user = ctx;
00584   }//end for i
00585 
00586 }//end fn.
00587 
00588 void DestroyDirichletJacContexts(ot::DAMG* damg) {
00589   int nlevels = damg[0]->nlevels; //number of multigrid levels
00590   for(int i = 0; i < nlevels; i++) {
00591     DirichletJacData* ctx = (static_cast<DirichletJacData*>(damg[i]->user));
00592     if(ctx->bdyArr) {
00593       delete [] (ctx->bdyArr);
00594       ctx->bdyArr = NULL;
00595     }
00596     if(ctx->Jmat_private) {
00597       MatDestroy(ctx->Jmat_private);
00598       ctx->Jmat_private = NULL;
00599     }
00600     if(ctx->inTmp) {
00601       VecDestroy(ctx->inTmp);
00602       ctx->inTmp = NULL;
00603     }
00604     if(ctx->outTmp) {
00605       VecDestroy(ctx->outTmp);
00606       ctx->outTmp = NULL;
00607     }
00608     delete ctx;
00609     ctx = NULL;
00610   }
00611 }//end fn.
00612 
00613 PetscErrorCode DirichletLaplacianShellMatMult(Mat J, Vec in, Vec out) {
00614   PetscFunctionBegin;
00615 
00616   ot::DAMG damg;
00617 
00618   MatShellGetContext(J, (void**)(&damg));
00619 
00620   DirichletJacData* ctx = static_cast<DirichletJacData*>(damg->user);
00621 
00622   if(damg->da->iAmActive()) {      
00623     PetscScalar* inArray;
00624     PetscScalar* outArray;
00625 
00626     VecGetArray(in, &inArray);
00627     VecGetArray(out, &outArray);
00628 
00629     VecPlaceArray(ctx->inTmp, inArray);
00630     VecPlaceArray(ctx->outTmp, outArray);
00631 
00632     MatMult(ctx->Jmat_private, ctx->inTmp, ctx->outTmp);
00633 
00634     VecResetArray(ctx->inTmp);
00635     VecResetArray(ctx->outTmp);
00636 
00637     VecRestoreArray(in, &inArray);
00638     VecRestoreArray(out, &outArray);
00639   }
00640 
00641   PetscFunctionReturn(0);
00642 }
00643 
00644 PetscErrorCode DirichletJacobianShellMatMult(Mat J, Vec in, Vec out) {
00645   PetscFunctionBegin;
00646 
00647   ot::DAMG damg;
00648 
00649   MatShellGetContext(J, (void**)(&damg));
00650 
00651   DirichletJacData* ctx = static_cast<DirichletJacData*>(damg->user);
00652 
00653   if(damg->da->iAmActive()) {      
00654     PetscScalar* inArray;
00655     PetscScalar* outArray;
00656 
00657     VecGetArray(in, &inArray);
00658     VecGetArray(out, &outArray);
00659 
00660     VecPlaceArray(ctx->inTmp, inArray);
00661     VecPlaceArray(ctx->outTmp, outArray);
00662 
00663     MatMult(ctx->Jmat_private, ctx->inTmp, ctx->outTmp);
00664 
00665     VecResetArray(ctx->inTmp);
00666     VecResetArray(ctx->outTmp);
00667 
00668     VecRestoreArray(in, &inArray);
00669     VecRestoreArray(out, &outArray);
00670   }
00671 
00672   PetscFunctionReturn(0);
00673 }
00674 
00675 PetscErrorCode TmpDirichletLaplacianMatMult(Mat J, Vec in, Vec out) {
00676   PetscFunctionBegin;
00677 
00678   ot::DAMG damg;
00679   iC(MatShellGetContext(J, (void**)(&damg)));
00680 
00681   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00682 
00683   unsigned char* bdyArr = data->bdyArr;
00684 
00685   ot::DA* da = damg->da;
00686 
00687   iC(VecZeroEntries(out));
00688 
00689   unsigned int maxD;
00690   double hFac;
00691   if(da->iAmActive()) {
00692     maxD = da->getMaxDepth();
00693     hFac = 1.0/((double)(1u << (maxD-1)));
00694   }
00695 
00696   PetscScalar *outArr=NULL;
00697   PetscScalar *inArr=NULL;
00698 
00699   /*Nodal,Non-Ghosted,Read,1 dof*/
00700   da->vecGetBuffer(in,inArr,false,false,true,1);
00701 
00702   /*Nodal,Non-Ghosted,Write,1 dof*/
00703   da->vecGetBuffer(out,outArr,false,false,false,1);
00704 
00705   if(da->iAmActive()) {
00706 
00707     da->ReadFromGhostsBegin<PetscScalar>(inArr,1);
00708 
00709     for(da->init<ot::DA_FLAGS::INDEPENDENT>();
00710         da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();
00711         da->next<ot::DA_FLAGS::INDEPENDENT>() ) {
00712       unsigned int idx = da->curr();
00713       unsigned int lev = da->getLevel(idx);
00714       double h = hFac*(1u << (maxD - lev));
00715       double fac1 = h/2.0;
00716       unsigned int indices[8];
00717       da->getNodeIndices(indices);
00718       unsigned char childNum = da->getChildNumber();
00719       unsigned char hnMask = da->getHangingNodeIndex(idx);
00720       unsigned char elemType = 0;
00721       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00722         for(int k = 0; k < 8; k++) {
00723           if(!bdyArr[indices[k]]) {
00724             for(int j = 0; j < 8; j++) {
00725               outArr[indices[k]] += (fac1*LaplacianType2Stencil[childNum][elemType][k][j]*inArr[indices[j]]);
00726             }/*end for j*/
00727           }
00728         }/*end for k*/
00729     } /*end independent*/
00730 
00731     da->ReadFromGhostsEnd<PetscScalar>(inArr);
00732 
00733     for(da->init<ot::DA_FLAGS::DEPENDENT>();
00734         da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>();
00735         da->next<ot::DA_FLAGS::DEPENDENT>() ) {
00736       unsigned int idx = da->curr();
00737       unsigned int lev = da->getLevel(idx);
00738       double h = hFac*(1u << (maxD - lev));
00739       double fac1 = h/2.0;
00740       double fac2 = h*h*h/8.0;
00741       unsigned int indices[8];
00742       da->getNodeIndices(indices);
00743       unsigned char childNum = da->getChildNumber();
00744       unsigned char hnMask = da->getHangingNodeIndex(idx);
00745       unsigned char elemType = 0;
00746       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00747         for(int k = 0; k < 8; k++) {
00748           if(!bdyArr[indices[k]]) {
00749             for(int j = 0; j < 8; j++) {
00750               outArr[indices[k]] += (fac1*LaplacianType2Stencil[childNum][elemType][k][j]*inArr[indices[j]]);
00751             }/*end for j*/
00752           }
00753         }/*end for k*/
00754     } /*end loop for dependent elems*/
00755 
00756   } /*end if active*/
00757 
00758   da->vecRestoreBuffer(in,inArr,false,false,true,1);
00759 
00760   da->vecRestoreBuffer(out,outArr,false,false,false,1);
00761 
00762   PetscFunctionReturn(0);
00763 }
00764 
00765 
00766 PetscErrorCode TmpDirichletJacobianMatMult(Mat J, Vec in, Vec out) {
00767   PetscFunctionBegin;
00768 
00769   ot::DAMG damg;
00770   iC(MatShellGetContext(J, (void**)(&damg)));
00771 
00772   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00773 
00774   unsigned char* bdyArr = data->bdyArr;
00775 
00776   ot::DA* da = damg->da;
00777 
00778   iC(VecZeroEntries(out));
00779 
00780   unsigned int maxD;
00781   double hFac;
00782   if(da->iAmActive()) {
00783     maxD = da->getMaxDepth();
00784     hFac = 1.0/((double)(1u << (maxD-1)));
00785   }
00786 
00787   PetscScalar *outArr=NULL;
00788   PetscScalar *inArr=NULL;
00789 
00790   /*Nodal,Non-Ghosted,Read,1 dof*/
00791   da->vecGetBuffer(in,inArr,false,false,true,1);
00792 
00793   /*Nodal,Non-Ghosted,Write,1 dof*/
00794   da->vecGetBuffer(out,outArr,false,false,false,1);
00795 
00796   if(da->iAmActive()) {
00797 
00798     da->ReadFromGhostsBegin<PetscScalar>(inArr,1);
00799 
00800     for(da->init<ot::DA_FLAGS::INDEPENDENT>();
00801         da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();
00802         da->next<ot::DA_FLAGS::INDEPENDENT>() ) {
00803       unsigned int idx = da->curr();
00804       unsigned int lev = da->getLevel(idx);
00805       double h = hFac*(1u << (maxD - lev));
00806       double fac1 = h/2.0;
00807       double fac2 = h*h*h/8.0;
00808       unsigned int indices[8];
00809       da->getNodeIndices(indices);
00810       unsigned char childNum = da->getChildNumber();
00811       unsigned char hnMask = da->getHangingNodeIndex(idx);
00812       unsigned char elemType = 0;
00813       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00814         for(int k = 0; k < 8; k++) {
00815           if(!bdyArr[indices[k]]) {
00816             for(int j = 0; j < 8; j++) {
00817               outArr[indices[k]] +=  (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
00818                     (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);
00819             }/*end for j*/
00820           }
00821         }/*end for k*/
00822     } /*end independent*/
00823 
00824     da->ReadFromGhostsEnd<PetscScalar>(inArr);
00825 
00826     for(da->init<ot::DA_FLAGS::DEPENDENT>();
00827         da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>();
00828         da->next<ot::DA_FLAGS::DEPENDENT>() ) {
00829       unsigned int idx = da->curr();
00830       unsigned int lev = da->getLevel(idx);
00831       double h = hFac*(1u << (maxD - lev));
00832       double fac1 = h/2.0;
00833       double fac2 = h*h*h/8.0;
00834       unsigned int indices[8];
00835       da->getNodeIndices(indices);
00836       unsigned char childNum = da->getChildNumber();
00837       unsigned char hnMask = da->getHangingNodeIndex(idx);
00838       unsigned char elemType = 0;
00839       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00840         for(int k = 0; k < 8; k++) {
00841           if(!bdyArr[indices[k]]) {
00842             for(int j = 0; j < 8; j++) {
00843               outArr[indices[k]] +=  (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
00844                     (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);
00845             }/*end for j*/
00846           }
00847         }/*end for k*/
00848     } /*end loop for dependent elems*/
00849 
00850   } /*end if active*/
00851 
00852   da->vecRestoreBuffer(in,inArr,false,false,true,1);
00853 
00854   da->vecRestoreBuffer(out,outArr,false,false,false,1);
00855 
00856   PetscFunctionReturn(0);
00857 }
00858 
00859 PetscErrorCode DirichletLaplacianMatMult(Mat J, Vec in, Vec out) {
00860   PetscFunctionBegin;
00861 
00862   ot::DAMG damg;
00863   iC(MatShellGetContext(J, (void**)(&damg)));
00864 
00865   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00866 
00867   unsigned char* bdyArr = data->bdyArr;
00868 
00869   ot::DA* da = damg->da;
00870 
00871   iC(VecZeroEntries(out));
00872 
00873   unsigned int maxD;
00874   double hFac;
00875   if(da->iAmActive()) {
00876     maxD = da->getMaxDepth();
00877     hFac = 1.0/((double)(1u << (maxD-1)));
00878   }
00879 
00880   PetscScalar *outArr=NULL;
00881   PetscScalar *inArr=NULL;
00882 
00883   /*Nodal,Non-Ghosted,Read,1 dof*/
00884   da->vecGetBuffer(in,inArr,false,false,true,1);
00885 
00886   /*Nodal,Non-Ghosted,Write,1 dof*/
00887   da->vecGetBuffer(out,outArr,false,false,false,1);
00888 
00889   if(da->iAmActive()) {
00890 
00891     da->ReadFromGhostsBegin<PetscScalar>(inArr,1);
00892 
00893     for(da->init<ot::DA_FLAGS::INDEPENDENT>();
00894         da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();
00895         da->next<ot::DA_FLAGS::INDEPENDENT>() ) {
00896       unsigned int idx = da->curr();
00897       unsigned int lev = da->getLevel(idx);
00898       double h = hFac*(1u << (maxD - lev));
00899       double fac1 = h/2.0;
00900       unsigned int indices[8];
00901       da->getNodeIndices(indices);
00902       unsigned char childNum = da->getChildNumber();
00903       unsigned char hnMask = da->getHangingNodeIndex(idx);
00904       unsigned char elemType = 0;
00905       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00906         for(int k = 0; k < 8; k++) {
00907           if(bdyArr[indices[k]]) {
00908             outArr[indices[k]] =  inArr[indices[k]];
00909           } else {
00910             for(int j = 0; j < 8; j++) {
00911               if(!bdyArr[indices[j]]) {
00912                 outArr[indices[k]] += (fac1*LaplacianType2Stencil[childNum][elemType][k][j]*inArr[indices[j]]);
00913               }
00914             }/*end for j*/
00915           }
00916         }/*end for k*/
00917     } /*end independent*/
00918 
00919     da->ReadFromGhostsEnd<PetscScalar>(inArr);
00920 
00921     for(da->init<ot::DA_FLAGS::DEPENDENT>();
00922         da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>();
00923         da->next<ot::DA_FLAGS::DEPENDENT>() ) {
00924       unsigned int idx = da->curr();
00925       unsigned int lev = da->getLevel(idx);
00926       double h = hFac*(1u << (maxD - lev));
00927       double fac1 = h/2.0;
00928       double fac2 = h*h*h/8.0;
00929       unsigned int indices[8];
00930       da->getNodeIndices(indices);
00931       unsigned char childNum = da->getChildNumber();
00932       unsigned char hnMask = da->getHangingNodeIndex(idx);
00933       unsigned char elemType = 0;
00934       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00935         for(int k = 0; k < 8; k++) {
00936           if(bdyArr[indices[k]]) {
00937             outArr[indices[k]] =  inArr[indices[k]];
00938           } else {
00939             for(int j = 0; j < 8; j++) {
00940               if(!bdyArr[indices[j]]) {
00941                 outArr[indices[k]] += (fac1*LaplacianType2Stencil[childNum][elemType][k][j]*inArr[indices[j]]);
00942               }
00943             }/*end for j*/
00944           }
00945         }/*end for k*/
00946     } /*end loop for dependent elems*/
00947 
00948   } /*end if active*/
00949 
00950   da->vecRestoreBuffer(in,inArr,false,false,true,1);
00951 
00952   da->vecRestoreBuffer(out,outArr,false,false,false,1);
00953 
00954   PetscFunctionReturn(0);
00955 }
00956 
00957 PetscErrorCode DirichletJacobianMatMult(Mat J, Vec in, Vec out) {
00958   PetscFunctionBegin;
00959 
00960   ot::DAMG damg;
00961   iC(MatShellGetContext(J, (void**)(&damg)));
00962 
00963   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
00964 
00965   unsigned char* bdyArr = data->bdyArr;
00966 
00967   ot::DA* da = damg->da;
00968 
00969   iC(VecZeroEntries(out));
00970 
00971   unsigned int maxD;
00972   double hFac;
00973   if(da->iAmActive()) {
00974     maxD = da->getMaxDepth();
00975     hFac = 1.0/((double)(1u << (maxD-1)));
00976   }
00977 
00978   PetscScalar *outArr=NULL;
00979   PetscScalar *inArr=NULL;
00980 
00981   /*Nodal,Non-Ghosted,Read,1 dof*/
00982   da->vecGetBuffer(in,inArr,false,false,true,1);
00983 
00984   /*Nodal,Non-Ghosted,Write,1 dof*/
00985   da->vecGetBuffer(out,outArr,false,false,false,1);
00986 
00987   if(da->iAmActive()) {
00988 
00989     da->ReadFromGhostsBegin<PetscScalar>(inArr,1);
00990 
00991     for(da->init<ot::DA_FLAGS::INDEPENDENT>();
00992         da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();
00993         da->next<ot::DA_FLAGS::INDEPENDENT>() ) {
00994       unsigned int idx = da->curr();
00995       unsigned int lev = da->getLevel(idx);
00996       double h = hFac*(1u << (maxD - lev));
00997       double fac1 = h/2.0;
00998       double fac2 = h*h*h/8.0;
00999       unsigned int indices[8];
01000       da->getNodeIndices(indices);
01001       unsigned char childNum = da->getChildNumber();
01002       unsigned char hnMask = da->getHangingNodeIndex(idx);
01003       unsigned char elemType = 0;
01004       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
01005         for(int k = 0; k < 8; k++) {
01006           if(bdyArr[indices[k]]) {
01007             outArr[indices[k]] =  inArr[indices[k]];
01008           } else {
01009             for(int j = 0; j < 8; j++) {
01010               if(!bdyArr[indices[j]]) {
01011                 outArr[indices[k]] +=  (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
01012                       (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);
01013               }
01014             }/*end for j*/
01015           }
01016         }/*end for k*/
01017     } /*end independent*/
01018 
01019     da->ReadFromGhostsEnd<PetscScalar>(inArr);
01020 
01021     for(da->init<ot::DA_FLAGS::DEPENDENT>();
01022         da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>();
01023         da->next<ot::DA_FLAGS::DEPENDENT>() ) {
01024       unsigned int idx = da->curr();
01025       unsigned int lev = da->getLevel(idx);
01026       double h = hFac*(1u << (maxD - lev));
01027       double fac1 = h/2.0;
01028       double fac2 = h*h*h/8.0;
01029       unsigned int indices[8];
01030       da->getNodeIndices(indices);
01031       unsigned char childNum = da->getChildNumber();
01032       unsigned char hnMask = da->getHangingNodeIndex(idx);
01033       unsigned char elemType = 0;
01034       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
01035         for(int k = 0; k < 8; k++) {
01036           if(bdyArr[indices[k]]) {
01037             outArr[indices[k]] =  inArr[indices[k]];
01038           } else {
01039             for(int j = 0; j < 8; j++) {
01040               if(!bdyArr[indices[j]]) {
01041                 outArr[indices[k]] +=  (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
01042                       (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);
01043               }
01044             }/*end for j*/
01045           }
01046         }/*end for k*/
01047     } /*end loop for dependent elems*/
01048 
01049   } /*end if active*/
01050 
01051   da->vecRestoreBuffer(in,inArr,false,false,true,1);
01052 
01053   da->vecRestoreBuffer(out,outArr,false,false,false,1);
01054 
01055   PetscFunctionReturn(0);
01056 }
01057 
01058 PetscErrorCode DirichletLaplacianMatGetDiagonal(Mat J, Vec diag) {
01059   PetscFunctionBegin;
01060 
01061   ot::DAMG damg;
01062   iC(MatShellGetContext(J, (void**)(&damg)));
01063 
01064   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
01065 
01066   ot::DA* da = damg->da;
01067 
01068   iC(VecZeroEntries(diag));
01069 
01070   unsigned char* bdyArr = data->bdyArr;
01071 
01072   PetscScalar *diagArr;
01073   /*Nodal,Non-Ghosted,Write,1 dof*/
01074   da->vecGetBuffer(diag, diagArr, false, false, false, 1);
01075 
01076   unsigned int maxD;
01077   double hFac;
01078   if(da->iAmActive()) {
01079     maxD = (da->getMaxDepth());
01080     hFac = 1.0/((double)(1u << (maxD-1)));
01081     /*Loop through All Elements including ghosted*/
01082     for(da->init<ot::DA_FLAGS::ALL>();
01083         da->curr() < da->end<ot::DA_FLAGS::ALL>();
01084         da->next<ot::DA_FLAGS::ALL>()) {
01085       unsigned int idx = da->curr();
01086       unsigned int lev = da->getLevel(idx);
01087       double h = hFac*(1u << (maxD - lev));
01088       double fac1 = h/2.0;
01089       unsigned int indices[8];
01090       da->getNodeIndices(indices);
01091       unsigned char childNum = da->getChildNumber();
01092       unsigned char hnMask = da->getHangingNodeIndex(idx);
01093       unsigned char elemType = 0;
01094       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
01095         for(int k = 0; k < 8; k++) {
01096           if(bdyArr[indices[k]]) {
01097             diagArr[indices[k]] = 1.0;
01098           } else {
01099             diagArr[indices[k]] +=  (fac1*LaplacianType2Stencil[childNum][elemType][k][k]);
01100           } /* end if bdy */
01101         } /*end k*/
01102     } /*end ALL loop*/
01103   } /*end if active*/
01104 
01105   da->vecRestoreBuffer(diag, diagArr, false, false, false, 1);
01106 
01107   PetscFunctionReturn(0);
01108 }
01109 
01110 PetscErrorCode DirichletJacobianMatGetDiagonal(Mat J, Vec diag) {
01111   PetscFunctionBegin;
01112 
01113   ot::DAMG damg;
01114   iC(MatShellGetContext(J, (void**)(&damg)));
01115 
01116   DirichletJacData *data = (static_cast<DirichletJacData*>(damg->user));
01117 
01118   ot::DA* da = damg->da;
01119 
01120   iC(VecZeroEntries(diag));
01121 
01122   unsigned char* bdyArr = data->bdyArr;
01123 
01124   PetscScalar *diagArr;
01125   /*Nodal,Non-Ghosted,Write,1 dof*/
01126   da->vecGetBuffer(diag, diagArr, false, false, false, 1);
01127 
01128   unsigned int maxD;
01129   double hFac;
01130   if(da->iAmActive()) {
01131     maxD = (da->getMaxDepth());
01132     hFac = 1.0/((double)(1u << (maxD-1)));
01133     /*Loop through All Elements including ghosted*/
01134     for(da->init<ot::DA_FLAGS::ALL>();
01135         da->curr() < da->end<ot::DA_FLAGS::ALL>();
01136         da->next<ot::DA_FLAGS::ALL>()) {
01137       unsigned int idx = da->curr();
01138       unsigned int lev = da->getLevel(idx);
01139       double h = hFac*(1u << (maxD - lev));
01140       double fac1 = h/2.0;
01141       double fac2 = h*h*h/8.0;
01142       unsigned int indices[8];
01143       da->getNodeIndices(indices);
01144       unsigned char childNum = da->getChildNumber();
01145       unsigned char hnMask = da->getHangingNodeIndex(idx);
01146       unsigned char elemType = 0;
01147       GET_ETYPE_BLOCK(elemType,hnMask,childNum)
01148         for(int k = 0; k < 8; k++) {
01149           if(bdyArr[indices[k]]) {
01150             diagArr[indices[k]] = 1.0;
01151           } else {
01152             diagArr[indices[k]] +=  ((fac1*(LaplacianType2Stencil[childNum][elemType][k][k])) +
01153                 (fac2*(MassType2Stencil[childNum][elemType][k][k])));
01154           } /* end if bdy */
01155         } /*end k*/
01156     } /*end ALL loop*/
01157   } /*end if active*/
01158 
01159   da->vecRestoreBuffer(diag, diagArr, false, false, false, 1);
01160 
01161   PetscFunctionReturn(0);
01162 }
01163 
01164 PetscErrorCode Jacobian2ShellMatMult(Mat J, Vec in, Vec out) {
01165   PetscFunctionBegin;
01166 
01167   ot::DAMG damg;
01168 
01169   MatShellGetContext(J, (void**)(&damg));
01170 
01171   Jac2MFreeData* ctx = static_cast<Jac2MFreeData*>(damg->user);
01172 
01173   if(damg->da->iAmActive()) {      
01174     PetscScalar* inArray;
01175     PetscScalar* outArray;
01176 
01177     VecGetArray(in, &inArray);
01178     VecGetArray(out, &outArray);
01179 
01180     VecPlaceArray(ctx->inTmp, inArray);
01181     VecPlaceArray(ctx->outTmp, outArray);
01182 
01183     MatMult(ctx->Jmat_private, ctx->inTmp, ctx->outTmp);
01184 
01185     VecResetArray(ctx->inTmp);
01186     VecResetArray(ctx->outTmp);
01187 
01188     VecRestoreArray(in, &inArray);
01189     VecRestoreArray(out, &outArray);
01190   }
01191 
01192   PetscFunctionReturn(0);
01193 }
01194 
01195 PetscErrorCode Jacobian3ShellMatMult(Mat J, Vec in, Vec out) {
01196   PetscFunctionBegin;
01197 
01198   ot::DAMG damg;
01199 
01200   MatShellGetContext(J, (void**)(&damg));
01201 
01202   Jac3MFreeData* ctx = static_cast<Jac3MFreeData*>(damg->user);
01203 
01204   if(damg->da->iAmActive()) {      
01205     PetscScalar* inArray;
01206     PetscScalar* outArray;
01207 
01208     VecGetArray(in, &inArray);
01209     VecGetArray(out, &outArray);
01210 
01211     VecPlaceArray(ctx->inTmp, inArray);
01212     VecPlaceArray(ctx->outTmp, outArray);
01213 
01214     MatMult(ctx->Jmat_private, ctx->inTmp, ctx->outTmp);
01215 
01216     VecResetArray(ctx->inTmp);
01217     VecResetArray(ctx->outTmp);
01218 
01219     VecRestoreArray(in, &inArray);
01220     VecRestoreArray(out, &outArray);
01221   }
01222 
01223   PetscFunctionReturn(0);
01224 }
01225 
01226 void getActiveStateAndActiveCommForKSP_Shell_DirichletJac(Mat mat,
01227     bool & activeState, MPI_Comm & activeComm) {
01228   PetscTruth isshell;
01229   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01230   assert(isshell);
01231   ot::DAMG damg;
01232   MatShellGetContext(mat, (void**)(&damg));
01233   ot::DA* da = damg->da;
01234   activeState = da->iAmActive();
01235   activeComm = da->getCommActive();
01236 }
01237 
01238 void getActiveStateAndActiveCommForKSP_Shell_Jac1(Mat mat,
01239     bool & activeState, MPI_Comm & activeComm) {
01240   PetscTruth isshell;
01241   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01242   assert(isshell);
01243   Jac1MFreeData *data;
01244   MatShellGetContext(mat, (void**)(&data));
01245   ot::DA* da = data->da;
01246   activeState = da->iAmActive();
01247   activeComm = da->getCommActive();
01248 }
01249 
01250 void getActiveStateAndActiveCommForKSP_Shell_Jac2or3(Mat mat,
01251     bool & activeState, MPI_Comm & activeComm) {
01252   PetscTruth isshell;
01253   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01254   assert(isshell);
01255   ot::DAMG damg;
01256   MatShellGetContext(mat, (void**)(&damg));
01257   ot::DA* da = damg->da;
01258   activeState = da->iAmActive();
01259   activeComm = da->getCommActive();
01260 }
01261 
01262 void getPrivateMatricesForKSP_Shell_DirichletJac(Mat mat,
01263     Mat *AmatPrivate, Mat *PmatPrivate, MatStructure* pFlag) {
01264   PetscTruth isshell;
01265   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01266   assert(isshell);
01267   ot::DAMG damg;
01268   MatShellGetContext(mat, (void**)(&damg));
01269   DirichletJacData* data = (static_cast<DirichletJacData*>(damg->user));
01270   *AmatPrivate = data->Jmat_private;
01271   *PmatPrivate = data->Jmat_private;
01272   *pFlag = DIFFERENT_NONZERO_PATTERN;
01273 }
01274 
01275 void getPrivateMatricesForKSP_Shell_Jac1(Mat mat,
01276     Mat *AmatPrivate, Mat *PmatPrivate, MatStructure* pFlag) {
01277   PetscTruth isshell;
01278   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01279   assert(isshell);
01280   Jac1MFreeData* data;
01281   MatShellGetContext(mat, (void**)(&data));
01282   *AmatPrivate = data->Jmat_private;
01283   *PmatPrivate = data->Jmat_private;
01284   *pFlag = DIFFERENT_NONZERO_PATTERN;
01285 }
01286 
01287 void getPrivateMatricesForKSP_Shell_Jac2(Mat mat,
01288     Mat *AmatPrivate, Mat *PmatPrivate, MatStructure* pFlag) {
01289   PetscTruth isshell;
01290   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01291   assert(isshell);
01292   ot::DAMG damg;
01293   MatShellGetContext(mat, (void**)(&damg));
01294   Jac2MFreeData* data = (static_cast<Jac2MFreeData*>(damg->user));
01295   *AmatPrivate = data->Jmat_private;
01296   *PmatPrivate = data->Jmat_private;
01297   *pFlag = DIFFERENT_NONZERO_PATTERN;
01298 }
01299 
01300 void getPrivateMatricesForKSP_Shell_Jac3(Mat mat,
01301     Mat *AmatPrivate, Mat *PmatPrivate, MatStructure* pFlag) {
01302   PetscTruth isshell;
01303   PetscTypeCompare((PetscObject)mat, MATSHELL, &isshell);
01304   assert(isshell);
01305   ot::DAMG damg;
01306   MatShellGetContext(mat, (void**)(&damg));
01307   Jac3MFreeData *data = (static_cast<Jac3MFreeData*>(damg->user));
01308   *AmatPrivate = data->Jmat_private;
01309   *PmatPrivate = data->Jmat_private;
01310   *pFlag = DIFFERENT_NONZERO_PATTERN;
01311 }
01312 
01313 PetscErrorCode CreateAndComputeMassMatrix(ot::DAMG damg, Mat* jac) {
01314   unsigned int  m,n;
01315   PetscFunctionBegin;
01316   ot::DA* da = damg->da;
01317   //The size this processor owns ( without ghosts).
01318   m=n=da->getNodeSize();
01319   Jac1MFreeData* data = new Jac1MFreeData;
01320   data->da = da;
01321   data->inTmp = NULL;
01322   data->outTmp = NULL;
01323   data->Jmat_private = NULL;
01324   iC(MatCreateShell(da->getComm(), m ,n,PETSC_DETERMINE,PETSC_DETERMINE, (void*)(data), jac));
01325   iC(MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) MassMatMult));
01326   iC(MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void(*)(void)) MassMatGetDiagonal));
01327   iC(MatShellSetOperation(*jac ,MATOP_DESTROY, (void(*)(void)) MassMatDestroy));
01328   PetscFunctionReturn(0);
01329 }
01330 
01331 /* WRAPPERS FOR JACOBIAN TYPE-1 MATRICES */
01332 PetscErrorCode CreateJacobian1(ot::DAMG damg,Mat *jac) {
01333   PetscFunctionBegin;
01334   PetscInt buildFullCoarseMat;
01335   PetscInt buildFullMatAll;
01336   int totalLevels;
01337   PetscTruth flg;
01338   PetscOptionsGetInt(PETSC_NULL, "-buildFullMatAll", &buildFullMatAll, &flg);
01339   PetscOptionsGetInt(PETSC_NULL, "-buildFullCoarseMat", &buildFullCoarseMat, &flg);
01340   if(buildFullMatAll) {
01341     buildFullCoarseMat = 1;
01342   }
01343   totalLevels = damg->totalLevels;
01344   ot::DA* da = damg->da;
01345   int myRank;
01346   MPI_Comm_rank(da->getComm(), &myRank);
01347   //The size this processor owns ( without ghosts).
01348   unsigned int  m,n;
01349   m=n=da->getNodeSize();
01350   if(totalLevels == damg->nlevels) {
01351     //This is the coarsest.
01352     if( (!myRank) && buildFullCoarseMat ) {
01353       std::cout<<"Building Full Coarse Mat."<<std::endl;
01354     }
01355     if(buildFullCoarseMat) {
01356       if(!(da->computedLocalToGlobal())) {
01357         da->computeLocalToGlobalMappings();
01358       }
01359     }
01360     bool requirePrivateMats = (da->getNpesActive() != da->getNpesAll());    
01361     if(requirePrivateMats) {
01362       Jac1MFreeData* data = new Jac1MFreeData;
01363       data->da = da;
01364       if(damg->nlevels == 1) {
01365         data->isFinestLevel = true;
01366       }else {
01367         data->isFinestLevel = false;
01368       }
01369       if(da->iAmActive()) {
01370         if(buildFullCoarseMat) {
01371           CreateAndComputeFullActiveJacobian1(damg, &(data->Jmat_private));
01372         } else {
01373           iC(MatCreateShell(damg->da->getCommActive(), m ,n,PETSC_DETERMINE,PETSC_DETERMINE,
01374                 (void*)(data), &(data->Jmat_private)));
01375 
01376           iC(MatShellSetOperation( data->Jmat_private, MATOP_MULT,
01377                 (void(*)(void)) Jacobian1MatMult));
01378 
01379           iC(MatShellSetOperation( data->Jmat_private, MATOP_GET_DIAGONAL,
01380                 (void(*)(void)) Jacobian1MatGetDiagonal));
01381 
01382           iC(MatShellSetOperation(data->Jmat_private ,MATOP_DESTROY,
01383                 (void(*)(void)) Jacobian1MatDestroy));
01384         }
01385         MatGetVecs(data->Jmat_private, &(data->inTmp), &(data->outTmp));
01386       } else {
01387         data->Jmat_private = NULL;
01388         data->inTmp = NULL;
01389         data->outTmp = NULL;
01390       }
01391       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE,PETSC_DETERMINE,
01392           (void*)(data), jac);
01393       MatShellSetOperation(*jac ,MATOP_DESTROY, (void(*)(void)) Jacobian1MatDestroy);
01394       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian1ShellMatMult);
01395     } else {
01396       if(buildFullCoarseMat) {
01397         CreateAndComputeFullJacobian1(damg, jac);
01398       } else {
01399         Jac1MFreeData* data = new Jac1MFreeData;
01400         data->da = da;
01401         if(damg->nlevels == 1) {
01402           data->isFinestLevel = true;
01403         }else {
01404           data->isFinestLevel = false;
01405         }
01406         data->Jmat_private = NULL;
01407         data->inTmp = NULL;
01408         data->outTmp = NULL;
01409         MatCreateShell(damg->comm, m ,n,PETSC_DETERMINE,PETSC_DETERMINE,
01410             (void*)(data), jac);
01411 
01412         MatShellSetOperation(*jac ,MATOP_MULT,
01413             (void(*)(void)) Jacobian1MatMult);
01414 
01415         MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL,
01416             (void(*)(void)) Jacobian1MatGetDiagonal);
01417 
01418         MatShellSetOperation(*jac ,MATOP_DESTROY,
01419             (void(*)(void)) Jacobian1MatDestroy);
01420       }
01421     }
01422     if( (!myRank) && buildFullCoarseMat ) {
01423       std::cout<<"Finished Building Full Coarse Mat."<<std::endl;
01424     }
01425   } else {
01426     //This is some finer level. So no need for KSP_Shell
01427     if(buildFullMatAll) {
01428       if(!(da->computedLocalToGlobal())) {
01429         da->computeLocalToGlobalMappings();
01430       }
01431       if(!myRank) {
01432         std::cout<<"Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
01433       }
01434       CreateAndComputeFullJacobian1(damg,jac);
01435       if(!myRank) {
01436         std::cout<<"Finished Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
01437       }
01438     } else {
01439       Jac1MFreeData* data = new Jac1MFreeData;
01440       data->da = da;
01441       if(damg->nlevels == 1) {
01442         data->isFinestLevel = true;
01443       }else {
01444         data->isFinestLevel = false;
01445       }
01446       data->Jmat_private = NULL;
01447       data->inTmp = NULL;
01448       data->outTmp = NULL;
01449       MatCreateShell(damg->comm, m ,n,PETSC_DETERMINE,PETSC_DETERMINE,
01450           (void*)(data), jac);
01451       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian1MatMult);
01452       MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void(*)(void)) Jacobian1MatGetDiagonal);
01453       MatShellSetOperation(*jac ,MATOP_DESTROY, (void(*)(void)) Jacobian1MatDestroy);
01454     }    
01455   }
01456 
01457   PetscFunctionReturn(0);
01458 }
01459 
01460 PetscErrorCode CreateAndComputeFullJacobian1(ot::DAMG damg,Mat *mat)
01461 {
01462   PetscFunctionBegin;
01463   CreateAndComputeFullJacobian1(damg->da, mat);
01464   PetscFunctionReturn(0);
01465 }
01466 
01467 PetscErrorCode CreateAndComputeFullActiveJacobian1(ot::DAMG damg,Mat *mat)
01468 {
01469   PetscFunctionBegin;
01470   CreateAndComputeFullActiveJacobian1(damg->da, mat);
01471   PetscFunctionReturn(0);
01472 }
01473 
01474 PetscErrorCode ComputeJacobian1(ot::DAMG damg,Mat J, Mat B) {
01475   //damg not used here. might be used if user defined props exist for each level.
01476   //Since J and B are the same, only B is built.
01477   PetscFunctionBegin;
01478   //Nothing to do here
01479   PetscFunctionReturn(0);
01480 }
01481 
01482 PetscErrorCode CreateJacobian2(ot::DAMG damg, Mat *jac) {
01483   PetscFunctionBegin;
01484   int totalLevels;
01485   PetscTruth flg;
01486   PetscInt buildFullCoarseMat;
01487   PetscInt buildFullMatAll;
01488   PetscOptionsGetInt(PETSC_NULL,"-buildFullMatAll",&buildFullMatAll,&flg);
01489   PetscOptionsGetInt(PETSC_NULL,"-buildFullCoarseMat",&buildFullCoarseMat,&flg);
01490   if(buildFullMatAll) {
01491     buildFullCoarseMat = 1;
01492   }
01493   totalLevels = damg->totalLevels;
01494   ot::DA* da = damg->da;
01495   int myRank;
01496   MPI_Comm_rank(da->getComm(),&myRank);
01497   //The size this processor owns ( without ghosts).
01498   unsigned int  m,n;
01499   m=n=da->getNodeSize();
01500   if(totalLevels == damg->nlevels) {
01501     //This is the coarsest.
01502     if( (!myRank) && buildFullCoarseMat ) {
01503       std::cout<<"Building Full Coarse Mat."<<std::endl;
01504     }
01505     char matType[30];
01506     if(buildFullCoarseMat) {
01507       if(!(da->computedLocalToGlobal())) {
01508         da->computeLocalToGlobalMappings();
01509       }
01510       PetscTruth typeFound;
01511       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
01512       if(!typeFound) {
01513         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
01514         assert(false);
01515       } 
01516     }
01517     bool requirePrivateMats = (da->getNpesActive() != da->getNpesAll());    
01518     if(requirePrivateMats ) {
01519       Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
01520       if(da->iAmActive()) {
01521         if(buildFullCoarseMat) {
01522           da->createActiveMatrix(data->Jmat_private, matType, 1);
01523         } else {
01524           MatCreateShell(da->getCommActive(), m, n, PETSC_DETERMINE,
01525               PETSC_DETERMINE, damg, &(data->Jmat_private));
01526           MatShellSetOperation(data->Jmat_private, MATOP_MULT,
01527               (void (*)(void)) Jacobian2MatMult);
01528           MatShellSetOperation(data->Jmat_private, MATOP_GET_DIAGONAL,
01529               (void (*)(void)) Jacobian2MatGetDiagonal);
01530           MatShellSetOperation(data->Jmat_private, MATOP_DESTROY,
01531               (void (*)(void)) Jacobian2MatDestroy);
01532         }
01533         MatGetVecs(data->Jmat_private, &(data->inTmp), &(data->outTmp));
01534       } else {
01535         data->Jmat_private = NULL;
01536         data->inTmp = NULL;
01537         data->outTmp = NULL;
01538       }
01539       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
01540       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian2MatDestroy);
01541       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian2ShellMatMult);
01542     } else {
01543       if(buildFullCoarseMat) {
01544         da->createMatrix(*jac, matType, 1);
01545       } else {
01546         MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
01547         MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) Jacobian2MatMult);
01548         MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) Jacobian2MatGetDiagonal);
01549         MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian2MatDestroy);
01550       }
01551     }
01552     if((!myRank) && buildFullCoarseMat) {
01553       std::cout<<"Finished Building Full Coarse Mat."<<std::endl;
01554     }
01555   } else {
01556     //This is some finer level.
01557     if(buildFullMatAll) {
01558       if(!myRank) {
01559         std::cout<<"Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
01560       }
01561       if(!(da->computedLocalToGlobal())) {
01562         da->computeLocalToGlobalMappings();
01563       }
01564       char matType[30];
01565       PetscTruth typeFound;
01566       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
01567       if(!typeFound) {
01568         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
01569         assert(false);
01570       } 
01571       da->createMatrix(*jac, matType, 1);
01572       if(!myRank) {
01573         std::cout<<"Finished Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
01574       }
01575     } else {
01576       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
01577       MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) Jacobian2MatMult);
01578       MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) Jacobian2MatGetDiagonal);
01579       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian2MatDestroy);
01580     }
01581   }
01582 
01583   PetscFunctionReturn(0);
01584 }//end fn.
01585 
01586 PetscErrorCode Jacobian2MatDestroy(Mat J) {
01587   PetscFunctionBegin;
01588   //Nothing to be done here. No new pointers were created during creation. 
01589   //The pointer were created in setUSerContext. So they will be destroyed in
01590   //DestroyUserContexts.
01591   PetscFunctionReturn(0);
01592 }
01593 
01594 #define JAC_TYPE2_ELEM_DIAG_BLOCK {\
01595   unsigned int idx = da->curr();\
01596   unsigned int lev = da->getLevel(idx);\
01597   double h = hFac*(1u << (maxD - lev));\
01598   double matP1 = matPropArr[2*idx];\
01599   double matP2 = matPropArr[2*idx+1];\
01600   double fac1 = matP1*h/2.0;\
01601   double fac2 = matP2*h*h*h/8.0;\
01602   unsigned int indices[8];\
01603   da->getNodeIndices(indices);\
01604   unsigned char childNum = da->getChildNumber();\
01605   unsigned char hnMask = da->getHangingNodeIndex(idx);\
01606   unsigned char elemType = 0;\
01607   GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
01608   for(int k = 0; k < 8; k++) {\
01609     diagArr[indices[k]] +=  ((fac1*(LaplacianType2Stencil[childNum][elemType][k][k])) +\
01610         (fac2*(MassType2Stencil[childNum][elemType][k][k])));\
01611   } /*end k*/\
01612 }
01613 
01614 #define JAC_TYPE2_DIAG_BLOCK {\
01615   ot::DA* da = damg->da;\
01616   iC(VecZeroEntries(diag));\
01617   double *matPropArr;\
01618   /*Elem,Ghost,Read-only,1 dof*/\
01619   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01620   PetscScalar *diagArr;\
01621   /*Nodal,Non-Ghosted,Write,1 dof*/\
01622   da->vecGetBuffer(diag,diagArr,false,false,false,1);\
01623   unsigned int maxD;\
01624   double hFac;\
01625   if(da->iAmActive()) {\
01626     maxD = (da->getMaxDepth());\
01627     hFac = 1.0/((double)(1u << (maxD-1)));\
01628     /*Loop through All Elements including ghosted*/\
01629     for(da->init<ot::DA_FLAGS::ALL>();\
01630         da->curr() < da->end<ot::DA_FLAGS::ALL>();\
01631         da->next<ot::DA_FLAGS::ALL>()) {\
01632       JAC_TYPE2_ELEM_DIAG_BLOCK\
01633     } /*end i*/\
01634   } /*end if active*/\
01635   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01636   da->vecRestoreBuffer(diag,diagArr,false,false,false,1);\
01637   PetscLogFlops(44*(da->getGhostedElementSize()));\
01638 }
01639 
01640 PetscErrorCode Jacobian2MatGetDiagonal(Mat J, Vec diag) {
01641   PetscFunctionBegin;
01642 
01643   PetscLogEventBegin(Jac2DiagEvent,diag,0,0,0);
01644 
01645   ot::DAMG damg;
01646   iC(MatShellGetContext(J, (void**)(&damg)));
01647 
01648   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
01649 
01650   if(data->isFinestLevel) {
01651     PetscLogEventBegin(Jac2FinestDiagEvent,diag,0,0,0);
01652   }
01653 
01654   JAC_TYPE2_DIAG_BLOCK 
01655 
01656     if(data->isFinestLevel) {
01657       PetscLogEventEnd(Jac2FinestDiagEvent,diag,0,0,0);
01658     }
01659 
01660   PetscLogEventEnd(Jac2DiagEvent,diag,0,0,0);
01661 
01662   PetscFunctionReturn(0);
01663 }
01664 
01665 #define JAC_TYPE2_ELEM_MULT_BLOCK {\
01666   unsigned int idx = da->curr();\
01667   unsigned int lev = da->getLevel(idx);\
01668   double h = hFac*(1u << (maxD - lev));\
01669   double matP1 = matPropArr[2*idx];\
01670   double matP2 = matPropArr[2*idx+1];\
01671   double fac1 = matP1*h/2.0;\
01672   double fac2 = matP2*h*h*h/8.0;\
01673   unsigned int indices[8];\
01674   da->getNodeIndices(indices);\
01675   unsigned char childNum = da->getChildNumber();\
01676   unsigned char hnMask = da->getHangingNodeIndex(idx);\
01677   unsigned char elemType = 0;\
01678   GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
01679   for(int k = 0;k < 8;k++) {\
01680     for(int j=0;j<8;j++) {\
01681       outArr[indices[k]] +=  (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
01682             (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);\
01683     }/*end for j*/\
01684   }/*end for k*/\
01685 }
01686 
01687 #define JAC_TYPE2_MULT_BLOCK {\
01688   ot::DA* da = damg->da;\
01689   iC(VecZeroEntries(out));\
01690   unsigned int maxD;\
01691   double hFac;\
01692   if(da->iAmActive()) {\
01693     maxD = da->getMaxDepth();\
01694     hFac = 1.0/((double)(1u << (maxD-1)));\
01695   }\
01696   double *matPropArr = NULL;\
01697   /*Elem,Ghost,Read-only,2 dof*/\
01698   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01699   PetscScalar *outArr=NULL;\
01700   PetscScalar *inArr=NULL;\
01701   /*Nodal,Non-Ghosted,Read,1 dof*/\
01702   da->vecGetBuffer(in,inArr,false,false,true,1);\
01703   if(da->iAmActive()) {\
01704     da->ReadFromGhostsBegin<PetscScalar>(inArr,1);\
01705   }\
01706   /*Nodal,Non-Ghosted,Write,1 dof*/\
01707   da->vecGetBuffer(out,outArr,false,false,false,1);\
01708   /*Loop through All Independent Elements*/\
01709   if(da->iAmActive()) {\
01710     for(da->init<ot::DA_FLAGS::INDEPENDENT>();\
01711         da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();\
01712         da->next<ot::DA_FLAGS::INDEPENDENT>() ) {\
01713       JAC_TYPE2_ELEM_MULT_BLOCK\
01714     } /*end independent*/\
01715   } /*end if active*/\
01716   if(da->iAmActive()) {\
01717     da->ReadFromGhostsEnd<PetscScalar>(inArr);\
01718   }\
01719   /*Loop through All Dependent Elements,*/\
01720   /*i.e. Elements which have atleast one*/\
01721   /*vertex owned by this processor and at least one*/\
01722   /*vertex not owned by this processor.*/\
01723   if(da->iAmActive()) {\
01724     for(da->init<ot::DA_FLAGS::DEPENDENT>();\
01725         da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>();\
01726         da->next<ot::DA_FLAGS::DEPENDENT>() ) {\
01727       JAC_TYPE2_ELEM_MULT_BLOCK\
01728     } /*end loop for dependent elems*/\
01729   } /*end if active*/\
01730   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01731   da->vecRestoreBuffer(in,inArr,false,false,true,1);\
01732   da->vecRestoreBuffer(out,outArr,false,false,false,1);\
01733   PetscLogFlops(332*(da->getGhostedElementSize()));\
01734 }
01735 
01736 #define JAC_TYPE2_MULT_DEBUG_BLOCK {\
01737   ot::DA* da = damg->da;\
01738   unsigned int maxD;\
01739   double hFac;\
01740   if(da->iAmActive()) {\
01741     maxD = da->getMaxDepth();\
01742     hFac = 1.0/((double)(1u << (maxD-1)));\
01743   }\
01744   double *matPropArr = NULL;\
01745   /*Elem,Ghost,Read-only,2 dof*/\
01746   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01747   PetscScalar *outArr=NULL;\
01748   PetscScalar *inArr=NULL;\
01749   /*Nodal,Non-Ghosted,Read,1 dof*/\
01750   da->vecGetBuffer(in,inArr,false,false,true,1);\
01751   if(da->iAmActive()) {\
01752     da->ReadFromGhostsBegin<PetscScalar>(inArr,1);\
01753     da->ReadFromGhostsEnd<PetscScalar>(inArr);\
01754   }\
01755   /*Nodal,Non-Ghosted,Write,1 dof*/\
01756   VecZeroEntries(out);\
01757   da->vecGetBuffer(out,outArr,false,false,false,1);\
01758   if(da->iAmActive()) {\
01759     for(da->init<ot::DA_FLAGS::WRITABLE>();\
01760         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();\
01761         da->next<ot::DA_FLAGS::WRITABLE>() ) {\
01762       JAC_TYPE2_ELEM_MULT_BLOCK\
01763     } /*end loop */\
01764   } /*end if active*/\
01765   if(da->iAmActive()) {\
01766     da->WriteToGhostsBegin<PetscScalar>(outArr,1);\
01767     da->WriteToGhostsEnd<PetscScalar>(outArr,1);\
01768   }\
01769   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01770   da->vecRestoreBuffer(in,inArr,false,false,true,1);\
01771   da->vecRestoreBuffer(out,outArr,false,false,false,1);\
01772   PetscLogFlops(332*(da->getGhostedElementSize()));\
01773 }
01774 
01775 PetscErrorCode Jacobian2MatMult(Mat J, Vec in, Vec out)
01776 {
01777   PetscFunctionBegin;
01778 
01779   PetscLogEventBegin(Jac2MultEvent,in,out,0,0);
01780 
01781   ot::DAMG damg;
01782   iC(MatShellGetContext(J, (void**)(&damg)));
01783 
01784   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
01785 
01786   if(data->isFinestLevel) {
01787     PetscLogEventBegin(Jac2FinestMultEvent,in,out,0,0);
01788   }
01789 
01790   JAC_TYPE2_MULT_BLOCK 
01791 
01792     if(data->isFinestLevel) {
01793       PetscLogEventEnd(Jac2FinestMultEvent,in,out,0,0);
01794     }
01795 
01796   PetscLogEventEnd(Jac2MultEvent,in,out,0,0);
01797 
01798   PetscFunctionReturn(0);
01799 }
01800 
01801 #undef JAC_TYPE2_MULT_DEBUG_BLOCK 
01802 
01803 #define BUILD_FULL_JAC_TYPE2_BLOCK(B) {\
01804   ot::DA* da = damg->da;\
01805   MatZeroEntries(B);\
01806   std::vector<ot::MatRecord> records;\
01807   unsigned int maxD;\
01808   double hFac;\
01809   if(da->iAmActive()) {\
01810     maxD = da->getMaxDepth();\
01811     hFac = 1.0/((double)(1u << (maxD-1)));\
01812   }\
01813   double *matPropArr = NULL;\
01814   /*Elem,Ghost,Read-only,2 dof*/\
01815   /*Note: All the flags are used for describing*/\
01816   /*the type of input vector, not*/\
01817   /*the type of the buffer.*/\
01818   da->vecGetBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01819   if(da->iAmActive()) {\
01820     for(da->init<ot::DA_FLAGS::WRITABLE>();\
01821         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();\
01822         da->next<ot::DA_FLAGS::WRITABLE>()) {\
01823       unsigned int idx = da->curr();\
01824       unsigned int lev = da->getLevel(idx);\
01825       double h = hFac*(1u << (maxD - lev));\
01826       double matP1 = matPropArr[2*idx];\
01827       double matP2 = matPropArr[2*idx+1];\
01828       double fac1 = matP1*h/2.0;\
01829       double fac2 = matP2*h*h*h/8.0;\
01830       unsigned int indices[8];\
01831       da->getNodeIndices(indices);\
01832       unsigned char childNum = da->getChildNumber();\
01833       unsigned char hnMask = da->getHangingNodeIndex(idx);\
01834       unsigned char elemType = 0;\
01835       GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
01836       for(int k = 0;k < 8;k++) {\
01837         for(int j=0;j<8;j++) {\
01838           ot::MatRecord currRec;\
01839           currRec.rowIdx = indices[k];\
01840           currRec.colIdx = indices[j];\
01841           currRec.rowDim = 0;\
01842           currRec.colDim = 0;\
01843           currRec.val = ((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
01844               (fac2*(MassType2Stencil[childNum][elemType][k][j])));\
01845           records.push_back(currRec);\
01846         } /*end for j*/\
01847       } /*end for k*/\
01848       if(records.size() > 1000) {\
01849         /*records will be cleared inside the function*/\
01850         da->setValuesInMatrix(B, records, 1, ADD_VALUES);\
01851       }\
01852     } /*end writable*/\
01853   } /*end if active*/\
01854   da->setValuesInMatrix(B, records, 1, ADD_VALUES);\
01855   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);\
01856   da->vecRestoreBuffer<double>(*(data->matProp),matPropArr,true,true,true,2);\
01857   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);\
01858 }
01859 
01860 PetscErrorCode ComputeJacobian2(ot::DAMG damg, Mat J, Mat B) {
01861   //For matShells nothing to be done here.
01862   PetscFunctionBegin;
01863 
01864   PetscTruth isshell;
01865   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
01866 
01867   Jac2MFreeData *data = (static_cast<Jac2MFreeData*>(damg->user));
01868 
01869   assert(B == J);
01870 
01871   if(isshell) {
01872     if( data->Jmat_private == NULL ) {
01873       PetscFunctionReturn(0);
01874     } else {
01875       J = data->Jmat_private;
01876       B = data->Jmat_private;
01877     }
01878   }
01879 
01880   //B and J are the same.
01881 
01882   PetscTypeCompare((PetscObject)B, MATSHELL, &isshell);
01883   if(isshell) {
01884     //Nothing to be done here.
01885     PetscFunctionReturn(0);
01886   }
01887 
01888   BUILD_FULL_JAC_TYPE2_BLOCK(B) 
01889 
01890     PetscFunctionReturn(0);
01891 }
01892 
01893 /*Functions for Jacobian Type 3: Exact Fine grid integration using coarse grid
01894 ** shape functions  */
01895 PetscErrorCode CreateJacobian3(ot::DAMG damg,Mat *jac) {
01896   PetscFunctionBegin;
01897   int totalLevels;
01898   PetscTruth flg;
01899   PetscInt buildFullMatAll;
01900   PetscInt buildFullCoarseMat;
01901   PetscOptionsGetInt(PETSC_NULL,"-buildFullMatAll",&buildFullMatAll,&flg);
01902   PetscOptionsGetInt(PETSC_NULL,"-buildFullCoarseMat",&buildFullCoarseMat,&flg);
01903   if(buildFullMatAll) {
01904     buildFullCoarseMat = 1;
01905   }
01906   totalLevels = damg->nlevels;
01907   ot::DA* da = damg->da;
01908   int myRank;
01909   MPI_Comm_rank(da->getComm(), &myRank);
01910   //The size this processor owns ( without ghosts).
01911   unsigned int  m,n;
01912   m=n=da->getNodeSize();
01913   if(totalLevels == damg->nlevels) {
01914     //This is the coarsest level
01915     if( (!myRank) && buildFullCoarseMat ) {
01916       std::cout<<"Building Full Mat for the coarsest level."<<std::endl;
01917     }
01918     char matType[30];
01919     if(buildFullCoarseMat) {
01920       if(!(da->computedLocalToGlobal())) {
01921         da->computeLocalToGlobalMappings();
01922       }
01923       PetscTruth typeFound;
01924       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
01925       if(!typeFound) {
01926         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
01927         assert(false);
01928       } 
01929     }
01930     bool requirePrivateMats = (da->getNpesActive() != da->getNpesAll());    
01931     if(requirePrivateMats) {
01932       Jac3MFreeData *data = (static_cast<Jac3MFreeData*>(damg->user));
01933       if(da->iAmActive()) {
01934         if(buildFullCoarseMat) {
01935           da->createActiveMatrix(data->Jmat_private, matType, 1);
01936         } else {
01937           MatCreateShell(damg->da->getCommActive(), m ,n, PETSC_DETERMINE,
01938               PETSC_DETERMINE, damg, &(data->Jmat_private) );
01939 
01940           MatShellSetOperation(data->Jmat_private ,MATOP_MULT,
01941               (void (*)(void)) Jacobian3MatMult);
01942 
01943           MatShellSetOperation(data->Jmat_private ,MATOP_GET_DIAGONAL,
01944               (void (*)(void)) Jacobian3MatGetDiagonal);
01945 
01946           MatShellSetOperation(data->Jmat_private ,MATOP_DESTROY,
01947               (void (*)(void)) Jacobian3MatDestroy);
01948         }
01949         MatGetVecs(data->Jmat_private, &(data->inTmp), &(data->outTmp));
01950       } else {
01951         data->Jmat_private = NULL;
01952         data->inTmp = NULL;
01953         data->outTmp = NULL;
01954       }
01955       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
01956       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian3MatDestroy);
01957       MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian3ShellMatMult);
01958     } else {
01959       if(buildFullCoarseMat) {
01960         da->createMatrix(*jac, matType, 1);
01961       } else {
01962         MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
01963         MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) Jacobian3MatMult);
01964         MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) Jacobian3MatGetDiagonal);
01965         MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian3MatDestroy);
01966       }
01967     }
01968     if( (!myRank) && buildFullCoarseMat ) {
01969       std::cout<<"Finished Building Full Mat for the coarsest level."<<std::endl;
01970     }
01971   } else {
01972     //This is some finer level
01973     if(buildFullMatAll) {
01974       if(!myRank) {
01975         std::cout<<"Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
01976       }
01977       if(!(da->computedLocalToGlobal())) {
01978         da->computeLocalToGlobalMappings();
01979       }
01980       char matType[30];
01981       PetscTruth typeFound;
01982       PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
01983       if(!typeFound) {
01984         std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
01985         assert(false);
01986       } 
01987       da->createMatrix(*jac, matType, 1);
01988       if(!myRank) {
01989         std::cout<<"Finished Building Full Mat for level: "<<(damg->nlevels)<<std::endl;
01990       }
01991     } else {
01992       MatCreateShell(damg->comm, m ,n, PETSC_DETERMINE, PETSC_DETERMINE, damg, jac);
01993       MatShellSetOperation(*jac ,MATOP_MULT, (void (*)(void)) Jacobian3MatMult);
01994       MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void (*)(void)) Jacobian3MatGetDiagonal);
01995       MatShellSetOperation(*jac ,MATOP_DESTROY, (void (*)(void)) Jacobian3MatDestroy);
01996     }
01997   }
01998 
01999   PetscFunctionReturn(0);
02000 }
02001 
02002 PetscErrorCode Jacobian3MatDestroy(Mat J) {
02003   PetscFunctionBegin;
02004   //Nothing to be done here. No new pointers were created during creation. 
02005   //The pointer were created in setUSerContext. So they will be destroyed in
02006   //DestroyUserContexts.
02007   PetscFunctionReturn(0);
02008 }
02009 
02010 #define JAC_TYPE3_DIAG_BLOCK {\
02011   /*The fine loop is always Writable, but the coarse loop*/\
02012   /*could be Independent or W_Dependent. Hence the fine counter must*/\
02013   /*be incremented properly to align with the coarse.*/\
02014   Point Cpt = da->getCurrentOffset();\
02015   while(daf->getCurrentOffset() != Cpt) {\
02016     daf->next<ot::DA_FLAGS::WRITABLE>();\
02017   }\
02018   unsigned int idxC= da->curr();\
02019   unsigned int lev = da->getLevel(idxC);\
02020   double h = hFac*(1u << (maxD - lev));\
02021   unsigned int indices[8];\
02022   da->getNodeIndices(indices);\
02023   unsigned char childNum = da->getChildNumber();\
02024   unsigned char hnMask = da->getHangingNodeIndex(idxC);\
02025   unsigned char elemType = 0;\
02026   GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
02027   if(daf->getLevel(daf->curr()) == lev) {\
02028     /*The coarse and fine elements are the same,*/\
02029     type2Cnt++;\
02030     unsigned int idxF = daf->curr();\
02031     double matP1 = matPropArr[2*idxF];\
02032     double matP2 = matPropArr[2*idxF+1];\
02033     double fac1 = matP1*h/2.0;\
02034     double fac2 = matP2*h*h*h/8.0;\
02035     for(int k = 0; k < 8; k++) {\
02036       diagArr[indices[k]] +=  ((fac1*(LaplacianType2Stencil[childNum][elemType][k][k])) +\
02037           (fac2*(MassType2Stencil[childNum][elemType][k][k])));\
02038     } /*end k*/\
02039     daf->next<ot::DA_FLAGS::WRITABLE>();\
02040   }else {\
02041     type1Cnt++;\
02042     for(unsigned int cNumFine = 0; cNumFine < 8; cNumFine++) {\
02043       /*The coarse and fine elements are NOT the same. */\
02044       /*Loop over each of the 8 children of the coarse element.*/\
02045       /*These are the underlying fine elements.*/\
02046       unsigned int idxF = daf->curr();\
02047       double matP1 = matPropArr[2*idxF];\
02048       double matP2 = matPropArr[2*idxF+1];\
02049       double fac1 = matP1*h/2.0;\
02050       double fac2 = matP2*h*h*h/8.0;\
02051       for(int k = 0; k < 8; k++) {\
02052         diagArr[indices[k]] += \
02053         ((fac1*(LaplacianType1Stencil[childNum][elemType][cNumFine][k][k])) +\
02054          (fac2*(MassType1Stencil[childNum][elemType][cNumFine][k][k])));\
02055       } /*end k*/\
02056       daf->next<ot::DA_FLAGS::WRITABLE>();\
02057     } /*end loop over the 8 fine elements*/\
02058   }\
02059 }
02060 
02061 PetscErrorCode Jacobian3MatGetDiagonal(Mat J, Vec diag) {
02062 
02063   PetscFunctionBegin;
02064 
02065   PetscLogEventBegin(Jac3DiagEvent,0,0,0,0);
02066 
02067   ot::DAMG damg;
02068   iC(MatShellGetContext(J, (void**)(&damg)));
02069 
02070   Jac3MFreeData *data = (static_cast<Jac3MFreeData*>(damg->user));
02071 
02072   if(data->isFinestLevel) {
02073     PetscLogEventBegin(Jac3FinestDiagEvent,0,0,0,0);
02074   }
02075 
02076   if( (data->isFinestLevel) ||
02077       ( (data->JmatThisLevel != data->BmatThisLevel)
02078         && (J == data->BmatThisLevel) ) ) {
02079     JAC_TYPE2_DIAG_BLOCK 
02080   }else {
02081     //Use the fine grid material properties
02082     //Loop over the coarse and fine meshes simultaneously
02083     ot::DA* da = damg->da;
02084     ot::DA* daf = data->daf;
02085     assert(da->iAmActive() == daf->iAmActive());
02086     double *matPropArr = NULL;
02087     if(data->changedPartition) {
02088       /*Elem,Non-Ghost,Read-only,1 dof*/
02089       daf->vecGetBuffer<double>(*(data->matPropFine),matPropArr,true,false,true,2);
02090     }else {
02091       /*Elem,Ghost,Read-only,1 dof*/
02092       daf->vecGetBuffer<double>(*(data->matPropFine),matPropArr,true,true,true,2);
02093     }
02094     PetscScalar *diagArr = NULL;
02095     VecZeroEntries(diag);
02096     /*Nodal,Non-Ghosted,Write,1 dof*/
02097     da->vecGetBuffer(diag,diagArr,false,false,false,1);
02098     unsigned int maxD;
02099     double hFac;
02100     unsigned int type1Cnt = 0; /*Coarse and Fine are not the same */
02101     unsigned int type2Cnt = 0; /*Coarse and Fine are the same */
02102     if(da->iAmActive()) {
02103       maxD = (da->getMaxDepth());
02104       hFac = 1.0/((double)(1u << (maxD-1)));
02105       for(da->init<ot::DA_FLAGS::W_DEPENDENT>(), daf->init<ot::DA_FLAGS::WRITABLE>();
02106           da->curr() < da->end<ot::DA_FLAGS::W_DEPENDENT>(); da->next<ot::DA_FLAGS::W_DEPENDENT>()) {
02107         JAC_TYPE3_DIAG_BLOCK 
02108       } /*end dependent loop*/
02109       da->WriteToGhostsBegin<PetscScalar>(diagArr, 1);
02110       for(da->init<ot::DA_FLAGS::INDEPENDENT>(), daf->init<ot::DA_FLAGS::WRITABLE>();
02111           da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>();  da->next<ot::DA_FLAGS::INDEPENDENT>()) {
02112         JAC_TYPE3_DIAG_BLOCK 
02113       } /*end Independent loop (overlapping with write to ghosts)*/
02114       da->WriteToGhostsEnd<PetscScalar>(diagArr, 1);
02115     } /*end if active*/
02116 
02117     if(data->changedPartition) {
02118       daf->vecRestoreBuffer<double>(*(data->matPropFine),matPropArr,true,false,true,2);
02119     }else {
02120       daf->vecRestoreBuffer<double>(*(data->matPropFine),matPropArr,true,true,true,2);
02121     }
02122 
02123     da->vecRestoreBuffer(diag,diagArr,false,false,false,1);
02124 
02125     PetscLogFlops( (type1Cnt*336) + (type2Cnt*44) );
02126   }
02127 
02128   if(data->isFinestLevel) {
02129     PetscLogEventEnd(Jac3FinestDiagEvent,0,0,0,0);
02130   }
02131 
02132   PetscLogEventEnd(Jac3DiagEvent,0,0,0,0);
02133 
02134   PetscFunctionReturn(0);
02135 }
02136 
02137 #undef JAC_TYPE3_DIAG_BLOCK 
02138 
02139 #define JAC_TYPE3_MULT_BLOCK {\
02140   /*The fine loop is always Writable, but the coarse loop*/\
02141   /*could be Independent or W_Dependent. Hence the fine counter must*/\
02142   /*be incremented properly to align with the coarse.*/\
02143   Point Cpt = da->getCurrentOffset();\
02144   while(daf->getCurrentOffset() != Cpt) {\
02145     daf->next<ot::DA_FLAGS::WRITABLE>();\
02146   }\
02147   unsigned int idxC= da->curr();\
02148   unsigned int lev = da->getLevel(idxC);\
02149   double h = hFac*(1u << (maxD - lev));\
02150   unsigned int indices[8];\
02151   da->getNodeIndices(indices);\
02152   unsigned char childNum = da->getChildNumber();\
02153   unsigned char hnMask = da->getHangingNodeIndex(idxC);\
02154   unsigned char elemType = 0;\
02155   GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
02156   if(daf->getLevel(daf->curr()) == lev) {\
02157     /*The coarse and fine elements are the same,*/\
02158     type2Cnt++;\
02159     unsigned int idxF = daf->curr();\
02160     double matP1 = matPropArr[2*idxF];\
02161     double matP2 = matPropArr[2*idxF+1];\
02162     double fac1 = matP1*h/2.0;\
02163     double fac2 = matP2*h*h*h/8.0;\
02164     for(int k = 0; k < 8; k++) {\
02165       for(int j = 0; j < 8; j++) {\
02166         outArr[indices[k]] += (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
02167               (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);\
02168       } /*end j*/\
02169     } /*end k*/\
02170     daf->next<ot::DA_FLAGS::WRITABLE>();\
02171   }else {\
02172     double matP1[8];\
02173     double matP2[8];\
02174     for(unsigned int cNumFine = 0; cNumFine < 8; cNumFine++) {\
02175       /*The coarse and fine elements are NOT the same. */\
02176       /*Loop over each of the 8 children of the coarse element.*/\
02177       /*These are the underlying fine elements.*/\
02178       unsigned int idxF = daf->curr();\
02179       matP1[cNumFine] = matPropArr[2*idxF];\
02180       matP2[cNumFine] = matPropArr[2*idxF+1];\
02181       daf->next<ot::DA_FLAGS::WRITABLE>();\
02182     } /*end loop over the 8 fine elements*/\
02183     double maxP1 = matP1[0];\
02184     double minP1 = matP1[0];\
02185     double maxP2 = matP2[0];\
02186     double minP2 = matP2[0];\
02187     double totalP1 = 0.0;\
02188     double totalP2 = 0.0;\
02189     for(unsigned int cNumFine = 0; cNumFine < 8; cNumFine++) {\
02190       if(matP1[cNumFine] > maxP1) {\
02191         maxP1 = matP1[cNumFine];\
02192       }\
02193       if(matP2[cNumFine] > maxP2) {\
02194         maxP2 = matP2[cNumFine];\
02195       }\
02196       if(matP1[cNumFine] < minP1) {\
02197         minP1 = matP1[cNumFine];\
02198       }\
02199       if(matP2[cNumFine] < minP2) {\
02200         minP2 = matP2[cNumFine];\
02201       }\
02202       totalP1 += matP1[cNumFine];\
02203       totalP2 += matP2[cNumFine];\
02204     }\
02205     /*If the difference in the material properties is small*/\
02206     /*use the average value instead*/\
02207     if( ( (maxP1-minP1) <= (tolToCoarsenMatProp*maxP1) )\
02208         && ( (maxP2-minP2) <= (tolToCoarsenMatProp*maxP2) ) ) {\
02209       type2Cnt++;\
02210       double fac1 = totalP1*h/16.0;\
02211       double fac2 = totalP2*h*h*h/64.0;\
02212       for(int k = 0; k < 8; k++) {\
02213         for(int j = 0; j < 8; j++) {\
02214           outArr[indices[k]] += (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
02215                 (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);\
02216         } /*end j*/\
02217       } /*end k*/\
02218     }else {\
02219       type1Cnt++;\
02220       for(unsigned int cNumFine = 0; cNumFine < 8; cNumFine++) {\
02221         double fac1 = (matP1[cNumFine])*h/2.0;\
02222         double fac2 = (matP2[cNumFine])*h*h*h/8.0;\
02223         for(int k = 0; k < 8; k++) {\
02224           for(int j = 0; j < 8; j++) {\
02225             outArr[indices[k]] +=\
02226             (((fac1*(LaplacianType1Stencil[childNum][elemType][cNumFine][k][j])) +\
02227               (fac2*(MassType1Stencil[childNum][elemType][cNumFine][k][j])))*inArr[indices[j]]);\
02228           } /*end j*/\
02229         } /*end k*/\
02230       } /*end loop over the 8 fine elements*/\
02231     }\
02232   }\
02233 }
02234 
02235 PetscErrorCode Jacobian3MatMult(Mat J, Vec in, Vec out)
02236 {
02237   PetscFunctionBegin;
02238 
02239   PetscLogEventBegin(Jac3MultEvent,in,out,0,0);
02240 
02241   ot::DAMG damg;
02242   iC(MatShellGetContext(J, (void**)(&damg)));
02243 
02244   Jac3MFreeData *data = (static_cast<Jac3MFreeData*>(damg->user));
02245 
02246   if(data->isFinestLevel) {
02247     PetscLogEventBegin(Jac3FinestMultEvent,in,out,0,0);
02248   }
02249 
02250   //The finest level and the pcMat for other levels use matProp directly
02251   //The Jmat for other levels use matPropFine
02252   //Only the finest and the coarsest grids have Jmat==Bmat
02253   //For the coarsest grid matPropFine must be used
02254   if( (data->isFinestLevel) ||
02255       ( (data->BmatThisLevel != data->JmatThisLevel) 
02256         && (J == data->BmatThisLevel) ) ) {
02257     JAC_TYPE2_MULT_BLOCK 
02258   }else {
02259     //Use the fine grid material properties
02260     //Loop over the coarse and fine meshes simultaneously
02261     PetscReal tolToCoarsenMatProp = 1.0e-12;
02262     PetscTruth optFound;
02263     PetscOptionsGetReal(0,"-tolToCoarsenMatProp",&tolToCoarsenMatProp,&optFound);
02264     assert(tolToCoarsenMatProp >= 0.0);
02265 
02266     ot::DA* da = damg->da;
02267     ot::DA* daf = data->daf;
02268     assert(da->iAmActive() == daf->iAmActive());
02269     double *matPropArr = NULL;
02270     if(data->changedPartition) {
02271       /*Elem,Non-Ghost,Read-only,1 dof*/
02272       daf->vecGetBuffer<double>(*(data->matPropFine),matPropArr,true,false,true,2);
02273     }else {
02274       /*Elem,Ghost,Read-only,1 dof*/
02275       daf->vecGetBuffer<double>(*(data->matPropFine),matPropArr,true,true,true,2);
02276     }
02277     PetscScalar *inArr = NULL;
02278     PetscScalar *outArr = NULL;
02279     /*Nodal,Non-Ghosted,ReadOnly,1 dof*/
02280     da->vecGetBuffer(in, inArr, false, false, true, 1);
02281     if(da->iAmActive()) {
02282       da->ReadFromGhostsBegin<PetscScalar>(inArr, 1);
02283     }
02284     VecZeroEntries(out);
02285     /*Nodal,Non-Ghosted,Write,1 dof*/
02286     da->vecGetBuffer(out, outArr, false, false, false, 1);
02287     unsigned int maxD;
02288     double hFac;
02289     unsigned int type1Cnt = 0; /*Coarse and Fine are not the same */
02290     unsigned int type2Cnt = 0; /*Coarse and Fine are the same */
02291     if(da->iAmActive()) {
02292       maxD = (da->getMaxDepth());
02293       hFac = 1.0/((double)(1u << (maxD-1)));
02294       unsigned int loopCtr = 0;
02295       unsigned int numItersFirstLoop = static_cast<unsigned int>(0.3*static_cast<double>(da->getElementSize()));
02296       for(da->init<ot::DA_FLAGS::INDEPENDENT>(), daf->init<ot::DA_FLAGS::WRITABLE>();
02297           ( (daf->currWithInfo() == daf->currWithInfo()) && 
02298             (da->currWithInfo() < da->end<ot::DA_FLAGS::INDEPENDENT>()) && (loopCtr < numItersFirstLoop) );
02299           da->next<ot::DA_FLAGS::INDEPENDENT>(), loopCtr++) {
02300         JAC_TYPE3_MULT_BLOCK 
02301       } /*end Independent loop (overlapping with read from ghosts)*/
02302     } /* end if active */
02303     if(da->iAmActive()) {
02304       da->ReadFromGhostsEnd<PetscScalar>(inArr);
02305     }
02306     if(da->iAmActive()) {
02307       for(da->init<ot::DA_FLAGS::W_DEPENDENT>(), daf->init<ot::DA_FLAGS::WRITABLE>();
02308           da->curr() < da->end<ot::DA_FLAGS::W_DEPENDENT>(); da->next<ot::DA_FLAGS::W_DEPENDENT>()) {
02309         JAC_TYPE3_MULT_BLOCK 
02310       } /*end dependent loop*/
02311       da->WriteToGhostsBegin<PetscScalar>(outArr, 1);
02312       for(da->init<ot::DA_FLAGS::FROM_STORED>(), daf->init<ot::DA_FLAGS::FROM_STORED>();
02313           da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>(); da->next<ot::DA_FLAGS::INDEPENDENT>()) {
02314         JAC_TYPE3_MULT_BLOCK 
02315       } /*end Independent loop (overlapping with write to ghosts)*/
02316       da->WriteToGhostsEnd<PetscScalar>(outArr, 1);
02317     } /*end if active*/
02318 
02319     if(data->changedPartition) {
02320       daf->vecRestoreBuffer<double>(*(data->matPropFine),matPropArr,true,false,true,2);
02321     }else {
02322       daf->vecRestoreBuffer<double>(*(data->matPropFine),matPropArr,true,true,true,2);
02323     }
02324 
02325     da->vecRestoreBuffer(out, outArr, false, false, false, 1);
02326     da->vecRestoreBuffer(in, inArr, false, false, true, 1);
02327 
02328     PetscLogFlops( (type1Cnt*2643) + (type2Cnt*333) );
02329   }
02330 
02331   if(data->isFinestLevel) {
02332     PetscLogEventEnd(Jac3FinestMultEvent,in,out,0,0);
02333   }
02334   PetscLogEventEnd(Jac3MultEvent,in,out,0,0);
02335 
02336   PetscFunctionReturn(0);
02337 }
02338 
02339 #undef JAC_TYPE3_MULT_BLOCK 
02340 
02341 #define BUILD_FULL_JAC_TYPE3_BLOCK(B) {\
02342   ot::DA* da = damg->da;\
02343   ot::DA* daf = data->daf;\
02344   MatZeroEntries(B);\
02345   std::vector<ot::MatRecord> records;\
02346   unsigned int maxD;\
02347   double hFac;\
02348   if(da->iAmActive()) {\
02349     maxD = da->getMaxDepth();\
02350     hFac = 1.0/((double)(1u << (maxD-1)));\
02351   }\
02352   double *matPropArr = NULL;\
02353   if(data->changedPartition) {\
02354     /*Elem,Non-Ghosted,Read-only,2 dof*/\
02355     daf->vecGetBuffer<double>(*(data->matPropFine),matPropArr,\
02356         true,false,true,2);\
02357   }else {\
02358     /*Elem,Ghosted,Read-only,2 dof*/\
02359     daf->vecGetBuffer<double>(*(data->matPropFine),matPropArr,\
02360         true,true,true,2);\
02361   }\
02362   if(da->iAmActive()) {\
02363     assert(daf->iAmActive());\
02364     for(da->init<ot::DA_FLAGS::WRITABLE>(),\
02365         daf->init<ot::DA_FLAGS::WRITABLE>();\
02366         da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();\
02367         da->next<ot::DA_FLAGS::WRITABLE>()) {\
02368       Point Cpt = da->getCurrentOffset();\
02369       while(daf->getCurrentOffset() != Cpt) {\
02370         daf->next<ot::DA_FLAGS::WRITABLE>();\
02371       }\
02372       unsigned int idxC = da->curr();\
02373       unsigned int lev = da->getLevel(idxC);\
02374       double h = hFac*(1u << (maxD - lev));\
02375       unsigned int indices[8];\
02376       da->getNodeIndices(indices);\
02377       unsigned char childNum = da->getChildNumber();\
02378       unsigned char hnMask = da->getHangingNodeIndex(idxC);\
02379       unsigned char elemType = 0;\
02380       GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
02381       if(daf->getLevel(daf->curr()) == lev) {\
02382         /*The coarse and fine elements are the same,*/\
02383         unsigned int idxF = daf->curr();\
02384         double matP1 = matPropArr[2*idxF];\
02385         double matP2 = matPropArr[2*idxF+1];\
02386         double fac1 = matP1*h/2.0;\
02387         double fac2 = matP2*h*h*h/8.0;\
02388         for(int k = 0; k < 8; k++) {\
02389           for(int j = 0; j < 8; j++) {\
02390             ot::MatRecord currRec;\
02391             currRec.rowIdx = indices[k];\
02392             currRec.colIdx = indices[j];\
02393             currRec.rowDim = 0;\
02394             currRec.colDim = 0;\
02395             currRec.val = ((fac1*\
02396                   (LaplacianType2Stencil[childNum][elemType][k][j])) +\
02397                 (fac2*\
02398                  (MassType2Stencil[childNum][elemType][k][j])));\
02399             records.push_back(currRec);\
02400           } /*end for j*/\
02401         } /*end for k*/\
02402         daf->next<ot::DA_FLAGS::WRITABLE>();\
02403       }else {\
02404         for(unsigned char cNumFine = 0; cNumFine < 8; cNumFine++) {\
02405           /*The coarse and fine elements are NOT the same. */\
02406           /*Loop over each of the 8 children of the coarse element.*/\
02407           /*These are the underlying fine elements.*/\
02408           unsigned int idxF = daf->curr();\
02409           double matP1 = matPropArr[2*idxF];\
02410           double matP2 = matPropArr[2*idxF+1];\
02411           double fac1 = matP1*h/2.0;\
02412           double fac2 = matP2*h*h*h/8.0;\
02413           for(int k = 0; k < 8; k++) {\
02414             for(int j = 0; j < 8; j++) {\
02415               ot::MatRecord currRec;\
02416               currRec.rowIdx = indices[k];\
02417               currRec.colIdx = indices[j];\
02418               currRec.rowDim = 0;\
02419               currRec.colDim = 0;\
02420               currRec.val = ((fac1*(LaplacianType1Stencil\
02421                       [childNum][elemType][cNumFine][k][j]))+\
02422                   (fac2*(MassType1Stencil\
02423                          [childNum][elemType][cNumFine][k][j])));\
02424               records.push_back(currRec);\
02425             } /*end for j*/\
02426           } /*end for k*/\
02427           daf->next<ot::DA_FLAGS::WRITABLE>();\
02428         } /*end loop over the 8 fine elements*/\
02429       }\
02430       if(records.size() > 1000) {\
02431         /*records will be cleared inside the function*/\
02432         da->setValuesInMatrix(B, records, 1, ADD_VALUES);\
02433       }\
02434     } /*end writable*/\
02435   } else {\
02436     assert(!(daf->iAmActive()));\
02437   } /*end if active*/\
02438   da->setValuesInMatrix(B, records, 1, ADD_VALUES);\
02439   MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY);\
02440   if(data->changedPartition) {\
02441     daf->vecRestoreBuffer<double>(*(data->matPropFine),matPropArr,\
02442         true,false,true,2);\
02443   }else {\
02444     daf->vecRestoreBuffer<double>(*(data->matPropFine),matPropArr,\
02445         true,true,true,2);\
02446   }\
02447   MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY);\
02448 }
02449 
02450 PetscErrorCode ComputeJacobian3(ot::DAMG damg, Mat J, Mat B) {
02451   PetscFunctionBegin;
02452 
02453   Jac3MFreeData *data = (static_cast<Jac3MFreeData*>(damg->user));
02454 
02455   PetscTruth isShellB, isShellJ;
02456   PetscTypeCompare((PetscObject)B, MATSHELL, &isShellB);
02457   PetscTypeCompare((PetscObject)J, MATSHELL, &isShellJ);
02458 
02459   assert(isShellB == isShellJ);
02460 
02461   //For matShells nothing to be done here.
02462   if(isShellB) {
02463     if( data->Jmat_private == NULL ) {
02464       //This will be used to determine the type of matrix in the MatVecs
02465       data->JmatThisLevel = J;
02466       data->BmatThisLevel = B;
02467 
02468       PetscFunctionReturn(0);
02469     } else {
02470       //This must be the coarsest level: J and B will be the same
02471       J = data->Jmat_private;
02472       B = data->Jmat_private;
02473     }
02474   }
02475 
02476   //This will be used to determine the type of matrix in the MatVecs
02477   data->JmatThisLevel = J;
02478   data->BmatThisLevel = B;
02479 
02480   PetscTypeCompare((PetscObject)B, MATSHELL, &isShellB);
02481   PetscTypeCompare((PetscObject)J, MATSHELL, &isShellJ);
02482 
02483   if(J != B) {
02484     //Build both B ond J
02485     //Use matProp for J
02486     if(!isShellJ) {
02487       BUILD_FULL_JAC_TYPE2_BLOCK(J) 
02488     }
02489     //Use matPropFine for B
02490     //Loop over the coarse and fine meshes simultaneously
02491     if(!isShellB) {
02492       BUILD_FULL_JAC_TYPE3_BLOCK(B) 
02493     }
02494   } else {
02495     //Build B only
02496     if(!isShellB) {
02497       if(data->isFinestLevel) {
02498         //Use matProp
02499         BUILD_FULL_JAC_TYPE2_BLOCK(B) 
02500       } else {
02501         //This must be the coarsest grid
02502         //Use matPropFine
02503         //Loop over the coarse and fine meshes simultaneously
02504         BUILD_FULL_JAC_TYPE3_BLOCK(B) 
02505       }//end if finest
02506     }
02507   }//end if J == B
02508 
02509   PetscFunctionReturn(0);
02510 }
02511 
02512 
02513 #undef BUILD_FULL_JAC_TYPE2_BLOCK 
02514 #undef BUILD_FULL_JAC_TYPE3_BLOCK 
02515 #undef JAC_TYPE2_MULT_BLOCK 
02516 #undef JAC_TYPE2_DIAG_BLOCK 
02517 #undef JAC_TYPE2_ELEM_DIAG_BLOCK 
02518 #undef JAC_TYPE2_ELEM_MULT_BLOCK 
02519 
02520 
02521 

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