1 #define PETSCKSP_DLL 2 3 #include "src/ksp/pc/impls/factor/icc/icc.h" /*I "petscpc.h" I*/ 4 5 EXTERN_C_BEGIN 6 #undef __FUNCT__ 7 #define __FUNCT__ "PCFactorSetZeroPivot_ICC" 8 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot_ICC(PC pc,PetscReal z) 9 { 10 PC_ICC *icc = (PC_ICC*)pc->data; 11 12 PetscFunctionBegin; 13 ((PC_Factor*)icc)->info.zeropivot = z; 14 PetscFunctionReturn(0); 15 } 16 EXTERN_C_END 17 18 EXTERN_C_BEGIN 19 #undef __FUNCT__ 20 #define __FUNCT__ "PCFactorSetShiftNonzero_ICC" 21 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero_ICC(PC pc,PetscReal shift) 22 { 23 PC_ICC *dir = (PC_ICC*)pc->data; 24 25 PetscFunctionBegin; 26 if (shift == (PetscReal) PETSC_DECIDE) { 27 ((PC_Factor*)dir)->info.shiftnz = 1.e-12; 28 } else { 29 ((PC_Factor*)dir)->info.shiftnz = shift; 30 } 31 PetscFunctionReturn(0); 32 } 33 EXTERN_C_END 34 35 EXTERN_C_BEGIN 36 #undef __FUNCT__ 37 #define __FUNCT__ "PCFactorSetShiftPd_ICC" 38 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd_ICC(PC pc,PetscTruth shift) 39 { 40 PC_ICC *dir = (PC_ICC*)pc->data; 41 42 PetscFunctionBegin; 43 if (shift) { 44 ((PC_Factor*)dir)->info.shiftpd = 1.0; 45 } else { 46 ((PC_Factor*)dir)->info.shiftpd = 0.0; 47 } 48 PetscFunctionReturn(0); 49 } 50 EXTERN_C_END 51 52 EXTERN_C_BEGIN 53 #undef __FUNCT__ 54 #define __FUNCT__ "PCFactorSetMatOrderingType_ICC" 55 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetMatOrderingType_ICC(PC pc,const MatOrderingType ordering) 56 { 57 PC_ICC *dir = (PC_ICC*)pc->data; 58 PetscErrorCode ierr; 59 60 PetscFunctionBegin; 61 ierr = PetscStrfree(((PC_Factor*)dir)->ordering);CHKERRQ(ierr); 62 ierr = PetscStrallocpy(ordering,& ((PC_Factor*)dir)->ordering);CHKERRQ(ierr); 63 PetscFunctionReturn(0); 64 } 65 EXTERN_C_END 66 67 EXTERN_C_BEGIN 68 #undef __FUNCT__ 69 #define __FUNCT__ "PCFactorSetFill_ICC" 70 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetFill_ICC(PC pc,PetscReal fill) 71 { 72 PC_ICC *dir = (PC_ICC*)pc->data; 73 74 PetscFunctionBegin; 75 ((PC_Factor*)dir)->info.fill = fill; 76 PetscFunctionReturn(0); 77 } 78 EXTERN_C_END 79 80 EXTERN_C_BEGIN 81 #undef __FUNCT__ 82 #define __FUNCT__ "PCFactorSetLevels_ICC" 83 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetLevels_ICC(PC pc,PetscInt levels) 84 { 85 PC_ICC *icc = (PC_ICC*)pc->data; 86 87 PetscFunctionBegin; 88 ((PC_Factor*)icc)->info.levels = levels; 89 PetscFunctionReturn(0); 90 } 91 EXTERN_C_END 92 93 #undef __FUNCT__ 94 #define __FUNCT__ "PCSetup_ICC" 95 static PetscErrorCode PCSetup_ICC(PC pc) 96 { 97 PC_ICC *icc = (PC_ICC*)pc->data; 98 IS perm,cperm; 99 PetscErrorCode ierr; 100 MatInfo info; 101 102 PetscFunctionBegin; 103 ierr = MatGetOrdering(pc->pmat, ((PC_Factor*)icc)->ordering,&perm,&cperm);CHKERRQ(ierr); 104 105 if (!pc->setupcalled) { 106 ierr = MatGetFactor(pc->pmat,MAT_SOLVER_PETSC,MAT_FACTOR_ICC,& ((PC_Factor*)icc)->fact);CHKERRQ(ierr); 107 ierr = MatICCFactorSymbolic(((PC_Factor*)icc)->fact,pc->pmat,perm,&((PC_Factor*)icc)->info);CHKERRQ(ierr); 108 } else if (pc->flag != SAME_NONZERO_PATTERN) { 109 ierr = MatDestroy(((PC_Factor*)icc)->fact);CHKERRQ(ierr); 110 ierr = MatGetFactor(pc->pmat,MAT_SOLVER_PETSC,MAT_FACTOR_ICC,&((PC_Factor*)icc)->fact);CHKERRQ(ierr); 111 ierr = MatICCFactorSymbolic(((PC_Factor*)icc)->fact,pc->pmat,perm,&((PC_Factor*)icc)->info);CHKERRQ(ierr); 112 } 113 ierr = MatGetInfo(((PC_Factor*)icc)->fact,MAT_LOCAL,&info);CHKERRQ(ierr); 114 icc->actualfill = info.fill_ratio_needed; 115 116 ierr = ISDestroy(cperm);CHKERRQ(ierr); 117 ierr = ISDestroy(perm);CHKERRQ(ierr); 118 ierr = MatCholeskyFactorNumeric(((PC_Factor*)icc)->fact,pc->pmat,&((PC_Factor*)icc)->info);CHKERRQ(ierr); 119 PetscFunctionReturn(0); 120 } 121 122 #undef __FUNCT__ 123 #define __FUNCT__ "PCDestroy_ICC" 124 static PetscErrorCode PCDestroy_ICC(PC pc) 125 { 126 PC_ICC *icc = (PC_ICC*)pc->data; 127 PetscErrorCode ierr; 128 129 PetscFunctionBegin; 130 if (((PC_Factor*)icc)->fact) {ierr = MatDestroy(((PC_Factor*)icc)->fact);CHKERRQ(ierr);} 131 ierr = PetscStrfree(((PC_Factor*)icc)->ordering);CHKERRQ(ierr); 132 ierr = PetscFree(icc);CHKERRQ(ierr); 133 PetscFunctionReturn(0); 134 } 135 136 #undef __FUNCT__ 137 #define __FUNCT__ "PCApply_ICC" 138 static PetscErrorCode PCApply_ICC(PC pc,Vec x,Vec y) 139 { 140 PC_ICC *icc = (PC_ICC*)pc->data; 141 PetscErrorCode ierr; 142 143 PetscFunctionBegin; 144 ierr = MatSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr); 145 PetscFunctionReturn(0); 146 } 147 148 #undef __FUNCT__ 149 #define __FUNCT__ "PCApplySymmetricLeft_ICC" 150 static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y) 151 { 152 PetscErrorCode ierr; 153 PC_ICC *icc = (PC_ICC*)pc->data; 154 155 PetscFunctionBegin; 156 ierr = MatForwardSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr); 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNCT__ 161 #define __FUNCT__ "PCApplySymmetricRight_ICC" 162 static PetscErrorCode PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y) 163 { 164 PetscErrorCode ierr; 165 PC_ICC *icc = (PC_ICC*)pc->data; 166 167 PetscFunctionBegin; 168 ierr = MatBackwardSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr); 169 PetscFunctionReturn(0); 170 } 171 172 #undef __FUNCT__ 173 #define __FUNCT__ "PCFactorGetMatrix_ICC" 174 static PetscErrorCode PCFactorGetMatrix_ICC(PC pc,Mat *mat) 175 { 176 PC_ICC *icc = (PC_ICC*)pc->data; 177 178 PetscFunctionBegin; 179 *mat = ((PC_Factor*)icc)->fact; 180 PetscFunctionReturn(0); 181 } 182 183 #undef __FUNCT__ 184 #define __FUNCT__ "PCSetFromOptions_ICC" 185 static PetscErrorCode PCSetFromOptions_ICC(PC pc) 186 { 187 PC_ICC *icc = (PC_ICC*)pc->data; 188 char tname[256]; 189 PetscTruth flg; 190 PetscErrorCode ierr; 191 PetscFList ordlist; 192 193 PetscFunctionBegin; 194 ierr = MatOrderingRegisterAll(PETSC_NULL);CHKERRQ(ierr); 195 ierr = PetscOptionsHead("ICC Options");CHKERRQ(ierr); 196 ierr = PetscOptionsReal("-pc_factor_levels","levels of fill","PCFactorSetLevels",((PC_Factor*)icc)->info.levels,&((PC_Factor*)icc)->info.levels,&flg);CHKERRQ(ierr); 197 ierr = PetscOptionsReal("-pc_factor_fill","Expected fill in factorization","PCFactorSetFill",((PC_Factor*)icc)->info.fill,&((PC_Factor*)icc)->info.fill,&flg);CHKERRQ(ierr); 198 ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr); 199 ierr = PetscOptionsList("-pc_factor_mat_ordering_type","Reorder to reduce nonzeros in ICC","PCFactorSetMatOrderingType",ordlist,((PC_Factor*)icc)->ordering,tname,256,&flg);CHKERRQ(ierr); 200 if (flg) { 201 ierr = PCFactorSetMatOrderingType(pc,tname);CHKERRQ(ierr); 202 } 203 ierr = PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);CHKERRQ(ierr); 204 if (flg) { 205 ierr = PCFactorSetShiftNonzero(pc,(PetscReal)PETSC_DECIDE);CHKERRQ(ierr); 206 } 207 ierr = PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",((PC_Factor*)icc)->info.shiftnz,&((PC_Factor*)icc)->info.shiftnz,0);CHKERRQ(ierr); 208 flg = (((PC_Factor*)icc)->info.shiftpd > 0.0) ? PETSC_TRUE : PETSC_FALSE; 209 ierr = PetscOptionsTruth("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCFactorSetShiftPd",flg,&flg,PETSC_NULL);CHKERRQ(ierr); 210 ierr = PCFactorSetShiftPd(pc,flg);CHKERRQ(ierr); 211 ierr = PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",((PC_Factor*)icc)->info.zeropivot,&((PC_Factor*)icc)->info.zeropivot,0);CHKERRQ(ierr); 212 213 ierr = PetscOptionsTail();CHKERRQ(ierr); 214 PetscFunctionReturn(0); 215 } 216 217 #undef __FUNCT__ 218 #define __FUNCT__ "PCView_ICC" 219 static PetscErrorCode PCView_ICC(PC pc,PetscViewer viewer) 220 { 221 PC_ICC *icc = (PC_ICC*)pc->data; 222 PetscErrorCode ierr; 223 PetscTruth isstring,iascii; 224 225 PetscFunctionBegin; 226 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr); 227 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 228 if (iascii) { 229 if (((PC_Factor*)icc)->info.levels == 1) { 230 ierr = PetscViewerASCIIPrintf(viewer," ICC: %D level of fill\n",(PetscInt)((PC_Factor*)icc)->info.levels);CHKERRQ(ierr); 231 } else { 232 ierr = PetscViewerASCIIPrintf(viewer," ICC: %D levels of fill\n",(PetscInt)((PC_Factor*)icc)->info.levels);CHKERRQ(ierr); 233 } 234 ierr = PetscViewerASCIIPrintf(viewer," ICC: factor fill ratio allocated %G, ordering used %s\n",((PC_Factor*)icc)->info.fill,((PC_Factor*)icc)->ordering);CHKERRQ(ierr); 235 if (((PC_Factor*)icc)->info.shiftpd) {ierr = PetscViewerASCIIPrintf(viewer," ICC: using Manteuffel shift\n");CHKERRQ(ierr);} 236 if (((PC_Factor*)icc)->info.shiftnz) {ierr = PetscViewerASCIIPrintf(viewer," ICC: using diagonal shift to prevent zero pivot\n");CHKERRQ(ierr);} 237 if (((PC_Factor*)icc)->fact) { 238 ierr = PetscViewerASCIIPrintf(viewer," ICC: factor fill ratio needed %G\n",icc->actualfill);CHKERRQ(ierr); 239 ierr = PetscViewerASCIIPrintf(viewer," Factored matrix follows\n");CHKERRQ(ierr); 240 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 241 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 242 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 243 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 244 ierr = MatView(((PC_Factor*)icc)->fact,viewer);CHKERRQ(ierr); 245 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 246 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 247 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 248 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 249 } 250 } else if (isstring) { 251 ierr = PetscViewerStringSPrintf(viewer," lvls=%D",(PetscInt)((PC_Factor*)icc)->info.levels);CHKERRQ(ierr);CHKERRQ(ierr); 252 } else { 253 SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCICC",((PetscObject)viewer)->type_name); 254 } 255 PetscFunctionReturn(0); 256 } 257 258 /*MC 259 PCICC - Incomplete Cholesky factorization preconditioners. 260 261 Options Database Keys: 262 + -pc_factor_levels <k> - number of levels of fill for ICC(k) 263 . -pc_factor_in_place - only for ICC(0) with natural ordering, reuses the space of the matrix for 264 its factorization (overwrites original matrix) 265 . -pc_factor_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1 266 . -pc_factor_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix 267 . -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default 268 - -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value 269 is optional with PETSC_TRUE being the default 270 271 Level: beginner 272 273 Concepts: incomplete Cholesky factorization 274 275 Notes: Only implemented for some matrix formats. Not implemented in parallel (for parallel use you 276 must use MATMPIROWBS, see MatCreateMPIRowbs(), this supports only ICC(0) and this is not recommended 277 unless you really want a parallel ICC). 278 279 For BAIJ matrices this implements a point block ICC. 280 281 The Manteuffel shift is only implemented for matrices with block size 1 282 283 By default, the Manteuffel is applied (for matrices with block size 1). Call PCFactorSetShiftPd(pc,PETSC_FALSE); 284 to turn off the shift. 285 286 References: 287 Review article: APPROXIMATE AND INCOMPLETE FACTORIZATIONS, TONY F. CHAN AND HENK A. VAN DER VORST 288 http://igitur-archive.library.uu.nl/math/2001-0621-115821/proc.pdf chapter in Parallel Numerical 289 Algorithms, edited by D. Keyes, A. Semah, V. Venkatakrishnan, ICASE/LaRC Interdisciplinary Series in 290 Science and Engineering, Kluwer, pp. 167--202. 291 292 293 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType, 294 PCFactorSetZeroPivot(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(), 295 PCFactorSetFill(), PCFactorSetMatOrderingType(), PCFactorSetReuseOrdering(), 296 PCFactorSetLevels(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd(), 297 298 M*/ 299 300 EXTERN_C_BEGIN 301 #undef __FUNCT__ 302 #define __FUNCT__ "PCCreate_ICC" 303 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_ICC(PC pc) 304 { 305 PetscErrorCode ierr; 306 PC_ICC *icc; 307 308 PetscFunctionBegin; 309 ierr = PetscNewLog(pc,PC_ICC,&icc);CHKERRQ(ierr); 310 311 ((PC_Factor*)icc)->fact = 0; 312 ierr = PetscStrallocpy(MATORDERING_NATURAL,&((PC_Factor*)icc)->ordering);CHKERRQ(ierr); 313 ierr = MatFactorInfoInitialize(&((PC_Factor*)icc)->info);CHKERRQ(ierr); 314 ((PC_Factor*)icc)->info.levels = 0; 315 ((PC_Factor*)icc)->info.fill = 1.0; 316 icc->implctx = 0; 317 318 ((PC_Factor*)icc)->info.dtcol = PETSC_DEFAULT; 319 ((PC_Factor*)icc)->info.shiftnz = 0.0; 320 ((PC_Factor*)icc)->info.shiftpd = 1.0; /* true */ 321 ((PC_Factor*)icc)->info.zeropivot = 1.e-12; 322 pc->data = (void*)icc; 323 324 pc->ops->apply = PCApply_ICC; 325 pc->ops->setup = PCSetup_ICC; 326 pc->ops->destroy = PCDestroy_ICC; 327 pc->ops->setfromoptions = PCSetFromOptions_ICC; 328 pc->ops->view = PCView_ICC; 329 pc->ops->getfactoredmatrix = PCFactorGetMatrix_ICC; 330 pc->ops->applysymmetricleft = PCApplySymmetricLeft_ICC; 331 pc->ops->applysymmetricright = PCApplySymmetricRight_ICC; 332 333 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_ICC", 334 PCFactorSetZeroPivot_ICC);CHKERRQ(ierr); 335 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_ICC", 336 PCFactorSetShiftNonzero_ICC);CHKERRQ(ierr); 337 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_ICC", 338 PCFactorSetShiftPd_ICC);CHKERRQ(ierr); 339 340 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetLevels_C","PCFactorSetLevels_ICC", 341 PCFactorSetLevels_ICC);CHKERRQ(ierr); 342 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetFill_C","PCFactorSetFill_ICC", 343 PCFactorSetFill_ICC);CHKERRQ(ierr); 344 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatOrderingType_C","PCFactorSetMatOrderingType_ICC", 345 PCFactorSetMatOrderingType_ICC);CHKERRQ(ierr); 346 PetscFunctionReturn(0); 347 } 348 EXTERN_C_END 349 350 351