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