PETSC_EXTERN void PETSC_STDCALL petscobjectgetid_(PetscObject obj,PetscObjectId *id, int *__ierr ){ *__ierr = PetscObjectGetId( (PetscObject)PetscToPointer((obj) ), (PetscObjectId* )PetscToPointer((id) )); }
static PetscErrorCode KSPSolve_Chebyshev(KSP ksp) { KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data; PetscErrorCode ierr; PetscInt k,kp1,km1,maxit,ktmp,i; PetscScalar alpha,omegaprod,mu,omega,Gamma,c[3],scale; PetscReal rnorm = 0.0; Vec sol_orig,b,p[3],r; Mat Amat,Pmat; PetscBool diagonalscale; PetscFunctionBegin; 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); ierr = PCGetOperators(ksp->pc,&Amat,&Pmat);CHKERRQ(ierr); if (cheb->kspest) { PetscObjectId amatid, pmatid; PetscObjectState amatstate, pmatstate; ierr = PetscObjectGetId((PetscObject)Amat,&amatid);CHKERRQ(ierr); ierr = PetscObjectGetId((PetscObject)Pmat,&pmatid);CHKERRQ(ierr); ierr = PetscObjectStateGet((PetscObject)Amat,&amatstate);CHKERRQ(ierr); ierr = PetscObjectStateGet((PetscObject)Pmat,&pmatstate);CHKERRQ(ierr); if (amatid != cheb->amatid || pmatid != cheb->pmatid || amatstate != cheb->amatstate || pmatstate != cheb->pmatstate) { PetscReal max=0.0,min=0.0; Vec B; KSPConvergedReason reason; if (cheb->userandom) { B = ksp->work[1]; if (!cheb->random) { ierr = PetscRandomCreate(PetscObjectComm((PetscObject)B),&cheb->random);CHKERRQ(ierr); } ierr = VecSetRandom(B,cheb->random);CHKERRQ(ierr); } else { B = ksp->vec_rhs; } ierr = KSPSolve(cheb->kspest,B,ksp->work[0]);CHKERRQ(ierr); ierr = KSPGetConvergedReason(cheb->kspest,&reason);CHKERRQ(ierr); if (reason < 0) { if (reason == KSP_DIVERGED_ITS) { ierr = PetscInfo(ksp,"Eigen estimator ran for prescribed number of iterations\n");CHKERRQ(ierr); } else { PetscInt its; ierr = KSPGetIterationNumber(cheb->kspest,&its);CHKERRQ(ierr); SETERRQ2(PetscObjectComm((PetscObject)ksp),PETSC_ERR_PLIB,"Eigen estimator failed: %s at iteration %D",KSPConvergedReasons[reason],its); } } else if (reason==KSP_CONVERGED_RTOL ||reason==KSP_CONVERGED_ATOL) { ierr = PetscInfo(ksp,"Eigen estimator converged prematurely. Should not happen except for small or low rank problem\n");CHKERRQ(ierr); } else { ierr = PetscInfo1(ksp,"Eigen estimator did not converge by iteration: %s\n",KSPConvergedReasons[reason]);CHKERRQ(ierr); } ierr = KSPChebyshevComputeExtremeEigenvalues_Private(cheb->kspest,&min,&max);CHKERRQ(ierr); cheb->emin = cheb->tform[0]*min + cheb->tform[1]*max; cheb->emax = cheb->tform[2]*min + cheb->tform[3]*max; cheb->amatid = amatid; cheb->pmatid = pmatid; cheb->amatstate = amatstate; cheb->pmatstate = pmatstate; } } ksp->its = 0; maxit = ksp->max_it; /* These three point to the three active solutions, we rotate these three at each solution update */ km1 = 0; k = 1; kp1 = 2; sol_orig = ksp->vec_sol; /* ksp->vec_sol will be asigned to rotating vector p[k], thus save its address */ b = ksp->vec_rhs; p[km1] = sol_orig; p[k] = ksp->work[0]; p[kp1] = ksp->work[1]; r = ksp->work[2]; /* use scale*B as our preconditioner */ scale = 2.0/(cheb->emax + cheb->emin); /* -alpha <= scale*lambda(B^{-1}A) <= alpha */ alpha = 1.0 - scale*(cheb->emin); Gamma = 1.0; mu = 1.0/alpha; omegaprod = 2.0/alpha; c[km1] = 1.0; c[k] = mu; if (!ksp->guess_zero) { ierr = KSP_MatMult(ksp,Amat,p[km1],r);CHKERRQ(ierr); /* r = b - A*p[km1] */ ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); } else { ierr = VecCopy(b,r);CHKERRQ(ierr); } ierr = KSP_PCApply(ksp,r,p[k]);CHKERRQ(ierr); /* p[k] = scale B^{-1}r + p[km1] */ ierr = VecAYPX(p[k],scale,p[km1]);CHKERRQ(ierr); for (i=0; i<maxit; i++) { ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->its++; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); c[kp1] = 2.0*mu*c[k] - c[km1]; omega = omegaprod*c[k]/c[kp1]; ierr = KSP_MatMult(ksp,Amat,p[k],r);CHKERRQ(ierr); /* r = b - Ap[k] */ ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); ierr = KSP_PCApply(ksp,r,p[kp1]);CHKERRQ(ierr); /* p[kp1] = B^{-1}r */ ksp->vec_sol = p[k]; /* calculate residual norm if requested */ if (ksp->normtype != KSP_NORM_NONE || ksp->numbermonitors) { if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNorm(r,NORM_2,&rnorm);CHKERRQ(ierr); } else { ierr = VecNorm(p[kp1],NORM_2,&rnorm);CHKERRQ(ierr); } ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->rnorm = rnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ierr = KSPLogResidualHistory(ksp,rnorm);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i,rnorm);CHKERRQ(ierr); ierr = (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (ksp->reason) break; } /* y^{k+1} = omega(y^{k} - y^{k-1} + Gamma*r^{k}) + y^{k-1} */ ierr = VecAXPBYPCZ(p[kp1],1.0-omega,omega,omega*Gamma*scale,p[km1],p[k]);CHKERRQ(ierr); ktmp = km1; km1 = k; k = kp1; kp1 = ktmp; } if (!ksp->reason) { if (ksp->normtype != KSP_NORM_NONE) { ierr = KSP_MatMult(ksp,Amat,p[k],r);CHKERRQ(ierr); /* r = b - Ap[k] */ ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) { ierr = VecNorm(r,NORM_2,&rnorm);CHKERRQ(ierr); } else { ierr = KSP_PCApply(ksp,r,p[kp1]);CHKERRQ(ierr); /* p[kp1] = B^{-1}r */ ierr = VecNorm(p[kp1],NORM_2,&rnorm);CHKERRQ(ierr); } ierr = PetscObjectSAWsTakeAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->rnorm = rnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)ksp);CHKERRQ(ierr); ksp->vec_sol = p[k]; ierr = KSPLogResidualHistory(ksp,rnorm);CHKERRQ(ierr); ierr = KSPMonitor(ksp,i,rnorm);CHKERRQ(ierr); } if (ksp->its >= ksp->max_it) { if (ksp->normtype != KSP_NORM_NONE) { ierr = (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);CHKERRQ(ierr); if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS; } else ksp->reason = KSP_CONVERGED_ITS; } } /* make sure solution is in vector x */ ksp->vec_sol = sol_orig; if (k) { ierr = VecCopy(p[k],sol_orig);CHKERRQ(ierr); } PetscFunctionReturn(0); }