1 #include <petsc/private/kspimpl.h> /*I <petscksp.h> I*/ 2 #include <../src/ksp/pc/impls/bddc/bddc.h> 3 4 /* 5 This file implements the FETI-DP method in PETSc as part of KSP. 6 */ 7 typedef struct { 8 KSP parentksp; 9 } KSP_FETIDPMon; 10 11 typedef struct { 12 KSP innerksp; /* the KSP for the Lagrange multipliers */ 13 PC innerbddc; /* the inner BDDC object */ 14 PetscBool fully_redundant; /* true for using a fully redundant set of multipliers */ 15 PetscBool userbddc; /* true if the user provided the PCBDDC object */ 16 PetscBool saddlepoint; /* support for saddle point problems */ 17 KSP_FETIDPMon *monctx; /* monitor context, used to pass user defined monitors 18 in the physical space */ 19 } KSP_FETIDP; 20 21 #undef __FUNCT__ 22 #define __FUNCT__ "KSPFETIDPSetPressureOperators_FETIDP" 23 static PetscErrorCode KSPFETIDPSetPressureOperators_FETIDP(KSP ksp, Mat A, Mat P) 24 { 25 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 26 PetscErrorCode ierr; 27 28 PetscFunctionBegin; 29 if (A || P) fetidp->saddlepoint = PETSC_TRUE; 30 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_AAmat",(PetscObject)A);CHKERRQ(ierr); 31 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PAmat",(PetscObject)P);CHKERRQ(ierr); 32 PetscFunctionReturn(0); 33 } 34 35 #undef __FUNCT__ 36 #define __FUNCT__ "KSPFETIDPSetPressureOperators" 37 /*@ 38 KSPFETIDPSetPressureOperators - Sets the operators used to setup the pressure preconditioner for saddle point FETI-DP. 39 40 Collective on KSP 41 42 Input Parameters: 43 + ksp - the FETI-DP Krylov solver 44 . A - the linear operator defining the pressure problem 45 - P - the linear operator to be preconditioned 46 47 Level: advanced 48 49 Notes: The operators can be either passed in monolithic global ordering or in interface pressure ordering. 50 In the latter case, the interface pressure ordering of dofs needs to satisfy 51 pid_1 < pid_2 iff gid_1 < gid_2 52 where pid_1 and pid_2 are two different pressure dof numbers and gid_1 and gid_2 the corresponding 53 id in the global ordering. 54 55 .seealso: MATIS, PCBDDC, KSPFETIDPGetInnerBDDC, KSPFETIDPGetInnerKSP, KSPSetOperators 56 @*/ 57 PetscErrorCode KSPFETIDPSetPressureOperators(KSP ksp, Mat A, Mat P) 58 { 59 PetscErrorCode ierr; 60 61 PetscFunctionBegin; 62 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 63 if (A) PetscValidHeaderSpecific(A,MAT_CLASSID,2); 64 if (P) PetscValidHeaderSpecific(P,MAT_CLASSID,3); 65 ierr = PetscTryMethod(ksp,"KSPFETIDPSetPressureOperators_C",(KSP,Mat,Mat),(ksp,A,P));CHKERRQ(ierr); 66 PetscFunctionReturn(0); 67 } 68 69 #undef __FUNCT__ 70 #define __FUNCT__ "KSPFETIDPGetInnerKSP_FETIDP" 71 static PetscErrorCode KSPFETIDPGetInnerKSP_FETIDP(KSP ksp, KSP* innerksp) 72 { 73 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 74 75 PetscFunctionBegin; 76 *innerksp = fetidp->innerksp; 77 PetscFunctionReturn(0); 78 } 79 80 #undef __FUNCT__ 81 #define __FUNCT__ "KSPFETIDPGetInnerKSP" 82 /*@ 83 KSPFETIDPGetInnerKSP - Gets the KSP object for the Lagrange multipliers 84 85 Input Parameters: 86 + ksp - the FETI-DP KSP 87 - innerksp - the KSP for the multipliers 88 89 Level: advanced 90 91 Notes: 92 93 .seealso: MATIS, PCBDDC, KSPFETIDPSetInnerBDDC, KSPFETIDPGetInnerBDDC 94 @*/ 95 PetscErrorCode KSPFETIDPGetInnerKSP(KSP ksp, KSP* innerksp) 96 { 97 PetscErrorCode ierr; 98 99 PetscFunctionBegin; 100 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 101 PetscValidPointer(innerksp,2); 102 ierr = PetscUseMethod(ksp,"KSPFETIDPGetInnerKSP_C",(KSP,KSP*),(ksp,innerksp));CHKERRQ(ierr); 103 PetscFunctionReturn(0); 104 } 105 106 #undef __FUNCT__ 107 #define __FUNCT__ "KSPFETIDPGetInnerBDDC_FETIDP" 108 static PetscErrorCode KSPFETIDPGetInnerBDDC_FETIDP(KSP ksp, PC* pc) 109 { 110 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 111 112 PetscFunctionBegin; 113 *pc = fetidp->innerbddc; 114 PetscFunctionReturn(0); 115 } 116 117 #undef __FUNCT__ 118 #define __FUNCT__ "KSPFETIDPGetInnerBDDC" 119 /*@ 120 KSPFETIDPGetInnerBDDC - Gets the BDDC preconditioner used to setup the FETI-DP matrix for the Lagrange multipliers 121 122 Input Parameters: 123 + ksp - the FETI-DP Krylov solver 124 - pc - the BDDC preconditioner 125 126 Level: advanced 127 128 Notes: 129 130 .seealso: MATIS, PCBDDC, KSPFETIDPSetInnerBDDC, KSPFETIDPGetInnerKSP 131 @*/ 132 PetscErrorCode KSPFETIDPGetInnerBDDC(KSP ksp, PC* pc) 133 { 134 PetscErrorCode ierr; 135 136 PetscFunctionBegin; 137 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 138 PetscValidPointer(pc,2); 139 ierr = PetscUseMethod(ksp,"KSPFETIDPGetInnerBDDC_C",(KSP,PC*),(ksp,pc));CHKERRQ(ierr); 140 PetscFunctionReturn(0); 141 } 142 143 #undef __FUNCT__ 144 #define __FUNCT__ "KSPFETIDPSetInnerBDDC_FETIDP" 145 static PetscErrorCode KSPFETIDPSetInnerBDDC_FETIDP(KSP ksp, PC pc) 146 { 147 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 148 PetscErrorCode ierr; 149 150 PetscFunctionBegin; 151 ierr = PetscObjectReference((PetscObject)pc);CHKERRQ(ierr); 152 ierr = PCDestroy(&fetidp->innerbddc);CHKERRQ(ierr); 153 fetidp->innerbddc = pc; 154 fetidp->userbddc = PETSC_TRUE; 155 PetscFunctionReturn(0); 156 } 157 158 #undef __FUNCT__ 159 #define __FUNCT__ "KSPFETIDPSetInnerBDDC" 160 /*@ 161 KSPFETIDPSetInnerBDDC - Sets the BDDC preconditioner used to setup the FETI-DP matrix for the Lagrange multipliers 162 163 Collective on KSP 164 165 Input Parameters: 166 + ksp - the FETI-DP Krylov solver 167 - pc - the BDDC preconditioner 168 169 Level: advanced 170 171 Notes: 172 173 .seealso: MATIS, PCBDDC, KSPFETIDPGetInnerBDDC, KSPFETIDPGetInnerKSP 174 @*/ 175 PetscErrorCode KSPFETIDPSetInnerBDDC(KSP ksp, PC pc) 176 { 177 PetscBool isbddc; 178 PetscErrorCode ierr; 179 180 PetscFunctionBegin; 181 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 182 PetscValidHeaderSpecific(pc,PC_CLASSID,2); 183 ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr); 184 if (!isbddc) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_WRONG,"KSPFETIDPSetInnerBDDC need a PCBDDC preconditioner"); 185 ierr = PetscTryMethod(ksp,"KSPFETIDPSetInnerBDDC_C",(KSP,PC),(ksp,pc));CHKERRQ(ierr); 186 PetscFunctionReturn(0); 187 } 188 189 #undef __FUNCT__ 190 #define __FUNCT__ "KSPBuildSolution_FETIDP" 191 static PetscErrorCode KSPBuildSolution_FETIDP(KSP ksp,Vec v,Vec *V) 192 { 193 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 194 Mat F; 195 Vec Xl; 196 PetscErrorCode ierr; 197 198 PetscFunctionBegin; 199 ierr = KSPGetOperators(fetidp->innerksp,&F,NULL);CHKERRQ(ierr); 200 ierr = KSPBuildSolution(fetidp->innerksp,NULL,&Xl);CHKERRQ(ierr); 201 if (v) { 202 ierr = PCBDDCMatFETIDPGetSolution(F,Xl,v);CHKERRQ(ierr); 203 *V = v; 204 } else { 205 ierr = PCBDDCMatFETIDPGetSolution(F,Xl,*V);CHKERRQ(ierr); 206 } 207 PetscFunctionReturn(0); 208 } 209 210 #undef __FUNCT__ 211 #define __FUNCT__ "KSPMonitor_FETIDP" 212 static PetscErrorCode KSPMonitor_FETIDP(KSP ksp,PetscInt it,PetscReal rnorm,void* ctx) 213 { 214 KSP_FETIDPMon *monctx = (KSP_FETIDPMon*)ctx; 215 PetscErrorCode ierr; 216 217 PetscFunctionBegin; 218 ierr = KSPMonitor(monctx->parentksp,it,rnorm);CHKERRQ(ierr); 219 PetscFunctionReturn(0); 220 } 221 222 #undef __FUNCT__ 223 #define __FUNCT__ "KSPComputeEigenvalues_FETIDP" 224 static PetscErrorCode KSPComputeEigenvalues_FETIDP(KSP ksp,PetscInt nmax,PetscReal *r,PetscReal *c,PetscInt *neig) 225 { 226 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 227 PetscErrorCode ierr; 228 229 PetscFunctionBegin; 230 ierr = KSPComputeEigenvalues(fetidp->innerksp,nmax,r,c,neig);CHKERRQ(ierr); 231 PetscFunctionReturn(0); 232 } 233 234 #undef __FUNCT__ 235 #define __FUNCT__ "KSPComputeExtremeSingularValues_FETIDP" 236 static PetscErrorCode KSPComputeExtremeSingularValues_FETIDP(KSP ksp,PetscReal *emax,PetscReal *emin) 237 { 238 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 239 PetscErrorCode ierr; 240 241 PetscFunctionBegin; 242 ierr = KSPComputeExtremeSingularValues(fetidp->innerksp,emax,emin);CHKERRQ(ierr); 243 PetscFunctionReturn(0); 244 } 245 246 #undef __FUNCT__ 247 #define __FUNCT__ "KSPFETIDPSetUpOperators" 248 static PetscErrorCode KSPFETIDPSetUpOperators(KSP ksp) 249 { 250 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 251 PC_BDDC *pcbddc = (PC_BDDC*)fetidp->innerbddc->data; 252 Mat A,Ap; 253 PetscInt fid = -1; 254 PetscBool ismatis,pisz; 255 PetscBool flip; /* Usually, Stokes is written 256 | A B'| | v | = | f | 257 | B 0 | | p | = | g | 258 If saddlepoint_flip is true, the code assumes it is written as 259 | A B'| | v | = | f | 260 |-B 0 | | p | = |-g | 261 */ 262 PetscErrorCode ierr; 263 264 PetscFunctionBegin; 265 pisz = PETSC_FALSE; 266 flip = PETSC_FALSE; 267 ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)ksp),((PetscObject)ksp)->prefix,"FETI-DP options","PC");CHKERRQ(ierr); 268 ierr = PetscOptionsInt("-ksp_fetidp_pressure_field","Field id for pressures for saddle-point problems",NULL,fid,&fid,NULL);CHKERRQ(ierr); 269 ierr = PetscOptionsBool("-ksp_fetidp_pressure_iszero","Zero pressure block",NULL,pisz,&pisz,NULL);CHKERRQ(ierr); 270 ierr = PetscOptionsBool("-ksp_fetidp_saddlepoint_flip","Flip the sign of the pressure-velocity (lower-left) block",NULL,flip,&flip,NULL);CHKERRQ(ierr); 271 ierr = PetscOptionsEnd();CHKERRQ(ierr); 272 273 fetidp->saddlepoint = (fid >= 0 ? PETSC_TRUE : fetidp->saddlepoint); 274 275 ierr = KSPGetOperators(ksp,&A,&Ap);CHKERRQ(ierr); 276 ierr = PetscObjectTypeCompare((PetscObject)Ap,MATIS,&ismatis);CHKERRQ(ierr); 277 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Pmat should be of type MATIS"); 278 279 /* see if MATIS has same fields attached */ 280 if (!pcbddc->n_ISForDofsLocal && !pcbddc->n_ISForDofs) { 281 PetscContainer c; 282 283 ierr = PetscObjectQuery((PetscObject)Ap,"_convert_nest_lfields",(PetscObject*)&c);CHKERRQ(ierr); 284 if (c) { 285 MatISLocalFields lf; 286 ierr = PetscContainerGetPointer(c,(void**)&lf);CHKERRQ(ierr); 287 ierr = PCBDDCSetDofsSplittingLocal(fetidp->innerbddc,lf->nr,lf->rf);CHKERRQ(ierr); 288 } 289 } 290 291 if (!fetidp->saddlepoint) { 292 ierr = PCSetOperators(fetidp->innerbddc,A,Ap);CHKERRQ(ierr); 293 } else { 294 KSP kP; 295 Mat nA,lA; 296 Mat PAmat,PPmat; 297 Vec rhs_flip; 298 IS pP,lP; 299 300 ierr = MatISGetLocalMat(Ap,&lA);CHKERRQ(ierr); 301 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_lA",(PetscObject)lA);CHKERRQ(ierr); 302 303 /* saved index sets */ 304 pP = NULL; 305 lP = NULL; 306 ierr = PetscObjectQuery((PetscObject)fetidp->innerbddc,"__KSPFETIDP_pP" ,(PetscObject*)&pP);CHKERRQ(ierr); 307 ierr = PetscObjectQuery((PetscObject)fetidp->innerbddc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr); 308 309 /* vector for flipping rhs */ 310 rhs_flip = NULL; 311 ierr = PetscObjectQuery((PetscObject)fetidp->innerbddc,"__KSPFETIDP_flip" ,(PetscObject*)&rhs_flip);CHKERRQ(ierr); 312 if (!pP && !lP) { /* first time, need to compute boundary pressure dofs */ 313 PC_IS *pcis = (PC_IS*)fetidp->innerbddc->data; 314 Mat_IS *matis = (Mat_IS*)(Ap->data); 315 ISLocalToGlobalMapping l2g; 316 IS II,pII,lPall,Pall,is1,is2; 317 const PetscInt *idxs; 318 PetscInt nl,ni,*widxs; 319 PetscInt i,j,n_neigh,*neigh,*n_shared,**shared,*count; 320 PetscInt rst,ren,n; 321 PetscBool ploc; 322 323 ierr = MatGetLocalSize(Ap,&nl,NULL);CHKERRQ(ierr); 324 ierr = MatGetOwnershipRange(Ap,&rst,&ren);CHKERRQ(ierr); 325 ierr = MatGetLocalSize(lA,&n,NULL);CHKERRQ(ierr); 326 327 if (!pcis->is_I_local) { /* need to compute interior dofs */ 328 ierr = PetscCalloc1(n,&count);CHKERRQ(ierr); 329 ierr = MatGetLocalToGlobalMapping(Ap,&l2g,NULL);CHKERRQ(ierr); 330 ierr = ISLocalToGlobalMappingGetInfo(l2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr); 331 for (i=1;i<n_neigh;i++) 332 for (j=0;j<n_shared[i];j++) 333 count[shared[i][j]] += 1; 334 for (i=0,j=0;i<n;i++) if (!count[i]) count[j++] = i; 335 ierr = ISLocalToGlobalMappingRestoreInfo(l2g,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr); 336 ierr = ISCreateGeneral(PETSC_COMM_SELF,j,count,PETSC_OWN_POINTER,&II);CHKERRQ(ierr); 337 } else { 338 ierr = PetscObjectReference((PetscObject)pcis->is_I_local);CHKERRQ(ierr); 339 II = pcis->is_I_local; 340 } 341 342 /* interior dofs in layout */ 343 ierr = MatISSetUpSF(Ap);CHKERRQ(ierr); 344 ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr); 345 ierr = PetscMemzero(matis->sf_rootdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 346 ierr = ISGetLocalSize(II,&ni);CHKERRQ(ierr); 347 ierr = ISGetIndices(II,&idxs);CHKERRQ(ierr); 348 for (i=0;i<ni;i++) matis->sf_leafdata[idxs[i]] = 1; 349 ierr = ISRestoreIndices(II,&idxs);CHKERRQ(ierr); 350 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPIU_REPLACE);CHKERRQ(ierr); 351 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPIU_REPLACE);CHKERRQ(ierr); 352 ierr = PetscMalloc1(PetscMax(nl,n),&widxs);CHKERRQ(ierr); 353 for (i=0,ni=0;i<nl;i++) if (matis->sf_rootdata[i]) widxs[ni++] = i+rst; 354 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),ni,widxs,PETSC_COPY_VALUES,&pII);CHKERRQ(ierr); 355 356 /* pressure space at the interface */ 357 Pall = NULL; 358 lPall = NULL; 359 ploc = PETSC_FALSE; 360 if (fid >= 0) { 361 if (pcbddc->n_ISForDofsLocal) { 362 PetscInt np; 363 364 if (fid >= pcbddc->n_ISForDofsLocal) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Invalid field id for pressure %D, max %D",fid,pcbddc->n_ISForDofsLocal); 365 /* need a sequential IS */ 366 ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[fid],&np);CHKERRQ(ierr); 367 ierr = ISGetIndices(pcbddc->ISForDofsLocal[fid],&idxs);CHKERRQ(ierr); 368 ierr = ISCreateGeneral(PETSC_COMM_SELF,np,idxs,PETSC_COPY_VALUES,&lPall);CHKERRQ(ierr); 369 ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[fid],&idxs);CHKERRQ(ierr); 370 ploc = PETSC_TRUE; 371 } else if (pcbddc->n_ISForDofs) { 372 if (fid >= pcbddc->n_ISForDofs) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Invalid field id for pressure %D, max %D",fid,pcbddc->n_ISForDofs); 373 ierr = PetscObjectReference((PetscObject)pcbddc->ISForDofs[fid]);CHKERRQ(ierr); 374 Pall = pcbddc->ISForDofs[fid]; 375 } else SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Missing fields! Use PCBDDCSetDofsSplitting/Local"); 376 } else { /* fallback to zero pressure block */ 377 ierr = MatFindZeroDiagonals(Ap,&Pall);CHKERRQ(ierr); 378 } 379 if (ploc) { 380 ierr = ISDifference(lPall,II,&lP);CHKERRQ(ierr); 381 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_lP",(PetscObject)lP);CHKERRQ(ierr); 382 } else { 383 ierr = ISDifference(Pall,pII,&pP);CHKERRQ(ierr); 384 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_pP",(PetscObject)pP);CHKERRQ(ierr); 385 /* need all local pressure dofs */ 386 ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr); 387 ierr = PetscMemzero(matis->sf_rootdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 388 ierr = ISGetLocalSize(Pall,&ni);CHKERRQ(ierr); 389 ierr = ISGetIndices(Pall,&idxs);CHKERRQ(ierr); 390 for (i=0;i<ni;i++) matis->sf_rootdata[idxs[i]-rst] = 1; 391 ierr = ISRestoreIndices(Pall,&idxs);CHKERRQ(ierr); 392 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 393 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 394 for (i=0,ni=0;i<n;i++) if (matis->sf_leafdata[i]) widxs[ni++] = i; 395 ierr = ISCreateGeneral(PETSC_COMM_SELF,ni,widxs,PETSC_COPY_VALUES,&lPall);CHKERRQ(ierr); 396 } 397 398 if (flip) { 399 PetscInt npl; 400 if (!Pall) { 401 ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr); 402 ierr = PetscMemzero(matis->sf_rootdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 403 ierr = ISGetLocalSize(lPall,&ni);CHKERRQ(ierr); 404 ierr = ISGetIndices(lPall,&idxs);CHKERRQ(ierr); 405 for (i=0;i<ni;i++) matis->sf_leafdata[idxs[i]] = 1; 406 ierr = ISRestoreIndices(lPall,&idxs);CHKERRQ(ierr); 407 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPIU_REPLACE);CHKERRQ(ierr); 408 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPIU_REPLACE);CHKERRQ(ierr); 409 for (i=0,ni=0;i<nl;i++) if (matis->sf_rootdata[i]) widxs[ni++] = i+rst; 410 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),ni,widxs,PETSC_COPY_VALUES,&Pall);CHKERRQ(ierr); 411 } 412 ierr = ISGetLocalSize(Pall,&npl);CHKERRQ(ierr); 413 ierr = ISGetIndices(Pall,&idxs);CHKERRQ(ierr); 414 ierr = MatCreateVecs(Ap,NULL,&rhs_flip);CHKERRQ(ierr); 415 ierr = VecSet(rhs_flip,1.);CHKERRQ(ierr); 416 ierr = VecSetOption(rhs_flip,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 417 for (i=0;i<npl;i++) { 418 ierr = VecSetValue(rhs_flip,idxs[i],-1.,INSERT_VALUES);CHKERRQ(ierr); 419 } 420 ierr = VecAssemblyBegin(rhs_flip);CHKERRQ(ierr); 421 ierr = VecAssemblyEnd(rhs_flip);CHKERRQ(ierr); 422 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_flip",(PetscObject)rhs_flip);CHKERRQ(ierr); 423 ierr = ISRestoreIndices(Pall,&idxs);CHKERRQ(ierr); 424 } 425 ierr = ISDestroy(&Pall);CHKERRQ(ierr); 426 ierr = ISDestroy(&pII);CHKERRQ(ierr); 427 428 /* local interface pressures in subdomain-wise and global ordering */ 429 ierr = PetscMemzero(matis->sf_leafdata,n*sizeof(PetscInt));CHKERRQ(ierr); 430 ierr = PetscMemzero(matis->sf_rootdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 431 if (pP) { 432 ierr = ISGetLocalSize(pP,&ni);CHKERRQ(ierr); 433 ierr = ISGetIndices(pP,&idxs);CHKERRQ(ierr); 434 for (i=0;i<ni;i++) matis->sf_rootdata[idxs[i]-rst] = 1; 435 ierr = ISRestoreIndices(pP,&idxs);CHKERRQ(ierr); 436 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 437 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 438 for (i=0,ni=0;i<n;i++) if (matis->sf_leafdata[i]) widxs[ni++] = i; 439 ierr = ISLocalToGlobalMappingApply(l2g,ni,widxs,widxs+ni);CHKERRQ(ierr); 440 ierr = ISCreateGeneral(PETSC_COMM_SELF,ni,widxs,PETSC_COPY_VALUES,&lP);CHKERRQ(ierr); 441 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_lP",(PetscObject)lP);CHKERRQ(ierr); 442 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),ni,widxs+ni,PETSC_COPY_VALUES,&is1);CHKERRQ(ierr); 443 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_gP",(PetscObject)is1);CHKERRQ(ierr); 444 ierr = ISDestroy(&is1);CHKERRQ(ierr); 445 } else { 446 ierr = ISGetLocalSize(lP,&ni);CHKERRQ(ierr); 447 ierr = ISGetIndices(lP,&idxs);CHKERRQ(ierr); 448 for (i=0;i<ni;i++) 449 if (idxs[i] >=0 && idxs[i] < n) 450 matis->sf_leafdata[idxs[i]] = 1; 451 ierr = ISRestoreIndices(lP,&idxs);CHKERRQ(ierr); 452 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPIU_REPLACE);CHKERRQ(ierr); 453 ierr = ISLocalToGlobalMappingApply(l2g,ni,idxs,widxs);CHKERRQ(ierr); 454 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),ni,widxs,PETSC_COPY_VALUES,&is1);CHKERRQ(ierr); 455 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_gP",(PetscObject)is1);CHKERRQ(ierr); 456 ierr = ISDestroy(&is1);CHKERRQ(ierr); 457 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,matis->sf_leafdata,matis->sf_rootdata,MPIU_REPLACE);CHKERRQ(ierr); 458 for (i=0,ni=0;i<nl;i++) if (matis->sf_rootdata[i]) widxs[ni++] = i+rst; 459 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),ni,widxs,PETSC_COPY_VALUES,&pP);CHKERRQ(ierr); 460 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_pP",(PetscObject)pP);CHKERRQ(ierr); 461 } 462 ierr = PetscFree(widxs);CHKERRQ(ierr); 463 464 /* We may want to use a discrete harmonic solver instead 465 of a Stokes harmonic for the Dirichler preconditioner 466 Need to extract the interior pressure dofs in interior dofs ordering */ 467 ierr = ISDifference(lPall,lP,&is1);CHKERRQ(ierr); 468 ierr = ISDifference(II,is1,&is2);CHKERRQ(ierr); 469 ierr = ISDestroy(&is1);CHKERRQ(ierr); 470 ierr = ISLocalToGlobalMappingCreateIS(II,&l2g);CHKERRQ(ierr); 471 ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,is2,&is1);CHKERRQ(ierr); 472 ierr = ISGetLocalSize(is1,&i);CHKERRQ(ierr); 473 ierr = ISGetLocalSize(is2,&j);CHKERRQ(ierr); 474 if (i != j) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent local sizes %D and %D for iP",i,j); 475 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_iP",(PetscObject)is1);CHKERRQ(ierr); 476 ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 477 ierr = ISDestroy(&is1);CHKERRQ(ierr); 478 ierr = ISDestroy(&is2);CHKERRQ(ierr); 479 ierr = ISDestroy(&lPall);CHKERRQ(ierr); 480 ierr = ISDestroy(&II);CHKERRQ(ierr); 481 482 /* exclude interface pressures from the inner BDDC */ 483 if (pcbddc->DirichletBoundariesLocal) { 484 IS list[2],plP,isout; 485 PetscInt np; 486 487 /* need a parallel IS */ 488 ierr = ISGetLocalSize(lP,&np);CHKERRQ(ierr); 489 ierr = ISGetIndices(lP,&idxs);CHKERRQ(ierr); 490 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),np,idxs,PETSC_USE_POINTER,&plP);CHKERRQ(ierr); 491 list[0] = plP; 492 list[1] = pcbddc->DirichletBoundariesLocal; 493 ierr = ISConcatenate(PetscObjectComm((PetscObject)ksp),2,list,&isout);CHKERRQ(ierr); 494 ierr = ISDestroy(&plP);CHKERRQ(ierr); 495 ierr = ISRestoreIndices(lP,&idxs);CHKERRQ(ierr); 496 ierr = PCBDDCSetDirichletBoundariesLocal(fetidp->innerbddc,isout);CHKERRQ(ierr); 497 ierr = ISDestroy(&isout);CHKERRQ(ierr); 498 } else if (pcbddc->DirichletBoundaries) { 499 IS list[2],isout; 500 501 list[0] = pP; 502 list[1] = pcbddc->DirichletBoundaries; 503 ierr = ISConcatenate(PetscObjectComm((PetscObject)ksp),2,list,&isout);CHKERRQ(ierr); 504 ierr = PCBDDCSetDirichletBoundaries(fetidp->innerbddc,isout);CHKERRQ(ierr); 505 ierr = ISDestroy(&isout);CHKERRQ(ierr); 506 } else { 507 IS plP; 508 PetscInt np; 509 510 /* need a parallel IS */ 511 ierr = ISGetLocalSize(lP,&np);CHKERRQ(ierr); 512 ierr = ISGetIndices(lP,&idxs);CHKERRQ(ierr); 513 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ksp),np,idxs,PETSC_COPY_VALUES,&plP);CHKERRQ(ierr); 514 ierr = PCBDDCSetDirichletBoundariesLocal(fetidp->innerbddc,plP);CHKERRQ(ierr); 515 ierr = ISDestroy(&plP);CHKERRQ(ierr); 516 ierr = ISRestoreIndices(lP,&idxs);CHKERRQ(ierr); 517 } 518 } else { 519 if (!pP) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_PLIB,"Missing global interface pressure field"); 520 if (!lP) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_PLIB,"Missing local interface pressure field"); 521 ierr = PetscObjectReference((PetscObject)pP);CHKERRQ(ierr); 522 ierr = PetscObjectReference((PetscObject)lP);CHKERRQ(ierr); 523 if (rhs_flip) { 524 ierr = PetscObjectReference((PetscObject)rhs_flip);CHKERRQ(ierr); 525 } 526 } 527 528 /* Set operator for inner BDDC */ 529 ierr = MatDuplicate(Ap,MAT_COPY_VALUES,&nA);CHKERRQ(ierr); 530 if (rhs_flip) { 531 Mat lA2; 532 533 ierr = MatDiagonalScale(nA,rhs_flip,NULL);CHKERRQ(ierr); 534 ierr = MatISGetLocalMat(nA,&lA);CHKERRQ(ierr); 535 ierr = MatDuplicate(lA,MAT_COPY_VALUES,&lA2);CHKERRQ(ierr); 536 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_lA",(PetscObject)lA2);CHKERRQ(ierr); 537 ierr = MatDestroy(&lA2);CHKERRQ(ierr); 538 } 539 ierr = MatSetOption(nA,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 540 ierr = MatZeroRowsColumnsIS(nA,pP,1.,NULL,NULL);CHKERRQ(ierr); 541 ierr = PCSetOperators(fetidp->innerbddc,nA,nA);CHKERRQ(ierr); 542 ierr = MatDestroy(&nA);CHKERRQ(ierr); 543 ierr = VecDestroy(&rhs_flip);CHKERRQ(ierr); 544 545 /* non-zero rhs on interior dofs when applying the preconditioner */ 546 pcbddc->switch_static = PETSC_TRUE; 547 548 /* Operators for pressure preconditioner */ 549 ierr = PetscObjectQuery((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PAmat",(PetscObject*)&PAmat);CHKERRQ(ierr); 550 ierr = PetscObjectQuery((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PPmat",(PetscObject*)&PPmat);CHKERRQ(ierr); 551 if (PAmat) { 552 ierr = PetscObjectReference((PetscObject)PAmat);CHKERRQ(ierr); 553 } 554 if (PPmat) { 555 ierr = PetscObjectReference((PetscObject)PPmat);CHKERRQ(ierr); 556 } 557 558 /* Extract pressure block */ 559 if (!pisz) { 560 Mat C; 561 562 ierr = MatGetSubMatrix(Ap,pP,pP,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 563 ierr = MatScale(C,-1.);CHKERRQ(ierr); 564 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_C",(PetscObject)C);CHKERRQ(ierr); 565 /* default operators for the interface pressure solver */ 566 if (!PAmat) { 567 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); 568 PAmat = C; 569 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PAmat",(PetscObject)PAmat);CHKERRQ(ierr); 570 } 571 if (!PPmat) { 572 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); 573 PPmat = C; 574 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PPmat",(PetscObject)PPmat);CHKERRQ(ierr); 575 } 576 ierr = MatDestroy(&C);CHKERRQ(ierr); 577 } 578 579 if (!PAmat) { /* Just use the identity */ 580 PetscInt nl; 581 582 ierr = ISGetLocalSize(pP,&nl);CHKERRQ(ierr); 583 ierr = MatCreate(PetscObjectComm((PetscObject)ksp),&PAmat);CHKERRQ(ierr); 584 ierr = MatSetSizes(PAmat,nl,nl,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 585 ierr = MatSetType(PAmat,MATAIJ);CHKERRQ(ierr); 586 ierr = MatMPIAIJSetPreallocation(PAmat,1,NULL,0,NULL);CHKERRQ(ierr); 587 ierr = MatSeqAIJSetPreallocation(PAmat,1,NULL);CHKERRQ(ierr); 588 ierr = MatAssemblyBegin(PAmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 589 ierr = MatAssemblyEnd(PAmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 590 ierr = MatShift(PAmat,1.);CHKERRQ(ierr); 591 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PAmat",(PetscObject)PAmat);CHKERRQ(ierr); 592 } else { /* check size of pressure operator and restrict if needed */ 593 PetscInt AM,PAM,PAN,pam,pan,am,an,pl; 594 595 ierr = MatGetSize(Ap,&AM,NULL);CHKERRQ(ierr); 596 ierr = MatGetSize(PAmat,&PAM,&PAN);CHKERRQ(ierr); 597 ierr = MatGetLocalSize(PAmat,&pam,&pan);CHKERRQ(ierr); 598 ierr = MatGetLocalSize(Ap,&am,&an);CHKERRQ(ierr); 599 ierr = ISGetLocalSize(pP,&pl);CHKERRQ(ierr); 600 if (PAM != PAN) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Pressure matrix must be square, unsupported %D x %D",PAM,PAN); 601 if (pam != pan) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Local sizes of pressure matrix must be equal, unsupported %D x %D",pam,pan); 602 if (pam != am && pam != pl) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local rows %D for pressure matrix! Supported are %D or %D",pam,am,pl); 603 if (pan != an && pan != pl) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local columns %D for pressure matrix! Supported are %D or %D",pan,an,pl); 604 if (PAM == AM) { /* monolithic ordering, restrict to interface pressure */ 605 Mat C; 606 607 ierr = MatGetSubMatrix(PAmat,pP,pP,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 608 ierr = MatDestroy(&PAmat);CHKERRQ(ierr); 609 PAmat = C; 610 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PAmat",(PetscObject)PAmat);CHKERRQ(ierr); 611 } 612 } 613 if (PPmat) { 614 PetscInt AM,PAM,PAN,pam,pan,am,an,pl; 615 616 ierr = MatGetSize(Ap,&AM,NULL);CHKERRQ(ierr); 617 ierr = MatGetSize(PPmat,&PAM,&PAN);CHKERRQ(ierr); 618 ierr = MatGetLocalSize(PPmat,&pam,&pan);CHKERRQ(ierr); 619 ierr = MatGetLocalSize(Ap,&am,&an);CHKERRQ(ierr); 620 ierr = ISGetLocalSize(pP,&pl);CHKERRQ(ierr); 621 if (PAM != PAN) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Pressure matrix must be square, unsupported %D x %D",PAM,PAN); 622 if (pam != pan) SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_USER,"Local sizes of pressure matrix must be equal, unsupported %D x %D",pam,pan); 623 if (pam != am && pam != pl) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local rows %D for pressure matrix! Supported are %D or %D",pam,am,pl); 624 if (pan != an && pan != pl) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid number of local columns %D for pressure matrix! Supported are %D or %D",pan,an,pl); 625 if (PAM == AM) { /* monolithic ordering, restrict to interface pressure */ 626 Mat C; 627 628 ierr = MatGetSubMatrix(PPmat,pP,pP,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 629 ierr = MatDestroy(&PPmat);CHKERRQ(ierr); 630 PPmat = C; 631 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PPmat",(PetscObject)PPmat);CHKERRQ(ierr); 632 } 633 } else { 634 ierr = PetscObjectReference((PetscObject)PAmat);CHKERRQ(ierr); 635 PPmat = PAmat; 636 } 637 638 /* create pressure solver */ 639 ierr = KSPCreate(PetscObjectComm((PetscObject)ksp),&kP);CHKERRQ(ierr); 640 ierr = KSPSetOperators(kP,PAmat,PPmat);CHKERRQ(ierr); 641 ierr = KSPSetOptionsPrefix(kP,((PetscObject)ksp)->prefix);CHKERRQ(ierr); 642 ierr = KSPAppendOptionsPrefix(kP,"fetidp_p_");CHKERRQ(ierr); 643 ierr = KSPSetFromOptions(kP);CHKERRQ(ierr); 644 ierr = PetscObjectCompose((PetscObject)fetidp->innerbddc,"__KSPFETIDP_PKSP",(PetscObject)kP);CHKERRQ(ierr); 645 ierr = MatDestroy(&PAmat);CHKERRQ(ierr); 646 ierr = MatDestroy(&PPmat);CHKERRQ(ierr); 647 ierr = KSPDestroy(&kP);CHKERRQ(ierr); 648 649 ierr = ISDestroy(&lP);CHKERRQ(ierr); 650 ierr = ISDestroy(&pP);CHKERRQ(ierr); 651 } 652 PetscFunctionReturn(0); 653 } 654 655 #undef __FUNCT__ 656 #define __FUNCT__ "KSPSetUp_FETIDP" 657 static PetscErrorCode KSPSetUp_FETIDP(KSP ksp) 658 { 659 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 660 PC_BDDC *pcbddc = (PC_BDDC*)fetidp->innerbddc->data; 661 PetscBool flg; 662 PetscErrorCode ierr; 663 664 PetscFunctionBegin; 665 ierr = KSPFETIDPSetUpOperators(ksp);CHKERRQ(ierr); 666 /* set up BDDC */ 667 ierr = PCSetUp(fetidp->innerbddc);CHKERRQ(ierr); 668 669 /* FETI-DP as it is implemented needs an exact coarse solver */ 670 if (pcbddc->coarse_ksp) { 671 ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_SMALL,PETSC_SMALL,PETSC_DEFAULT,1000);CHKERRQ(ierr); 672 ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_DEFAULT);CHKERRQ(ierr); 673 } 674 /* FETI-DP as it is implemented needs exact local Neumann solvers */ 675 ierr = KSPSetTolerances(pcbddc->ksp_R,PETSC_SMALL,PETSC_SMALL,PETSC_DEFAULT,1000);CHKERRQ(ierr); 676 ierr = KSPSetNormType(pcbddc->ksp_R,KSP_NORM_DEFAULT);CHKERRQ(ierr); 677 678 /* if the primal space is changed, setup F */ 679 if (pcbddc->new_primal_space || !pcbddc->coarse_size) { 680 Mat F; /* the FETI-DP matrix */ 681 PC D; /* the FETI-DP preconditioner */ 682 ierr = KSPReset(fetidp->innerksp);CHKERRQ(ierr); 683 ierr = PCBDDCCreateFETIDPOperators(fetidp->innerbddc,fetidp->fully_redundant,((PetscObject)ksp)->prefix,&F,&D);CHKERRQ(ierr); 684 ierr = KSPSetOperators(fetidp->innerksp,F,F);CHKERRQ(ierr); 685 ierr = KSPSetTolerances(fetidp->innerksp,ksp->rtol,ksp->abstol,ksp->divtol,ksp->max_it);CHKERRQ(ierr); 686 ierr = KSPSetPC(fetidp->innerksp,D);CHKERRQ(ierr); 687 ierr = MatCreateVecs(F,&(fetidp->innerksp)->vec_rhs,&(fetidp->innerksp)->vec_sol);CHKERRQ(ierr); 688 ierr = MatDestroy(&F);CHKERRQ(ierr); 689 ierr = PCDestroy(&D);CHKERRQ(ierr); 690 } 691 692 /* propagate settings to the inner solve */ 693 ierr = KSPGetComputeSingularValues(ksp,&flg);CHKERRQ(ierr); 694 ierr = KSPSetComputeSingularValues(fetidp->innerksp,flg);CHKERRQ(ierr); 695 if (ksp->res_hist) { 696 ierr = KSPSetResidualHistory(fetidp->innerksp,ksp->res_hist,ksp->res_hist_max,ksp->res_hist_reset);CHKERRQ(ierr); 697 } 698 ierr = KSPSetUp(fetidp->innerksp);CHKERRQ(ierr); 699 PetscFunctionReturn(0); 700 } 701 702 #undef __FUNCT__ 703 #define __FUNCT__ "KSPSolve_FETIDP" 704 static PetscErrorCode KSPSolve_FETIDP(KSP ksp) 705 { 706 PetscErrorCode ierr; 707 Mat F; 708 Vec X,B,Xl,Bl; 709 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 710 PC_BDDC *pcbddc = (PC_BDDC*)fetidp->innerbddc->data; 711 712 PetscFunctionBegin; 713 ierr = KSPGetRhs(ksp,&B);CHKERRQ(ierr); 714 ierr = KSPGetSolution(ksp,&X);CHKERRQ(ierr); 715 ierr = KSPGetOperators(fetidp->innerksp,&F,NULL);CHKERRQ(ierr); 716 ierr = KSPGetRhs(fetidp->innerksp,&Bl);CHKERRQ(ierr); 717 ierr = KSPGetSolution(fetidp->innerksp,&Xl);CHKERRQ(ierr); 718 ierr = PCBDDCMatFETIDPGetRHS(F,B,Bl);CHKERRQ(ierr); 719 if (ksp->transpose_solve) { 720 ierr = KSPSolveTranspose(fetidp->innerksp,Bl,Xl);CHKERRQ(ierr); 721 } else { 722 ierr = KSPSolve(fetidp->innerksp,Bl,Xl);CHKERRQ(ierr); 723 } 724 ierr = PCBDDCMatFETIDPGetSolution(F,Xl,X);CHKERRQ(ierr); 725 /* update ksp with stats from inner ksp */ 726 ierr = KSPGetConvergedReason(fetidp->innerksp,&ksp->reason);CHKERRQ(ierr); 727 ierr = KSPGetIterationNumber(fetidp->innerksp,&ksp->its);CHKERRQ(ierr); 728 ksp->totalits += ksp->its; 729 ierr = KSPGetResidualHistory(fetidp->innerksp,NULL,&ksp->res_hist_len);CHKERRQ(ierr); 730 /* restore defaults for inner BDDC (Pre/PostSolve flags) */ 731 pcbddc->temp_solution_used = PETSC_FALSE; 732 pcbddc->rhs_change = PETSC_FALSE; 733 pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 734 PetscFunctionReturn(0); 735 } 736 737 #undef __FUNCT__ 738 #define __FUNCT__ "KSPDestroy_FETIDP" 739 static PetscErrorCode KSPDestroy_FETIDP(KSP ksp) 740 { 741 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 742 PetscErrorCode ierr; 743 744 PetscFunctionBegin; 745 ierr = PCDestroy(&fetidp->innerbddc);CHKERRQ(ierr); 746 ierr = KSPDestroy(&fetidp->innerksp);CHKERRQ(ierr); 747 ierr = PetscFree(fetidp->monctx);CHKERRQ(ierr); 748 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPSetInnerBDDC_C",NULL);CHKERRQ(ierr); 749 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPGetInnerBDDC_C",NULL);CHKERRQ(ierr); 750 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPGetInnerKSP_C",NULL);CHKERRQ(ierr); 751 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPSetPressureOperators_C",NULL);CHKERRQ(ierr); 752 ierr = PetscFree(ksp->data);CHKERRQ(ierr); 753 PetscFunctionReturn(0); 754 } 755 756 #undef __FUNCT__ 757 #define __FUNCT__ "KSPView_FETIDP" 758 static PetscErrorCode KSPView_FETIDP(KSP ksp,PetscViewer viewer) 759 { 760 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 761 PetscErrorCode ierr; 762 PetscBool iascii; 763 764 PetscFunctionBegin; 765 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 766 if (iascii) { 767 ierr = PetscViewerASCIIPrintf(viewer," FETI-DP: fully redundant: %D\n",fetidp->fully_redundant);CHKERRQ(ierr); 768 ierr = PetscViewerASCIIPrintf(viewer," FETI-DP: saddle point: %D\n",fetidp->saddlepoint);CHKERRQ(ierr); 769 ierr = PetscViewerASCIIPrintf(viewer," FETI-DP: inner solver details\n");CHKERRQ(ierr); 770 ierr = PetscViewerASCIIAddTab(viewer,2);CHKERRQ(ierr); 771 } 772 ierr = KSPView(fetidp->innerksp,viewer);CHKERRQ(ierr); 773 if (iascii) { 774 ierr = PetscViewerASCIISubtractTab(viewer,2);CHKERRQ(ierr); 775 ierr = PetscViewerASCIIPrintf(viewer," FETI-DP: BDDC solver details\n");CHKERRQ(ierr); 776 ierr = PetscViewerASCIIAddTab(viewer,2);CHKERRQ(ierr); 777 } 778 ierr = PCView(fetidp->innerbddc,viewer);CHKERRQ(ierr); 779 if (iascii) { 780 ierr = PetscViewerASCIISubtractTab(viewer,2);CHKERRQ(ierr); 781 } 782 PetscFunctionReturn(0); 783 } 784 785 #undef __FUNCT__ 786 #define __FUNCT__ "KSPSetFromOptions_FETIDP" 787 static PetscErrorCode KSPSetFromOptions_FETIDP(PetscOptionItems *PetscOptionsObject,KSP ksp) 788 { 789 KSP_FETIDP *fetidp = (KSP_FETIDP*)ksp->data; 790 PetscErrorCode ierr; 791 792 PetscFunctionBegin; 793 /* set options prefixes for the inner objects, since the parent prefix will be valid at this point */ 794 ierr = PetscObjectSetOptionsPrefix((PetscObject)fetidp->innerksp,((PetscObject)ksp)->prefix);CHKERRQ(ierr); 795 ierr = PetscObjectAppendOptionsPrefix((PetscObject)fetidp->innerksp,"fetidp_");CHKERRQ(ierr); 796 if (!fetidp->userbddc) { 797 ierr = PetscObjectSetOptionsPrefix((PetscObject)fetidp->innerbddc,((PetscObject)ksp)->prefix);CHKERRQ(ierr); 798 ierr = PetscObjectAppendOptionsPrefix((PetscObject)fetidp->innerbddc,"fetidp_bddc_");CHKERRQ(ierr); 799 } 800 ierr = PetscOptionsHead(PetscOptionsObject,"KSP FETIDP options");CHKERRQ(ierr); 801 ierr = PetscOptionsBool("-ksp_fetidp_fullyredundant","Use fully redundant multipliers","none",fetidp->fully_redundant,&fetidp->fully_redundant,NULL);CHKERRQ(ierr); 802 ierr = PetscOptionsBool("-ksp_fetidp_saddlepoint","Activates support for saddle-point problems",NULL,fetidp->saddlepoint,&fetidp->saddlepoint,NULL);CHKERRQ(ierr); 803 ierr = PetscOptionsTail();CHKERRQ(ierr); 804 ierr = PCSetFromOptions(fetidp->innerbddc);CHKERRQ(ierr); 805 ierr = KSPSetFromOptions(fetidp->innerksp);CHKERRQ(ierr); 806 PetscFunctionReturn(0); 807 } 808 809 /*MC 810 KSPFETIDP - The FETI-DP method 811 812 This class implements the FETI-DP method [1]. 813 The preconditioning matrix for the KSP must be of type MATIS. 814 The FETI-DP linear system (automatically generated constructing an internal PCBDDC object) is solved using an inner KSP object. 815 816 Options Database Keys: 817 + -ksp_fetidp_fullyredundant <false> : use a fully redundant set of Lagrange multipliers 818 - -ksp_fetidp_saddlepoint <false> : activates support for saddle point problems, see [2] 819 820 Level: Advanced 821 822 Notes: Options for the inner KSP and for the customization of the PCBDDC object can be specified at command line by using the prefixes -fetidp_ and -fetidp_bddc_. E.g., 823 .vb 824 -fetidp_ksp_type gmres -fetidp_bddc_pc_bddc_symmetric false 825 .ve 826 will use GMRES for the solution of the linear system on the Lagrange multipliers, generated using a non-symmetric PCBDDC. 827 For saddle point problems with continuous pressures, the operators for the interface pressure solver can be specified with KSPFETIDPSetPressureOperators(). 828 829 References: 830 .vb 831 . [1] - C. Farhat, M. Lesoinne, P. LeTallec, K. Pierson, and D. Rixen, FETI-DP: a dual-primal unified FETI method. I. A faster alternative to the two-level FETI method, Internat. J. Numer. Methods Engrg., 50 (2001), pp. 1523--1544 832 . [2] - X. Tu, J. Li, A FETI-DP type domain decomposition algorithm for three-dimensional incompressible Stokes equations, SIAM J. Numer. Anal., 53 (2015), pp. 720-742 833 .ve 834 835 .seealso: MATIS, PCBDDC, KSPFETIDPSetInnerBDDC, KSPFETIDPGetInnerBDDC, KSPFETIDPGetInnerKSP 836 M*/ 837 #undef __FUNCT__ 838 #define __FUNCT__ "KSPCreate_FETIDP" 839 PETSC_EXTERN PetscErrorCode KSPCreate_FETIDP(KSP ksp) 840 { 841 PetscErrorCode ierr; 842 KSP_FETIDP *fetidp; 843 KSP_FETIDPMon *monctx; 844 PC_BDDC *pcbddc; 845 PC pc; 846 847 PetscFunctionBegin; 848 ierr = PetscNewLog(ksp,&fetidp);CHKERRQ(ierr); 849 ksp->data = (void*)fetidp; 850 ksp->ops->setup = KSPSetUp_FETIDP; 851 ksp->ops->solve = KSPSolve_FETIDP; 852 ksp->ops->destroy = KSPDestroy_FETIDP; 853 ksp->ops->computeeigenvalues = KSPComputeEigenvalues_FETIDP; 854 ksp->ops->computeextremesingularvalues = KSPComputeExtremeSingularValues_FETIDP; 855 ksp->ops->view = KSPView_FETIDP; 856 ksp->ops->setfromoptions = KSPSetFromOptions_FETIDP; 857 ksp->ops->buildsolution = KSPBuildSolution_FETIDP; 858 ksp->ops->buildresidual = KSPBuildResidualDefault; 859 /* create the inner KSP for the Lagrange multipliers */ 860 ierr = KSPCreate(PetscObjectComm((PetscObject)ksp),&fetidp->innerksp);CHKERRQ(ierr); 861 ierr = KSPGetPC(fetidp->innerksp,&pc);CHKERRQ(ierr); 862 ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); 863 ierr = PetscLogObjectParent((PetscObject)ksp,(PetscObject)fetidp->innerksp);CHKERRQ(ierr); 864 /* monitor */ 865 ierr = PetscNew(&monctx);CHKERRQ(ierr); 866 monctx->parentksp = ksp; 867 fetidp->monctx = monctx; 868 ierr = KSPMonitorSet(fetidp->innerksp,KSPMonitor_FETIDP,fetidp->monctx,NULL);CHKERRQ(ierr); 869 /* create the inner BDDC */ 870 ierr = PCCreate(PetscObjectComm((PetscObject)ksp),&fetidp->innerbddc);CHKERRQ(ierr); 871 ierr = PCSetType(fetidp->innerbddc,PCBDDC);CHKERRQ(ierr); 872 /* make sure we always obtain a consistent FETI-DP matrix 873 for symmetric problems, the user can always customize it through the command line */ 874 pcbddc = (PC_BDDC*)fetidp->innerbddc->data; 875 pcbddc->symmetric_primal = PETSC_FALSE; 876 ierr = PetscLogObjectParent((PetscObject)ksp,(PetscObject)fetidp->innerbddc);CHKERRQ(ierr); 877 /* composed functions */ 878 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPSetInnerBDDC_C",KSPFETIDPSetInnerBDDC_FETIDP);CHKERRQ(ierr); 879 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPGetInnerBDDC_C",KSPFETIDPGetInnerBDDC_FETIDP);CHKERRQ(ierr); 880 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPGetInnerKSP_C",KSPFETIDPGetInnerKSP_FETIDP);CHKERRQ(ierr); 881 ierr = PetscObjectComposeFunction((PetscObject)ksp,"KSPFETIDPSetPressureOperators_C",KSPFETIDPSetPressureOperators_FETIDP);CHKERRQ(ierr); 882 /* need to call KSPSetUp_FETIDP even with KSP_SETUP_NEWMATRIX */ 883 ksp->setupnewmatrix = PETSC_TRUE; 884 PetscFunctionReturn(0); 885 } 886