1 2 #include "../src/ksp/pc/impls/is/pcis.h" /*I "petscpc.h" I*/ 3 4 EXTERN_C_BEGIN 5 #undef __FUNCT__ 6 #define __FUNCT__ "PCISSetSubdomainDiagonalScaling_IS" 7 static PetscErrorCode PCISSetSubdomainDiagonalScaling_IS(PC pc, Vec scaling_factors) 8 { 9 PetscErrorCode ierr; 10 PC_IS *pcis = (PC_IS*)pc->data; 11 12 PetscFunctionBegin; 13 ierr = VecDestroy(&pcis->D);CHKERRQ(ierr); 14 ierr = PetscObjectReference((PetscObject)scaling_factors);CHKERRQ(ierr); 15 pcis->D = scaling_factors; 16 PetscFunctionReturn(0); 17 } 18 EXTERN_C_END 19 20 #undef __FUNCT__ 21 #define __FUNCT__ "PCISSetSubdomainDiagonalScaling" 22 /*@ 23 PCISSetSubdomainDiagonalScaling - Set diagonal scaling for PCIS. 24 25 Not collective 26 27 Input Parameters: 28 + pc - the preconditioning context 29 - scaling_factors - scaling factors for the subdomain 30 31 Level: intermediate 32 33 Notes: 34 Intended to use with jumping coefficients cases. 35 36 .seealso: PCBDDC 37 @*/ 38 PetscErrorCode PCISSetSubdomainDiagonalScaling(PC pc, Vec scaling_factors) 39 { 40 PetscErrorCode ierr; 41 42 PetscFunctionBegin; 43 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 44 ierr = PetscTryMethod(pc,"PCISSetSubdomainDiagonalScaling_C",(PC,Vec),(pc,scaling_factors));CHKERRQ(ierr); 45 PetscFunctionReturn(0); 46 } 47 48 EXTERN_C_BEGIN 49 #undef __FUNCT__ 50 #define __FUNCT__ "PCISSetSubdomainScalingFactor_IS" 51 static PetscErrorCode PCISSetSubdomainScalingFactor_IS(PC pc, PetscScalar scal) 52 { 53 PC_IS *pcis = (PC_IS*)pc->data; 54 55 PetscFunctionBegin; 56 pcis->scaling_factor = scal; 57 PetscFunctionReturn(0); 58 } 59 EXTERN_C_END 60 61 #undef __FUNCT__ 62 #define __FUNCT__ "PCISSetSubdomainScalingFactor" 63 /*@ 64 PCISSetSubdomainScalingFactor - Set scaling factor for PCIS. 65 66 Not collective 67 68 Input Parameters: 69 + pc - the preconditioning context 70 - scal - scaling factor for the subdomain 71 72 Level: intermediate 73 74 Notes: 75 Intended to use with jumping coefficients cases. 76 77 .seealso: PCBDDC 78 @*/ 79 PetscErrorCode PCISSetSubdomainScalingFactor(PC pc, PetscScalar scal) 80 { 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 85 ierr = PetscTryMethod(pc,"PCISSetSubdomainScalingFactor_C",(PC,PetscScalar),(pc,scal));CHKERRQ(ierr); 86 PetscFunctionReturn(0); 87 } 88 89 90 /* -------------------------------------------------------------------------- */ 91 /* 92 PCISSetUp - 93 */ 94 #undef __FUNCT__ 95 #define __FUNCT__ "PCISSetUp" 96 PetscErrorCode PCISSetUp(PC pc) 97 { 98 PC_IS *pcis = (PC_IS*)(pc->data); 99 Mat_IS *matis = (Mat_IS*)pc->mat->data; 100 PetscInt i; 101 PetscErrorCode ierr; 102 PetscBool flg; 103 Vec counter; 104 105 PetscFunctionBegin; 106 ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&flg);CHKERRQ(ierr); 107 if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG,"Preconditioner type of Neumann Neumman requires matrix of type MATIS"); 108 109 pcis->pure_neumann = matis->pure_neumann; 110 111 /* 112 Creating the local vector vec1_N, containing the inverse of the number 113 of subdomains to which each local node (either owned or ghost) 114 pertains. To accomplish that, we scatter local vectors of 1's to 115 a global vector (adding the values); scatter the result back to 116 local vectors and finally invert the result. 117 */ 118 ierr = VecDuplicate(matis->x,&pcis->vec1_N);CHKERRQ(ierr); 119 ierr = MatGetVecs(pc->pmat,&counter,0);CHKERRQ(ierr); /* temporary auxiliar vector */ 120 ierr = VecSet(counter,0.0);CHKERRQ(ierr); 121 ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr); 122 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 123 ierr = VecScatterEnd (matis->ctx,pcis->vec1_N,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 124 ierr = VecScatterBegin(matis->ctx,counter,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 125 ierr = VecScatterEnd (matis->ctx,counter,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 126 /* 127 Creating local and global index sets for interior and 128 inteface nodes. Notice that interior nodes have D[i]==1.0. 129 */ 130 { 131 PetscInt n_I; 132 PetscInt *idx_I_local,*idx_B_local,*idx_I_global,*idx_B_global; 133 PetscScalar *array; 134 /* Identifying interior and interface nodes, in local numbering */ 135 ierr = VecGetSize(pcis->vec1_N,&pcis->n);CHKERRQ(ierr); 136 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 137 ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&idx_I_local);CHKERRQ(ierr); 138 ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&idx_B_local);CHKERRQ(ierr); 139 for (i=0, pcis->n_B=0, n_I=0; i<pcis->n; i++) { 140 if (array[i] == 1.0) { idx_I_local[n_I] = i; n_I++; } 141 else { idx_B_local[pcis->n_B] = i; pcis->n_B++; } 142 } 143 /* Getting the global numbering */ 144 idx_B_global = idx_I_local + n_I; /* Just avoiding allocating extra memory, since we have vacant space */ 145 idx_I_global = idx_B_local + pcis->n_B; 146 ierr = ISLocalToGlobalMappingApply(matis->mapping,pcis->n_B,idx_B_local,idx_B_global);CHKERRQ(ierr); 147 ierr = ISLocalToGlobalMappingApply(matis->mapping,n_I, idx_I_local,idx_I_global);CHKERRQ(ierr); 148 /* Creating the index sets. */ 149 ierr = ISCreateGeneral(MPI_COMM_SELF,pcis->n_B,idx_B_local,PETSC_COPY_VALUES, &pcis->is_B_local);CHKERRQ(ierr); 150 ierr = ISCreateGeneral(MPI_COMM_SELF,pcis->n_B,idx_B_global,PETSC_COPY_VALUES,&pcis->is_B_global);CHKERRQ(ierr); 151 ierr = ISCreateGeneral(MPI_COMM_SELF,n_I ,idx_I_local,PETSC_COPY_VALUES, &pcis->is_I_local);CHKERRQ(ierr); 152 ierr = ISCreateGeneral(MPI_COMM_SELF,n_I ,idx_I_global,PETSC_COPY_VALUES,&pcis->is_I_global);CHKERRQ(ierr); 153 /* Freeing memory and restoring arrays */ 154 ierr = PetscFree(idx_B_local);CHKERRQ(ierr); 155 ierr = PetscFree(idx_I_local);CHKERRQ(ierr); 156 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 157 } 158 159 /* 160 Extracting the blocks A_II, A_BI, A_IB and A_BB from A. If the numbering 161 is such that interior nodes come first than the interface ones, we have 162 163 [ | ] 164 [ A_II | A_IB ] 165 A = [ | ] 166 [-----------+------] 167 [ A_BI | A_BB ] 168 */ 169 170 ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_II);CHKERRQ(ierr); 171 ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); 172 ierr = MatGetSubMatrix(matis->A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); 173 ierr = MatGetSubMatrix(matis->A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr); 174 175 /* 176 Creating work vectors and arrays 177 */ 178 /* pcis->vec1_N has already been created */ 179 ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr); 180 ierr = VecCreateSeq(PETSC_COMM_SELF,pcis->n-pcis->n_B,&pcis->vec1_D);CHKERRQ(ierr); 181 ierr = VecDuplicate(pcis->vec1_D,&pcis->vec2_D);CHKERRQ(ierr); 182 ierr = VecDuplicate(pcis->vec1_D,&pcis->vec3_D);CHKERRQ(ierr); 183 ierr = VecCreateSeq(PETSC_COMM_SELF,pcis->n_B,&pcis->vec1_B);CHKERRQ(ierr); 184 ierr = VecDuplicate(pcis->vec1_B,&pcis->vec2_B);CHKERRQ(ierr); 185 ierr = VecDuplicate(pcis->vec1_B,&pcis->vec3_B);CHKERRQ(ierr); 186 ierr = MatGetVecs(pc->pmat,&pcis->vec1_global,0);CHKERRQ(ierr); 187 ierr = PetscMalloc((pcis->n)*sizeof(PetscScalar),&pcis->work_N);CHKERRQ(ierr); 188 189 /* Creating the scatter contexts */ 190 ierr = VecScatterCreate(pcis->vec1_global,pcis->is_I_global,pcis->vec1_D,(IS)0,&pcis->global_to_D);CHKERRQ(ierr); 191 ierr = VecScatterCreate(pcis->vec1_N,pcis->is_B_local,pcis->vec1_B,(IS)0,&pcis->N_to_B);CHKERRQ(ierr); 192 ierr = VecScatterCreate(pcis->vec1_global,pcis->is_B_global,pcis->vec1_B,(IS)0,&pcis->global_to_B);CHKERRQ(ierr); 193 194 /* Creating scaling "matrix" D */ 195 if( !pcis->D ) { 196 ierr = VecSet(pcis->vec1_B,pcis->scaling_factor);CHKERRQ(ierr); 197 } else { 198 ierr = VecCopy(pcis->D,pcis->vec1_B);CHKERRQ(ierr); 199 } 200 ierr = VecSet(counter,0.0);CHKERRQ(ierr); 201 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 202 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 203 ierr = VecScatterBegin(pcis->global_to_B,counter,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 204 ierr = VecScatterEnd (pcis->global_to_B,counter,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 205 if( !pcis->D ) { 206 ierr = VecDuplicate(pcis->vec1_B,&pcis->D);CHKERRQ(ierr); 207 ierr = VecCopy(pcis->vec1_B,pcis->D);CHKERRQ(ierr); 208 ierr = VecReciprocal(pcis->D);CHKERRQ(ierr); 209 ierr = VecScale(pcis->D,pcis->scaling_factor);CHKERRQ(ierr); 210 } else { 211 ierr = VecPointwiseDivide(pcis->D,pcis->D,pcis->vec1_B);CHKERRQ(ierr); 212 } 213 214 /* See historical note 01, at the bottom of this file. */ 215 216 /* 217 Creating the KSP contexts for the local Dirichlet and Neumann problems. 218 */ 219 { 220 PC pc_ctx; 221 /* Dirichlet */ 222 ierr = KSPCreate(PETSC_COMM_SELF,&pcis->ksp_D);CHKERRQ(ierr); 223 ierr = PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr); 224 ierr = KSPSetOperators(pcis->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr); 225 ierr = KSPSetOptionsPrefix(pcis->ksp_D,"is_localD_");CHKERRQ(ierr); 226 ierr = KSPGetPC(pcis->ksp_D,&pc_ctx);CHKERRQ(ierr); 227 ierr = PCSetType(pc_ctx,PCLU);CHKERRQ(ierr); 228 ierr = KSPSetType(pcis->ksp_D,KSPPREONLY);CHKERRQ(ierr); 229 ierr = KSPSetFromOptions(pcis->ksp_D);CHKERRQ(ierr); 230 /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */ 231 ierr = KSPSetUp(pcis->ksp_D);CHKERRQ(ierr); 232 /* Neumann */ 233 ierr = KSPCreate(PETSC_COMM_SELF,&pcis->ksp_N);CHKERRQ(ierr); 234 ierr = PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_N,(PetscObject)pc,1);CHKERRQ(ierr); 235 ierr = KSPSetOperators(pcis->ksp_N,matis->A,matis->A,SAME_PRECONDITIONER);CHKERRQ(ierr); 236 ierr = KSPSetOptionsPrefix(pcis->ksp_N,"is_localN_");CHKERRQ(ierr); 237 ierr = KSPGetPC(pcis->ksp_N,&pc_ctx);CHKERRQ(ierr); 238 ierr = PCSetType(pc_ctx,PCLU);CHKERRQ(ierr); 239 ierr = KSPSetType(pcis->ksp_N,KSPPREONLY);CHKERRQ(ierr); 240 ierr = KSPSetFromOptions(pcis->ksp_N);CHKERRQ(ierr); 241 { 242 PetscBool damp_fixed = PETSC_FALSE, 243 remove_nullspace_fixed = PETSC_FALSE, 244 set_damping_factor_floating = PETSC_FALSE, 245 not_damp_floating = PETSC_FALSE, 246 not_remove_nullspace_floating = PETSC_FALSE; 247 PetscReal fixed_factor, 248 floating_factor; 249 250 ierr = PetscOptionsGetReal(((PetscObject)pc_ctx)->prefix,"-pc_is_damp_fixed",&fixed_factor,&damp_fixed);CHKERRQ(ierr); 251 if (!damp_fixed) { fixed_factor = 0.0; } 252 ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_damp_fixed",&damp_fixed,PETSC_NULL);CHKERRQ(ierr); 253 254 ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_remove_nullspace_fixed",&remove_nullspace_fixed,PETSC_NULL);CHKERRQ(ierr); 255 256 ierr = PetscOptionsGetReal(((PetscObject)pc_ctx)->prefix,"-pc_is_set_damping_factor_floating", 257 &floating_factor,&set_damping_factor_floating);CHKERRQ(ierr); 258 if (!set_damping_factor_floating) { floating_factor = 0.0; } 259 ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_set_damping_factor_floating",&set_damping_factor_floating,PETSC_NULL);CHKERRQ(ierr); 260 if (!set_damping_factor_floating) { floating_factor = 1.e-12; } 261 262 ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_not_damp_floating",¬_damp_floating,PETSC_NULL);CHKERRQ(ierr); 263 264 ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_not_remove_nullspace_floating",¬_remove_nullspace_floating,PETSC_NULL);CHKERRQ(ierr); 265 266 if (pcis->pure_neumann) { /* floating subdomain */ 267 if (!(not_damp_floating)) { 268 ierr = PCFactorSetShiftType(pc_ctx,MAT_SHIFT_NONZERO);CHKERRQ(ierr); 269 ierr = PCFactorSetShiftAmount(pc_ctx,floating_factor);CHKERRQ(ierr); 270 } 271 if (!(not_remove_nullspace_floating)){ 272 MatNullSpace nullsp; 273 ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,PETSC_NULL,&nullsp);CHKERRQ(ierr); 274 ierr = KSPSetNullSpace(pcis->ksp_N,nullsp);CHKERRQ(ierr); 275 ierr = MatNullSpaceDestroy(&nullsp);CHKERRQ(ierr); 276 } 277 } else { /* fixed subdomain */ 278 if (damp_fixed) { 279 ierr = PCFactorSetShiftType(pc_ctx,MAT_SHIFT_NONZERO);CHKERRQ(ierr); 280 ierr = PCFactorSetShiftAmount(pc_ctx,floating_factor);CHKERRQ(ierr); 281 } 282 if (remove_nullspace_fixed) { 283 MatNullSpace nullsp; 284 ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,PETSC_NULL,&nullsp);CHKERRQ(ierr); 285 ierr = KSPSetNullSpace(pcis->ksp_N,nullsp);CHKERRQ(ierr); 286 ierr = MatNullSpaceDestroy(&nullsp);CHKERRQ(ierr); 287 } 288 } 289 } 290 /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */ 291 ierr = KSPSetUp(pcis->ksp_N);CHKERRQ(ierr); 292 } 293 294 ierr = ISLocalToGlobalMappingGetInfo(((Mat_IS*)(pc->mat->data))->mapping,&(pcis->n_neigh),&(pcis->neigh),&(pcis->n_shared),&(pcis->shared));CHKERRQ(ierr); 295 pcis->ISLocalToGlobalMappingGetInfoWasCalled = PETSC_TRUE; 296 ierr = VecDestroy(&counter);CHKERRQ(ierr); 297 PetscFunctionReturn(0); 298 } 299 300 /* -------------------------------------------------------------------------- */ 301 /* 302 PCISDestroy - 303 */ 304 #undef __FUNCT__ 305 #define __FUNCT__ "PCISDestroy" 306 PetscErrorCode PCISDestroy(PC pc) 307 { 308 PC_IS *pcis = (PC_IS*)(pc->data); 309 PetscErrorCode ierr; 310 311 PetscFunctionBegin; 312 ierr = ISDestroy(&pcis->is_B_local);CHKERRQ(ierr); 313 ierr = ISDestroy(&pcis->is_I_local);CHKERRQ(ierr); 314 ierr = ISDestroy(&pcis->is_B_global);CHKERRQ(ierr); 315 ierr = ISDestroy(&pcis->is_I_global);CHKERRQ(ierr); 316 ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr); 317 ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr); 318 ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr); 319 ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr); 320 ierr = VecDestroy(&pcis->D);CHKERRQ(ierr); 321 ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr); 322 ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr); 323 ierr = VecDestroy(&pcis->vec1_N);CHKERRQ(ierr); 324 ierr = VecDestroy(&pcis->vec2_N);CHKERRQ(ierr); 325 ierr = VecDestroy(&pcis->vec1_D);CHKERRQ(ierr); 326 ierr = VecDestroy(&pcis->vec2_D);CHKERRQ(ierr); 327 ierr = VecDestroy(&pcis->vec3_D);CHKERRQ(ierr); 328 ierr = VecDestroy(&pcis->vec1_B);CHKERRQ(ierr); 329 ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr); 330 ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr); 331 ierr = VecDestroy(&pcis->vec1_global);CHKERRQ(ierr); 332 ierr = VecScatterDestroy(&pcis->global_to_D);CHKERRQ(ierr); 333 ierr = VecScatterDestroy(&pcis->N_to_B);CHKERRQ(ierr); 334 ierr = VecScatterDestroy(&pcis->global_to_B);CHKERRQ(ierr); 335 ierr = PetscFree(pcis->work_N);CHKERRQ(ierr); 336 if (pcis->ISLocalToGlobalMappingGetInfoWasCalled) { 337 ierr = ISLocalToGlobalMappingRestoreInfo((ISLocalToGlobalMapping)0,&(pcis->n_neigh),&(pcis->neigh),&(pcis->n_shared),&(pcis->shared));CHKERRQ(ierr); 338 } 339 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCISSetSubdomainScalingFactor_C","",PETSC_NULL);CHKERRQ(ierr); 340 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCISSetSubdomainDiagonalScaling_C","",PETSC_NULL);CHKERRQ(ierr); 341 PetscFunctionReturn(0); 342 } 343 344 /* -------------------------------------------------------------------------- */ 345 /* 346 PCISCreate - 347 */ 348 #undef __FUNCT__ 349 #define __FUNCT__ "PCISCreate" 350 PetscErrorCode PCISCreate(PC pc) 351 { 352 PC_IS *pcis = (PC_IS*)(pc->data); 353 PetscErrorCode ierr; 354 355 PetscFunctionBegin; 356 pcis->is_B_local = 0; 357 pcis->is_I_local = 0; 358 pcis->is_B_global = 0; 359 pcis->is_I_global = 0; 360 pcis->A_II = 0; 361 pcis->A_IB = 0; 362 pcis->A_BI = 0; 363 pcis->A_BB = 0; 364 pcis->D = 0; 365 pcis->ksp_N = 0; 366 pcis->ksp_D = 0; 367 pcis->vec1_N = 0; 368 pcis->vec2_N = 0; 369 pcis->vec1_D = 0; 370 pcis->vec2_D = 0; 371 pcis->vec3_D = 0; 372 pcis->vec1_B = 0; 373 pcis->vec2_B = 0; 374 pcis->vec3_B = 0; 375 pcis->vec1_global = 0; 376 pcis->work_N = 0; 377 pcis->global_to_D = 0; 378 pcis->N_to_B = 0; 379 pcis->global_to_B = 0; 380 pcis->ISLocalToGlobalMappingGetInfoWasCalled = PETSC_FALSE; 381 pcis->scaling_factor = 1.0; 382 /* composing functions */ 383 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCISSetSubdomainScalingFactor_C","PCISSetSubdomainScalingFactor_IS", 384 PCISSetSubdomainScalingFactor_IS);CHKERRQ(ierr); 385 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCISSetSubdomainDiagonalScaling_C","PCISSetSubdomainDiagonalScaling_IS", 386 PCISSetSubdomainDiagonalScaling_IS);CHKERRQ(ierr); 387 PetscFunctionReturn(0); 388 } 389 390 /* -------------------------------------------------------------------------- */ 391 /* 392 PCISApplySchur - 393 394 Input parameters: 395 . pc - preconditioner context 396 . v - vector to which the Schur complement is to be applied (it is NOT modified inside this function, UNLESS vec2_B is null) 397 398 Output parameters: 399 . vec1_B - result of Schur complement applied to chunk 400 . vec2_B - garbage (used as work space), or null (and v is used as workspace) 401 . vec1_D - garbage (used as work space) 402 . vec2_D - garbage (used as work space) 403 404 */ 405 #undef __FUNCT__ 406 #define __FUNCT__ "PCISApplySchur" 407 PetscErrorCode PCISApplySchur(PC pc, Vec v, Vec vec1_B, Vec vec2_B, Vec vec1_D, Vec vec2_D) 408 { 409 PetscErrorCode ierr; 410 PC_IS *pcis = (PC_IS*)(pc->data); 411 412 PetscFunctionBegin; 413 if (!vec2_B) { vec2_B = v; } 414 415 ierr = MatMult(pcis->A_BB,v,vec1_B);CHKERRQ(ierr); 416 ierr = MatMult(pcis->A_IB,v,vec1_D);CHKERRQ(ierr); 417 ierr = KSPSolve(pcis->ksp_D,vec1_D,vec2_D);CHKERRQ(ierr); 418 ierr = MatMult(pcis->A_BI,vec2_D,vec2_B);CHKERRQ(ierr); 419 ierr = VecAXPY(vec1_B,-1.0,vec2_B);CHKERRQ(ierr); 420 PetscFunctionReturn(0); 421 } 422 423 /* -------------------------------------------------------------------------- */ 424 /* 425 PCISScatterArrayNToVecB - Scatters interface node values from a big array (of all local nodes, interior or interface, 426 including ghosts) into an interface vector, when in SCATTER_FORWARD mode, or vice-versa, when in SCATTER_REVERSE 427 mode. 428 429 Input parameters: 430 . pc - preconditioner context 431 . array_N - [when in SCATTER_FORWARD mode] Array to be scattered into the vector 432 . v_B - [when in SCATTER_REVERSE mode] Vector to be scattered into the array 433 434 Output parameter: 435 . array_N - [when in SCATTER_REVERSE mode] Array to receive the scattered vector 436 . v_B - [when in SCATTER_FORWARD mode] Vector to receive the scattered array 437 438 Notes: 439 The entries in the array that do not correspond to interface nodes remain unaltered. 440 */ 441 #undef __FUNCT__ 442 #define __FUNCT__ "PCISScatterArrayNToVecB" 443 PetscErrorCode PCISScatterArrayNToVecB (PetscScalar *array_N, Vec v_B, InsertMode imode, ScatterMode smode, PC pc) 444 { 445 PetscInt i; 446 const PetscInt *idex; 447 PetscErrorCode ierr; 448 PetscScalar *array_B; 449 PC_IS *pcis = (PC_IS*)(pc->data); 450 451 PetscFunctionBegin; 452 ierr = VecGetArray(v_B,&array_B);CHKERRQ(ierr); 453 ierr = ISGetIndices(pcis->is_B_local,&idex);CHKERRQ(ierr); 454 455 if (smode == SCATTER_FORWARD) { 456 if (imode == INSERT_VALUES) { 457 for (i=0; i<pcis->n_B; i++) { array_B[i] = array_N[idex[i]]; } 458 } else { /* ADD_VALUES */ 459 for (i=0; i<pcis->n_B; i++) { array_B[i] += array_N[idex[i]]; } 460 } 461 } else { /* SCATTER_REVERSE */ 462 if (imode == INSERT_VALUES) { 463 for (i=0; i<pcis->n_B; i++) { array_N[idex[i]] = array_B[i]; } 464 } else { /* ADD_VALUES */ 465 for (i=0; i<pcis->n_B; i++) { array_N[idex[i]] += array_B[i]; } 466 } 467 } 468 ierr = ISRestoreIndices(pcis->is_B_local,&idex);CHKERRQ(ierr); 469 ierr = VecRestoreArray(v_B,&array_B);CHKERRQ(ierr); 470 PetscFunctionReturn(0); 471 } 472 473 /* -------------------------------------------------------------------------- */ 474 /* 475 PCISApplyInvSchur - Solves the Neumann problem related to applying the inverse of the Schur complement. 476 More precisely, solves the problem: 477 [ A_II A_IB ] [ . ] [ 0 ] 478 [ ] [ ] = [ ] 479 [ A_BI A_BB ] [ x ] [ b ] 480 481 Input parameters: 482 . pc - preconditioner context 483 . b - vector of local interface nodes (including ghosts) 484 485 Output parameters: 486 . x - vector of local interface nodes (including ghosts); returns the application of the inverse of the Schur 487 complement to b 488 . vec1_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space) 489 . vec2_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space) 490 491 */ 492 #undef __FUNCT__ 493 #define __FUNCT__ "PCISApplyInvSchur" 494 PetscErrorCode PCISApplyInvSchur (PC pc, Vec b, Vec x, Vec vec1_N, Vec vec2_N) 495 { 496 PetscErrorCode ierr; 497 PC_IS *pcis = (PC_IS*)(pc->data); 498 499 PetscFunctionBegin; 500 /* 501 Neumann solvers. 502 Applying the inverse of the local Schur complement, i.e, solving a Neumann 503 Problem with zero at the interior nodes of the RHS and extracting the interface 504 part of the solution. inverse Schur complement is applied to b and the result 505 is stored in x. 506 */ 507 /* Setting the RHS vec1_N */ 508 ierr = VecSet(vec1_N,0.0);CHKERRQ(ierr); 509 ierr = VecScatterBegin(pcis->N_to_B,b,vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 510 ierr = VecScatterEnd (pcis->N_to_B,b,vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 511 /* Checking for consistency of the RHS */ 512 { 513 PetscBool flg = PETSC_FALSE; 514 ierr = PetscOptionsGetBool(PETSC_NULL,"-pc_is_check_consistency",&flg,PETSC_NULL);CHKERRQ(ierr); 515 if (flg) { 516 PetscScalar average; 517 PetscViewer viewer; 518 ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);CHKERRQ(ierr); 519 520 ierr = VecSum(vec1_N,&average);CHKERRQ(ierr); 521 average = average / ((PetscReal)pcis->n); 522 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 523 if (pcis->pure_neumann) { 524 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d is floating. Average = % 1.14e\n",PetscGlobalRank,PetscAbsScalar(average));CHKERRQ(ierr); 525 } else { 526 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d is fixed. Average = % 1.14e\n",PetscGlobalRank,PetscAbsScalar(average));CHKERRQ(ierr); 527 } 528 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 529 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 530 } 531 } 532 /* Solving the system for vec2_N */ 533 ierr = KSPSolve(pcis->ksp_N,vec1_N,vec2_N);CHKERRQ(ierr); 534 /* Extracting the local interface vector out of the solution */ 535 ierr = VecScatterBegin(pcis->N_to_B,vec2_N,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 536 ierr = VecScatterEnd (pcis->N_to_B,vec2_N,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 537 PetscFunctionReturn(0); 538 } 539 540 541 542 543 544 545 546 547 548