I checked out branch barry/fix-huge-flaw-in-ts
<https://bitbucket.org/petsc/petsc/branch/barry/fix-huge-flaw-in-ts> (see
pull request #655) and reconfigured and rebuilt.
No, the ts/.../ex2.c example is not fixed. It gives same error:
~/petsc/src/ts/examples/tutorials[barry/fix-huge-flaw-in-ts*]$ ./ex2 -ts_dt
0.001 -ts_final_time 0.001 -snes_monitor -snes_mf_operator
0 SNES Function norm 1.059316422854e+01
[0]PETSC ERROR: --------------------- Error Message
--------------------------------------------------------------
[0]PETSC ERROR: No support for this operation for this object type
[0]PETSC ERROR: Mat type mffd
[0]PETSC ERROR: See http://www.mcs.anl.gov/petsc/documentation/faq.html for
trouble shooting.
[0]PETSC ERROR: Petsc Development GIT revision: v3.7.5-3346-g41a1d4d GIT
Date: 2017-03-24 14:39:28 -0500
[0]PETSC ERROR: ./ex2 on a linux-c-dbg named bueler-leopard by ed Sun Apr
2 18:31:55 2017
[0]PETSC ERROR: Configure options --download-mpich --with-debugging=1
[0]PETSC ERROR: #1 MatZeroEntries() line 5471 in
/home/ed/petsc/src/mat/interface/matrix.c
[0]PETSC ERROR: #2 TSComputeIJacobian() line 942 in
/home/ed/petsc/src/ts/interface/ts.c
[0]PETSC ERROR: #3 SNESTSFormJacobian_Theta() line 515 in
/home/ed/petsc/src/ts/impls/implicit/theta/theta.c
[0]PETSC ERROR: #4 SNESTSFormJacobian() line 5055 in
/home/ed/petsc/src/ts/interface/ts.c
[0]PETSC ERROR: #5 SNESComputeJacobian() line 2276 in
/home/ed/petsc/src/snes/interface/snes.c
[0]PETSC ERROR: #6 SNESSolve_NEWTONLS() line 222 in
/home/ed/petsc/src/snes/impls/ls/ls.c
[0]PETSC ERROR: #7 SNESSolve() line 3967 in
/home/ed/petsc/src/snes/interface/snes.c
[0]PETSC ERROR: #8 TS_SNESSolve() line 171 in
/home/ed/petsc/src/ts/impls/implicit/theta/theta.c
[0]PETSC ERROR: #9 TSStep_Theta() line 211 in
/home/ed/petsc/src/ts/impls/implicit/theta/theta.c
[0]PETSC ERROR: #10 TSStep() line 3820 in
/home/ed/petsc/src/ts/interface/ts.c
[0]PETSC ERROR: #11 TSSolve() line 4065 in
/home/ed/petsc/src/ts/interface/ts.c
[0]PETSC ERROR: #12 main() line 194 in
/home/ed/petsc/src/ts/examples/tutorials/ex2.c
[0]PETSC ERROR: PETSc Option Table entries:
[0]PETSC ERROR: -snes_mf_operator
[0]PETSC ERROR: -snes_monitor
[0]PETSC ERROR: -ts_dt 0.001
[0]PETSC ERROR: -ts_final_time 0.001
[0]PETSC ERROR: ----------------End of Error Message -------send entire
error message to [email protected]
application called MPI_Abort(MPI_COMM_WORLD, 56) - process 0
[unset]: aborting job:
application called MPI_Abort(MPI_COMM_WORLD, 56) - process 0
Curiously, my own code (attached), which differs from ex2.c in that it uses
DMDA, *does* change behavior to a DIVERGED_NONLINEAR_SOLVE error:
$ ./advect -da_refine 0 -ts_monitor -adv_circlewind -adv_conex 0.3
-adv_coney 0.3 -ts_type beuler -snes_monitor_short -ts_final_time 0.01
-ts_dt 0.01 -snes_rtol 1.0e-4 -adv_firstorder -snes_mf_operator
solving on 5 x 5 grid with dx=0.2 x dy=0.2 cells, t0=0.,
and initial step dt=0.01 ...
0 TS dt 0.01 time 0.
0 SNES Function norm 2.1277
[0]PETSC ERROR: --------------------- Error Message
--------------------------------------------------------------
[0]PETSC ERROR:
[0]PETSC ERROR: TSStep has failed due to DIVERGED_NONLINEAR_SOLVE, increase
-ts_max_snes_failures or make negative to attempt recovery
[0]PETSC ERROR: See http://www.mcs.anl.gov/petsc/documentation/faq.html for
trouble shooting.
[0]PETSC ERROR: Petsc Development GIT revision: v3.7.5-3346-g41a1d4d GIT
Date: 2017-03-24 14:39:28 -0500
[0]PETSC ERROR: ./advect on a linux-c-dbg named bueler-leopard by ed Sun
Apr 2 18:34:18 2017
[0]PETSC ERROR: Configure options --download-mpich --with-debugging=1
[0]PETSC ERROR: #1 TSStep() line 3829 in
/home/ed/petsc/src/ts/interface/ts.c
[0]PETSC ERROR: #2 TSSolve() line 4065 in
/home/ed/petsc/src/ts/interface/ts.c
[0]PETSC ERROR: #3 main() line 314 in /home/ed/repos/p4pdes/c/ch9/advect.c
[0]PETSC ERROR: PETSc Option Table entries:
[0]PETSC ERROR: -adv_circlewind
[0]PETSC ERROR: -adv_conex 0.3
[0]PETSC ERROR: -adv_coney 0.3
[0]PETSC ERROR: -adv_firstorder
[0]PETSC ERROR: -da_refine 0
[0]PETSC ERROR: -snes_mf_operator
[0]PETSC ERROR: -snes_monitor_short
[0]PETSC ERROR: -snes_rtol 1.0e-4
[0]PETSC ERROR: -ts_dt 0.01
[0]PETSC ERROR: -ts_final_time 0.01
[0]PETSC ERROR: -ts_monitor
[0]PETSC ERROR: -ts_type beuler
[0]PETSC ERROR: ----------------End of Error Message -------send entire
error message to [email protected]
application called MPI_Abort(MPI_COMM_WORLD, 91) - process 0
[unset]: aborting job:
application called MPI_Abort(MPI_COMM_WORLD, 91) - process 0
Previously it gave a "No support for this operation for this object type
... Mat type mffd" error like ex2.c. Progress?
Note that my code works fine (i.e. no errors) with any of: the analytical
Jacobian or -snes_fd or -snes_fd_color or -snes_mf.
Ed
On Sun, Apr 2, 2017 at 6:23 PM, Jed Brown <[email protected]> wrote:
> The issue is that we need to create
>
> a*I - Jrhs
>
> and this is currently done by creating a*I first when we have separate
> matrices for the left and right hand sides. There is code to just scale
> and shift Jrhs when there is no IJacobian, but the creation logic got
> messed up at some point (or at least for some TS configurations that are
> common). We were discussing this recently in a performance context and
> this branch is supposed to fix that logic. Does this branch work for
> you?
>
> https://bitbucket.org/petsc/petsc/pull-requests/655/fix-
> flaw-with-tssetrhsjacobian-and-no/diff
>
> Ed Bueler <[email protected]> writes:
>
> > Dear PETSc --
> >
> > I have a TS-using and DMDA-using code in which I want to set a
> RHSJacobian
> > which is only approximate. (The Jacobian uses first-order upwinding MOL
> > while the RHSFunction uses a flux-limited MOL.) While it works with the
> > analytical Jacobian, and -snes_fd, and -snes_fd_color, and -snes_mf, I
> get
> > a "No support ..." message for -snes_mf_operator.
> >
> > It suffices to show the problem with
> >
> > src/ts/examples/tutorials/ex2.c
> >
> > (Note ex2.c does not use DMDA so ..._color is not available for ex2.c.)
> >
> > Error as follows:
> >
> > ~/petsc/src/ts/examples/tutorials[master*]$ ./ex2 -ts_dt 0.001
> > -ts_final_time 0.001 -snes_monitor
> > 0 SNES Function norm 1.059316422854e+01
> > 1 SNES Function norm 1.035505461114e-05
> > 2 SNES Function norm 5.498223366328e-12
> > ~/petsc/src/ts/examples/tutorials[master*]$ ./ex2 -ts_dt 0.001
> > -ts_final_time 0.001 -snes_monitor -snes_fd
> > 0 SNES Function norm 1.059316422854e+01
> > 1 SNES Function norm 1.208245988550e-05
> > 2 SNES Function norm 6.022374930788e-12
> > ~/petsc/src/ts/examples/tutorials[master*]$ ./ex2 -ts_dt 0.001
> > -ts_final_time 0.001 -snes_monitor -snes_mf
> > 0 SNES Function norm 1.059316422854e+01
> > 1 SNES Function norm 6.136984336801e-05
> > 2 SNES Function norm 5.355730806625e-10
> > ~/petsc/src/ts/examples/tutorials[master*]$ ./ex2 -ts_dt 0.001
> > -ts_final_time 0.001 -snes_monitor -snes_mf_operator
> > 0 SNES Function norm 1.059316422854e+01
> > [0]PETSC ERROR: --------------------- Error Message
> > --------------------------------------------------------------
> > [0]PETSC ERROR: No support for this operation for this object type
> > [0]PETSC ERROR: Mat type mffd
> > [0]PETSC ERROR: See http://www.mcs.anl.gov/petsc/documentation/faq.html
> for
> > trouble shooting.
> > [0]PETSC ERROR: Petsc Development GIT revision: v3.7.5-3426-g0c7851c GIT
> > Date: 2017-04-01 18:40:06 -0600
> > [0]PETSC ERROR: ./ex2 on a linux-c-dbg named ed-lemur by ed Sun Apr 2
> > 17:02:47 2017
> > [0]PETSC ERROR: Configure options --download-mpich --with-debugging=1
> > [0]PETSC ERROR: #1 MatZeroEntries() line 5471 in
> > /home/ed/petsc/src/mat/interface/matrix.c
> > [0]PETSC ERROR: #2 TSComputeIJacobian() line 965 in
> > /home/ed/petsc/src/ts/interface/ts.c
> > [0]PETSC ERROR: #3 SNESTSFormJacobian_Theta() line 515 in
> > /home/ed/petsc/src/ts/impls/implicit/theta/theta.c
> > [0]PETSC ERROR: #4 SNESTSFormJacobian() line 5078 in
> > /home/ed/petsc/src/ts/interface/ts.c
> > [0]PETSC ERROR: #5 SNESComputeJacobian() line 2276 in
> > /home/ed/petsc/src/snes/interface/snes.c
> > [0]PETSC ERROR: #6 SNESSolve_NEWTONLS() line 222 in
> > /home/ed/petsc/src/snes/impls/ls/ls.c
> > [0]PETSC ERROR: #7 SNESSolve() line 3967 in
> > /home/ed/petsc/src/snes/interface/snes.c
> > [0]PETSC ERROR: #8 TS_SNESSolve() line 171 in
> > /home/ed/petsc/src/ts/impls/implicit/theta/theta.c
> > [0]PETSC ERROR: #9 TSStep_Theta() line 211 in
> > /home/ed/petsc/src/ts/impls/implicit/theta/theta.c
> > [0]PETSC ERROR: #10 TSStep() line 3843 in
> > /home/ed/petsc/src/ts/interface/ts.c
> > [0]PETSC ERROR: #11 TSSolve() line 4088 in
> > /home/ed/petsc/src/ts/interface/ts.c
> > [0]PETSC ERROR: #12 main() line 194 in
> > /home/ed/petsc/src/ts/examples/tutorials/ex2.c
> > [0]PETSC ERROR: PETSc Option Table entries:
> > [0]PETSC ERROR: -snes_mf_operator
> > [0]PETSC ERROR: -snes_monitor
> > [0]PETSC ERROR: -ts_dt 0.001
> > [0]PETSC ERROR: -ts_final_time 0.001
> > [0]PETSC ERROR: ----------------End of Error Message -------send entire
> > error message to [email protected]
> > application called MPI_Abort(MPI_COMM_WORLD, 56) - process 0
> > [unset]: aborting job:
> > application called MPI_Abort(MPI_COMM_WORLD, 56) - process 0
> >
> > Is this intended or a bug? If it is intended, what is the issue?
> >
> > I am using current master branch (commit
> > 0c7851c55cba8e40da5083f79ba1ff846acd45b2).
> >
> > Thanks for your help and awesome library!
> >
> > Ed
> >
> >
> >
> >
> >
> > --
> > Ed Bueler
> > Dept of Math and Stat and Geophysical Institute
> > University of Alaska Fairbanks
> > Fairbanks, AK 99775-6660
> > 301C Chapman
>
--
Ed Bueler
Dept of Math and Stat and Geophysical Institute
University of Alaska Fairbanks
Fairbanks, AK 99775-6660
301C Chapman
static char help[] =
"Time-dependent pure-advection equation in 2D using TS. Option prefix -adv_.\n"
"Domain is (0,1) x (0,1). Equation is\n"
" u_t + div(a(x,y) u) = g(x,y,u).\n"
"Boundary conditions are periodic in x and y. Cells are grid-point centered.\n"
"Uses van Leer (1974) flux-limited (non-oscillatory) method-of-lines\n"
"discretization [default], or first-order upwind.\n";
#include <petsc.h>
// try:
// ./advect -da_refine 5 -ts_monitor_solution draw -ts_monitor -ts_rk_type 5dp
// one lap of circular motion, computed in parallel:
// mpiexec -n 4 ./advect -da_refine 5 -adv_circlewind -adv_conex 0.3 -adv_coney 0.3 -ts_final_time 3.1416 -ts_monitor -ts_monitor_solution draw -ksp_rtol 1.0e-10
// implicit:
// mpiexec -n 4 ./advect -ts_monitor_solution draw -ts_monitor -adv_circlewind -ts_final_time 0.5 -adv_conex 0.3 -adv_coney 0.3 -ts_type cn -da_refine 6 -snes_monitor -ts_dt 0.05 -ksp_rtol 1.0e-10
// with -adv_firstorder, -snes_type test suggests Jacobian is correct
// testing Jacobian options (fails with XX=-snes_mf_operator; use -ksp_view_mat ::ascii_matlab etc.):
// ./advect -da_refine 0 -ts_monitor -adv_circlewind -adv_conex 0.3 -adv_coney 0.3 -ts_type beuler -snes_monitor_short -ts_final_time 0.01 -ts_dt 0.01 -snes_rtol 1.0e-4 -adv_firstorder XX
typedef struct {
PetscBool firstorder, // if true, use first-order upwinding
circlewind; // if true, wind is equivalent to rigid rotation
double windx, windy, // x,y components of wind (if not circular)
conex, coney, coner, coneh; // parameters for cone initial cond.
} AdvectCtx;
PetscErrorCode FormInitial(DMDALocalInfo *info, Vec u, AdvectCtx* user) {
PetscErrorCode ierr;
DMDACoor2d **coords;
int i, j;
double x, y, r, **au;
ierr = VecSet(u,0.0); CHKERRQ(ierr); // clear it first
ierr = DMDAGetCoordinateArray(info->da, &coords); CHKERRQ(ierr);
ierr = DMDAVecGetArray(info->da, u, &au); CHKERRQ(ierr);
for (j=info->ys; j<info->ys+info->ym; j++) {
for (i=info->xs; i<info->xs+info->xm; i++) {
x = coords[j][i].x - user->conex;
y = coords[j][i].y - user->coney;
r = PetscSqrtReal(x * x + y * y);
if (r < user->coner) {
au[j][i] = user->coneh * (1.0 - r / user->coner);
}
}
}
ierr = DMDAVecRestoreArray(info->da, u, &au); CHKERRQ(ierr);
ierr = DMDARestoreCoordinateArray(info->da, &coords); CHKERRQ(ierr);
return 0;
}
// velocity a(x,y) = ( a^x(x,y), a^y(x,y) )
static double a_wind(double x, double y, int dir, AdvectCtx* user) {
if (user->circlewind) {
return (dir == 0) ? - 2.0 * (y - 0.5) : 2.0 * (x - 0.5);
} else {
return (dir == 0) ? user->windx : user->windy;
}
}
// source g(x,y,u)
static double g_source(double x, double y, double u, AdvectCtx* user) {
return 0.0;
}
// d g(x,y,u) / d u
static double dg_source(double x, double y, double u, AdvectCtx* user) {
return 0.0;
}
/* the van Leer (1974) limiter is formula (1.11) in section III.1 of
Hundsdorfer & Verwer */
//STARTLIMITER
static double limiter(double th) {
return 0.5 * (th + PetscAbsReal(th)) / (1.0 + PetscAbsReal(th));
}
//ENDLIMITER
/* method-of-lines discretization gives ODE system u' = G(t,u) */
//STARTFUNCTION
PetscErrorCode FormRHSFunctionLocal(DMDALocalInfo *info, double t,
double **au, double **aG, AdvectCtx *user) {
int i, j, l;
const int dir[4] = {0, 1, 0, 1}, // use x (0) or y (1) component
xsh[4] = { 1, 0,-1, 0}, ysh[4] = { 0, 1, 0,-1},
aposi[4] = { 0, 0,-1, 0}, anegi[4] = { 1, 0, 0, 0},
aposj[4] = { 0, 0, 0,-1}, anegj[4] = { 0, 1, 0, 0},
posfari[4] = {-1, 0,-2, 0}, negfari[4] = { 2, 0, 1, 0},
posfarj[4] = { 0,-1, 0,-2}, negfarj[4] = { 0, 2, 0, 1};
double hx, hy, halfx, halfy, x, y, a, u_up, u_dn, u_far, theta,
flux[4];
// fluxes on cell boundaries are traversed in this order (=l): ,-1-,
// cell center at * has coordinates (x,y): 2 * 0
// '-3-'
hx = 1.0 / info->mx; hy = 1.0 / info->my;
halfx = hx / 2.0; halfy = hy / 2.0;
for (j = info->ys; j < info->ys + info->ym; j++) {
y = (j + 0.5) * hy;
for (i = info->xs; i < info->xs + info->xm; i++) {
x = (i + 0.5) * hx;
for (l = 0; l < 4; l++) { // loop over cell boundaries
a = a_wind(x + halfx*xsh[l],y + halfy*ysh[l],dir[l],user);
if (user->firstorder) {
u_up = (a >= 0) ? au[j + aposj[l]][i + aposi[l]]
: au[j + anegj[l]][i + anegi[l]];
flux[l] = a * u_up;
} else { // use formulas (1.2), (1.3), (1.6) on
// pp 216--217 of Hundsdorfer & Verwer
if (a >= 0.0) {
u_dn = au[j + anegj[l]][i + anegi[l]];
u_up = au[j + aposj[l]][i + aposi[l]];
u_far = au[j + posfarj[l]][i + posfari[l]];
} else {
u_dn = au[j + aposj[l]][i + aposi[l]];
u_up = au[j + anegj[l]][i + anegi[l]];
u_far = au[j + negfarj[l]][i + negfari[l]];
}
flux[l] = a * u_up;
if (u_dn != u_up) {
theta = (u_up - u_far) / (u_dn - u_up);
flux[l] += a * limiter(theta) * (u_dn - u_up);
}
}
}
aG[j][i] = - (flux[0] - flux[2])/hx - (flux[1] - flux[3])/hy
+ g_source(x,y,au[j][i],user);
}
}
return 0;
}
//ENDFUNCTION
PetscErrorCode FormRHSJacobianLocal(DMDALocalInfo *info, double t,
double **au, Mat J, Mat P, AdvectCtx *user) {
PetscErrorCode ierr;
const int dir[4] = {0, 1, 0, 1}, // use x (0) or y (1) component
xsh[4] = { 1, 0,-1, 0}, ysh[4] = { 0, 1, 0,-1};
int i, j, l, ncols;
double hx, hy, halfx, halfy, x, y, a, v[5];
MatStencil col[5],row;
ierr = MatZeroEntries(P); CHKERRQ(ierr);
hx = 1.0 / info->mx; hy = 1.0 / info->my;
halfx = hx / 2.0; halfy = hy / 2.0;
for (j = info->ys; j < info->ys+info->ym; j++) {
y = (j + 0.5) * hy;
row.j = j; col[0].j = j;
for (i = info->xs; i < info->xs+info->xm; i++) {
x = (i + 0.5) * hx;
row.i = i; col[0].i = i;
v[0] = dg_source(x,y,au[j][i],user);
ncols = 1;
for (l = 0; l < 4; l++) { // loop over cell boundaries
a = a_wind(x + halfx*xsh[l],y + halfy*ysh[l],dir[l],user);
// u_up = (a >= 0) ? au[j + aposj[l]][i + aposi[l]]
// : au[j + anegj[l]][i + anegi[l]];
// flux[l] = a * u_up;
if (a >= 0.0) {
switch (l) {
case 0:
col[ncols].j = j; col[ncols].i = i;
v[ncols++] = - a / hx;
break;
case 1:
col[ncols].j = j; col[ncols].i = i;
v[ncols++] = - a / hy;
break;
case 2:
col[ncols].j = j; col[ncols].i = i-1;
v[ncols++] = a / hx;
break;
case 3:
col[ncols].j = j-1; col[ncols].i = i;
v[ncols++] = a / hy;
break;
}
} else { // a < 0
switch (l) {
case 0:
col[ncols].j = j; col[ncols].i = i+1;
v[ncols++] = - a / hx;
break;
case 1:
col[ncols].j = j+1; col[ncols].i = i;
v[ncols++] = - a / hy;
break;
case 2:
col[ncols].j = j; col[ncols].i = i;
v[ncols++] = a / hx;
break;
case 3:
col[ncols].j = j; col[ncols].i = i;
v[ncols++] = a / hy;
break;
}
}
}
ierr = MatSetValuesStencil(P,1,&row,ncols,col,v,ADD_VALUES); CHKERRQ(ierr);
}
}
ierr = MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
ierr = MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
if (J != P) {
ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
}
return 0;
}
int main(int argc,char **argv) {
PetscErrorCode ierr;
AdvectCtx user;
TS ts;
DM da;
Vec u;
DMDALocalInfo info;
double hx, hy, t0, dt;
PetscBool dump = PETSC_FALSE;
char fileroot[PETSC_MAX_PATH_LEN] = "";
PetscInitialize(&argc,&argv,(char*)0,help);
// the wind, and the cone initial condition, are from
// Hundsdorfer & Verwer, "Numerical Solution of Time-Dependent Advection-
// Diffusion-Reaction Equations", Springer 2003, page 303
user.windx = 1.0;
user.windy = 1.0;
user.conex = 0.2;
user.coney = 0.2;
user.coner = 0.1;
user.coneh = 1.0;
user.circlewind = PETSC_FALSE;
user.firstorder = PETSC_FALSE;
ierr = PetscOptionsBegin(PETSC_COMM_WORLD,
"adv_", "options for advect.c", ""); CHKERRQ(ierr);
ierr = PetscOptionsBool("-circlewind","if true, wind is rigid rotation",
"advect.c",user.circlewind,&user.circlewind,NULL);CHKERRQ(ierr);
ierr = PetscOptionsReal("-coneh","cone height",
"advect.c",user.coneh,&user.coneh,NULL);CHKERRQ(ierr);
ierr = PetscOptionsReal("-coner","cone radius",
"advect.c",user.coner,&user.coner,NULL);CHKERRQ(ierr);
ierr = PetscOptionsReal("-conex","x component of cone center",
"advect.c",user.conex,&user.conex,NULL);CHKERRQ(ierr);
ierr = PetscOptionsReal("-coney","y component of cone center",
"advect.c",user.coney,&user.coney,NULL);CHKERRQ(ierr);
ierr = PetscOptionsString("-dumpto","filename root for initial/final state",
"advect.c",fileroot,fileroot,PETSC_MAX_PATH_LEN,&dump);CHKERRQ(ierr);
ierr = PetscOptionsBool("-firstorder","if true, use first-order upwinding",
"advect.c",user.firstorder,&user.firstorder,NULL);CHKERRQ(ierr);
ierr = PetscOptionsReal("-windx","x component of wind (if not circular)",
"advect.c",user.windx,&user.windx,NULL);CHKERRQ(ierr);
ierr = PetscOptionsReal("-windy","y component of wind (if not circular)",
"advect.c",user.windy,&user.windy,NULL);CHKERRQ(ierr);
ierr = PetscOptionsEnd(); CHKERRQ(ierr);
ierr = DMDACreate2d(PETSC_COMM_WORLD,
DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC,
DMDA_STENCIL_STAR, // no diagonal differencing
5,5,PETSC_DECIDE,PETSC_DECIDE, // default to hx=hx=0.2 grid
// (mx=my=5 allows -snes_fd_color)
1, // degrees of freedom
2, // stencil width (flux-limiting)
NULL,NULL,&da); CHKERRQ(ierr);
ierr = DMSetFromOptions(da); CHKERRQ(ierr);
ierr = DMSetUp(da); CHKERRQ(ierr);
ierr = DMSetApplicationContext(da,&user); CHKERRQ(ierr);
// grid is cell-centered
ierr = DMDAGetLocalInfo(da,&info); CHKERRQ(ierr);
hx = 1.0 / info.mx; hy = 1.0 / info.my;
ierr = DMDASetUniformCoordinates(da,
0.0+hx/2.0,1.0-hx/2.0,0.0+hy/2.0,1.0-hy/2.0,0.0,1.0);CHKERRQ(ierr);
ierr = TSCreate(PETSC_COMM_WORLD,&ts); CHKERRQ(ierr);
ierr = TSSetProblemType(ts,TS_NONLINEAR); CHKERRQ(ierr);
ierr = TSSetDM(ts,da); CHKERRQ(ierr);
ierr = DMDATSSetRHSFunctionLocal(da,INSERT_VALUES,
(DMDATSRHSFunctionLocal)FormRHSFunctionLocal,&user); CHKERRQ(ierr);
ierr = DMDATSSetRHSJacobianLocal(da,
(DMDATSRHSJacobianLocal)FormRHSJacobianLocal,&user); CHKERRQ(ierr);
ierr = TSSetType(ts,TSRK); CHKERRQ(ierr);
ierr = TSRKSetType(ts,TSRK2A); CHKERRQ(ierr);
ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); CHKERRQ(ierr);
ierr = TSSetInitialTimeStep(ts,0.0,0.1); CHKERRQ(ierr);
ierr = TSSetDuration(ts,1000000,0.6); CHKERRQ(ierr);
ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
ierr = TSGetTime(ts,&t0); CHKERRQ(ierr);
ierr = TSGetTimeStep(ts,&dt); CHKERRQ(ierr);
ierr = PetscPrintf(PETSC_COMM_WORLD,
"solving on %d x %d grid with dx=%g x dy=%g cells, t0=%g,\n"
"and initial step dt=%g ...\n",
info.mx,info.my,hx,hy,t0,dt); CHKERRQ(ierr);
ierr = DMCreateGlobalVector(da,&u); CHKERRQ(ierr);
ierr = FormInitial(&info,u,&user); CHKERRQ(ierr);
if (dump) {
PetscViewer viewer;
char filename[PETSC_MAX_PATH_LEN] = "";
ierr = sprintf(filename,"%s_initial.dat",fileroot);
ierr = PetscPrintf(PETSC_COMM_WORLD,
"writing PETSC binary file %s ...\n",filename); CHKERRQ(ierr);
ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,
FILE_MODE_WRITE,&viewer); CHKERRQ(ierr);
ierr = VecView(u,viewer); CHKERRQ(ierr);
ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
}
ierr = TSSolve(ts,u); CHKERRQ(ierr);
if (dump) {
PetscViewer viewer;
char filename[PETSC_MAX_PATH_LEN] = "";
ierr = sprintf(filename,"%s_final.dat",fileroot);
ierr = PetscPrintf(PETSC_COMM_WORLD,
"writing PETSC binary file %s ...\n",filename); CHKERRQ(ierr);
ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,
FILE_MODE_WRITE,&viewer); CHKERRQ(ierr);
ierr = VecView(u,viewer); CHKERRQ(ierr);
ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
}
VecDestroy(&u); TSDestroy(&ts); DMDestroy(&da);
PetscFinalize();
return 0;
}