xref: /petsc/src/ts/tutorials/ex52.c (revision 589a23caa660d2a5f330cc8d1ed213e9cfaf51a7)
1f746d17cSMukkund Sunjii static char help[] = "Simple Advection-diffusion equation solved using FVM in DMPLEX\n";
2f746d17cSMukkund Sunjii 
3f746d17cSMukkund Sunjii /*
4f746d17cSMukkund Sunjii    Solves the simple advection equation given by
5f746d17cSMukkund Sunjii 
6f746d17cSMukkund Sunjii    q_t + u (q_x) + v (q_y) - D (q_xx + q_yy) = 0 using FVM and First Order Upwind discretization.
7f746d17cSMukkund Sunjii 
8f746d17cSMukkund Sunjii    with a user defined initial condition.
9f746d17cSMukkund Sunjii 
10f746d17cSMukkund Sunjii    with dirichlet/neumann conditions on the four boundaries of the domain.
11f746d17cSMukkund Sunjii 
12f746d17cSMukkund Sunjii    User can define the mesh parameters either in the command line or inside
13f746d17cSMukkund Sunjii    the ProcessOptions() routine.
14f746d17cSMukkund Sunjii 
15f746d17cSMukkund Sunjii    Contributed by: Mukkund Sunjii, Domenico Lahaye
16f746d17cSMukkund Sunjii */
17f746d17cSMukkund Sunjii 
18f746d17cSMukkund Sunjii #include <petscdmplex.h>
19f746d17cSMukkund Sunjii #include <petscts.h>
20f746d17cSMukkund Sunjii #include <petscblaslapack.h>
21f746d17cSMukkund Sunjii 
22f746d17cSMukkund Sunjii #if defined(PETSC_HAVE_CGNS)
23f746d17cSMukkund Sunjii #undef I
24f746d17cSMukkund Sunjii #include <cgnslib.h>
25f746d17cSMukkund Sunjii #endif
26f746d17cSMukkund Sunjii /*
27f746d17cSMukkund Sunjii    User-defined routines
28f746d17cSMukkund Sunjii */
29f746d17cSMukkund Sunjii extern PetscErrorCode FormFunction(TS, PetscReal, Vec, Vec, void *), FormInitialSolution(DM, Vec);
30f746d17cSMukkund Sunjii extern PetscErrorCode MyTSMonitor(TS, PetscInt, PetscReal, Vec, void *);
31f746d17cSMukkund Sunjii extern PetscErrorCode MySNESMonitor(SNES, PetscInt, PetscReal, PetscViewerAndFormat *);
32f746d17cSMukkund Sunjii 
33f746d17cSMukkund Sunjii /* Defining the usr defined context */
34f746d17cSMukkund Sunjii typedef struct {
35f746d17cSMukkund Sunjii     DM da;
36f746d17cSMukkund Sunjii     PetscBool interpolate;                  /* Generate intermediate mesh elements */
37f746d17cSMukkund Sunjii     char filename[PETSC_MAX_PATH_LEN]; /* Mesh filename */
38f746d17cSMukkund Sunjii     PetscInt dim;
39f746d17cSMukkund Sunjii     PetscScalar diffusion;
40f746d17cSMukkund Sunjii     PetscReal u, v;
41f746d17cSMukkund Sunjii     PetscScalar delta_x, delta_y;
42f746d17cSMukkund Sunjii     PetscInt cells[2];
43f746d17cSMukkund Sunjii } AppCtx;
44f746d17cSMukkund Sunjii 
45f746d17cSMukkund Sunjii /* Options for the scenario */
46f746d17cSMukkund Sunjii static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) {
47f746d17cSMukkund Sunjii     PetscErrorCode ierr;
48f746d17cSMukkund Sunjii 
49f746d17cSMukkund Sunjii     PetscFunctionBeginUser;
50f746d17cSMukkund Sunjii     options->interpolate = PETSC_TRUE;
51f746d17cSMukkund Sunjii     options->filename[0] = '\0';
52f746d17cSMukkund Sunjii     options->dim = 2;
53f746d17cSMukkund Sunjii     options->u = 2.5;
54f746d17cSMukkund Sunjii     options->v = 0.0;
55f746d17cSMukkund Sunjii     options->cells[0] = 20;
56f746d17cSMukkund Sunjii     options->cells[1] = 20;
57f746d17cSMukkund Sunjii     options->diffusion = 0.0;
58f746d17cSMukkund Sunjii 
59f746d17cSMukkund Sunjii     ierr = PetscOptionsBegin(comm, "", "Meshing Problem Options", "DMPLEX");CHKERRQ(ierr);
60f746d17cSMukkund Sunjii     ierr = PetscOptionsBool("-interpolate", "Generate intermediate mesh elements", "advection_DMPLEX.c",options->interpolate, &options->interpolate, NULL);CHKERRQ(ierr);
61*589a23caSBarry Smith     ierr = PetscOptionsString("-filename", "The mesh file", "advection_DMPLEX.c", options->filename, options->filename, sizeof(options->filename), NULL);CHKERRQ(ierr);
62f746d17cSMukkund Sunjii     ierr = PetscOptionsRangeInt("-dim", "Problem dimension used for the non-file mesh.", "ex7.c", options->dim, &options->dim, NULL,1,3);CHKERRQ(ierr);
63f746d17cSMukkund Sunjii     ierr = PetscOptionsReal("-u", "The x component of the convective coefficient", "advection_DMPLEX.c", options->u, &options->u, NULL);CHKERRQ(ierr);
64f746d17cSMukkund Sunjii     ierr = PetscOptionsReal("-v", "The y component of the convective coefficient", "advection_DMPLEX.c", options->v, &options->v, NULL);CHKERRQ(ierr);
65f746d17cSMukkund Sunjii     ierr = PetscOptionsScalar("-diffus", "The diffusive coefficient", "advection_DMPLEX.c", options->diffusion, &options->diffusion, NULL);CHKERRQ(ierr);
66f746d17cSMukkund Sunjii     ierr = PetscOptionsEnd();
67f746d17cSMukkund Sunjii     PetscFunctionReturn(0);
68f746d17cSMukkund Sunjii }
69f746d17cSMukkund Sunjii 
70f746d17cSMukkund Sunjii /*
71f746d17cSMukkund Sunjii   User can provide the file containing the mesh.
72f746d17cSMukkund Sunjii   Or can generate the mesh using DMPlexCreateBoxMesh with the specified options.
73f746d17cSMukkund Sunjii */
74f746d17cSMukkund Sunjii static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) {
75f746d17cSMukkund Sunjii     size_t len;
76f746d17cSMukkund Sunjii     PetscErrorCode ierr;
77f746d17cSMukkund Sunjii     PetscFunctionBeginUser;
78f746d17cSMukkund Sunjii     ierr = PetscStrlen(user->filename, &len);CHKERRQ(ierr);
79f746d17cSMukkund Sunjii     if (!len) {
80f746d17cSMukkund Sunjii         DMLabel label;
81f746d17cSMukkund Sunjii         ierr = DMPlexCreateBoxMesh(comm, user->dim, PETSC_FALSE, user->cells, NULL, NULL, NULL, user->interpolate, dm);CHKERRQ(ierr);
82f746d17cSMukkund Sunjii         /* Mark boundary and set BC */
83f746d17cSMukkund Sunjii         ierr = DMCreateLabel(*dm, "boundary");CHKERRQ(ierr);
84f746d17cSMukkund Sunjii         ierr = DMGetLabel(*dm, "boundary", &label);CHKERRQ(ierr);
85f746d17cSMukkund Sunjii         ierr = DMPlexMarkBoundaryFaces(*dm, 1, label);CHKERRQ(ierr);
86f746d17cSMukkund Sunjii         ierr = DMPlexLabelComplete(*dm, label);CHKERRQ(ierr);
87f746d17cSMukkund Sunjii     } else {
88f746d17cSMukkund Sunjii         ierr = DMPlexCreateFromFile(comm, user->filename, user->interpolate, dm);CHKERRQ(ierr);
89f746d17cSMukkund Sunjii     }
90f746d17cSMukkund Sunjii     ierr = PetscObjectSetName((PetscObject) * dm, "Mesh");CHKERRQ(ierr);
91f746d17cSMukkund Sunjii     ierr = DMSetFromOptions(*dm);CHKERRQ(ierr);
92f746d17cSMukkund Sunjii     ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr);
93f746d17cSMukkund Sunjii     PetscFunctionReturn(0);
94f746d17cSMukkund Sunjii }
95f746d17cSMukkund Sunjii 
96f746d17cSMukkund Sunjii     /* This routine is responsible for defining the local solution vector x
97f746d17cSMukkund Sunjii     with a given initial solution.
98f746d17cSMukkund Sunjii     The initial solution can be modified accordingly inside the loops.
99f746d17cSMukkund Sunjii     No need for a local vector because there is exchange of information
100f746d17cSMukkund Sunjii     across the processors. Unlike for FormFunction which depends on the neighbours */
101f746d17cSMukkund Sunjii PetscErrorCode FormInitialSolution(DM da, Vec U) {
102f746d17cSMukkund Sunjii     PetscErrorCode ierr;
103f746d17cSMukkund Sunjii     PetscScalar *u;
104f746d17cSMukkund Sunjii     PetscInt cell, cStart, cEnd;
105f746d17cSMukkund Sunjii     PetscReal cellvol, centroid[3], normal[3];
106f746d17cSMukkund Sunjii 
107f746d17cSMukkund Sunjii     PetscFunctionBeginUser;
108f746d17cSMukkund Sunjii     /* Get pointers to vector data */
109f746d17cSMukkund Sunjii     ierr = VecGetArray(U, &u);CHKERRQ(ierr);
110f746d17cSMukkund Sunjii     /* Get local grid boundaries */
111f746d17cSMukkund Sunjii     ierr = DMPlexGetHeightStratum(da, 0, &cStart, &cEnd);CHKERRQ(ierr);
112f746d17cSMukkund Sunjii     /* Assigning the values at the cell centers based on x and y directions */
113f746d17cSMukkund Sunjii     for (cell = cStart; cell < cEnd; cell++) {
114f746d17cSMukkund Sunjii         ierr = DMPlexComputeCellGeometryFVM(da, cell, &cellvol, centroid, normal);CHKERRQ(ierr);
115f746d17cSMukkund Sunjii         if (centroid[0] > 0.9 && centroid[0] < 0.95) {
116f746d17cSMukkund Sunjii             if (centroid[1] > 0.9 && centroid[1] < 0.95) u[cell] = 2.0;
117f746d17cSMukkund Sunjii         }
118f746d17cSMukkund Sunjii         else u[cell] = 0;
119f746d17cSMukkund Sunjii     }
120f746d17cSMukkund Sunjii     ierr = VecRestoreArray(U, &u);CHKERRQ(ierr);
121f746d17cSMukkund Sunjii     PetscFunctionReturn(0);
122f746d17cSMukkund Sunjii }
123f746d17cSMukkund Sunjii 
124f746d17cSMukkund Sunjii PetscErrorCode MyTSMonitor(TS ts, PetscInt step, PetscReal ptime, Vec v, void *ctx) {
125f746d17cSMukkund Sunjii     PetscErrorCode ierr;
126f746d17cSMukkund Sunjii     PetscReal norm;
127f746d17cSMukkund Sunjii     MPI_Comm comm;
128f746d17cSMukkund Sunjii     PetscFunctionBeginUser;
129f746d17cSMukkund Sunjii     if (step < 0) PetscFunctionReturn(0); /* step of -1 indicates an interpolated solution */
130f746d17cSMukkund Sunjii     ierr = VecNorm(v, NORM_2, &norm);CHKERRQ(ierr);
131f746d17cSMukkund Sunjii     ierr = PetscObjectGetComm((PetscObject) ts, &comm);CHKERRQ(ierr);
132f746d17cSMukkund Sunjii     ierr = PetscPrintf(comm, "timestep %D time %g norm %g\n", step, (double) ptime, (double) norm);CHKERRQ(ierr);
133f746d17cSMukkund Sunjii     PetscFunctionReturn(0);
134f746d17cSMukkund Sunjii }
135f746d17cSMukkund Sunjii 
136f746d17cSMukkund Sunjii /*
137f746d17cSMukkund Sunjii    MySNESMonitor - illustrate how to set user-defined monitoring routine for SNES.
138f746d17cSMukkund Sunjii    Input Parameters:
139f746d17cSMukkund Sunjii      snes - the SNES context
140f746d17cSMukkund Sunjii      its - iteration number
141f746d17cSMukkund Sunjii      fnorm - 2-norm function value (may be estimated)
142f746d17cSMukkund Sunjii      ctx - optional user-defined context for private data for the
143f746d17cSMukkund Sunjii          monitor routine, as set by SNESMonitorSet()
144f746d17cSMukkund Sunjii */
145f746d17cSMukkund Sunjii PetscErrorCode MySNESMonitor(SNES snes, PetscInt its, PetscReal fnorm, PetscViewerAndFormat *vf) {
146f746d17cSMukkund Sunjii     PetscErrorCode ierr;
147f746d17cSMukkund Sunjii     PetscFunctionBeginUser;
148f746d17cSMukkund Sunjii     ierr = SNESMonitorDefaultShort(snes, its, fnorm, vf);CHKERRQ(ierr);
149f746d17cSMukkund Sunjii     PetscFunctionReturn(0);
150f746d17cSMukkund Sunjii }
151f746d17cSMukkund Sunjii 
152f746d17cSMukkund Sunjii /*
153f746d17cSMukkund Sunjii    FormFunction - Evaluates nonlinear function, F(x).
154f746d17cSMukkund Sunjii 
155f746d17cSMukkund Sunjii    Input Parameters:
156f746d17cSMukkund Sunjii .  ts - the TS context
157f746d17cSMukkund Sunjii .  X - input vector
158f746d17cSMukkund Sunjii .  ctx - optional user-defined context, as set by SNESSetFunction()
159f746d17cSMukkund Sunjii 
160f746d17cSMukkund Sunjii    Output Parameter:
161f746d17cSMukkund Sunjii .  F - function vector
162f746d17cSMukkund Sunjii  */
163f746d17cSMukkund Sunjii PetscErrorCode FormFunction(TS ts, PetscReal ftime, Vec X, Vec F, void *ctx) {
164f746d17cSMukkund Sunjii     AppCtx *user = (AppCtx *) ctx;
165f746d17cSMukkund Sunjii     DM da = (DM) user->da;
166f746d17cSMukkund Sunjii     PetscErrorCode ierr;
167f746d17cSMukkund Sunjii     PetscScalar *x, *f;
168f746d17cSMukkund Sunjii     Vec localX;
169f746d17cSMukkund Sunjii     PetscInt fStart, fEnd, nF;
170f746d17cSMukkund Sunjii     PetscInt cell, cStart, cEnd, nC;
171f746d17cSMukkund Sunjii     DM dmFace;      /* DMPLEX for face geometry */
172f746d17cSMukkund Sunjii     PetscFV fvm;                /* specify type of FVM discretization */
173f746d17cSMukkund Sunjii     Vec cellGeom, faceGeom; /* vector of structs related to cell/face geometry*/
174f746d17cSMukkund Sunjii     const PetscScalar *fgeom;             /* values stored in the vector facegeom */
175f746d17cSMukkund Sunjii     PetscFVFaceGeom *fgA;               /* struct with face geometry information */
176f746d17cSMukkund Sunjii     const PetscInt *cellcone, *cellsupport;
177f746d17cSMukkund Sunjii     PetscScalar flux_east, flux_west, flux_north, flux_south, flux_centre;
178f746d17cSMukkund Sunjii     PetscScalar centroid_x[2], centroid_y[2], boundary = 0.0;
179f746d17cSMukkund Sunjii     PetscScalar boundary_left = 0.0;
180f746d17cSMukkund Sunjii     PetscReal u_plus, u_minus, v_plus, v_minus, zero = 0.0;
181f746d17cSMukkund Sunjii     PetscScalar delta_x, delta_y;
182f746d17cSMukkund Sunjii 
183f746d17cSMukkund Sunjii     /* Get the local vector from the DM object. */
184f746d17cSMukkund Sunjii     PetscFunctionBeginUser;
185f746d17cSMukkund Sunjii     ierr = DMGetLocalVector(da, &localX);CHKERRQ(ierr);
186f746d17cSMukkund Sunjii 
187f746d17cSMukkund Sunjii     /* Scatter ghost points to local vector,using the 2-step process
188f746d17cSMukkund Sunjii        DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). */
189f746d17cSMukkund Sunjii     ierr = DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX);CHKERRQ(ierr);
190f746d17cSMukkund Sunjii     ierr = DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX);CHKERRQ(ierr);
191f746d17cSMukkund Sunjii     /* Get pointers to vector data. */
192f746d17cSMukkund Sunjii     ierr = VecGetArray(localX, &x);CHKERRQ(ierr);
193f746d17cSMukkund Sunjii     ierr = VecGetArray(F, &f);CHKERRQ(ierr);
194f746d17cSMukkund Sunjii 
195f746d17cSMukkund Sunjii     /* Obtaining local cell and face ownership */
196f746d17cSMukkund Sunjii     ierr = DMPlexGetHeightStratum(da, 0, &cStart, &cEnd);CHKERRQ(ierr);
197f746d17cSMukkund Sunjii     ierr = DMPlexGetHeightStratum(da, 1, &fStart, &fEnd);CHKERRQ(ierr);
198f746d17cSMukkund Sunjii 
199f746d17cSMukkund Sunjii     /* Creating the PetscFV object to obtain face and cell geometry.
200f746d17cSMukkund Sunjii     Later to be used to compute face centroid to find cell widths. */
201f746d17cSMukkund Sunjii 
202f746d17cSMukkund Sunjii     ierr = PetscFVCreate(PETSC_COMM_WORLD, &fvm);CHKERRQ(ierr);
203f746d17cSMukkund Sunjii     ierr = PetscFVSetType(fvm, PETSCFVUPWIND);CHKERRQ(ierr);
204f746d17cSMukkund Sunjii     /*....Retrieve precomputed cell geometry....*/
205f746d17cSMukkund Sunjii     ierr = DMPlexGetDataFVM(da, fvm, &cellGeom, &faceGeom, NULL);CHKERRQ(ierr);
206f746d17cSMukkund Sunjii     ierr = VecGetDM(faceGeom, &dmFace);CHKERRQ(ierr);
207f746d17cSMukkund Sunjii     ierr = VecGetArrayRead(faceGeom, &fgeom);CHKERRQ(ierr);
208f746d17cSMukkund Sunjii 
209f746d17cSMukkund Sunjii     /* Spanning through all the cells and an inner loop through the faces. Find the
210f746d17cSMukkund Sunjii     face neighbors and pick the upwinded cell value for flux. */
211f746d17cSMukkund Sunjii 
212f746d17cSMukkund Sunjii     u_plus = PetscMax(user->u, zero);
213f746d17cSMukkund Sunjii     u_minus = PetscMin(user->u, zero);
214f746d17cSMukkund Sunjii     v_plus = PetscMax(user->v, zero);
215f746d17cSMukkund Sunjii     v_minus = PetscMin(user->v, zero);
216f746d17cSMukkund Sunjii 
217f746d17cSMukkund Sunjii     for (cell = cStart; cell < cEnd; cell++) {
218f746d17cSMukkund Sunjii         /* Obtaining the faces of the cell */
219f746d17cSMukkund Sunjii         ierr = DMPlexGetConeSize(da, cell, &nF);CHKERRQ(ierr);
220f746d17cSMukkund Sunjii         ierr = DMPlexGetCone(da, cell, &cellcone);CHKERRQ(ierr);
221f746d17cSMukkund Sunjii 
222f746d17cSMukkund Sunjii         /* south */
223f746d17cSMukkund Sunjii         ierr = DMPlexPointLocalRead(dmFace, cellcone[0], fgeom, &fgA);CHKERRQ(ierr);
224f746d17cSMukkund Sunjii         centroid_y[0] = fgA->centroid[1];
225f746d17cSMukkund Sunjii         /* North */
226f746d17cSMukkund Sunjii         ierr = DMPlexPointLocalRead(dmFace, cellcone[2], fgeom, &fgA);CHKERRQ(ierr);
227f746d17cSMukkund Sunjii         centroid_y[1] = fgA->centroid[1];
228f746d17cSMukkund Sunjii         /* West */
229f746d17cSMukkund Sunjii         ierr = DMPlexPointLocalRead(dmFace, cellcone[3], fgeom, &fgA);CHKERRQ(ierr);
230f746d17cSMukkund Sunjii         centroid_x[0] = fgA->centroid[0];
231f746d17cSMukkund Sunjii         /* East */
232f746d17cSMukkund Sunjii         ierr = DMPlexPointLocalRead(dmFace, cellcone[1], fgeom, &fgA);CHKERRQ(ierr);
233f746d17cSMukkund Sunjii         centroid_x[1] = fgA->centroid[0];
234f746d17cSMukkund Sunjii 
235f746d17cSMukkund Sunjii         /* Computing the cell widths in the x and y direction */
236f746d17cSMukkund Sunjii         delta_x = centroid_x[1] - centroid_x[0];
237f746d17cSMukkund Sunjii         delta_y = centroid_y[1] - centroid_y[0];
238f746d17cSMukkund Sunjii 
239f746d17cSMukkund Sunjii         /* Getting the neighbors of each face
240f746d17cSMukkund Sunjii            Going through the faces by the order (cellcone) */
241f746d17cSMukkund Sunjii 
242f746d17cSMukkund Sunjii         /* cellcone[0] - south */
243f746d17cSMukkund Sunjii         ierr = DMPlexGetSupportSize(da, cellcone[0], &nC);CHKERRQ(ierr);
244f746d17cSMukkund Sunjii         ierr = DMPlexGetSupport(da, cellcone[0], &cellsupport);CHKERRQ(ierr);
245f746d17cSMukkund Sunjii         if (nC == 2) flux_south = (x[cellsupport[0]] * (-v_plus - user->diffusion * delta_x)) / delta_y;
246f746d17cSMukkund Sunjii         else flux_south = (boundary * (-v_plus - user->diffusion * delta_x)) / delta_y;
247f746d17cSMukkund Sunjii 
248f746d17cSMukkund Sunjii         /* cellcone[1] - east */
249f746d17cSMukkund Sunjii         ierr = DMPlexGetSupportSize(da, cellcone[1], &nC);CHKERRQ(ierr);
250f746d17cSMukkund Sunjii         ierr = DMPlexGetSupport(da, cellcone[1], &cellsupport);CHKERRQ(ierr);
251f746d17cSMukkund Sunjii         if (nC == 2) flux_east = (x[cellsupport[1]] * (u_minus - user->diffusion * delta_y)) / delta_x;
252f746d17cSMukkund Sunjii         else flux_east = (boundary * (u_minus - user->diffusion * delta_y)) / delta_x;
253f746d17cSMukkund Sunjii 
254f746d17cSMukkund Sunjii         /* cellcone[2] - north */
255f746d17cSMukkund Sunjii         ierr = DMPlexGetSupportSize(da, cellcone[2], &nC);CHKERRQ(ierr);
256f746d17cSMukkund Sunjii         ierr = DMPlexGetSupport(da, cellcone[2], &cellsupport);CHKERRQ(ierr);
257f746d17cSMukkund Sunjii         if (nC == 2) flux_north = (x[cellsupport[1]] * (v_minus - user->diffusion * delta_x)) / delta_y;
258f746d17cSMukkund Sunjii         else flux_north = (boundary * (v_minus - user->diffusion * delta_x)) / delta_y;
259f746d17cSMukkund Sunjii 
260f746d17cSMukkund Sunjii         /* cellcone[3] - west */
261f746d17cSMukkund Sunjii         ierr = DMPlexGetSupportSize(da, cellcone[3], &nC);CHKERRQ(ierr);
262f746d17cSMukkund Sunjii         ierr = DMPlexGetSupport(da, cellcone[3], &cellsupport);CHKERRQ(ierr);
263f746d17cSMukkund Sunjii         if (nC == 2) flux_west = (x[cellsupport[0]] * (-u_plus - user->diffusion * delta_y)) / delta_x;
264f746d17cSMukkund Sunjii         else flux_west = (boundary_left * (-u_plus - user->diffusion * delta_y)) / delta_x;
265f746d17cSMukkund Sunjii 
266f746d17cSMukkund Sunjii         /* Contribution by the cell to the fluxes */
267f746d17cSMukkund Sunjii         flux_centre = x[cell] * ((u_plus - u_minus + 2 * user->diffusion * delta_y) / delta_x +
268f746d17cSMukkund Sunjii                                  (v_plus - v_minus + 2 * user->diffusion * delta_x) / delta_y);
269f746d17cSMukkund Sunjii 
270f746d17cSMukkund Sunjii         /* Calculating the net flux for each cell
271f746d17cSMukkund Sunjii            and computing the RHS time derivative f[.] */
272f746d17cSMukkund Sunjii         f[cell] = -(flux_centre + flux_east + flux_west + flux_north + flux_south);
273f746d17cSMukkund Sunjii 
274f746d17cSMukkund Sunjii     }
275f746d17cSMukkund Sunjii 
276f746d17cSMukkund Sunjii     ierr = PetscFVDestroy(&fvm);
277f746d17cSMukkund Sunjii     ierr = VecRestoreArray(localX, &x);CHKERRQ(ierr);
278f746d17cSMukkund Sunjii     ierr = VecRestoreArray(F, &f);CHKERRQ(ierr);
279f746d17cSMukkund Sunjii     ierr = DMRestoreLocalVector(da, &localX);CHKERRQ(ierr);
280f746d17cSMukkund Sunjii 
281f746d17cSMukkund Sunjii     PetscFunctionReturn(0);
282f746d17cSMukkund Sunjii }
283f746d17cSMukkund Sunjii 
284f746d17cSMukkund Sunjii int main(int argc, char **argv) {
285f746d17cSMukkund Sunjii     TS ts;                         /* time integrator */
286f746d17cSMukkund Sunjii     SNES snes;
287f746d17cSMukkund Sunjii     Vec x, r;                        /* solution, residual vectors */
288f746d17cSMukkund Sunjii     PetscErrorCode ierr;
289f746d17cSMukkund Sunjii     DM da;
290f746d17cSMukkund Sunjii     PetscMPIInt rank;
291f746d17cSMukkund Sunjii     PetscViewerAndFormat *vf;
292f746d17cSMukkund Sunjii     AppCtx user;                             /* mesh context */
293f746d17cSMukkund Sunjii     PetscInt numFields = 1, numBC, i;
294f746d17cSMukkund Sunjii     PetscInt numComp[1];
295f746d17cSMukkund Sunjii     PetscInt numDof[12];
296f746d17cSMukkund Sunjii     PetscInt bcField[1];
297f746d17cSMukkund Sunjii     PetscSection section;
298f746d17cSMukkund Sunjii     IS bcPointIS[1];
299f746d17cSMukkund Sunjii 
300f746d17cSMukkund Sunjii     /* Initialize program */
301f746d17cSMukkund Sunjii     ierr = PetscInitialize(&argc, &argv, (char *) 0, help);
302f746d17cSMukkund Sunjii     if (ierr) return ierr;
303f746d17cSMukkund Sunjii     ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);CHKERRQ(ierr);
304f746d17cSMukkund Sunjii     /* Create distributed array (DMPLEX) to manage parallel grid and vectors */
305f746d17cSMukkund Sunjii     ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr);
306f746d17cSMukkund Sunjii     ierr = CreateMesh(PETSC_COMM_WORLD, &user, &da);CHKERRQ(ierr);
307f746d17cSMukkund Sunjii 
308f746d17cSMukkund Sunjii     /* Specifying the fields and dof for the formula through PETSc Section
309f746d17cSMukkund Sunjii     Create a scalar field u with 1 component on cells, faces and edges.
310f746d17cSMukkund Sunjii     Alternatively, the field information could be added through a PETSCFV object
311f746d17cSMukkund Sunjii     using DMAddField(...).*/
312f746d17cSMukkund Sunjii     numComp[0] = 1;
313f746d17cSMukkund Sunjii 
314f746d17cSMukkund Sunjii     for (i = 0; i < numFields * (user.dim + 1); ++i) numDof[i] = 0;
315f746d17cSMukkund Sunjii 
316f746d17cSMukkund Sunjii     numDof[0 * (user.dim + 1)] = 1;
317f746d17cSMukkund Sunjii     numDof[0 * (user.dim + 1) + user.dim - 1] = 1;
318f746d17cSMukkund Sunjii     numDof[0 * (user.dim + 1) + user.dim] = 1;
319f746d17cSMukkund Sunjii 
320f746d17cSMukkund Sunjii     /* Setup boundary conditions */
321f746d17cSMukkund Sunjii     numBC = 1;
322f746d17cSMukkund Sunjii     /* Prescribe a Dirichlet condition on u on the boundary
323f746d17cSMukkund Sunjii        Label "marker" is made by the mesh creation routine  */
324f746d17cSMukkund Sunjii     bcField[0] = 0;
325f746d17cSMukkund Sunjii     ierr = DMGetStratumIS(da, "marker", 1, &bcPointIS[0]);CHKERRQ(ierr);
326f746d17cSMukkund Sunjii 
327f746d17cSMukkund Sunjii     /* Create a PetscSection with this data layout */
328f746d17cSMukkund Sunjii     ierr = DMSetNumFields(da, numFields);CHKERRQ(ierr);
329f746d17cSMukkund Sunjii     ierr = DMPlexCreateSection(da, NULL, numComp, numDof, numBC, bcField, NULL, bcPointIS, NULL, &section);CHKERRQ(ierr);
330f746d17cSMukkund Sunjii 
331f746d17cSMukkund Sunjii     /* Name the Field variables */
332f746d17cSMukkund Sunjii     ierr = PetscSectionSetFieldName(section, 0, "u");CHKERRQ(ierr);
333f746d17cSMukkund Sunjii 
334f746d17cSMukkund Sunjii     /* Tell the DM to use this section (with the specified fields and dof) */
335f746d17cSMukkund Sunjii     ierr = DMSetLocalSection(da, section);CHKERRQ(ierr);
336f746d17cSMukkund Sunjii     user.da = da;
337f746d17cSMukkund Sunjii 
338f746d17cSMukkund Sunjii     /* Extract global vectors from DMDA; then duplicate for remaining
339f746d17cSMukkund Sunjii        vectors that are the same types */
340f746d17cSMukkund Sunjii 
341f746d17cSMukkund Sunjii     /* Create a Vec with this layout and view it */
342f746d17cSMukkund Sunjii     ierr = DMGetGlobalVector(da, &x);CHKERRQ(ierr);
343f746d17cSMukkund Sunjii     ierr = VecDuplicate(x, &r);CHKERRQ(ierr);
344f746d17cSMukkund Sunjii 
345f746d17cSMukkund Sunjii     /* Create timestepping solver context */
346f746d17cSMukkund Sunjii     ierr = TSCreate(PETSC_COMM_WORLD, &ts);CHKERRQ(ierr);
347f746d17cSMukkund Sunjii     ierr = TSSetProblemType(ts, TS_NONLINEAR);CHKERRQ(ierr);
348f746d17cSMukkund Sunjii     ierr = TSSetRHSFunction(ts, NULL, FormFunction, &user);CHKERRQ(ierr);
349f746d17cSMukkund Sunjii 
350f746d17cSMukkund Sunjii     ierr = TSSetMaxTime(ts, 1.0);CHKERRQ(ierr);
351f746d17cSMukkund Sunjii     ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr);
352f746d17cSMukkund Sunjii     ierr = TSMonitorSet(ts, MyTSMonitor, PETSC_VIEWER_STDOUT_WORLD, NULL);CHKERRQ(ierr);
353f746d17cSMukkund Sunjii     ierr = TSSetDM(ts, da);CHKERRQ(ierr);
354f746d17cSMukkund Sunjii 
355f746d17cSMukkund Sunjii     /* Customize nonlinear solver */
356f746d17cSMukkund Sunjii     ierr = TSSetType(ts, TSEULER);CHKERRQ(ierr);
357f746d17cSMukkund Sunjii     ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
358f746d17cSMukkund Sunjii     ierr = PetscViewerAndFormatCreate(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_DEFAULT, &vf);CHKERRQ(ierr);
359f746d17cSMukkund Sunjii     ierr = SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *)) MySNESMonitor, vf,(PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr);
360f746d17cSMukkund Sunjii 
361f746d17cSMukkund Sunjii      /* Set initial conditions */
362f746d17cSMukkund Sunjii     ierr = FormInitialSolution(da, x);CHKERRQ(ierr);
363f746d17cSMukkund Sunjii     ierr = TSSetTimeStep(ts, .0001);CHKERRQ(ierr);
364f746d17cSMukkund Sunjii     ierr = TSSetSolution(ts, x);CHKERRQ(ierr);
365f746d17cSMukkund Sunjii     /* Set runtime options */
366f746d17cSMukkund Sunjii     ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
367f746d17cSMukkund Sunjii     /* Solve nonlinear system */
368f746d17cSMukkund Sunjii     ierr = TSSolve(ts, x);CHKERRQ(ierr);
369f746d17cSMukkund Sunjii 
370f746d17cSMukkund Sunjii     /* Clean up routine */
371f746d17cSMukkund Sunjii     ierr = DMRestoreGlobalVector(da, &x);CHKERRQ(ierr);
372f746d17cSMukkund Sunjii     ierr = ISDestroy(&bcPointIS[0]);CHKERRQ(ierr);
373f746d17cSMukkund Sunjii     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
374f746d17cSMukkund Sunjii     ierr = VecDestroy(&r);CHKERRQ(ierr);
375f746d17cSMukkund Sunjii     ierr = TSDestroy(&ts);CHKERRQ(ierr);
376f746d17cSMukkund Sunjii     ierr = DMDestroy(&da);CHKERRQ(ierr);
377f746d17cSMukkund Sunjii     ierr = PetscFinalize();
378f746d17cSMukkund Sunjii     return ierr;
379f746d17cSMukkund Sunjii }
380f746d17cSMukkund Sunjii 
381f746d17cSMukkund Sunjii /*TEST
382f746d17cSMukkund Sunjii 
383f746d17cSMukkund Sunjii     test:
384f746d17cSMukkund Sunjii       suffix: 0
385f746d17cSMukkund Sunjii       args: -ts_max_steps 5 -ts_type rk
386f746d17cSMukkund Sunjii       requires: !single !complex triangle ctetgen
387f746d17cSMukkund Sunjii 
388f746d17cSMukkund Sunjii TEST*/
389