1c4762a1bSJed Brown /* 2c4762a1bSJed Brown The Problem: 3c4762a1bSJed Brown Solve the convection-diffusion equation: 4c4762a1bSJed Brown 5c4762a1bSJed Brown u_t+a*(u_x+u_y)=epsilon*(u_xx+u_yy) 6c4762a1bSJed Brown u=0 at x=0, y=0 7c4762a1bSJed Brown u_x=0 at x=1 8c4762a1bSJed Brown u_y=0 at y=1 9c4762a1bSJed Brown u = exp(-20.0*(pow(x-0.5,2.0)+pow(y-0.5,2.0))) at t=0 10c4762a1bSJed Brown 11c4762a1bSJed Brown This program tests the routine of computing the Jacobian by the 12c4762a1bSJed Brown finite difference method as well as PETSc. 13c4762a1bSJed Brown 14c4762a1bSJed Brown */ 15c4762a1bSJed Brown 16c4762a1bSJed Brown static char help[] = "Solve the convection-diffusion equation. \n\n"; 17c4762a1bSJed Brown 18c4762a1bSJed Brown #include <petscts.h> 19c4762a1bSJed Brown 209371c9d4SSatish Balay typedef struct { 21c4762a1bSJed Brown PetscInt m; /* the number of mesh points in x-direction */ 22c4762a1bSJed Brown PetscInt n; /* the number of mesh points in y-direction */ 23c4762a1bSJed Brown PetscReal dx; /* the grid space in x-direction */ 24c4762a1bSJed Brown PetscReal dy; /* the grid space in y-direction */ 25c4762a1bSJed Brown PetscReal a; /* the convection coefficient */ 26c4762a1bSJed Brown PetscReal epsilon; /* the diffusion coefficient */ 27c4762a1bSJed Brown PetscReal tfinal; 28c4762a1bSJed Brown } Data; 29c4762a1bSJed Brown 30c4762a1bSJed Brown extern PetscErrorCode Monitor(TS, PetscInt, PetscReal, Vec, void *); 31c4762a1bSJed Brown extern PetscErrorCode Initial(Vec, void *); 32c4762a1bSJed Brown extern PetscErrorCode RHSFunction(TS, PetscReal, Vec, Vec, void *); 33c4762a1bSJed Brown extern PetscErrorCode RHSJacobian(TS, PetscReal, Vec, Mat, Mat, void *); 34c4762a1bSJed Brown extern PetscErrorCode PostStep(TS); 35c4762a1bSJed Brown 36d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 37d71ae5a4SJacob Faibussowitsch { 38c4762a1bSJed Brown PetscInt time_steps = 100, iout, NOUT = 1; 39c4762a1bSJed Brown Vec global; 40c4762a1bSJed Brown PetscReal dt, ftime, ftime_original; 41c4762a1bSJed Brown TS ts; 42c4762a1bSJed Brown PetscViewer viewfile; 43c4762a1bSJed Brown Mat J = 0; 44c4762a1bSJed Brown Vec x; 45c4762a1bSJed Brown Data data; 46c4762a1bSJed Brown PetscInt mn; 47c4762a1bSJed Brown PetscBool flg; 48c4762a1bSJed Brown MatColoring mc; 49c4762a1bSJed Brown ISColoring iscoloring; 50c4762a1bSJed Brown MatFDColoring matfdcoloring = 0; 51c4762a1bSJed Brown PetscBool fd_jacobian_coloring = PETSC_FALSE; 52c4762a1bSJed Brown SNES snes; 53c4762a1bSJed Brown KSP ksp; 54c4762a1bSJed Brown PC pc; 55c4762a1bSJed Brown 56327415f7SBarry Smith PetscFunctionBeginUser; 57c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 58c4762a1bSJed Brown 59c4762a1bSJed Brown /* set data */ 60c4762a1bSJed Brown data.m = 9; 61c4762a1bSJed Brown data.n = 9; 62c4762a1bSJed Brown data.a = 1.0; 63c4762a1bSJed Brown data.epsilon = 0.1; 64c4762a1bSJed Brown data.dx = 1.0 / (data.m + 1.0); 65c4762a1bSJed Brown data.dy = 1.0 / (data.n + 1.0); 66c4762a1bSJed Brown mn = (data.m) * (data.n); 679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-time", &time_steps, NULL)); 68c4762a1bSJed Brown 69c4762a1bSJed Brown /* set initial conditions */ 709566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &global)); 719566063dSJacob Faibussowitsch PetscCall(VecSetSizes(global, PETSC_DECIDE, mn)); 729566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(global)); 739566063dSJacob Faibussowitsch PetscCall(Initial(global, &data)); 749566063dSJacob Faibussowitsch PetscCall(VecDuplicate(global, &x)); 75c4762a1bSJed Brown 76c4762a1bSJed Brown /* create timestep context */ 779566063dSJacob Faibussowitsch PetscCall(TSCreate(PETSC_COMM_WORLD, &ts)); 789566063dSJacob Faibussowitsch PetscCall(TSMonitorSet(ts, Monitor, &data, NULL)); 799566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSEULER)); 80c4762a1bSJed Brown dt = 0.1; 81c4762a1bSJed Brown ftime_original = data.tfinal = 1.0; 82c4762a1bSJed Brown 839566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, dt)); 849566063dSJacob Faibussowitsch PetscCall(TSSetMaxSteps(ts, time_steps)); 859566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts, ftime_original)); 869566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER)); 879566063dSJacob Faibussowitsch PetscCall(TSSetSolution(ts, global)); 88c4762a1bSJed Brown 89c4762a1bSJed Brown /* set user provided RHSFunction and RHSJacobian */ 909566063dSJacob Faibussowitsch PetscCall(TSSetRHSFunction(ts, NULL, RHSFunction, &data)); 919566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &J)); 929566063dSJacob Faibussowitsch PetscCall(MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, mn, mn)); 939566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J)); 949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 5, NULL)); 959566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 5, NULL, 5, NULL)); 96c4762a1bSJed Brown 979566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-ts_fd", &flg)); 98c4762a1bSJed Brown if (!flg) { 999566063dSJacob Faibussowitsch PetscCall(TSSetRHSJacobian(ts, J, J, RHSJacobian, &data)); 100c4762a1bSJed Brown } else { 1019566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &snes)); 1029566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-fd_color", &fd_jacobian_coloring)); 103c4762a1bSJed Brown if (fd_jacobian_coloring) { /* Use finite differences with coloring */ 104c4762a1bSJed Brown /* Get data structure of J */ 105c4762a1bSJed Brown PetscBool pc_diagonal; 1069566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-pc_diagonal", &pc_diagonal)); 107c4762a1bSJed Brown if (pc_diagonal) { /* the preconditioner of J is a diagonal matrix */ 108c4762a1bSJed Brown PetscInt rstart, rend, i; 109c4762a1bSJed Brown PetscScalar zero = 0.0; 1109566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(J, &rstart, &rend)); 11148a46eb9SPierre Jolivet for (i = rstart; i < rend; i++) PetscCall(MatSetValues(J, 1, &i, 1, &i, &zero, INSERT_VALUES)); 1129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 1139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 114c4762a1bSJed Brown } else { 115c4762a1bSJed Brown /* Fill the structure using the expensive SNESComputeJacobianDefault. Temporarily set up the TS so we can call this function */ 1169566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSBEULER)); 1179566063dSJacob Faibussowitsch PetscCall(TSSetUp(ts)); 1189566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, J, J, ts)); 119c4762a1bSJed Brown } 120c4762a1bSJed Brown 121c4762a1bSJed Brown /* create coloring context */ 1229566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(J, &mc)); 1239566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 1249566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(mc)); 1259566063dSJacob Faibussowitsch PetscCall(MatColoringApply(mc, &iscoloring)); 1269566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&mc)); 1279566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(J, iscoloring, &matfdcoloring)); 1282ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)SNESTSFormFunction, ts)); 1299566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 1309566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(J, iscoloring, matfdcoloring)); 1319566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, matfdcoloring)); 1329566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring)); 133c4762a1bSJed Brown } else { /* Use finite differences (slow) */ 1349566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefault, NULL)); 135c4762a1bSJed Brown } 136c4762a1bSJed Brown } 137c4762a1bSJed Brown 138f0b74427SPierre Jolivet /* Pick up a PETSc preconditioner */ 139c4762a1bSJed Brown /* one can always set method or preconditioner during the run time */ 1409566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &snes)); 1419566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp)); 1429566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 1439566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCJACOBI)); 1449566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER)); 145c4762a1bSJed Brown 1469566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts)); 1479566063dSJacob Faibussowitsch PetscCall(TSSetUp(ts)); 148c4762a1bSJed Brown 149c4762a1bSJed Brown /* Test TSSetPostStep() */ 1509566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-test_PostStep", &flg)); 1511baa6e33SBarry Smith if (flg) PetscCall(TSSetPostStep(ts, PostStep)); 152c4762a1bSJed Brown 1539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-NOUT", &NOUT, NULL)); 154c4762a1bSJed Brown for (iout = 1; iout <= NOUT; iout++) { 1559566063dSJacob Faibussowitsch PetscCall(TSSetMaxSteps(ts, time_steps)); 1569566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts, iout * ftime_original / NOUT)); 1579566063dSJacob Faibussowitsch PetscCall(TSSolve(ts, global)); 1589566063dSJacob Faibussowitsch PetscCall(TSGetSolveTime(ts, &ftime)); 1599566063dSJacob Faibussowitsch PetscCall(TSSetTime(ts, ftime)); 1609566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, dt)); 161c4762a1bSJed Brown } 162c4762a1bSJed Brown /* Interpolate solution at tfinal */ 1639566063dSJacob Faibussowitsch PetscCall(TSGetSolution(ts, &global)); 1649566063dSJacob Faibussowitsch PetscCall(TSInterpolate(ts, ftime_original, global)); 165c4762a1bSJed Brown 1669566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-matlab_view", &flg)); 167c4762a1bSJed Brown if (flg) { /* print solution into a MATLAB file */ 1689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_WORLD, "out.m", &viewfile)); 1699566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewfile, PETSC_VIEWER_ASCII_MATLAB)); 1709566063dSJacob Faibussowitsch PetscCall(VecView(global, viewfile)); 1719566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewfile)); 1729566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewfile)); 173c4762a1bSJed Brown } 174c4762a1bSJed Brown 175c4762a1bSJed Brown /* free the memories */ 1769566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts)); 1779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 1789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 1799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 1809566063dSJacob Faibussowitsch if (fd_jacobian_coloring) PetscCall(MatFDColoringDestroy(&matfdcoloring)); 1819566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 182b122ec5aSJacob Faibussowitsch return 0; 183c4762a1bSJed Brown } 184c4762a1bSJed Brown 185c4762a1bSJed Brown /* -------------------------------------------------------------------*/ 186c4762a1bSJed Brown /* the initial function */ 187d71ae5a4SJacob Faibussowitsch PetscReal f_ini(PetscReal x, PetscReal y) 188d71ae5a4SJacob Faibussowitsch { 189c4762a1bSJed Brown PetscReal f; 190c4762a1bSJed Brown 191c4762a1bSJed Brown f = PetscExpReal(-20.0 * (PetscPowRealInt(x - 0.5, 2) + PetscPowRealInt(y - 0.5, 2))); 192c4762a1bSJed Brown return f; 193c4762a1bSJed Brown } 194c4762a1bSJed Brown 195*2a8381b2SBarry Smith PetscErrorCode Initial(Vec global, PetscCtx ctx) 196d71ae5a4SJacob Faibussowitsch { 197c4762a1bSJed Brown Data *data = (Data *)ctx; 198c4762a1bSJed Brown PetscInt m, row, col; 199c4762a1bSJed Brown PetscReal x, y, dx, dy; 200c4762a1bSJed Brown PetscScalar *localptr; 201c4762a1bSJed Brown PetscInt i, mybase, myend, locsize; 202c4762a1bSJed Brown 203c4762a1bSJed Brown PetscFunctionBeginUser; 204c4762a1bSJed Brown /* make the local copies of parameters */ 205c4762a1bSJed Brown m = data->m; 206c4762a1bSJed Brown dx = data->dx; 207c4762a1bSJed Brown dy = data->dy; 208c4762a1bSJed Brown 209c4762a1bSJed Brown /* determine starting point of each processor */ 2109566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(global, &mybase, &myend)); 2119566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(global, &locsize)); 212c4762a1bSJed Brown 213c4762a1bSJed Brown /* Initialize the array */ 2149566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(global, &localptr)); 215c4762a1bSJed Brown 216c4762a1bSJed Brown for (i = 0; i < locsize; i++) { 217c4762a1bSJed Brown row = 1 + (mybase + i) - ((mybase + i) / m) * m; 218c4762a1bSJed Brown col = (mybase + i) / m + 1; 219c4762a1bSJed Brown x = dx * row; 220c4762a1bSJed Brown y = dy * col; 221c4762a1bSJed Brown localptr[i] = f_ini(x, y); 222c4762a1bSJed Brown } 223c4762a1bSJed Brown 2249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(global, &localptr)); 2253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 226c4762a1bSJed Brown } 227c4762a1bSJed Brown 228*2a8381b2SBarry Smith PetscErrorCode Monitor(TS ts, PetscInt step, PetscReal time, Vec global, PetscCtx ctx) 229d71ae5a4SJacob Faibussowitsch { 230c4762a1bSJed Brown VecScatter scatter; 231c4762a1bSJed Brown IS from, to; 232c4762a1bSJed Brown PetscInt i, n, *idx, nsteps, maxsteps; 233c4762a1bSJed Brown Vec tmp_vec; 234c4762a1bSJed Brown const PetscScalar *tmp; 235c4762a1bSJed Brown 236c4762a1bSJed Brown PetscFunctionBeginUser; 2379566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts, &nsteps)); 238c4762a1bSJed Brown /* display output at selected time steps */ 2399566063dSJacob Faibussowitsch PetscCall(TSGetMaxSteps(ts, &maxsteps)); 2403ba16761SJacob Faibussowitsch if (nsteps % 10 != 0) PetscFunctionReturn(PETSC_SUCCESS); 241c4762a1bSJed Brown 242c4762a1bSJed Brown /* Get the size of the vector */ 2439566063dSJacob Faibussowitsch PetscCall(VecGetSize(global, &n)); 244c4762a1bSJed Brown 245c4762a1bSJed Brown /* Set the index sets */ 2469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idx)); 247c4762a1bSJed Brown for (i = 0; i < n; i++) idx[i] = i; 248c4762a1bSJed Brown 249c4762a1bSJed Brown /* Create local sequential vectors */ 2509566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, &tmp_vec)); 251c4762a1bSJed Brown 252c4762a1bSJed Brown /* Create scatter context */ 2539566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idx, PETSC_COPY_VALUES, &from)); 2549566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idx, PETSC_COPY_VALUES, &to)); 2559566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(global, from, tmp_vec, to, &scatter)); 2569566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scatter, global, tmp_vec, INSERT_VALUES, SCATTER_FORWARD)); 2579566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scatter, global, tmp_vec, INSERT_VALUES, SCATTER_FORWARD)); 258c4762a1bSJed Brown 2599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tmp_vec, &tmp)); 26063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "At t[%" PetscInt_FMT "] =%14.2e u= %14.2e at the center \n", nsteps, (double)time, (double)PetscRealPart(tmp[n / 2]))); 2619566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tmp_vec, &tmp)); 262c4762a1bSJed Brown 2639566063dSJacob Faibussowitsch PetscCall(PetscFree(idx)); 2649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 2669566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&scatter)); 2679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tmp_vec)); 2683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 269c4762a1bSJed Brown } 270c4762a1bSJed Brown 271d71ae5a4SJacob Faibussowitsch PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec x, Mat A, Mat BB, void *ptr) 272d71ae5a4SJacob Faibussowitsch { 273c4762a1bSJed Brown Data *data = (Data *)ptr; 274c4762a1bSJed Brown PetscScalar v[5]; 275c4762a1bSJed Brown PetscInt idx[5], i, j, row; 276c4762a1bSJed Brown PetscInt m, n, mn; 277c4762a1bSJed Brown PetscReal dx, dy, a, epsilon, xc, xl, xr, yl, yr; 278c4762a1bSJed Brown 279c4762a1bSJed Brown PetscFunctionBeginUser; 280c4762a1bSJed Brown m = data->m; 281c4762a1bSJed Brown n = data->n; 282c4762a1bSJed Brown mn = m * n; 283c4762a1bSJed Brown dx = data->dx; 284c4762a1bSJed Brown dy = data->dy; 285c4762a1bSJed Brown a = data->a; 286c4762a1bSJed Brown epsilon = data->epsilon; 287c4762a1bSJed Brown 288c4762a1bSJed Brown xc = -2.0 * epsilon * (1.0 / (dx * dx) + 1.0 / (dy * dy)); 289c4762a1bSJed Brown xl = 0.5 * a / dx + epsilon / (dx * dx); 290c4762a1bSJed Brown xr = -0.5 * a / dx + epsilon / (dx * dx); 291c4762a1bSJed Brown yl = 0.5 * a / dy + epsilon / (dy * dy); 292c4762a1bSJed Brown yr = -0.5 * a / dy + epsilon / (dy * dy); 293c4762a1bSJed Brown 294c4762a1bSJed Brown row = 0; 2959371c9d4SSatish Balay v[0] = xc; 2969371c9d4SSatish Balay v[1] = xr; 2979371c9d4SSatish Balay v[2] = yr; 2989371c9d4SSatish Balay idx[0] = 0; 2999371c9d4SSatish Balay idx[1] = 2; 3009371c9d4SSatish Balay idx[2] = m; 3019566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 3, idx, v, INSERT_VALUES)); 302c4762a1bSJed Brown 303c4762a1bSJed Brown row = m - 1; 3049371c9d4SSatish Balay v[0] = 2.0 * xl; 3059371c9d4SSatish Balay v[1] = xc; 3069371c9d4SSatish Balay v[2] = yr; 3079371c9d4SSatish Balay idx[0] = m - 2; 3089371c9d4SSatish Balay idx[1] = m - 1; 3099371c9d4SSatish Balay idx[2] = m - 1 + m; 3109566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 3, idx, v, INSERT_VALUES)); 311c4762a1bSJed Brown 312c4762a1bSJed Brown for (i = 1; i < m - 1; i++) { 313c4762a1bSJed Brown row = i; 3149371c9d4SSatish Balay v[0] = xl; 3159371c9d4SSatish Balay v[1] = xc; 3169371c9d4SSatish Balay v[2] = xr; 3179371c9d4SSatish Balay v[3] = yr; 3189371c9d4SSatish Balay idx[0] = i - 1; 3199371c9d4SSatish Balay idx[1] = i; 3209371c9d4SSatish Balay idx[2] = i + 1; 3219371c9d4SSatish Balay idx[3] = i + m; 3229566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 4, idx, v, INSERT_VALUES)); 323c4762a1bSJed Brown } 324c4762a1bSJed Brown 325c4762a1bSJed Brown for (j = 1; j < n - 1; j++) { 326c4762a1bSJed Brown row = j * m; 3279371c9d4SSatish Balay v[0] = xc; 3289371c9d4SSatish Balay v[1] = xr; 3299371c9d4SSatish Balay v[2] = yl; 3309371c9d4SSatish Balay v[3] = yr; 3319371c9d4SSatish Balay idx[0] = j * m; 3329371c9d4SSatish Balay idx[1] = j * m; 3339371c9d4SSatish Balay idx[2] = j * m - m; 3349371c9d4SSatish Balay idx[3] = j * m + m; 3359566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 4, idx, v, INSERT_VALUES)); 336c4762a1bSJed Brown 337c4762a1bSJed Brown row = j * m + m - 1; 3389371c9d4SSatish Balay v[0] = xc; 3399371c9d4SSatish Balay v[1] = 2.0 * xl; 3409371c9d4SSatish Balay v[2] = yl; 3419371c9d4SSatish Balay v[3] = yr; 3429371c9d4SSatish Balay idx[0] = j * m + m - 1; 3439371c9d4SSatish Balay idx[1] = j * m + m - 1 - 1; 3449371c9d4SSatish Balay idx[2] = j * m + m - 1 - m; 3459371c9d4SSatish Balay idx[3] = j * m + m - 1 + m; 3469566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 4, idx, v, INSERT_VALUES)); 347c4762a1bSJed Brown 348c4762a1bSJed Brown for (i = 1; i < m - 1; i++) { 349c4762a1bSJed Brown row = j * m + i; 3509371c9d4SSatish Balay v[0] = xc; 3519371c9d4SSatish Balay v[1] = xl; 3529371c9d4SSatish Balay v[2] = xr; 3539371c9d4SSatish Balay v[3] = yl; 3549371c9d4SSatish Balay v[4] = yr; 3559371c9d4SSatish Balay idx[0] = j * m + i; 3569371c9d4SSatish Balay idx[1] = j * m + i - 1; 3579371c9d4SSatish Balay idx[2] = j * m + i + 1; 3589371c9d4SSatish Balay idx[3] = j * m + i - m; 359c4762a1bSJed Brown idx[4] = j * m + i + m; 3609566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 5, idx, v, INSERT_VALUES)); 361c4762a1bSJed Brown } 362c4762a1bSJed Brown } 363c4762a1bSJed Brown 364c4762a1bSJed Brown row = mn - m; 3659371c9d4SSatish Balay v[0] = xc; 3669371c9d4SSatish Balay v[1] = xr; 3679371c9d4SSatish Balay v[2] = 2.0 * yl; 3689371c9d4SSatish Balay idx[0] = mn - m; 3699371c9d4SSatish Balay idx[1] = mn - m + 1; 3709371c9d4SSatish Balay idx[2] = mn - m - m; 3719566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 3, idx, v, INSERT_VALUES)); 372c4762a1bSJed Brown 373c4762a1bSJed Brown row = mn - 1; 3749371c9d4SSatish Balay v[0] = xc; 3759371c9d4SSatish Balay v[1] = 2.0 * xl; 3769371c9d4SSatish Balay v[2] = 2.0 * yl; 3779371c9d4SSatish Balay idx[0] = mn - 1; 3789371c9d4SSatish Balay idx[1] = mn - 2; 3799371c9d4SSatish Balay idx[2] = mn - 1 - m; 3809566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &i, 3, idx, v, INSERT_VALUES)); 381c4762a1bSJed Brown 382c4762a1bSJed Brown for (i = 1; i < m - 1; i++) { 383c4762a1bSJed Brown row = mn - m + i; 3849371c9d4SSatish Balay v[0] = xl; 3859371c9d4SSatish Balay v[1] = xc; 3869371c9d4SSatish Balay v[2] = xr; 3879371c9d4SSatish Balay v[3] = 2.0 * yl; 3889371c9d4SSatish Balay idx[0] = mn - m + i - 1; 3899371c9d4SSatish Balay idx[1] = mn - m + i; 3909371c9d4SSatish Balay idx[2] = mn - m + i + 1; 3919371c9d4SSatish Balay idx[3] = mn - m + i - m; 3929566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &row, 4, idx, v, INSERT_VALUES)); 393c4762a1bSJed Brown } 394c4762a1bSJed Brown 3959566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 3969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 3973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 398c4762a1bSJed Brown } 399c4762a1bSJed Brown 400c4762a1bSJed Brown /* globalout = -a*(u_x+u_y) + epsilon*(u_xx+u_yy) */ 401*2a8381b2SBarry Smith PetscErrorCode RHSFunction(TS ts, PetscReal t, Vec globalin, Vec globalout, PetscCtx ctx) 402d71ae5a4SJacob Faibussowitsch { 403c4762a1bSJed Brown Data *data = (Data *)ctx; 404c4762a1bSJed Brown PetscInt m, n, mn; 405c4762a1bSJed Brown PetscReal dx, dy; 406c4762a1bSJed Brown PetscReal xc, xl, xr, yl, yr; 407c4762a1bSJed Brown PetscReal a, epsilon; 408c4762a1bSJed Brown PetscScalar *outptr; 409c4762a1bSJed Brown const PetscScalar *inptr; 410c4762a1bSJed Brown PetscInt i, j, len; 411c4762a1bSJed Brown IS from, to; 412c4762a1bSJed Brown PetscInt *idx; 413c4762a1bSJed Brown VecScatter scatter; 414c4762a1bSJed Brown Vec tmp_in, tmp_out; 415c4762a1bSJed Brown 416c4762a1bSJed Brown PetscFunctionBeginUser; 417c4762a1bSJed Brown m = data->m; 418c4762a1bSJed Brown n = data->n; 419c4762a1bSJed Brown mn = m * n; 420c4762a1bSJed Brown dx = data->dx; 421c4762a1bSJed Brown dy = data->dy; 422c4762a1bSJed Brown a = data->a; 423c4762a1bSJed Brown epsilon = data->epsilon; 424c4762a1bSJed Brown 425c4762a1bSJed Brown xc = -2.0 * epsilon * (1.0 / (dx * dx) + 1.0 / (dy * dy)); 426c4762a1bSJed Brown xl = 0.5 * a / dx + epsilon / (dx * dx); 427c4762a1bSJed Brown xr = -0.5 * a / dx + epsilon / (dx * dx); 428c4762a1bSJed Brown yl = 0.5 * a / dy + epsilon / (dy * dy); 429c4762a1bSJed Brown yr = -0.5 * a / dy + epsilon / (dy * dy); 430c4762a1bSJed Brown 431c4762a1bSJed Brown /* Get the length of parallel vector */ 4329566063dSJacob Faibussowitsch PetscCall(VecGetSize(globalin, &len)); 433c4762a1bSJed Brown 434c4762a1bSJed Brown /* Set the index sets */ 4359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len, &idx)); 436c4762a1bSJed Brown for (i = 0; i < len; i++) idx[i] = i; 437c4762a1bSJed Brown 438c4762a1bSJed Brown /* Create local sequential vectors */ 4399566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, len, &tmp_in)); 4409566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tmp_in, &tmp_out)); 441c4762a1bSJed Brown 442c4762a1bSJed Brown /* Create scatter context */ 4439566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, len, idx, PETSC_COPY_VALUES, &from)); 4449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, len, idx, PETSC_COPY_VALUES, &to)); 4459566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(globalin, from, tmp_in, to, &scatter)); 4469566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scatter, globalin, tmp_in, INSERT_VALUES, SCATTER_FORWARD)); 4479566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scatter, globalin, tmp_in, INSERT_VALUES, SCATTER_FORWARD)); 4489566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&scatter)); 449c4762a1bSJed Brown 450c4762a1bSJed Brown /*Extract income array - include ghost points */ 4519566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tmp_in, &inptr)); 452c4762a1bSJed Brown 453c4762a1bSJed Brown /* Extract outcome array*/ 4549566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(tmp_out, &outptr)); 455c4762a1bSJed Brown 456c4762a1bSJed Brown outptr[0] = xc * inptr[0] + xr * inptr[1] + yr * inptr[m]; 457c4762a1bSJed Brown outptr[m - 1] = 2.0 * xl * inptr[m - 2] + xc * inptr[m - 1] + yr * inptr[m - 1 + m]; 458ad540459SPierre Jolivet for (i = 1; i < m - 1; i++) outptr[i] = xc * inptr[i] + xl * inptr[i - 1] + xr * inptr[i + 1] + yr * inptr[i + m]; 459c4762a1bSJed Brown 460c4762a1bSJed Brown for (j = 1; j < n - 1; j++) { 461c4762a1bSJed Brown outptr[j * m] = xc * inptr[j * m] + xr * inptr[j * m + 1] + yl * inptr[j * m - m] + yr * inptr[j * m + m]; 462c4762a1bSJed Brown outptr[j * m + m - 1] = xc * inptr[j * m + m - 1] + 2.0 * xl * inptr[j * m + m - 1 - 1] + yl * inptr[j * m + m - 1 - m] + yr * inptr[j * m + m - 1 + m]; 463ad540459SPierre Jolivet for (i = 1; i < m - 1; i++) outptr[j * m + i] = xc * inptr[j * m + i] + xl * inptr[j * m + i - 1] + xr * inptr[j * m + i + 1] + yl * inptr[j * m + i - m] + yr * inptr[j * m + i + m]; 464c4762a1bSJed Brown } 465c4762a1bSJed Brown 466c4762a1bSJed Brown outptr[mn - m] = xc * inptr[mn - m] + xr * inptr[mn - m + 1] + 2.0 * yl * inptr[mn - m - m]; 467c4762a1bSJed Brown outptr[mn - 1] = 2.0 * xl * inptr[mn - 2] + xc * inptr[mn - 1] + 2.0 * yl * inptr[mn - 1 - m]; 468ad540459SPierre Jolivet for (i = 1; i < m - 1; i++) outptr[mn - m + i] = xc * inptr[mn - m + i] + xl * inptr[mn - m + i - 1] + xr * inptr[mn - m + i + 1] + 2 * yl * inptr[mn - m + i - m]; 469c4762a1bSJed Brown 4709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tmp_in, &inptr)); 4719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(tmp_out, &outptr)); 472c4762a1bSJed Brown 4739566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(tmp_out, from, globalout, to, &scatter)); 4749566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scatter, tmp_out, globalout, INSERT_VALUES, SCATTER_FORWARD)); 4759566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scatter, tmp_out, globalout, INSERT_VALUES, SCATTER_FORWARD)); 476c4762a1bSJed Brown 477aeebefc2SPierre Jolivet /* Destroy idx and scatter */ 4789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tmp_in)); 4799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tmp_out)); 4809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 4819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 4829566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&scatter)); 483c4762a1bSJed Brown 4849566063dSJacob Faibussowitsch PetscCall(PetscFree(idx)); 4853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 486c4762a1bSJed Brown } 487c4762a1bSJed Brown 488d71ae5a4SJacob Faibussowitsch PetscErrorCode PostStep(TS ts) 489d71ae5a4SJacob Faibussowitsch { 490c4762a1bSJed Brown PetscReal t; 491c4762a1bSJed Brown 492c4762a1bSJed Brown PetscFunctionBeginUser; 4939566063dSJacob Faibussowitsch PetscCall(TSGetTime(ts, &t)); 4949566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " PostStep, t: %g\n", (double)t)); 4953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 496c4762a1bSJed Brown } 497c4762a1bSJed Brown 498c4762a1bSJed Brown /*TEST 499c4762a1bSJed Brown 500c4762a1bSJed Brown test: 501c4762a1bSJed Brown args: -ts_fd -ts_type beuler 502c4762a1bSJed Brown output_file: output/ex4.out 503c4762a1bSJed Brown 504c4762a1bSJed Brown test: 505c4762a1bSJed Brown suffix: 2 506c4762a1bSJed Brown args: -ts_fd -ts_type beuler 507c4762a1bSJed Brown nsize: 2 508c4762a1bSJed Brown output_file: output/ex4.out 509c4762a1bSJed Brown 510c4762a1bSJed Brown test: 511c4762a1bSJed Brown suffix: 3 512c4762a1bSJed Brown args: -ts_fd -ts_type cn 513c4762a1bSJed Brown 514c4762a1bSJed Brown test: 515c4762a1bSJed Brown suffix: 4 516c4762a1bSJed Brown args: -ts_fd -ts_type cn 517c4762a1bSJed Brown output_file: output/ex4_3.out 518c4762a1bSJed Brown nsize: 2 519c4762a1bSJed Brown 520c4762a1bSJed Brown test: 521c4762a1bSJed Brown suffix: 5 522c4762a1bSJed Brown args: -ts_type beuler -ts_fd -fd_color -mat_coloring_type sl 523c4762a1bSJed Brown output_file: output/ex4.out 524c4762a1bSJed Brown 525c4762a1bSJed Brown test: 526c4762a1bSJed Brown suffix: 6 527c4762a1bSJed Brown args: -ts_type beuler -ts_fd -fd_color -mat_coloring_type sl 528c4762a1bSJed Brown output_file: output/ex4.out 529c4762a1bSJed Brown nsize: 2 530c4762a1bSJed Brown 531c4762a1bSJed Brown test: 532c4762a1bSJed Brown suffix: 7 533c4762a1bSJed Brown requires: !single 534188af4bfSBarry Smith args: -ts_fd -ts_type beuler -test_PostStep -ts_time_step .1 535c4762a1bSJed Brown 536c4762a1bSJed Brown test: 537c4762a1bSJed Brown suffix: 8 538c4762a1bSJed Brown requires: !single 539188af4bfSBarry Smith args: -ts_type rk -ts_rk_type 5dp -ts_time_step .01 -ts_adapt_type none -ts_view 540c4762a1bSJed Brown 541c4762a1bSJed Brown TEST*/ 542