1c4762a1bSJed Brown static char help[] = "Demonstrates automatic, matrix-free Jacobian generation using ADOL-C for a time-dependent PDE in 2d, solved using implicit timestepping.\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown /* 4c4762a1bSJed Brown Concepts: TS^time-dependent nonlinear problems 5c4762a1bSJed Brown Concepts: Automatic differentiation using ADOL-C 6c4762a1bSJed Brown Concepts: Matrix-free methods 7c4762a1bSJed Brown */ 8c4762a1bSJed Brown /* 9c4762a1bSJed Brown REQUIRES configuration of PETSc with option --download-adolc. 10c4762a1bSJed Brown 11c4762a1bSJed Brown For documentation on ADOL-C, see 12c4762a1bSJed Brown $PETSC_ARCH/externalpackages/ADOL-C-2.6.0/ADOL-C/doc/adolc-manual.pdf 13c4762a1bSJed Brown */ 14c4762a1bSJed Brown /* ------------------------------------------------------------------------ 15c4762a1bSJed Brown See ../advection-diffusion-reaction/ex5 for a description of the problem 16c4762a1bSJed Brown ------------------------------------------------------------------------- */ 17c4762a1bSJed Brown 18c4762a1bSJed Brown #include <petscdmda.h> 19c4762a1bSJed Brown #include <petscts.h> 20c4762a1bSJed Brown #include "adolc-utils/init.cxx" 21c4762a1bSJed Brown #include "adolc-utils/matfree.cxx" 22c4762a1bSJed Brown #include <adolc/adolc.h> 23c4762a1bSJed Brown 24c4762a1bSJed Brown /* (Passive) field for the two variables */ 25c4762a1bSJed Brown typedef struct { 26c4762a1bSJed Brown PetscScalar u,v; 27c4762a1bSJed Brown } Field; 28c4762a1bSJed Brown 29c4762a1bSJed Brown /* Active field for the two variables */ 30c4762a1bSJed Brown typedef struct { 31c4762a1bSJed Brown adouble u,v; 32c4762a1bSJed Brown } AField; 33c4762a1bSJed Brown 34c4762a1bSJed Brown /* Application context */ 35c4762a1bSJed Brown typedef struct { 36c4762a1bSJed Brown PetscReal D1,D2,gamma,kappa; 37c4762a1bSJed Brown AField **u_a,**f_a; 38c4762a1bSJed Brown AdolcCtx *adctx; /* Automatic differentation support */ 39c4762a1bSJed Brown } AppCtx; 40c4762a1bSJed Brown 41c4762a1bSJed Brown extern PetscErrorCode InitialConditions(DM da,Vec U); 42c4762a1bSJed Brown extern PetscErrorCode InitializeLambda(DM da,Vec lambda,PetscReal x,PetscReal y); 43c4762a1bSJed Brown extern PetscErrorCode IFunctionLocalPassive(DMDALocalInfo *info,PetscReal t,Field**u,Field**udot,Field**f,void *ptr); 44c4762a1bSJed Brown extern PetscErrorCode IFunctionActive(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr); 45c4762a1bSJed Brown extern PetscErrorCode IJacobianMatFree(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat A_shell,Mat B,void *ctx); 46c4762a1bSJed Brown 47c4762a1bSJed Brown int main(int argc,char **argv) 48c4762a1bSJed Brown { 49c4762a1bSJed Brown TS ts; /* ODE integrator */ 50c4762a1bSJed Brown Vec x,r; /* solution, residual */ 51c4762a1bSJed Brown PetscErrorCode ierr; 52c4762a1bSJed Brown DM da; 53c4762a1bSJed Brown AppCtx appctx; /* Application context */ 54c4762a1bSJed Brown AdolcMatCtx matctx; /* Matrix (free) context */ 55c4762a1bSJed Brown Vec lambda[1]; 56c4762a1bSJed Brown PetscBool forwardonly=PETSC_FALSE; 57c4762a1bSJed Brown Mat A; /* (Matrix free) Jacobian matrix */ 58c4762a1bSJed Brown PetscInt gxm,gym; 59c4762a1bSJed Brown 60c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 61c4762a1bSJed Brown Initialize program 62c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 63c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr; 64*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-forwardonly",&forwardonly,NULL)); 65c4762a1bSJed Brown PetscFunctionBeginUser; 66c4762a1bSJed Brown appctx.D1 = 8.0e-5; 67c4762a1bSJed Brown appctx.D2 = 4.0e-5; 68c4762a1bSJed Brown appctx.gamma = .024; 69c4762a1bSJed Brown appctx.kappa = .06; 70*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventRegister("df/dx forward",MAT_CLASSID,&matctx.event1)); 71*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventRegister("df/d(xdot) forward",MAT_CLASSID,&matctx.event2)); 72*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventRegister("df/dx reverse",MAT_CLASSID,&matctx.event3)); 73*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventRegister("df/d(xdot) reverse",MAT_CLASSID,&matctx.event4)); 74c4762a1bSJed Brown 75c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 76c4762a1bSJed Brown Create distributed array (DMDA) to manage parallel grid and vectors 77c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 78*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC,DM_BOUNDARY_PERIODIC,DMDA_STENCIL_STAR,65,65,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,NULL,&da)); 79*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(da)); 80*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(da)); 81*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,0,"u")); 82*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,1,"v")); 83c4762a1bSJed Brown 84c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 85c4762a1bSJed Brown Extract global vectors from DMDA; then duplicate for remaining 86c4762a1bSJed Brown vectors that are the same types 87c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 88*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(da,&x)); 89*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(x,&r)); 90c4762a1bSJed Brown 91c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 92c4762a1bSJed Brown Create matrix free context and specify usage of PETSc-ADOL-C drivers 93c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 94*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetMatType(da,MATSHELL)); 95*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(da,&A)); 96*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetContext(A,&matctx)); 97*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscAdolcIJacobianVectorProductIDMass)); 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(A,MATOP_MULT_TRANSPOSE,(void (*)(void))PetscAdolcIJacobianTransposeVectorProductIDMass)); 99*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(x,&matctx.X)); 100*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(x,&matctx.Xdot)); 101*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(da,&matctx.localX0)); 102c4762a1bSJed Brown 103c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 104c4762a1bSJed Brown Create timestepping solver context 105c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 106*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSCreate(PETSC_COMM_WORLD,&ts)); 107*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetType(ts,TSCN)); 108*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetDM(ts,da)); 109*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetProblemType(ts,TS_NONLINEAR)); 110*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDATSSetIFunctionLocal(da,INSERT_VALUES,(DMDATSIFunctionLocal)IFunctionLocalPassive,&appctx)); 111c4762a1bSJed Brown 112c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 113c4762a1bSJed Brown Some data required for matrix-free context 114c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 115*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetGhostCorners(da,NULL,NULL,NULL,&gxm,&gym,NULL)); 116c4762a1bSJed Brown matctx.m = 2*gxm*gym;matctx.n = 2*gxm*gym; /* Number of dependent and independent variables */ 117c4762a1bSJed Brown matctx.flg = PETSC_FALSE; /* Flag for reverse mode */ 118c4762a1bSJed Brown matctx.tag1 = 1; /* Tape identifier */ 119c4762a1bSJed Brown 120c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 121c4762a1bSJed Brown Trace function just once 122c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 123*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&appctx.adctx)); 124*5f80ce2aSJacob Faibussowitsch CHKERRQ(IFunctionActive(ts,1.,x,matctx.Xdot,r,&appctx)); 125*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(appctx.adctx)); 126c4762a1bSJed Brown 127c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 128c4762a1bSJed Brown Set Jacobian. In this case, IJacobian simply acts to pass context 129c4762a1bSJed Brown information to the matrix-free Jacobian vector product. 130c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 131*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetIJacobian(ts,A,A,IJacobianMatFree,&appctx)); 132c4762a1bSJed Brown 133c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 134c4762a1bSJed Brown Set initial conditions 135c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 136*5f80ce2aSJacob Faibussowitsch CHKERRQ(InitialConditions(da,x)); 137*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetSolution(ts,x)); 138c4762a1bSJed Brown 139c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 140c4762a1bSJed Brown Have the TS save its trajectory so that TSAdjointSolve() may be used 141c4762a1bSJed Brown and set solver options 142c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 143c4762a1bSJed Brown if (!forwardonly) { 144*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetSaveTrajectory(ts)); 145*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxTime(ts,200.0)); 146*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTimeStep(ts,0.5)); 147c4762a1bSJed Brown } else { 148*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxTime(ts,2000.0)); 149*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTimeStep(ts,10)); 150c4762a1bSJed Brown } 151*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER)); 152*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetFromOptions(ts)); 153c4762a1bSJed Brown 154c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 155c4762a1bSJed Brown Solve ODE system 156c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 157*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSolve(ts,x)); 158c4762a1bSJed Brown if (!forwardonly) { 159c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 160c4762a1bSJed Brown Start the Adjoint model 161c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 162*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(x,&lambda[0])); 163c4762a1bSJed Brown /* Reset initial conditions for the adjoint integration */ 164*5f80ce2aSJacob Faibussowitsch CHKERRQ(InitializeLambda(da,lambda[0],0.5,0.5)); 165*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetCostGradients(ts,1,lambda,NULL)); 166*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdjointSolve(ts)); 167*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&lambda[0])); 168c4762a1bSJed Brown } 169c4762a1bSJed Brown 170c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 171c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they 172c4762a1bSJed Brown are no longer needed. 173c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 174*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(da,&matctx.localX0)); 175*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&r)); 176*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&matctx.X)); 177*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&matctx.Xdot)); 178*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 179*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x)); 180*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSDestroy(&ts)); 181*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&da)); 182c4762a1bSJed Brown 183c4762a1bSJed Brown ierr = PetscFinalize(); 184c4762a1bSJed Brown return ierr; 185c4762a1bSJed Brown } 186c4762a1bSJed Brown 187c4762a1bSJed Brown PetscErrorCode InitialConditions(DM da,Vec U) 188c4762a1bSJed Brown { 189c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym,Mx,My; 190c4762a1bSJed Brown Field **u; 191c4762a1bSJed Brown PetscReal hx,hy,x,y; 192c4762a1bSJed Brown 193c4762a1bSJed Brown PetscFunctionBegin; 194*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 195c4762a1bSJed Brown 196c4762a1bSJed Brown hx = 2.5/(PetscReal)Mx; 197c4762a1bSJed Brown hy = 2.5/(PetscReal)My; 198c4762a1bSJed Brown 199c4762a1bSJed Brown /* 200c4762a1bSJed Brown Get pointers to vector data 201c4762a1bSJed Brown */ 202*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,U,&u)); 203c4762a1bSJed Brown 204c4762a1bSJed Brown /* 205c4762a1bSJed Brown Get local grid boundaries 206c4762a1bSJed Brown */ 207*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL)); 208c4762a1bSJed Brown 209c4762a1bSJed Brown /* 210c4762a1bSJed Brown Compute function over the locally owned part of the grid 211c4762a1bSJed Brown */ 212c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 213c4762a1bSJed Brown y = j*hy; 214c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 215c4762a1bSJed Brown x = i*hx; 21666baab88SBarry Smith if (PetscApproximateGTE(x,1.0) && PetscApproximateLTE(x,1.5) && PetscApproximateGTE(y,1.0) && PetscApproximateLTE(y,1.5)) u[j][i].v = PetscPowReal(PetscSinReal(4.0*PETSC_PI*x),2.0)*PetscPowReal(PetscSinReal(4.0*PETSC_PI*y),2.0)/4.0; 217c4762a1bSJed Brown else u[j][i].v = 0.0; 218c4762a1bSJed Brown 219c4762a1bSJed Brown u[j][i].u = 1.0 - 2.0*u[j][i].v; 220c4762a1bSJed Brown } 221c4762a1bSJed Brown } 222c4762a1bSJed Brown 223c4762a1bSJed Brown /* 224c4762a1bSJed Brown Restore vectors 225c4762a1bSJed Brown */ 226*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,U,&u)); 227c4762a1bSJed Brown PetscFunctionReturn(0); 228c4762a1bSJed Brown } 229c4762a1bSJed Brown 230c4762a1bSJed Brown PetscErrorCode InitializeLambda(DM da,Vec lambda,PetscReal x,PetscReal y) 231c4762a1bSJed Brown { 232c4762a1bSJed Brown PetscInt i,j,Mx,My,xs,ys,xm,ym; 233c4762a1bSJed Brown Field **l; 234c4762a1bSJed Brown 235410585f6SHong Zhang PetscFunctionBegin; 236*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 237c4762a1bSJed Brown /* locate the global i index for x and j index for y */ 238c4762a1bSJed Brown i = (PetscInt)(x*(Mx-1)); 239c4762a1bSJed Brown j = (PetscInt)(y*(My-1)); 240*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL)); 241c4762a1bSJed Brown 242c4762a1bSJed Brown if (xs <= i && i < xs+xm && ys <= j && j < ys+ym) { 243c4762a1bSJed Brown /* the i,j vertex is on this process */ 244*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,lambda,&l)); 245c4762a1bSJed Brown l[j][i].u = 1.0; 246c4762a1bSJed Brown l[j][i].v = 1.0; 247*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,lambda,&l)); 248c4762a1bSJed Brown } 249c4762a1bSJed Brown PetscFunctionReturn(0); 250c4762a1bSJed Brown } 251c4762a1bSJed Brown 252c4762a1bSJed Brown PetscErrorCode IFunctionLocalPassive(DMDALocalInfo *info,PetscReal t,Field**u,Field**udot,Field**f,void *ptr) 253c4762a1bSJed Brown { 254c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ptr; 255c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym; 256c4762a1bSJed Brown PetscReal hx,hy,sx,sy; 257c4762a1bSJed Brown PetscScalar uc,uxx,uyy,vc,vxx,vyy; 258c4762a1bSJed Brown 259c4762a1bSJed Brown PetscFunctionBegin; 260c4762a1bSJed Brown hx = 2.50/(PetscReal)(info->mx); sx = 1.0/(hx*hx); 261c4762a1bSJed Brown hy = 2.50/(PetscReal)(info->my); sy = 1.0/(hy*hy); 262c4762a1bSJed Brown 263c4762a1bSJed Brown /* Get local grid boundaries */ 264c4762a1bSJed Brown xs = info->xs; xm = info->xm; ys = info->ys; ym = info->ym; 265c4762a1bSJed Brown 266c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 267c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 268c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 269c4762a1bSJed Brown uc = u[j][i].u; 270c4762a1bSJed Brown uxx = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx; 271c4762a1bSJed Brown uyy = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy; 272c4762a1bSJed Brown vc = u[j][i].v; 273c4762a1bSJed Brown vxx = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx; 274c4762a1bSJed Brown vyy = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy; 275c4762a1bSJed Brown f[j][i].u = udot[j][i].u - appctx->D1*(uxx + uyy) + uc*vc*vc - appctx->gamma*(1.0 - uc); 276c4762a1bSJed Brown f[j][i].v = udot[j][i].v - appctx->D2*(vxx + vyy) - uc*vc*vc + (appctx->gamma + appctx->kappa)*vc; 277c4762a1bSJed Brown } 278c4762a1bSJed Brown } 279*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops(16.0*xm*ym)); 280c4762a1bSJed Brown PetscFunctionReturn(0); 281c4762a1bSJed Brown } 282c4762a1bSJed Brown 283c4762a1bSJed Brown PetscErrorCode IFunctionActive(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr) 284c4762a1bSJed Brown { 285c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ptr; 286c4762a1bSJed Brown DM da; 287c4762a1bSJed Brown DMDALocalInfo info; 288c4762a1bSJed Brown Field **u,**f,**udot; 289c4762a1bSJed Brown Vec localU; 290c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym,gxs,gys,gxm,gym; 291c4762a1bSJed Brown PetscReal hx,hy,sx,sy; 292c4762a1bSJed Brown adouble uc,uxx,uyy,vc,vxx,vyy; 293c4762a1bSJed Brown AField **f_a,*f_c,**u_a,*u_c; 294c4762a1bSJed Brown PetscScalar dummy; 295c4762a1bSJed Brown 296c4762a1bSJed Brown PetscFunctionBegin; 297*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&da)); 298*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetLocalInfo(da,&info)); 299*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(da,&localU)); 300c4762a1bSJed Brown hx = 2.50/(PetscReal)(info.mx); sx = 1.0/(hx*hx); 301c4762a1bSJed Brown hy = 2.50/(PetscReal)(info.my); sy = 1.0/(hy*hy); 302c4762a1bSJed Brown xs = info.xs; xm = info.xm; gxs = info.gxs; gxm = info.gxm; 303c4762a1bSJed Brown ys = info.ys; ym = info.ym; gys = info.gys; gym = info.gym; 304c4762a1bSJed Brown 305c4762a1bSJed Brown /* 306c4762a1bSJed Brown Scatter ghost points to local vector,using the 2-step process 307c4762a1bSJed Brown DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). 308c4762a1bSJed Brown By placing code between these two statements, computations can be 309c4762a1bSJed Brown done while messages are in transition. 310c4762a1bSJed Brown */ 311*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU)); 312*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU)); 313c4762a1bSJed Brown 314c4762a1bSJed Brown /* 315c4762a1bSJed Brown Get pointers to vector data 316c4762a1bSJed Brown */ 317*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayRead(da,localU,&u)); 318*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,F,&f)); 319*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayRead(da,Udot,&udot)); 320c4762a1bSJed Brown 321c4762a1bSJed Brown /* 322c4762a1bSJed Brown Create contiguous 1-arrays of AFields 323c4762a1bSJed Brown 324c4762a1bSJed Brown NOTE: Memory for ADOL-C active variables (such as adouble and AField) 325c4762a1bSJed Brown cannot be allocated using PetscMalloc, as this does not call the 326c4762a1bSJed Brown relevant class constructor. Instead, we use the C++ keyword `new`. 327c4762a1bSJed Brown */ 328c4762a1bSJed Brown u_c = new AField[info.gxm*info.gym]; 329c4762a1bSJed Brown f_c = new AField[info.gxm*info.gym]; 330c4762a1bSJed Brown 331c4762a1bSJed Brown /* Create corresponding 2-arrays of AFields */ 332c4762a1bSJed Brown u_a = new AField*[info.gym]; 333c4762a1bSJed Brown f_a = new AField*[info.gym]; 334c4762a1bSJed Brown 335c4762a1bSJed Brown /* Align indices between array types to endow 2d array with ghost points */ 336*5f80ce2aSJacob Faibussowitsch CHKERRQ(GiveGhostPoints(da,u_c,&u_a)); 337*5f80ce2aSJacob Faibussowitsch CHKERRQ(GiveGhostPoints(da,f_c,&f_a)); 338c4762a1bSJed Brown 339c4762a1bSJed Brown trace_on(1); /* Start of active section on tape 1 */ 340c4762a1bSJed Brown 341c4762a1bSJed Brown /* 342c4762a1bSJed Brown Mark independence 343c4762a1bSJed Brown 344c4762a1bSJed Brown NOTE: Ghost points are marked as independent, in place of the points they represent on 345c4762a1bSJed Brown other processors / on other boundaries. 346c4762a1bSJed Brown */ 347c4762a1bSJed Brown for (j=gys; j<gys+gym; j++) { 348c4762a1bSJed Brown for (i=gxs; i<gxs+gxm; i++) { 349c4762a1bSJed Brown u_a[j][i].u <<= u[j][i].u; 350c4762a1bSJed Brown u_a[j][i].v <<= u[j][i].v; 351c4762a1bSJed Brown } 352c4762a1bSJed Brown } 353c4762a1bSJed Brown 354c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 355c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 356c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 357c4762a1bSJed Brown uc = u_a[j][i].u; 358c4762a1bSJed Brown uxx = (-2.0*uc + u_a[j][i-1].u + u_a[j][i+1].u)*sx; 359c4762a1bSJed Brown uyy = (-2.0*uc + u_a[j-1][i].u + u_a[j+1][i].u)*sy; 360c4762a1bSJed Brown vc = u_a[j][i].v; 361c4762a1bSJed Brown vxx = (-2.0*vc + u_a[j][i-1].v + u_a[j][i+1].v)*sx; 362c4762a1bSJed Brown vyy = (-2.0*vc + u_a[j-1][i].v + u_a[j+1][i].v)*sy; 363c4762a1bSJed Brown f_a[j][i].u = udot[j][i].u - appctx->D1*(uxx + uyy) + uc*vc*vc - appctx->gamma*(1.0 - uc); 364c4762a1bSJed Brown f_a[j][i].v = udot[j][i].v - appctx->D2*(vxx + vyy) - uc*vc*vc + (appctx->gamma + appctx->kappa)*vc; 365c4762a1bSJed Brown } 366c4762a1bSJed Brown } 367c4762a1bSJed Brown 368c4762a1bSJed Brown /* 369c4762a1bSJed Brown Mark dependence 370c4762a1bSJed Brown 371c4762a1bSJed Brown NOTE: Marking dependence of dummy variables makes the index notation much simpler when forming 372c4762a1bSJed Brown the Jacobian later. 373c4762a1bSJed Brown */ 374c4762a1bSJed Brown for (j=gys; j<gys+gym; j++) { 375c4762a1bSJed Brown for (i=gxs; i<gxs+gxm; i++) { 376c4762a1bSJed Brown if ((i < xs) || (i >= xs+xm) || (j < ys) || (j >= ys+ym)) { 377c4762a1bSJed Brown f_a[j][i].u >>= dummy; 378c4762a1bSJed Brown f_a[j][i].v >>= dummy; 379c4762a1bSJed Brown } else { 380c4762a1bSJed Brown f_a[j][i].u >>= f[j][i].u; 381c4762a1bSJed Brown f_a[j][i].v >>= f[j][i].v; 382c4762a1bSJed Brown } 383c4762a1bSJed Brown } 384c4762a1bSJed Brown } 385c4762a1bSJed Brown trace_off(); /* End of active section */ 386*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops(16.0*xm*ym)); 387c4762a1bSJed Brown 388c4762a1bSJed Brown /* Restore vectors */ 389*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,F,&f)); 390*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayRead(da,localU,&u)); 391*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayRead(da,Udot,&udot)); 392c4762a1bSJed Brown 393*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(da,&localU)); 394410585f6SHong Zhang 395c4762a1bSJed Brown /* Destroy AFields appropriately */ 396c4762a1bSJed Brown f_a += info.gys; 397c4762a1bSJed Brown u_a += info.gys; 398c4762a1bSJed Brown delete[] f_a; 399c4762a1bSJed Brown delete[] u_a; 400c4762a1bSJed Brown delete[] f_c; 401c4762a1bSJed Brown delete[] u_c; 402c4762a1bSJed Brown PetscFunctionReturn(0); 403c4762a1bSJed Brown } 404c4762a1bSJed Brown 405c4762a1bSJed Brown /* 406c4762a1bSJed Brown Simply acts to pass TS information to the AdolcMatCtx 407c4762a1bSJed Brown */ 408c4762a1bSJed Brown PetscErrorCode IJacobianMatFree(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat A_shell,Mat B,void *ctx) 409c4762a1bSJed Brown { 410c4762a1bSJed Brown AdolcMatCtx *mctx; 411c4762a1bSJed Brown DM da; 412c4762a1bSJed Brown 413c4762a1bSJed Brown PetscFunctionBeginUser; 414*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A_shell,&mctx)); 415c4762a1bSJed Brown 416c4762a1bSJed Brown mctx->time = t; 417c4762a1bSJed Brown mctx->shift = a; 418c4762a1bSJed Brown if (mctx->ts != ts) mctx->ts = ts; 419*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(X,mctx->X)); 420*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(Xdot,mctx->Xdot)); 421*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&da)); 422*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(da,mctx->X,INSERT_VALUES,mctx->localX0)); 423*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(da,mctx->X,INSERT_VALUES,mctx->localX0)); 424c4762a1bSJed Brown PetscFunctionReturn(0); 425c4762a1bSJed Brown } 426c4762a1bSJed Brown 427c4762a1bSJed Brown /*TEST 428c4762a1bSJed Brown 429c4762a1bSJed Brown build: 430c4762a1bSJed Brown requires: double !complex adolc 431c4762a1bSJed Brown 432c4762a1bSJed Brown test: 433c4762a1bSJed Brown suffix: 1 434c4762a1bSJed Brown args: -ts_max_steps 1 -da_grid_x 12 -da_grid_y 12 -snes_test_jacobian 435c4762a1bSJed Brown output_file: output/adr_ex5adj_mf_1.out 436c4762a1bSJed Brown 437c4762a1bSJed Brown test: 438c4762a1bSJed Brown suffix: 2 439c4762a1bSJed Brown nsize: 4 440c4762a1bSJed Brown args: -ts_max_steps 10 -da_grid_x 12 -da_grid_y 12 -ts_monitor -ts_adjoint_monitor 441c4762a1bSJed Brown output_file: output/adr_ex5adj_mf_2.out 442c4762a1bSJed Brown 443c4762a1bSJed Brown TEST*/ 444