1*c4762a1bSJed Brown static char help[] = "Multiphase flow in a porous medium in 1d.\n\n"; 2*c4762a1bSJed Brown #include <petscdm.h> 3*c4762a1bSJed Brown #include <petscdmda.h> 4*c4762a1bSJed Brown #include <petscsnes.h> 5*c4762a1bSJed Brown 6*c4762a1bSJed Brown typedef struct { 7*c4762a1bSJed Brown DM cda; 8*c4762a1bSJed Brown Vec uold; 9*c4762a1bSJed Brown Vec Kappa; 10*c4762a1bSJed Brown PetscReal phi; 11*c4762a1bSJed Brown PetscReal kappaWet; 12*c4762a1bSJed Brown PetscReal kappaNoWet; 13*c4762a1bSJed Brown PetscReal dt; 14*c4762a1bSJed Brown /* Boundary conditions */ 15*c4762a1bSJed Brown PetscReal sl, vl, pl; 16*c4762a1bSJed Brown } AppCtx; 17*c4762a1bSJed Brown 18*c4762a1bSJed Brown typedef struct { 19*c4762a1bSJed Brown PetscScalar s; /* The saturation on each cell */ 20*c4762a1bSJed Brown PetscScalar v; /* The velocity on each face */ 21*c4762a1bSJed Brown PetscScalar p; /* The pressure on each cell */ 22*c4762a1bSJed Brown } Field; 23*c4762a1bSJed Brown 24*c4762a1bSJed Brown /* 25*c4762a1bSJed Brown FormPermeability - Forms permeability field. 26*c4762a1bSJed Brown 27*c4762a1bSJed Brown Input Parameters: 28*c4762a1bSJed Brown user - user-defined application context 29*c4762a1bSJed Brown 30*c4762a1bSJed Brown Output Parameter: 31*c4762a1bSJed Brown Kappa - vector 32*c4762a1bSJed Brown */ 33*c4762a1bSJed Brown PetscErrorCode FormPermeability(DM da, Vec Kappa, AppCtx *user) 34*c4762a1bSJed Brown { 35*c4762a1bSJed Brown DM cda; 36*c4762a1bSJed Brown Vec c; 37*c4762a1bSJed Brown PetscScalar *K; 38*c4762a1bSJed Brown PetscScalar *coords; 39*c4762a1bSJed Brown PetscInt xs, xm, i; 40*c4762a1bSJed Brown PetscErrorCode ierr; 41*c4762a1bSJed Brown 42*c4762a1bSJed Brown PetscFunctionBeginUser; 43*c4762a1bSJed Brown ierr = DMGetCoordinateDM(da, &cda);CHKERRQ(ierr); 44*c4762a1bSJed Brown ierr = DMGetCoordinates(da, &c);CHKERRQ(ierr); 45*c4762a1bSJed Brown ierr = DMDAGetCorners(da, &xs,NULL,NULL, &xm,NULL,NULL);CHKERRQ(ierr); 46*c4762a1bSJed Brown ierr = DMDAVecGetArray(da, Kappa, &K);CHKERRQ(ierr); 47*c4762a1bSJed Brown ierr = DMDAVecGetArray(cda, c, &coords);CHKERRQ(ierr); 48*c4762a1bSJed Brown for (i = xs; i < xs+xm; ++i) { 49*c4762a1bSJed Brown #if 1 50*c4762a1bSJed Brown K[i] = 1.0; 51*c4762a1bSJed Brown #else 52*c4762a1bSJed Brown /* Notch */ 53*c4762a1bSJed Brown if (i == (xs+xm)/2) K[i] = 0.00000001; 54*c4762a1bSJed Brown else K[i] = 1.0; 55*c4762a1bSJed Brown #endif 56*c4762a1bSJed Brown } 57*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(da, Kappa, &K);CHKERRQ(ierr); 58*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(cda, c, &coords);CHKERRQ(ierr); 59*c4762a1bSJed Brown PetscFunctionReturn(0); 60*c4762a1bSJed Brown } 61*c4762a1bSJed Brown 62*c4762a1bSJed Brown /* 63*c4762a1bSJed Brown FormFunctionLocal - Evaluates nonlinear residual, F(x) on local process patch 64*c4762a1bSJed Brown */ 65*c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo *info, Field *u, Field *f, AppCtx *user) 66*c4762a1bSJed Brown { 67*c4762a1bSJed Brown Vec L; 68*c4762a1bSJed Brown PetscReal phi = user->phi; 69*c4762a1bSJed Brown PetscReal dt = user->dt; 70*c4762a1bSJed Brown PetscReal dx = 1.0/(PetscReal)(info->mx-1); 71*c4762a1bSJed Brown PetscReal alpha = 2.0; 72*c4762a1bSJed Brown PetscReal beta = 2.0; 73*c4762a1bSJed Brown PetscReal kappaWet = user->kappaWet; 74*c4762a1bSJed Brown PetscReal kappaNoWet = user->kappaNoWet; 75*c4762a1bSJed Brown Field *uold; 76*c4762a1bSJed Brown PetscScalar *Kappa; 77*c4762a1bSJed Brown PetscInt i; 78*c4762a1bSJed Brown PetscErrorCode ierr; 79*c4762a1bSJed Brown 80*c4762a1bSJed Brown PetscFunctionBeginUser; 81*c4762a1bSJed Brown ierr = DMGetGlobalVector(user->cda, &L);CHKERRQ(ierr); 82*c4762a1bSJed Brown 83*c4762a1bSJed Brown ierr = DMDAVecGetArray(info->da, user->uold, &uold);CHKERRQ(ierr); 84*c4762a1bSJed Brown ierr = DMDAVecGetArray(user->cda, user->Kappa, &Kappa);CHKERRQ(ierr); 85*c4762a1bSJed Brown /* Compute residual over the locally owned part of the grid */ 86*c4762a1bSJed Brown for (i = info->xs; i < info->xs+info->xm; ++i) { 87*c4762a1bSJed Brown if (i == 0) { 88*c4762a1bSJed Brown f[i].s = u[i].s - user->sl; 89*c4762a1bSJed Brown f[i].v = u[i].v - user->vl; 90*c4762a1bSJed Brown f[i].p = u[i].p - user->pl; 91*c4762a1bSJed Brown } else { 92*c4762a1bSJed Brown PetscScalar K = 2*dx/(dx/Kappa[i] + dx/Kappa[i-1]); 93*c4762a1bSJed Brown PetscReal lambdaWet = kappaWet*PetscRealPart(PetscPowScalar(u[i].s, alpha)); 94*c4762a1bSJed Brown PetscReal lambda = lambdaWet + kappaNoWet*PetscRealPart(PetscPowScalar(1.-u[i].s, beta)); 95*c4762a1bSJed Brown PetscReal lambdaWetL = kappaWet*PetscRealPart(PetscPowScalar(u[i-1].s, alpha)); 96*c4762a1bSJed Brown PetscReal lambdaL = lambdaWetL + kappaNoWet*PetscRealPart(PetscPowScalar(1.-u[i-1].s, beta)); 97*c4762a1bSJed Brown 98*c4762a1bSJed Brown f[i].s = phi*(u[i].s - uold[i].s) + (dt/dx)*((lambdaWet/lambda)*u[i].v - (lambdaWetL/lambdaL)*u[i-1].v); 99*c4762a1bSJed Brown 100*c4762a1bSJed Brown f[i].v = u[i].v + K*lambda*(u[i].p - u[i-1].p)/dx; 101*c4762a1bSJed Brown 102*c4762a1bSJed Brown /*pxx = (2.0*u[i].p - u[i-1].p - u[i+1].p)/dx;*/ 103*c4762a1bSJed Brown f[i].p = u[i].v - u[i-1].v; 104*c4762a1bSJed Brown } 105*c4762a1bSJed Brown } 106*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(info->da, user->uold, &uold);CHKERRQ(ierr); 107*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(user->cda, user->Kappa, &Kappa);CHKERRQ(ierr); 108*c4762a1bSJed Brown /* ierr = PetscLogFlops(11.0*info->ym*info->xm);CHKERRQ(ierr); */ 109*c4762a1bSJed Brown 110*c4762a1bSJed Brown ierr = DMRestoreGlobalVector(user->cda, &L);CHKERRQ(ierr); 111*c4762a1bSJed Brown PetscFunctionReturn(0); 112*c4762a1bSJed Brown } 113*c4762a1bSJed Brown 114*c4762a1bSJed Brown int main(int argc, char **argv) 115*c4762a1bSJed Brown { 116*c4762a1bSJed Brown SNES snes; /* nonlinear solver */ 117*c4762a1bSJed Brown DM da; /* grid */ 118*c4762a1bSJed Brown Vec u; /* solution vector */ 119*c4762a1bSJed Brown AppCtx user; /* user-defined work context */ 120*c4762a1bSJed Brown PetscReal t = 0.0;/* time */ 121*c4762a1bSJed Brown PetscErrorCode ierr; 122*c4762a1bSJed Brown PetscInt n; 123*c4762a1bSJed Brown 124*c4762a1bSJed Brown ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 125*c4762a1bSJed Brown /* Create solver */ 126*c4762a1bSJed Brown ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); 127*c4762a1bSJed Brown /* Create mesh */ 128*c4762a1bSJed Brown ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,4,3,1,NULL,&da);CHKERRQ(ierr); 129*c4762a1bSJed Brown ierr = DMSetFromOptions(da);CHKERRQ(ierr); 130*c4762a1bSJed Brown ierr = DMSetUp(da);CHKERRQ(ierr); 131*c4762a1bSJed Brown ierr = DMSetApplicationContext(da, &user);CHKERRQ(ierr); 132*c4762a1bSJed Brown ierr = SNESSetDM(snes, da);CHKERRQ(ierr); 133*c4762a1bSJed Brown /* Create coefficient */ 134*c4762a1bSJed Brown ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,4,1,1,NULL,&user.cda);CHKERRQ(ierr); 135*c4762a1bSJed Brown ierr = DMSetFromOptions(user.cda);CHKERRQ(ierr); 136*c4762a1bSJed Brown ierr = DMSetUp(user.cda);CHKERRQ(ierr); 137*c4762a1bSJed Brown ierr = DMDASetUniformCoordinates(user.cda, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0);CHKERRQ(ierr); 138*c4762a1bSJed Brown ierr = DMGetGlobalVector(user.cda, &user.Kappa);CHKERRQ(ierr); 139*c4762a1bSJed Brown ierr = FormPermeability(user.cda, user.Kappa, &user);CHKERRQ(ierr); 140*c4762a1bSJed Brown /* Setup Problem */ 141*c4762a1bSJed Brown ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); 142*c4762a1bSJed Brown ierr = DMGetGlobalVector(da, &u);CHKERRQ(ierr); 143*c4762a1bSJed Brown ierr = DMGetGlobalVector(da, &user.uold);CHKERRQ(ierr); 144*c4762a1bSJed Brown 145*c4762a1bSJed Brown user.sl = 1.0; 146*c4762a1bSJed Brown user.vl = 0.1; 147*c4762a1bSJed Brown user.pl = 1.0; 148*c4762a1bSJed Brown user.phi = 1.0; 149*c4762a1bSJed Brown 150*c4762a1bSJed Brown user.kappaWet = 1.0; 151*c4762a1bSJed Brown user.kappaNoWet = 0.3; 152*c4762a1bSJed Brown 153*c4762a1bSJed Brown /* Time Loop */ 154*c4762a1bSJed Brown user.dt = 0.1; 155*c4762a1bSJed Brown for (n = 0; n < 100; ++n, t += user.dt) { 156*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, "Starting time %g\n", (double)t);CHKERRQ(ierr); 157*c4762a1bSJed Brown ierr = VecView(u, PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr); 158*c4762a1bSJed Brown /* Solve */ 159*c4762a1bSJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 160*c4762a1bSJed Brown ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr); 161*c4762a1bSJed Brown /* Update */ 162*c4762a1bSJed Brown ierr = VecCopy(u, user.uold);CHKERRQ(ierr); 163*c4762a1bSJed Brown 164*c4762a1bSJed Brown ierr = VecView(u, PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr); 165*c4762a1bSJed Brown } 166*c4762a1bSJed Brown /* Cleanup */ 167*c4762a1bSJed Brown ierr = DMRestoreGlobalVector(da, &u);CHKERRQ(ierr); 168*c4762a1bSJed Brown ierr = DMRestoreGlobalVector(da, &user.uold);CHKERRQ(ierr); 169*c4762a1bSJed Brown ierr = DMRestoreGlobalVector(user.cda, &user.Kappa);CHKERRQ(ierr); 170*c4762a1bSJed Brown ierr = DMDestroy(&user.cda);CHKERRQ(ierr); 171*c4762a1bSJed Brown ierr = DMDestroy(&da);CHKERRQ(ierr); 172*c4762a1bSJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 173*c4762a1bSJed Brown ierr = PetscFinalize(); 174*c4762a1bSJed Brown return ierr; 175*c4762a1bSJed Brown } 176*c4762a1bSJed Brown 177*c4762a1bSJed Brown /*TEST 178*c4762a1bSJed Brown 179*c4762a1bSJed Brown test: 180*c4762a1bSJed Brown suffix: 0 181*c4762a1bSJed Brown requires: !single 182*c4762a1bSJed Brown args: -snes_converged_reason -snes_monitor_short 183*c4762a1bSJed Brown 184*c4762a1bSJed Brown TEST*/ 185