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