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 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 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 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