1 /* 2 This file implements the FCG (Flexible Conjugate Gradient) method 3 4 */ 5 6 #include <../src/ksp/ksp/impls/fcg/fcgimpl.h> /*I "petscksp.h" I*/ 7 extern PetscErrorCode KSPComputeExtremeSingularValues_CG(KSP,PetscReal*,PetscReal*); 8 extern PetscErrorCode KSPComputeEigenvalues_CG(KSP,PetscInt,PetscReal*,PetscReal*,PetscInt*); 9 10 const char *const KSPFCGTruncationTypes[] = {"STANDARD","NOTAY","KSPFCGTrunctionTypes","KSP_FCG_TRUNC_TYPE_",0}; 11 12 #define KSPFCG_DEFAULT_MMAX 30 /* maximum number of search directions to keep */ 13 #define KSPFCG_DEFAULT_NPREALLOC 10 /* number of search directions to preallocate */ 14 #define KSPFCG_DEFAULT_VECB 5 /* number of search directions to allocate each time new direction vectors are needed */ 15 #define KSPFCG_DEFAULT_TRUNCSTRAT KSP_FCG_TRUNC_TYPE_NOTAY 16 17 #undef __FUNCT__ 18 #define __FUNCT__ "KSPAllocateVectors_FCG" 19 static PetscErrorCode KSPAllocateVectors_FCG(KSP ksp, PetscInt nvecsneeded, PetscInt chunksize) 20 { 21 PetscErrorCode ierr; 22 PetscInt i; 23 KSP_FCG *fcg = (KSP_FCG*)ksp->data; 24 PetscInt nnewvecs, nvecsprev; 25 26 PetscFunctionBegin; 27 /* Allocate enough new vectors to add chunksize new vectors, reach nvecsneedtotal, or to reach mmax+1, whichever is smallest */ 28 if (fcg->nvecs < PetscMin(fcg->mmax+1,nvecsneeded)){ 29 nvecsprev = fcg->nvecs; 30 nnewvecs = PetscMin(PetscMax(nvecsneeded-fcg->nvecs,chunksize),fcg->mmax+1-fcg->nvecs); 31 ierr = KSPCreateVecs(ksp,nnewvecs,&fcg->pCvecs[fcg->nchunks],0,NULL);CHKERRQ(ierr); 32 ierr = PetscLogObjectParents((PetscObject)ksp,nnewvecs,fcg->pCvecs[fcg->nchunks]);CHKERRQ(ierr); 33 ierr = KSPCreateVecs(ksp,nnewvecs,&fcg->pPvecs[fcg->nchunks],0,NULL);CHKERRQ(ierr); 34 ierr = PetscLogObjectParents((PetscObject)ksp,nnewvecs,fcg->pPvecs[fcg->nchunks]);CHKERRQ(ierr); 35 fcg->nvecs += nnewvecs; 36 for (i=0;i<nnewvecs;++i){ 37 fcg->Cvecs[nvecsprev + i] = fcg->pCvecs[fcg->nchunks][i]; 38 fcg->Pvecs[nvecsprev + i] = fcg->pPvecs[fcg->nchunks][i]; 39 } 40 fcg->chunksizes[fcg->nchunks] = nnewvecs; 41 ++fcg->nchunks; 42 } 43 PetscFunctionReturn(0); 44 } 45 46 #undef __FUNCT__ 47 #define __FUNCT__ "KSPSetUp_FCG" 48 PetscErrorCode KSPSetUp_FCG(KSP ksp) 49 { 50 PetscErrorCode ierr; 51 KSP_FCG *fcg = (KSP_FCG*)ksp->data; 52 PetscInt maxit = ksp->max_it; 53 const PetscInt nworkstd = 2; 54 55 PetscFunctionBegin; 56 57 /* Allocate "standard" work vectors (not including the basis and transformed basis vectors) */ 58 ierr = KSPSetWorkVecs(ksp,nworkstd);CHKERRQ(ierr); 59 60 /* Allocated space for pointers to additional work vectors 61 note that mmax is the number of previous directions, so we add 1 for the current direction, 62 and an extra 1 for the prealloc (which might be empty) */ 63 ierr = PetscMalloc5(fcg->mmax+1,&fcg->Pvecs,fcg->mmax+1,&fcg->Cvecs,fcg->mmax+1,&fcg->pPvecs,fcg->mmax+1,&fcg->pCvecs,fcg->mmax+2,&fcg->chunksizes);CHKERRQ(ierr); 64 ierr = PetscLogObjectMemory((PetscObject)ksp,2*(fcg->mmax+1)*sizeof(Vec*) + 2*(fcg->mmax + 1)*sizeof(Vec**) + (fcg->mmax + 2)*sizeof(PetscInt));CHKERRQ(ierr); 65 66 /* Preallocate additional work vectors */ 67 ierr = KSPAllocateVectors_FCG(ksp,fcg->nprealloc,fcg->nprealloc);CHKERRQ(ierr); 68 /* 69 If user requested computations of eigenvalues then allocate work 70 work space needed 71 */ 72 if (ksp->calc_sings) { 73 /* get space to store tridiagonal matrix for Lanczos */ 74 ierr = PetscMalloc4(maxit,&fcg->e,maxit,&fcg->d,maxit,&fcg->ee,maxit,&fcg->dd);CHKERRQ(ierr); 75 ierr = PetscLogObjectMemory((PetscObject)ksp,2*(maxit+1)*(sizeof(PetscScalar)+sizeof(PetscReal)));CHKERRQ(ierr); 76 77 ksp->ops->computeextremesingularvalues = KSPComputeExtremeSingularValues_CG; 78 ksp->ops->computeeigenvalues = KSPComputeEigenvalues_CG; 79 } 80 PetscFunctionReturn(0); 81 } 82 83 #undef __FUNCT__ 84 #define __FUNCT__ "KSPSolve_FCG" 85 PetscErrorCode KSPSolve_FCG(KSP ksp) 86 { 87 PetscErrorCode ierr; 88 PetscInt i,k,idx,mi; 89 KSP_FCG *fcg = (KSP_FCG*)ksp->data; 90 PetscScalar alpha=0.0,beta = 0.0,dpi,s; 91 PetscReal dp=0.0; 92 Vec B,R,Z,X,Pcurr,Ccurr; 93 Mat Amat,Pmat; 94 PetscInt eigs = ksp->calc_sings; /* Variables for eigen estimation - START*/ 95 PetscInt stored_max_it = ksp->max_it; 96 PetscScalar alphaold = 0,betaold = 1.0,*e = 0,*d = 0;/* Variables for eigen estimation - FINISH */ 97 98 PetscFunctionBegin; 99 100 #define VecXDot(x,y,a) (((fcg->type) == (KSP_CG_HERMITIAN)) ? VecDot(x,y,a) : VecTDot(x,y,a)) 101 #define VecXMDot(a,b,c,d) (((fcg->type) == (KSP_CG_HERMITIAN)) ? VecMDot(a,b,c,d) : VecMTDot(a,b,c,d)) 102 103 X = ksp->vec_sol; 104 B = ksp->vec_rhs; 105 R = ksp->work[0]; 106 Z = ksp->work[1]; 107 108 ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);CHKERRQ(ierr); 109 if (eigs) {e = fcg->e; d = fcg->d; e[0] = 0.0; } 110 /* Compute initial residual needed for convergence check*/ 111 ksp->its = 0; 112 if (!ksp->guess_zero) { 113 ierr = KSP_MatMult(ksp,Amat,X,R);CHKERRQ(ierr); 114 ierr = VecAYPX(R,-1.0,B);CHKERRQ(ierr); /* r <- b - Ax */ 115 } else { 116 ierr = VecCopy(B,R);CHKERRQ(ierr); /* r <- b (x is 0) */ 117 } 118 switch (ksp->normtype) { 119 case KSP_NORM_PRECONDITIONED: 120 ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ 121 ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- dqrt(z'*z) = sqrt(e'*A'*B'*B*A*e) */ 122 break; 123 case KSP_NORM_UNPRECONDITIONED: 124 ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- sqrt(r'*r) = sqrt(e'*A'*A*e) */ 125 break; 126 case KSP_NORM_NATURAL: 127 ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ 128 ierr = VecXDot(R,Z,&s);CHKERRQ(ierr); 129 dp = PetscSqrtReal(PetscAbsScalar(s)); /* dp <- sqrt(r'*z) = sqrt(e'*A'*B*A*e) */ 130 break; 131 case KSP_NORM_NONE: 132 dp = 0.0; 133 break; 134 default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]); 135 } 136 137 /* Initial Convergence Check */ 138 ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); 139 ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); 140 ksp->rnorm = dp; 141 if (ksp->normtype == KSP_NORM_NONE) { 142 ierr = KSPConvergedSkip(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); 143 } else { 144 ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); 145 } 146 if (ksp->reason) PetscFunctionReturn(0); 147 148 /* Apply PC if not already done for convergence check */ 149 if(ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->normtype == KSP_NORM_NONE){ 150 ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ 151 } 152 153 i = 0; 154 do { 155 ksp->its = i+1; 156 157 /* If needbe, allocate a new chunk of vectors in P and C */ 158 ierr = KSPAllocateVectors_FCG(ksp,i+1,fcg->vecb);CHKERRQ(ierr); 159 160 /* Note that we wrap around and start clobbering old vectors */ 161 idx = i % (fcg->mmax+1); 162 Pcurr = fcg->Pvecs[idx]; 163 Ccurr = fcg->Cvecs[idx]; 164 165 /* Compute a new column of P (Currently does not support modified G-S or iterative refinement)*/ 166 switch(fcg->truncstrat){ 167 case KSP_FCG_TRUNC_TYPE_NOTAY : 168 mi = PetscMax(1,i%(fcg->mmax+1)); 169 break; 170 case KSP_FCG_TRUNC_TYPE_STANDARD : 171 mi = fcg->mmax; 172 break; 173 default: 174 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unrecognized FCG Truncation Strategy");CHKERRQ(ierr); 175 } 176 ierr = VecCopy(Z,Pcurr);CHKERRQ(ierr); 177 178 { 179 PetscInt l,ndots; 180 181 l = PetscMax(0,i-mi); 182 ndots = i-l; 183 if (ndots){ 184 PetscInt j; 185 Vec *Pold, *Cold; 186 PetscScalar *dots; 187 188 ierr = PetscMalloc3(ndots,&dots,ndots,&Cold,ndots,&Pold);CHKERRQ(ierr); 189 for(k=l,j=0;j<ndots;++k,++j){ 190 idx = k % (fcg->mmax+1); 191 Cold[j] = fcg->Cvecs[idx]; 192 Pold[j] = fcg->Pvecs[idx]; 193 } 194 ierr = VecXMDot(Z,ndots,Cold,dots);CHKERRQ(ierr); 195 for(k=0;k<ndots;++k){ 196 dots[k] = -dots[k]; 197 } 198 ierr = VecMAXPY(Pcurr,ndots,dots,Pold);CHKERRQ(ierr); 199 ierr = PetscFree3(dots,Cold,Pold);CHKERRQ(ierr); 200 } 201 } 202 203 /* Update X and R */ 204 betaold = beta; 205 ierr = VecXDot(Pcurr,R,&beta);CHKERRQ(ierr); /* beta <- pi'*r */ 206 ierr = KSP_MatMult(ksp,Amat,Pcurr,Ccurr);CHKERRQ(ierr); /* w <- A*pi (stored in ci) */ 207 ierr = VecXDot(Pcurr,Ccurr,&dpi);CHKERRQ(ierr); /* dpi <- pi'*w */ 208 alphaold = alpha; 209 alpha = beta / dpi; /* alpha <- beta/dpi */ 210 ierr = VecAXPY(X,alpha,Pcurr);CHKERRQ(ierr); /* x <- x + alpha * pi */ 211 ierr = VecAXPY(R,-alpha,Ccurr);CHKERRQ(ierr); /* r <- r - alpha * wi */ 212 213 /* Compute norm for convergence check */ 214 switch (ksp->normtype) { 215 case KSP_NORM_PRECONDITIONED: 216 ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ 217 ierr = VecNorm(Z,NORM_2,&dp);CHKERRQ(ierr); /* dp <- sqrt(z'*z) = sqrt(e'*A'*B'*B*A*e) */ 218 break; 219 case KSP_NORM_UNPRECONDITIONED: 220 ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); /* dp <- sqrt(r'*r) = sqrt(e'*A'*A*e) */ 221 break; 222 case KSP_NORM_NATURAL: 223 ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ 224 ierr = VecXDot(R,Z,&s);CHKERRQ(ierr); 225 dp = PetscSqrtReal(PetscAbsScalar(s)); /* dp <- sqrt(r'*z) = sqrt(e'*A'*B*A*e) */ 226 break; 227 case KSP_NORM_NONE: 228 dp = 0.0; 229 break; 230 default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]); 231 } 232 233 /* Check for convergence */ 234 ksp->rnorm = dp; 235 KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); 236 ierr = KSPMonitor(ksp,i+1,dp);CHKERRQ(ierr); 237 ierr = (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); 238 if (ksp->reason) break; 239 240 /* Apply PC if not already done for convergence check */ 241 if(ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->normtype == KSP_NORM_NONE){ 242 ierr = KSP_PCApply(ksp,R,Z);CHKERRQ(ierr); /* z <- Br */ 243 } 244 245 /* Compute current C (which is W/dpi) */ 246 ierr = VecScale(Ccurr,1.0/dpi);CHKERRQ(ierr); /* w <- ci/dpi */ 247 248 if (eigs) { 249 if (i > 0) { 250 if (ksp->max_it != stored_max_it) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Can not change maxit AND calculate eigenvalues"); 251 e[i] = PetscSqrtReal(PetscAbsScalar(beta/betaold))/alphaold; 252 d[i] = PetscSqrtReal(PetscAbsScalar(beta/betaold))*e[i] + 1.0/alpha; 253 } else { 254 d[i] = PetscSqrtReal(PetscAbsScalar(beta))*e[i] + 1.0/alpha; 255 } 256 fcg->ned = ksp->its-1; 257 } 258 ++i; 259 } while (i<ksp->max_it); 260 if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; 261 PetscFunctionReturn(0); 262 } 263 264 #undef __FUNCT__ 265 #define __FUNCT__ "KSPDestroy_FCG" 266 PetscErrorCode KSPDestroy_FCG(KSP ksp) 267 { 268 PetscErrorCode ierr; 269 PetscInt i; 270 KSP_FCG *fcg = (KSP_FCG*)ksp->data; 271 272 PetscFunctionBegin; 273 274 /* Destroy "standard" work vecs */ 275 VecDestroyVecs(ksp->nwork,&ksp->work); 276 277 /* Destroy P and C vectors and the arrays that manage pointers to them */ 278 if (fcg->nvecs){ 279 for (i=0;i<fcg->nchunks;++i){ 280 ierr = VecDestroyVecs(fcg->chunksizes[i],&fcg->pPvecs[i]);CHKERRQ(ierr); 281 ierr = VecDestroyVecs(fcg->chunksizes[i],&fcg->pCvecs[i]);CHKERRQ(ierr); 282 } 283 } 284 ierr = PetscFree5(fcg->Pvecs,fcg->Cvecs,fcg->pPvecs,fcg->pCvecs,fcg->chunksizes);CHKERRQ(ierr); 285 /* free space used for singular value calculations */ 286 if (ksp->calc_sings) { 287 ierr = PetscFree4(fcg->e,fcg->d,fcg->ee,fcg->dd);CHKERRQ(ierr); 288 } 289 ierr = KSPDestroyDefault(ksp);CHKERRQ(ierr); 290 PetscFunctionReturn(0); 291 } 292 293 #undef __FUNCT__ 294 #define __FUNCT__ "KSPView_FCG" 295 PetscErrorCode KSPView_FCG(KSP ksp,PetscViewer viewer) 296 { 297 KSP_FCG *fcg = (KSP_FCG*)ksp->data; 298 PetscErrorCode ierr; 299 PetscBool iascii,isstring; 300 const char *truncstr; 301 302 PetscFunctionBegin; 303 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 304 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 305 306 if (fcg->truncstrat == KSP_FCG_TRUNC_TYPE_STANDARD) truncstr = "Using standard truncation strategy"; 307 else if (fcg->truncstrat == KSP_FCG_TRUNC_TYPE_NOTAY) truncstr = "Using Notay's truncation strategy"; 308 else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Undefined FCG truncation strategy"); 309 310 if (iascii) { 311 ierr = PetscViewerASCIIPrintf(viewer," FCG: m_max=%D\n",fcg->mmax);CHKERRQ(ierr); 312 ierr = PetscViewerASCIIPrintf(viewer," FCG: preallocated %D directions\n",PetscMin(fcg->nprealloc,fcg->mmax+1));CHKERRQ(ierr); 313 ierr = PetscViewerASCIIPrintf(viewer," FCG: %s\n",truncstr);CHKERRQ(ierr); 314 } else if (isstring) { 315 ierr = PetscViewerStringSPrintf(viewer,"m_max %D nprealloc %D %s",fcg->mmax,fcg->nprealloc,truncstr);CHKERRQ(ierr); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 #undef __FUNCT__ 321 #define __FUNCT__ "KSPFCGSetMmax" 322 /*@ 323 KSPFCGSetMmax - set the maximum number of previous directions FCG will store for orthogonalization 324 325 Note: mmax + 1 directions are stored (mmax previous ones along with a current one) 326 and whether all are used in each iteration also depends on the truncation strategy 327 (see KSPFCGSetTruncationType()) 328 329 Logically Collective on KSP 330 331 Input Parameters: 332 + ksp - the Krylov space context 333 - mmax - the maximum number of previous directions to orthogonalize againt 334 335 Level: intermediate 336 337 Options Database: 338 . -ksp_fcg_mmax <N> 339 340 .seealso: KSPFCG, KSPFCGGetTruncationType(), KSPFCGGetNprealloc() 341 @*/ 342 PetscErrorCode KSPFCGSetMmax(KSP ksp,PetscInt mmax) 343 { 344 KSP_FCG *fcg = (KSP_FCG*)ksp->data; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 348 PetscValidLogicalCollectiveEnum(ksp,mmax,2); 349 fcg->mmax = mmax; 350 PetscFunctionReturn(0); 351 } 352 353 #undef __FUNCT__ 354 #define __FUNCT__ "KSPFCGGetMmax" 355 /*@ 356 KSPFCGGetMmax - get the maximum number of previous directions FCG will store 357 358 Note: FCG stores mmax+1 directions at most (mmax previous ones, and one current one) 359 360 Not Collective 361 362 Input Parameter: 363 . ksp - the Krylov space context 364 365 Output Parameter: 366 . mmax - the maximum number of previous directons allowed for orthogonalization 367 368 Options Database: 369 . -ksp_fcg_mmax <N> 370 371 Level: intermediate 372 373 .keywords: KSP, FCG, truncation 374 375 .seealso: KSPFCG, KSPFCGGetTruncationType(), KSPFCGGetNprealloc(), KSPFCGSetMmax() 376 @*/ 377 378 PetscErrorCode KSPFCGGetMmax(KSP ksp,PetscInt *mmax) 379 { 380 KSP_FCG *fcg=(KSP_FCG*)ksp->data; 381 382 PetscFunctionBegin; 383 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 384 *mmax = fcg->mmax; 385 PetscFunctionReturn(0); 386 } 387 388 #undef __FUNCT__ 389 #define __FUNCT__ "KSPFCGSetNprealloc" 390 /*@ 391 KSPFCGSetNprealloc - set the number of directions to preallocate with FCG 392 393 Logically Collective on KSP 394 395 Input Parameters: 396 + ksp - the Krylov space context 397 - nprealloc - the number of vectors to preallocate 398 399 Level: advanced 400 401 Options Database: 402 . -ksp_fcg_nprealloc <N> 403 404 .seealso: KSPFCG, KSPFCGGetTruncationType(), KSPFCGGetNprealloc() 405 @*/ 406 PetscErrorCode KSPFCGSetNprealloc(KSP ksp,PetscInt nprealloc) 407 { 408 KSP_FCG *fcg=(KSP_FCG*)ksp->data; 409 410 PetscFunctionBegin; 411 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 412 PetscValidLogicalCollectiveEnum(ksp,nprealloc,2); 413 if(nprealloc > fcg->mmax+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Cannot preallocate more than m_max+1 vectors"); 414 fcg->nprealloc = nprealloc; 415 PetscFunctionReturn(0); 416 } 417 418 #undef __FUNCT__ 419 #define __FUNCT__ "KSPFCGGetNprealloc" 420 /*@ 421 KSPFCGGetNprealloc - get the number of directions preallocate by FCG 422 423 Not Collective 424 425 Input Parameter: 426 . ksp - the Krylov space context 427 428 Output Parameter: 429 . nprealloc - the number of directions preallocated 430 431 Options Database: 432 . -ksp_fcg_nprealloc <N> 433 434 Level: advanced 435 436 .keywords: KSP, FCG, truncation 437 438 .seealso: KSPFCG, KSPFCGGetTruncationType(), KSPFCGSetNprealloc() 439 @*/ 440 PetscErrorCode KSPFCGGetNprealloc(KSP ksp,PetscInt *nprealloc) 441 { 442 KSP_FCG *fcg=(KSP_FCG*)ksp->data; 443 444 PetscFunctionBegin; 445 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 446 *nprealloc = fcg->nprealloc; 447 PetscFunctionReturn(0); 448 } 449 450 #undef __FUNCT__ 451 #define __FUNCT__ "KSPFCGSetTruncationType" 452 /*@ 453 KSPFCGSetTruncationType - specify how many of its stored previous directions FCG uses during orthoganalization 454 455 Logically Collective on KSP 456 457 KSP_FCG_TRUNC_TYPE_STANDARD uses all (up to mmax) stored directions 458 KSP_FCG_TRUNC_TYPE_NOTAY uses the last max(1,mod(i,mmax)) stored directions at iteration i=0,1.. 459 460 Input Parameters: 461 + ksp - the Krylov space context 462 - truncstrat - the choice of strategy 463 464 Level: intermediate 465 466 Options Database: 467 . -ksp_fcg_truncation_type <standard, notay> 468 469 .seealso: KSPFCGTruncationType, KSPFCGGetTruncationType 470 @*/ 471 PetscErrorCode KSPFCGSetTruncationType(KSP ksp,KSPFCGTruncationType truncstrat) 472 { 473 KSP_FCG *fcg=(KSP_FCG*)ksp->data; 474 475 PetscFunctionBegin; 476 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 477 PetscValidLogicalCollectiveEnum(ksp,truncstrat,2); 478 fcg->truncstrat=truncstrat; 479 PetscFunctionReturn(0); 480 } 481 482 #undef __FUNCT__ 483 #define __FUNCT__ "KSPFCGGetTruncationType" 484 /*@ 485 KSPFCGGetTruncationType - get the truncation strategy employed by FCG 486 487 Not Collective 488 489 Input Parameter: 490 . ksp - the Krylov space context 491 492 Output Parameter: 493 . truncstrat - the strategy type 494 495 Options Database: 496 . -ksp_fcg_truncation_type <standard, notay> 497 498 Level: intermediate 499 500 .keywords: KSP, FCG, truncation 501 502 .seealso: KSPFCG, KSPFCGSetTruncationType, KSPFCGTruncationType 503 @*/ 504 PetscErrorCode KSPFCGGetTruncationType(KSP ksp,KSPFCGTruncationType *truncstrat) 505 { 506 KSP_FCG *fcg=(KSP_FCG*)ksp->data; 507 508 PetscFunctionBegin; 509 PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); 510 *truncstrat=fcg->truncstrat; 511 PetscFunctionReturn(0); 512 } 513 514 #undef __FUNCT__ 515 #define __FUNCT__ "KSPSetFromOptions_FCG" 516 PetscErrorCode KSPSetFromOptions_FCG(PetscOptionItems *PetscOptionsObject,KSP ksp) 517 { 518 PetscErrorCode ierr; 519 KSP_FCG *fcg=(KSP_FCG*)ksp->data; 520 PetscInt mmax,nprealloc; 521 PetscBool flg; 522 523 PetscFunctionBegin; 524 ierr = PetscOptionsHead(PetscOptionsObject,"KSP FCG Options");CHKERRQ(ierr); 525 ierr = PetscOptionsInt("-ksp_fcg_mmax","Maximum number of search directions to store","KSPFCGSetMmax",fcg->mmax,&mmax,&flg);CHKERRQ(ierr); 526 if (flg) { 527 ierr = KSPFCGSetMmax(ksp,mmax);CHKERRQ(ierr); 528 } 529 ierr = PetscOptionsInt("-ksp_fcg_nprealloc","Number of directions to preallocate","KSPFCGSetNprealloc",fcg->nprealloc,&nprealloc,&flg);CHKERRQ(ierr); 530 if (flg) { 531 ierr = KSPFCGSetNprealloc(ksp,nprealloc);CHKERRQ(ierr); 532 } 533 ierr = PetscOptionsEnum("-ksp_fcg_truncation_type","Truncation approach for directions","KSPFCGSetTruncationType",KSPFCGTruncationTypes,(PetscEnum)fcg->truncstrat,(PetscEnum*)&fcg->truncstrat,NULL);CHKERRQ(ierr); 534 ierr = PetscOptionsTail();CHKERRQ(ierr); 535 PetscFunctionReturn(0); 536 } 537 538 /*MC 539 KSPFCG - Implements the Flexible Conjugate Gradient method (FCG) 540 541 Options Database Keys: 542 + -ksp_fcg_mmax <N> 543 . -ksp_fcg_nprealloc <N> 544 - -ksp_fcg_truncation_type <standard,notay> 545 546 Contributed by Patrick Sanan 547 548 Notes: 549 Supports left preconditioning only. 550 551 Level: beginner 552 553 References: 554 1) Notay, Y."Flexible Conjugate Gradients", SIAM J. Sci. Comput. 22:4, pp 1444-1460, 2000 555 556 2) Axelsson, O. and Vassilevski, P. S. "A Black Box Generalized Conjugate Gradient Solver with Inner Iterations and Variable-Step Preconditioning", 557 SIAM J. Matrix Anal. Appl. 12:4, pp 625-44, 1991 558 559 .seealso : KSPGCR, KSPFGMRES, KSPCG, KSPFCGSetMmax(), KSPFCGGetMmax(), KSPFCGSetNprealloc(), KSPFCGGetNprealloc(), KSPFCGSetTruncationType(), KSPFCGGetTruncationType() 560 561 M*/ 562 #undef __FUNCT__ 563 #define __FUNCT__ "KSPCreate_FCG" 564 PETSC_EXTERN PetscErrorCode KSPCreate_FCG(KSP ksp) 565 { 566 PetscErrorCode ierr; 567 KSP_FCG *fcg; 568 569 PetscFunctionBegin; 570 ierr = PetscNewLog(ksp,&fcg);CHKERRQ(ierr); 571 #if !defined(PETSC_USE_COMPLEX) 572 fcg->type = KSP_CG_SYMMETRIC; 573 #else 574 fcg->type = KSP_CG_HERMITIAN; 575 #endif 576 fcg->mmax = KSPFCG_DEFAULT_MMAX; 577 fcg->nprealloc = KSPFCG_DEFAULT_NPREALLOC; 578 fcg->nvecs = 0; 579 fcg->vecb = KSPFCG_DEFAULT_VECB; 580 fcg->nchunks = 0; 581 fcg->truncstrat = KSPFCG_DEFAULT_TRUNCSTRAT; 582 583 ksp->data = (void*)fcg; 584 585 ierr = KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,2);CHKERRQ(ierr); 586 ierr = KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,1);CHKERRQ(ierr); 587 ierr = KSPSetSupportedNorm(ksp,KSP_NORM_NATURAL,PC_LEFT,1);CHKERRQ(ierr); 588 ierr = KSPSetSupportedNorm(ksp,KSP_NORM_NONE,PC_LEFT,1);CHKERRQ(ierr); 589 590 ksp->ops->setup = KSPSetUp_FCG; 591 ksp->ops->solve = KSPSolve_FCG; 592 ksp->ops->destroy = KSPDestroy_FCG; 593 ksp->ops->view = KSPView_FCG; 594 ksp->ops->setfromoptions = KSPSetFromOptions_FCG; 595 ksp->ops->buildsolution = KSPBuildSolutionDefault; 596 ksp->ops->buildresidual = KSPBuildResidualDefault; 597 PetscFunctionReturn(0); 598 } 599 600