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