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 PCBlockDiagonal::PCBlockDiagonal(KSP& rKspObject)
00033 {
00034 PCBlockDiagonalCreate(rKspObject);
00035 PCBlockDiagonalSetUp();
00036 }
00037
00038 PCBlockDiagonal::~PCBlockDiagonal()
00039 {
00040 MatDestroy(mPCContext.A11_matrix_subblock);
00041 MatDestroy(mPCContext.A22_matrix_subblock);
00042
00043 PCDestroy(mPCContext.PC_amg_A11);
00044 PCDestroy(mPCContext.PC_amg_A22);
00045
00046 VecDestroy(mPCContext.x1_subvector);
00047 VecDestroy(mPCContext.y1_subvector);
00048
00049 VecDestroy(mPCContext.x2_subvector);
00050 VecDestroy(mPCContext.y2_subvector);
00051 }
00052
00053 void PCBlockDiagonal::PCBlockDiagonalCreate(KSP& rKspObject)
00054 {
00055 KSPGetPC(rKspObject, &mPetscPCObject);
00056
00057 Mat system_matrix, dummy;
00058 MatStructure flag;
00059 KSPGetOperators(rKspObject, &system_matrix, &dummy, &flag);
00060
00061 PetscInt num_rows, num_columns;
00062 MatGetSize(system_matrix, &num_rows, &num_columns);
00063 assert(num_rows==num_columns);
00064
00065 PCSetType(mPetscPCObject, PCSHELL);
00066 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00067 PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply, (void*) &mPCContext);
00068 #else
00069
00070 PCShellSetContext(mPetscPCObject, &mPCContext);
00071
00072 PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply);
00073 #endif
00074
00075
00076 IS A11_rows, A11_columns;
00077 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 0, 2, &A11_rows);
00078 ISCreateStride(PETSC_COMM_WORLD, num_columns/2, 0, 2, &A11_columns);
00079
00080 MatGetSubMatrix(system_matrix, A11_rows, A11_columns, PETSC_DECIDE, MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock);
00081
00082 ISDestroy(A11_rows);
00083 ISDestroy(A11_columns);
00084
00085
00086 IS A22_rows, A22_columns;
00087 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 1, 2, &A22_rows);
00088 ISCreateStride(PETSC_COMM_WORLD, num_columns/2, 1, 2, &A22_columns);
00089
00090 MatGetSubMatrix(system_matrix, A22_rows, A22_columns, PETSC_DECIDE, MAT_INITIAL_MATRIX, &mPCContext.A22_matrix_subblock);
00091
00092 ISDestroy(A22_rows);
00093 ISDestroy(A22_columns);
00094
00095
00096 mPCContext.x1_subvector = PetscTools::CreateVec(num_rows/2);
00097 mPCContext.x2_subvector = PetscTools::CreateVec(num_rows/2);
00098 mPCContext.y1_subvector = PetscTools::CreateVec(num_rows/2);
00099 mPCContext.y2_subvector = PetscTools::CreateVec(num_rows/2);
00100 }
00101
00102 void PCBlockDiagonal::PCBlockDiagonalSetUp()
00103 {
00104
00105 PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1");
00106 PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0");
00107 PetscOptionsSetValue("-pc_hypre_type", "boomeramg");
00108
00109
00110 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A11));
00111 PCSetType(mPCContext.PC_amg_A11, PCBJACOBI);
00112 PCSetOperators(mPCContext.PC_amg_A11, mPCContext.A11_matrix_subblock, mPCContext.A11_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00113 PCSetFromOptions(mPCContext.PC_amg_A11);
00114 PCSetUp(mPCContext.PC_amg_A11);
00115
00116
00117 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A22));
00118 PCSetType(mPCContext.PC_amg_A22, PCHYPRE);
00119 PCSetOperators(mPCContext.PC_amg_A22, mPCContext.A22_matrix_subblock, mPCContext.A22_matrix_subblock, DIFFERENT_NONZERO_PATTERN);
00120 PCSetFromOptions(mPCContext.PC_amg_A22);
00121 PCSetUp(mPCContext.PC_amg_A22);
00122 }
00123
00124 PetscErrorCode PCBlockDiagonalApply(void* pc_context, Vec x, Vec y)
00125 {
00127
00128
00129 PCBlockDiagonal::PCBlockDiagonalContext* block_diag_context = (PCBlockDiagonal::PCBlockDiagonalContext*) pc_context;
00130 assert(block_diag_context!=NULL);
00131
00133 PetscInt num_rows;
00134 VecGetSize(x, &num_rows);
00135
00136 IS A11_rows;
00137 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 0, 2, &A11_rows);
00138
00139 VecScatter A11_scatter_ctx;
00140 VecScatterCreate(x, A11_rows, block_diag_context->x1_subvector, PETSC_NULL, &A11_scatter_ctx);
00141
00142
00143 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00144 VecScatterBegin(A11_scatter_ctx, x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD);
00145 VecScatterEnd(A11_scatter_ctx, x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD);
00146 #else
00147 VecScatterBegin(x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD, A11_scatter_ctx);
00148 VecScatterEnd(x, block_diag_context->x1_subvector, INSERT_VALUES, SCATTER_FORWARD, A11_scatter_ctx);
00149 #endif
00150
00151 IS A22_rows;
00152 ISCreateStride(PETSC_COMM_WORLD, num_rows/2, 1, 2, &A22_rows);
00153
00154 VecScatter A22_scatter_ctx;
00155 VecScatterCreate(x, A22_rows, block_diag_context->x2_subvector, PETSC_NULL, &A22_scatter_ctx);
00156
00157
00158 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00159 VecScatterBegin(A22_scatter_ctx, x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD);
00160 VecScatterEnd(A22_scatter_ctx, x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD);
00161 #else
00162 VecScatterBegin(x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD, A22_scatter_ctx);
00163 VecScatterEnd(x, block_diag_context->x2_subvector, INSERT_VALUES, SCATTER_FORWARD, A22_scatter_ctx);
00164 #endif
00165
00166
00167 PCApply(block_diag_context->PC_amg_A11, block_diag_context->x1_subvector, block_diag_context->y1_subvector);
00168 PCApply(block_diag_context->PC_amg_A22, block_diag_context->x2_subvector, block_diag_context->y2_subvector);
00169
00171
00172
00173 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00174 VecScatterBegin(A11_scatter_ctx, block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00175 VecScatterEnd(A11_scatter_ctx, block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00176 #else
00177 VecScatterBegin(block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE, A11_scatter_ctx);
00178 VecScatterEnd(block_diag_context->y1_subvector, y, INSERT_VALUES, SCATTER_REVERSE, A11_scatter_ctx);
00179 #endif
00180
00181
00182 #if ( (PETSC_VERSION_MAJOR == 3) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 3)) //2.3.3 or 3.x.x
00183 VecScatterBegin(A22_scatter_ctx, block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00184 VecScatterEnd(A22_scatter_ctx, block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE);
00185 #else
00186 VecScatterBegin(block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE, A22_scatter_ctx);
00187 VecScatterEnd(block_diag_context->y2_subvector, y, INSERT_VALUES, SCATTER_REVERSE, A22_scatter_ctx);
00188 #endif
00189
00191
00192 ISDestroy(A11_rows);
00193 ISDestroy(A22_rows);
00194
00195 VecScatterDestroy(A11_scatter_ctx);
00196 VecScatterDestroy(A22_scatter_ctx);
00197
00198 return 0;
00199 }