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