Dear PETSc --

I tried twice to make this an issue at the gitlab.com host site, but both
times got "something went wrong (500)".  So this is a bug report by
old-fashioned means.

I created a TS example,
https://github.com/bueler/p4pdes-next/blob/master/c/fix-arkimex/ex54.c at
my github, also attached.  It solves a 2D linear ODE
```
   x' + y' = 6 y
        y' = x
```
Pretty basic; the known exact solution is just exponentials.  The code
writes it as F(t,u,u')=G(t,u) and supplies all the pieces, namely
IFunction,IJacobian,RHSFunction,RHSJacobian.  Note both F and G must be
seen by TS to get the correct solution.  In summary, a boring (and
valgrind-clean ;-)) example.

For current master branch it runs fine for the fully-implicit methods (e.g.
BDF, CN, ROSW) which can use the IFunction F, including with
finite-differenced Jacobians.  With BDF2, BDF2+-snes_fd, BDF6+tight tol.,
CN, BEULER, ROSW:
$ ./ex54
error norm at tf = 1.000000 from 33 steps:  |u-u_exact| =  9.29170e-02
$ ./ex54 -snes_fd
error norm at tf = 1.000000 from 33 steps:  |u-u_exact| =  9.29170e-02
$ ./ex54 -ts_rtol 1.0e-14 -ts_atol 1.0e-14 -ts_bdf_order 6
error norm at tf = 1.000000 from 388 steps:  |u-u_exact| =  4.23624e-11
$ ./ex54 -ts_type beuler
error norm at tf = 1.000000 from 100 steps:  |u-u_exact| =  6.71676e-01
$ ./ex54 -ts_type cn
error norm at tf = 1.000000 from 100 steps:  |u-u_exact| =  2.22839e-03
$ ./ex54 -ts_type rosw
error norm at tf = 1.000000 from 21 steps:  |u-u_exact| =  5.64012e-03

But it produces wrong values with ARKIMEX:
$ ./ex54 -ts_type arkimex
error norm at tf = 1.000000 from 16 steps:  |u-u_exact| =  1.93229e+01

Neither tightening tolerance nor changing type (`-ts_arkimex_type`) helps
ARKIMEX.

Thanks!

Ed

PS  My book is at a late proofs stage, and out of my hands.  It should
appear SIAM Press in a couple of months.  In all the examples in my book,
only my diffusion-reaction system example using F(t,u,u') = G(t,u) is
broken.  Thus the motivation for a trivial ODE example as above.


-- 
Ed Bueler
Dept of Mathematics and Statistics
University of Alaska Fairbanks
Fairbanks, AK 99775-6660
306C Chapman
static char help[] =
"Simple ODE system to test implicit and IMEX methods when both RHSFunction()\n"
"and IFunction() are supplied, with Jacobians as well.  Problem has form\n"
"   F(t,u,dudt) = G(t,u)\n"
"where  u(t) = (x(t),y(t))  and x,y are scalar.  Functions F (IFunction) and\n"
"G (RHSFunction) are actually linear, but this example uses TS_NONLINEAR type.\n"
"In fact the system is\n"
"   x' + y' = 6 y\n"
"        y' = x\n"
"with x(0)=1 and y(0)=3.  The exact solution is known; see end of main()\n"
"for computation of numerical error.  Defaults to BDF TS type.\n\n";

/* with BDF2, BDF2+-snes_fd, BDF6+tight tol., CN, ROSW:
$ ./ex54
error norm at tf = 1.000000 from 33 steps:  |u-u_exact| =  9.29170e-02
$ ./ex54 -snes_fd
error norm at tf = 1.000000 from 33 steps:  |u-u_exact| =  9.29170e-02
$ ./ex54 -ts_rtol 1.0e-14 -ts_atol 1.0e-14 -ts_bdf_order 6
error norm at tf = 1.000000 from 388 steps:  |u-u_exact| =  4.23624e-11
$ ./ex54 -ts_type cn
error norm at tf = 1.000000 from 100 steps:  |u-u_exact| =  2.22839e-03
$ ./ex54 -ts_type rosw
error norm at tf = 1.000000 from 21 steps:  |u-u_exact| =  5.64012e-03

BROKEN with arkimex:
$ ./ex54 -ts_type arkimex
error norm at tf = 1.000000 from 16 steps:  |u-u_exact| =  1.93229e+01
*/

#include <petsc.h>

extern PetscErrorCode FormIFunction(TS,PetscReal,Vec,Vec,Vec F,void*);
extern PetscErrorCode FormIJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
extern PetscErrorCode FormRHSFunction(TS,PetscReal,Vec,Vec,void*);
extern PetscErrorCode FormRHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*);

