static PetscErrorCode KSPGMRESBuildSoln(PetscScalar *nrs,Vec vs,Vec vdest,KSP ksp,PetscInt it) { PetscScalar tt; PetscErrorCode ierr; PetscInt ii,k,j; KSP_GMRES *gmres = (KSP_GMRES*)(ksp->data); PetscFunctionBegin; /* Solve for solution vector that minimizes the residual */ /* If it is < 0, no gmres steps have been performed */ if (it < 0) { ierr = VecCopy(vs,vdest);CHKERRQ(ierr); /* VecCopy() is smart, exists immediately if vguess == vdest */ PetscFunctionReturn(0); } if (*HH(it,it) != 0.0) { nrs[it] = *GRS(it) / *HH(it,it); } else { ksp->reason = KSP_DIVERGED_BREAKDOWN; ierr = PetscInfo2(ksp,"Likely your matrix or preconditioner is singular. HH(it,it) is identically zero; it = %D GRS(it) = %G",it,PetscAbsScalar(*GRS(it)));CHKERRQ(ierr); PetscFunctionReturn(0); } for (ii=1; ii<=it; ii++) { k = it - ii; tt = *GRS(k); for (j=k+1; j<=it; j++) tt = tt - *HH(k,j) * nrs[j]; if (*HH(k,k) == 0.0) { ksp->reason = KSP_DIVERGED_BREAKDOWN; ierr = PetscInfo1(ksp,"Likely your matrix or preconditioner is singular. HH(k,k) is identically zero; k = %D",k);CHKERRQ(ierr); PetscFunctionReturn(0); } nrs[k] = tt / *HH(k,k); } /* Accumulate the correction to the solution of the preconditioned problem in TEMP */ ierr = VecSet(VEC_TEMP,0.0);CHKERRQ(ierr); ierr = VecMAXPY(VEC_TEMP,it+1,nrs,&VEC_VV(0));CHKERRQ(ierr); ierr = KSPUnwindPreconditioner(ksp,VEC_TEMP,VEC_TEMP_MATOP);CHKERRQ(ierr); /* add solution to previous solution */ if (vdest != vs) { ierr = VecCopy(vs,vdest);CHKERRQ(ierr); } ierr = VecAXPY(vdest,1.0,VEC_TEMP);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPPGMRESBuildSoln(PetscScalar *nrs,Vec vguess,Vec vdest,KSP ksp,PetscInt it) { PetscScalar tt; PetscErrorCode ierr; PetscInt k,j; KSP_PGMRES *pgmres = (KSP_PGMRES*)(ksp->data); PetscFunctionBegin; /* Solve for solution vector that minimizes the residual */ if (it < 0) { /* no pgmres steps have been performed */ ierr = VecCopy(vguess,vdest);CHKERRQ(ierr); /* VecCopy() is smart, exits immediately if vguess == vdest */ PetscFunctionReturn(0); } /* solve the upper triangular system - RS is the right side and HH is the upper triangular matrix - put soln in nrs */ if (*HH(it,it) != 0.0) nrs[it] = *RS(it) / *HH(it,it); else nrs[it] = 0.0; for (k=it-1; k>=0; k--) { tt = *RS(k); for (j=k+1; j<=it; j++) tt -= *HH(k,j) * nrs[j]; nrs[k] = tt / *HH(k,k); } /* Accumulate the correction to the solution of the preconditioned problem in TEMP */ ierr = VecZeroEntries(VEC_TEMP);CHKERRQ(ierr); ierr = VecMAXPY(VEC_TEMP,it+1,nrs,&VEC_VV(0));CHKERRQ(ierr); ierr = KSPUnwindPreconditioner(ksp,VEC_TEMP,VEC_TEMP_MATOP);CHKERRQ(ierr); /* add solution to previous solution */ if (vdest == vguess) { ierr = VecAXPY(vdest,1.0,VEC_TEMP);CHKERRQ(ierr); } else { ierr = VecWAXPY(vdest,1.0,VEC_TEMP,vguess);CHKERRQ(ierr); } PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_TCQMR(KSP ksp) { PetscReal rnorm0,rnorm,dp1,Gamma; PetscScalar theta,ep,cl1,sl1,cl,sl,sprod,tau_n1,f; PetscScalar deltmp,rho,beta,eptmp,ta,s,c,tau_n,delta; PetscScalar dp11,dp2,rhom1,alpha,tmp; PetscErrorCode ierr; PetscFunctionBegin; ksp->its = 0; ierr = KSPInitialResidual(ksp,x,u,v,r,b);CHKERRQ(ierr); ierr = VecNorm(r,NORM_2,&rnorm0);CHKERRQ(ierr); /* rnorm0 = ||r|| */ KSPCheckNorm(ksp,rnorm0); ierr = (*ksp->converged)(ksp,0,rnorm0,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); ierr = VecSet(um1,0.0);CHKERRQ(ierr); ierr = VecCopy(r,u);CHKERRQ(ierr); rnorm = rnorm0; tmp = 1.0/rnorm; ierr = VecScale(u,tmp);CHKERRQ(ierr); ierr = VecSet(vm1,0.0);CHKERRQ(ierr); ierr = VecCopy(u,v);CHKERRQ(ierr); ierr = VecCopy(u,v0);CHKERRQ(ierr); ierr = VecSet(pvec1,0.0);CHKERRQ(ierr); ierr = VecSet(pvec2,0.0);CHKERRQ(ierr); ierr = VecSet(p,0.0);CHKERRQ(ierr); theta = 0.0; ep = 0.0; cl1 = 0.0; sl1 = 0.0; cl = 0.0; sl = 0.0; sprod = 1.0; tau_n1= rnorm0; f = 1.0; Gamma = 1.0; rhom1 = 1.0; /* CALCULATE SQUARED LANCZOS vectors */ ierr = (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); while (!ksp->reason) { ierr = KSPMonitor(ksp,ksp->its,rnorm);CHKERRQ(ierr); ksp->its++; ierr = KSP_PCApplyBAorAB(ksp,u,y,vtmp);CHKERRQ(ierr); /* y = A*u */ ierr = VecDot(y,v0,&dp11);CHKERRQ(ierr); KSPCheckDot(ksp,dp11); ierr = VecDot(u,v0,&dp2);CHKERRQ(ierr); alpha = dp11 / dp2; /* alpha = v0'*y/v0'*u */ deltmp = alpha; ierr = VecCopy(y,z);CHKERRQ(ierr); ierr = VecAXPY(z,-alpha,u);CHKERRQ(ierr); /* z = y - alpha u */ ierr = VecDot(u,v0,&rho);CHKERRQ(ierr); beta = rho / (f*rhom1); rhom1 = rho; ierr = VecCopy(z,utmp);CHKERRQ(ierr); /* up1 = (A-alpha*I)* (z-2*beta*p) + f*beta* beta*um1 */ ierr = VecAXPY(utmp,-2.0*beta,p);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp,utmp,up1,vtmp);CHKERRQ(ierr); ierr = VecAXPY(up1,-alpha,utmp);CHKERRQ(ierr); ierr = VecAXPY(up1,f*beta*beta,um1);CHKERRQ(ierr); ierr = VecNorm(up1,NORM_2,&dp1);CHKERRQ(ierr); KSPCheckNorm(ksp,dp1); f = 1.0 / dp1; ierr = VecScale(up1,f);CHKERRQ(ierr); ierr = VecAYPX(p,-beta,z);CHKERRQ(ierr); /* p = f*(z-beta*p) */ ierr = VecScale(p,f);CHKERRQ(ierr); ierr = VecCopy(u,um1);CHKERRQ(ierr); ierr = VecCopy(up1,u);CHKERRQ(ierr); beta = beta/Gamma; eptmp = beta; ierr = KSP_PCApplyBAorAB(ksp,v,vp1,vtmp);CHKERRQ(ierr); ierr = VecAXPY(vp1,-alpha,v);CHKERRQ(ierr); ierr = VecAXPY(vp1,-beta,vm1);CHKERRQ(ierr); ierr = VecNorm(vp1,NORM_2,&Gamma);CHKERRQ(ierr); KSPCheckNorm(ksp,Gamma); ierr = VecScale(vp1,1.0/Gamma);CHKERRQ(ierr); ierr = VecCopy(v,vm1);CHKERRQ(ierr); ierr = VecCopy(vp1,v);CHKERRQ(ierr); /* SOLVE Ax = b */ /* Apply last two Given's (Gl-1 and Gl) rotations to (beta,alpha,Gamma) */ if (ksp->its > 2) { theta = sl1*beta; eptmp = -cl1*beta; } if (ksp->its > 1) { ep = -cl*eptmp + sl*alpha; deltmp = -sl*eptmp - cl*alpha; } if (PetscAbsReal(Gamma) > PetscAbsScalar(deltmp)) { ta = -deltmp / Gamma; s = 1.0 / PetscSqrtScalar(1.0 + ta*ta); c = s*ta; } else { ta = -Gamma/deltmp; c = 1.0 / PetscSqrtScalar(1.0 + ta*ta); s = c*ta; } delta = -c*deltmp + s*Gamma; tau_n = -c*tau_n1; tau_n1 = -s*tau_n1; ierr = VecCopy(vm1,pvec);CHKERRQ(ierr); ierr = VecAXPY(pvec,-theta,pvec2);CHKERRQ(ierr); ierr = VecAXPY(pvec,-ep,pvec1);CHKERRQ(ierr); ierr = VecScale(pvec,1.0/delta);CHKERRQ(ierr); ierr = VecAXPY(x,tau_n,pvec);CHKERRQ(ierr); cl1 = cl; sl1 = sl; cl = c; sl = s; ierr = VecCopy(pvec1,pvec2);CHKERRQ(ierr); ierr = VecCopy(pvec,pvec1);CHKERRQ(ierr); /* Compute the upper bound on the residual norm r (See QMR paper p. 13) */ sprod = sprod*PetscAbsScalar(s); rnorm = rnorm0 * PetscSqrtReal((PetscReal)ksp->its+2.0) * PetscRealPart(sprod); ierr = (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->its >= ksp->max_it) { if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS; break; } } ierr = KSPMonitor(ksp,ksp->its,rnorm);CHKERRQ(ierr); ierr = KSPUnwindPreconditioner(ksp,x,vtmp);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_CGS(KSP ksp) { PetscErrorCode ierr; PetscInt i; PetscScalar rho,rhoold,a,s,b; Vec X,B,V,P,R,RP,T,Q,U,AUQ; PetscReal dp = 0.0; PetscBool diagonalscale; PetscFunctionBegin; /* not sure what residual norm it does use, should use for right preconditioning */ ierr = PCGetDiagonalScale(ksp->pc,&diagonalscale);CHKERRQ(ierr); if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name); X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; RP = ksp->work[1]; V = ksp->work[2]; T = ksp->work[3]; Q = ksp->work[4]; P = ksp->work[5]; U = ksp->work[6]; AUQ = V; /* Compute initial preconditioned residual */ ierr = KSPInitialResidual(ksp,X,V,T,R,B);CHKERRQ(ierr); /* Test for nothing to do */ ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_NATURAL) dp *= dp; ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its = 0; ksp->rnorm = dp; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); /* Make the initial Rp == R */ ierr = VecCopy(R,RP);CHKERRQ(ierr); /* added for Fidap */ /* Penalize Startup - Isaac Hasbani Trick for CGS Since most initial conditions result in a mostly 0 residual, we change all the 0 values in the vector RP to the maximum. */ if (ksp->normtype == KSP_NORM_NATURAL) { PetscReal vr0max; PetscScalar *tmp_RP=0; PetscInt numnp =0, *max_pos=0; ierr = VecMax(RP, max_pos, &vr0max);CHKERRQ(ierr); ierr = VecGetArray(RP, &tmp_RP);CHKERRQ(ierr); ierr = VecGetLocalSize(RP, &numnp);CHKERRQ(ierr); for (i=0; i<numnp; i++) { if (tmp_RP[i] == 0.0) tmp_RP[i] = vr0max; } ierr = VecRestoreArray(RP, &tmp_RP);CHKERRQ(ierr); } /* end of addition for Fidap */ /* Set the initial conditions */ ierr = VecDot(R,RP,&rhoold);CHKERRQ(ierr); /* rhoold = (r,rp) */ ierr = VecCopy(R,U);CHKERRQ(ierr); ierr = VecCopy(R,P);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp,P,V,T);CHKERRQ(ierr); i = 0; do { ierr = VecDot(V,RP,&s);CHKERRQ(ierr); /* s <- (v,rp) */ a = rhoold / s; /* a <- rho / s */ ierr = VecWAXPY(Q,-a,V,U);CHKERRQ(ierr); /* q <- u - a v */ ierr = VecWAXPY(T,1.0,U,Q);CHKERRQ(ierr); /* t <- u + q */ ierr = VecAXPY(X,a,T);CHKERRQ(ierr); /* x <- x + a (u + q) */ ierr = KSP_PCApplyBAorAB(ksp,T,AUQ,U);CHKERRQ(ierr); ierr = VecAXPY(R,-a,AUQ);CHKERRQ(ierr); /* r <- r - a K (u + q) */ ierr = VecDot(R,RP,&rho);CHKERRQ(ierr); /* rho <- (r,rp) */ if (ksp->normtype == KSP_NORM_NATURAL) { dp = PetscAbsScalar(rho); } else { ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); } ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its++; ksp->rnorm = dp; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,dp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i+1,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; b = rho / rhoold; /* b <- rho / rhoold */ ierr = VecWAXPY(U,b,Q,R);CHKERRQ(ierr); /* u <- r + b q */ ierr = VecAXPY(Q,b,P);CHKERRQ(ierr); ierr = VecWAXPY(P,b,Q,U);CHKERRQ(ierr); /* p <- u + b(q + b p) */ ierr = KSP_PCApplyBAorAB(ksp,P,V,Q);CHKERRQ(ierr); /* v <- K p */ rhoold = rho; i++; } while (i<ksp->max_it); if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS; ierr = KSPUnwindPreconditioner(ksp,X,T);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_IBCGS(KSP ksp) { PetscErrorCode ierr; PetscInt i,N; PetscReal rnorm,rnormin = 0.0; #if defined(PETSC_HAVE_MPI_LONG_DOUBLE) && !defined(PETSC_USE_COMPLEX) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) /* Because of possible instabilities in the algorithm (as indicated by different residual histories for the same problem on the same number of processes with different runs) we support computing the inner products using Intel's 80 bit arithematic rather than just 64 bit. Thus we copy our double precision values into long doubles (hoping this keeps the 16 extra bits) and tell MPI to do its ALlreduces with MPI_LONG_DOUBLE. Note for developers that does not effect the code. Intel's long double is implemented by storing the 80 bits of extended double precision into a 16 byte space (the rest of the space is ignored) */ long double insums[7],outsums[7]; #else PetscScalar insums[7],outsums[7]; #endif PetscScalar sigman_2, sigman_1, sigman, pin_1, pin, phin_1, phin,tmp1,tmp2; PetscScalar taun_1, taun, rhon, alphan_1, alphan, omegan_1, omegan; const PetscScalar *PETSC_RESTRICT r0, *PETSC_RESTRICT f0, *PETSC_RESTRICT qn, *PETSC_RESTRICT b, *PETSC_RESTRICT un; PetscScalar *PETSC_RESTRICT rn, *PETSC_RESTRICT xn, *PETSC_RESTRICT vn, *PETSC_RESTRICT zn; /* the rest do not have to keep n_1 values */ PetscScalar kappan, thetan, etan, gamman, betan, deltan; const PetscScalar *PETSC_RESTRICT tn; PetscScalar *PETSC_RESTRICT sn; Vec R0,Rn,Xn,F0,Vn,Zn,Qn,Tn,Sn,B,Un; Mat A; PetscFunctionBegin; if (!ksp->vec_rhs->petscnative) SETERRQ(((PetscObject)ksp)->comm,PETSC_ERR_SUP,"Only coded for PETSc vectors"); ierr = PCGetOperators(ksp->pc,&A,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); ierr = VecGetLocalSize(ksp->vec_sol,&N);CHKERRQ(ierr); Xn = ksp->vec_sol;ierr = VecGetArray(Xn_1,(PetscScalar**)&xn_1);CHKERRQ(ierr);ierr = VecRestoreArray(Xn_1,PETSC_NULL);CHKERRQ(ierr); B = ksp->vec_rhs;ierr = VecGetArrayRead(B,(const PetscScalar**)&b);ierr = VecRestoreArrayRead(B,PETSC_NULL);CHKERRQ(ierr); R0 = ksp->work[0];ierr = VecGetArrayRead(R0,(const PetscScalar**)&r0);CHKERRQ(ierr);ierr = VecRestoreArrayRead(R0,PETSC_NULL);CHKERRQ(ierr); Rn = ksp->work[1];ierr = VecGetArray(Rn_1,(PetscScalar**)&rn_1);CHKERRQ(ierr);ierr = VecRestoreArray(Rn_1,PETSC_NULL);CHKERRQ(ierr); Un = ksp->work[2];ierr = VecGetArrayRead(Un_1,(const PetscScalar**)&un_1);CHKERRQ(ierr);ierr = VecRestoreArrayRead(Un_1,PETSC_NULL);CHKERRQ(ierr); F0 = ksp->work[3];ierr = VecGetArrayRead(F0,(const PetscScalar**)&f0);CHKERRQ(ierr);ierr = VecRestoreArrayRead(F0,PETSC_NULL);CHKERRQ(ierr); Vn = ksp->work[4];ierr = VecGetArray(Vn_1,(PetscScalar**)&vn_1);CHKERRQ(ierr);ierr = VecRestoreArray(Vn_1,PETSC_NULL);CHKERRQ(ierr); Zn = ksp->work[5];ierr = VecGetArray(Zn_1,(PetscScalar**)&zn_1);CHKERRQ(ierr);ierr = VecRestoreArray(Zn_1,PETSC_NULL);CHKERRQ(ierr); Qn = ksp->work[6];ierr = VecGetArrayRead(Qn_1,(const PetscScalar**)&qn_1);CHKERRQ(ierr);ierr = VecRestoreArrayRead(Qn_1,PETSC_NULL);CHKERRQ(ierr); Tn = ksp->work[7];ierr = VecGetArrayRead(Tn,(const PetscScalar**)&tn);CHKERRQ(ierr);ierr = VecRestoreArrayRead(Tn,PETSC_NULL);CHKERRQ(ierr); Sn = ksp->work[8];ierr = VecGetArrayRead(Sn,(const PetscScalar**)&sn);CHKERRQ(ierr);ierr = VecRestoreArrayRead(Sn,PETSC_NULL);CHKERRQ(ierr); /* r0 = rn_1 = b - A*xn_1; */ /* ierr = KSP_PCApplyBAorAB(ksp,Xn_1,Rn_1,Tn);CHKERRQ(ierr); ierr = VecAYPX(Rn_1,-1.0,B);CHKERRQ(ierr); */ ierr = KSPInitialResidual(ksp,Xn_1,Tn,Sn,Rn_1,B);CHKERRQ(ierr); ierr = VecNorm(Rn_1,NORM_2,&rnorm);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,rnorm);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,0,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); ierr = VecCopy(Rn_1,R0);CHKERRQ(ierr); /* un_1 = A*rn_1; */ ierr = KSP_PCApplyBAorAB(ksp,Rn_1,Un_1,Tn);CHKERRQ(ierr); /* f0 = A'*rn_1; */ if (ksp->pc_side == PC_RIGHT) { /* B' A' */ ierr = MatMultTranspose(A,R0,Tn);CHKERRQ(ierr); ierr = PCApplyTranspose(ksp->pc,Tn,F0);CHKERRQ(ierr); } else if (ksp->pc_side == PC_LEFT) { /* A' B' */ ierr = PCApplyTranspose(ksp->pc,R0,Tn);CHKERRQ(ierr); ierr = MatMultTranspose(A,Tn,F0);CHKERRQ(ierr); } /*qn_1 = vn_1 = zn_1 = 0.0; */ ierr = VecSet(Qn_1,0.0);CHKERRQ(ierr); ierr = VecSet(Vn_1,0.0);CHKERRQ(ierr); ierr = VecSet(Zn_1,0.0);CHKERRQ(ierr); sigman_2 = pin_1 = taun_1 = 0.0; /* the paper says phin_1 should be initialized to zero, it is actually R0'R0 */ ierr = VecDot(R0,R0,&phin_1);CHKERRQ(ierr); /* sigman_1 = rn_1'un_1 */ ierr = VecDot(R0,Un_1,&sigman_1);CHKERRQ(ierr); alphan_1 = omegan_1 = 1.0; for (ksp->its = 1; ksp->its<ksp->max_it+1; ksp->its++) { rhon = phin_1 - omegan_1*sigman_2 + omegan_1*alphan_1*pin_1; /* if (rhon == 0.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"rhon is zero, iteration %D",n); */ if (ksp->its == 1) deltan = rhon; else deltan = rhon/taun_1; betan = deltan/omegan_1; taun = sigman_1 + betan*taun_1 - deltan*pin_1; if (taun == 0.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"taun is zero, iteration %D",ksp->its); alphan = rhon/taun; ierr = PetscLogFlops(15.0); /* zn = alphan*rn_1 + (alphan/alphan_1)betan*zn_1 - alphan*deltan*vn_1 vn = un_1 + betan*vn_1 - deltan*qn_1 sn = rn_1 - alphan*vn The algorithm in the paper is missing the alphan/alphan_1 term in the zn update */ ierr = PetscLogEventBegin(VEC_Ops,0,0,0,0);CHKERRQ(ierr); tmp1 = (alphan/alphan_1)*betan; tmp2 = alphan*deltan; for (i=0; i<N; i++) { zn[i] = alphan*rn_1[i] + tmp1*zn_1[i] - tmp2*vn_1[i]; vn[i] = un_1[i] + betan*vn_1[i] - deltan*qn_1[i]; sn[i] = rn_1[i] - alphan*vn[i]; } ierr = PetscLogFlops(3.0+11.0*N); ierr = PetscLogEventEnd(VEC_Ops,0,0,0,0);CHKERRQ(ierr); /* qn = A*vn */ ierr = KSP_PCApplyBAorAB(ksp,Vn,Qn,Tn);CHKERRQ(ierr); /* tn = un_1 - alphan*qn */ ierr = VecWAXPY(Tn,-alphan,Qn,Un_1);CHKERRQ(ierr); /* phin = r0'sn pin = r0'qn gamman = f0'sn etan = f0'tn thetan = sn'tn kappan = tn'tn */ ierr = PetscLogEventBegin(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); phin = pin = gamman = etan = thetan = kappan = 0.0; for (i=0; i<N; i++) { phin += r0[i]*sn[i]; pin += r0[i]*qn[i]; gamman += f0[i]*sn[i]; etan += f0[i]*tn[i]; thetan += sn[i]*tn[i]; kappan += tn[i]*tn[i]; } ierr = PetscLogFlops(12.0*N); ierr = PetscLogEventEnd(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); insums[0] = phin; insums[1] = pin; insums[2] = gamman; insums[3] = etan; insums[4] = thetan; insums[5] = kappan; insums[6] = rnormin; ierr = PetscLogEventBarrierBegin(VEC_ReduceBarrier,0,0,0,0,((PetscObject)ksp)->comm);CHKERRQ(ierr); #if defined(PETSC_HAVE_MPI_LONG_DOUBLE) && !defined(PETSC_USE_COMPLEX) && (defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)) if (ksp->lagnorm && ksp->its > 1) { ierr = MPI_Allreduce(insums,outsums,7,MPI_LONG_DOUBLE,MPI_SUM,((PetscObject)ksp)->comm);CHKERRQ(ierr); } else { ierr = MPI_Allreduce(insums,outsums,6,MPI_LONG_DOUBLE,MPI_SUM,((PetscObject)ksp)->comm);CHKERRQ(ierr); } #else if (ksp->lagnorm && ksp->its > 1) { ierr = MPI_Allreduce(insums,outsums,7,MPIU_SCALAR,MPIU_SUM,((PetscObject)ksp)->comm);CHKERRQ(ierr); } else { ierr = MPI_Allreduce(insums,outsums,6,MPIU_SCALAR,MPIU_SUM,((PetscObject)ksp)->comm);CHKERRQ(ierr); } #endif ierr = PetscLogEventBarrierEnd(VEC_ReduceBarrier,0,0,0,0,((PetscObject)ksp)->comm);CHKERRQ(ierr); phin = outsums[0]; pin = outsums[1]; gamman = outsums[2]; etan = outsums[3]; thetan = outsums[4]; kappan = outsums[5]; if (ksp->lagnorm && ksp->its > 1) rnorm = PetscSqrtReal(PetscRealPart(outsums[6])); if (kappan == 0.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"kappan is zero, iteration %D",ksp->its); if (thetan == 0.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"thetan is zero, iteration %D",ksp->its); omegan = thetan/kappan; sigman = gamman - omegan*etan; /* rn = sn - omegan*tn xn = xn_1 + zn + omegan*sn */ ierr = PetscLogEventBegin(VEC_Ops,0,0,0,0);CHKERRQ(ierr); rnormin = 0.0; for (i=0; i<N; i++) { rn[i] = sn[i] - omegan*tn[i]; rnormin += PetscRealPart(PetscConj(rn[i])*rn[i]); xn[i] += zn[i] + omegan*sn[i]; } ierr = PetscObjectStateIncrease((PetscObject)Xn);CHKERRQ(ierr); ierr = PetscLogFlops(7.0*N); ierr = PetscLogEventEnd(VEC_Ops,0,0,0,0);CHKERRQ(ierr); if (!ksp->lagnorm && ksp->chknorm < ksp->its) { ierr = PetscLogEventBarrierBegin(VEC_ReduceBarrier,0,0,0,0,((PetscObject)ksp)->comm);CHKERRQ(ierr); ierr = MPI_Allreduce(&rnormin,&rnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)ksp)->comm);CHKERRQ(ierr); ierr = PetscLogEventBarrierEnd(VEC_ReduceBarrier,0,0,0,0,((PetscObject)ksp)->comm);CHKERRQ(ierr); rnorm = PetscSqrtReal(rnorm); } /* Test for convergence */ ierr = KSPMonitor(ksp,ksp->its,rnorm);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,ksp->its,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; /* un = A*rn */ ierr = KSP_PCApplyBAorAB(ksp,Rn,Un,Tn);CHKERRQ(ierr); /* Update n-1 locations with n locations */ sigman_2 = sigman_1; sigman_1 = sigman; pin_1 = pin; phin_1 = phin; alphan_1 = alphan; taun_1 = taun; omegan_1 = omegan; } if (ksp->its >= ksp->max_it) { ksp->reason = KSP_DIVERGED_ITS; } ierr = KSPUnwindPreconditioner(ksp,Xn,Tn);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPLGMRESBuildSoln(PetscScalar *nrs,Vec vguess,Vec vdest,KSP ksp,PetscInt it) { PetscScalar tt; PetscErrorCode ierr; PetscInt ii,k,j; KSP_LGMRES *lgmres = (KSP_LGMRES*)(ksp->data); /*LGMRES_MOD */ PetscInt it_arnoldi, it_aug; PetscInt jj, spot = 0; PetscFunctionBegin; /* Solve for solution vector that minimizes the residual */ /* If it is < 0, no lgmres steps have been performed */ if (it < 0) { ierr = VecCopy(vguess,vdest);CHKERRQ(ierr); /* VecCopy() is smart, exists immediately if vguess == vdest */ PetscFunctionReturn(0); } /* so (it+1) lgmres steps HAVE been performed */ /* LGMRES_MOD - determine if we need to use augvecs for the soln - do not assume that this is called after the total its allowed for an approx space */ if (lgmres->approx_constant) { it_arnoldi = lgmres->max_k - lgmres->aug_ct; } else { it_arnoldi = lgmres->max_k - lgmres->aug_dim; } if (it_arnoldi >= it +1) { it_aug = 0; it_arnoldi = it+1; } else { it_aug = (it + 1) - it_arnoldi; } /* now it_arnoldi indicates the number of matvecs that took place */ lgmres->matvecs += it_arnoldi; /* solve the upper triangular system - GRS is the right side and HH is the upper triangular matrix - put soln in nrs */ if (*HH(it,it) == 0.0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"HH(it,it) is identically zero; it = %D GRS(it) = %G",it,PetscAbsScalar(*GRS(it))); if (*HH(it,it) != 0.0) { nrs[it] = *GRS(it) / *HH(it,it); } else { nrs[it] = 0.0; } for (ii=1; ii<=it; ii++) { k = it - ii; tt = *GRS(k); for (j=k+1; j<=it; j++) tt = tt - *HH(k,j) * nrs[j]; nrs[k] = tt / *HH(k,k); } /* Accumulate the correction to the soln of the preconditioned prob. in VEC_TEMP */ ierr = VecSet(VEC_TEMP,0.0);CHKERRQ(ierr); /* set VEC_TEMP components to 0 */ /*LGMRES_MOD - if augmenting has happened we need to form the solution using the augvecs */ if (!it_aug) { /* all its are from arnoldi */ ierr = VecMAXPY(VEC_TEMP,it+1,nrs,&VEC_VV(0));CHKERRQ(ierr); } else { /*use aug vecs */ /*first do regular krylov directions */ ierr = VecMAXPY(VEC_TEMP,it_arnoldi,nrs,&VEC_VV(0));CHKERRQ(ierr); /*now add augmented portions - add contribution of aug vectors one at a time*/ for (ii=0; ii<it_aug; ii++) { for (jj=0; jj<lgmres->aug_dim; jj++) { if (lgmres->aug_order[jj] == (ii+1)) { spot = jj; break; /* must have this because there will be duplicates before aug_ct = aug_dim */ } } ierr = VecAXPY(VEC_TEMP,nrs[it_arnoldi+ii],AUGVEC(spot));CHKERRQ(ierr); } } /* now VEC_TEMP is what we want to keep for augmenting purposes - grab before the preconditioner is "unwound" from right-precondtioning*/ ierr = VecCopy(VEC_TEMP, AUG_TEMP);CHKERRQ(ierr); ierr = KSPUnwindPreconditioner(ksp,VEC_TEMP,VEC_TEMP_MATOP);CHKERRQ(ierr); /* add solution to previous solution */ /* put updated solution into vdest.*/ ierr = VecCopy(vguess,vdest);CHKERRQ(ierr); ierr = VecAXPY(vdest,1.0,VEC_TEMP);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPAGMRESBuildSoln(KSP ksp,PetscInt it) { KSP_AGMRES *agmres = (KSP_AGMRES*)ksp->data; PetscErrorCode ierr; PetscInt max_k = agmres->max_k; /* Size of the non-augmented Krylov basis */ PetscInt i, j; PetscInt r = agmres->r; /* current number of augmented eigenvectors */ PetscBLASInt KspSize; PetscBLASInt lC; PetscBLASInt N; PetscBLASInt ldH = N + 1; PetscBLASInt lwork; PetscBLASInt info, nrhs = 1; PetscFunctionBegin; ierr = PetscBLASIntCast(KSPSIZE,&KspSize);CHKERRQ(ierr); ierr = PetscBLASIntCast(4 * (KspSize+1),&lwork);CHKERRQ(ierr); ierr = PetscBLASIntCast(KspSize+1,&lC);CHKERRQ(ierr); ierr = PetscBLASIntCast(MAXKSPSIZE + 1,&N);CHKERRQ(ierr); ierr = PetscBLASIntCast(N + 1,&ldH);CHKERRQ(ierr); /* Save a copy of the Hessenberg matrix */ for (j = 0; j < N-1; j++) { for (i = 0; i < N; i++) { *HS(i,j) = *H(i,j); } } /* QR factorize the Hessenberg matrix */ #if defined(PETSC_MISSING_LAPACK_GEQRF) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"GEQRF - Lapack routine is unavailable."); #else PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&lC, &KspSize, agmres->hh_origin, &ldH, agmres->tau, agmres->work, &lwork, &info)); if (info) SETERRQ1(PetscObjectComm((PetscObject)ksp), PETSC_ERR_LIB,"Error in LAPACK routine XGEQRF INFO=%d", info); #endif /* Update the right hand side of the least square problem */ ierr = PetscMemzero(agmres->nrs, N*sizeof(PetscScalar));CHKERRQ(ierr); agmres->nrs[0] = ksp->rnorm; #if defined(PETSC_MISSING_LAPACK_ORMQR) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"GEQRF - Lapack routine is unavailable."); #else PetscStackCallBLAS("LAPACKormqr",LAPACKormqr_("L", "T", &lC, &nrhs, &KspSize, agmres->hh_origin, &ldH, agmres->tau, agmres->nrs, &N, agmres->work, &lwork, &info)); if (info) SETERRQ1(PetscObjectComm((PetscObject)ksp), PETSC_ERR_LIB,"Error in LAPACK routine XORMQR INFO=%d",info); #endif ksp->rnorm = PetscAbsScalar(agmres->nrs[KspSize]); /* solve the least-square problem */ #if defined(PETSC_MISSING_LAPACK_TRTRS) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"TRTRS - Lapack routine is unavailable."); #else PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U", "N", "N", &KspSize, &nrhs, agmres->hh_origin, &ldH, agmres->nrs, &N, &info)); if (info) SETERRQ1(PetscObjectComm((PetscObject)ksp), PETSC_ERR_LIB,"Error in LAPACK routine XTRTRS INFO=%d",info); #endif /* Accumulate the correction to the solution of the preconditioned problem in VEC_TMP */ ierr = VecZeroEntries(VEC_TMP);CHKERRQ(ierr); ierr = VecMAXPY(VEC_TMP, max_k, agmres->nrs, &VEC_V(0));CHKERRQ(ierr); if (!agmres->DeflPrecond) { ierr = VecMAXPY(VEC_TMP, r, &agmres->nrs[max_k], agmres->U);CHKERRQ(ierr); } if ((ksp->pc_side == PC_RIGHT) && agmres->r && agmres->DeflPrecond) { ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_TMP, VEC_TMP_MATOP);CHKERRQ(ierr); ierr = VecCopy(VEC_TMP_MATOP, VEC_TMP);CHKERRQ(ierr); } ierr = KSPUnwindPreconditioner(ksp, VEC_TMP, VEC_TMP_MATOP);CHKERRQ(ierr); /* add the solution to the previous one */ ierr = VecAXPY(ksp->vec_sol, 1.0, VEC_TMP);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode KSPSolve_TFQMR(KSP ksp) { PetscErrorCode ierr; PetscInt i,m; PetscScalar rho,rhoold,a,s,b,eta,etaold,psiold,cf; PetscReal dp,dpold,w,dpest,tau,psi,cm; Vec X,B,V,P,R,RP,T,T1,Q,U,D,AUQ; PetscFunctionBegin; X = ksp->vec_sol; B = ksp->vec_rhs; R = ksp->work[0]; RP = ksp->work[1]; V = ksp->work[2]; T = ksp->work[3]; Q = ksp->work[4]; P = ksp->work[5]; U = ksp->work[6]; D = ksp->work[7]; T1 = ksp->work[8]; AUQ = V; /* Compute initial preconditioned residual */ ierr = KSPInitialResidual(ksp,X,V,T,R,B);CHKERRQ(ierr); /* Test for nothing to do */ ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->rnorm = dp; ksp->its = 0; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); ierr = KSPMonitor(ksp,0,dp);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) PetscFunctionReturn(0); /* Make the initial Rp == R */ ierr = VecCopy(R,RP);CHKERRQ(ierr); /* Set the initial conditions */ etaold = 0.0; psiold = 0.0; tau = dp; dpold = dp; ierr = VecDot(R,RP,&rhoold);CHKERRQ(ierr); /* rhoold = (r,rp) */ ierr = VecCopy(R,U);CHKERRQ(ierr); ierr = VecCopy(R,P);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp,P,V,T);CHKERRQ(ierr); ierr = VecSet(D,0.0);CHKERRQ(ierr); i=0; do { ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->its++; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); ierr = VecDot(V,RP,&s);CHKERRQ(ierr); /* s <- (v,rp) */ a = rhoold / s; /* a <- rho / s */ ierr = VecWAXPY(Q,-a,V,U);CHKERRQ(ierr); /* q <- u - a v */ ierr = VecWAXPY(T,1.0,U,Q);CHKERRQ(ierr); /* t <- u + q */ ierr = KSP_PCApplyBAorAB(ksp,T,AUQ,T1);CHKERRQ(ierr); ierr = VecAXPY(R,-a,AUQ);CHKERRQ(ierr); /* r <- r - a K (u + q) */ ierr = VecNorm(R,NORM_2,&dp);CHKERRQ(ierr); for (m=0; m<2; m++) { if (!m) { w = PetscSqrtReal(dp*dpold); } else { w = dp; } psi = w / tau; cm = 1.0 / PetscSqrtReal(1.0 + psi * psi); tau = tau * psi * cm; eta = cm * cm * a; cf = psiold * psiold * etaold / a; if (!m) { ierr = VecAYPX(D,cf,U);CHKERRQ(ierr); } else { ierr = VecAYPX(D,cf,Q);CHKERRQ(ierr); } ierr = VecAXPY(X,eta,D);CHKERRQ(ierr); dpest = PetscSqrtReal(m + 1.0) * tau; ierr = PetscObjectTakeAccess(ksp);CHKERRQ(ierr); ksp->rnorm = dpest; ierr = PetscObjectGrantAccess(ksp);CHKERRQ(ierr); KSPLogResidualHistory(ksp,dpest); ierr = KSPMonitor(ksp,i+1,dpest);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i+1,dpest,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; etaold = eta; psiold = psi; } if (ksp->reason) break; ierr = VecDot(R,RP,&rho);CHKERRQ(ierr); /* rho <- (r,rp) */ b = rho / rhoold; /* b <- rho / rhoold */ ierr = VecWAXPY(U,b,Q,R);CHKERRQ(ierr); /* u <- r + b q */ ierr = VecAXPY(Q,b,P);CHKERRQ(ierr); ierr = VecWAXPY(P,b,Q,U);CHKERRQ(ierr); /* p <- u + b(q + b p) */ ierr = KSP_PCApplyBAorAB(ksp,P,V,Q);CHKERRQ(ierr); /* v <- K p */ rhoold = rho; dpold = dp; i++; } while (i<ksp->max_it); if (i >= ksp->max_it) { ksp->reason = KSP_DIVERGED_ITS; } ierr = KSPUnwindPreconditioner(ksp,X,T);CHKERRQ(ierr); PetscFunctionReturn(0); }