PCBlockDiagonal.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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     // Register PC context so it gets passed to PCBlockDiagonalApply
00070     PCShellSetContext(mPetscPCObject, &mPCContext);
00071     // Register call-back function
00072     PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply);
00073 #endif
00074 
00075     // Get matrix sublock A11
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     // Get matrix sublock A22
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     // Allocate memory
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     // These options will get read by PCSetFromOptions
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     // Set up amg preconditioner for block A11
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);//   SAME_PRECONDITIONER);
00113     PCSetFromOptions(mPCContext.PC_amg_A11);
00114     PCSetUp(mPCContext.PC_amg_A11);
00115 
00116     // Set up amg preconditioner for block A22
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);//   SAME_PRECONDITIONER);
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     // Cast the pointer to a PC context to our defined type
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 //PETSc-3.x.x or PETSc-2.3.3
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 //PETSc-3.x.x or PETSc-2.3.3
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 //PETSc-3.x.x or PETSc-2.3.3
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 //PETSc-3.x.x or PETSc-2.3.3
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 }

Generated by  doxygen 1.6.2