00001
00007 #include "petscmat.h"
00008 #include "petscpc.h"
00009 #include "private/pcimpl.h"
00010 #include "blockDiag.h"
00011 #include <cassert>
00012
00013 namespace ot {
00014
00015 extern void (*getDofAndNodeSizeForPC_BlockDiag)(Mat pcMat,
00016 unsigned int & dof, unsigned int & nodeSize);
00017
00018 extern void (*computeInvBlockDiagEntriesForPC_BlockDiag)(Mat pcMat,
00019 double **invBlockDiagEntries);
00020
00021
00022 PetscErrorCode PCSetUp_BlockDiag(PC pc) {
00023
00024 PetscFunctionBegin;
00025 PC_BlockDiag* data = static_cast<PC_BlockDiag*>(pc->data);
00026
00027 Mat pcMat = pc->pmat;
00028 PetscTruth isshell;
00029 PetscTypeCompare((PetscObject)pcMat, MATSHELL, &isshell);
00030
00031 if(!isshell) {
00032 SETERRQ(PETSC_ERR_SUP," Expected a MATSHELL.");
00033 assert(false);
00034 }
00035
00036 if(pc->setupcalled == 0) {
00037 if(getDofAndNodeSizeForPC_BlockDiag) {
00038 (*getDofAndNodeSizeForPC_BlockDiag)(pcMat, data->dof, data->nodeSize);
00039 } else {
00040 SETERRQ(PETSC_ERR_USER," Expected function to be set: getDofAndNodeSizeForPC_BlockDiag");
00041 assert(false);
00042 }
00043
00044
00045 assert(data->invBlockDiagEntries == NULL);
00046 if((data->dof) && (data->nodeSize)) {
00047 typedef double* doublePtr;
00048 data->invBlockDiagEntries = new doublePtr[(data->dof)*(data->nodeSize)];
00049 for(int i = 0; i < ((data->dof)*(data->nodeSize)); i++) {
00050 data->invBlockDiagEntries[i] = new double[data->dof];
00051 }
00052 PetscLogObjectMemory(pc, (((data->dof)*(data->nodeSize))*sizeof(double)));
00053 }
00054 }
00055
00056 if(computeInvBlockDiagEntriesForPC_BlockDiag) {
00057 (*computeInvBlockDiagEntriesForPC_BlockDiag)(pcMat, data->invBlockDiagEntries);
00058 } else {
00059 SETERRQ(PETSC_ERR_USER,
00060 " Expected function to be set: computeInvBlockDiagEntriesForPC_BlockDiag");
00061 assert(false);
00062 }
00063
00064 PetscFunctionReturn(0);
00065 }
00066
00067 PetscErrorCode PCApply_BlockDiag(PC pc, Vec x, Vec y) {
00068
00069 PetscFunctionBegin;
00070 PC_BlockDiag* data = static_cast<PC_BlockDiag*>(pc->data);
00071
00072
00073 VecZeroEntries(y);
00074 PetscScalar *yArr = NULL;
00075 PetscScalar *xArr = NULL;
00076 VecGetArray(y, &yArr);
00077 VecGetArray(x, &xArr);
00078 for(int i = 0; i < data->nodeSize; i++) {
00079 for(int j = 0; j < data->dof; j++) {
00080 for(int k = 0; k < data->dof; k++) {
00081 yArr[((data->dof)*i) + j] +=
00082 ((data->invBlockDiagEntries[((data->dof)*i) + j][k])*
00083 xArr[((data->dof)*i) + k]);
00084 }
00085 }
00086 }
00087 VecRestoreArray(y, &yArr);
00088 VecRestoreArray(x, &xArr);
00089
00090 PetscFunctionReturn(0);
00091 }
00092
00093 PetscErrorCode PCCreate_BlockDiag(PC pc) {
00094
00095 PetscFunctionBegin;
00096 PC_BlockDiag* data = new PC_BlockDiag;
00097
00098 pc->data = (void*)(data);
00099
00100 PetscLogObjectMemory(pc, sizeof(PC_BlockDiag));
00101
00102
00103 data->dof = 0;
00104 data->nodeSize = 0;
00105 data->invBlockDiagEntries = NULL;
00106
00107 pc->ops->apply = PCApply_BlockDiag;
00108 pc->ops->setup = PCSetUp_BlockDiag;
00109 pc->ops->destroy = PCDestroy_BlockDiag;
00110 pc->ops->setfromoptions = PCSetFromOptions_BlockDiag;
00111 pc->ops->applytranspose = NULL;
00112 pc->ops->view = NULL;
00113 pc->ops->applyrichardson = NULL;
00114 pc->ops->applysymmetricleft = NULL;
00115 pc->ops->applysymmetricright = NULL;
00116
00117 PetscFunctionReturn(0);
00118 }
00119
00120 PetscErrorCode PCDestroy_BlockDiag(PC pc) {
00121
00122 PetscFunctionBegin;
00123 PC_BlockDiag* data = static_cast<PC_BlockDiag*>(pc->data);
00124
00125 if(data) {
00126
00127 if(data->invBlockDiagEntries) {
00128 for(int i = 0; i < ((data->dof)*(data->nodeSize)); i++) {
00129 delete [] (data->invBlockDiagEntries[i]);
00130 data->invBlockDiagEntries[i] = NULL;
00131 }
00132 delete [] (data->invBlockDiagEntries);
00133 data->invBlockDiagEntries = NULL;
00134 }
00135
00136 delete data;
00137 data = NULL;
00138
00139 }
00140
00141 PetscFunctionReturn(0);
00142 }
00143
00144 PetscErrorCode PCSetFromOptions_BlockDiag(PC pc) {
00145 PetscFunctionBegin;
00146 PetscFunctionReturn(0);
00147 }
00148
00149 }
00150
00151