static PetscErrorCode KSPSolve_AGMRES(KSP ksp) { PetscErrorCode ierr; PetscInt its; KSP_AGMRES *agmres = (KSP_AGMRES*)ksp->data; PetscBool guess_zero = ksp->guess_zero; PetscReal res_old, res; PetscInt test; PetscFunctionBegin; ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its = 0; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->reason = KSP_CONVERGED_ITERATING; if (!agmres->HasShifts) { /* Compute Shifts for the Newton basis */ ierr = KSPComputeShifts_DGMRES(ksp);CHKERRQ(ierr); } /* NOTE: At this step, the initial guess is not equal to zero since one cycle of the classical GMRES is performed to compute the shifts */ ierr = (*ksp->converged)(ksp,0,ksp->rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); while (!ksp->reason) { ierr = KSPInitialResidual(ksp,ksp->vec_sol,VEC_TMP,VEC_TMP_MATOP,VEC_V(0),ksp->vec_rhs);CHKERRQ(ierr); if ((ksp->pc_side == PC_LEFT) && agmres->r && agmres->DeflPrecond) { ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_V(0), VEC_TMP);CHKERRQ(ierr); ierr = VecCopy(VEC_TMP, VEC_V(0));CHKERRQ(ierr); agmres->matvecs += 1; } ierr = VecNormalize(VEC_V(0),&(ksp->rnorm));CHKERRQ(ierr); KSPCheckNorm(ksp,ksp->rnorm); res_old = ksp->rnorm; /* Record the residual norm to test if deflation is needed */ ksp->ops->buildsolution = KSPBuildSolution_AGMRES; ierr = KSPAGMRESCycle(&its,ksp);CHKERRQ(ierr); if (ksp->its >= ksp->max_it) { if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS; break; } /* compute the eigenvectors to augment the subspace : use an adaptive strategy */ res = ksp->rnorm; if (!ksp->reason && agmres->neig > 0) { test = agmres->max_k * PetscLogReal(ksp->rtol/res) / PetscLogReal(res/res_old); /* estimate the remaining number of steps */ if ((test > agmres->smv*(ksp->max_it-ksp->its)) || agmres->force) { if (!agmres->force && ((test > agmres->bgv*(ksp->max_it-ksp->its)) && ((agmres->r + 1) < agmres->max_neig))) { agmres->neig += 1; /* Augment the number of eigenvalues to deflate if the convergence is too slow */ } ierr = KSPDGMRESComputeDeflationData_DGMRES(ksp,&agmres->neig);CHKERRQ(ierr); } } ksp->guess_zero = PETSC_FALSE; /* every future call to KSPInitialResidual() will have nonzero guess */ } ksp->guess_zero = guess_zero; /* restore if user has provided nonzero initial guess */ 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 KSPAGMRESBuildBasis(KSP ksp) { PetscErrorCode ierr; KSP_AGMRES *agmres = (KSP_AGMRES*)ksp->data; PetscReal *Rshift = agmres->Rshift; PetscReal *Ishift = agmres->Ishift; PetscReal *Scale = agmres->Scale; PetscInt max_k = agmres->max_k; PetscInt KspSize = KSPSIZE; /* if max_k == KspSizen then the basis should not be augmented */ PetscInt j = 1; PetscFunctionBegin; ierr = PetscLogEventBegin(KSP_AGMRESBuildBasis, ksp, 0,0,0);CHKERRQ(ierr); Scale[0] = 1.0; while (j <= max_k) { if (Ishift[j-1] == 0) { if ((ksp->pc_side == PC_LEFT) && agmres->r && agmres->DeflPrecond) { /* Apply the precond-matrix operators */ ierr = KSP_PCApplyBAorAB(ksp, VEC_V(j-1), VEC_TMP, VEC_TMP_MATOP);CHKERRQ(ierr); /* Then apply deflation as a preconditioner */ ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_TMP, VEC_V(j));CHKERRQ(ierr); } else if ((ksp->pc_side == PC_RIGHT) && agmres->r && agmres->DeflPrecond) { ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_V(j-1), VEC_TMP);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp, VEC_TMP, VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); } else { ierr = KSP_PCApplyBAorAB(ksp, VEC_V(j-1), VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); } ierr = VecAXPY(VEC_V(j), -Rshift[j-1], VEC_V(j-1));CHKERRQ(ierr); #if defined(KSP_AGMRES_NONORM) Scale[j] = 1.0; #else ierr = VecScale(VEC_V(j), Scale[j-1]);CHKERRQ(ierr); /* This step can be postponed until all vectors are built */ ierr = VecNorm(VEC_V(j), NORM_2, &(Scale[j]));CHKERRQ(ierr); Scale[j] = 1.0/Scale[j]; #endif agmres->matvecs += 1; j++; } else { if ((ksp->pc_side == PC_LEFT) && agmres->r && agmres->DeflPrecond) { /* Apply the precond-matrix operators */ ierr = KSP_PCApplyBAorAB(ksp, VEC_V(j-1), VEC_TMP, VEC_TMP_MATOP);CHKERRQ(ierr); /* Then apply deflation as a preconditioner */ ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_TMP, VEC_V(j));CHKERRQ(ierr); } else if ((ksp->pc_side == PC_RIGHT) && agmres->r && agmres->DeflPrecond) { ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_V(j-1), VEC_TMP);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp, VEC_TMP, VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); } else { ierr = KSP_PCApplyBAorAB(ksp, VEC_V(j-1), VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); } ierr = VecAXPY(VEC_V(j), -Rshift[j-1], VEC_V(j-1));CHKERRQ(ierr); #if defined(KSP_AGMRES_NONORM) Scale[j] = 1.0; #else ierr = VecScale(VEC_V(j), Scale[j-1]);CHKERRQ(ierr); ierr = VecNorm(VEC_V(j), NORM_2, &(Scale[j]));CHKERRQ(ierr); Scale[j] = 1.0/Scale[j]; #endif agmres->matvecs += 1; j++; if ((ksp->pc_side == PC_LEFT) && agmres->r && agmres->DeflPrecond) { /* Apply the precond-matrix operators */ ierr = KSP_PCApplyBAorAB(ksp, VEC_V(j-1), VEC_TMP, VEC_TMP_MATOP);CHKERRQ(ierr); /* Then apply deflation as a preconditioner */ ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_TMP, VEC_V(j));CHKERRQ(ierr); } else if ((ksp->pc_side == PC_RIGHT) && agmres->r && agmres->DeflPrecond) { ierr = KSPDGMRESApplyDeflation_DGMRES(ksp, VEC_V(j-1), VEC_TMP);CHKERRQ(ierr); ierr = KSP_PCApplyBAorAB(ksp, VEC_TMP, VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); } else { ierr = KSP_PCApplyBAorAB(ksp, VEC_V(j-1), VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); } ierr = VecAXPY(VEC_V(j), -Rshift[j-2], VEC_V(j-1));CHKERRQ(ierr); ierr = VecAXPY(VEC_V(j), Scale[j-2]*Ishift[j-2]*Ishift[j-2], VEC_V(j-2));CHKERRQ(ierr); #if defined(KSP_AGMRES_NONORM) Scale[j] = 1.0; #else ierr = VecNorm(VEC_V(j), NORM_2, &(Scale[j]));CHKERRQ(ierr); Scale[j] = 1.0/Scale[j]; #endif agmres->matvecs += 1; j++; } } /* Augment the subspace with the eigenvectors*/ while (j <= KspSize) { ierr = KSP_PCApplyBAorAB(ksp, agmres->U[j - max_k - 1], VEC_V(j), VEC_TMP_MATOP);CHKERRQ(ierr); #if defined(KSP_AGMRES_NONORM) Scale[j] = 1.0; #else ierr = VecScale(VEC_V(j), Scale[j-1]);CHKERRQ(ierr); ierr = VecNorm(VEC_V(j), NORM_2, &(Scale[j]));CHKERRQ(ierr); Scale[j] = 1.0/Scale[j]; #endif agmres->matvecs += 1; j++; } ierr = PetscLogEventEnd(KSP_AGMRESBuildBasis, ksp, 0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }