xref: /petsc/src/ts/tests/ex24.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
15591c571SHong Zhang static char help[] = "Test TSComputeIJacobian()\n\n";
25591c571SHong Zhang 
35591c571SHong Zhang #include <petscsys.h>
45591c571SHong Zhang #include <petscdm.h>
55591c571SHong Zhang #include <petscdmda.h>
65591c571SHong Zhang #include <petscts.h>
75591c571SHong Zhang 
85591c571SHong Zhang typedef struct {
95591c571SHong Zhang   PetscScalar u, v;
105591c571SHong Zhang } Field;
115591c571SHong Zhang 
125591c571SHong Zhang typedef struct {
135591c571SHong Zhang   PetscReal D1, D2, gamma, kappa;
145591c571SHong Zhang } AppCtx;
155591c571SHong Zhang 
169371c9d4SSatish Balay PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat BB, void *ctx) {
175591c571SHong Zhang   AppCtx     *appctx = (AppCtx *)ctx; /* user-defined application context */
185591c571SHong Zhang   DM          da;
195591c571SHong Zhang   PetscInt    i, j, Mx, My, xs, ys, xm, ym;
205591c571SHong Zhang   PetscReal   hx, hy, sx, sy;
215591c571SHong Zhang   PetscScalar uc, vc;
225591c571SHong Zhang   Field     **u;
235591c571SHong Zhang   Vec         localU;
245591c571SHong Zhang   MatStencil  stencil[6], rowstencil;
255591c571SHong Zhang   PetscScalar entries[6];
265591c571SHong Zhang 
277510d9b0SBarry Smith   PetscFunctionBeginUser;
289566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &da));
299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(da, &localU));
309566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, PETSC_IGNORE, &Mx, &My, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE));
315591c571SHong Zhang 
329371c9d4SSatish Balay   hx = 2.50 / (PetscReal)Mx;
339371c9d4SSatish Balay   sx = 1.0 / (hx * hx);
349371c9d4SSatish Balay   hy = 2.50 / (PetscReal)My;
359371c9d4SSatish Balay   sy = 1.0 / (hy * hy);
365591c571SHong Zhang 
375591c571SHong Zhang   /*
385591c571SHong Zhang      Scatter ghost points to local vector,using the 2-step process
395591c571SHong Zhang         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
405591c571SHong Zhang      By placing code between these two statements, computations can be
415591c571SHong Zhang      done while messages are in transition.
425591c571SHong Zhang   */
439566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(da, U, INSERT_VALUES, localU));
449566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(da, U, INSERT_VALUES, localU));
455591c571SHong Zhang 
465591c571SHong Zhang   /*
475591c571SHong Zhang      Get pointers to vector data
485591c571SHong Zhang   */
499566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArrayRead(da, localU, &u));
505591c571SHong Zhang 
515591c571SHong Zhang   /*
525591c571SHong Zhang      Get local grid boundaries
535591c571SHong Zhang   */
549566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL));
555591c571SHong Zhang 
565591c571SHong Zhang   stencil[0].k = 0;
575591c571SHong Zhang   stencil[1].k = 0;
585591c571SHong Zhang   stencil[2].k = 0;
595591c571SHong Zhang   stencil[3].k = 0;
605591c571SHong Zhang   stencil[4].k = 0;
615591c571SHong Zhang   stencil[5].k = 0;
625591c571SHong Zhang   rowstencil.k = 0;
635591c571SHong Zhang   /*
645591c571SHong Zhang      Compute function over the locally owned part of the grid
655591c571SHong Zhang   */
665591c571SHong Zhang   for (j = ys; j < ys + ym; j++) {
675591c571SHong Zhang     stencil[0].j = j - 1;
685591c571SHong Zhang     stencil[1].j = j + 1;
695591c571SHong Zhang     stencil[2].j = j;
705591c571SHong Zhang     stencil[3].j = j;
715591c571SHong Zhang     stencil[4].j = j;
725591c571SHong Zhang     stencil[5].j = j;
739371c9d4SSatish Balay     rowstencil.k = 0;
749371c9d4SSatish Balay     rowstencil.j = j;
755591c571SHong Zhang     for (i = xs; i < xs + xm; i++) {
765591c571SHong Zhang       uc = u[j][i].u;
775591c571SHong Zhang       vc = u[j][i].v;
785591c571SHong Zhang 
795591c571SHong Zhang       /*      uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
805591c571SHong Zhang       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
815591c571SHong Zhang 
825591c571SHong Zhang       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
835591c571SHong Zhang       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
845591c571SHong Zhang        f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);*/
855591c571SHong Zhang 
869371c9d4SSatish Balay       stencil[0].i = i;
879371c9d4SSatish Balay       stencil[0].c = 0;
889371c9d4SSatish Balay       entries[0]   = appctx->D1 * sy;
899371c9d4SSatish Balay       stencil[1].i = i;
909371c9d4SSatish Balay       stencil[1].c = 0;
919371c9d4SSatish Balay       entries[1]   = appctx->D1 * sy;
929371c9d4SSatish Balay       stencil[2].i = i - 1;
939371c9d4SSatish Balay       stencil[2].c = 0;
949371c9d4SSatish Balay       entries[2]   = appctx->D1 * sx;
959371c9d4SSatish Balay       stencil[3].i = i + 1;
969371c9d4SSatish Balay       stencil[3].c = 0;
979371c9d4SSatish Balay       entries[3]   = appctx->D1 * sx;
989371c9d4SSatish Balay       stencil[4].i = i;
999371c9d4SSatish Balay       stencil[4].c = 0;
1009371c9d4SSatish Balay       entries[4]   = -2.0 * appctx->D1 * (sx + sy) - vc * vc - appctx->gamma;
1019371c9d4SSatish Balay       stencil[5].i = i;
1029371c9d4SSatish Balay       stencil[5].c = 1;
1039371c9d4SSatish Balay       entries[5]   = -2.0 * uc * vc;
1049371c9d4SSatish Balay       rowstencil.i = i;
1059371c9d4SSatish Balay       rowstencil.c = 0;
1065591c571SHong Zhang 
1079566063dSJacob Faibussowitsch       PetscCall(MatSetValuesStencil(A, 1, &rowstencil, 6, stencil, entries, INSERT_VALUES));
1089371c9d4SSatish Balay       stencil[0].c = 1;
1099371c9d4SSatish Balay       entries[0]   = appctx->D2 * sy;
1109371c9d4SSatish Balay       stencil[1].c = 1;
1119371c9d4SSatish Balay       entries[1]   = appctx->D2 * sy;
1129371c9d4SSatish Balay       stencil[2].c = 1;
1139371c9d4SSatish Balay       entries[2]   = appctx->D2 * sx;
1149371c9d4SSatish Balay       stencil[3].c = 1;
1159371c9d4SSatish Balay       entries[3]   = appctx->D2 * sx;
1169371c9d4SSatish Balay       stencil[4].c = 1;
1179371c9d4SSatish Balay       entries[4]   = -2.0 * appctx->D2 * (sx + sy) + 2.0 * uc * vc - appctx->gamma - appctx->kappa;
1189371c9d4SSatish Balay       stencil[5].c = 0;
1199371c9d4SSatish Balay       entries[5]   = vc * vc;
1205591c571SHong Zhang       rowstencil.c = 1;
1215591c571SHong Zhang 
1229566063dSJacob Faibussowitsch       PetscCall(MatSetValuesStencil(A, 1, &rowstencil, 6, stencil, entries, INSERT_VALUES));
1235591c571SHong Zhang       /* f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc; */
1245591c571SHong Zhang     }
1255591c571SHong Zhang   }
1265591c571SHong Zhang 
1275591c571SHong Zhang   /*
1285591c571SHong Zhang      Restore vectors
1295591c571SHong Zhang   */
1309566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(19 * xm * ym));
1319566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArrayRead(da, localU, &u));
1329566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(da, &localU));
1339566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1349566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1359566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
1365591c571SHong Zhang   PetscFunctionReturn(0);
1375591c571SHong Zhang }
1385591c571SHong Zhang 
1399371c9d4SSatish Balay PetscErrorCode InitialConditions(DM da, Vec U) {
1405591c571SHong Zhang   PetscInt  i, j, xs, ys, xm, ym, Mx, My;
1415591c571SHong Zhang   Field   **u;
1425591c571SHong Zhang   PetscReal hx, hy, x, y;
1435591c571SHong Zhang 
1447510d9b0SBarry Smith   PetscFunctionBeginUser;
1459566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, PETSC_IGNORE, &Mx, &My, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE));
1465591c571SHong Zhang 
1475591c571SHong Zhang   hx = 2.5 / (PetscReal)Mx;
1485591c571SHong Zhang   hy = 2.5 / (PetscReal)My;
1495591c571SHong Zhang 
1505591c571SHong Zhang   /*
1515591c571SHong Zhang      Get pointers to vector data
1525591c571SHong Zhang   */
1539566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(da, U, &u));
1545591c571SHong Zhang 
1555591c571SHong Zhang   /*
1565591c571SHong Zhang      Get local grid boundaries
1575591c571SHong Zhang   */
1589566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL));
1595591c571SHong Zhang 
1605591c571SHong Zhang   /*
1615591c571SHong Zhang      Compute function over the locally owned part of the grid
1625591c571SHong Zhang   */
1635591c571SHong Zhang   for (j = ys; j < ys + ym; j++) {
1645591c571SHong Zhang     y = j * hy;
1655591c571SHong Zhang     for (i = xs; i < xs + xm; i++) {
1665591c571SHong Zhang       x = i * hx;
1675591c571SHong Zhang       if ((1.0 <= x) && (x <= 1.5) && (1.0 <= y) && (y <= 1.5)) u[j][i].v = .25 * PetscPowReal(PetscSinReal(4.0 * PETSC_PI * x), 2.0) * PetscPowReal(PetscSinReal(4.0 * PETSC_PI * y), 2.0);
1685591c571SHong Zhang       else u[j][i].v = 0.0;
1695591c571SHong Zhang 
1705591c571SHong Zhang       u[j][i].u = 1.0 - 2.0 * u[j][i].v;
1715591c571SHong Zhang     }
1725591c571SHong Zhang   }
1735591c571SHong Zhang 
1745591c571SHong Zhang   /*
1755591c571SHong Zhang      Restore vectors
1765591c571SHong Zhang   */
1779566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(da, U, &u));
1785591c571SHong Zhang   PetscFunctionReturn(0);
1795591c571SHong Zhang }
1805591c571SHong Zhang 
1819371c9d4SSatish Balay int main(int argc, char **argv) {
1825591c571SHong Zhang   TS        ts;
1835591c571SHong Zhang   Vec       U, Udot;
1845591c571SHong Zhang   Mat       Jac, Jac2;
1855591c571SHong Zhang   DM        da;
1865591c571SHong Zhang   AppCtx    appctx;
1875591c571SHong Zhang   PetscReal t = 0, shift, norm;
1885591c571SHong Zhang 
189327415f7SBarry Smith   PetscFunctionBeginUser;
1909566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
1915591c571SHong Zhang 
1925591c571SHong Zhang   appctx.D1    = 8.0e-5;
1935591c571SHong Zhang   appctx.D2    = 4.0e-5;
1945591c571SHong Zhang   appctx.gamma = .024;
1955591c571SHong Zhang   appctx.kappa = .06;
1965591c571SHong Zhang 
1975591c571SHong Zhang   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1985591c571SHong Zhang      Create distributed array (DMDA) to manage parallel grid and vectors
1995591c571SHong Zhang   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2009566063dSJacob Faibussowitsch   PetscCall(DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC, DMDA_STENCIL_STAR, 64, 64, PETSC_DECIDE, PETSC_DECIDE, 2, 1, NULL, NULL, &da));
2019566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(da));
2029566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da));
2039566063dSJacob Faibussowitsch   PetscCall(DMDASetFieldName(da, 0, "u"));
2049566063dSJacob Faibussowitsch   PetscCall(DMDASetFieldName(da, 1, "v"));
2059566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(da, MATAIJ));
2069566063dSJacob Faibussowitsch   PetscCall(DMCreateMatrix(da, &Jac));
2079566063dSJacob Faibussowitsch   PetscCall(DMCreateMatrix(da, &Jac2));
2085591c571SHong Zhang 
2095591c571SHong Zhang   /*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2105591c571SHong Zhang      Extract global vectors from DMDA; then duplicate for remaining
2115591c571SHong Zhang      vectors that are the same types
2125591c571SHong Zhang    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2139566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(da, &U));
2149566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(U, &Udot));
2159566063dSJacob Faibussowitsch   PetscCall(VecSet(Udot, 0.0));
2165591c571SHong Zhang 
2175591c571SHong Zhang   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2185591c571SHong Zhang      Create timestepping solver context
2195591c571SHong Zhang      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2209566063dSJacob Faibussowitsch   PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
2219566063dSJacob Faibussowitsch   PetscCall(TSSetDM(ts, da));
2229566063dSJacob Faibussowitsch   PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
2239566063dSJacob Faibussowitsch   PetscCall(TSSetRHSJacobian(ts, Jac, Jac, RHSJacobian, &appctx));
2245591c571SHong Zhang 
2255591c571SHong Zhang   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2265591c571SHong Zhang      Set initial conditions
2275591c571SHong Zhang    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2289566063dSJacob Faibussowitsch   PetscCall(InitialConditions(da, U));
2299566063dSJacob Faibussowitsch   PetscCall(TSSetSolution(ts, U));
2309566063dSJacob Faibussowitsch   PetscCall(TSSetFromOptions(ts));
2319566063dSJacob Faibussowitsch   PetscCall(TSSetUp(ts));
2325591c571SHong Zhang 
2335591c571SHong Zhang   shift = 2.;
2349566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, t, U, Udot, shift, Jac2, Jac2, PETSC_FALSE));
2355591c571SHong Zhang   shift = 1.;
2369566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, t, U, Udot, shift, Jac, Jac, PETSC_FALSE));
2375591c571SHong Zhang   shift = 2.;
2389566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, t, U, Udot, shift, Jac, Jac, PETSC_FALSE));
2399566063dSJacob Faibussowitsch   PetscCall(MatAXPY(Jac, -1, Jac2, SAME_NONZERO_PATTERN));
2409566063dSJacob Faibussowitsch   PetscCall(MatNorm(Jac, NORM_INFINITY, &norm));
241*48a46eb9SPierre Jolivet   if (norm > 100.0 * PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error Norm %g \n Incorrect behaviour of TSComputeIJacobian(). The two matrices should have the same results.\n", (double)norm));
2429566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Jac));
2439566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Jac2));
2449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&U));
2459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Udot));
2469566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts));
2479566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&da));
2489566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
249b122ec5aSJacob Faibussowitsch   return 0;
2505591c571SHong Zhang }
2515591c571SHong Zhang 
2525591c571SHong Zhang /*TEST
2535591c571SHong Zhang   test:
2545591c571SHong Zhang 
2555591c571SHong Zhang TEST*/
256