xref: /petsc/src/ts/tests/ex21.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1c4762a1bSJed Brown static char help[] = "Solves a time-dependent nonlinear PDE.\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /* ------------------------------------------------------------------------
4c4762a1bSJed Brown 
5c4762a1bSJed Brown    This program solves the two-dimensional time-dependent Bratu problem
6c4762a1bSJed Brown        u_t = u_xx +  u_yy + \lambda*exp(u),
7c4762a1bSJed Brown    on the domain 0 <= x,y <= 1,
8c4762a1bSJed Brown    with the boundary conditions
9c4762a1bSJed Brown        u(t,0,y) = 0, u_x(t,1,y) = 0,
10c4762a1bSJed Brown        u(t,x,0) = 0, u_x(t,x,1) = 0,
11c4762a1bSJed Brown    and the initial condition
12c4762a1bSJed Brown        u(0,x,y) = 0.
13c4762a1bSJed Brown    We discretize the right-hand side using finite differences with
14c4762a1bSJed Brown    uniform grid spacings hx,hy:
15c4762a1bSJed Brown        u_xx = (u_{i+1} - 2u_{i} + u_{i-1})/(hx^2)
16c4762a1bSJed Brown        u_yy = (u_{j+1} - 2u_{j} + u_{j-1})/(hy^2)
17c4762a1bSJed Brown 
18c4762a1bSJed Brown   ------------------------------------------------------------------------- */
19c4762a1bSJed Brown 
20c4762a1bSJed Brown #include <petscdmda.h>
21c4762a1bSJed Brown #include <petscts.h>
22c4762a1bSJed Brown 
23c4762a1bSJed Brown /*
24c4762a1bSJed Brown    User-defined application context - contains data needed by the
25c4762a1bSJed Brown    application-provided call-back routines.
26c4762a1bSJed Brown */
27c4762a1bSJed Brown typedef struct {
28c4762a1bSJed Brown   PetscReal lambda;
29c4762a1bSJed Brown } AppCtx;
30c4762a1bSJed Brown 
31c4762a1bSJed Brown /*
32c4762a1bSJed Brown    FormIFunctionLocal - Evaluates nonlinear implicit function on local process patch
33c4762a1bSJed Brown  */
34*9371c9d4SSatish Balay static PetscErrorCode FormIFunctionLocal(DMDALocalInfo *info, PetscReal t, PetscScalar **x, PetscScalar **xdot, PetscScalar **f, AppCtx *app) {
35c4762a1bSJed Brown   PetscInt    i, j;
36c4762a1bSJed Brown   PetscReal   lambda, hx, hy;
37c4762a1bSJed Brown   PetscScalar ut, u, ue, uw, un, us, uxx, uyy;
38c4762a1bSJed Brown 
39c4762a1bSJed Brown   PetscFunctionBeginUser;
40c4762a1bSJed Brown   lambda = app->lambda;
41c4762a1bSJed Brown   hx     = 1.0 / (PetscReal)(info->mx - 1);
42c4762a1bSJed Brown   hy     = 1.0 / (PetscReal)(info->my - 1);
43c4762a1bSJed Brown 
44c4762a1bSJed Brown   /*
45c4762a1bSJed Brown      Compute RHS function over the locally owned part of the grid
46c4762a1bSJed Brown   */
47c4762a1bSJed Brown   for (j = info->ys; j < info->ys + info->ym; j++) {
48c4762a1bSJed Brown     for (i = info->xs; i < info->xs + info->xm; i++) {
49c4762a1bSJed Brown       if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) {
50c4762a1bSJed Brown         /* boundary points */
51c4762a1bSJed Brown         f[j][i] = x[j][i] - (PetscReal)0;
52c4762a1bSJed Brown       } else {
53c4762a1bSJed Brown         /* interior points */
54c4762a1bSJed Brown         ut = xdot[j][i];
55c4762a1bSJed Brown         u  = x[j][i];
56c4762a1bSJed Brown         uw = x[j][i - 1];
57c4762a1bSJed Brown         ue = x[j][i + 1];
58c4762a1bSJed Brown         un = x[j + 1][i];
59c4762a1bSJed Brown         us = x[j - 1][i];
60c4762a1bSJed Brown 
61c4762a1bSJed Brown         uxx     = (uw - 2.0 * u + ue) / (hx * hx);
62c4762a1bSJed Brown         uyy     = (un - 2.0 * u + us) / (hy * hy);
63c4762a1bSJed Brown         f[j][i] = ut - uxx - uyy - lambda * PetscExpScalar(u);
64c4762a1bSJed Brown       }
65c4762a1bSJed Brown     }
66c4762a1bSJed Brown   }
67c4762a1bSJed Brown   PetscFunctionReturn(0);
68c4762a1bSJed Brown }
69c4762a1bSJed Brown 
70c4762a1bSJed Brown /*
71c4762a1bSJed Brown    FormIJacobianLocal - Evaluates implicit Jacobian matrix on local process patch
72c4762a1bSJed Brown */
73*9371c9d4SSatish Balay static PetscErrorCode FormIJacobianLocal(DMDALocalInfo *info, PetscReal t, PetscScalar **x, PetscScalar **xdot, PetscScalar shift, Mat jac, Mat jacpre, AppCtx *app) {
74c4762a1bSJed Brown   PetscInt    i, j, k;
75c4762a1bSJed Brown   MatStencil  col[5], row;
76c4762a1bSJed Brown   PetscScalar v[5], lambda, hx, hy;
77c4762a1bSJed Brown 
78c4762a1bSJed Brown   PetscFunctionBeginUser;
79c4762a1bSJed Brown   lambda = app->lambda;
80c4762a1bSJed Brown   hx     = 1.0 / (PetscReal)(info->mx - 1);
81c4762a1bSJed Brown   hy     = 1.0 / (PetscReal)(info->my - 1);
82c4762a1bSJed Brown 
83c4762a1bSJed Brown   /*
84c4762a1bSJed Brown      Compute Jacobian entries for the locally owned part of the grid
85c4762a1bSJed Brown   */
86c4762a1bSJed Brown   for (j = info->ys; j < info->ys + info->ym; j++) {
87c4762a1bSJed Brown     for (i = info->xs; i < info->xs + info->xm; i++) {
88*9371c9d4SSatish Balay       row.j = j;
89*9371c9d4SSatish Balay       row.i = i;
90*9371c9d4SSatish Balay       k     = 0;
91c4762a1bSJed Brown       if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) {
92c4762a1bSJed Brown         /* boundary points */
93c4762a1bSJed Brown         v[0] = 1.0;
949566063dSJacob Faibussowitsch         PetscCall(MatSetValuesStencil(jacpre, 1, &row, 1, &row, v, INSERT_VALUES));
95c4762a1bSJed Brown       } else {
96c4762a1bSJed Brown         /* interior points */
97*9371c9d4SSatish Balay         v[k]     = -1.0 / (hy * hy);
98*9371c9d4SSatish Balay         col[k].j = j - 1;
99*9371c9d4SSatish Balay         col[k].i = i;
100*9371c9d4SSatish Balay         k++;
101*9371c9d4SSatish Balay         v[k]     = -1.0 / (hx * hx);
102*9371c9d4SSatish Balay         col[k].j = j;
103*9371c9d4SSatish Balay         col[k].i = i - 1;
104*9371c9d4SSatish Balay         k++;
105c4762a1bSJed Brown 
106c4762a1bSJed Brown         v[k]     = shift + 2.0 / (hx * hx) + 2.0 / (hy * hy) - lambda * PetscExpScalar(x[j][i]);
107*9371c9d4SSatish Balay         col[k].j = j;
108*9371c9d4SSatish Balay         col[k].i = i;
109*9371c9d4SSatish Balay         k++;
110c4762a1bSJed Brown 
111*9371c9d4SSatish Balay         v[k]     = -1.0 / (hx * hx);
112*9371c9d4SSatish Balay         col[k].j = j;
113*9371c9d4SSatish Balay         col[k].i = i + 1;
114*9371c9d4SSatish Balay         k++;
115*9371c9d4SSatish Balay         v[k]     = -1.0 / (hy * hy);
116*9371c9d4SSatish Balay         col[k].j = j + 1;
117*9371c9d4SSatish Balay         col[k].i = i;
118*9371c9d4SSatish Balay         k++;
119c4762a1bSJed Brown 
1209566063dSJacob Faibussowitsch         PetscCall(MatSetValuesStencil(jacpre, 1, &row, k, col, v, INSERT_VALUES));
121c4762a1bSJed Brown       }
122c4762a1bSJed Brown     }
123c4762a1bSJed Brown   }
124c4762a1bSJed Brown 
125c4762a1bSJed Brown   /*
126c4762a1bSJed Brown      Assemble matrix
127c4762a1bSJed Brown   */
1289566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(jacpre, MAT_FINAL_ASSEMBLY));
1299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(jacpre, MAT_FINAL_ASSEMBLY));
130c4762a1bSJed Brown   PetscFunctionReturn(0);
131c4762a1bSJed Brown }
132c4762a1bSJed Brown 
133*9371c9d4SSatish Balay int main(int argc, char **argv) {
134c4762a1bSJed Brown   TS              ts; /* ODE integrator */
135c4762a1bSJed Brown   DM              da; /* DM context */
136c4762a1bSJed Brown   Vec             U;  /* solution vector */
137c4762a1bSJed Brown   DMBoundaryType  bt = DM_BOUNDARY_NONE;
138c4762a1bSJed Brown   DMDAStencilType st = DMDA_STENCIL_STAR;
139c4762a1bSJed Brown   PetscInt        sw = 1;
140c4762a1bSJed Brown   PetscInt        N  = 17;
141c4762a1bSJed Brown   PetscInt        n  = PETSC_DECIDE;
142c4762a1bSJed Brown   AppCtx          app;
143c4762a1bSJed Brown 
144c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145c4762a1bSJed Brown      Initialize program
146c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
147327415f7SBarry Smith   PetscFunctionBeginUser;
1489566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
149d0609cedSBarry Smith   PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "ex21 options", "");
150c4762a1bSJed Brown   {
151*9371c9d4SSatish Balay     app.lambda = 6.8;
152*9371c9d4SSatish Balay     app.lambda = 6.0;
1539566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-lambda", "", "", app.lambda, &app.lambda, NULL));
154c4762a1bSJed Brown   }
155d0609cedSBarry Smith   PetscOptionsEnd();
156c4762a1bSJed Brown 
157c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158c4762a1bSJed Brown      Create DM context
159c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1609566063dSJacob Faibussowitsch   PetscCall(DMDACreate2d(PETSC_COMM_WORLD, bt, bt, st, N, N, n, n, 1, sw, NULL, NULL, &da));
1619566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(da));
1629566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da));
1639566063dSJacob Faibussowitsch   PetscCall(DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 1.0, 0, 1.0));
164c4762a1bSJed Brown 
165c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
166c4762a1bSJed Brown      Create timestepping solver context
167c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1689566063dSJacob Faibussowitsch   PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
1699566063dSJacob Faibussowitsch   PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
1709566063dSJacob Faibussowitsch   PetscCall(TSSetDM(ts, da));
1719566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&da));
172c4762a1bSJed Brown 
1739566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &da));
1749566063dSJacob Faibussowitsch   PetscCall(DMDATSSetIFunctionLocal(da, INSERT_VALUES, (DMDATSIFunctionLocal)FormIFunctionLocal, &app));
1759566063dSJacob Faibussowitsch   PetscCall(DMDATSSetIJacobianLocal(da, (DMDATSIJacobianLocal)FormIJacobianLocal, &app));
176c4762a1bSJed Brown 
177c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
178c4762a1bSJed Brown      Set solver options
179c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1809566063dSJacob Faibussowitsch   PetscCall(TSSetType(ts, TSBDF));
1819566063dSJacob Faibussowitsch   PetscCall(TSSetTimeStep(ts, 1e-4));
1829566063dSJacob Faibussowitsch   PetscCall(TSSetMaxTime(ts, 1.0));
1839566063dSJacob Faibussowitsch   PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER));
1849566063dSJacob Faibussowitsch   PetscCall(TSSetFromOptions(ts));
185c4762a1bSJed Brown 
186c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187c4762a1bSJed Brown      Set initial conditions
188c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1899566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &da));
1909566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(da, &U));
1919566063dSJacob Faibussowitsch   PetscCall(VecSet(U, 0.0));
1929566063dSJacob Faibussowitsch   PetscCall(TSSetSolution(ts, U));
193c4762a1bSJed Brown 
194c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
195c4762a1bSJed Brown      Run timestepping solver
196c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1979566063dSJacob Faibussowitsch   PetscCall(TSSolve(ts, U));
198c4762a1bSJed Brown 
199c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
200c4762a1bSJed Brown       All PETSc objects should be destroyed when they are no longer needed.
201c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&U));
2039566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts));
2049566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
205b122ec5aSJacob Faibussowitsch   return 0;
206c4762a1bSJed Brown }
207c4762a1bSJed Brown 
208c4762a1bSJed Brown /*TEST
209c4762a1bSJed Brown 
210c4762a1bSJed Brown     testset:
211c4762a1bSJed Brown       requires: !single !complex
212c4762a1bSJed Brown       args: -da_grid_x 5 -da_grid_y 5 -da_refine 2 -dm_view -ts_type bdf -ts_adapt_type none -ts_dt 1e-3 -ts_monitor -ts_max_steps 5 -ts_view -snes_rtol 1e-6 -snes_type ngmres -npc_snes_type fas
213c4762a1bSJed Brown       filter: grep -v "total number of"
214c4762a1bSJed Brown       test:
215c4762a1bSJed Brown         suffix: 1_bdf_ngmres_fas_ms
216c4762a1bSJed Brown         args: -prefix_push npc_fas_levels_ -snes_type ms -snes_max_it 5 -ksp_type preonly -prefix_pop
217c4762a1bSJed Brown       test:
218c4762a1bSJed Brown         suffix: 2_bdf_ngmres_fas_ms
219c4762a1bSJed Brown         args: -prefix_push npc_fas_levels_ -snes_type ms -snes_max_it 5 -ksp_type preonly -prefix_pop
220c4762a1bSJed Brown         nsize: 2
221c4762a1bSJed Brown       test:
222c4762a1bSJed Brown         suffix: 1_bdf_ngmres_fas_ngs
223c4762a1bSJed Brown         args: -prefix_push npc_fas_levels_ -snes_type ngs -snes_max_it 5 -prefix_pop
224c4762a1bSJed Brown       test:
225c4762a1bSJed Brown         suffix: 2_bdf_ngmres_fas_ngs
226c4762a1bSJed Brown         args: -prefix_push npc_fas_levels_ -snes_type ngs -snes_max_it 5 -prefix_pop
227c4762a1bSJed Brown         nsize: 2
228c4762a1bSJed Brown 
229c4762a1bSJed Brown TEST*/
230