Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include <iostream> 00037 00038 #include "PetscVecTools.hpp" // Includes Ublas so must come first 00039 #include "PCBlockDiagonal.hpp" 00040 #include "Exception.hpp" 00041 00042 PCBlockDiagonal::PCBlockDiagonal(KSP& rKspObject) 00043 { 00044 #ifdef TRACE_KSP 00045 mPCContext.mScatterTime = 0.0; 00046 mPCContext.mA1PreconditionerTime = 0.0;; 00047 mPCContext.mA2PreconditionerTime = 0.0;; 00048 mPCContext.mGatherTime = 0.0;; 00049 #endif 00050 00051 PCBlockDiagonalCreate(rKspObject); 00052 PCBlockDiagonalSetUp(); 00053 } 00054 00055 PCBlockDiagonal::~PCBlockDiagonal() 00056 { 00057 #ifdef TRACE_KSP 00058 if (PetscTools::AmMaster()) 00059 { 00060 std::cout << " -- Block diagonal preconditioner profile information: " << std::endl; 00061 std::cout << "\t mScatterTime: " << mPCContext.mScatterTime << std::endl; 00062 std::cout << "\t mA1PreconditionerTime: " << mPCContext.mA1PreconditionerTime << std::endl; 00063 std::cout << "\t mA2PreconditionerTime: " << mPCContext.mA2PreconditionerTime << std::endl; 00064 std::cout << "\t mGatherTime: " << mPCContext.mGatherTime << std::endl; 00065 } 00066 #endif 00067 00068 PetscTools::Destroy(mPCContext.A11_matrix_subblock); 00069 PetscTools::Destroy(mPCContext.A22_matrix_subblock); 00070 00071 PCDestroy(PETSC_DESTROY_PARAM(mPCContext.PC_amg_A11)); 00072 PCDestroy(PETSC_DESTROY_PARAM(mPCContext.PC_amg_A22)); 00073 00074 PetscTools::Destroy(mPCContext.x1_subvector); 00075 PetscTools::Destroy(mPCContext.y1_subvector); 00076 00077 PetscTools::Destroy(mPCContext.x2_subvector); 00078 PetscTools::Destroy(mPCContext.y2_subvector); 00079 00080 VecScatterDestroy(PETSC_DESTROY_PARAM(mPCContext.A11_scatter_ctx)); 00081 VecScatterDestroy(PETSC_DESTROY_PARAM(mPCContext.A22_scatter_ctx)); 00082 } 00083 00084 void PCBlockDiagonal::PCBlockDiagonalCreate(KSP& rKspObject) 00085 { 00086 KSPGetPC(rKspObject, &mPetscPCObject); 00087 00088 Mat system_matrix, dummy; 00089 MatStructure flag; 00090 KSPGetOperators(rKspObject, &system_matrix, &dummy, &flag); 00091 00092 PetscInt num_rows, num_columns; 00093 MatGetSize(system_matrix, &num_rows, &num_columns); 00094 assert(num_rows==num_columns); 00095 00096 PetscInt num_local_rows, num_local_columns; 00097 MatGetLocalSize(system_matrix, &num_local_rows, &num_local_columns); 00098 00099 // Odd number of rows: impossible in Bidomain. 00100 // Odd number of local rows: impossible if V_m and phi_e for each node are stored in the same processor. 00101 if ((num_rows%2 != 0) || (num_local_rows%2 != 0)) 00102 { 00103 TERMINATE("Wrong matrix parallel layout detected in PCLDUFactorisation."); 00104 } 00105 00106 // Allocate memory 00107 unsigned subvector_num_rows = num_rows/2; 00108 unsigned subvector_local_rows = num_local_rows/2; 00109 mPCContext.x1_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows); 00110 mPCContext.x2_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows); 00111 mPCContext.y1_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows); 00112 mPCContext.y2_subvector = PetscTools::CreateVec(subvector_num_rows, subvector_local_rows); 00113 00114 // Create scatter contexts 00115 { 00116 // Needed by SetupInterleavedVectorScatterGather in order to find out parallel layout. 00117 Vec dummy_vec = PetscTools::CreateVec(num_rows, num_local_rows); 00118 00119 PetscVecTools::SetupInterleavedVectorScatterGather(dummy_vec, mPCContext.A11_scatter_ctx, mPCContext.A22_scatter_ctx); 00120 00121 PetscTools::Destroy(dummy_vec); 00122 } 00123 00124 // Get matrix sublock A11 00125 { 00126 // Work out local row range for subblock A11 (same as x1 or y1) 00127 PetscInt low, high, global_size; 00128 VecGetOwnershipRange(mPCContext.x1_subvector, &low, &high); 00129 VecGetSize(mPCContext.x1_subvector, &global_size); 00130 assert(global_size == num_rows/2); 00131 00132 IS A11_local_rows; 00133 IS A11_columns; 00134 ISCreateStride(PETSC_COMM_WORLD, high-low, 2*low, 2, &A11_local_rows); 00135 ISCreateStride(PETSC_COMM_WORLD, global_size, 0, 2, &A11_columns); 00136 00137 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 1) //PETSc 3.1 or later 00138 MatGetSubMatrix(system_matrix, A11_local_rows, A11_local_rows, 00139 MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock); 00140 #else 00141 MatGetSubMatrix(system_matrix, A11_local_rows, A11_columns, PETSC_DECIDE, 00142 MAT_INITIAL_MATRIX, &mPCContext.A11_matrix_subblock); 00143 #endif 00144 00145 00146 ISDestroy(PETSC_DESTROY_PARAM(A11_local_rows)); 00147 ISDestroy(PETSC_DESTROY_PARAM(A11_columns)); 00148 } 00149 00150 // Get matrix sublock A22 00151 { 00152 // Work out local row range for subblock A22 (same as x2 or y2) 00153 PetscInt low, high, global_size; 00154 VecGetOwnershipRange(mPCContext.x2_subvector, &low, &high); 00155 VecGetSize(mPCContext.x2_subvector, &global_size); 00156 assert(global_size == num_rows/2); 00157 00158 IS A22_local_rows; 00159 IS A22_columns; 00160 ISCreateStride(PETSC_COMM_WORLD, high-low, 2*low+1, 2, &A22_local_rows); 00161 ISCreateStride(PETSC_COMM_WORLD, global_size, 1, 2, &A22_columns); 00162 00163 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 1) //PETSc 3.1 or later 00164 MatGetSubMatrix(system_matrix, A22_local_rows, A22_local_rows, 00165 MAT_INITIAL_MATRIX, &mPCContext.A22_matrix_subblock); 00166 #else 00167 MatGetSubMatrix(system_matrix, A22_local_rows, A22_columns, PETSC_DECIDE, 00168 MAT_INITIAL_MATRIX, &mPCContext.A22_matrix_subblock); 00169 #endif 00170 00171 ISDestroy(PETSC_DESTROY_PARAM(A22_local_rows)); 00172 ISDestroy(PETSC_DESTROY_PARAM(A22_columns)); 00173 } 00174 00175 // Register call-back function and its context 00176 PCSetType(mPetscPCObject, PCSHELL); 00177 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2 00178 PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply, (void*) &mPCContext); 00179 #else 00180 // Register PC context so it gets passed to PCBlockDiagonalApply 00181 PCShellSetContext(mPetscPCObject, &mPCContext); 00182 00183 // Register call-back function 00184 PCShellSetApply(mPetscPCObject, PCBlockDiagonalApply); 00185 #endif 00186 00187 } 00188 00189 void PCBlockDiagonal::PCBlockDiagonalSetUp() 00190 { 00191 // These options will get read by PCSetFromOptions 00192 // PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1"); 00193 // PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0"); 00194 // PetscOptionsSetValue("-pc_hypre_type", "boomeramg"); 00195 00196 // Set up amg preconditioner for block A11 00197 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A11)); 00198 00199 // PCSetType(mPCContext.PC_amg_A11, PCBJACOBI); 00200 00201 PCSetType(mPCContext.PC_amg_A11, PCHYPRE); 00202 //PCHYPRESetType(mPCContext.PC_amg_A11, "euclid"); 00203 PetscOptionsSetValue("-pc_hypre_type", "euclid"); 00204 PetscOptionsSetValue("-pc_hypre_euclid_levels", "0"); 00205 00206 00207 //PCSetType(mPCContext.PC_amg_A11, PCHYPRE); 00208 //PetscOptionsSetValue("-pc_hypre_type", "boomeramg"); 00209 //PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1"); 00210 //PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0"); 00211 //PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type", "HMIS"); 00212 00213 PCSetOperators(mPCContext.PC_amg_A11, mPCContext.A11_matrix_subblock, mPCContext.A11_matrix_subblock, SAME_PRECONDITIONER); 00214 PCSetFromOptions(mPCContext.PC_amg_A11); 00215 PCSetUp(mPCContext.PC_amg_A11); 00216 00217 // Set up amg preconditioner for block A22 00218 PCCreate(PETSC_COMM_WORLD, &(mPCContext.PC_amg_A22)); 00219 00220 /* Full AMG in the block */ 00221 PCSetType(mPCContext.PC_amg_A22, PCHYPRE); 00222 //PCHYPRESetType(mPCContext.PC_amg_A22, "boomeramg"); 00223 PetscOptionsSetValue("-pc_hypre_type", "boomeramg"); 00224 PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1"); 00225 PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0"); 00226 PetscOptionsSetValue("-pc_hypre_boomeramg_coarsen_type", "HMIS"); 00227 // PetscOptionsSetValue("-pc_hypre_boomeramg_relax_type_all","Jacobi"); 00228 //PetscOptionsSetValue("-pc_hypre_boomeramg_max_levels","10"); 00229 //PetscOptionsSetValue("-pc_hypre_boomeramg_agg_nl", "1"); 00230 // PetscOptionsSetValue("-pc_hypre_boomeramg_print_statistics",""); 00231 // PetscOptionsSetValue("-pc_hypre_boomeramg_interp_type","standard"); 00232 // PetscOptionsSetValue("-pc_hypre_boomeramg_interp_type","ext+i"); 00233 00234 // PCHYPRESetType(mPCContext.PC_amg_A22, "euclid"); 00235 00236 /* Block Jacobi with AMG at each block */ 00237 // PCSetType(mPCContext.PC_amg_A22, PCBJACOBI); 00238 00239 // PetscOptionsSetValue("-sub_pc_type", "hypre"); 00240 00241 // PetscOptionsSetValue("-sub_pc_hypre_type", "boomeramg"); 00242 // PetscOptionsSetValue("-sub_pc_hypre_boomeramg_max_iter", "1"); 00243 // PetscOptionsSetValue("-sub_pc_hypre_boomeramg_strong_threshold", "0.0"); 00244 00245 // PetscOptionsSetValue("-pc_hypre_type", "boomeramg"); 00246 // PetscOptionsSetValue("-pc_hypre_boomeramg_max_iter", "1"); 00247 // PetscOptionsSetValue("-pc_hypre_boomeramg_strong_threshold", "0.0"); 00248 00249 /* Additive Schwarz with AMG at each block */ 00250 // PCSetType(mPCContext.PC_amg_A22, PCASM); 00251 00252 // PetscOptionsSetValue("-pc_asm_type", "basic"); 00253 // PetscOptionsSetValue("-pc_asm_overlap", "1"); 00254 00255 // PetscOptionsSetValue("-sub_ksp_type", "preonly"); 00256 00257 // PetscOptionsSetValue("-sub_pc_type", "hypre"); 00258 00259 // PetscOptionsSetValue("-sub_pc_hypre_type", "boomeramg"); 00260 // PetscOptionsSetValue("-sub_pc_hypre_boomeramg_max_iter", "1"); 00261 // PetscOptionsSetValue("-sub_pc_hypre_boomeramg_strong_threshold", "0.0"); 00262 00263 PCSetOperators(mPCContext.PC_amg_A22, mPCContext.A22_matrix_subblock, mPCContext.A22_matrix_subblock, SAME_PRECONDITIONER); 00264 PCSetFromOptions(mPCContext.PC_amg_A22); 00265 PCSetUp(mPCContext.PC_amg_A22); 00266 } 00267 00268 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 1) //PETSc 3.1 or later 00269 PetscErrorCode PCBlockDiagonalApply(PC pc_object, Vec x, Vec y) 00270 { 00271 void* pc_context; 00272 00273 PCShellGetContext(pc_object, &pc_context); 00274 #else 00275 PetscErrorCode PCBlockDiagonalApply(void* pc_context, Vec x, Vec y) 00276 { 00277 #endif 00278 00279 // Cast the context pointer to PCBlockDiagonalContext 00280 PCBlockDiagonal::PCBlockDiagonalContext* block_diag_context = (PCBlockDiagonal::PCBlockDiagonalContext*) pc_context; 00281 assert(block_diag_context!=NULL); 00282 00283 /* 00284 * Scatter x = [x1 x2]' 00285 */ 00286 #ifdef TRACE_KSP 00287 double init_time = MPI_Wtime(); 00288 #endif 00289 00290 PetscVecTools::DoInterleavedVecScatter(x, block_diag_context->A11_scatter_ctx, block_diag_context->x1_subvector, block_diag_context->A22_scatter_ctx, block_diag_context->x2_subvector); 00291 00292 #ifdef TRACE_KSP 00293 block_diag_context->mScatterTime += MPI_Wtime() - init_time; 00294 #endif 00295 00296 /* 00297 * y1 = AMG(A11)*x1 00298 * y2 = AMG(A22)*x2 00299 */ 00300 #ifdef TRACE_KSP 00301 init_time = MPI_Wtime(); 00302 #endif 00303 PCApply(block_diag_context->PC_amg_A11, block_diag_context->x1_subvector, block_diag_context->y1_subvector); 00304 #ifdef TRACE_KSP 00305 block_diag_context->mA1PreconditionerTime += MPI_Wtime() - init_time; 00306 #endif 00307 00308 #ifdef TRACE_KSP 00309 init_time = MPI_Wtime(); 00310 #endif 00311 PCApply(block_diag_context->PC_amg_A22, block_diag_context->x2_subvector, block_diag_context->y2_subvector); 00312 #ifdef TRACE_KSP 00313 block_diag_context->mA2PreconditionerTime += MPI_Wtime() - init_time; 00314 #endif 00315 00316 /* 00317 * Gather y = [y1 y2]' 00318 */ 00319 //PETSc-3.x.x or PETSc-2.3.3 00320 #ifdef TRACE_KSP 00321 init_time = MPI_Wtime(); 00322 #endif 00323 00324 PetscVecTools::DoInterleavedVecGather(y, block_diag_context->A11_scatter_ctx, block_diag_context->y1_subvector, block_diag_context->A22_scatter_ctx, block_diag_context->y2_subvector); 00325 00326 #ifdef TRACE_KSP 00327 block_diag_context->mGatherTime += MPI_Wtime() - init_time; 00328 #endif 00329 return 0; 00330 }