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 "PCBlockDiagonal.hpp"
00030 #include "Exception.hpp"
00031
00032
00033
00034 PCBlockDiagonal::PCBlockDiagonal(KSP& rKspObject)
00035 {
00036 PCBlockDiagonalCreate(rKspObject);
00037 PCBlockDiagonalSetUp();
00038 }
00039
00040 PCBlockDiagonal::~PCBlockDiagonal()
00041 {
00042 MatDestroy(mPCContext.A11_matrix_subblock);
00043 MatDestroy(mPCContext.A22_matrix_subblock);
00044
00045 PCDestroy(mPCContext.PC_amg_A11);
00046 PCDestroy(mPCContext.PC_amg_A22);
00047
00048 VecDestroy(mPCContext.x1_subvector);
00049 VecDestroy(mPCContext.y1_subvector);
00050
00051 VecDestroy(mPCContext.x2_subvector);
00052 VecDestroy(mPCContext.y2_subvector);
00053
00054 VecScatterDestroy(mPCContext.A11_scatter_ctx);
00055 VecScatterDestroy(mPCContext.A22_scatter_ctx);
00056 }
00057
00058 void PCBlockDiagonal::PCBlockDiagonalCreate(KSP& rKspObject)
00059 {
00060 KSPGetPC(rKspObject, &mPetscPCObject);
00061
00062 Mat system_matrix, dummy;
00063 MatStructure flag;
00064 KSPGetOperators(rKspObject, &system_matrix, &dummy, &flag);
00065
00066 PetscInt num_rows, num_columns;
00067 MatGetSize(system_matrix, &num_rows, &num_columns);
00068 assert(num_rows==num_columns);
00069
00070 PetscInt num_local_rows, num_local_columns;
00071 MatGetLocalSize(system_matrix, &num_local_rows, &num_local_columns);
00072
00073
00074
00075 if ((num_rows%2 != 0) || (num_local_rows%2 != 0))
00076 {
00077 TERMINATE("Wrong matrix parallel layout detected in PCLDUFactorisation.");
00078 }
00079
00080
00081 unsigned subvector_num_rows = num_rows/2;
00082 unsigned subvector_local_rows = num_local_rows/2;
00083 mPCContext.x1_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows);
00084 mPCContext.x2_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows);
00085 mPCContext.y1_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows);
00086 mPCContext.y2_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows);
00087
00088
00089 {
00090
00091 Vec dummy_vec = PetscTools::CreateVec(num_rows, num_local_rows);
00092
00093 IS A11_rows, A22_rows;
00094 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 0, 2, &A11_rows);
00095 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 1, 2, &A22_rows);
00096
00097 IS all_vector;
00098 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 0, 1, &all_vector);
00099
00100 VecScatterCreate(dummy_vec, A11_rows, mPCContext.x1_subvector, all_vector, &mPCContext.A11_scatter_ctx);
00101 VecScatterCreate(dummy_vec, A22_rows, mPCContext.x2_subvector, all_vector, &mPCContext.A22_scatter_ctx);
00102
00103 ISDestroy(A11_rows);
00104 ISDestroy(A22_rows);
00105 ISDestroy(all_vector);
00106
00107 VecDestroy(dummy_vec);
00108 }
00109
00110
00111 {
00112
00113 PetscInt low, high, global_size;
00114 VecGetOwnershipRange(mPCContext.x1_subvector, &low, &high);
00115 VecGetSize(mPCContext.x1_subvector, &global_size);
00116 assert(global_size == num_rows/2);
00117
00118 IS A11_local_rows;
00119 IS A11_columns;
00120 ISCreateStride(PETSC_COMM_WORLD, high-low, 2*low, 2, &A11_local_rows);
00121 ISCreateStride(PETSC_COMM_WORLD, global_size, 0, 2, &A11_columns);
00122
00123 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00124 MatGetSubMatrix(system_matrix, A11_local_rows, A11_columns,
00125 MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock);
00126 #else
00127 MatGetSubMatrix(system_matrix, A11_local_rows, A11_columns, PETSC_DECIDE,
00128 MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock);
00129 #endif
00130
00131
00132 ISDestroy(A11_local_rows);
00133 ISDestroy(A11_columns);
00134 }
00135
00136
00137 {
00138
00139 PetscInt low, high, global_size;
00140 VecGetOwnershipRange(mPCContext.x2_subvector, &low, &high);
00141 VecGetSize(mPCContext.x2_subvector, &global_size);
00142 assert(global_size == num_rows/2);
00143
00144 IS A22_local_rows;
00145 IS A22_columns;
00146 ISCreateStride(PETSC_COMM_WORLD, high-low, 2*low+1, 2, &A22_local_rows);
00147 ISCreateStride(PETSC_COMM_WORLD, global_size, 1, 2, &A22_columns);
00148
00149 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00150 MatGetSubMatrix(system_matrix, A22_local_rows, A22_columns,
00151 MAT_INITIAL_MATRIX, &mPCContext.A22_matrix_subblock);
00152 #else
00153 MatGetSubMatrix(system_matrix, A22_local_rows, A22_columns, PETSC_DECIDE,
00154 MAT_INITIAL_MATRIX, &mPCContext.A22_matrix_subblock);
00155 #endif
00156
00157 ISDestroy(A22_local_rows);
00158 ISDestroy(A22_columns);
00159 }
00160
00161
00162 PCSetType(mPetscPCObject, PCSHELL);
00163 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00164 PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply, (void*) &mPCContext);
00165 #else
00166
00167 PCShellSetContext(mPetscPCObject, &mPCContext);
00168
00169 PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply);
00170 #endif
00171
00172 }
00173
00174 void PCBlockDiagonal::PCBlockDiagonalSetUp()
00175 {
00176
00177 PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1");
00178 PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0");
00179 PetscOptionsSetValue("-pc_hypre_type", "boomeramg");
00180
00181
00182 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A11));
00183 PCSetType(mPCContext.PC_amg_A11, PCBJACOBI);
00184
00185
00186
00187 PCSetOperators(mPCContext.PC_amg_A11, mPCContext.A11_matrix_subblock, mPCContext.A11_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00188 PCSetFromOptions(mPCContext.PC_amg_A11);
00189 PCSetUp(mPCContext.PC_amg_A11);
00190
00191
00192 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A22));
00193
00194
00195 PCSetType(mPCContext.PC_amg_A22, PCHYPRE);
00196
00197 PetscOptionsSetValue("-pc_hypre_type", "boomeramg");
00198
00199 PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1");
00200 PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0");
00201 PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type", "HMIS");
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 PCSetOperators(mPCContext.PC_amg_A22, mPCContext.A22_matrix_subblock, mPCContext.A22_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00241 PCSetFromOptions(mPCContext.PC_amg_A22);
00242 PCSetUp(mPCContext.PC_amg_A22);
00243 }
00244
00245 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 1) //PETSc 3.1
00246 PetscErrorCode PCBlockDiagonalApply(PC pc_object, Vec x, Vec y)
00247 {
00248 void* pc_context;
00249
00250 PCShellGetContext(pc_object, &pc_context);
00251 #else
00252 PetscErrorCode PCBlockDiagonalApply(void* pc_context, Vec x, Vec y)
00253 {
00254 #endif
00255
00256
00257 PCBlockDiagonal::PCBlockDiagonalContext* block_diag_context = (PCBlockDiagonal::PCBlockDiagonalContext*) pc_context;
00258 assert(block_diag_context!=NULL);
00259
00260
00261
00262
00263
00264
00265 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00266 VecScatterBegin(block_diag_context->A11_scatter_ctx, x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD);
00267 VecScatterEnd(block_diag_context->A11_scatter_ctx, x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD);
00268 #else
00269 VecScatterBegin(x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A11_scatter_ctx);
00270 VecScatterEnd(x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A11_scatter_ctx);
00271 #endif
00272
00273
00274 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00275 VecScatterBegin(block_diag_context->A22_scatter_ctx, x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD);
00276 VecScatterEnd(block_diag_context->A22_scatter_ctx, x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD);
00277 #else
00278 VecScatterBegin(x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A22_scatter_ctx);
00279 VecScatterEnd(x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD, block_diag_context->A22_scatter_ctx);
00280 #endif
00281
00282
00283
00284
00285
00286
00287 PCApply(block_diag_context->PC_amg_A11, block_diag_context->x1_subvector, block_diag_context->y1_subvector);
00288
00289 PCApply(block_diag_context->PC_amg_A22, block_diag_context->x2_subvector, block_diag_context->y2_subvector);
00290
00291
00292
00293
00294
00295
00296 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00297 VecScatterBegin(block_diag_context->A11_scatter_ctx, block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00298 VecScatterEnd(block_diag_context->A11_scatter_ctx, block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00299 #else
00300 VecScatterBegin(block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A11_scatter_ctx);
00301 VecScatterEnd(block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A11_scatter_ctx);
00302 #endif
00303
00304
00305 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00306 VecScatterBegin(block_diag_context->A22_scatter_ctx, block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00307 VecScatterEnd(block_diag_context->A22_scatter_ctx, block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00308 #else
00309 VecScatterBegin(block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A22_scatter_ctx);
00310 VecScatterEnd(block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE, block_diag_context->A22_scatter_ctx);
00311 #endif
00312
00313
00314 return 0;
00315 }