PetscErrorCode TSMonitorSPEig(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx) { TSMonitorSPEigCtx ctx = (TSMonitorSPEigCtx) monctx; PetscErrorCode ierr; KSP ksp = ctx->ksp; PetscInt n,N,nits,neig,i,its = 200; PetscReal *r,*c,time_step_save; PetscDrawSP drawsp = ctx->drawsp; Mat A,B; Vec xdot; SNES snes; PetscFunctionBegin; if (!step) PetscFunctionReturn(0); if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) { ierr = VecDuplicate(v,&xdot);CHKERRQ(ierr); ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = SNESGetJacobian(snes,&A,&B,NULL,NULL);CHKERRQ(ierr); ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&B);CHKERRQ(ierr); /* This doesn't work because methods keep and use internal information about the shift so it seems we would need code for each method to trick the correct Jacobian in being computed. */ time_step_save = ts->time_step; ts->time_step = PETSC_MAX_REAL; ierr = SNESComputeJacobian(snes,v,A,B);CHKERRQ(ierr); ts->time_step = time_step_save; ierr = KSPSetOperators(ksp,B,B);CHKERRQ(ierr); ierr = VecGetSize(v,&n);CHKERRQ(ierr); if (n < 200) its = n; ierr = KSPSetTolerances(ksp,1.e-10,PETSC_DEFAULT,PETSC_DEFAULT,its);CHKERRQ(ierr); ierr = VecSetRandom(xdot,ctx->rand);CHKERRQ(ierr); ierr = KSPSolve(ksp,xdot,xdot);CHKERRQ(ierr); ierr = VecDestroy(&xdot);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&nits);CHKERRQ(ierr); N = nits+2; if (nits) { PetscDraw draw; PetscReal pause; PetscDrawAxis axis; PetscReal xmin,xmax,ymin,ymax; ierr = PetscDrawSPReset(drawsp);CHKERRQ(ierr); ierr = PetscDrawSPSetLimits(drawsp,ctx->xmin,ctx->xmax,ctx->ymin,ctx->ymax);CHKERRQ(ierr); ierr = PetscMalloc2(PetscMax(n,N),&r,PetscMax(n,N),&c);CHKERRQ(ierr); if (ctx->computeexplicitly) { ierr = KSPComputeEigenvaluesExplicitly(ksp,n,r,c);CHKERRQ(ierr); neig = n; } else { ierr = KSPComputeEigenvalues(ksp,N,r,c,&neig);CHKERRQ(ierr); } /* We used the positive operator to be able to reuse KSPs that require positive definiteness, now flip the spectrum as is conventional for ODEs */ for (i=0; i<neig; i++) r[i] = -r[i]; for (i=0; i<neig; i++) { if (ts->ops->linearstability) { PetscReal fr,fi; ierr = TSComputeLinearStability(ts,r[i],c[i],&fr,&fi);CHKERRQ(ierr); if ((fr*fr + fi*fi) > 1.0) { ierr = PetscPrintf(ctx->comm,"Linearized Eigenvalue %g + %g i linear stability function %g norm indicates unstable scheme \n",(double)r[i],(double)c[i],(double)(fr*fr + fi*fi));CHKERRQ(ierr); } } ierr = PetscDrawSPAddPoint(drawsp,r+i,c+i);CHKERRQ(ierr); } ierr = PetscFree2(r,c);CHKERRQ(ierr); ierr = PetscDrawSPGetDraw(drawsp,&draw);CHKERRQ(ierr); ierr = PetscDrawGetPause(draw,&pause);CHKERRQ(ierr); ierr = PetscDrawSetPause(draw,0.0);CHKERRQ(ierr); ierr = PetscDrawSPDraw(drawsp,PETSC_TRUE);CHKERRQ(ierr); ierr = PetscDrawSetPause(draw,pause);CHKERRQ(ierr); if (ts->ops->linearstability) { ierr = PetscDrawSPGetAxis(drawsp,&axis);CHKERRQ(ierr); ierr = PetscDrawAxisGetLimits(axis,&xmin,&xmax,&ymin,&ymax);CHKERRQ(ierr); ierr = PetscDrawIndicatorFunction(draw,xmin,xmax,ymin,ymax,PETSC_DRAW_CYAN,(PetscErrorCode (*)(void*,PetscReal,PetscReal,PetscBool*))TSLinearStabilityIndicator,ts);CHKERRQ(ierr); ierr = PetscDrawSPDraw(drawsp,PETSC_FALSE);CHKERRQ(ierr); } } ierr = MatDestroy(&B);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL kspcomputeeigenvaluesexplicitly_(KSP ksp,PetscInt *nmax,PetscReal r[],PetscReal c[], int *__ierr ){ *__ierr = KSPComputeEigenvaluesExplicitly( (KSP)PetscToPointer((ksp) ),*nmax,r,c); }