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         //#include "Timer.hpp"
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     // odd number of rows: impossible in Bidomain.
00074     // odd number of local rows: impossible if V_m and phi_e for each node are stored in the same processor.
00075     if ((num_rows%2 != 0) || (num_local_rows%2 != 0))
00076     {
00077         TERMINATE("Wrong matrix parallel layout detected in PCLDUFactorisation.");
00078     }
00079 
00080     // Allocate memory     
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     // Create scatter contexts
00089     {
00090         // Needed by VecScatterCreate in order to find out parallel layout.
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     // Get matrix sublock A11        
00111     {
00112         // Work out local row range for subblock A11 (same as x1 or y1) 
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     // Get matrix sublock A22
00137     {
00138         // Work out local row range for subblock A22 (same as x2 or y2) 
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     // Register call-back function and its context
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     // Register PC context so it gets passed to PCBlockDiagonalApply
00167     PCShellSetContext(mPetscPCObject, &mPCContext);
00168     // Register call-back function
00169     PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply);
00170 #endif
00171 
00172 }
00173 
00174 void PCBlockDiagonal::PCBlockDiagonalSetUp()
00175 {
00176     // These options will get read by PCSetFromOptions
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     // Set up amg preconditioner for block A11
00182     PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A11));
00183     PCSetType(mPCContext.PC_amg_A11, PCBJACOBI);
00184 //     PCSetType(mPCContext.PC_amg_A11, PCHYPRE);
00185 //     PCHYPRESetType(mPCContext.PC_amg_A11, "euclid");
00186 
00187     PCSetOperators(mPCContext.PC_amg_A11, mPCContext.A11_matrix_subblock, mPCContext.A11_matrix_subblock, DIFFERENT_NONZERO_PATTERN);//   SAME_PRECONDITIONER);
00188     PCSetFromOptions(mPCContext.PC_amg_A11);
00189     PCSetUp(mPCContext.PC_amg_A11);
00190 
00191     // Set up amg preconditioner for block A22
00192     PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A22));
00193 
00194     /* Full AMG in the block */
00195     PCSetType(mPCContext.PC_amg_A22, PCHYPRE);
00196     //PCHYPRESetType(mPCContext.PC_amg_A22, "boomeramg");
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     //    PetscOptionsSetValue("-pc_hypre_boomeramg_relax_type_all","Jacobi");
00203     //PetscOptionsSetValue("-pc_hypre_boomeramg_max_levels","10");
00204     //PetscOptionsSetValue("-pc_hypre_boomeramg_agg_nl", "1");
00205     //    PetscOptionsSetValue("-pc_hypre_boomeramg_print_statistics","");
00206     //    PetscOptionsSetValue("-pc_hypre_boomeramg_interp_type","standard");
00207 
00208     //    PCHYPRESetType(mPCContext.PC_amg_A22, "euclid");
00209 
00210 
00211 
00212     /* Block Jacobi with AMG at each block */
00213     //     PCSetType(mPCContext.PC_amg_A22, PCBJACOBI);
00214     
00215     //     PetscOptionsSetValue("-sub_pc_type", "hypre");
00216     
00217     //     PetscOptionsSetValue("-sub_pc_hypre_type", "boomeramg");
00218     //     PetscOptionsSetValue("-sub_pc_hypre_boomeramg_max_iter", "1");
00219     //     PetscOptionsSetValue("-sub_pc_hypre_boomeramg_strong_threshold", "0.0");
00220     
00221     //     PetscOptionsSetValue("-pc_hypre_type", "boomeramg");
00222     //     PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1");
00223     //     PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0");
00224 
00225     /* Additive Schwarz with AMG at each block */
00226 //     PCSetType(mPCContext.PC_amg_A22, PCASM);
00227     
00228 //     PetscOptionsSetValue("-pc_asm_type", "basic");
00229 //     PetscOptionsSetValue("-pc_asm_overlap", "1");
00230 
00231 //     PetscOptionsSetValue("-sub_ksp_type", "preonly");    
00232 
00233 //     PetscOptionsSetValue("-sub_pc_type", "hypre");
00234     
00235 //     PetscOptionsSetValue("-sub_pc_hypre_type", "boomeramg");
00236 //     PetscOptionsSetValue("-sub_pc_hypre_boomeramg_max_iter", "1");
00237 //     PetscOptionsSetValue("-sub_pc_hypre_boomeramg_strong_threshold", "0.0");
00238  
00239 
00240     PCSetOperators(mPCContext.PC_amg_A22, mPCContext.A22_matrix_subblock, mPCContext.A22_matrix_subblock, DIFFERENT_NONZERO_PATTERN);//   SAME_PRECONDITIONER);
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     // Cast the context pointer to PCBlockDiagonalContext
00257     PCBlockDiagonal::PCBlockDiagonalContext* block_diag_context = (PCBlockDiagonal::PCBlockDiagonalContext*) pc_context;
00258     assert(block_diag_context!=NULL);
00259 
00260     /*
00261      * Scatter x = [x1 x2]'
00262      */
00263 //PETSc-3.x.x or PETSc-2.3.3
00264 //    Timer::Reset();
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 //PETSc-3.x.x or PETSc-2.3.3
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     //    Timer::PrintAndReset("scatter");
00282 
00283     /*
00284      *  y1 = AMG(A11)*x1
00285      *  y2 = AMG(A22)*x2
00286      */
00287     PCApply(block_diag_context->PC_amg_A11, block_diag_context->x1_subvector, block_diag_context->y1_subvector);
00288     //    Timer::PrintAndReset("first prec");    
00289     PCApply(block_diag_context->PC_amg_A22, block_diag_context->x2_subvector, block_diag_context->y2_subvector);
00290     //    Timer::PrintAndReset("second prec");        
00291 
00292     /*
00293      * Gather y = [y1 y2]'
00294      */
00295 //PETSc-3.x.x or PETSc-2.3.3
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 //PETSc-3.x.x or PETSc-2.3.3
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     //    Timer::PrintAndReset("gather");
00313 
00314     return 0;
00315 }

Generated on Mon Nov 1 12:35:17 2010 for Chaste by  doxygen 1.5.5