1c4762a1bSJed Brown static const char help[] = "Call PetscInitialize multiple times.\n";
2c4762a1bSJed Brown /*
3c4762a1bSJed Brown This example is based on the Brusselator tutorial of the same name, but tests multiple calls to PetscInitialize().
4c4762a1bSJed Brown This is a bad "convergence study" because it only compares min and max values of the solution rather than comparing
5c4762a1bSJed Brown norms of the errors. For convergence studies, we recommend invoking PetscInitialize() only once and comparing norms
6c4762a1bSJed Brown of errors (perhaps estimated using an accurate reference solution).
7c4762a1bSJed Brown
8c4762a1bSJed Brown Time-dependent Brusselator reaction-diffusion PDE in 1d. Demonstrates IMEX methods and multiple solves.
9c4762a1bSJed Brown
10c4762a1bSJed Brown u_t - alpha u_xx = A + u^2 v - (B+1) u
11c4762a1bSJed Brown v_t - alpha v_xx = B u - u^2 v
12c4762a1bSJed Brown 0 < x < 1;
13c4762a1bSJed Brown A = 1, B = 3, alpha = 1/10
14c4762a1bSJed Brown
15c4762a1bSJed Brown Initial conditions:
16c4762a1bSJed Brown u(x,0) = 1 + sin(2 pi x)
17c4762a1bSJed Brown v(x,0) = 3
18c4762a1bSJed Brown
19c4762a1bSJed Brown Boundary conditions:
20c4762a1bSJed Brown u(0,t) = u(1,t) = 1
21c4762a1bSJed Brown v(0,t) = v(1,t) = 3
22c4762a1bSJed Brown */
23c4762a1bSJed Brown
24c4762a1bSJed Brown #include <petscdm.h>
25c4762a1bSJed Brown #include <petscdmda.h>
26c4762a1bSJed Brown #include <petscts.h>
27c4762a1bSJed Brown
28c4762a1bSJed Brown typedef struct {
29c4762a1bSJed Brown PetscScalar u, v;
30c4762a1bSJed Brown } Field;
31c4762a1bSJed Brown
32c4762a1bSJed Brown typedef struct _User *User;
33c4762a1bSJed Brown struct _User {
34c4762a1bSJed Brown PetscReal A, B; /* Reaction coefficients */
35c4762a1bSJed Brown PetscReal alpha; /* Diffusion coefficient */
36c4762a1bSJed Brown PetscReal uleft, uright; /* Dirichlet boundary conditions */
37c4762a1bSJed Brown PetscReal vleft, vright; /* Dirichlet boundary conditions */
38c4762a1bSJed Brown };
39c4762a1bSJed Brown
40c4762a1bSJed Brown static PetscErrorCode FormRHSFunction(TS, PetscReal, Vec, Vec, void *);
41c4762a1bSJed Brown static PetscErrorCode FormIFunction(TS, PetscReal, Vec, Vec, Vec, void *);
42c4762a1bSJed Brown static PetscErrorCode FormIJacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *);
43c4762a1bSJed Brown static PetscErrorCode FormInitialSolution(TS, Vec, void *);
443ba16761SJacob Faibussowitsch static PetscErrorCode Brusselator(int, char **, PetscInt);
45c4762a1bSJed Brown
main(int argc,char ** argv)46d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
47d71ae5a4SJacob Faibussowitsch {
483ba16761SJacob Faibussowitsch int ierr = MPI_Init(&argc, &argv);
499371c9d4SSatish Balay if (ierr) return ierr;
503ba16761SJacob Faibussowitsch for (PetscInt cycle = 0; cycle < 4; cycle++) {
513ba16761SJacob Faibussowitsch if (Brusselator(argc, argv, cycle)) return 1;
52c4762a1bSJed Brown }
533ba16761SJacob Faibussowitsch return MPI_Finalize();
54c4762a1bSJed Brown }
55c4762a1bSJed Brown
Brusselator(int argc,char ** argv,PetscInt cycle)56d71ae5a4SJacob Faibussowitsch PetscErrorCode Brusselator(int argc, char **argv, PetscInt cycle)
57d71ae5a4SJacob Faibussowitsch {
58c4762a1bSJed Brown TS ts; /* nonlinear solver */
59c4762a1bSJed Brown Vec X; /* solution, residual vectors */
60c4762a1bSJed Brown Mat J; /* Jacobian matrix */
61c4762a1bSJed Brown PetscInt steps, mx;
62c4762a1bSJed Brown DM da;
63c4762a1bSJed Brown PetscReal ftime, hx, dt, xmax, xmin;
64c4762a1bSJed Brown struct _User user; /* user-defined work context */
65c4762a1bSJed Brown TSConvergedReason reason;
66c4762a1bSJed Brown
67327415f7SBarry Smith PetscFunctionBeginUser;
68c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &argv, NULL, help));
69c4762a1bSJed Brown
70c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
71c4762a1bSJed Brown Create distributed array (DMDA) to manage parallel grid and vectors
72c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
739566063dSJacob Faibussowitsch PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, 11, 2, 2, NULL, &da));
749566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(da));
759566063dSJacob Faibussowitsch PetscCall(DMSetUp(da));
76c4762a1bSJed Brown
77c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
78c4762a1bSJed Brown Extract global vectors from DMDA;
79c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
809566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(da, &X));
81c4762a1bSJed Brown
82c4762a1bSJed Brown /* Initialize user application context */
83d0609cedSBarry Smith PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "Advection-reaction options", "");
84c4762a1bSJed Brown {
85c4762a1bSJed Brown user.A = 1;
86c4762a1bSJed Brown user.B = 3;
87c4762a1bSJed Brown user.alpha = 0.1;
88c4762a1bSJed Brown user.uleft = 1;
89c4762a1bSJed Brown user.uright = 1;
90c4762a1bSJed Brown user.vleft = 3;
91c4762a1bSJed Brown user.vright = 3;
929566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-A", "Reaction rate", "", user.A, &user.A, NULL));
939566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-B", "Reaction rate", "", user.B, &user.B, NULL));
949566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-alpha", "Diffusion coefficient", "", user.alpha, &user.alpha, NULL));
959566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-uleft", "Dirichlet boundary condition", "", user.uleft, &user.uleft, NULL));
969566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-uright", "Dirichlet boundary condition", "", user.uright, &user.uright, NULL));
979566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-vleft", "Dirichlet boundary condition", "", user.vleft, &user.vleft, NULL));
989566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-vright", "Dirichlet boundary condition", "", user.vright, &user.vright, NULL));
99c4762a1bSJed Brown }
100d0609cedSBarry Smith PetscOptionsEnd();
101c4762a1bSJed Brown
102c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
103c4762a1bSJed Brown Create timestepping solver context
104c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1059566063dSJacob Faibussowitsch PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
1069566063dSJacob Faibussowitsch PetscCall(TSSetDM(ts, da));
1079566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSARKIMEX));
1089566063dSJacob Faibussowitsch PetscCall(TSSetRHSFunction(ts, NULL, FormRHSFunction, &user));
1099566063dSJacob Faibussowitsch PetscCall(TSSetIFunction(ts, NULL, FormIFunction, &user));
1109566063dSJacob Faibussowitsch PetscCall(DMSetMatType(da, MATAIJ));
1119566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(da, &J));
1129566063dSJacob Faibussowitsch PetscCall(TSSetIJacobian(ts, J, J, FormIJacobian, &user));
113c4762a1bSJed Brown
114c4762a1bSJed Brown ftime = 1.0;
1159566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts, ftime));
1169566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER));
117c4762a1bSJed Brown
118c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119c4762a1bSJed Brown Set initial conditions
120c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1219566063dSJacob Faibussowitsch PetscCall(FormInitialSolution(ts, X, &user));
1229566063dSJacob Faibussowitsch PetscCall(TSSetSolution(ts, X));
1239566063dSJacob Faibussowitsch PetscCall(VecGetSize(X, &mx));
124c4762a1bSJed Brown hx = 1.0 / (PetscReal)(mx / 2 - 1);
125c4762a1bSJed Brown dt = 0.4 * PetscSqr(hx) / user.alpha; /* Diffusive stability limit */
126c4762a1bSJed Brown dt *= PetscPowRealInt(0.2, cycle); /* Shrink the time step in convergence study. */
1279566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, dt));
1289566063dSJacob Faibussowitsch PetscCall(TSSetTolerances(ts, 1e-3 * PetscPowRealInt(0.5, cycle), NULL, 1e-3 * PetscPowRealInt(0.5, cycle), NULL));
129c4762a1bSJed Brown
130c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131c4762a1bSJed Brown Set runtime options
132c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1339566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts));
134c4762a1bSJed Brown
135c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136c4762a1bSJed Brown Solve nonlinear system
137c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1389566063dSJacob Faibussowitsch PetscCall(TSSolve(ts, X));
1399566063dSJacob Faibussowitsch PetscCall(TSGetSolveTime(ts, &ftime));
1409566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts, &steps));
1419566063dSJacob Faibussowitsch PetscCall(TSGetConvergedReason(ts, &reason));
1429566063dSJacob Faibussowitsch PetscCall(VecMin(X, NULL, &xmin));
1439566063dSJacob Faibussowitsch PetscCall(VecMax(X, NULL, &xmax));
14463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s at time %g after % 3" PetscInt_FMT " steps. Range [%6.4f,%6.4f]\n", TSConvergedReasons[reason], (double)ftime, steps, (double)xmin, (double)xmax));
145c4762a1bSJed Brown
146c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
147c4762a1bSJed Brown Free work space.
148c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J));
1509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X));
1519566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts));
1529566063dSJacob Faibussowitsch PetscCall(DMDestroy(&da));
1539566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
1543ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
155c4762a1bSJed Brown }
156c4762a1bSJed Brown
FormIFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void * ptr)157d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormIFunction(TS ts, PetscReal t, Vec X, Vec Xdot, Vec F, void *ptr)
158d71ae5a4SJacob Faibussowitsch {
159c4762a1bSJed Brown User user = (User)ptr;
160c4762a1bSJed Brown DM da;
161c4762a1bSJed Brown DMDALocalInfo info;
162c4762a1bSJed Brown PetscInt i;
163c4762a1bSJed Brown Field *x, *xdot, *f;
164c4762a1bSJed Brown PetscReal hx;
165c4762a1bSJed Brown Vec Xloc;
166c4762a1bSJed Brown
167c4762a1bSJed Brown PetscFunctionBeginUser;
1689566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
1699566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(da, &info));
170c4762a1bSJed Brown hx = 1.0 / (PetscReal)(info.mx - 1);
171c4762a1bSJed Brown
172c4762a1bSJed Brown /*
173c4762a1bSJed Brown Scatter ghost points to local vector,using the 2-step process
174c4762a1bSJed Brown DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
175c4762a1bSJed Brown By placing code between these two statements, computations can be
176c4762a1bSJed Brown done while messages are in transition.
177c4762a1bSJed Brown */
1789566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da, &Xloc));
1799566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc));
1809566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc));
181c4762a1bSJed Brown
182c4762a1bSJed Brown /* Get pointers to vector data */
1839566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, Xloc, &x));
1849566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, Xdot, &xdot));
1859566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, F, &f));
186c4762a1bSJed Brown
187c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */
188c4762a1bSJed Brown for (i = info.xs; i < info.xs + info.xm; i++) {
189c4762a1bSJed Brown if (i == 0) {
190c4762a1bSJed Brown f[i].u = hx * (x[i].u - user->uleft);
191c4762a1bSJed Brown f[i].v = hx * (x[i].v - user->vleft);
192c4762a1bSJed Brown } else if (i == info.mx - 1) {
193c4762a1bSJed Brown f[i].u = hx * (x[i].u - user->uright);
194c4762a1bSJed Brown f[i].v = hx * (x[i].v - user->vright);
195c4762a1bSJed Brown } else {
196c4762a1bSJed Brown f[i].u = hx * xdot[i].u - user->alpha * (x[i - 1].u - 2. * x[i].u + x[i + 1].u) / hx;
197c4762a1bSJed Brown f[i].v = hx * xdot[i].v - user->alpha * (x[i - 1].v - 2. * x[i].v + x[i + 1].v) / hx;
198c4762a1bSJed Brown }
199c4762a1bSJed Brown }
200c4762a1bSJed Brown
201c4762a1bSJed Brown /* Restore vectors */
2029566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, Xloc, &x));
2039566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, Xdot, &xdot));
2049566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, F, &f));
2059566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da, &Xloc));
2063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
207c4762a1bSJed Brown }
208c4762a1bSJed Brown
FormRHSFunction(TS ts,PetscReal t,Vec X,Vec F,void * ptr)209d71ae5a4SJacob Faibussowitsch static PetscErrorCode FormRHSFunction(TS ts, PetscReal t, Vec X, Vec F, void *ptr)
210d71ae5a4SJacob Faibussowitsch {
211c4762a1bSJed Brown User user = (User)ptr;
212c4762a1bSJed Brown DM da;
213c4762a1bSJed Brown DMDALocalInfo info;
214c4762a1bSJed Brown PetscInt i;
215c4762a1bSJed Brown PetscReal hx;
216c4762a1bSJed Brown Field *x, *f;
217c4762a1bSJed Brown
218c4762a1bSJed Brown PetscFunctionBeginUser;
2199566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
2209566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(da, &info));
221c4762a1bSJed Brown hx = 1.0 / (PetscReal)(info.mx - 1);
222c4762a1bSJed Brown
223c4762a1bSJed Brown /* Get pointers to vector data */
2249566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, X, &x));
2259566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, F, &f));
226c4762a1bSJed Brown
227c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */
228c4762a1bSJed Brown for (i = info.xs; i < info.xs + info.xm; i++) {
229c4762a1bSJed Brown PetscScalar u = x[i].u, v = x[i].v;
230c4762a1bSJed Brown f[i].u = hx * (user->A + u * u * v - (user->B + 1) * u);
231c4762a1bSJed Brown f[i].v = hx * (user->B * u - u * u * v);
232c4762a1bSJed Brown }
233c4762a1bSJed Brown
234c4762a1bSJed Brown /* Restore vectors */
2359566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, X, &x));
2369566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, F, &f));
2373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
238c4762a1bSJed Brown }
239c4762a1bSJed Brown
240c4762a1bSJed Brown /* --------------------------------------------------------------------- */
241c4762a1bSJed Brown /*
242c4762a1bSJed Brown IJacobian - Compute IJacobian = dF/dU + a dF/dUdot
243c4762a1bSJed Brown */
FormIJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat J,Mat Jpre,void * ptr)244d71ae5a4SJacob Faibussowitsch PetscErrorCode FormIJacobian(TS ts, PetscReal t, Vec X, Vec Xdot, PetscReal a, Mat J, Mat Jpre, void *ptr)
245d71ae5a4SJacob Faibussowitsch {
246c4762a1bSJed Brown User user = (User)ptr;
247c4762a1bSJed Brown DMDALocalInfo info;
248c4762a1bSJed Brown PetscInt i;
249c4762a1bSJed Brown PetscReal hx;
250c4762a1bSJed Brown DM da;
251c4762a1bSJed Brown Field *x, *xdot;
252c4762a1bSJed Brown
253c4762a1bSJed Brown PetscFunctionBeginUser;
2549566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
2559566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(da, &info));
256c4762a1bSJed Brown hx = 1.0 / (PetscReal)(info.mx - 1);
257c4762a1bSJed Brown
258c4762a1bSJed Brown /* Get pointers to vector data */
2599566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, X, &x));
2609566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, Xdot, &xdot));
261c4762a1bSJed Brown
262c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */
263c4762a1bSJed Brown for (i = info.xs; i < info.xs + info.xm; i++) {
264c4762a1bSJed Brown if (i == 0 || i == info.mx - 1) {
265c4762a1bSJed Brown const PetscInt row = i, col = i;
2669371c9d4SSatish Balay const PetscScalar vals[2][2] = {
2679371c9d4SSatish Balay {hx, 0 },
2689371c9d4SSatish Balay {0, hx}
2699371c9d4SSatish Balay };
2709566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(Jpre, 1, &row, 1, &col, &vals[0][0], INSERT_VALUES));
271c4762a1bSJed Brown } else {
272c4762a1bSJed Brown const PetscInt row = i, col[] = {i - 1, i, i + 1};
273c4762a1bSJed Brown const PetscScalar dxxL = -user->alpha / hx, dxx0 = 2. * user->alpha / hx, dxxR = -user->alpha / hx;
2749371c9d4SSatish Balay const PetscScalar vals[2][3][2] = {
2759371c9d4SSatish Balay {{dxxL, 0}, {a * hx + dxx0, 0}, {dxxR, 0}},
2769371c9d4SSatish Balay {{0, dxxL}, {0, a * hx + dxx0}, {0, dxxR}}
2779371c9d4SSatish Balay };
2789566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(Jpre, 1, &row, 3, col, &vals[0][0][0], INSERT_VALUES));
279c4762a1bSJed Brown }
280c4762a1bSJed Brown }
281c4762a1bSJed Brown
282c4762a1bSJed Brown /* Restore vectors */
2839566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, X, &x));
2849566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, Xdot, &xdot));
285c4762a1bSJed Brown
2869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Jpre, MAT_FINAL_ASSEMBLY));
2879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Jpre, MAT_FINAL_ASSEMBLY));
288c4762a1bSJed Brown if (J != Jpre) {
2899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
2909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
291c4762a1bSJed Brown }
2923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
293c4762a1bSJed Brown }
294c4762a1bSJed Brown
FormInitialSolution(TS ts,Vec X,PetscCtx ctx)295*2a8381b2SBarry Smith PetscErrorCode FormInitialSolution(TS ts, Vec X, PetscCtx ctx)
296d71ae5a4SJacob Faibussowitsch {
297c4762a1bSJed Brown User user = (User)ctx;
298c4762a1bSJed Brown DM da;
299c4762a1bSJed Brown PetscInt i;
300c4762a1bSJed Brown DMDALocalInfo info;
301c4762a1bSJed Brown Field *x;
302c4762a1bSJed Brown PetscReal hx;
303c4762a1bSJed Brown
304c4762a1bSJed Brown PetscFunctionBeginUser;
3059566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da));
3069566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(da, &info));
307c4762a1bSJed Brown hx = 1.0 / (PetscReal)(info.mx - 1);
308c4762a1bSJed Brown
309c4762a1bSJed Brown /* Get pointers to vector data */
3109566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, X, &x));
311c4762a1bSJed Brown
312c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */
313c4762a1bSJed Brown for (i = info.xs; i < info.xs + info.xm; i++) {
314c4762a1bSJed Brown PetscReal xi = i * hx;
315c4762a1bSJed Brown x[i].u = user->uleft * (1. - xi) + user->uright * xi + PetscSinReal(2. * PETSC_PI * xi);
316c4762a1bSJed Brown x[i].v = user->vleft * (1. - xi) + user->vright * xi;
317c4762a1bSJed Brown }
3189566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, X, &x));
3193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
320c4762a1bSJed Brown }
321c4762a1bSJed Brown
322c4762a1bSJed Brown /*TEST
323c4762a1bSJed Brown
324c4762a1bSJed Brown test:
325c4762a1bSJed Brown args: -ts_exact_final_time INTERPOLATE -snes_rtol 1.e-3
326c4762a1bSJed Brown
327c4762a1bSJed Brown test:
328c4762a1bSJed Brown suffix: 2
329c4762a1bSJed Brown args: -ts_exact_final_time INTERPOLATE -snes_rtol 1.e-3
330c4762a1bSJed Brown
331c4762a1bSJed Brown TEST*/
332