00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "PCTwoLevelsBlockDiagonal.hpp"
00030 #include "Exception.hpp"
00031
00032 #include <iostream>
00033
00034 PCTwoLevelsBlockDiagonal::PCTwoLevelsBlockDiagonal(KSP& rKspObject, std::vector<PetscInt>& rBathNodes)
00035 {
00036 PCTwoLevelsBlockDiagonalCreate(rKspObject, rBathNodes);
00037 PCTwoLevelsBlockDiagonalSetUp();
00038 }
00039
00040 PCTwoLevelsBlockDiagonal::~PCTwoLevelsBlockDiagonal()
00041 {
00042 MatDestroy(mPCContext.A11_matrix_subblock);
00043 MatDestroy(mPCContext.A22_B1_matrix_subblock);
00044 MatDestroy(mPCContext.A22_B2_matrix_subblock);
00045
00046 PCDestroy(mPCContext.PC_amg_A11);
00047 PCDestroy(mPCContext.PC_amg_A22_B1);
00048 PCDestroy(mPCContext.PC_amg_A22_B2);
00049
00050 VecDestroy(mPCContext.x1_subvector);
00051 VecDestroy(mPCContext.y1_subvector);
00052
00053 VecDestroy(mPCContext.x21_subvector);
00054 VecDestroy(mPCContext.y21_subvector);
00055
00056 VecDestroy(mPCContext.x22_subvector);
00057 VecDestroy(mPCContext.y22_subvector);
00058
00059 VecScatterDestroy(mPCContext.A11_scatter_ctx);
00060 VecScatterDestroy(mPCContext.A22_B1_scatter_ctx);
00061 VecScatterDestroy(mPCContext.A22_B2_scatter_ctx);
00062 }
00063
00064 void PCTwoLevelsBlockDiagonal::PCTwoLevelsBlockDiagonalCreate(KSP& rKspObject, std::vector<PetscInt>& rBathNodes)
00065 {
00066 KSPGetPC(rKspObject, &mPetscPCObject);
00067
00068 Mat system_matrix, dummy;
00069 MatStructure flag;
00070 KSPGetOperators(rKspObject, &system_matrix, &dummy, &flag);
00071
00072 PetscInt num_rows, num_columns;
00073 MatGetSize(system_matrix, &num_rows, &num_columns);
00074 assert(num_rows==num_columns);
00075
00076 PetscInt num_local_rows, num_local_columns;
00077 MatGetLocalSize(system_matrix, &num_local_rows, &num_local_columns);
00078
00079
00080
00081 if ((num_rows%2 != 0) || (num_local_rows%2 != 0))
00082 {
00083 TERMINATE("Wrong matrix parallel layout detected in PCLDUFactorisation.");
00084 }
00085
00086
00087 unsigned subvector_num_rows = num_rows/2;
00088 unsigned subvector_local_rows = num_local_rows/2;
00089
00090 unsigned subvector_num_rows_tissue = subvector_num_rows - rBathNodes.size();
00091 unsigned subvector_local_rows_tissue = subvector_num_rows_tissue;
00092
00093 unsigned subvector_num_rows_bath = rBathNodes.size();
00094 unsigned subvector_local_rows_bath = subvector_num_rows_bath;
00095
00096 assert(PetscTools::IsSequential());
00097
00098 mPCContext.x1_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows);
00099 mPCContext.x21_subvector = PetscTools::CreateVec(subvector_num_rows_tissue, subvector_local_rows_tissue);
00100 mPCContext.x22_subvector = PetscTools::CreateVec(subvector_num_rows_bath, subvector_local_rows_bath);
00101 mPCContext.y1_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows);
00102 mPCContext.y21_subvector = PetscTools::CreateVec(subvector_num_rows_tissue, subvector_local_rows_tissue);
00103 mPCContext.y22_subvector = PetscTools::CreateVec(subvector_num_rows_bath, subvector_local_rows_bath);
00104
00105
00106
00107
00108 IS A11_all_rows;
00109 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 0, 2, &A11_all_rows);
00110
00111 IS A22_all_rows;
00112 PetscInt A22_size;
00113 VecGetSize(mPCContext.x1_subvector, &A22_size);
00115 ISCreateStride(PETSC_COMM_WORLD, A22_size, 1, 2, &A22_all_rows);
00116
00117 IS A22_bath_rows;
00118 PetscInt* phi_e_bath_rows = new PetscInt[rBathNodes.size()];
00119 for (unsigned index=0; index<rBathNodes.size(); index++)
00120 {
00121 phi_e_bath_rows[index] = 2*rBathNodes[index] + 1;
00122 }
00123 ISCreateGeneralWithArray(PETSC_COMM_WORLD, rBathNodes.size(), phi_e_bath_rows, &A22_bath_rows);
00124
00125 IS A22_tissue_rows;
00126 ISDifference(A22_all_rows, A22_bath_rows, &A22_tissue_rows);
00127
00128
00129 {
00130
00131 Vec dummy_vec = PetscTools::CreateVec(num_rows, num_local_rows);
00132
00134 IS& A11_rows=A11_all_rows;
00135 IS& A22_B1_rows=A22_tissue_rows;
00136 IS& A22_B2_rows=A22_bath_rows;
00137
00138 IS all_vector;
00139 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 0, 1, &all_vector);
00140
00141 IS tissue_vector;
00142 ISCreateStride(PETSC_COMM_WORLD, (num_rows/2)-rBathNodes.size(), 0, 1, &tissue_vector);
00143
00144 IS bath_vector;
00145 ISCreateStride(PETSC_COMM_WORLD, rBathNodes.size(), 0, 1, &bath_vector);
00146
00147 VecScatterCreate(dummy_vec, A11_rows, mPCContext.x1_subvector, all_vector, &mPCContext.A11_scatter_ctx);
00148 VecScatterCreate(dummy_vec, A22_B1_rows, mPCContext.x21_subvector, tissue_vector, &mPCContext.A22_B1_scatter_ctx);
00149 VecScatterCreate(dummy_vec, A22_B2_rows, mPCContext.x22_subvector, bath_vector, &mPCContext.A22_B2_scatter_ctx);
00150
00151 ISDestroy(all_vector);
00152 ISDestroy(tissue_vector);
00153 ISDestroy(bath_vector);
00154
00155 VecDestroy(dummy_vec);
00156 }
00157
00158
00159 {
00160
00161 PetscInt low, high, global_size;
00162 VecGetOwnershipRange(mPCContext.x1_subvector, &low, &high);
00163 VecGetSize(mPCContext.x1_subvector, &global_size);
00164 assert(global_size == num_rows/2);
00165
00166 IS A11_local_rows;
00167 IS& A11_columns=A11_all_rows;
00168 ISCreateStride(PETSC_COMM_WORLD, high-low, 2*low, 2, &A11_local_rows);
00169
00170 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00171 MatGetSubMatrix(system_matrix, A11_local_rows, A11_columns,
00172 MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock);
00173 #else
00174 MatGetSubMatrix(system_matrix, A11_local_rows, A11_columns, PETSC_DECIDE,
00175 MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock);
00176 #endif
00177
00178 ISDestroy(A11_local_rows);
00179 }
00180
00181
00182 {
00183
00184
00185
00186
00187
00188
00189 assert(PetscTools::IsSequential());
00190 IS& A22_B1_local_rows = A22_tissue_rows;
00191 IS& A22_B1_columns = A22_tissue_rows;
00192
00193 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00194 MatGetSubMatrix(system_matrix, A22_B1_local_rows, A22_B1_columns,
00195 MAT_INITIAL_MATRIX, &mPCContext.A22_B1_matrix_subblock);
00196 #else
00197 MatGetSubMatrix(system_matrix, A22_B1_local_rows, A22_B1_columns, PETSC_DECIDE,
00198 MAT_INITIAL_MATRIX, &mPCContext.A22_B1_matrix_subblock);
00199 #endif
00200
00201 }
00202
00203
00204 {
00205
00206
00207
00208
00209
00210
00211 assert(PetscTools::IsSequential());
00212 IS& A22_B2_local_rows = A22_bath_rows;
00213 IS& A22_B2_columns = A22_bath_rows;
00214
00215 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00216 MatGetSubMatrix(system_matrix, A22_B2_local_rows, A22_B2_columns,
00217 MAT_INITIAL_MATRIX, &mPCContext.A22_B2_matrix_subblock);
00218 #else
00219 MatGetSubMatrix(system_matrix, A22_B2_local_rows, A22_B2_columns, PETSC_DECIDE,
00220 MAT_INITIAL_MATRIX, &mPCContext.A22_B2_matrix_subblock);
00221 #endif
00222
00223 }
00224
00225 ISDestroy(A11_all_rows);
00226 ISDestroy(A22_all_rows);
00227 ISDestroy(A22_bath_rows);
00228 delete[] phi_e_bath_rows;
00229 ISDestroy(A22_tissue_rows);
00230
00231
00232 PCSetType(mPetscPCObject, PCSHELL);
00233 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00234 PCShellSetApply(mPetscPCObject, PCTwoLevelsBlockDiagonalApply, (void*) &mPCContext);
00235 #else
00236
00237 PCShellSetContext(mPetscPCObject, &mPCContext);
00238
00239 PCShellSetApply(mPetscPCObject, PCTwoLevelsBlockDiagonalApply);
00240 #endif
00241 }
00242
00243 void PCTwoLevelsBlockDiagonal::PCTwoLevelsBlockDiagonalSetUp()
00244 {
00245
00246 PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1");
00247 PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0");
00248 PetscOptionsSetValue("-pc_hypre_type", "boomeramg");
00249
00250
00251 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A11));
00252 PCSetType(mPCContext.PC_amg_A11, PCBJACOBI);
00253 PCSetOperators(mPCContext.PC_amg_A11, mPCContext.A11_matrix_subblock, mPCContext.A11_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00254 PCSetFromOptions(mPCContext.PC_amg_A11);
00255 PCSetUp(mPCContext.PC_amg_A11);
00256
00257
00258 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A22_B1));
00259 PCSetType(mPCContext.PC_amg_A22_B1, PCBJACOBI);
00260 PCSetOperators(mPCContext.PC_amg_A22_B1, mPCContext.A22_B1_matrix_subblock, mPCContext.A22_B1_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00261 PCSetFromOptions(mPCContext.PC_amg_A22_B1);
00262 PCSetUp(mPCContext.PC_amg_A22_B1);
00263
00264
00265 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A22_B2));
00266 PCSetType(mPCContext.PC_amg_A22_B2, PCHYPRE);
00267
00268 PetscOptionsSetValue("-pc_hypre_type", "boomeramg");
00269
00270 PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1");
00271 PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0");
00272 PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type", "HMIS");
00273
00274 PCSetOperators(mPCContext.PC_amg_A22_B2, mPCContext.A22_B2_matrix_subblock, mPCContext.A22_B2_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00275 PCSetFromOptions(mPCContext.PC_amg_A22_B2);
00276 PCSetUp(mPCContext.PC_amg_A22_B2);
00277 }
00278
00279 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00280 PetscErrorCode PCTwoLevelsBlockDiagonalApply(PC pc_object, Vec x, Vec y)
00281 {
00282 void* pc_context;
00283
00284 PCShellGetContext(pc_object, &pc_context);
00285 #else
00286 PetscErrorCode PCTwoLevelsBlockDiagonalApply(void* pc_context, Vec x, Vec y)
00287 {
00288 #endif
00289
00290
00291 PCTwoLevelsBlockDiagonal::PCTwoLevelsBlockDiagonalContext* block_diag_context = (PCTwoLevelsBlockDiagonal::PCTwoLevelsBlockDiagonalContext*) pc_context;
00292 assert(block_diag_context!=NULL);
00293
00294
00295
00296
00297
00298 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00299 VecScatterBegin(block_diag_context->A11_scatter_ctx, x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD);
00300 VecScatterEnd(block_diag_context->A11_scatter_ctx, x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD);
00301 #else
00302 VecScatterBegin(x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A11_scatter_ctx);
00303 VecScatterEnd(x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A11_scatter_ctx);
00304 #endif
00305
00306
00307 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00308 VecScatterBegin(block_diag_context->A22_B1_scatter_ctx, x, block_diag_context->x21_subvector, INSERT_VALUES, SCATTER_FORWARD);
00309 VecScatterEnd(block_diag_context->A22_B1_scatter_ctx, x, block_diag_context->x21_subvector, INSERT_VALUES, SCATTER_FORWARD);
00310 #else
00311 VecScatterBegin(x, block_diag_context->x21_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A22_B1_scatter_ctx);
00312 VecScatterEnd(x, block_diag_context->x21_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A22_B1_scatter_ctx);
00313 #endif
00314
00315
00316 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00317 VecScatterBegin(block_diag_context->A22_B2_scatter_ctx, x, block_diag_context->x22_subvector, INSERT_VALUES, SCATTER_FORWARD);
00318 VecScatterEnd(block_diag_context->A22_B2_scatter_ctx, x, block_diag_context->x22_subvector, INSERT_VALUES, SCATTER_FORWARD);
00319 #else
00320 VecScatterBegin(x, block_diag_context->x22_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A22_B2_scatter_ctx);
00321 VecScatterEnd(x, block_diag_context->x22_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A22_B2_scatter_ctx);
00322 #endif
00323
00324
00325
00326
00327
00328
00329 PCApply(block_diag_context->PC_amg_A11, block_diag_context->x1_subvector, block_diag_context->y1_subvector);
00330 PCApply(block_diag_context->PC_amg_A22_B1, block_diag_context->x21_subvector, block_diag_context->y21_subvector);
00331 PCApply(block_diag_context->PC_amg_A22_B2, block_diag_context->x22_subvector, block_diag_context->y22_subvector);
00332
00333
00334
00335
00336
00337 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00338 VecScatterBegin(block_diag_context->A11_scatter_ctx, block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00339 VecScatterEnd(block_diag_context->A11_scatter_ctx, block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00340 #else
00341 VecScatterBegin(block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A11_scatter_ctx);
00342 VecScatterEnd(block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A11_scatter_ctx);
00343 #endif
00344
00345
00346 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00347 VecScatterBegin(block_diag_context->A22_B1_scatter_ctx, block_diag_context->y21_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00348 VecScatterEnd(block_diag_context->A22_B1_scatter_ctx, block_diag_context->y21_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00349 #else
00350 VecScatterBegin(block_diag_context->y21_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A22_B1_scatter_ctx);
00351 VecScatterEnd(block_diag_context->y21_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A22_B1_scatter_ctx);
00352 #endif
00353
00354
00355 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00356 VecScatterBegin(block_diag_context->A22_B2_scatter_ctx, block_diag_context->y22_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00357 VecScatterEnd(block_diag_context->A22_B2_scatter_ctx, block_diag_context->y22_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00358 #else
00359 VecScatterBegin(block_diag_context->y22_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A22_B2_scatter_ctx);
00360 VecScatterEnd(block_diag_context->y22_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A22_B2_scatter_ctx);
00361 #endif
00362
00363 return 0;
00364 }