1c4762a1bSJed Brown 2c4762a1bSJed Brown static char help[] = "Tests recovery from domain errors in MatMult() and PCApply()\n\n"; 3c4762a1bSJed Brown 4c4762a1bSJed Brown /* 5c4762a1bSJed Brown See src/ksp/ksp/tutorials/ex19.c from which this was copied 6c4762a1bSJed Brown */ 7c4762a1bSJed Brown 8c4762a1bSJed Brown #include <petscsnes.h> 9c4762a1bSJed Brown #include <petscdm.h> 10c4762a1bSJed Brown #include <petscdmda.h> 11c4762a1bSJed Brown 12c4762a1bSJed Brown /* 13c4762a1bSJed Brown User-defined routines and data structures 14c4762a1bSJed Brown */ 15c4762a1bSJed Brown typedef struct { 16c4762a1bSJed Brown PetscScalar u,v,omega,temp; 17c4762a1bSJed Brown } Field; 18c4762a1bSJed Brown 19c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo*,Field**,Field**,void*); 20c4762a1bSJed Brown 21c4762a1bSJed Brown typedef struct { 22c4762a1bSJed Brown PetscReal lidvelocity,prandtl,grashof; /* physical parameters */ 23c4762a1bSJed Brown PetscBool draw_contours; /* flag - 1 indicates drawing contours */ 24c4762a1bSJed Brown PetscBool errorindomain; 25c4762a1bSJed Brown PetscBool errorindomainmf; 26c4762a1bSJed Brown SNES snes; 27c4762a1bSJed Brown } AppCtx; 28c4762a1bSJed Brown 29c4762a1bSJed Brown typedef struct { 30c4762a1bSJed Brown Mat Jmf; 31c4762a1bSJed Brown } MatShellCtx; 32c4762a1bSJed Brown 33c4762a1bSJed Brown extern PetscErrorCode FormInitialGuess(AppCtx*,DM,Vec); 34c4762a1bSJed Brown extern PetscErrorCode MatMult_MyShell(Mat,Vec,Vec); 35c4762a1bSJed Brown extern PetscErrorCode MatAssemblyEnd_MyShell(Mat,MatAssemblyType); 36c4762a1bSJed Brown extern PetscErrorCode PCApply_MyShell(PC,Vec,Vec); 37c4762a1bSJed Brown extern PetscErrorCode SNESComputeJacobian_MyShell(SNES,Vec,Mat,Mat,void*); 38c4762a1bSJed Brown 39c4762a1bSJed Brown int main(int argc,char **argv) 40c4762a1bSJed Brown { 41c4762a1bSJed Brown AppCtx user; /* user-defined work context */ 42c4762a1bSJed Brown PetscInt mx,my; 43c4762a1bSJed Brown PetscErrorCode ierr; 44c4762a1bSJed Brown MPI_Comm comm; 45c4762a1bSJed Brown DM da; 46c4762a1bSJed Brown Vec x; 47c4762a1bSJed Brown Mat J = NULL,Jmf = NULL; 48c4762a1bSJed Brown MatShellCtx matshellctx; 49c4762a1bSJed Brown PetscInt mlocal,nlocal; 50c4762a1bSJed Brown PC pc; 51c4762a1bSJed Brown KSP ksp; 52c4762a1bSJed Brown PetscBool errorinmatmult = PETSC_FALSE,errorinpcapply = PETSC_FALSE,errorinpcsetup = PETSC_FALSE; 53c4762a1bSJed Brown 54c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; 55c4762a1bSJed Brown ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_matmult",&errorinmatmult,NULL);CHKERRQ(ierr); 56c4762a1bSJed Brown ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_pcapply",&errorinpcapply,NULL);CHKERRQ(ierr); 57c4762a1bSJed Brown ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_pcsetup",&errorinpcsetup,NULL);CHKERRQ(ierr); 58c4762a1bSJed Brown user.errorindomain = PETSC_FALSE; 59c4762a1bSJed Brown ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_domain",&user.errorindomain,NULL);CHKERRQ(ierr); 60c4762a1bSJed Brown user.errorindomainmf = PETSC_FALSE; 61c4762a1bSJed Brown ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_domainmf",&user.errorindomainmf,NULL);CHKERRQ(ierr); 62c4762a1bSJed Brown 63c4762a1bSJed Brown comm = PETSC_COMM_WORLD; 64c4762a1bSJed Brown ierr = SNESCreate(comm,&user.snes);CHKERRQ(ierr); 65c4762a1bSJed Brown 66c4762a1bSJed Brown /* 67c4762a1bSJed Brown Create distributed array object to manage parallel grid and vectors 68c4762a1bSJed Brown for principal unknowns (x) and governing residuals (f) 69c4762a1bSJed Brown */ 70c4762a1bSJed Brown ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,4,4,PETSC_DECIDE,PETSC_DECIDE,4,1,0,0,&da);CHKERRQ(ierr); 71c4762a1bSJed Brown ierr = DMSetFromOptions(da);CHKERRQ(ierr); 72c4762a1bSJed Brown ierr = DMSetUp(da);CHKERRQ(ierr); 73c4762a1bSJed Brown ierr = SNESSetDM(user.snes,da);CHKERRQ(ierr); 74c4762a1bSJed Brown 75c4762a1bSJed Brown ierr = DMDAGetInfo(da,0,&mx,&my,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, 76c4762a1bSJed Brown PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); 77c4762a1bSJed Brown /* 78c4762a1bSJed Brown Problem parameters (velocity of lid, prandtl, and grashof numbers) 79c4762a1bSJed Brown */ 80c4762a1bSJed Brown user.lidvelocity = 1.0/(mx*my); 81c4762a1bSJed Brown user.prandtl = 1.0; 82c4762a1bSJed Brown user.grashof = 1.0; 83c4762a1bSJed Brown 84c4762a1bSJed Brown ierr = PetscOptionsGetReal(NULL,NULL,"-lidvelocity",&user.lidvelocity,NULL);CHKERRQ(ierr); 85c4762a1bSJed Brown ierr = PetscOptionsGetReal(NULL,NULL,"-prandtl",&user.prandtl,NULL);CHKERRQ(ierr); 86c4762a1bSJed Brown ierr = PetscOptionsGetReal(NULL,NULL,"-grashof",&user.grashof,NULL);CHKERRQ(ierr); 87c4762a1bSJed Brown ierr = PetscOptionsHasName(NULL,NULL,"-contours",&user.draw_contours);CHKERRQ(ierr); 88c4762a1bSJed Brown 89c4762a1bSJed Brown ierr = DMDASetFieldName(da,0,"x_velocity");CHKERRQ(ierr); 90c4762a1bSJed Brown ierr = DMDASetFieldName(da,1,"y_velocity");CHKERRQ(ierr); 91c4762a1bSJed Brown ierr = DMDASetFieldName(da,2,"Omega");CHKERRQ(ierr); 92c4762a1bSJed Brown ierr = DMDASetFieldName(da,3,"temperature");CHKERRQ(ierr); 93c4762a1bSJed Brown 94c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 95c4762a1bSJed Brown Create user context, set problem data, create vector data structures. 96c4762a1bSJed Brown Also, compute the initial guess. 97c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 98c4762a1bSJed Brown 99c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 100c4762a1bSJed Brown Create nonlinear solver context 101c4762a1bSJed Brown 102c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 103c4762a1bSJed Brown ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); 104c4762a1bSJed Brown ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); 105c4762a1bSJed Brown 106c4762a1bSJed Brown if (errorinmatmult) { 107c4762a1bSJed Brown ierr = MatCreateSNESMF(user.snes,&Jmf);CHKERRQ(ierr); 108c4762a1bSJed Brown ierr = MatSetFromOptions(Jmf);CHKERRQ(ierr); 109c4762a1bSJed Brown ierr = MatGetLocalSize(Jmf,&mlocal,&nlocal);CHKERRQ(ierr); 110c4762a1bSJed Brown matshellctx.Jmf = Jmf; 111c4762a1bSJed Brown ierr = MatCreateShell(PetscObjectComm((PetscObject)Jmf),mlocal,nlocal,PETSC_DECIDE,PETSC_DECIDE,&matshellctx,&J);CHKERRQ(ierr); 112c4762a1bSJed Brown ierr = MatShellSetOperation(J,MATOP_MULT,(void (*)(void))MatMult_MyShell);CHKERRQ(ierr); 113c4762a1bSJed Brown ierr = MatShellSetOperation(J,MATOP_ASSEMBLY_END,(void (*)(void))MatAssemblyEnd_MyShell);CHKERRQ(ierr); 114c4762a1bSJed Brown ierr = SNESSetJacobian(user.snes,J,J,MatMFFDComputeJacobian,NULL);CHKERRQ(ierr); 115c4762a1bSJed Brown } 116c4762a1bSJed Brown 117c4762a1bSJed Brown ierr = SNESSetFromOptions(user.snes);CHKERRQ(ierr); 118c4762a1bSJed Brown ierr = PetscPrintf(comm,"lid velocity = %g, prandtl # = %g, grashof # = %g\n",(double)user.lidvelocity,(double)user.prandtl,(double)user.grashof);CHKERRQ(ierr); 119c4762a1bSJed Brown 120c4762a1bSJed Brown if (errorinpcapply) { 121c4762a1bSJed Brown ierr = SNESGetKSP(user.snes,&ksp);CHKERRQ(ierr); 122c4762a1bSJed Brown ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 123c4762a1bSJed Brown ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr); 124c4762a1bSJed Brown ierr = PCShellSetApply(pc,PCApply_MyShell);CHKERRQ(ierr); 125c4762a1bSJed Brown } 126c4762a1bSJed Brown 127c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 128c4762a1bSJed Brown Solve the nonlinear system 129c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 130c4762a1bSJed Brown ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); 131c4762a1bSJed Brown ierr = FormInitialGuess(&user,da,x);CHKERRQ(ierr); 132c4762a1bSJed Brown 133c4762a1bSJed Brown if (errorinpcsetup) { 134c4762a1bSJed Brown ierr = SNESSetUp(user.snes);CHKERRQ(ierr); 135c4762a1bSJed Brown ierr = SNESSetJacobian(user.snes,NULL,NULL,SNESComputeJacobian_MyShell,NULL);CHKERRQ(ierr); 136c4762a1bSJed Brown } 137c4762a1bSJed Brown ierr = SNESSolve(user.snes,NULL,x);CHKERRQ(ierr); 138c4762a1bSJed Brown 139c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 140c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they 141c4762a1bSJed Brown are no longer needed. 142c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 143c4762a1bSJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 144c4762a1bSJed Brown ierr = MatDestroy(&Jmf);CHKERRQ(ierr); 145c4762a1bSJed Brown ierr = VecDestroy(&x);CHKERRQ(ierr); 146c4762a1bSJed Brown ierr = DMDestroy(&da);CHKERRQ(ierr); 147c4762a1bSJed Brown ierr = SNESDestroy(&user.snes);CHKERRQ(ierr); 148c4762a1bSJed Brown ierr = PetscFinalize(); 149c4762a1bSJed Brown return ierr; 150c4762a1bSJed Brown } 151c4762a1bSJed Brown 152c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 153c4762a1bSJed Brown 154c4762a1bSJed Brown /* 155c4762a1bSJed Brown FormInitialGuess - Forms initial approximation. 156c4762a1bSJed Brown 157c4762a1bSJed Brown Input Parameters: 158c4762a1bSJed Brown user - user-defined application context 159c4762a1bSJed Brown X - vector 160c4762a1bSJed Brown 161c4762a1bSJed Brown Output Parameter: 162c4762a1bSJed Brown X - vector 163c4762a1bSJed Brown */ 164c4762a1bSJed Brown PetscErrorCode FormInitialGuess(AppCtx *user,DM da,Vec X) 165c4762a1bSJed Brown { 166c4762a1bSJed Brown PetscInt i,j,mx,xs,ys,xm,ym; 167c4762a1bSJed Brown PetscErrorCode ierr; 168c4762a1bSJed Brown PetscReal grashof,dx; 169c4762a1bSJed Brown Field **x; 170c4762a1bSJed Brown 171c4762a1bSJed Brown PetscFunctionBeginUser; 172c4762a1bSJed Brown grashof = user->grashof; 173c4762a1bSJed Brown 174c4762a1bSJed Brown ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); 175c4762a1bSJed Brown dx = 1.0/(mx-1); 176c4762a1bSJed Brown 177c4762a1bSJed Brown /* 178c4762a1bSJed Brown Get local grid boundaries (for 2-dimensional DMDA): 179c4762a1bSJed Brown xs, ys - starting grid indices (no ghost points) 180c4762a1bSJed Brown xm, ym - widths of local grid (no ghost points) 181c4762a1bSJed Brown */ 182c4762a1bSJed Brown ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); 183c4762a1bSJed Brown 184c4762a1bSJed Brown /* 185c4762a1bSJed Brown Get a pointer to vector data. 186c4762a1bSJed Brown - For default PETSc vectors, VecGetArray() returns a pointer to 187c4762a1bSJed Brown the data array. Otherwise, the routine is implementation dependent. 188c4762a1bSJed Brown - You MUST call VecRestoreArray() when you no longer need access to 189c4762a1bSJed Brown the array. 190c4762a1bSJed Brown */ 191c4762a1bSJed Brown ierr = DMDAVecGetArray(da,X,&x);CHKERRQ(ierr); 192c4762a1bSJed Brown 193c4762a1bSJed Brown /* 194c4762a1bSJed Brown Compute initial guess over the locally owned part of the grid 195c4762a1bSJed Brown Initial condition is motionless fluid and equilibrium temperature 196c4762a1bSJed Brown */ 197c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 198c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 199c4762a1bSJed Brown x[j][i].u = 0.0; 200c4762a1bSJed Brown x[j][i].v = 0.0; 201c4762a1bSJed Brown x[j][i].omega = 0.0; 202c4762a1bSJed Brown x[j][i].temp = (grashof>0)*i*dx; 203c4762a1bSJed Brown } 204c4762a1bSJed Brown } 205c4762a1bSJed Brown 206c4762a1bSJed Brown /* 207c4762a1bSJed Brown Restore vector 208c4762a1bSJed Brown */ 209c4762a1bSJed Brown ierr = DMDAVecRestoreArray(da,X,&x);CHKERRQ(ierr); 210c4762a1bSJed Brown PetscFunctionReturn(0); 211c4762a1bSJed Brown } 212c4762a1bSJed Brown 213c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,Field **x,Field **f,void *ptr) 214c4762a1bSJed Brown { 215c4762a1bSJed Brown AppCtx *user = (AppCtx*)ptr; 216c4762a1bSJed Brown PetscErrorCode ierr; 217c4762a1bSJed Brown PetscInt xints,xinte,yints,yinte,i,j; 218c4762a1bSJed Brown PetscReal hx,hy,dhx,dhy,hxdhy,hydhx; 219c4762a1bSJed Brown PetscReal grashof,prandtl,lid; 220c4762a1bSJed Brown PetscScalar u,uxx,uyy,vx,vy,avx,avy,vxp,vxm,vyp,vym; 221c4762a1bSJed Brown static PetscInt fail = 0; 222c4762a1bSJed Brown 223c4762a1bSJed Brown PetscFunctionBeginUser; 224c4762a1bSJed Brown if ((fail++ > 7 && user->errorindomainmf) || (fail++ > 36 && user->errorindomain)) { 225c4762a1bSJed Brown PetscMPIInt rank; 226ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)user->snes),&rank);CHKERRMPI(ierr); 227*dd400576SPatrick Sanan if (rank == 0) { 228c4762a1bSJed Brown ierr = SNESSetFunctionDomainError(user->snes);CHKERRQ(ierr); 229c4762a1bSJed Brown } 230c4762a1bSJed Brown } 231c4762a1bSJed Brown grashof = user->grashof; 232c4762a1bSJed Brown prandtl = user->prandtl; 233c4762a1bSJed Brown lid = user->lidvelocity; 234c4762a1bSJed Brown 235c4762a1bSJed Brown /* 236c4762a1bSJed Brown Define mesh intervals ratios for uniform grid. 237c4762a1bSJed Brown 238c4762a1bSJed Brown Note: FD formulae below are normalized by multiplying through by 239c4762a1bSJed Brown local volume element (i.e. hx*hy) to obtain coefficients O(1) in two dimensions. 240c4762a1bSJed Brown 241c4762a1bSJed Brown */ 242c4762a1bSJed Brown dhx = (PetscReal)(info->mx-1); dhy = (PetscReal)(info->my-1); 243c4762a1bSJed Brown hx = 1.0/dhx; hy = 1.0/dhy; 244c4762a1bSJed Brown hxdhy = hx*dhy; hydhx = hy*dhx; 245c4762a1bSJed Brown 246c4762a1bSJed Brown xints = info->xs; xinte = info->xs+info->xm; yints = info->ys; yinte = info->ys+info->ym; 247c4762a1bSJed Brown 248c4762a1bSJed Brown /* Test whether we are on the bottom edge of the global array */ 249c4762a1bSJed Brown if (yints == 0) { 250c4762a1bSJed Brown j = 0; 251c4762a1bSJed Brown yints = yints + 1; 252c4762a1bSJed Brown /* bottom edge */ 253c4762a1bSJed Brown for (i=info->xs; i<info->xs+info->xm; i++) { 254c4762a1bSJed Brown f[j][i].u = x[j][i].u; 255c4762a1bSJed Brown f[j][i].v = x[j][i].v; 256c4762a1bSJed Brown f[j][i].omega = x[j][i].omega + (x[j+1][i].u - x[j][i].u)*dhy; 257c4762a1bSJed Brown f[j][i].temp = x[j][i].temp-x[j+1][i].temp; 258c4762a1bSJed Brown } 259c4762a1bSJed Brown } 260c4762a1bSJed Brown 261c4762a1bSJed Brown /* Test whether we are on the top edge of the global array */ 262c4762a1bSJed Brown if (yinte == info->my) { 263c4762a1bSJed Brown j = info->my - 1; 264c4762a1bSJed Brown yinte = yinte - 1; 265c4762a1bSJed Brown /* top edge */ 266c4762a1bSJed Brown for (i=info->xs; i<info->xs+info->xm; i++) { 267c4762a1bSJed Brown f[j][i].u = x[j][i].u - lid; 268c4762a1bSJed Brown f[j][i].v = x[j][i].v; 269c4762a1bSJed Brown f[j][i].omega = x[j][i].omega + (x[j][i].u - x[j-1][i].u)*dhy; 270c4762a1bSJed Brown f[j][i].temp = x[j][i].temp-x[j-1][i].temp; 271c4762a1bSJed Brown } 272c4762a1bSJed Brown } 273c4762a1bSJed Brown 274c4762a1bSJed Brown /* Test whether we are on the left edge of the global array */ 275c4762a1bSJed Brown if (xints == 0) { 276c4762a1bSJed Brown i = 0; 277c4762a1bSJed Brown xints = xints + 1; 278c4762a1bSJed Brown /* left edge */ 279c4762a1bSJed Brown for (j=info->ys; j<info->ys+info->ym; j++) { 280c4762a1bSJed Brown f[j][i].u = x[j][i].u; 281c4762a1bSJed Brown f[j][i].v = x[j][i].v; 282c4762a1bSJed Brown f[j][i].omega = x[j][i].omega - (x[j][i+1].v - x[j][i].v)*dhx; 283c4762a1bSJed Brown f[j][i].temp = x[j][i].temp; 284c4762a1bSJed Brown } 285c4762a1bSJed Brown } 286c4762a1bSJed Brown 287c4762a1bSJed Brown /* Test whether we are on the right edge of the global array */ 288c4762a1bSJed Brown if (xinte == info->mx) { 289c4762a1bSJed Brown i = info->mx - 1; 290c4762a1bSJed Brown xinte = xinte - 1; 291c4762a1bSJed Brown /* right edge */ 292c4762a1bSJed Brown for (j=info->ys; j<info->ys+info->ym; j++) { 293c4762a1bSJed Brown f[j][i].u = x[j][i].u; 294c4762a1bSJed Brown f[j][i].v = x[j][i].v; 295c4762a1bSJed Brown f[j][i].omega = x[j][i].omega - (x[j][i].v - x[j][i-1].v)*dhx; 296c4762a1bSJed Brown f[j][i].temp = x[j][i].temp - (PetscReal)(grashof>0); 297c4762a1bSJed Brown } 298c4762a1bSJed Brown } 299c4762a1bSJed Brown 300c4762a1bSJed Brown /* Compute over the interior points */ 301c4762a1bSJed Brown for (j=yints; j<yinte; j++) { 302c4762a1bSJed Brown for (i=xints; i<xinte; i++) { 303c4762a1bSJed Brown 304c4762a1bSJed Brown /* 305c4762a1bSJed Brown convective coefficients for upwinding 306c4762a1bSJed Brown */ 307c4762a1bSJed Brown vx = x[j][i].u; avx = PetscAbsScalar(vx); 308c4762a1bSJed Brown vxp = .5*(vx+avx); vxm = .5*(vx-avx); 309c4762a1bSJed Brown vy = x[j][i].v; avy = PetscAbsScalar(vy); 310c4762a1bSJed Brown vyp = .5*(vy+avy); vym = .5*(vy-avy); 311c4762a1bSJed Brown 312c4762a1bSJed Brown /* U velocity */ 313c4762a1bSJed Brown u = x[j][i].u; 314c4762a1bSJed Brown uxx = (2.0*u - x[j][i-1].u - x[j][i+1].u)*hydhx; 315c4762a1bSJed Brown uyy = (2.0*u - x[j-1][i].u - x[j+1][i].u)*hxdhy; 316c4762a1bSJed Brown f[j][i].u = uxx + uyy - .5*(x[j+1][i].omega-x[j-1][i].omega)*hx; 317c4762a1bSJed Brown 318c4762a1bSJed Brown /* V velocity */ 319c4762a1bSJed Brown u = x[j][i].v; 320c4762a1bSJed Brown uxx = (2.0*u - x[j][i-1].v - x[j][i+1].v)*hydhx; 321c4762a1bSJed Brown uyy = (2.0*u - x[j-1][i].v - x[j+1][i].v)*hxdhy; 322c4762a1bSJed Brown f[j][i].v = uxx + uyy + .5*(x[j][i+1].omega-x[j][i-1].omega)*hy; 323c4762a1bSJed Brown 324c4762a1bSJed Brown /* Omega */ 325c4762a1bSJed Brown u = x[j][i].omega; 326c4762a1bSJed Brown uxx = (2.0*u - x[j][i-1].omega - x[j][i+1].omega)*hydhx; 327c4762a1bSJed Brown uyy = (2.0*u - x[j-1][i].omega - x[j+1][i].omega)*hxdhy; 328c4762a1bSJed Brown f[j][i].omega = uxx + uyy + (vxp*(u - x[j][i-1].omega) + vxm*(x[j][i+1].omega - u))*hy + 329c4762a1bSJed Brown (vyp*(u - x[j-1][i].omega) + vym*(x[j+1][i].omega - u))*hx - 330c4762a1bSJed Brown .5*grashof*(x[j][i+1].temp - x[j][i-1].temp)*hy; 331c4762a1bSJed Brown 332c4762a1bSJed Brown /* Temperature */ 333c4762a1bSJed Brown u = x[j][i].temp; 334c4762a1bSJed Brown uxx = (2.0*u - x[j][i-1].temp - x[j][i+1].temp)*hydhx; 335c4762a1bSJed Brown uyy = (2.0*u - x[j-1][i].temp - x[j+1][i].temp)*hxdhy; 336c4762a1bSJed Brown f[j][i].temp = uxx + uyy + prandtl*((vxp*(u - x[j][i-1].temp) + vxm*(x[j][i+1].temp - u))*hy + 337c4762a1bSJed Brown (vyp*(u - x[j-1][i].temp) + vym*(x[j+1][i].temp - u))*hx); 338c4762a1bSJed Brown } 339c4762a1bSJed Brown } 340c4762a1bSJed Brown 341c4762a1bSJed Brown /* 342c4762a1bSJed Brown Flop count (multiply-adds are counted as 2 operations) 343c4762a1bSJed Brown */ 344c4762a1bSJed Brown ierr = PetscLogFlops(84.0*info->ym*info->xm);CHKERRQ(ierr); 345c4762a1bSJed Brown PetscFunctionReturn(0); 346c4762a1bSJed Brown } 347c4762a1bSJed Brown 348c4762a1bSJed Brown PetscErrorCode MatMult_MyShell(Mat A,Vec x,Vec y) 349c4762a1bSJed Brown { 350c4762a1bSJed Brown PetscErrorCode ierr; 351c4762a1bSJed Brown MatShellCtx *matshellctx; 352c4762a1bSJed Brown static PetscInt fail = 0; 353c4762a1bSJed Brown 354c4762a1bSJed Brown PetscFunctionBegin; 355c4762a1bSJed Brown ierr = MatShellGetContext(A,&matshellctx);CHKERRQ(ierr); 356c4762a1bSJed Brown ierr = MatMult(matshellctx->Jmf,x,y);CHKERRQ(ierr); 357c4762a1bSJed Brown if (fail++ > 5) { 358c4762a1bSJed Brown PetscMPIInt rank; 359ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRMPI(ierr); 360*dd400576SPatrick Sanan if (rank == 0) {ierr = VecSetInf(y);CHKERRQ(ierr);} 361c4762a1bSJed Brown } 362c4762a1bSJed Brown PetscFunctionReturn(0); 363c4762a1bSJed Brown } 364c4762a1bSJed Brown 365c4762a1bSJed Brown PetscErrorCode MatAssemblyEnd_MyShell(Mat A,MatAssemblyType tp) 366c4762a1bSJed Brown { 367c4762a1bSJed Brown PetscErrorCode ierr; 368c4762a1bSJed Brown MatShellCtx *matshellctx; 369c4762a1bSJed Brown 370c4762a1bSJed Brown PetscFunctionBegin; 371c4762a1bSJed Brown ierr = MatShellGetContext(A,&matshellctx);CHKERRQ(ierr); 372c4762a1bSJed Brown ierr = MatAssemblyEnd(matshellctx->Jmf,tp);CHKERRQ(ierr); 373c4762a1bSJed Brown PetscFunctionReturn(0); 374c4762a1bSJed Brown } 375c4762a1bSJed Brown 376c4762a1bSJed Brown PetscErrorCode PCApply_MyShell(PC pc,Vec x,Vec y) 377c4762a1bSJed Brown { 378c4762a1bSJed Brown PetscErrorCode ierr; 379c4762a1bSJed Brown static PetscInt fail = 0; 380c4762a1bSJed Brown 381c4762a1bSJed Brown PetscFunctionBegin; 382c4762a1bSJed Brown ierr = VecCopy(x,y);CHKERRQ(ierr); 383c4762a1bSJed Brown if (fail++ > 3) { 384c4762a1bSJed Brown PetscMPIInt rank; 385ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr); 386*dd400576SPatrick Sanan if (rank == 0) {ierr = VecSetInf(y);CHKERRQ(ierr);} 387c4762a1bSJed Brown } 388c4762a1bSJed Brown PetscFunctionReturn(0); 389c4762a1bSJed Brown } 390c4762a1bSJed Brown 391c4762a1bSJed Brown PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES,Vec,Mat,Mat,void*); 392c4762a1bSJed Brown 393c4762a1bSJed Brown PetscErrorCode SNESComputeJacobian_MyShell(SNES snes,Vec X,Mat A,Mat B,void *ctx) 394c4762a1bSJed Brown { 395c4762a1bSJed Brown static PetscInt fail = 0; 396c4762a1bSJed Brown PetscErrorCode ierr; 397c4762a1bSJed Brown 398c4762a1bSJed Brown PetscFunctionBegin; 399c4762a1bSJed Brown ierr = SNESComputeJacobian_DMDA(snes,X,A,B,ctx);CHKERRQ(ierr); 400c4762a1bSJed Brown if (fail++ > 0) { 401c4762a1bSJed Brown ierr = MatZeroEntries(A);CHKERRQ(ierr); 402c4762a1bSJed Brown } 403c4762a1bSJed Brown PetscFunctionReturn(0); 404c4762a1bSJed Brown } 405c4762a1bSJed Brown 406c4762a1bSJed Brown /*TEST 407c4762a1bSJed Brown 408c4762a1bSJed Brown test: 409c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason 410c4762a1bSJed Brown 411c4762a1bSJed Brown test: 412c4762a1bSJed Brown suffix: 2 413c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_matmult 414c4762a1bSJed Brown 415c4762a1bSJed Brown test: 416c4762a1bSJed Brown suffix: 3 417c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_pcapply 418c4762a1bSJed Brown 419c4762a1bSJed Brown test: 420c4762a1bSJed Brown suffix: 4 421c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_pcsetup 422c4762a1bSJed Brown 423c4762a1bSJed Brown test: 424c4762a1bSJed Brown suffix: 5 425c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_pcsetup -pc_type bjacobi 426c4762a1bSJed Brown 427c4762a1bSJed Brown test: 428c4762a1bSJed Brown suffix: 5_fieldsplit 429c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_pcsetup -pc_type fieldsplit 430c4762a1bSJed Brown output_file: output/ex69_5.out 431c4762a1bSJed Brown 432c4762a1bSJed Brown test: 433c4762a1bSJed Brown suffix: 6 434c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_domainmf -snes_mf -pc_type none 435c4762a1bSJed Brown 436c4762a1bSJed Brown test: 437c4762a1bSJed Brown suffix: 7 438c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_domain 439c4762a1bSJed Brown 440c4762a1bSJed Brown test: 441c4762a1bSJed Brown suffix: 8 442c4762a1bSJed Brown args: -snes_converged_reason -ksp_converged_reason -error_in_domain -snes_mf -pc_type none 443c4762a1bSJed Brown 444c4762a1bSJed Brown TEST*/ 445