00001
00007 #include "petsc.h"
00008 #include "petscvec.h"
00009 #include "petscmat.h"
00010 #include "odaJac.h"
00011
00012 #ifdef PETSC_USE_LOG
00013 extern int Jac1DiagEvent;
00014 extern int Jac1MultEvent;
00015 extern int Jac1FinestDiagEvent;
00016 extern int Jac1FinestMultEvent;
00017 #endif
00018
00019 extern double**** LaplacianType2Stencil;
00020 extern double**** MassType2Stencil;
00021
00022 PetscErrorCode Jacobian1ShellMatMult(Mat J, Vec in, Vec out) {
00023 PetscFunctionBegin;
00024
00025 Jac1MFreeData* ctx;
00026
00027 MatShellGetContext(J, (void**)(&ctx));
00028
00029 assert(ctx != NULL);
00030 assert(ctx->da != NULL);
00031
00032 if(ctx->da->iAmActive()) {
00033 PetscScalar* inArray;
00034 PetscScalar* outArray;
00035
00036 VecGetArray(in, &inArray);
00037 VecGetArray(out, &outArray);
00038
00039 VecPlaceArray(ctx->inTmp, inArray);
00040 VecPlaceArray(ctx->outTmp, outArray);
00041
00042 MatMult(ctx->Jmat_private, ctx->inTmp, ctx->outTmp);
00043
00044 VecResetArray(ctx->inTmp);
00045 VecResetArray(ctx->outTmp);
00046
00047 VecRestoreArray(in, &inArray);
00048 VecRestoreArray(out, &outArray);
00049 }
00050
00051 PetscFunctionReturn(0);
00052 }
00053
00054 PetscErrorCode CreateJacobian1(ot::DA *da, Mat *jac)
00055 {
00056 PetscInt m,n;
00057 PetscFunctionBegin;
00058
00059 m=n=da->getNodeSize();
00060 Jac1MFreeData* data = new Jac1MFreeData;
00061 data->da = da;
00062 data->Jmat_private = NULL;
00063 data->inTmp = NULL;
00064 data->outTmp = NULL;
00065 data->isFinestLevel = true;
00066 iC(MatCreateShell(da->getComm(), m ,n,PETSC_DETERMINE,PETSC_DETERMINE,
00067 (void*)(data), jac));
00068 iC(MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian1MatMult));
00069 iC(MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void(*)(void)) Jacobian1MatGetDiagonal));
00070 iC(MatShellSetOperation(*jac ,MATOP_DESTROY, (void(*)(void)) Jacobian1MatDestroy));
00071 PetscFunctionReturn(0);
00072 }
00073
00074 PetscErrorCode CreateActiveJacobian1(ot::DA *da, Mat *jac)
00075 {
00076 PetscInt m,n;
00077 PetscFunctionBegin;
00078 if(da->iAmActive()) {
00079
00080 m=n=da->getNodeSize();
00081 Jac1MFreeData* data = new Jac1MFreeData;
00082 data->da = da;
00083 data->Jmat_private = NULL;
00084 data->inTmp = NULL;
00085 data->outTmp = NULL;
00086 data->isFinestLevel = true;
00087 iC(MatCreateShell(da->getCommActive(), m ,n,PETSC_DETERMINE,PETSC_DETERMINE,
00088 (void*)(data), jac));
00089 iC(MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) Jacobian1MatMult));
00090 iC(MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void(*)(void)) Jacobian1MatGetDiagonal));
00091 iC(MatShellSetOperation(*jac ,MATOP_DESTROY, (void(*)(void)) Jacobian1MatDestroy));
00092 }
00093 PetscFunctionReturn(0);
00094 }
00095
00096 PetscErrorCode ComputeJacobian1(ot::DA* da, Mat J)
00097 {
00098 PetscFunctionBegin;
00099
00100 PetscFunctionReturn(0);
00101 }
00102
00103 PetscErrorCode CreateAndComputeMassMatrix(ot::DA* da, Mat* jac) {
00104 PetscInt m,n;
00105 PetscFunctionBegin;
00106
00107 m=n=da->getNodeSize();
00108 Jac1MFreeData* data = new Jac1MFreeData;
00109 data->da = da;
00110 data->Jmat_private = NULL;
00111 data->inTmp = NULL;
00112 data->outTmp = NULL;
00113 iC(MatCreateShell(da->getComm(), m ,n,PETSC_DETERMINE,PETSC_DETERMINE, (void*)(data), jac));
00114 iC(MatShellSetOperation(*jac ,MATOP_MULT, (void(*)(void)) MassMatMult));
00115 iC(MatShellSetOperation(*jac ,MATOP_GET_DIAGONAL, (void(*)(void)) MassMatGetDiagonal));
00116 iC(MatShellSetOperation(*jac ,MATOP_DESTROY, (void(*)(void)) MassMatDestroy));
00117 PetscFunctionReturn(0);
00118 }
00119
00120 PetscErrorCode Jacobian1MatDestroy(Mat J) {
00121 PetscFunctionBegin;
00122 Jac1MFreeData *data;
00123 iC(MatShellGetContext( J, (void **)&data));
00124 if(data != NULL) {
00125 if(J != data->Jmat_private) {
00126 if(data->Jmat_private) {
00127 MatDestroy(data->Jmat_private);
00128 data->Jmat_private = NULL;
00129 }
00130 }
00131 if(data->inTmp) {
00132 VecDestroy(data->inTmp);
00133 data->inTmp = NULL;
00134 }
00135 if(data->outTmp) {
00136 VecDestroy(data->outTmp);
00137 data->outTmp = NULL;
00138 }
00139 delete data;
00140 data = NULL;
00141 }
00142 PetscFunctionReturn(0);
00143 }
00144
00145 PetscErrorCode MassMatDestroy(Mat J) {
00146 PetscFunctionBegin;
00147 Jac1MFreeData *data;
00148 iC(MatShellGetContext( J, (void **)&data));
00149 if(data) {
00150 if(data->Jmat_private) {
00151 MatDestroy(data->Jmat_private);
00152 data->Jmat_private = NULL;
00153 }
00154 delete data;
00155 data = NULL;
00156 }
00157 PetscFunctionReturn(0);
00158 }
00159
00160 PetscErrorCode Jacobian1MatGetDiagonal(Mat J, Vec diag) {
00161 PetscFunctionBegin;
00162
00163 PetscLogEventBegin(Jac1DiagEvent,diag,0,0,0);
00164 Jac1MFreeData *data;
00165 iC(MatShellGetContext(J, (void **)&data));
00166 if(data->isFinestLevel) {
00167 PetscLogEventBegin(Jac1FinestDiagEvent,diag,0,0,0);
00168 }
00169 iC(VecZeroEntries(diag));
00170
00171 PetscScalar *diagArr;
00172
00173 data->da->vecGetBuffer(diag,diagArr,false,false,false,1);
00174
00175
00176
00177
00178
00179 unsigned int maxD;
00180 double hFac;
00181
00182 PetscReal lapFac = 1.0;
00183 PetscReal massFac = 1.0;
00184 PetscTruth optFound;
00185 PetscOptionsGetReal("lap","-MatPropFac",&lapFac,&optFound);
00186 PetscOptionsGetReal("mass","-MatPropFac",&massFac,&optFound);
00187
00188 if(data->da->iAmActive()) {
00189 maxD = (data->da->getMaxDepth());
00190 hFac = 1.0/((double)(1u << (maxD-1)));
00191
00192
00193 for(data->da->init<ot::DA_FLAGS::ALL>();
00194 data->da->curr() < data->da->end<ot::DA_FLAGS::ALL>();
00195 data->da->next<ot::DA_FLAGS::ALL>()) {
00196
00197 unsigned int lev = data->da->getLevel(data->da->curr());
00198 double h = hFac*(1u << (maxD - lev));
00199 double fac1 = lapFac*h/2.0;
00200 double fac2 = massFac*h*h*h/8.0;
00201 unsigned int indices[8];
00202 data->da->getNodeIndices(indices);
00203 unsigned char childNum = data->da->getChildNumber();
00204 unsigned char hnMask = data->da->getHangingNodeIndex(data->da->curr());
00205 unsigned char elemType = 0;
00206 GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00207 for(int k = 0;k < 8;k++) {
00208 diagArr[indices[k]] += ((fac1*(LaplacianType2Stencil[childNum][elemType][k][k])) +
00209 (fac2*(MassType2Stencil[childNum][elemType][k][k])));
00210 }
00211 }
00212 }
00213
00214 data->da->vecRestoreBuffer(diag,diagArr,false,false,false,1);
00215
00216 PetscLogFlops(44*(data->da->getGhostedElementSize()));
00217 PetscLogEventEnd(Jac1DiagEvent,diag,0,0,0);
00218 if(data->isFinestLevel) {
00219 PetscLogEventEnd(Jac1FinestDiagEvent,diag,0,0,0);
00220 }
00221
00222 PetscFunctionReturn(0);
00223 }
00224
00225 PetscErrorCode MassMatGetDiagonal(Mat J, Vec diag) {
00226 PetscFunctionBegin;
00227 Jac1MFreeData *data;
00228 iC(MatShellGetContext(J, (void **)&data));
00229 iC(VecZeroEntries(diag));
00230
00231
00232
00233
00234
00235 unsigned int maxD;
00236 double hFac;
00237 if(data->da->iAmActive()) {
00238 maxD = (data->da->getMaxDepth());
00239 hFac = 1.0/((double)(1u << (maxD-1)));
00240 }
00241
00242 PetscScalar *diagArr;
00243
00244 data->da->vecGetBuffer(diag,diagArr,false,false,false,1);
00245
00246 if(data->da->iAmActive()) {
00247
00248 for(data->da->init<ot::DA_FLAGS::ALL>();
00249 data->da->curr() < data->da->end<ot::DA_FLAGS::ALL>();
00250 data->da->next<ot::DA_FLAGS::ALL>()) {
00251
00252 unsigned int lev = data->da->getLevel(data->da->curr());
00253 double h = hFac*(1u << (maxD - lev));
00254 double fac2 = h*h*h/8.0;
00255 unsigned int indices[8];
00256 data->da->getNodeIndices(indices);
00257 unsigned char childNum = data->da->getChildNumber();
00258 unsigned char hnMask = data->da->getHangingNodeIndex(data->da->curr());
00259 unsigned char elemType = 0;
00260 GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00261 for(int k = 0;k < 8;k++) {
00262 diagArr[indices[k]] += (fac2*(MassType2Stencil[childNum][elemType][k][k]));
00263 }
00264 }
00265 }
00266
00267 data->da->vecRestoreBuffer(diag,diagArr,false,false,false,1);
00268 PetscFunctionReturn(0);
00269 }
00270
00271 #define JACOBIAN_TYPE1_MULT_BLOCK {\
00272 unsigned int lev = data->da->getLevel(data->da->curr());\
00273 double h = hFac*(1u << (maxD - lev));\
00274 double fac1 = lapFac*h/2.0;\
00275 double fac2 = massFac*h*h*h/8.0;\
00276 unsigned int indices[8];\
00277 data->da->getNodeIndices(indices);\
00278 unsigned char childNum = data->da->getChildNumber();\
00279 unsigned char hnMask = data->da->getHangingNodeIndex(data->da->curr());\
00280 unsigned char elemType = 0;\
00281 GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
00282 for(int k = 0;k < 8;k++) {\
00283 for(int j=0;j<8;j++) {\
00284 outArr[indices[k]] += (((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +\
00285 (fac2*(MassType2Stencil[childNum][elemType][k][j])))*inArr[indices[j]]);\
00286 } \
00287 } \
00288 }
00289
00290 PetscErrorCode Jacobian1MatMult(Mat J, Vec in, Vec out)
00291 {
00292 PetscFunctionBegin;
00293
00294 Jac1MFreeData *data;
00295 PetscLogEventBegin(Jac1MultEvent,in,out,0,0);
00296 iC(MatShellGetContext( J, (void **)&data));
00297 if(data->isFinestLevel) {
00298 PetscLogEventBegin(Jac1FinestMultEvent,in,out,0,0);
00299 }
00300 iC(VecZeroEntries(out));
00301
00302 unsigned int maxD;
00303 double hFac;
00304 if(data->da->iAmActive()) {
00305 maxD = data->da->getMaxDepth();
00306 hFac = 1.0/((double)(1u << (maxD-1)));
00307 }
00308
00309 PetscReal lapFac = 1.0;
00310 PetscReal massFac = 1.0;
00311 PetscTruth optFound;
00312 PetscOptionsGetReal("lap","-MatPropFac",&lapFac,&optFound);
00313 PetscOptionsGetReal("mass","-MatPropFac",&massFac,&optFound);
00314
00315 PetscScalar *outArr=NULL;
00316 PetscScalar *inArr=NULL;
00317
00318 data->da->vecGetBuffer(in,inArr,false,false,true,1);
00319
00320
00321 if(data->da->iAmActive()) {
00322 data->da->ReadFromGhostsBegin<PetscScalar>(inArr,1);
00323 }
00324
00325
00326 data->da->vecGetBuffer(out,outArr,false,false,false,1);
00327
00328
00329
00330 if(data->da->iAmActive()) {
00331 for(data->da->init<ot::DA_FLAGS::INDEPENDENT>();
00332 data->da->curr() < data->da->end<ot::DA_FLAGS::INDEPENDENT>();
00333 data->da->next<ot::DA_FLAGS::INDEPENDENT>() ) {
00334 JACOBIAN_TYPE1_MULT_BLOCK
00335 }
00336 }
00337
00338 if(data->da->iAmActive()) {
00339 data->da->ReadFromGhostsEnd<PetscScalar>(inArr);
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 if(data->da->iAmActive()) {
00354 for(data->da->init<ot::DA_FLAGS::DEPENDENT>();
00355 data->da->curr() < data->da->end<ot::DA_FLAGS::DEPENDENT>();
00356 data->da->next<ot::DA_FLAGS::DEPENDENT>() ) {
00357 JACOBIAN_TYPE1_MULT_BLOCK
00358 }
00359 }
00360
00361 data->da->vecRestoreBuffer(in,inArr,false,false,true,1);
00362 data->da->vecRestoreBuffer(out,outArr,false,false,false,1);
00363
00364
00365
00366
00367 PetscLogFlops(332*(data->da->getGhostedElementSize()));
00368 PetscLogEventEnd(Jac1MultEvent,in,out,0,0);
00369 if(data->isFinestLevel) {
00370 PetscLogEventEnd(Jac1FinestMultEvent,in,out,0,0);
00371 }
00372
00373 PetscFunctionReturn(0);
00374 }
00375
00376 #undef JACOBIAN_TYPE1_MULT_BLOCK
00377
00378 #define MASS_MULT_BLOCK {\
00379 unsigned int lev = data->da->getLevel(data->da->curr());\
00380 double h = hFac*(1u << (maxD - lev));\
00381 double fac2 = h*h*h/8.0;\
00382 unsigned int indices[8];\
00383 data->da->getNodeIndices(indices);\
00384 unsigned char childNum = data->da->getChildNumber();\
00385 unsigned char hnMask = data->da->getHangingNodeIndex(data->da->curr());\
00386 unsigned char elemType = 0;\
00387 GET_ETYPE_BLOCK(elemType,hnMask,childNum)\
00388 for(int k = 0;k < 8;k++) {\
00389 for(int j=0;j<8;j++) {\
00390 outArr[indices[k]] += ((fac2*(MassType2Stencil[childNum][elemType][k][j]))*inArr[indices[j]]);\
00391 } \
00392 } \
00393 }
00394
00395 PetscErrorCode MassMatMult(Mat J, Vec in, Vec out)
00396 {
00397 PetscFunctionBegin;
00398 Jac1MFreeData *data;
00399
00400 iC(MatShellGetContext( J, (void **)&data));
00401
00402 iC (VecSet(out, 0));
00403
00404 unsigned int maxD;
00405 double hFac;
00406
00407 if(data->da->iAmActive()) {
00408 maxD = data->da->getMaxDepth();
00409 hFac = 1.0/((double)(1u << (maxD-1)));
00410 }
00411
00412 PetscScalar *outArr=NULL;
00413 PetscScalar *inArr=NULL;
00414
00415 data->da->vecGetBuffer(in,inArr,false,false,true,1);
00416
00417 if(data->da->iAmActive()) {
00418 data->da->ReadFromGhostsBegin<PetscScalar>(inArr,1);
00419 }
00420
00421
00422 data->da->vecGetBuffer(out,outArr,false,false,false,1);
00423
00424
00425 if(data->da->iAmActive()) {
00426 for(data->da->init<ot::DA_FLAGS::INDEPENDENT>();
00427 data->da->curr() < data->da->end<ot::DA_FLAGS::INDEPENDENT>();
00428 data->da->next<ot::DA_FLAGS::INDEPENDENT>() ) {
00429 MASS_MULT_BLOCK
00430 }
00431 }
00432
00433
00434 if(data->da->iAmActive()) {
00435 data->da->ReadFromGhostsEnd<PetscScalar>(inArr);
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 if(data->da->iAmActive()) {
00450 for(data->da->init<ot::DA_FLAGS::DEPENDENT>();
00451 data->da->curr() < data->da->end<ot::DA_FLAGS::DEPENDENT>();
00452 data->da->next<ot::DA_FLAGS::DEPENDENT>() ) {
00453 MASS_MULT_BLOCK
00454 }
00455 }
00456
00457 data->da->vecRestoreBuffer(in,inArr,false,false,true,1);
00458
00459 data->da->vecRestoreBuffer(out,outArr,false,false,false,1);
00460
00461 PetscFunctionReturn(0);
00462 }
00463
00464 #undef MASS_MULT_BLOCK
00465
00466 PetscErrorCode CreateAndComputeFullJacobian1(ot::DA* da,Mat * J)
00467 {
00468 PetscFunctionBegin;
00469
00470 assert(da->computedLocalToGlobal());
00471
00472 char matType[30];
00473 PetscTruth typeFound;
00474 PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00475 if(!typeFound) {
00476 std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00477 MPI_Finalize();
00478 exit(0);
00479 }
00480 da->createMatrix(*J, matType, 1);
00481 MatZeroEntries(*J);
00482 std::vector<ot::MatRecord> records;
00483
00484 unsigned int maxD;
00485 double hFac;
00486 if(da->iAmActive()) {
00487 maxD = da->getMaxDepth();
00488 hFac = 1.0/((double)(1u << (maxD-1)));
00489 }
00490
00491
00492 PetscReal lapFac = 1.0;
00493 PetscReal massFac = 1.0;
00494 PetscTruth optFound;
00495 PetscOptionsGetReal("lap","-MatPropFac",&lapFac,&optFound);
00496 PetscOptionsGetReal("mass","-MatPropFac",&massFac,&optFound);
00497
00498 if(da->iAmActive()) {
00499 for(da->init<ot::DA_FLAGS::WRITABLE>();
00500 da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();
00501 da->next<ot::DA_FLAGS::WRITABLE>()) {
00502 unsigned int lev = da->getLevel(da->curr());
00503 double h = hFac*(1u << (maxD - lev));
00504 double fac1 = lapFac*h/2.0;
00505 double fac2 = massFac*h*h*h/8.0;
00506 unsigned int indices[8];
00507 da->getNodeIndices(indices);
00508 unsigned char childNum = da->getChildNumber();
00509 unsigned char hnMask = da->getHangingNodeIndex(da->curr());
00510 unsigned char elemType = 0;
00511 GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00512 for(int k = 0;k < 8;k++) {
00513 for(int j=0;j<8;j++) {
00514 ot::MatRecord currRec;
00515 currRec.rowIdx = indices[k];
00516 currRec.colIdx = indices[j];
00517 currRec.rowDim = 0;
00518 currRec.colDim = 0;
00519 currRec.val = ((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
00520 (fac2*(MassType2Stencil[childNum][elemType][k][j])));
00521 records.push_back(currRec);
00522 }
00523 }
00524 if(records.size() > 1000) {
00525 da->setValuesInMatrix(*J, records, 1, ADD_VALUES);
00526 }
00527 }
00528 }
00529
00530 da->setValuesInMatrix(*J, records, 1, ADD_VALUES);
00531
00532 MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY);
00533 MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY);
00534
00535 PetscFunctionReturn(0);
00536 }
00537
00538 PetscErrorCode CreateAndComputeFullActiveJacobian1(ot::DA* da,Mat * J)
00539 {
00540 PetscFunctionBegin;
00541
00542 assert(da->computedLocalToGlobal());
00543
00544 if(da->iAmActive()) {
00545 char matType[30];
00546 PetscTruth typeFound;
00547 PetscOptionsGetString(PETSC_NULL,"-fullJacMatType",matType,30,&typeFound);
00548 if(!typeFound) {
00549 std::cout<<"I need a MatType for the full Jacobian matrix!"<<std::endl;
00550 MPI_Finalize();
00551 exit(0);
00552 }
00553 da->createActiveMatrix(*J, matType, 1);
00554 MatZeroEntries(*J);
00555 std::vector<ot::MatRecord> records;
00556
00557 unsigned int maxD;
00558 double hFac;
00559 maxD = da->getMaxDepth();
00560 hFac = 1.0/((double)(1u << (maxD-1)));
00561
00562 PetscReal lapFac = 1.0;
00563 PetscReal massFac = 1.0;
00564 PetscTruth optFound;
00565 PetscOptionsGetReal("lap","-MatPropFac",&lapFac,&optFound);
00566 PetscOptionsGetReal("mass","-MatPropFac",&massFac,&optFound);
00567
00568 for(da->init<ot::DA_FLAGS::WRITABLE>();
00569 da->curr() < da->end<ot::DA_FLAGS::WRITABLE>();
00570 da->next<ot::DA_FLAGS::WRITABLE>()) {
00571 unsigned int lev = da->getLevel(da->curr());
00572 double h = hFac*(1u << (maxD - lev));
00573 double fac1 = lapFac*h/2.0;
00574 double fac2 = massFac*h*h*h/8.0;
00575 unsigned int indices[8];
00576 da->getNodeIndices(indices);
00577 unsigned char childNum = da->getChildNumber();
00578 unsigned char hnMask = da->getHangingNodeIndex(da->curr());
00579 unsigned char elemType = 0;
00580 GET_ETYPE_BLOCK(elemType,hnMask,childNum)
00581 for(int k = 0;k < 8;k++) {
00582 for(int j=0;j<8;j++) {
00583 ot::MatRecord currRec;
00584 currRec.rowIdx = indices[k];
00585 currRec.colIdx = indices[j];
00586 currRec.rowDim = 0;
00587 currRec.colDim = 0;
00588 currRec.val =
00589 ((fac1*(LaplacianType2Stencil[childNum][elemType][k][j])) +
00590 (fac2*(MassType2Stencil[childNum][elemType][k][j])));
00591 records.push_back(currRec);
00592 }
00593 }
00594 if(records.size() > 1000) {
00595 da->setValuesInMatrix(*J, records, 1, ADD_VALUES);
00596 }
00597 }
00598
00599 da->setValuesInMatrix(*J, records, 1, ADD_VALUES);
00600
00601 MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY);
00602 MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY);
00603
00604 }
00605
00606 PetscFunctionReturn(0);
00607 }
00608
00609
00610