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
269371c9d4SSatish Balay typedef enum {
279371c9d4SSatish Balay JACOBIAN_ANALYTIC,
289371c9d4SSatish Balay JACOBIAN_FD_COLORING,
299371c9d4SSatish Balay JACOBIAN_FD_FULL
309371c9d4SSatish Balay } JacobianType;
31c4762a1bSJed Brown static const char *const JacobianTypes[] = {"analytic", "fd_coloring", "fd_full", "JacobianType", "fd_", 0};
32c4762a1bSJed Brown
33c4762a1bSJed Brown /*
34c4762a1bSJed Brown User-defined data structures and routines
35c4762a1bSJed Brown */
36c4762a1bSJed Brown typedef struct {
37c4762a1bSJed Brown PetscReal c;
38c4762a1bSJed Brown PetscInt boundary; /* Type of boundary condition */
39c4762a1bSJed Brown PetscBool viewJacobian;
40c4762a1bSJed Brown } AppCtx;
41c4762a1bSJed Brown
42c4762a1bSJed Brown static PetscErrorCode FormIFunction(TS, PetscReal, Vec, Vec, Vec, void *);
43c4762a1bSJed Brown static PetscErrorCode FormIJacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *);
44c4762a1bSJed Brown static PetscErrorCode FormInitialSolution(TS, Vec, void *);
45c4762a1bSJed Brown
main(int argc,char ** argv)46d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
47d71ae5a4SJacob Faibussowitsch {
48c4762a1bSJed Brown TS ts; /* nonlinear solver */
49c4762a1bSJed Brown Vec u; /* solution, residual vectors */
50c4762a1bSJed Brown Mat J; /* Jacobian matrix */
51c4762a1bSJed Brown PetscInt nsteps;
52c4762a1bSJed Brown PetscReal vmin, vmax, norm;
53c4762a1bSJed Brown DM da;
54c4762a1bSJed Brown PetscReal ftime, dt;
55c4762a1bSJed Brown AppCtx user; /* user-defined work context */
56c4762a1bSJed Brown JacobianType jacType;
57c4762a1bSJed Brown
58327415f7SBarry Smith PetscFunctionBeginUser;
59c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &argv, NULL, help));
60c4762a1bSJed Brown
61c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62c4762a1bSJed Brown Create distributed array (DMDA) to manage parallel grid and vectors
63c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
649566063dSJacob Faibussowitsch PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, 11, 1, 1, NULL, &da));
659566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(da));
669566063dSJacob Faibussowitsch PetscCall(DMSetUp(da));
67c4762a1bSJed Brown
68c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69c4762a1bSJed Brown Extract global vectors from DMDA;
70c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
719566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(da, &u));
72c4762a1bSJed Brown
73c4762a1bSJed Brown /* Initialize user application context */
74c4762a1bSJed Brown user.c = -30.0;
75c4762a1bSJed Brown user.boundary = 0; /* 0: Dirichlet BC; 1: Neumann BC */
76c4762a1bSJed Brown user.viewJacobian = PETSC_FALSE;
77c4762a1bSJed Brown
789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-boundary", &user.boundary, NULL));
799566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-viewJacobian", &user.viewJacobian));
80c4762a1bSJed Brown
81c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82c4762a1bSJed Brown Create timestepping solver context
83c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
849566063dSJacob Faibussowitsch PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
859566063dSJacob Faibussowitsch PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
869566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSTHETA));
879566063dSJacob Faibussowitsch PetscCall(TSThetaSetTheta(ts, 1.0)); /* Make the Theta method behave like backward Euler */
889566063dSJacob Faibussowitsch PetscCall(TSSetIFunction(ts, NULL, FormIFunction, &user));
89c4762a1bSJed Brown
909566063dSJacob Faibussowitsch PetscCall(DMSetMatType(da, MATAIJ));
919566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(da, &J));
92c4762a1bSJed Brown jacType = JACOBIAN_ANALYTIC; /* use user-provide Jacobian */
93c4762a1bSJed Brown
949566063dSJacob Faibussowitsch PetscCall(TSSetDM(ts, da)); /* Use TSGetDM() to access. Setting here allows easy use of geometric multigrid. */
95c4762a1bSJed Brown
96c4762a1bSJed Brown ftime = 1.0;
979566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts, ftime));
989566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER));
99c4762a1bSJed Brown
100c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101c4762a1bSJed Brown Set initial conditions
102c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1039566063dSJacob Faibussowitsch PetscCall(FormInitialSolution(ts, u, &user));
1049566063dSJacob Faibussowitsch PetscCall(TSSetSolution(ts, u));
105c4762a1bSJed Brown dt = .01;
1069566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, dt));
107c4762a1bSJed Brown
108c4762a1bSJed Brown /* Use slow fd Jacobian or fast fd Jacobian with colorings.
109145b44c9SPierre Jolivet Note: this requires snes which is not created until TSSetUp()/TSSetFromOptions() is called */
110d0609cedSBarry Smith PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "Options for Jacobian evaluation", NULL);
1119566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-jac_type", "Type of Jacobian", "", JacobianTypes, (PetscEnum)jacType, (PetscEnum *)&jacType, 0));
112d0609cedSBarry Smith PetscOptionsEnd();
113c4762a1bSJed Brown if (jacType == JACOBIAN_ANALYTIC) {
1149566063dSJacob Faibussowitsch PetscCall(TSSetIJacobian(ts, J, J, FormIJacobian, &user));
115c4762a1bSJed Brown } else if (jacType == JACOBIAN_FD_COLORING) {
116c4762a1bSJed Brown SNES snes;
1179566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &snes));
1189566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, 0));
119c4762a1bSJed Brown } else if (jacType == JACOBIAN_FD_FULL) {
120c4762a1bSJed Brown SNES snes;
1219566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &snes));
1229566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefault, &user));
123c4762a1bSJed Brown }
124c4762a1bSJed Brown
125c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
126c4762a1bSJed Brown Set runtime options
127c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1289566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts));
129c4762a1bSJed Brown
130c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131c4762a1bSJed Brown Integrate ODE system
132c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1339566063dSJacob Faibussowitsch PetscCall(TSSolve(ts, u));
134c4762a1bSJed Brown
135c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136c4762a1bSJed Brown Compute diagnostics of the solution
137c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1389566063dSJacob Faibussowitsch PetscCall(VecNorm(u, NORM_1, &norm));
1399566063dSJacob Faibussowitsch PetscCall(VecMax(u, NULL, &vmax));
1409566063dSJacob Faibussowitsch PetscCall(VecMin(u, NULL, &vmin));
1419566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts, &nsteps));
1429566063dSJacob Faibussowitsch PetscCall(TSGetTime(ts, &ftime));
14363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "timestep %" PetscInt_FMT ": time %g, solution norm %g, max %g, min %g\n", nsteps, (double)ftime, (double)norm, (double)vmax, (double)vmin));
144c4762a1bSJed Brown
145c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
146c4762a1bSJed Brown Free work space.
147c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J));
1499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&u));
1509566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts));
1519566063dSJacob Faibussowitsch PetscCall(DMDestroy(&da));
1529566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
153b122ec5aSJacob Faibussowitsch return 0;
154c4762a1bSJed Brown }
155c4762a1bSJed Brown /* ------------------------------------------------------------------- */
FormIFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void * ptr)156d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormIFunction(TS ts, PetscReal ftime, Vec U, Vec Udot, Vec F, void *ptr)
157d71ae5a4SJacob Faibussowitsch {
158c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr;
159c4762a1bSJed Brown DM da;
160c4762a1bSJed Brown PetscInt i, Mx, xs, xm;
161c4762a1bSJed Brown PetscReal hx, sx;
162c4762a1bSJed Brown PetscScalar *u, *udot, *f;
163c4762a1bSJed Brown Vec localU;
164c4762a1bSJed Brown
165c4762a1bSJed Brown PetscFunctionBeginUser;
1669566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
1679566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da, &localU));
1689566063dSJacob Faibussowitsch PetscCall(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));
169c4762a1bSJed Brown
1709371c9d4SSatish Balay hx = 1.0 / (PetscReal)(Mx - 1);
1719371c9d4SSatish Balay sx = 1.0 / (hx * hx);
172c4762a1bSJed Brown
173c4762a1bSJed Brown /*
174c4762a1bSJed Brown Scatter ghost points to local vector,using the 2-step process
175c4762a1bSJed Brown DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
176c4762a1bSJed Brown By placing code between these two statements, computations can be
177c4762a1bSJed Brown done while messages are in transition.
178c4762a1bSJed Brown */
1799566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da, U, INSERT_VALUES, localU));
1809566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da, U, INSERT_VALUES, localU));
181c4762a1bSJed Brown
182c4762a1bSJed Brown /* Get pointers to vector data */
1839566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, localU, &u));
1849566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, Udot, &udot));
1859566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, F, &f));
186c4762a1bSJed Brown
187c4762a1bSJed Brown /* Get local grid boundaries */
1889566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &xm, NULL, NULL));
189c4762a1bSJed Brown
190c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */
191c4762a1bSJed Brown for (i = xs; i < xs + xm; i++) {
192c4762a1bSJed Brown if (user->boundary == 0) { /* Dirichlet BC */
193c4762a1bSJed Brown if (i == 0 || i == Mx - 1) f[i] = u[i]; /* F = U */
194c4762a1bSJed Brown else f[i] = udot[i] + (2. * u[i] - u[i - 1] - u[i + 1]) * sx;
195c4762a1bSJed Brown } else { /* Neumann BC */
196c4762a1bSJed Brown if (i == 0) f[i] = u[0] - u[1];
197c4762a1bSJed Brown else if (i == Mx - 1) f[i] = u[i] - u[i - 1];
198c4762a1bSJed Brown else f[i] = udot[i] + (2. * u[i] - u[i - 1] - u[i + 1]) * sx;
199c4762a1bSJed Brown }
200c4762a1bSJed Brown }
201c4762a1bSJed Brown
202c4762a1bSJed Brown /* Restore vectors */
2039566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, localU, &u));
2049566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, Udot, &udot));
2059566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, F, &f));
2069566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da, &localU));
2073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
208c4762a1bSJed Brown }
209c4762a1bSJed Brown
210c4762a1bSJed Brown /* --------------------------------------------------------------------- */
211c4762a1bSJed Brown /*
212c4762a1bSJed Brown IJacobian - Compute IJacobian = dF/dU + a dF/dUdot
213c4762a1bSJed Brown */
FormIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat J,Mat Jpre,PetscCtx ctx)214*2a8381b2SBarry Smith PetscErrorCode FormIJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal a, Mat J, Mat Jpre, PetscCtx ctx)
215d71ae5a4SJacob Faibussowitsch {
216c4762a1bSJed Brown PetscInt i, rstart, rend, Mx;
217c4762a1bSJed Brown PetscReal hx, sx;
218c4762a1bSJed Brown AppCtx *user = (AppCtx *)ctx;
219c4762a1bSJed Brown DM da;
220c4762a1bSJed Brown MatStencil col[3], row;
221c4762a1bSJed Brown PetscInt nc;
222c4762a1bSJed Brown PetscScalar vals[3];
223c4762a1bSJed Brown
224c4762a1bSJed Brown PetscFunctionBeginUser;
2259566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
2269566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Jpre, &rstart, &rend));
2279566063dSJacob Faibussowitsch PetscCall(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));
2289371c9d4SSatish Balay hx = 1.0 / (PetscReal)(Mx - 1);
2299371c9d4SSatish Balay sx = 1.0 / (hx * hx);
230c4762a1bSJed Brown for (i = rstart; i < rend; i++) {
231c4762a1bSJed Brown nc = 0;
232c4762a1bSJed Brown row.i = i;
233c4762a1bSJed Brown if (user->boundary == 0 && (i == 0 || i == Mx - 1)) {
2349371c9d4SSatish Balay col[nc].i = i;
2359371c9d4SSatish Balay vals[nc++] = 1.0;
236c4762a1bSJed Brown } else if (user->boundary > 0 && i == 0) { /* Left Neumann */
2379371c9d4SSatish Balay col[nc].i = i;
2389371c9d4SSatish Balay vals[nc++] = 1.0;
2399371c9d4SSatish Balay col[nc].i = i + 1;
2409371c9d4SSatish Balay vals[nc++] = -1.0;
241c4762a1bSJed Brown } else if (user->boundary > 0 && i == Mx - 1) { /* Right Neumann */
2429371c9d4SSatish Balay col[nc].i = i - 1;
2439371c9d4SSatish Balay vals[nc++] = -1.0;
2449371c9d4SSatish Balay col[nc].i = i;
2459371c9d4SSatish Balay vals[nc++] = 1.0;
246c4762a1bSJed Brown } else { /* Interior */
2479371c9d4SSatish Balay col[nc].i = i - 1;
2489371c9d4SSatish Balay vals[nc++] = -1.0 * sx;
2499371c9d4SSatish Balay col[nc].i = i;
2509371c9d4SSatish Balay vals[nc++] = 2.0 * sx + a;
2519371c9d4SSatish Balay col[nc].i = i + 1;
2529371c9d4SSatish Balay vals[nc++] = -1.0 * sx;
253c4762a1bSJed Brown }
2549566063dSJacob Faibussowitsch PetscCall(MatSetValuesStencil(Jpre, 1, &row, nc, col, vals, INSERT_VALUES));
255c4762a1bSJed Brown }
256c4762a1bSJed Brown
2579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Jpre, MAT_FINAL_ASSEMBLY));
2589566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Jpre, MAT_FINAL_ASSEMBLY));
259c4762a1bSJed Brown if (J != Jpre) {
2609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
2619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
262c4762a1bSJed Brown }
263c4762a1bSJed Brown if (user->viewJacobian) {
2649566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Jpre:\n"));
2659566063dSJacob Faibussowitsch PetscCall(MatView(Jpre, PETSC_VIEWER_STDOUT_WORLD));
266c4762a1bSJed Brown }
2673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
268c4762a1bSJed Brown }
269c4762a1bSJed Brown
270c4762a1bSJed Brown /* ------------------------------------------------------------------- */
FormInitialSolution(TS ts,Vec U,void * ptr)271d71ae5a4SJacob Faibussowitsch PetscErrorCode FormInitialSolution(TS ts, Vec U, void *ptr)
272d71ae5a4SJacob Faibussowitsch {
273c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr;
274c4762a1bSJed Brown PetscReal c = user->c;
275c4762a1bSJed Brown DM da;
276c4762a1bSJed Brown PetscInt i, xs, xm, Mx;
277c4762a1bSJed Brown PetscScalar *u;
278c4762a1bSJed Brown PetscReal hx, x, r;
279c4762a1bSJed Brown
280c4762a1bSJed Brown PetscFunctionBeginUser;
2819566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
2829566063dSJacob Faibussowitsch PetscCall(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));
283c4762a1bSJed Brown
284c4762a1bSJed Brown hx = 1.0 / (PetscReal)(Mx - 1);
285c4762a1bSJed Brown
286c4762a1bSJed Brown /* Get pointers to vector data */
2879566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, U, &u));
288c4762a1bSJed Brown
289c4762a1bSJed Brown /* Get local grid boundaries */
2909566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &xm, NULL, NULL));
291c4762a1bSJed Brown
292c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */
293c4762a1bSJed Brown for (i = xs; i < xs + xm; i++) {
294c4762a1bSJed Brown x = i * hx;
295c4762a1bSJed Brown r = PetscSqrtReal((x - .5) * (x - .5));
296c4762a1bSJed Brown if (r < .125) u[i] = PetscExpReal(c * r * r * r);
297c4762a1bSJed Brown else u[i] = 0.0;
298c4762a1bSJed Brown }
299c4762a1bSJed Brown
300c4762a1bSJed Brown /* Restore vectors */
3019566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, U, &u));
3023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
303c4762a1bSJed Brown }
304c4762a1bSJed Brown
305c4762a1bSJed Brown /*TEST
306c4762a1bSJed Brown
307c4762a1bSJed Brown test:
308c4762a1bSJed Brown requires: !single
309c4762a1bSJed Brown args: -da_grid_x 40 -ts_max_steps 2 -snes_monitor_short -ksp_monitor_short -ts_monitor
310c4762a1bSJed Brown
311c4762a1bSJed Brown test:
312c4762a1bSJed Brown suffix: 2
313c4762a1bSJed Brown requires: !single
314c4762a1bSJed Brown args: -da_grid_x 100 -ts_type theta -ts_theta_theta 0.5
315c4762a1bSJed Brown
316c4762a1bSJed Brown TEST*/
317