xref: /petsc/src/ts/tests/ex24.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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 
RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat BB,PetscCtx ctx)16*2a8381b2SBarry Smith PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat BB, PetscCtx ctx)
17d71ae5a4SJacob Faibussowitsch {
185591c571SHong Zhang   AppCtx     *appctx = (AppCtx *)ctx; /* user-defined application context */
195591c571SHong Zhang   DM          da;
205591c571SHong Zhang   PetscInt    i, j, Mx, My, xs, ys, xm, ym;
215591c571SHong Zhang   PetscReal   hx, hy, sx, sy;
225591c571SHong Zhang   PetscScalar uc, vc;
235591c571SHong Zhang   Field     **u;
245591c571SHong Zhang   Vec         localU;
255591c571SHong Zhang   MatStencil  stencil[6], rowstencil;
265591c571SHong Zhang   PetscScalar entries[6];
275591c571SHong Zhang 
287510d9b0SBarry Smith   PetscFunctionBeginUser;
299566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &da));
309566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(da, &localU));
319566063dSJacob 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));
325591c571SHong Zhang 
339371c9d4SSatish Balay   hx = 2.50 / (PetscReal)Mx;
349371c9d4SSatish Balay   sx = 1.0 / (hx * hx);
359371c9d4SSatish Balay   hy = 2.50 / (PetscReal)My;
369371c9d4SSatish Balay   sy = 1.0 / (hy * hy);
375591c571SHong Zhang 
385591c571SHong Zhang   /*
395591c571SHong Zhang      Scatter ghost points to local vector,using the 2-step process
405591c571SHong Zhang         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
415591c571SHong Zhang      By placing code between these two statements, computations can be
425591c571SHong Zhang      done while messages are in transition.
435591c571SHong Zhang   */
449566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(da, U, INSERT_VALUES, localU));
459566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(da, U, INSERT_VALUES, localU));
465591c571SHong Zhang 
475591c571SHong Zhang   /*
485591c571SHong Zhang      Get pointers to vector data
495591c571SHong Zhang   */
509566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArrayRead(da, localU, &u));
515591c571SHong Zhang 
525591c571SHong Zhang   /*
535591c571SHong Zhang      Get local grid boundaries
545591c571SHong Zhang   */
559566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL));
565591c571SHong Zhang 
575591c571SHong Zhang   stencil[0].k = 0;
585591c571SHong Zhang   stencil[1].k = 0;
595591c571SHong Zhang   stencil[2].k = 0;
605591c571SHong Zhang   stencil[3].k = 0;
615591c571SHong Zhang   stencil[4].k = 0;
625591c571SHong Zhang   stencil[5].k = 0;
635591c571SHong Zhang   rowstencil.k = 0;
645591c571SHong Zhang   /*
655591c571SHong Zhang      Compute function over the locally owned part of the grid
665591c571SHong Zhang   */
675591c571SHong Zhang   for (j = ys; j < ys + ym; j++) {
685591c571SHong Zhang     stencil[0].j = j - 1;
695591c571SHong Zhang     stencil[1].j = j + 1;
705591c571SHong Zhang     stencil[2].j = j;
715591c571SHong Zhang     stencil[3].j = j;
725591c571SHong Zhang     stencil[4].j = j;
735591c571SHong Zhang     stencil[5].j = j;
749371c9d4SSatish Balay     rowstencil.k = 0;
759371c9d4SSatish Balay     rowstencil.j = j;
765591c571SHong Zhang     for (i = xs; i < xs + xm; i++) {
775591c571SHong Zhang       uc = u[j][i].u;
785591c571SHong Zhang       vc = u[j][i].v;
795591c571SHong Zhang 
805591c571SHong Zhang       /*      uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
815591c571SHong Zhang       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
825591c571SHong Zhang 
835591c571SHong Zhang       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
845591c571SHong Zhang       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
855591c571SHong Zhang        f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);*/
865591c571SHong Zhang 
879371c9d4SSatish Balay       stencil[0].i = i;
889371c9d4SSatish Balay       stencil[0].c = 0;
899371c9d4SSatish Balay       entries[0]   = appctx->D1 * sy;
909371c9d4SSatish Balay       stencil[1].i = i;
919371c9d4SSatish Balay       stencil[1].c = 0;
929371c9d4SSatish Balay       entries[1]   = appctx->D1 * sy;
939371c9d4SSatish Balay       stencil[2].i = i - 1;
949371c9d4SSatish Balay       stencil[2].c = 0;
959371c9d4SSatish Balay       entries[2]   = appctx->D1 * sx;
969371c9d4SSatish Balay       stencil[3].i = i + 1;
979371c9d4SSatish Balay       stencil[3].c = 0;
989371c9d4SSatish Balay       entries[3]   = appctx->D1 * sx;
999371c9d4SSatish Balay       stencil[4].i = i;
1009371c9d4SSatish Balay       stencil[4].c = 0;
1019371c9d4SSatish Balay       entries[4]   = -2.0 * appctx->D1 * (sx + sy) - vc * vc - appctx->gamma;
1029371c9d4SSatish Balay       stencil[5].i = i;
1039371c9d4SSatish Balay       stencil[5].c = 1;
1049371c9d4SSatish Balay       entries[5]   = -2.0 * uc * vc;
1059371c9d4SSatish Balay       rowstencil.i = i;
1069371c9d4SSatish Balay       rowstencil.c = 0;
1075591c571SHong Zhang 
1089566063dSJacob Faibussowitsch       PetscCall(MatSetValuesStencil(A, 1, &rowstencil, 6, stencil, entries, INSERT_VALUES));
1099371c9d4SSatish Balay       stencil[0].c = 1;
1109371c9d4SSatish Balay       entries[0]   = appctx->D2 * sy;
1119371c9d4SSatish Balay       stencil[1].c = 1;
1129371c9d4SSatish Balay       entries[1]   = appctx->D2 * sy;
1139371c9d4SSatish Balay       stencil[2].c = 1;
1149371c9d4SSatish Balay       entries[2]   = appctx->D2 * sx;
1159371c9d4SSatish Balay       stencil[3].c = 1;
1169371c9d4SSatish Balay       entries[3]   = appctx->D2 * sx;
1179371c9d4SSatish Balay       stencil[4].c = 1;
1189371c9d4SSatish Balay       entries[4]   = -2.0 * appctx->D2 * (sx + sy) + 2.0 * uc * vc - appctx->gamma - appctx->kappa;
1199371c9d4SSatish Balay       stencil[5].c = 0;
1209371c9d4SSatish Balay       entries[5]   = vc * vc;
1215591c571SHong Zhang       rowstencil.c = 1;
1225591c571SHong Zhang 
1239566063dSJacob Faibussowitsch       PetscCall(MatSetValuesStencil(A, 1, &rowstencil, 6, stencil, entries, INSERT_VALUES));
1245591c571SHong Zhang       /* f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc; */
1255591c571SHong Zhang     }
1265591c571SHong Zhang   }
1275591c571SHong Zhang 
1285591c571SHong Zhang   /*
1295591c571SHong Zhang      Restore vectors
1305591c571SHong Zhang   */
1319566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(19 * xm * ym));
1329566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArrayRead(da, localU, &u));
1339566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(da, &localU));
1349566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1359566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1369566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
1373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1385591c571SHong Zhang }
1395591c571SHong Zhang 
InitialConditions(DM da,Vec U)140d71ae5a4SJacob Faibussowitsch PetscErrorCode InitialConditions(DM da, Vec U)
141d71ae5a4SJacob Faibussowitsch {
1425591c571SHong Zhang   PetscInt  i, j, xs, ys, xm, ym, Mx, My;
1435591c571SHong Zhang   Field   **u;
1445591c571SHong Zhang   PetscReal hx, hy, x, y;
1455591c571SHong Zhang 
1467510d9b0SBarry Smith   PetscFunctionBeginUser;
1479566063dSJacob 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));
1485591c571SHong Zhang 
1495591c571SHong Zhang   hx = 2.5 / (PetscReal)Mx;
1505591c571SHong Zhang   hy = 2.5 / (PetscReal)My;
1515591c571SHong Zhang 
1525591c571SHong Zhang   /*
1535591c571SHong Zhang      Get pointers to vector data
1545591c571SHong Zhang   */
1559566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(da, U, &u));
1565591c571SHong Zhang 
1575591c571SHong Zhang   /*
1585591c571SHong Zhang      Get local grid boundaries
1595591c571SHong Zhang   */
1609566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL));
1615591c571SHong Zhang 
1625591c571SHong Zhang   /*
1635591c571SHong Zhang      Compute function over the locally owned part of the grid
1645591c571SHong Zhang   */
1655591c571SHong Zhang   for (j = ys; j < ys + ym; j++) {
1665591c571SHong Zhang     y = j * hy;
1675591c571SHong Zhang     for (i = xs; i < xs + xm; i++) {
1685591c571SHong Zhang       x = i * hx;
1695591c571SHong 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);
1705591c571SHong Zhang       else u[j][i].v = 0.0;
1715591c571SHong Zhang 
1725591c571SHong Zhang       u[j][i].u = 1.0 - 2.0 * u[j][i].v;
1735591c571SHong Zhang     }
1745591c571SHong Zhang   }
1755591c571SHong Zhang 
1765591c571SHong Zhang   /*
1775591c571SHong Zhang      Restore vectors
1785591c571SHong Zhang   */
1799566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(da, U, &u));
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1815591c571SHong Zhang }
1825591c571SHong Zhang 
main(int argc,char ** argv)183d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
184d71ae5a4SJacob Faibussowitsch {
1855591c571SHong Zhang   TS        ts;
1865591c571SHong Zhang   Vec       U, Udot;
1875591c571SHong Zhang   Mat       Jac, Jac2;
1885591c571SHong Zhang   DM        da;
1895591c571SHong Zhang   AppCtx    appctx;
1905591c571SHong Zhang   PetscReal t = 0, shift, norm;
1915591c571SHong Zhang 
192327415f7SBarry Smith   PetscFunctionBeginUser;
193c8025a54SPierre Jolivet   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
1945591c571SHong Zhang 
1955591c571SHong Zhang   appctx.D1    = 8.0e-5;
1965591c571SHong Zhang   appctx.D2    = 4.0e-5;
1975591c571SHong Zhang   appctx.gamma = .024;
1985591c571SHong Zhang   appctx.kappa = .06;
1995591c571SHong Zhang 
2005591c571SHong Zhang   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2015591c571SHong Zhang      Create distributed array (DMDA) to manage parallel grid and vectors
2025591c571SHong Zhang   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2039566063dSJacob 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));
2049566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(da));
2059566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da));
2069566063dSJacob Faibussowitsch   PetscCall(DMDASetFieldName(da, 0, "u"));
2079566063dSJacob Faibussowitsch   PetscCall(DMDASetFieldName(da, 1, "v"));
2089566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(da, MATAIJ));
2099566063dSJacob Faibussowitsch   PetscCall(DMCreateMatrix(da, &Jac));
2109566063dSJacob Faibussowitsch   PetscCall(DMCreateMatrix(da, &Jac2));
2115591c571SHong Zhang 
2125591c571SHong Zhang   /*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2135591c571SHong Zhang      Extract global vectors from DMDA; then duplicate for remaining
2145591c571SHong Zhang      vectors that are the same types
2155591c571SHong Zhang    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2169566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(da, &U));
2179566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(U, &Udot));
2189566063dSJacob Faibussowitsch   PetscCall(VecSet(Udot, 0.0));
2195591c571SHong Zhang 
2205591c571SHong Zhang   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2215591c571SHong Zhang      Create timestepping solver context
2225591c571SHong Zhang      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2239566063dSJacob Faibussowitsch   PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
2249566063dSJacob Faibussowitsch   PetscCall(TSSetDM(ts, da));
2259566063dSJacob Faibussowitsch   PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
2269566063dSJacob Faibussowitsch   PetscCall(TSSetRHSJacobian(ts, Jac, Jac, RHSJacobian, &appctx));
2275591c571SHong Zhang 
2285591c571SHong Zhang   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2295591c571SHong Zhang      Set initial conditions
2305591c571SHong Zhang    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2319566063dSJacob Faibussowitsch   PetscCall(InitialConditions(da, U));
2329566063dSJacob Faibussowitsch   PetscCall(TSSetSolution(ts, U));
2339566063dSJacob Faibussowitsch   PetscCall(TSSetFromOptions(ts));
2349566063dSJacob Faibussowitsch   PetscCall(TSSetUp(ts));
2355591c571SHong Zhang 
2365591c571SHong Zhang   shift = 2.;
2379566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, t, U, Udot, shift, Jac2, Jac2, PETSC_FALSE));
2385591c571SHong Zhang   shift = 1.;
2399566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, t, U, Udot, shift, Jac, Jac, PETSC_FALSE));
2405591c571SHong Zhang   shift = 2.;
2419566063dSJacob Faibussowitsch   PetscCall(TSComputeIJacobian(ts, t, U, Udot, shift, Jac, Jac, PETSC_FALSE));
2429566063dSJacob Faibussowitsch   PetscCall(MatAXPY(Jac, -1, Jac2, SAME_NONZERO_PATTERN));
2439566063dSJacob Faibussowitsch   PetscCall(MatNorm(Jac, NORM_INFINITY, &norm));
24448a46eb9SPierre 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));
2459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Jac));
2469566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Jac2));
2479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&U));
2489566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Udot));
2499566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts));
2509566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&da));
2519566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
252b122ec5aSJacob Faibussowitsch   return 0;
2535591c571SHong Zhang }
2545591c571SHong Zhang 
2555591c571SHong Zhang /*TEST
2563886731fSPierre Jolivet 
2575591c571SHong Zhang   test:
2583886731fSPierre Jolivet     output_file: output/empty.out
2595591c571SHong Zhang 
2605591c571SHong Zhang TEST*/
261