int main(int argc,char **argv)
{
  PetscErrorCode ierr;
  TS             ts;
  Vec            u, uexact;
  Mat            JF,JG;
  PetscReal      tf,xf,yf,errnorm;
  PetscInt       steps;

  PetscInitialize(&argc,&argv,(char*)0,help);

  ierr = VecCreate(PETSC_COMM_WORLD,&u); CHKERRQ(ierr);
  ierr = VecSetSizes(u,PETSC_DECIDE,2); CHKERRQ(ierr);
  ierr = VecSetFromOptions(u); CHKERRQ(ierr);

  ierr = MatCreate(PETSC_COMM_WORLD,&JF); CHKERRQ(ierr);
  ierr = MatSetSizes(JF,PETSC_DECIDE,PETSC_DECIDE,2,2); CHKERRQ(ierr);
  ierr = MatSetFromOptions(JF); CHKERRQ(ierr);
  ierr = MatSetUp(JF); CHKERRQ(ierr);
  ierr = MatDuplicate(JF,MAT_DO_NOT_COPY_VALUES,&JG); CHKERRQ(ierr);

  ierr = TSCreate(PETSC_COMM_WORLD,&ts); CHKERRQ(ierr);

  ierr = TSSetIFunction(ts,NULL,FormIFunction,NULL); CHKERRQ(ierr);
  ierr = TSSetIJacobian(ts,JF,JF,FormIJacobian,NULL); CHKERRQ(ierr);

  ierr = TSSetRHSFunction(ts,NULL,FormRHSFunction,NULL); CHKERRQ(ierr);
  ierr = TSSetRHSJacobian(ts,JG,JG,FormRHSJacobian,NULL); CHKERRQ(ierr);

  ierr = TSSetProblemType(ts,TS_NONLINEAR); CHKERRQ(ierr);
  ierr = TSSetType(ts,TSBDF); CHKERRQ(ierr);
  ierr = TSSetTime(ts,0.0); CHKERRQ(ierr);
  ierr = TSSetMaxTime(ts,1.0); CHKERRQ(ierr);
  ierr = TSSetTimeStep(ts,0.01); CHKERRQ(ierr);
  ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); CHKERRQ(ierr);
  ierr = TSSetFromOptions(ts);CHKERRQ(ierr);

  ierr = VecSetValue(u,0,1.0,INSERT_VALUES); CHKERRQ(ierr);
  ierr = VecSetValue(u,1,3.0,INSERT_VALUES); CHKERRQ(ierr);
  ierr = VecAssemblyBegin(u); CHKERRQ(ierr);
  ierr = VecAssemblyEnd(u); CHKERRQ(ierr);
  ierr = TSSolve(ts,u); CHKERRQ(ierr);

  ierr = TSGetStepNumber(ts,&steps); CHKERRQ(ierr);
  ierr = TSGetTime(ts,&tf); CHKERRQ(ierr);
  xf = -3.0 * PetscExpReal(-3.0*tf) + 4.0 * PetscExpReal(2.0*tf);
  yf = PetscExpReal(-3.0*tf) + 2.0 * PetscExpReal(2.0*tf);
  //ierr = PetscPrintf(PETSC_COMM_WORLD,
  //         "xf = %.6f, yf = %.6f\n",xf,yf); CHKERRQ(ierr);
  ierr = VecDuplicate(u,&uexact); CHKERRQ(ierr);
  ierr = VecSetValue(uexact,0,xf,INSERT_VALUES); CHKERRQ(ierr);
  ierr = VecSetValue(uexact,1,yf,INSERT_VALUES); CHKERRQ(ierr);
  ierr = VecAssemblyBegin(uexact); CHKERRQ(ierr);
  ierr = VecAssemblyEnd(uexact); CHKERRQ(ierr);
  ierr = VecAXPY(u,-1.0,uexact); CHKERRQ(ierr); // u <- u + (-1.0) uexact
  ierr = VecNorm(u,NORM_2,&errnorm); CHKERRQ(ierr);
  ierr = PetscPrintf(PETSC_COMM_WORLD,
           "error norm at tf = %.6f from %d steps:  |u-u_exact| =  %.5e\n",
           tf,steps,errnorm); CHKERRQ(ierr);

  VecDestroy(&u);  VecDestroy(&uexact);
  MatDestroy(&JF);  MatDestroy(&JG);
  TSDestroy(&ts);
  return PetscFinalize();
}


PetscErrorCode FormIFunction(TS ts, PetscReal t, Vec u, Vec dudt,
                             Vec F, void *ctx) {
    PetscErrorCode  ierr;
    const PetscReal *au, *adudt;
    PetscReal       *aF;

    ierr = VecGetArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecGetArrayRead(dudt,&adudt); CHKERRQ(ierr);
    ierr = VecGetArray(F,&aF);
    aF[0] = adudt[0] + adudt[1];
    aF[1] =            adudt[1];
    ierr = VecRestoreArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecRestoreArrayRead(dudt,&adudt); CHKERRQ(ierr);
    ierr = VecRestoreArray(F,&aF); CHKERRQ(ierr);
    return 0;
}

// computes  J = dF/du + a dF/d(dudt)
PetscErrorCode FormIJacobian(TS ts, PetscReal t, Vec u, Vec dudt,
                             PetscReal a, Mat J, Mat P, void *ctx) {
    PetscErrorCode ierr;
    PetscInt       row[2] = {0, 1},  col[2] = {0, 1};
    PetscReal      v[4] = { a,   a,
                            0.0, a};
    ierr = MatSetValues(P,2,row,2,col,v,INSERT_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;
}

PetscErrorCode FormRHSFunction(TS ts, PetscReal t, Vec u,
                               Vec G, void *ctx) {
    PetscErrorCode  ierr;
    const PetscReal *au;
    PetscReal       *aG;

    ierr = VecGetArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecGetArray(G,&aG); CHKERRQ(ierr);
    aG[0] = 6.0 * au[1];
    aG[1] = au[0];
    ierr = VecRestoreArrayRead(u,&au); CHKERRQ(ierr);
    ierr = VecRestoreArray(G,&aG); CHKERRQ(ierr);
    return 0;
}

PetscErrorCode FormRHSJacobian(TS ts, PetscReal t, Vec u, Mat J, Mat P,
                               void *ctx) {
    PetscErrorCode ierr;
    PetscInt       row[2] = {0, 1},  col[2] = {0, 1};
    PetscReal      v[4] = { 0.0, 6.0,
                            1.0, 0.0};
    ierr = MatSetValues(P,2,row,2,col,v,INSERT_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;
}

Reply via email to