<div dir="ltr">Suppose I want to solve a finite time step problem using FAS. The time step will be defined something like<div><div><br></div><div>static PetscErrorCode SNESTSFormFunction_ARKIMEX(SNES snes,Vec X,Vec F,TS ts)</div>
<div>{</div><div>  TS_ARKIMEX     *ark = (TS_ARKIMEX*)ts->data;</div><div>  PetscErrorCode ierr;</div><div><br></div><div>  PetscFunctionBegin;</div><div>  ierr = VecAXPBYPCZ(ark->Ydot,-ark->shift,ark->shift,0,ark->Z,X);CHKERRQ(ierr); /* Ydot = shift*(X-Z) */</div>
<div>  ierr = TSComputeIFunction(ts,ark->stage_time,X,ark->Ydot,F,ark->imex);CHKERRQ(ierr);</div><div>  PetscFunctionReturn(0);</div><div>}</div></div><div><br></div><div><br></div><div>where ark->Z was determined from previous stages and ark->Ydot is a work vector. So FAS creates some hierarchy, but it isn't very forthcoming about showing the hierarchy to the user. But I need a way to</div>
<div><br></div><div>1. Restrict ark->Z to the coarse level and obtain the work vector ark->Ydot somewhere that I can reuse it. The user might also have to restrict "auxiliary" variables to coarse grids. It's conceivable that they would want to do this in a different way from the restriction/prolongation for the solution variables. For example, if you were using upwinded R and P for a hyperbolic problem, but you needed to restrict coefficients (like bathymetry). Or they might want to sample differently out of some file. So I think we need an auxiliary transfer callback that is at least called every top-level SNESSolve() and optionally also called in every transfer (because it could be homogenizing coefficient structure that is a nonlinear function of state).</div>
<div><br></div><div>2. Put the DM from this SNES into the TS that calls the user's IFunction. The easiest way is to have TSPushDM(TS,DM) that just jams it in there, caching the old DM (so the user's call to TSGetDM() works correctly), and TSPopDM(TS). This is ugly and is scary if the user does something weird like TSGetSolution() (returning the state at the beginning of the step, not the current value at the stage). This is something that doesn't make semantic sense except maybe if they have some weird diagnostics, but TSGetIJacobian() might be used for caching, and I'm scared of the semantics it would involve to support this sort of caching.</div>
<div><br></div><div>The alternative is to make different TSs for each level and somehow locate the correct TS (maybe cache it in the SNES hierarchy). I think this could be quite confusing to restrict all the members to the coarse grid. But having a multi-level TS object may eventually be sensible because multilevel time integration schemes exist. Spectral deferred correction is one example where coarse grids (in space and time) can be used to accelerate convergence to a high-order solution. But these somewhat naturally expose additional parallelism in time (usually more communication, but also more concurrency), so it likely needs a more complete solution that includes ways to instantiate entire models on sub-communicators (we'll also want an interface of this type for UQ).</div>
<div><br></div><div><br></div><div>Preferences or suggestions?</div></div>