xref: /petsc/src/ts/tutorials/ex17.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
1c4762a1bSJed Brown static const char help[] = "Time-dependent PDE in 1d. Simplified from ex15.c for illustrating how to solve DAEs. \n";
2c4762a1bSJed Brown /*
3c4762a1bSJed Brown    u_t = uxx
4c4762a1bSJed Brown    0 < x < 1;
5c4762a1bSJed Brown    At t=0: u(x) = exp(c*r*r*r), if r=PetscSqrtReal((x-.5)*(x-.5)) < .125
6c4762a1bSJed Brown            u(x) = 0.0           if r >= .125
7c4762a1bSJed Brown 
8c4762a1bSJed Brown    Boundary conditions:
9c4762a1bSJed Brown    Dirichlet BC:
10c4762a1bSJed Brown    At x=0, x=1, u = 0.0
11c4762a1bSJed Brown 
12c4762a1bSJed Brown    Neumann BC:
13c4762a1bSJed Brown    At x=0, x=1: du(x,t)/dx = 0
14c4762a1bSJed Brown 
15c4762a1bSJed Brown    mpiexec -n 2 ./ex17 -da_grid_x 40 -ts_max_steps 2 -snes_monitor -ksp_monitor
16c4762a1bSJed Brown          ./ex17 -da_grid_x 40 -monitor_solution
17c4762a1bSJed Brown          ./ex17 -da_grid_x 100  -ts_type theta -ts_theta_theta 0.5 # Midpoint is not L-stable
18c4762a1bSJed Brown          ./ex17 -jac_type fd_coloring  -da_grid_x 500 -boundary 1
19c4762a1bSJed Brown          ./ex17 -da_grid_x 100  -ts_type gl -ts_adapt_type none -ts_max_steps 2
20c4762a1bSJed Brown */
21c4762a1bSJed Brown 
22c4762a1bSJed Brown #include <petscdm.h>
23c4762a1bSJed Brown #include <petscdmda.h>
24c4762a1bSJed Brown #include <petscts.h>
25c4762a1bSJed Brown 
26c4762a1bSJed Brown typedef enum {JACOBIAN_ANALYTIC,JACOBIAN_FD_COLORING,JACOBIAN_FD_FULL} JacobianType;
27c4762a1bSJed Brown static const char *const JacobianTypes[] = {"analytic","fd_coloring","fd_full","JacobianType","fd_",0};
28c4762a1bSJed Brown 
29c4762a1bSJed Brown /*
30c4762a1bSJed Brown    User-defined data structures and routines
31c4762a1bSJed Brown */
32c4762a1bSJed Brown typedef struct {
33c4762a1bSJed Brown   PetscReal c;
34c4762a1bSJed Brown   PetscInt  boundary;            /* Type of boundary condition */
35c4762a1bSJed Brown   PetscBool viewJacobian;
36c4762a1bSJed Brown } AppCtx;
37c4762a1bSJed Brown 
38c4762a1bSJed Brown static PetscErrorCode FormIFunction(TS,PetscReal,Vec,Vec,Vec,void*);
39c4762a1bSJed Brown static PetscErrorCode FormIJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
40c4762a1bSJed Brown static PetscErrorCode FormInitialSolution(TS,Vec,void*);
41c4762a1bSJed Brown 
42c4762a1bSJed Brown int main(int argc,char **argv)
43c4762a1bSJed Brown {
44c4762a1bSJed Brown   TS             ts;                   /* nonlinear solver */
45c4762a1bSJed Brown   Vec            u;                    /* solution, residual vectors */
46c4762a1bSJed Brown   Mat            J;                    /* Jacobian matrix */
47c4762a1bSJed Brown   PetscInt       nsteps;
48c4762a1bSJed Brown   PetscReal      vmin,vmax,norm;
49c4762a1bSJed Brown   PetscErrorCode ierr;
50c4762a1bSJed Brown   DM             da;
51c4762a1bSJed Brown   PetscReal      ftime,dt;
52c4762a1bSJed Brown   AppCtx         user;              /* user-defined work context */
53c4762a1bSJed Brown   JacobianType   jacType;
54c4762a1bSJed Brown 
55*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscInitialize(&argc,&argv,(char*)0,help));
56c4762a1bSJed Brown 
57c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58c4762a1bSJed Brown      Create distributed array (DMDA) to manage parallel grid and vectors
59c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,11,1,1,NULL,&da));
615f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(da));
625f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(da));
63c4762a1bSJed Brown 
64c4762a1bSJed Brown   /*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
65c4762a1bSJed Brown      Extract global vectors from DMDA;
66c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
675f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(da,&u));
68c4762a1bSJed Brown 
69c4762a1bSJed Brown   /* Initialize user application context */
70c4762a1bSJed Brown   user.c            = -30.0;
71c4762a1bSJed Brown   user.boundary     = 0;  /* 0: Dirichlet BC; 1: Neumann BC */
72c4762a1bSJed Brown   user.viewJacobian = PETSC_FALSE;
73c4762a1bSJed Brown 
745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-boundary",&user.boundary,NULL));
755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL,NULL,"-viewJacobian",&user.viewJacobian));
76c4762a1bSJed Brown 
77c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
78c4762a1bSJed Brown      Create timestepping solver context
79c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
805f80ce2aSJacob Faibussowitsch   CHKERRQ(TSCreate(PETSC_COMM_WORLD,&ts));
815f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetProblemType(ts,TS_NONLINEAR));
825f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetType(ts,TSTHETA));
835f80ce2aSJacob Faibussowitsch   CHKERRQ(TSThetaSetTheta(ts,1.0)); /* Make the Theta method behave like backward Euler */
845f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetIFunction(ts,NULL,FormIFunction,&user));
85c4762a1bSJed Brown 
865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetMatType(da,MATAIJ));
875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateMatrix(da,&J));
88c4762a1bSJed Brown   jacType = JACOBIAN_ANALYTIC; /* use user-provide Jacobian */
89c4762a1bSJed Brown 
905f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetDM(ts,da)); /* Use TSGetDM() to access. Setting here allows easy use of geometric multigrid. */
91c4762a1bSJed Brown 
92c4762a1bSJed Brown   ftime = 1.0;
935f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxTime(ts,ftime));
945f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER));
95c4762a1bSJed Brown 
96c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97c4762a1bSJed Brown      Set initial conditions
98c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
995f80ce2aSJacob Faibussowitsch   CHKERRQ(FormInitialSolution(ts,u,&user));
1005f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetSolution(ts,u));
101c4762a1bSJed Brown   dt   = .01;
1025f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(ts,dt));
103c4762a1bSJed Brown 
104c4762a1bSJed Brown   /* Use slow fd Jacobian or fast fd Jacobian with colorings.
105c4762a1bSJed Brown      Note: this requirs snes which is not created until TSSetUp()/TSSetFromOptions() is called */
106c4762a1bSJed Brown   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Options for Jacobian evaluation",NULL);CHKERRQ(ierr);
1075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-jac_type","Type of Jacobian","",JacobianTypes,(PetscEnum)jacType,(PetscEnum*)&jacType,0));
108c4762a1bSJed Brown   ierr = PetscOptionsEnd();CHKERRQ(ierr);
109c4762a1bSJed Brown   if (jacType == JACOBIAN_ANALYTIC) {
1105f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetIJacobian(ts,J,J,FormIJacobian,&user));
111c4762a1bSJed Brown   } else if (jacType == JACOBIAN_FD_COLORING) {
112c4762a1bSJed Brown     SNES snes;
1135f80ce2aSJacob Faibussowitsch     CHKERRQ(TSGetSNES(ts,&snes));
1145f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,0));
115c4762a1bSJed Brown   } else if (jacType == JACOBIAN_FD_FULL) {
116c4762a1bSJed Brown     SNES snes;
1175f80ce2aSJacob Faibussowitsch     CHKERRQ(TSGetSNES(ts,&snes));
1185f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESSetJacobian(snes,J,J,SNESComputeJacobianDefault,&user));
119c4762a1bSJed Brown   }
120c4762a1bSJed Brown 
121c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
122c4762a1bSJed Brown      Set runtime options
123c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1245f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetFromOptions(ts));
125c4762a1bSJed Brown 
126c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
127c4762a1bSJed Brown      Integrate ODE system
128c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1295f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSolve(ts,u));
130c4762a1bSJed Brown 
131c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132c4762a1bSJed Brown    Compute diagnostics of the solution
133c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1345f80ce2aSJacob Faibussowitsch   CHKERRQ(VecNorm(u,NORM_1,&norm));
1355f80ce2aSJacob Faibussowitsch   CHKERRQ(VecMax(u,NULL,&vmax));
1365f80ce2aSJacob Faibussowitsch   CHKERRQ(VecMin(u,NULL,&vmin));
1375f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetStepNumber(ts,&nsteps));
1385f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetTime(ts,&ftime));
1395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"timestep %D: time %g, solution norm %g, max %g, min %g\n",nsteps,(double)ftime,(double)norm,(double)vmax,(double)vmin));
140c4762a1bSJed Brown 
141c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
142c4762a1bSJed Brown      Free work space.
143c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1445f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&J));
1455f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&u));
1465f80ce2aSJacob Faibussowitsch   CHKERRQ(TSDestroy(&ts));
1475f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&da));
148*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscFinalize());
149*b122ec5aSJacob Faibussowitsch   return 0;
150c4762a1bSJed Brown }
151c4762a1bSJed Brown /* ------------------------------------------------------------------- */
152c4762a1bSJed Brown static PetscErrorCode FormIFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr)
153c4762a1bSJed Brown {
154c4762a1bSJed Brown   AppCtx         *user=(AppCtx*)ptr;
155c4762a1bSJed Brown   DM             da;
156c4762a1bSJed Brown   PetscInt       i,Mx,xs,xm;
157c4762a1bSJed Brown   PetscReal      hx,sx;
158c4762a1bSJed Brown   PetscScalar    *u,*udot,*f;
159c4762a1bSJed Brown   Vec            localU;
160c4762a1bSJed Brown 
161c4762a1bSJed Brown   PetscFunctionBeginUser;
1625f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts,&da));
1635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalVector(da,&localU));
1645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE));
165c4762a1bSJed Brown 
166c4762a1bSJed Brown   hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
167c4762a1bSJed Brown 
168c4762a1bSJed Brown   /*
169c4762a1bSJed Brown      Scatter ghost points to local vector,using the 2-step process
170c4762a1bSJed Brown         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
171c4762a1bSJed Brown      By placing code between these two statements, computations can be
172c4762a1bSJed Brown      done while messages are in transition.
173c4762a1bSJed Brown   */
1745f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU));
1755f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU));
176c4762a1bSJed Brown 
177c4762a1bSJed Brown   /* Get pointers to vector data */
1785f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArrayRead(da,localU,&u));
1795f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArrayRead(da,Udot,&udot));
1805f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArray(da,F,&f));
181c4762a1bSJed Brown 
182c4762a1bSJed Brown   /* Get local grid boundaries */
1835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL));
184c4762a1bSJed Brown 
185c4762a1bSJed Brown   /* Compute function over the locally owned part of the grid */
186c4762a1bSJed Brown   for (i=xs; i<xs+xm; i++) {
187c4762a1bSJed Brown     if (user->boundary == 0) { /* Dirichlet BC */
188c4762a1bSJed Brown       if (i == 0 || i == Mx-1) f[i] = u[i]; /* F = U */
189c4762a1bSJed Brown       else                     f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx;
190c4762a1bSJed Brown     } else { /* Neumann BC */
191c4762a1bSJed Brown       if (i == 0)         f[i] = u[0] - u[1];
192c4762a1bSJed Brown       else if (i == Mx-1) f[i] = u[i] - u[i-1];
193c4762a1bSJed Brown       else                f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx;
194c4762a1bSJed Brown     }
195c4762a1bSJed Brown   }
196c4762a1bSJed Brown 
197c4762a1bSJed Brown   /* Restore vectors */
1985f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecRestoreArrayRead(da,localU,&u));
1995f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecRestoreArrayRead(da,Udot,&udot));
2005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecRestoreArray(da,F,&f));
2015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreLocalVector(da,&localU));
202c4762a1bSJed Brown   PetscFunctionReturn(0);
203c4762a1bSJed Brown }
204c4762a1bSJed Brown 
205c4762a1bSJed Brown /* --------------------------------------------------------------------- */
206c4762a1bSJed Brown /*
207c4762a1bSJed Brown   IJacobian - Compute IJacobian = dF/dU + a dF/dUdot
208c4762a1bSJed Brown */
209c4762a1bSJed Brown PetscErrorCode FormIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat J,Mat Jpre,void *ctx)
210c4762a1bSJed Brown {
211c4762a1bSJed Brown   PetscInt       i,rstart,rend,Mx;
212c4762a1bSJed Brown   PetscReal      hx,sx;
213c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ctx;
214c4762a1bSJed Brown   DM             da;
215c4762a1bSJed Brown   MatStencil     col[3],row;
216c4762a1bSJed Brown   PetscInt       nc;
217c4762a1bSJed Brown   PetscScalar    vals[3];
218c4762a1bSJed Brown 
219c4762a1bSJed Brown   PetscFunctionBeginUser;
2205f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts,&da));
2215f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRange(Jpre,&rstart,&rend));
2225f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE));
223c4762a1bSJed Brown   hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
224c4762a1bSJed Brown   for (i=rstart; i<rend; i++) {
225c4762a1bSJed Brown     nc    = 0;
226c4762a1bSJed Brown     row.i = i;
227c4762a1bSJed Brown     if (user->boundary == 0 && (i == 0 || i == Mx-1)) {
228c4762a1bSJed Brown       col[nc].i = i; vals[nc++] = 1.0;
229c4762a1bSJed Brown     } else if (user->boundary > 0 && i == 0) { /* Left Neumann */
230c4762a1bSJed Brown       col[nc].i = i;   vals[nc++] = 1.0;
231c4762a1bSJed Brown       col[nc].i = i+1; vals[nc++] = -1.0;
232c4762a1bSJed Brown     } else if (user->boundary > 0 && i == Mx-1) { /* Right Neumann */
233c4762a1bSJed Brown       col[nc].i = i-1; vals[nc++] = -1.0;
234c4762a1bSJed Brown       col[nc].i = i;   vals[nc++] = 1.0;
235c4762a1bSJed Brown     } else {                    /* Interior */
236c4762a1bSJed Brown       col[nc].i = i-1; vals[nc++] = -1.0*sx;
237c4762a1bSJed Brown       col[nc].i = i;   vals[nc++] = 2.0*sx + a;
238c4762a1bSJed Brown       col[nc].i = i+1; vals[nc++] = -1.0*sx;
239c4762a1bSJed Brown     }
2405f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesStencil(Jpre,1,&row,nc,col,vals,INSERT_VALUES));
241c4762a1bSJed Brown   }
242c4762a1bSJed Brown 
2435f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(Jpre,MAT_FINAL_ASSEMBLY));
2445f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(Jpre,MAT_FINAL_ASSEMBLY));
245c4762a1bSJed Brown   if (J != Jpre) {
2465f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY));
2475f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY));
248c4762a1bSJed Brown   }
249c4762a1bSJed Brown   if (user->viewJacobian) {
2505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Jpre:\n"));
2515f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView(Jpre,PETSC_VIEWER_STDOUT_WORLD));
252c4762a1bSJed Brown   }
253c4762a1bSJed Brown   PetscFunctionReturn(0);
254c4762a1bSJed Brown }
255c4762a1bSJed Brown 
256c4762a1bSJed Brown /* ------------------------------------------------------------------- */
257c4762a1bSJed Brown PetscErrorCode FormInitialSolution(TS ts,Vec U,void *ptr)
258c4762a1bSJed Brown {
259c4762a1bSJed Brown   AppCtx         *user=(AppCtx*)ptr;
260c4762a1bSJed Brown   PetscReal      c    =user->c;
261c4762a1bSJed Brown   DM             da;
262c4762a1bSJed Brown   PetscInt       i,xs,xm,Mx;
263c4762a1bSJed Brown   PetscScalar    *u;
264c4762a1bSJed Brown   PetscReal      hx,x,r;
265c4762a1bSJed Brown 
266c4762a1bSJed Brown   PetscFunctionBeginUser;
2675f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts,&da));
2685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE));
269c4762a1bSJed Brown 
270c4762a1bSJed Brown   hx = 1.0/(PetscReal)(Mx-1);
271c4762a1bSJed Brown 
272c4762a1bSJed Brown   /* Get pointers to vector data */
2735f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArray(da,U,&u));
274c4762a1bSJed Brown 
275c4762a1bSJed Brown   /* Get local grid boundaries */
2765f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL));
277c4762a1bSJed Brown 
278c4762a1bSJed Brown   /* Compute function over the locally owned part of the grid */
279c4762a1bSJed Brown   for (i=xs; i<xs+xm; i++) {
280c4762a1bSJed Brown     x = i*hx;
281c4762a1bSJed Brown     r = PetscSqrtReal((x-.5)*(x-.5));
282c4762a1bSJed Brown     if (r < .125) u[i] = PetscExpReal(c*r*r*r);
283c4762a1bSJed Brown     else          u[i] = 0.0;
284c4762a1bSJed Brown   }
285c4762a1bSJed Brown 
286c4762a1bSJed Brown   /* Restore vectors */
2875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecRestoreArray(da,U,&u));
288c4762a1bSJed Brown   PetscFunctionReturn(0);
289c4762a1bSJed Brown }
290c4762a1bSJed Brown 
291c4762a1bSJed Brown /*TEST
292c4762a1bSJed Brown 
293c4762a1bSJed Brown     test:
294c4762a1bSJed Brown       requires: !single
295c4762a1bSJed Brown       args: -da_grid_x 40 -ts_max_steps 2 -snes_monitor_short -ksp_monitor_short -ts_monitor
296c4762a1bSJed Brown 
297c4762a1bSJed Brown     test:
298c4762a1bSJed Brown       suffix: 2
299c4762a1bSJed Brown       requires: !single
300c4762a1bSJed Brown       args: -da_grid_x 100 -ts_type theta -ts_theta_theta 0.5
301c4762a1bSJed Brown 
302c4762a1bSJed Brown TEST*/
303