1a312c225SMatthew G Knepley /* Defines the basic SNES object */ 2a312c225SMatthew G Knepley #include <private/snesimpl.h> 3a312c225SMatthew G Knepley 4087dfb9eSxuemin static PetscErrorCode BuildNGmresSoln(PetscScalar*,Vec,SNES,PetscInt,PetscInt); 5087dfb9eSxuemin 6a312c225SMatthew G Knepley /* Private structure for the Anderson mixing method aka nonlinear Krylov */ 7a312c225SMatthew G Knepley typedef struct { 8087dfb9eSxuemin PetscScalar *hh_origin; 9087dfb9eSxuemin Vec *v, *w, *q; 10a312c225SMatthew G Knepley PetscReal *f2; /* 2-norms of function (residual) at each stage */ 11a312c225SMatthew G Knepley PetscInt msize; /* maximum size of space */ 12a312c225SMatthew G Knepley PetscInt csize; /* current size of space */ 13087dfb9eSxuemin PetscScalar beta; /* relaxation parameter */ 14087dfb9eSxuemin PetscScalar *nrs; /* temp that holds the coefficients of the Krylov vectors that form the minimum residual solution */ 15087dfb9eSxuemin 16a312c225SMatthew G Knepley } SNES_NGMRES; 17a312c225SMatthew G Knepley 18087dfb9eSxuemin #define HH(a,b) (ngmres->hh_origin + (a)*(ngmres->msize)+(b)) 19087dfb9eSxuemin 20a312c225SMatthew G Knepley #undef __FUNCT__ 21a312c225SMatthew G Knepley #define __FUNCT__ "SNESReset_NGMRES" 22a312c225SMatthew G Knepley PetscErrorCode SNESReset_NGMRES(SNES snes) 23a312c225SMatthew G Knepley { 24a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 25a312c225SMatthew G Knepley PetscErrorCode ierr; 26a312c225SMatthew G Knepley 27a312c225SMatthew G Knepley PetscFunctionBegin; 28a312c225SMatthew G Knepley ierr = VecDestroyVecs(ngmres->msize, &ngmres->v);CHKERRQ(ierr); 29a312c225SMatthew G Knepley ierr = VecDestroyVecs(ngmres->msize, &ngmres->w);CHKERRQ(ierr); 30c0bbabecSxuemin ierr = VecDestroyVecs(ngmres->msize, &ngmres->q);CHKERRQ(ierr); 31a312c225SMatthew G Knepley PetscFunctionReturn(0); 32a312c225SMatthew G Knepley } 33a312c225SMatthew G Knepley 34a312c225SMatthew G Knepley #undef __FUNCT__ 35a312c225SMatthew G Knepley #define __FUNCT__ "SNESDestroy_NGMRES" 36a312c225SMatthew G Knepley PetscErrorCode SNESDestroy_NGMRES(SNES snes) 37a312c225SMatthew G Knepley { 38a312c225SMatthew G Knepley PetscErrorCode ierr; 39a312c225SMatthew G Knepley 40a312c225SMatthew G Knepley PetscFunctionBegin; 41a312c225SMatthew G Knepley ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 42a312c225SMatthew G Knepley if (snes->work) {ierr = VecDestroyVecs(snes->nwork, &snes->work);CHKERRQ(ierr);} 43a312c225SMatthew G Knepley PetscFunctionReturn(0); 44a312c225SMatthew G Knepley } 45a312c225SMatthew G Knepley 46a312c225SMatthew G Knepley #undef __FUNCT__ 47a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetUp_NGMRES" 48a312c225SMatthew G Knepley PetscErrorCode SNESSetUp_NGMRES(SNES snes) 49a312c225SMatthew G Knepley { 50a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 51087dfb9eSxuemin PetscInt msize,hh; 52a312c225SMatthew G Knepley PetscErrorCode ierr; 53a312c225SMatthew G Knepley 54a312c225SMatthew G Knepley PetscFunctionBegin; 55a312c225SMatthew G Knepley #if 0 56a312c225SMatthew G Knepley if (snes->pc_side != PC_LEFT) {SETERRQ(((PetscObject) snes)->comm, PETSC_ERR_SUP, "Only left preconditioning allowed for SNESNGMRES");} 57a312c225SMatthew G Knepley #endif 58087dfb9eSxuemin ngmres->beta = 1.0; 59087dfb9eSxuemin msize = ngmres->msize; /* restart size */ 60087dfb9eSxuemin hh = msize * msize; 61087dfb9eSxuemin ierr = PetscMalloc2(hh,PetscScalar,&ngmres->hh_origin,msize,PetscScalar,&ngmres->nrs);CHKERRQ(ierr); 62087dfb9eSxuemin 63087dfb9eSxuemin ierr = PetscMemzero(ngmres->hh_origin,hh*sizeof(PetscScalar));CHKERRQ(ierr); 64087dfb9eSxuemin ierr = PetscMemzero(ngmres->nrs,msize*sizeof(PetscScalar));CHKERRQ(ierr); 65087dfb9eSxuemin 66087dfb9eSxuemin // ierr = PetscLogObjectMemory(ksp,(hh+msize)*sizeof(PetscScalar));CHKERRQ(ierr); 67087dfb9eSxuemin 68*211b2d39SPeter Brune ierr = PetscLogObjectMemory(snes,(hh+msize)*sizeof(PetscScalar));CHKERRQ(ierr); 69*211b2d39SPeter Brune 70*211b2d39SPeter Brune //ierr = SNESGetVecs(snes,ngmres->msize,&ngmres->v,ngmres->msize*2,&ngmres->w);CHKERRQ(ierr); 71*211b2d39SPeter Brune //ierr = VecDuplicate(snes->vec_sol, ngmres->w);CHKERRQ(ierr); 72*211b2d39SPeter Brune //ierr = VecDuplicateVecs(ngmres->w[0], ngmres->msize, &ngmres->q);CHKERRQ(ierr); 73*211b2d39SPeter Brune 74a312c225SMatthew G Knepley ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->v);CHKERRQ(ierr); 75*211b2d39SPeter Brune ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize*2, &ngmres->w);CHKERRQ(ierr); 76087dfb9eSxuemin ierr = VecDuplicateVecs(snes->vec_sol, ngmres->msize, &ngmres->q);CHKERRQ(ierr); 77*211b2d39SPeter Brune ierr = SNESDefaultGetWork(snes, 3);CHKERRQ(ierr); 78a312c225SMatthew G Knepley PetscFunctionReturn(0); 79a312c225SMatthew G Knepley } 80a312c225SMatthew G Knepley 81a312c225SMatthew G Knepley #undef __FUNCT__ 82a312c225SMatthew G Knepley #define __FUNCT__ "SNESSetFromOptions_NGMRES" 83a312c225SMatthew G Knepley PetscErrorCode SNESSetFromOptions_NGMRES(SNES snes) 84a312c225SMatthew G Knepley { 85a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 86a312c225SMatthew G Knepley PetscErrorCode ierr; 87a312c225SMatthew G Knepley 88a312c225SMatthew G Knepley PetscFunctionBegin; 89a312c225SMatthew G Knepley ierr = PetscOptionsHead("SNES NGMRES options");CHKERRQ(ierr); 90c0bbabecSxuemin ierr = PetscOptionsInt("-snes_ngmres_restart", "Number of directions", "SNES", ngmres->msize, &ngmres->msize, PETSC_NULL);CHKERRQ(ierr); 91a312c225SMatthew G Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 92a312c225SMatthew G Knepley PetscFunctionReturn(0); 93a312c225SMatthew G Knepley } 94a312c225SMatthew G Knepley 95a312c225SMatthew G Knepley #undef __FUNCT__ 96a312c225SMatthew G Knepley #define __FUNCT__ "SNESView_NGMRES" 97a312c225SMatthew G Knepley PetscErrorCode SNESView_NGMRES(SNES snes, PetscViewer viewer) 98a312c225SMatthew G Knepley { 99a312c225SMatthew G Knepley SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 100a312c225SMatthew G Knepley PetscBool iascii; 101a312c225SMatthew G Knepley PetscErrorCode ierr; 102a312c225SMatthew G Knepley 103a312c225SMatthew G Knepley PetscFunctionBegin; 104a312c225SMatthew G Knepley ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 105a312c225SMatthew G Knepley if (iascii) { 106a312c225SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, " Size of space %d\n", ngmres->msize);CHKERRQ(ierr); 107a312c225SMatthew G Knepley } 108a312c225SMatthew G Knepley PetscFunctionReturn(0); 109a312c225SMatthew G Knepley } 110a312c225SMatthew G Knepley 111a312c225SMatthew G Knepley #undef __FUNCT__ 112a312c225SMatthew G Knepley #define __FUNCT__ "SNESSolve_NGMRES" 113*211b2d39SPeter Brune 114a312c225SMatthew G Knepley PetscErrorCode SNESSolve_NGMRES(SNES snes) 115a312c225SMatthew G Knepley { 1164a0c5b0cSMatthew G Knepley SNES pc; 117087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *) snes->data; 118*211b2d39SPeter Brune //Vec X,F,R, Fold, Xold,temp,*dX = ngmres->v,*dF = ngmres->w; 119*211b2d39SPeter Brune Vec X,F,R,Fold, Xold,temp,*dX = ngmres->w,*dF = ngmres->w+ngmres->msize; 120087dfb9eSxuemin PetscScalar *nrs=ngmres->nrs; 121*211b2d39SPeter Brune PetscReal gnorm, xnorm, pnorm; 122c0bbabecSxuemin PetscInt i, j, k,ivec, l, flag, it; 123a312c225SMatthew G Knepley PetscErrorCode ierr; 124a312c225SMatthew G Knepley 125a312c225SMatthew G Knepley PetscFunctionBegin; 126a312c225SMatthew G Knepley snes->reason = SNES_CONVERGED_ITERATING; 127a312c225SMatthew G Knepley X = snes->vec_sol; 128a312c225SMatthew G Knepley F = snes->vec_func; 129087dfb9eSxuemin Fold = snes->work[0]; 130087dfb9eSxuemin Xold = snes->work[1]; 131*211b2d39SPeter Brune R = snes->work[2]; 132087dfb9eSxuemin ierr = VecDuplicate(X,&Xold);CHKERRQ(ierr); 133087dfb9eSxuemin ierr = VecDuplicate(X,&temp);CHKERRQ(ierr); 134*211b2d39SPeter Brune ierr = VecDuplicate(X,&Fold);CHKERRQ(ierr); 135a312c225SMatthew G Knepley 1364a0c5b0cSMatthew G Knepley ierr = SNESGetPC(snes, &pc);CHKERRQ(ierr); 137a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 138a312c225SMatthew G Knepley snes->iter = 0; 139a312c225SMatthew G Knepley snes->norm = 0.; 140a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 141*211b2d39SPeter Brune ierr = SNESComputeFunction(snes, X, R);CHKERRQ(ierr); /* r = F(x) */ 142087dfb9eSxuemin #if 0 143*211b2d39SPeter Brune ierr = SNESSolve(snes->pc, R, F);CHKERRQ(ierr); /* p = P(r) */ 144087dfb9eSxuemin #else 145*211b2d39SPeter Brune ierr = VecCopy(R, F);CHKERRQ(ierr); /* p = r */ 146087dfb9eSxuemin #endif 147a312c225SMatthew G Knepley if (snes->domainerror) { 148a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 149a312c225SMatthew G Knepley PetscFunctionReturn(0); 150a312c225SMatthew G Knepley } 151087dfb9eSxuemin ierr = VecNorm(F, NORM_2, &gnorm);CHKERRQ(ierr); /* fnorm = ||r|| */ 152087dfb9eSxuemin if (PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 153087dfb9eSxuemin 154a312c225SMatthew G Knepley ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 155087dfb9eSxuemin snes->norm = gnorm; 156a312c225SMatthew G Knepley ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 157087dfb9eSxuemin SNESLogConvHistory(snes, gnorm, 0); 158087dfb9eSxuemin ierr = SNESMonitor(snes, 0, gnorm);CHKERRQ(ierr); 159087dfb9eSxuemin ierr = (*snes->ops->converged)(snes,0,0.0,0.0,gnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 160a312c225SMatthew G Knepley if (snes->reason) PetscFunctionReturn(0); 161a312c225SMatthew G Knepley 162087dfb9eSxuemin /* for k=0 */ 163087dfb9eSxuemin 164087dfb9eSxuemin k=0; 165087dfb9eSxuemin ierr= VecCopy(X,Xold); CHKERRQ(ierr); /* Xbar_0= X_0 */ 166087dfb9eSxuemin ierr= VecCopy(F,Fold); CHKERRQ(ierr); /* Fbar_0 = f_0= B(b-Ax_0) */ 167087dfb9eSxuemin ierr= VecWAXPY(X, ngmres->beta, Fold, Xold); CHKERRQ(ierr); /*X_1 = X_bar + beta * Fbar */ 168087dfb9eSxuemin 169087dfb9eSxuemin /* to calculate f_1 */ 170*211b2d39SPeter Brune ierr = SNESComputeFunction(snes, X, R);CHKERRQ(ierr); /* r = F(x) */ 171087dfb9eSxuemin #if 0 172087dfb9eSxuemin ierr = SNESSolve(snes->pc, temp, F);CHKERRQ(ierr); /* p = P(r) */ 1734a0c5b0cSMatthew G Knepley #else 174*211b2d39SPeter Brune ierr = VecCopy(R, F);CHKERRQ(ierr); /* p = r */ 175a312c225SMatthew G Knepley #endif 176a312c225SMatthew G Knepley 177087dfb9eSxuemin /* calculate dX and dF for k=0 */ 178087dfb9eSxuemin ierr= VecWAXPY(dX[k],-1.0, Xold, X); CHKERRQ(ierr); /* dX= X_1 - X_0 */ 179087dfb9eSxuemin ierr= VecWAXPY(dF[k],-1.0, Fold, F); CHKERRQ(ierr); /* dF= f_1 - f_0 */ 180087dfb9eSxuemin 181087dfb9eSxuemin ierr= VecCopy(X,Xold); CHKERRQ(ierr); /* Xbar_0= X_0 */ 182087dfb9eSxuemin ierr= VecCopy(F,Fold); CHKERRQ(ierr); /* Fbar_0 = f_0= B(b-Ax_0) */ 183087dfb9eSxuemin 184087dfb9eSxuemin flag=0; 185087dfb9eSxuemin 186087dfb9eSxuemin for (k=1; k<snes->max_its; k += 1) { /* begin the iteration */ 187087dfb9eSxuemin l=ngmres->msize; 188c0bbabecSxuemin 189c0bbabecSxuemin if(k<l) { 190c0bbabecSxuemin l=k; 191*211b2d39SPeter Brune ivec=l; 192c0bbabecSxuemin } 193c0bbabecSxuemin else{ 194c0bbabecSxuemin ivec=l-1; 195c0bbabecSxuemin } 196087dfb9eSxuemin it=l-1; 197087dfb9eSxuemin ierr = BuildNGmresSoln(nrs,Fold,snes,it,flag);CHKERRQ(ierr); 198087dfb9eSxuemin 199087dfb9eSxuemin /* to obtain the solution at k+1 step */ 200087dfb9eSxuemin ierr= VecCopy(Xold,X); CHKERRQ(ierr); /* X=Xold+Fold-(dX + dF) *nrd */ 201087dfb9eSxuemin ierr= VecAXPY(X,1.0,Fold); CHKERRQ(ierr); /* X= Xold+Fold */ 202087dfb9eSxuemin for(i=0;i<l;i++){ /*X= Xold+Fold- (dX+dF*beta) *innerb */ 203087dfb9eSxuemin ierr= VecAXPY(X,-nrs[i], dX[i]);CHKERRQ(ierr); 204087dfb9eSxuemin ierr= VecAXPY(X,-nrs[i]*ngmres->beta, dF[i]);CHKERRQ(ierr); 205a312c225SMatthew G Knepley } 206087dfb9eSxuemin 207087dfb9eSxuemin /* to calculate f_k+1 */ 208*211b2d39SPeter Brune ierr = SNESComputeFunction(snes, X, R);CHKERRQ(ierr); /* r = F(x) */ 209*211b2d39SPeter Brune 210087dfb9eSxuemin #if 0 211*211b2d39SPeter Brune ierr = SNESSolve(snes->pc, R, F);CHKERRQ(ierr); /* p = P(r) */ 212087dfb9eSxuemin #else 213*211b2d39SPeter Brune ierr = VecCopy(R, F);CHKERRQ(ierr); /* p = r */ 214087dfb9eSxuemin #endif 215087dfb9eSxuemin 216087dfb9eSxuemin /* check the convegence */ 217*211b2d39SPeter Brune 218*211b2d39SPeter Brune ierr = VecNorm(R, NORM_2, &gnorm);CHKERRQ(ierr); /* fnorm = ||r|| */ 219*211b2d39SPeter Brune ierr = VecNorm(dX[l-1], NORM_2, &pnorm);CHKERRQ(ierr); /* fnorm = ||r||*/ 220*211b2d39SPeter Brune ierr = VecNorm(X, NORM_2, &xnorm);CHKERRQ(ierr); /* fnorm = ||r|| */ 221087dfb9eSxuemin SNESLogConvHistory(snes, gnorm, k); 222087dfb9eSxuemin ierr = SNESMonitor(snes, k, gnorm);CHKERRQ(ierr); 223087dfb9eSxuemin snes->iter =k; 224*211b2d39SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,pnorm,gnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 225087dfb9eSxuemin if (snes->reason) PetscFunctionReturn(0); 226087dfb9eSxuemin 227087dfb9eSxuemin 228087dfb9eSxuemin 229087dfb9eSxuemin /* calculate dX and dF for k=0 */ 230c0bbabecSxuemin if( k>ivec) {/* we need to replace the old vectors */ 231087dfb9eSxuemin flag=1; 232c0bbabecSxuemin for(i=0;i<it;i++){ 233087dfb9eSxuemin ierr= VecCopy(dX[i+1],dX[i]); CHKERRQ(ierr); /* X=Xold+Fold-(dX + dF) *nrd */ 234087dfb9eSxuemin ierr= VecCopy(dF[i+1],dF[i]); CHKERRQ(ierr); /* X=Xold+Fold-(dX + dF) *nrd */ 235087dfb9eSxuemin for(j=0;j<l;j++) 236087dfb9eSxuemin *HH(j,i)=*HH(j,i+1); 237087dfb9eSxuemin } 238087dfb9eSxuemin } 239c0bbabecSxuemin 240c0bbabecSxuemin ierr= VecWAXPY(dX[ivec],-1.0, Xold, X); CHKERRQ(ierr); /* dX= X_1 - X_0 */ 241c0bbabecSxuemin ierr= VecWAXPY(dF[ivec],-1.0, Fold, F); CHKERRQ(ierr); /* dF= f_1 - f_0 */ 242087dfb9eSxuemin ierr= VecCopy(X,Xold); CHKERRQ(ierr); 243087dfb9eSxuemin ierr= VecCopy(F,Fold); CHKERRQ(ierr); 244087dfb9eSxuemin 245a312c225SMatthew G Knepley } 246a312c225SMatthew G Knepley snes->reason = SNES_DIVERGED_MAX_IT; 247a312c225SMatthew G Knepley PetscFunctionReturn(0); 248a312c225SMatthew G Knepley } 249a312c225SMatthew G Knepley 250a312c225SMatthew G Knepley /*MC 251a312c225SMatthew G Knepley SNESNGMRES - The Nonlinear Generalized Minimum Residual (NGMRES) method of Oosterlee and Washio. 252a312c225SMatthew G Knepley 253a312c225SMatthew G Knepley Level: beginner 254a312c225SMatthew G Knepley 255a312c225SMatthew G Knepley Notes: Supports only left preconditioning 256a312c225SMatthew G Knepley 257a312c225SMatthew G Knepley "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 258a312c225SMatthew G Knepley SIAM Journal on Scientific Computing, 21(5), 2000. 259a312c225SMatthew G Knepley 260a312c225SMatthew G Knepley .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 261a312c225SMatthew G Knepley M*/ 262a312c225SMatthew G Knepley EXTERN_C_BEGIN 263a312c225SMatthew G Knepley #undef __FUNCT__ 264a312c225SMatthew G Knepley #define __FUNCT__ "SNESCreate_NGMRES" 265a312c225SMatthew G Knepley PetscErrorCode SNESCreate_NGMRES(SNES snes) 266a312c225SMatthew G Knepley { 267a312c225SMatthew G Knepley SNES_NGMRES *ngmres; 268a312c225SMatthew G Knepley PetscErrorCode ierr; 269a312c225SMatthew G Knepley 270a312c225SMatthew G Knepley PetscFunctionBegin; 271a312c225SMatthew G Knepley snes->ops->destroy = SNESDestroy_NGMRES; 272a312c225SMatthew G Knepley snes->ops->setup = SNESSetUp_NGMRES; 273a312c225SMatthew G Knepley snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 274a312c225SMatthew G Knepley snes->ops->view = SNESView_NGMRES; 275a312c225SMatthew G Knepley snes->ops->solve = SNESSolve_NGMRES; 276a312c225SMatthew G Knepley snes->ops->reset = SNESReset_NGMRES; 277a312c225SMatthew G Knepley 278a312c225SMatthew G Knepley ierr = PetscNewLog(snes, SNES_NGMRES, &ngmres);CHKERRQ(ierr); 279a312c225SMatthew G Knepley snes->data = (void*) ngmres; 280a312c225SMatthew G Knepley ngmres->msize = 30; 281a312c225SMatthew G Knepley ngmres->csize = 0; 2824a0c5b0cSMatthew G Knepley 2834a0c5b0cSMatthew G Knepley ierr = SNESGetPC(snes, &snes->pc);CHKERRQ(ierr); 284a312c225SMatthew G Knepley #if 0 285a312c225SMatthew G Knepley if (ksp->pc_side != PC_LEFT) {ierr = PetscInfo(ksp,"WARNING! Setting PC_SIDE for NGMRES to left!\n");CHKERRQ(ierr);} 286a312c225SMatthew G Knepley snes->pc_side = PC_LEFT; 287a312c225SMatthew G Knepley #endif 288a312c225SMatthew G Knepley PetscFunctionReturn(0); 289a312c225SMatthew G Knepley } 290a312c225SMatthew G Knepley EXTERN_C_END 291087dfb9eSxuemin 292087dfb9eSxuemin 293087dfb9eSxuemin #undef __FUNCT__ 294087dfb9eSxuemin #define __FUNCT__ "BuildNGmresSoln" 295087dfb9eSxuemin static PetscErrorCode BuildNGmresSoln(PetscScalar* nrs, Vec Fold, SNES snes,PetscInt it, PetscInt flag) 296087dfb9eSxuemin { 297087dfb9eSxuemin PetscScalar tt,temps; 298087dfb9eSxuemin PetscErrorCode ierr; 299087dfb9eSxuemin PetscInt i,ii,j,l; 300087dfb9eSxuemin SNES_NGMRES *ngmres = (SNES_NGMRES *)(snes->data); 301*211b2d39SPeter Brune //Vec *dF=ngmres->w+ngmres->msize, *Q=ngmres->w+ngmres->msize*2,temp; 302*211b2d39SPeter Brune Vec *dF=ngmres->w+ngmres->msize,*Q=ngmres->q,temp; 303dadb11c9SJed Brown PetscReal gam,areal; 304dadb11c9SJed Brown PetscScalar a,b,c,s; 305087dfb9eSxuemin 306087dfb9eSxuemin PetscFunctionBegin; 307087dfb9eSxuemin ierr = VecDuplicate(Fold,&temp);CHKERRQ(ierr); 308087dfb9eSxuemin l=it+1; 309087dfb9eSxuemin 310087dfb9eSxuemin /* Solve for solution vector that minimizes the residual */ 311087dfb9eSxuemin 312087dfb9eSxuemin if(flag==1) { // we need to replace the old vector and need to modify the QR factors, use Givens rotation 313087dfb9eSxuemin for(i=0;i<it;i++){ 314087dfb9eSxuemin /* calculate the Givens rotation */ 315087dfb9eSxuemin a=*HH(i,i); 316087dfb9eSxuemin b=*HH(i+1,i); 317*211b2d39SPeter Brune gam=1.0/PetscRealPart(PetscSqrtScalar(PetscConj(a)*a + PetscConj(b)*b)); 318087dfb9eSxuemin c= a*gam; 319087dfb9eSxuemin s= b*gam; 320c0bbabecSxuemin 321c0bbabecSxuemin #if defined(PETSC_USE_COMPLEX) 322c0bbabecSxuemin /* update the Q factor */ 323c0bbabecSxuemin ierr= VecCopy(Q[i],temp); CHKERRQ(ierr); 324c0bbabecSxuemin ierr = VecAXPBY(temp,s,PetscConj(c),Q[i+1]);CHKERRQ(ierr); /*temp= c*Q[i]+s*Q[i+1] */ 325c0bbabecSxuemin ierr = VecAXPBY(Q[i+1],-s,c,Q[i]);CHKERRQ(ierr); /* Q[i+1]= -s*Q[i] + c*Q[i+1] */ 326c0bbabecSxuemin ierr= VecCopy(temp,Q[i]); CHKERRQ(ierr); /* Q[i]= c*Q[i] + s*Q[i+1] */ 327c0bbabecSxuemin /* update the R factor */ 328c0bbabecSxuemin for(j=0;j<l;j++){ 329c0bbabecSxuemin a= *HH(i,j); 330c0bbabecSxuemin b=*HH(i+1,j); 331c0bbabecSxuemin temps=PetscConj(c)* a+s* b; 332c0bbabecSxuemin *HH(i+1,j)=-s*a+c*b; 333c0bbabecSxuemin *HH(i,j)=temps; 334c0bbabecSxuemin } 335c0bbabecSxuemin #else 336087dfb9eSxuemin /* update the Q factor */ 337087dfb9eSxuemin ierr= VecCopy(Q[i],temp); CHKERRQ(ierr); 338087dfb9eSxuemin ierr = VecAXPBY(temp,s,c,Q[i+1]);CHKERRQ(ierr); /*temp= c*Q[i]+s*Q[i+1] */ 339087dfb9eSxuemin ierr = VecAXPBY(Q[i+1],-s,c,Q[i]);CHKERRQ(ierr); /* Q[i+1]= -s*Q[i] + c*Q[i+1] */ 340087dfb9eSxuemin ierr= VecCopy(temp,Q[i]); CHKERRQ(ierr); /* Q[i]= c*Q[i] + s*Q[i+1] */ 341087dfb9eSxuemin /* update the R factor */ 342087dfb9eSxuemin for(j=0;j<l;j++){ 343087dfb9eSxuemin a= *HH(i,j); 344087dfb9eSxuemin b=*HH(i+1,j); 345087dfb9eSxuemin temps=c* a+s* b; 346087dfb9eSxuemin *HH(i+1,j)=-s*a+c*b; 347087dfb9eSxuemin *HH(i,j)=temps; 348087dfb9eSxuemin } 349c0bbabecSxuemin #endif 350087dfb9eSxuemin } 351087dfb9eSxuemin } 352087dfb9eSxuemin 353087dfb9eSxuemin // add a new vector, use modified Gram-Schmidt 354087dfb9eSxuemin ierr= VecCopy(dF[it],temp); CHKERRQ(ierr); 355087dfb9eSxuemin for(i=0;i<it;i++){ 356087dfb9eSxuemin ierr=VecDot(temp,Q[i],HH(i,it));CHKERRQ(ierr); /* h(i,l-1)= dF[l-1]'*Q[i] */ 357087dfb9eSxuemin ierr = VecAXPBY(temp,-*HH(i,it),1.0,Q[i]);CHKERRQ(ierr); /* temp= temp- h(i,l-1)*Q[i] */ 358087dfb9eSxuemin } 359c0bbabecSxuemin ierr=VecCopy(temp,Q[it]);CHKERRQ(ierr); 360c0bbabecSxuemin ierr=VecNormalize(Q[it],&areal);CHKERRQ(ierr); 361c0bbabecSxuemin *HH(it,it) = areal; 362087dfb9eSxuemin 363087dfb9eSxuemin 364*211b2d39SPeter Brune 365087dfb9eSxuemin /* modify the RHS with Q'*Fold*/ 366087dfb9eSxuemin 367087dfb9eSxuemin for(i=0;i<l;i++) 368087dfb9eSxuemin ierr=VecDot(Fold,Q[i],ngmres->nrs+i);CHKERRQ(ierr); /* nrs= Fold'*Q[i] */ 369087dfb9eSxuemin 370087dfb9eSxuemin /* start backsubstitution to solve the least square problem */ 371087dfb9eSxuemin 372087dfb9eSxuemin if (*HH(it,it) != 0.0) { 373087dfb9eSxuemin nrs[it] = nrs[it]/ *HH(it,it); 374087dfb9eSxuemin } else { 375087dfb9eSxuemin snes->reason = SNES_DIVERGED_MAX_IT; 376087dfb9eSxuemin ierr = PetscInfo2(snes,"Likely your matrix or preconditioner is singular. HH(it,it) is identically zero; it = %D nrs(it) = %G",it,10); 377087dfb9eSxuemin PetscFunctionReturn(0); 378087dfb9eSxuemin } 379087dfb9eSxuemin for (ii=1; ii<=it; ii++) { 380087dfb9eSxuemin i = it - ii; 381087dfb9eSxuemin tt = nrs[i]; 382087dfb9eSxuemin for (j=i+1; j<=it; j++) tt = tt - *HH(i,j) * nrs[j]; 383087dfb9eSxuemin if (*HH(i,i) == 0.0) { 384087dfb9eSxuemin snes->reason = SNES_DIVERGED_MAX_IT; 385087dfb9eSxuemin ierr = PetscInfo1(snes,"Likely your matrix or preconditioner is singular. HH(k,k) is identically zero; i = %D",i); 386087dfb9eSxuemin PetscFunctionReturn(0); 387087dfb9eSxuemin } 388087dfb9eSxuemin nrs[i] = tt / *HH(i,i); 389087dfb9eSxuemin } 390087dfb9eSxuemin 391087dfb9eSxuemin 392087dfb9eSxuemin PetscFunctionReturn(0); 393087dfb9eSxuemin } 394