/* Formatted test for TS routines. Solves U_t=F(t,u) Where: [2*u1+u2 F(t,u)= [u1+2*u2+u3 [ u2+2*u3 We can compare the solutions from euler, beuler and SUNDIALS to see what is the difference. */ static char help[] = "Solves a linear ODE. \n\n"; #include #include extern PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*); extern PetscErrorCode RHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*); extern PetscErrorCode Monitor(TS,PetscInt,PetscReal,Vec,void*); extern PetscErrorCode Initial(Vec,void*); extern PetscErrorCode MyMatMult(Mat,Vec,Vec); extern PetscReal solx(PetscReal); extern PetscReal soly(PetscReal); extern PetscReal solz(PetscReal); int main(int argc,char **argv) { PetscInt time_steps = 100,steps; Vec global; PetscReal dt,ftime; TS ts; Mat A = 0,S; PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); PetscCall(PetscOptionsGetInt(NULL,NULL,"-time",&time_steps,NULL)); /* set initial conditions */ PetscCall(VecCreate(PETSC_COMM_WORLD,&global)); PetscCall(VecSetSizes(global,PETSC_DECIDE,3)); PetscCall(VecSetFromOptions(global)); PetscCall(Initial(global,NULL)); /* make timestep context */ PetscCall(TSCreate(PETSC_COMM_WORLD,&ts)); PetscCall(TSSetProblemType(ts,TS_NONLINEAR)); PetscCall(TSMonitorSet(ts,Monitor,NULL,NULL)); dt = 0.001; /* The user provides the RHS and Jacobian */ PetscCall(TSSetRHSFunction(ts,NULL,RHSFunction,NULL)); PetscCall(MatCreate(PETSC_COMM_WORLD,&A)); PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,3,3)); PetscCall(MatSetFromOptions(A)); PetscCall(MatSetUp(A)); PetscCall(RHSJacobian(ts,0.0,global,A,A,NULL)); PetscCall(TSSetRHSJacobian(ts,A,A,RHSJacobian,NULL)); PetscCall(MatCreateShell(PETSC_COMM_WORLD,3,3,3,3,NULL,&S)); PetscCall(MatShellSetOperation(S,MATOP_MULT,(void (*)(void))MyMatMult)); PetscCall(TSSetRHSJacobian(ts,S,A,RHSJacobian,NULL)); PetscCall(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP)); PetscCall(TSSetFromOptions(ts)); PetscCall(TSSetTimeStep(ts,dt)); PetscCall(TSSetMaxSteps(ts,time_steps)); PetscCall(TSSetMaxTime(ts,1)); PetscCall(TSSetSolution(ts,global)); PetscCall(TSSolve(ts,global)); PetscCall(TSGetSolveTime(ts,&ftime)); PetscCall(TSGetStepNumber(ts,&steps)); /* free the memories */ PetscCall(TSDestroy(&ts)); PetscCall(VecDestroy(&global)); PetscCall(MatDestroy(&A)); PetscCall(MatDestroy(&S)); PetscCall(PetscFinalize()); return 0; } PetscErrorCode MyMatMult(Mat S,Vec x,Vec y) { const PetscScalar *inptr; PetscScalar *outptr; PetscFunctionBegin; PetscCall(VecGetArrayRead(x,&inptr)); PetscCall(VecGetArrayWrite(y,&outptr)); outptr[0] = 2.0*inptr[0]+inptr[1]; outptr[1] = inptr[0]+2.0*inptr[1]+inptr[2]; outptr[2] = inptr[1]+2.0*inptr[2]; PetscCall(VecRestoreArrayRead(x,&inptr)); PetscCall(VecRestoreArrayWrite(y,&outptr)); PetscFunctionReturn(0); } /* this test problem has initial values (1,1,1). */ PetscErrorCode Initial(Vec global,void *ctx) { PetscScalar *localptr; PetscInt i,mybase,myend,locsize; /* determine starting point of each processor */ PetscCall(VecGetOwnershipRange(global,&mybase,&myend)); PetscCall(VecGetLocalSize(global,&locsize)); /* Initialize the array */ PetscCall(VecGetArrayWrite(global,&localptr)); for (i=0; i