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, §ion);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(§ion);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