/* Helper rutine to handle user postenvents and recording */ static PetscErrorCode TSPostEvent(TS ts,PetscReal t,Vec U) { PetscErrorCode ierr; TSEvent event = ts->event; PetscBool terminate = PETSC_FALSE; PetscBool restart = PETSC_FALSE; PetscInt i,ctr,stepnum; PetscBool inflag[2],outflag[2]; PetscBool forwardsolve = PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */ PetscFunctionBegin; if (event->postevent) { PetscObjectState state_prev,state_post; ierr = PetscObjectStateGet((PetscObject)U,&state_prev);CHKERRQ(ierr); ierr = (*event->postevent)(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->ctx);CHKERRQ(ierr); ierr = PetscObjectStateGet((PetscObject)U,&state_post);CHKERRQ(ierr); if (state_prev != state_post) restart = PETSC_TRUE; } /* Handle termination events and step restart */ for (i=0; i<event->nevents_zero; i++) if (event->terminate[event->events_zero[i]]) terminate = PETSC_TRUE; inflag[0] = restart; inflag[1] = terminate; ierr = MPIU_Allreduce(inflag,outflag,2,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr); restart = outflag[0]; terminate = outflag[1]; if (restart) {ierr = TSRestartStep(ts);CHKERRQ(ierr);} if (terminate) {ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);} event->status = terminate ? TSEVENT_NONE : TSEVENT_RESET_NEXTSTEP; /* Reset event residual functions as states might get changed by the postevent callback */ if (event->postevent) { ierr = VecLockPush(U);CHKERRQ(ierr); ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); ierr = VecLockPop(U);CHKERRQ(ierr); } /* Cache current time and event residual functions */ event->ptime_prev = t; for (i=0; i<event->nevents; i++) event->fvalue_prev[i] = event->fvalue[i]; /* Record the event in the event recorder */ ierr = TSGetStepNumber(ts,&stepnum);CHKERRQ(ierr); ctr = event->recorder.ctr; if (ctr == event->recsize) { ierr = TSEventRecorderResize(event);CHKERRQ(ierr); } event->recorder.time[ctr] = t; event->recorder.stepnum[ctr] = stepnum; event->recorder.nevents[ctr] = event->nevents_zero; for (i=0; i<event->nevents_zero; i++) event->recorder.eventidx[ctr][i] = event->events_zero[i]; event->recorder.ctr++; PetscFunctionReturn(0); }
static PetscErrorCode PCSetUp_ILU(PC pc) { PetscErrorCode ierr; PC_ILU *ilu = (PC_ILU*)pc->data; MatInfo info; PetscBool flg; const MatSolverPackage stype; MatFactorError err; PetscFunctionBegin; pc->failedreason = PC_NOERROR; /* ugly hack to change default, since it is not support by some matrix types */ if (((PC_Factor*)ilu)->info.shifttype == (PetscReal)MAT_SHIFT_NONZERO) { ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJ,&flg);CHKERRQ(ierr); if (!flg) { ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&flg);CHKERRQ(ierr); if (!flg) { ((PC_Factor*)ilu)->info.shifttype = (PetscReal)MAT_SHIFT_INBLOCKS; PetscInfo(pc,"Changing shift type from NONZERO to INBLOCKS because block matrices do not support NONZERO\n");CHKERRQ(ierr); } } } ierr = MatSetErrorIfFailure(pc->pmat,pc->erroriffailure);CHKERRQ(ierr); if (ilu->hdr.inplace) { if (!pc->setupcalled) { /* In-place factorization only makes sense with the natural ordering, so we only need to get the ordering once, even if nonzero structure changes */ ierr = MatGetOrdering(pc->pmat,((PC_Factor*)ilu)->ordering,&ilu->row,&ilu->col);CHKERRQ(ierr); if (ilu->row) {ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilu->row);CHKERRQ(ierr);} if (ilu->col) {ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilu->col);CHKERRQ(ierr);} } /* In place ILU only makes sense with fill factor of 1.0 because cannot have levels of fill */ ((PC_Factor*)ilu)->info.fill = 1.0; ((PC_Factor*)ilu)->info.diagonal_fill = 0.0; ierr = MatILUFactor(pc->pmat,ilu->row,ilu->col,&((PC_Factor*)ilu)->info);CHKERRQ(ierr);CHKERRQ(ierr); ierr = MatFactorGetError(pc->pmat,&err);CHKERRQ(ierr); if (err) { /* Factor() fails */ pc->failedreason = (PCFailedReason)err; PetscFunctionReturn(0); } ((PC_Factor*)ilu)->fact = pc->pmat; /* must update the pc record of the matrix state or the PC will attempt to run PCSetUp() yet again */ ierr = PetscObjectStateGet((PetscObject)pc->pmat,&pc->matstate);CHKERRQ(ierr); } else { if (!pc->setupcalled) { /* first time in so compute reordering and symbolic factorization */ ierr = MatGetOrdering(pc->pmat,((PC_Factor*)ilu)->ordering,&ilu->row,&ilu->col);CHKERRQ(ierr); if (ilu->row) {ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilu->row);CHKERRQ(ierr);} if (ilu->col) {ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilu->col);CHKERRQ(ierr);} /* Remove zeros along diagonal? */ if (ilu->nonzerosalongdiagonal) { ierr = MatReorderForNonzeroDiagonal(pc->pmat,ilu->nonzerosalongdiagonaltol,ilu->row,ilu->col);CHKERRQ(ierr); } if (!((PC_Factor*)ilu)->fact) { ierr = MatGetFactor(pc->pmat,((PC_Factor*)ilu)->solvertype,MAT_FACTOR_ILU,&((PC_Factor*)ilu)->fact);CHKERRQ(ierr); } ierr = MatILUFactorSymbolic(((PC_Factor*)ilu)->fact,pc->pmat,ilu->row,ilu->col,&((PC_Factor*)ilu)->info);CHKERRQ(ierr); ierr = MatGetInfo(((PC_Factor*)ilu)->fact,MAT_LOCAL,&info);CHKERRQ(ierr); ilu->hdr.actualfill = info.fill_ratio_needed; ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)((PC_Factor*)ilu)->fact);CHKERRQ(ierr); } else if (pc->flag != SAME_NONZERO_PATTERN) { if (!ilu->hdr.reuseordering) { /* compute a new ordering for the ILU */ ierr = ISDestroy(&ilu->row);CHKERRQ(ierr); ierr = ISDestroy(&ilu->col);CHKERRQ(ierr); ierr = MatGetOrdering(pc->pmat,((PC_Factor*)ilu)->ordering,&ilu->row,&ilu->col);CHKERRQ(ierr); if (ilu->row) {ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilu->row);CHKERRQ(ierr);} if (ilu->col) {ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilu->col);CHKERRQ(ierr);} /* Remove zeros along diagonal? */ if (ilu->nonzerosalongdiagonal) { ierr = MatReorderForNonzeroDiagonal(pc->pmat,ilu->nonzerosalongdiagonaltol,ilu->row,ilu->col);CHKERRQ(ierr); } } ierr = MatDestroy(&((PC_Factor*)ilu)->fact);CHKERRQ(ierr); ierr = MatGetFactor(pc->pmat,((PC_Factor*)ilu)->solvertype,MAT_FACTOR_ILU,&((PC_Factor*)ilu)->fact);CHKERRQ(ierr); ierr = MatILUFactorSymbolic(((PC_Factor*)ilu)->fact,pc->pmat,ilu->row,ilu->col,&((PC_Factor*)ilu)->info);CHKERRQ(ierr); ierr = MatGetInfo(((PC_Factor*)ilu)->fact,MAT_LOCAL,&info);CHKERRQ(ierr); ilu->hdr.actualfill = info.fill_ratio_needed; ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)((PC_Factor*)ilu)->fact);CHKERRQ(ierr); } ierr = MatFactorGetError(((PC_Factor*)ilu)->fact,&err);CHKERRQ(ierr); if (err) { /* FactorSymbolic() fails */ pc->failedreason = (PCFailedReason)err; PetscFunctionReturn(0); } ierr = MatLUFactorNumeric(((PC_Factor*)ilu)->fact,pc->pmat,&((PC_Factor*)ilu)->info);CHKERRQ(ierr); ierr = MatFactorGetError(((PC_Factor*)ilu)->fact,&err);CHKERRQ(ierr); if (err) { /* FactorNumeric() fails */ pc->failedreason = (PCFailedReason)err; } } ierr = PCFactorGetMatSolverPackage(pc,&stype);CHKERRQ(ierr); if (!stype) { const MatSolverPackage solverpackage; ierr = MatFactorGetSolverPackage(((PC_Factor*)ilu)->fact,&solverpackage);CHKERRQ(ierr); ierr = PCFactorSetMatSolverPackage(pc,solverpackage);CHKERRQ(ierr); } PetscFunctionReturn(0); }
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); }