1*c4762a1bSJed Brown 2*c4762a1bSJed Brown static char help[] ="Solves a simple data assimilation problem with one dimensional Burger's equation using TSAdjoint\n\n"; 3*c4762a1bSJed Brown 4*c4762a1bSJed Brown /* 5*c4762a1bSJed Brown 6*c4762a1bSJed Brown Not yet tested in parallel 7*c4762a1bSJed Brown 8*c4762a1bSJed Brown */ 9*c4762a1bSJed Brown /* 10*c4762a1bSJed Brown Concepts: TS^time-dependent nonlinear problems 11*c4762a1bSJed Brown Concepts: TS^Burger's equation 12*c4762a1bSJed Brown Concepts: adjoints 13*c4762a1bSJed Brown Processors: n 14*c4762a1bSJed Brown */ 15*c4762a1bSJed Brown 16*c4762a1bSJed Brown /* ------------------------------------------------------------------------ 17*c4762a1bSJed Brown 18*c4762a1bSJed Brown This program uses the one-dimensional Burger's equation 19*c4762a1bSJed Brown u_t = mu*u_xx - u u_x, 20*c4762a1bSJed Brown on the domain 0 <= x <= 1, with periodic boundary conditions 21*c4762a1bSJed Brown 22*c4762a1bSJed Brown to demonstrate solving a data assimilation problem of finding the initial conditions 23*c4762a1bSJed Brown to produce a given solution at a fixed time. 24*c4762a1bSJed Brown 25*c4762a1bSJed Brown The operators are discretized with the spectral element method 26*c4762a1bSJed Brown 27*c4762a1bSJed Brown See the paper PDE-CONSTRAINED OPTIMIZATION WITH SPECTRAL ELEMENTS USING PETSC AND TAO 28*c4762a1bSJed Brown by OANA MARIN, EMIL CONSTANTINESCU, AND BARRY SMITH for details on the exact solution 29*c4762a1bSJed Brown used 30*c4762a1bSJed Brown 31*c4762a1bSJed Brown ------------------------------------------------------------------------- */ 32*c4762a1bSJed Brown 33*c4762a1bSJed Brown #include <petsctao.h> 34*c4762a1bSJed Brown #include <petscts.h> 35*c4762a1bSJed Brown #include <petscdt.h> 36*c4762a1bSJed Brown #include <petscdraw.h> 37*c4762a1bSJed Brown #include <petscdmda.h> 38*c4762a1bSJed Brown 39*c4762a1bSJed Brown /* 40*c4762a1bSJed Brown User-defined application context - contains data needed by the 41*c4762a1bSJed Brown application-provided call-back routines. 42*c4762a1bSJed Brown */ 43*c4762a1bSJed Brown 44*c4762a1bSJed Brown typedef struct { 45*c4762a1bSJed Brown PetscInt n; /* number of nodes */ 46*c4762a1bSJed Brown PetscReal *nodes; /* GLL nodes */ 47*c4762a1bSJed Brown PetscReal *weights; /* GLL weights */ 48*c4762a1bSJed Brown } PetscGLL; 49*c4762a1bSJed Brown 50*c4762a1bSJed Brown typedef struct { 51*c4762a1bSJed Brown PetscInt N; /* grid points per elements*/ 52*c4762a1bSJed Brown PetscInt E; /* number of elements */ 53*c4762a1bSJed Brown PetscReal tol_L2,tol_max; /* error norms */ 54*c4762a1bSJed Brown PetscInt steps; /* number of timesteps */ 55*c4762a1bSJed Brown PetscReal Tend; /* endtime */ 56*c4762a1bSJed Brown PetscReal mu; /* viscosity */ 57*c4762a1bSJed Brown PetscReal L; /* total length of domain */ 58*c4762a1bSJed Brown PetscReal Le; 59*c4762a1bSJed Brown PetscReal Tadj; 60*c4762a1bSJed Brown } PetscParam; 61*c4762a1bSJed Brown 62*c4762a1bSJed Brown typedef struct { 63*c4762a1bSJed Brown Vec obj; /* desired end state */ 64*c4762a1bSJed Brown Vec grid; /* total grid */ 65*c4762a1bSJed Brown Vec grad; 66*c4762a1bSJed Brown Vec ic; 67*c4762a1bSJed Brown Vec curr_sol; 68*c4762a1bSJed Brown Vec true_solution; /* actual initial conditions for the final solution */ 69*c4762a1bSJed Brown } PetscData; 70*c4762a1bSJed Brown 71*c4762a1bSJed Brown typedef struct { 72*c4762a1bSJed Brown Vec grid; /* total grid */ 73*c4762a1bSJed Brown Vec mass; /* mass matrix for total integration */ 74*c4762a1bSJed Brown Mat stiff; /* stifness matrix */ 75*c4762a1bSJed Brown Mat keptstiff; 76*c4762a1bSJed Brown Mat grad; 77*c4762a1bSJed Brown PetscGLL gll; 78*c4762a1bSJed Brown } PetscSEMOperators; 79*c4762a1bSJed Brown 80*c4762a1bSJed Brown typedef struct { 81*c4762a1bSJed Brown DM da; /* distributed array data structure */ 82*c4762a1bSJed Brown PetscSEMOperators SEMop; 83*c4762a1bSJed Brown PetscParam param; 84*c4762a1bSJed Brown PetscData dat; 85*c4762a1bSJed Brown TS ts; 86*c4762a1bSJed Brown PetscReal initial_dt; 87*c4762a1bSJed Brown } AppCtx; 88*c4762a1bSJed Brown 89*c4762a1bSJed Brown /* 90*c4762a1bSJed Brown User-defined routines 91*c4762a1bSJed Brown */ 92*c4762a1bSJed Brown extern PetscErrorCode FormFunctionGradient(Tao,Vec,PetscReal*,Vec,void*); 93*c4762a1bSJed Brown extern PetscErrorCode RHSMatrixLaplaciangllDM(TS,PetscReal,Vec,Mat,Mat,void*); 94*c4762a1bSJed Brown extern PetscErrorCode RHSMatrixAdvectiongllDM(TS,PetscReal,Vec,Mat,Mat,void*); 95*c4762a1bSJed Brown extern PetscErrorCode InitialConditions(Vec,AppCtx*); 96*c4762a1bSJed Brown extern PetscErrorCode TrueSolution(Vec,AppCtx*); 97*c4762a1bSJed Brown extern PetscErrorCode ComputeObjective(PetscReal,Vec,AppCtx*); 98*c4762a1bSJed Brown extern PetscErrorCode MonitorError(Tao,void*); 99*c4762a1bSJed Brown extern PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*); 100*c4762a1bSJed Brown extern PetscErrorCode RHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*); 101*c4762a1bSJed Brown 102*c4762a1bSJed Brown int main(int argc,char **argv) 103*c4762a1bSJed Brown { 104*c4762a1bSJed Brown AppCtx appctx; /* user-defined application context */ 105*c4762a1bSJed Brown Tao tao; 106*c4762a1bSJed Brown Vec u; /* approximate solution vector */ 107*c4762a1bSJed Brown PetscErrorCode ierr; 108*c4762a1bSJed Brown PetscInt i, xs, xm, ind, j, lenglob; 109*c4762a1bSJed Brown PetscReal x, *wrk_ptr1, *wrk_ptr2; 110*c4762a1bSJed Brown MatNullSpace nsp; 111*c4762a1bSJed Brown PetscMPIInt size; 112*c4762a1bSJed Brown 113*c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 114*c4762a1bSJed Brown Initialize program and set problem parameters 115*c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 116*c4762a1bSJed Brown PetscFunctionBegin; 117*c4762a1bSJed Brown 118*c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; 119*c4762a1bSJed Brown 120*c4762a1bSJed Brown /*initialize parameters */ 121*c4762a1bSJed Brown appctx.param.N = 10; /* order of the spectral element */ 122*c4762a1bSJed Brown appctx.param.E = 10; /* number of elements */ 123*c4762a1bSJed Brown appctx.param.L = 4.0; /* length of the domain */ 124*c4762a1bSJed Brown appctx.param.mu = 0.01; /* diffusion coefficient */ 125*c4762a1bSJed Brown appctx.initial_dt = 5e-3; 126*c4762a1bSJed Brown appctx.param.steps = PETSC_MAX_INT; 127*c4762a1bSJed Brown appctx.param.Tend = 4; 128*c4762a1bSJed Brown 129*c4762a1bSJed Brown ierr = PetscOptionsGetInt(NULL,NULL,"-N",&appctx.param.N,NULL);CHKERRQ(ierr); 130*c4762a1bSJed Brown ierr = PetscOptionsGetInt(NULL,NULL,"-E",&appctx.param.E,NULL);CHKERRQ(ierr); 131*c4762a1bSJed Brown ierr = PetscOptionsGetReal(NULL,NULL,"-Tend",&appctx.param.Tend,NULL);CHKERRQ(ierr); 132*c4762a1bSJed Brown ierr = PetscOptionsGetReal(NULL,NULL,"-mu",&appctx.param.mu,NULL);CHKERRQ(ierr); 133*c4762a1bSJed Brown appctx.param.Le = appctx.param.L/appctx.param.E; 134*c4762a1bSJed Brown 135*c4762a1bSJed Brown ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 136*c4762a1bSJed Brown if (appctx.param.E % size) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Number of elements must be divisible by number of processes"); 137*c4762a1bSJed Brown 138*c4762a1bSJed Brown 139*c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 140*c4762a1bSJed Brown Create GLL data structures 141*c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 142*c4762a1bSJed Brown ierr = PetscMalloc2(appctx.param.N,&appctx.SEMop.gll.nodes,appctx.param.N,&appctx.SEMop.gll.weights);CHKERRQ(ierr); 143*c4762a1bSJed Brown ierr = PetscDTGaussLobattoLegendreQuadrature(appctx.param.N,PETSCGAUSSLOBATTOLEGENDRE_VIA_LINEAR_ALGEBRA,appctx.SEMop.gll.nodes,appctx.SEMop.gll.weights);CHKERRQ(ierr); 144*c4762a1bSJed Brown appctx.SEMop.gll.n = appctx.param.N; 145*c4762a1bSJed Brown lenglob = appctx.param.E*(appctx.param.N-1); 146*c4762a1bSJed Brown 147*c4762a1bSJed Brown /* 148*c4762a1bSJed Brown Create distributed array (DMDA) to manage parallel grid and vectors 149*c4762a1bSJed Brown and to set up the ghost point communication pattern. There are E*(Nl-1)+1 150*c4762a1bSJed Brown total grid values spread equally among all the processors, except first and last 151*c4762a1bSJed Brown */ 152*c4762a1bSJed Brown 153*c4762a1bSJed Brown ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC,lenglob,1,1,NULL,&appctx.da);CHKERRQ(ierr); 154*c4762a1bSJed Brown ierr = DMSetFromOptions(appctx.da);CHKERRQ(ierr); 155*c4762a1bSJed Brown ierr = DMSetUp(appctx.da);CHKERRQ(ierr); 156*c4762a1bSJed Brown 157*c4762a1bSJed Brown /* 158*c4762a1bSJed Brown Extract global and local vectors from DMDA; we use these to store the 159*c4762a1bSJed Brown approximate solution. Then duplicate these for remaining vectors that 160*c4762a1bSJed Brown have the same types. 161*c4762a1bSJed Brown */ 162*c4762a1bSJed Brown 163*c4762a1bSJed Brown ierr = DMCreateGlobalVector(appctx.da,&u);CHKERRQ(ierr); 164*c4762a1bSJed Brown ierr = VecDuplicate(u,&appctx.dat.ic);CHKERRQ(ierr); 165*c4762a1bSJed Brown ierr = VecDuplicate(u,&appctx.dat.true_solution);CHKERRQ(ierr); 166*c4762a1bSJed Brown ierr = VecDuplicate(u,&appctx.dat.obj);CHKERRQ(ierr); 167*c4762a1bSJed Brown ierr = VecDuplicate(u,&appctx.SEMop.grid);CHKERRQ(ierr); 168*c4762a1bSJed Brown ierr = VecDuplicate(u,&appctx.SEMop.mass);CHKERRQ(ierr); 169*c4762a1bSJed Brown ierr = VecDuplicate(u,&appctx.dat.curr_sol);CHKERRQ(ierr); 170*c4762a1bSJed Brown 171*c4762a1bSJed Brown ierr = DMDAGetCorners(appctx.da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); 172*c4762a1bSJed Brown ierr = DMDAVecGetArray(appctx.da,appctx.SEMop.grid,&wrk_ptr1);CHKERRQ(ierr); 173*c4762a1bSJed Brown ierr = DMDAVecGetArray(appctx.da,appctx.SEMop.mass,&wrk_ptr2);CHKERRQ(ierr); 174*c4762a1bSJed Brown 175*c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 176*c4762a1bSJed Brown 177*c4762a1bSJed Brown xs=xs/(appctx.param.N-1); 178*c4762a1bSJed Brown xm=xm/(appctx.param.N-1); 179*c4762a1bSJed Brown 180*c4762a1bSJed Brown /* 181*c4762a1bSJed Brown Build total grid and mass over entire mesh (multi-elemental) 182*c4762a1bSJed Brown */ 183*c4762a1bSJed Brown 184*c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 185*c4762a1bSJed Brown for (j=0; j<appctx.param.N-1; j++) { 186*c4762a1bSJed Brown x = (appctx.param.Le/2.0)*(appctx.SEMop.gll.nodes[j]+1.0)+appctx.param.Le*i; 187*c4762a1bSJed Brown ind=i*(appctx.param.N-1)+j; 188*c4762a1bSJed Brown wrk_ptr1[ind]=x; 189*c4762a1bSJed Brown wrk_ptr2[ind]=.5*appctx.param.Le*appctx.SEMop.gll.weights[j]; 190*c4762a1bSJed Brown if (j==0) wrk_ptr2[ind]+=.5*appctx.param.Le*appctx.SEMop.gll.weights[j]; 191*c4762a1bSJed Brown } 192*c4762a1bSJed Brown } 193*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(appctx.da,appctx.SEMop.grid,&wrk_ptr1);CHKERRQ(ierr); 194*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(appctx.da,appctx.SEMop.mass,&wrk_ptr2);CHKERRQ(ierr); 195*c4762a1bSJed Brown 196*c4762a1bSJed Brown 197*c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 198*c4762a1bSJed Brown Create matrix data structure; set matrix evaluation routine. 199*c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 200*c4762a1bSJed Brown ierr = DMSetMatrixPreallocateOnly(appctx.da, PETSC_TRUE);CHKERRQ(ierr); 201*c4762a1bSJed Brown ierr = DMCreateMatrix(appctx.da,&appctx.SEMop.stiff);CHKERRQ(ierr); 202*c4762a1bSJed Brown ierr = DMCreateMatrix(appctx.da,&appctx.SEMop.grad);CHKERRQ(ierr); 203*c4762a1bSJed Brown /* 204*c4762a1bSJed Brown For linear problems with a time-dependent f(u,t) in the equation 205*c4762a1bSJed Brown u_t = f(u,t), the user provides the discretized right-hand-side 206*c4762a1bSJed Brown as a time-dependent matrix. 207*c4762a1bSJed Brown */ 208*c4762a1bSJed Brown ierr = RHSMatrixLaplaciangllDM(appctx.ts,0.0,u,appctx.SEMop.stiff,appctx.SEMop.stiff,&appctx);CHKERRQ(ierr); 209*c4762a1bSJed Brown ierr = RHSMatrixAdvectiongllDM(appctx.ts,0.0,u,appctx.SEMop.grad,appctx.SEMop.grad,&appctx);CHKERRQ(ierr); 210*c4762a1bSJed Brown /* 211*c4762a1bSJed Brown For linear problems with a time-dependent f(u,t) in the equation 212*c4762a1bSJed Brown u_t = f(u,t), the user provides the discretized right-hand-side 213*c4762a1bSJed Brown as a time-dependent matrix. 214*c4762a1bSJed Brown */ 215*c4762a1bSJed Brown 216*c4762a1bSJed Brown ierr = MatDuplicate(appctx.SEMop.stiff,MAT_COPY_VALUES,&appctx.SEMop.keptstiff);CHKERRQ(ierr); 217*c4762a1bSJed Brown 218*c4762a1bSJed Brown /* attach the null space to the matrix, this probably is not needed but does no harm */ 219*c4762a1bSJed Brown ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,NULL,&nsp);CHKERRQ(ierr); 220*c4762a1bSJed Brown ierr = MatSetNullSpace(appctx.SEMop.stiff,nsp);CHKERRQ(ierr); 221*c4762a1bSJed Brown ierr = MatSetNullSpace(appctx.SEMop.keptstiff,nsp);CHKERRQ(ierr); 222*c4762a1bSJed Brown ierr = MatNullSpaceTest(nsp,appctx.SEMop.stiff,NULL);CHKERRQ(ierr); 223*c4762a1bSJed Brown ierr = MatNullSpaceDestroy(&nsp);CHKERRQ(ierr); 224*c4762a1bSJed Brown /* attach the null space to the matrix, this probably is not needed but does no harm */ 225*c4762a1bSJed Brown ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,NULL,&nsp);CHKERRQ(ierr); 226*c4762a1bSJed Brown ierr = MatSetNullSpace(appctx.SEMop.grad,nsp);CHKERRQ(ierr); 227*c4762a1bSJed Brown ierr = MatNullSpaceTest(nsp,appctx.SEMop.grad,NULL);CHKERRQ(ierr); 228*c4762a1bSJed Brown ierr = MatNullSpaceDestroy(&nsp);CHKERRQ(ierr); 229*c4762a1bSJed Brown 230*c4762a1bSJed Brown /* Create the TS solver that solves the ODE and its adjoint; set its options */ 231*c4762a1bSJed Brown ierr = TSCreate(PETSC_COMM_WORLD,&appctx.ts);CHKERRQ(ierr); 232*c4762a1bSJed Brown ierr = TSSetProblemType(appctx.ts,TS_NONLINEAR);CHKERRQ(ierr); 233*c4762a1bSJed Brown ierr = TSSetType(appctx.ts,TSRK);CHKERRQ(ierr); 234*c4762a1bSJed Brown ierr = TSSetDM(appctx.ts,appctx.da);CHKERRQ(ierr); 235*c4762a1bSJed Brown ierr = TSSetTime(appctx.ts,0.0);CHKERRQ(ierr); 236*c4762a1bSJed Brown ierr = TSSetTimeStep(appctx.ts,appctx.initial_dt);CHKERRQ(ierr); 237*c4762a1bSJed Brown ierr = TSSetMaxSteps(appctx.ts,appctx.param.steps);CHKERRQ(ierr); 238*c4762a1bSJed Brown ierr = TSSetMaxTime(appctx.ts,appctx.param.Tend);CHKERRQ(ierr); 239*c4762a1bSJed Brown ierr = TSSetExactFinalTime(appctx.ts,TS_EXACTFINALTIME_MATCHSTEP);CHKERRQ(ierr); 240*c4762a1bSJed Brown ierr = TSSetTolerances(appctx.ts,1e-7,NULL,1e-7,NULL);CHKERRQ(ierr); 241*c4762a1bSJed Brown ierr = TSSetSaveTrajectory(appctx.ts);CHKERRQ(ierr); 242*c4762a1bSJed Brown ierr = TSSetFromOptions(appctx.ts);CHKERRQ(ierr); 243*c4762a1bSJed Brown /* Need to save initial timestep user may have set with -ts_dt so it can be reset for each new TSSolve() */ 244*c4762a1bSJed Brown ierr = TSGetTimeStep(appctx.ts,&appctx.initial_dt);CHKERRQ(ierr); 245*c4762a1bSJed Brown ierr = TSSetRHSFunction(appctx.ts,NULL,RHSFunction,&appctx);CHKERRQ(ierr); 246*c4762a1bSJed Brown ierr = TSSetRHSJacobian(appctx.ts,appctx.SEMop.stiff,appctx.SEMop.stiff,RHSJacobian,&appctx);CHKERRQ(ierr); 247*c4762a1bSJed Brown 248*c4762a1bSJed Brown /* Set Objective and Initial conditions for the problem and compute Objective function (evolution of true_solution to final time */ 249*c4762a1bSJed Brown ierr = InitialConditions(appctx.dat.ic,&appctx);CHKERRQ(ierr); 250*c4762a1bSJed Brown ierr = TrueSolution(appctx.dat.true_solution,&appctx);CHKERRQ(ierr); 251*c4762a1bSJed Brown ierr = ComputeObjective(appctx.param.Tend,appctx.dat.obj,&appctx);CHKERRQ(ierr); 252*c4762a1bSJed Brown 253*c4762a1bSJed Brown /* Create TAO solver and set desired solution method */ 254*c4762a1bSJed Brown ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr); 255*c4762a1bSJed Brown ierr = TaoSetMonitor(tao,MonitorError,&appctx,NULL);CHKERRQ(ierr); 256*c4762a1bSJed Brown ierr = TaoSetType(tao,TAOBQNLS);CHKERRQ(ierr); 257*c4762a1bSJed Brown ierr = TaoSetInitialVector(tao,appctx.dat.ic);CHKERRQ(ierr); 258*c4762a1bSJed Brown /* Set routine for function and gradient evaluation */ 259*c4762a1bSJed Brown ierr = TaoSetObjectiveAndGradientRoutine(tao,FormFunctionGradient,(void *)&appctx);CHKERRQ(ierr); 260*c4762a1bSJed Brown /* Check for any TAO command line options */ 261*c4762a1bSJed Brown ierr = TaoSetTolerances(tao,1e-8,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 262*c4762a1bSJed Brown ierr = TaoSetFromOptions(tao);CHKERRQ(ierr); 263*c4762a1bSJed Brown ierr = TaoSolve(tao);CHKERRQ(ierr); 264*c4762a1bSJed Brown 265*c4762a1bSJed Brown ierr = TaoDestroy(&tao);CHKERRQ(ierr); 266*c4762a1bSJed Brown ierr = MatDestroy(&appctx.SEMop.stiff);CHKERRQ(ierr); 267*c4762a1bSJed Brown ierr = MatDestroy(&appctx.SEMop.keptstiff);CHKERRQ(ierr); 268*c4762a1bSJed Brown ierr = MatDestroy(&appctx.SEMop.grad);CHKERRQ(ierr); 269*c4762a1bSJed Brown ierr = VecDestroy(&u);CHKERRQ(ierr); 270*c4762a1bSJed Brown ierr = VecDestroy(&appctx.dat.ic);CHKERRQ(ierr); 271*c4762a1bSJed Brown ierr = VecDestroy(&appctx.dat.true_solution);CHKERRQ(ierr); 272*c4762a1bSJed Brown ierr = VecDestroy(&appctx.dat.obj);CHKERRQ(ierr); 273*c4762a1bSJed Brown ierr = VecDestroy(&appctx.SEMop.grid);CHKERRQ(ierr); 274*c4762a1bSJed Brown ierr = VecDestroy(&appctx.SEMop.mass);CHKERRQ(ierr); 275*c4762a1bSJed Brown ierr = VecDestroy(&appctx.dat.curr_sol);CHKERRQ(ierr); 276*c4762a1bSJed Brown ierr = PetscFree2(appctx.SEMop.gll.nodes,appctx.SEMop.gll.weights);CHKERRQ(ierr); 277*c4762a1bSJed Brown ierr = DMDestroy(&appctx.da);CHKERRQ(ierr); 278*c4762a1bSJed Brown ierr = TSDestroy(&appctx.ts);CHKERRQ(ierr); 279*c4762a1bSJed Brown 280*c4762a1bSJed Brown /* 281*c4762a1bSJed Brown Always call PetscFinalize() before exiting a program. This routine 282*c4762a1bSJed Brown - finalizes the PETSc libraries as well as MPI 283*c4762a1bSJed Brown - provides summary and diagnostic information if certain runtime 284*c4762a1bSJed Brown options are chosen (e.g., -log_summary). 285*c4762a1bSJed Brown */ 286*c4762a1bSJed Brown ierr = PetscFinalize(); 287*c4762a1bSJed Brown return ierr; 288*c4762a1bSJed Brown } 289*c4762a1bSJed Brown 290*c4762a1bSJed Brown /* --------------------------------------------------------------------- */ 291*c4762a1bSJed Brown /* 292*c4762a1bSJed Brown InitialConditions - Computes the initial conditions for the Tao optimization solve (these are also initial conditions for the first TSSolve() 293*c4762a1bSJed Brown 294*c4762a1bSJed Brown The routine TrueSolution() computes the true solution for the Tao optimization solve which means they are the initial conditions for the objective function 295*c4762a1bSJed Brown 296*c4762a1bSJed Brown Input Parameter: 297*c4762a1bSJed Brown u - uninitialized solution vector (global) 298*c4762a1bSJed Brown appctx - user-defined application context 299*c4762a1bSJed Brown 300*c4762a1bSJed Brown Output Parameter: 301*c4762a1bSJed Brown u - vector with solution at initial time (global) 302*c4762a1bSJed Brown */ 303*c4762a1bSJed Brown PetscErrorCode InitialConditions(Vec u,AppCtx *appctx) 304*c4762a1bSJed Brown { 305*c4762a1bSJed Brown PetscScalar *s; 306*c4762a1bSJed Brown const PetscScalar *xg; 307*c4762a1bSJed Brown PetscErrorCode ierr; 308*c4762a1bSJed Brown PetscInt i,xs,xn; 309*c4762a1bSJed Brown 310*c4762a1bSJed Brown PetscFunctionBegin; 311*c4762a1bSJed Brown ierr = DMDAVecGetArray(appctx->da,u,&s);CHKERRQ(ierr); 312*c4762a1bSJed Brown ierr = DMDAVecGetArrayRead(appctx->da,appctx->SEMop.grid,(void*)&xg);CHKERRQ(ierr); 313*c4762a1bSJed Brown ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); 314*c4762a1bSJed Brown for (i=xs; i<xs+xn; i++) { 315*c4762a1bSJed Brown s[i]=2.0*appctx->param.mu*PETSC_PI*PetscSinScalar(PETSC_PI*xg[i])/(2.0+PetscCosScalar(PETSC_PI*xg[i]))+0.25*PetscExpReal(-4.0*PetscPowReal(xg[i]-2.0,2.0)); 316*c4762a1bSJed Brown } 317*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(appctx->da,u,&s);CHKERRQ(ierr); 318*c4762a1bSJed Brown ierr = DMDAVecRestoreArrayRead(appctx->da,appctx->SEMop.grid,(void*)&xg);CHKERRQ(ierr); 319*c4762a1bSJed Brown PetscFunctionReturn(0); 320*c4762a1bSJed Brown } 321*c4762a1bSJed Brown 322*c4762a1bSJed Brown /* 323*c4762a1bSJed Brown TrueSolution() computes the true solution for the Tao optimization solve which means they are the initial conditions for the objective function. 324*c4762a1bSJed Brown 325*c4762a1bSJed Brown InitialConditions() computes the initial conditions for the begining of the Tao iterations 326*c4762a1bSJed Brown 327*c4762a1bSJed Brown Input Parameter: 328*c4762a1bSJed Brown u - uninitialized solution vector (global) 329*c4762a1bSJed Brown appctx - user-defined application context 330*c4762a1bSJed Brown 331*c4762a1bSJed Brown Output Parameter: 332*c4762a1bSJed Brown u - vector with solution at initial time (global) 333*c4762a1bSJed Brown */ 334*c4762a1bSJed Brown PetscErrorCode TrueSolution(Vec u,AppCtx *appctx) 335*c4762a1bSJed Brown { 336*c4762a1bSJed Brown PetscScalar *s; 337*c4762a1bSJed Brown const PetscScalar *xg; 338*c4762a1bSJed Brown PetscErrorCode ierr; 339*c4762a1bSJed Brown PetscInt i,xs,xn; 340*c4762a1bSJed Brown 341*c4762a1bSJed Brown PetscFunctionBegin; 342*c4762a1bSJed Brown ierr = DMDAVecGetArray(appctx->da,u,&s);CHKERRQ(ierr); 343*c4762a1bSJed Brown ierr = DMDAVecGetArrayRead(appctx->da,appctx->SEMop.grid,(void*)&xg);CHKERRQ(ierr); 344*c4762a1bSJed Brown ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); 345*c4762a1bSJed Brown for (i=xs; i<xs+xn; i++) { 346*c4762a1bSJed Brown s[i]=2.0*appctx->param.mu*PETSC_PI*PetscSinScalar(PETSC_PI*xg[i])/(2.0+PetscCosScalar(PETSC_PI*xg[i])); 347*c4762a1bSJed Brown } 348*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(appctx->da,u,&s);CHKERRQ(ierr); 349*c4762a1bSJed Brown ierr = DMDAVecRestoreArrayRead(appctx->da,appctx->SEMop.grid,(void*)&xg);CHKERRQ(ierr); 350*c4762a1bSJed Brown PetscFunctionReturn(0); 351*c4762a1bSJed Brown } 352*c4762a1bSJed Brown /* --------------------------------------------------------------------- */ 353*c4762a1bSJed Brown /* 354*c4762a1bSJed Brown Sets the desired profile for the final end time 355*c4762a1bSJed Brown 356*c4762a1bSJed Brown Input Parameters: 357*c4762a1bSJed Brown t - final time 358*c4762a1bSJed Brown obj - vector storing the desired profile 359*c4762a1bSJed Brown appctx - user-defined application context 360*c4762a1bSJed Brown 361*c4762a1bSJed Brown */ 362*c4762a1bSJed Brown PetscErrorCode ComputeObjective(PetscReal t,Vec obj,AppCtx *appctx) 363*c4762a1bSJed Brown { 364*c4762a1bSJed Brown PetscScalar *s; 365*c4762a1bSJed Brown const PetscScalar *xg; 366*c4762a1bSJed Brown PetscErrorCode ierr; 367*c4762a1bSJed Brown PetscInt i, xs,xn; 368*c4762a1bSJed Brown 369*c4762a1bSJed Brown PetscFunctionBegin; 370*c4762a1bSJed Brown ierr = DMDAVecGetArray(appctx->da,obj,&s);CHKERRQ(ierr); 371*c4762a1bSJed Brown ierr = DMDAVecGetArrayRead(appctx->da,appctx->SEMop.grid,(void*)&xg);CHKERRQ(ierr); 372*c4762a1bSJed Brown ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); 373*c4762a1bSJed Brown for (i=xs; i<xs+xn; i++) { 374*c4762a1bSJed Brown s[i]=2.0*appctx->param.mu*PETSC_PI*PetscSinScalar(PETSC_PI*xg[i])*PetscExpScalar(-PETSC_PI*PETSC_PI*t*appctx->param.mu)\ 375*c4762a1bSJed Brown /(2.0+PetscExpScalar(-PETSC_PI*PETSC_PI*t*appctx->param.mu)*PetscCosScalar(PETSC_PI*xg[i])); 376*c4762a1bSJed Brown } 377*c4762a1bSJed Brown ierr = DMDAVecRestoreArray(appctx->da,obj,&s);CHKERRQ(ierr); 378*c4762a1bSJed Brown ierr = DMDAVecRestoreArrayRead(appctx->da,appctx->SEMop.grid,(void*)&xg);CHKERRQ(ierr); 379*c4762a1bSJed Brown PetscFunctionReturn(0); 380*c4762a1bSJed Brown } 381*c4762a1bSJed Brown 382*c4762a1bSJed Brown PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec globalin,Vec globalout,void *ctx) 383*c4762a1bSJed Brown { 384*c4762a1bSJed Brown PetscErrorCode ierr; 385*c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; 386*c4762a1bSJed Brown 387*c4762a1bSJed Brown PetscFunctionBegin; 388*c4762a1bSJed Brown ierr = MatMult(appctx->SEMop.grad,globalin,globalout);CHKERRQ(ierr); /* grad u */ 389*c4762a1bSJed Brown ierr = VecPointwiseMult(globalout,globalin,globalout);CHKERRQ(ierr); /* u grad u */ 390*c4762a1bSJed Brown ierr = VecScale(globalout, -1.0);CHKERRQ(ierr); 391*c4762a1bSJed Brown ierr = MatMultAdd(appctx->SEMop.keptstiff,globalin,globalout,globalout);CHKERRQ(ierr); 392*c4762a1bSJed Brown PetscFunctionReturn(0); 393*c4762a1bSJed Brown } 394*c4762a1bSJed Brown 395*c4762a1bSJed Brown /* 396*c4762a1bSJed Brown 397*c4762a1bSJed Brown K is the discretiziation of the Laplacian 398*c4762a1bSJed Brown G is the discretization of the gradient 399*c4762a1bSJed Brown 400*c4762a1bSJed Brown Computes Jacobian of K u + diag(u) G u which is given by 401*c4762a1bSJed Brown K + diag(u)G + diag(Gu) 402*c4762a1bSJed Brown */ 403*c4762a1bSJed Brown PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec globalin,Mat A, Mat B,void *ctx) 404*c4762a1bSJed Brown { 405*c4762a1bSJed Brown PetscErrorCode ierr; 406*c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; 407*c4762a1bSJed Brown Vec Gglobalin; 408*c4762a1bSJed Brown 409*c4762a1bSJed Brown PetscFunctionBegin; 410*c4762a1bSJed Brown /* A = diag(u) G */ 411*c4762a1bSJed Brown 412*c4762a1bSJed Brown ierr = MatCopy(appctx->SEMop.grad,A,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 413*c4762a1bSJed Brown ierr = MatDiagonalScale(A,globalin,NULL);CHKERRQ(ierr); 414*c4762a1bSJed Brown 415*c4762a1bSJed Brown /* A = A + diag(Gu) */ 416*c4762a1bSJed Brown ierr = VecDuplicate(globalin,&Gglobalin);CHKERRQ(ierr); 417*c4762a1bSJed Brown ierr = MatMult(appctx->SEMop.grad,globalin,Gglobalin);CHKERRQ(ierr); 418*c4762a1bSJed Brown ierr = MatDiagonalSet(A,Gglobalin,ADD_VALUES);CHKERRQ(ierr); 419*c4762a1bSJed Brown ierr = VecDestroy(&Gglobalin);CHKERRQ(ierr); 420*c4762a1bSJed Brown 421*c4762a1bSJed Brown /* A = K - A */ 422*c4762a1bSJed Brown ierr = MatScale(A,-1.0);CHKERRQ(ierr); 423*c4762a1bSJed Brown ierr = MatAXPY(A,1.0,appctx->SEMop.keptstiff,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 424*c4762a1bSJed Brown PetscFunctionReturn(0); 425*c4762a1bSJed Brown } 426*c4762a1bSJed Brown 427*c4762a1bSJed Brown /* --------------------------------------------------------------------- */ 428*c4762a1bSJed Brown 429*c4762a1bSJed Brown /* 430*c4762a1bSJed Brown RHSMatrixLaplacian - User-provided routine to compute the right-hand-side 431*c4762a1bSJed Brown matrix for the heat equation. 432*c4762a1bSJed Brown 433*c4762a1bSJed Brown Input Parameters: 434*c4762a1bSJed Brown ts - the TS context 435*c4762a1bSJed Brown t - current time (ignored) 436*c4762a1bSJed Brown X - current solution (ignored) 437*c4762a1bSJed Brown dummy - optional user-defined context, as set by TSetRHSJacobian() 438*c4762a1bSJed Brown 439*c4762a1bSJed Brown Output Parameters: 440*c4762a1bSJed Brown AA - Jacobian matrix 441*c4762a1bSJed Brown BB - optionally different matrix from which the preconditioner is built 442*c4762a1bSJed Brown str - flag indicating matrix structure 443*c4762a1bSJed Brown 444*c4762a1bSJed Brown */ 445*c4762a1bSJed Brown PetscErrorCode RHSMatrixLaplaciangllDM(TS ts,PetscReal t,Vec X,Mat A,Mat BB,void *ctx) 446*c4762a1bSJed Brown { 447*c4762a1bSJed Brown PetscReal **temp; 448*c4762a1bSJed Brown PetscReal vv; 449*c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; /* user-defined application context */ 450*c4762a1bSJed Brown PetscErrorCode ierr; 451*c4762a1bSJed Brown PetscInt i,xs,xn,l,j; 452*c4762a1bSJed Brown PetscInt *rowsDM; 453*c4762a1bSJed Brown 454*c4762a1bSJed Brown PetscFunctionBegin; 455*c4762a1bSJed Brown /* 456*c4762a1bSJed Brown Creates the element stiffness matrix for the given gll 457*c4762a1bSJed Brown */ 458*c4762a1bSJed Brown ierr = PetscGaussLobattoLegendreElementLaplacianCreate(appctx->SEMop.gll.n,appctx->SEMop.gll.nodes,appctx->SEMop.gll.weights,&temp);CHKERRQ(ierr); 459*c4762a1bSJed Brown /* workarround for clang analyzer warning: Division by zero */ 460*c4762a1bSJed Brown if (appctx->param.N <= 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Spectral element order should be > 1"); 461*c4762a1bSJed Brown 462*c4762a1bSJed Brown /* scale by the size of the element */ 463*c4762a1bSJed Brown for (i=0; i<appctx->param.N; i++) { 464*c4762a1bSJed Brown vv=-appctx->param.mu*2.0/appctx->param.Le; 465*c4762a1bSJed Brown for (j=0; j<appctx->param.N; j++) temp[i][j]=temp[i][j]*vv; 466*c4762a1bSJed Brown } 467*c4762a1bSJed Brown 468*c4762a1bSJed Brown ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 469*c4762a1bSJed Brown ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); 470*c4762a1bSJed Brown 471*c4762a1bSJed Brown xs = xs/(appctx->param.N-1); 472*c4762a1bSJed Brown xn = xn/(appctx->param.N-1); 473*c4762a1bSJed Brown 474*c4762a1bSJed Brown ierr = PetscMalloc1(appctx->param.N,&rowsDM);CHKERRQ(ierr); 475*c4762a1bSJed Brown /* 476*c4762a1bSJed Brown loop over local elements 477*c4762a1bSJed Brown */ 478*c4762a1bSJed Brown for (j=xs; j<xs+xn; j++) { 479*c4762a1bSJed Brown for (l=0; l<appctx->param.N; l++) { 480*c4762a1bSJed Brown rowsDM[l] = 1+(j-xs)*(appctx->param.N-1)+l; 481*c4762a1bSJed Brown } 482*c4762a1bSJed Brown ierr = MatSetValuesLocal(A,appctx->param.N,rowsDM,appctx->param.N,rowsDM,&temp[0][0],ADD_VALUES);CHKERRQ(ierr); 483*c4762a1bSJed Brown } 484*c4762a1bSJed Brown ierr = PetscFree(rowsDM);CHKERRQ(ierr); 485*c4762a1bSJed Brown ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 486*c4762a1bSJed Brown ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 487*c4762a1bSJed Brown ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); 488*c4762a1bSJed Brown ierr = MatDiagonalScale(A,appctx->SEMop.mass,0);CHKERRQ(ierr); 489*c4762a1bSJed Brown ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); 490*c4762a1bSJed Brown 491*c4762a1bSJed Brown ierr = PetscGaussLobattoLegendreElementLaplacianDestroy(appctx->SEMop.gll.n,appctx->SEMop.gll.nodes,appctx->SEMop.gll.weights,&temp);CHKERRQ(ierr); 492*c4762a1bSJed Brown PetscFunctionReturn(0); 493*c4762a1bSJed Brown } 494*c4762a1bSJed Brown 495*c4762a1bSJed Brown /* 496*c4762a1bSJed Brown RHSMatrixAdvection - User-provided routine to compute the right-hand-side 497*c4762a1bSJed Brown matrix for the Advection equation. 498*c4762a1bSJed Brown 499*c4762a1bSJed Brown Input Parameters: 500*c4762a1bSJed Brown ts - the TS context 501*c4762a1bSJed Brown t - current time 502*c4762a1bSJed Brown global_in - global input vector 503*c4762a1bSJed Brown dummy - optional user-defined context, as set by TSetRHSJacobian() 504*c4762a1bSJed Brown 505*c4762a1bSJed Brown Output Parameters: 506*c4762a1bSJed Brown AA - Jacobian matrix 507*c4762a1bSJed Brown BB - optionally different preconditioning matrix 508*c4762a1bSJed Brown str - flag indicating matrix structure 509*c4762a1bSJed Brown 510*c4762a1bSJed Brown */ 511*c4762a1bSJed Brown PetscErrorCode RHSMatrixAdvectiongllDM(TS ts,PetscReal t,Vec X,Mat A,Mat BB,void *ctx) 512*c4762a1bSJed Brown { 513*c4762a1bSJed Brown PetscReal **temp; 514*c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; /* user-defined application context */ 515*c4762a1bSJed Brown PetscErrorCode ierr; 516*c4762a1bSJed Brown PetscInt xs,xn,l,j; 517*c4762a1bSJed Brown PetscInt *rowsDM; 518*c4762a1bSJed Brown 519*c4762a1bSJed Brown PetscFunctionBegin; 520*c4762a1bSJed Brown /* 521*c4762a1bSJed Brown Creates the advection matrix for the given gll 522*c4762a1bSJed Brown */ 523*c4762a1bSJed Brown ierr = PetscGaussLobattoLegendreElementAdvectionCreate(appctx->SEMop.gll.n,appctx->SEMop.gll.nodes,appctx->SEMop.gll.weights,&temp);CHKERRQ(ierr); 524*c4762a1bSJed Brown ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 525*c4762a1bSJed Brown 526*c4762a1bSJed Brown ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); 527*c4762a1bSJed Brown 528*c4762a1bSJed Brown xs = xs/(appctx->param.N-1); 529*c4762a1bSJed Brown xn = xn/(appctx->param.N-1); 530*c4762a1bSJed Brown 531*c4762a1bSJed Brown ierr = PetscMalloc1(appctx->param.N,&rowsDM);CHKERRQ(ierr); 532*c4762a1bSJed Brown for (j=xs; j<xs+xn; j++) { 533*c4762a1bSJed Brown for (l=0; l<appctx->param.N; l++) { 534*c4762a1bSJed Brown rowsDM[l] = 1+(j-xs)*(appctx->param.N-1)+l; 535*c4762a1bSJed Brown } 536*c4762a1bSJed Brown ierr = MatSetValuesLocal(A,appctx->param.N,rowsDM,appctx->param.N,rowsDM,&temp[0][0],ADD_VALUES);CHKERRQ(ierr); 537*c4762a1bSJed Brown } 538*c4762a1bSJed Brown ierr = PetscFree(rowsDM);CHKERRQ(ierr); 539*c4762a1bSJed Brown ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 540*c4762a1bSJed Brown ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 541*c4762a1bSJed Brown 542*c4762a1bSJed Brown ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); 543*c4762a1bSJed Brown ierr = MatDiagonalScale(A,appctx->SEMop.mass,0);CHKERRQ(ierr); 544*c4762a1bSJed Brown ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); 545*c4762a1bSJed Brown ierr = PetscGaussLobattoLegendreElementAdvectionDestroy(appctx->SEMop.gll.n,appctx->SEMop.gll.nodes,appctx->SEMop.gll.weights,&temp);CHKERRQ(ierr); 546*c4762a1bSJed Brown PetscFunctionReturn(0); 547*c4762a1bSJed Brown } 548*c4762a1bSJed Brown /* ------------------------------------------------------------------ */ 549*c4762a1bSJed Brown /* 550*c4762a1bSJed Brown FormFunctionGradient - Evaluates the function and corresponding gradient. 551*c4762a1bSJed Brown 552*c4762a1bSJed Brown Input Parameters: 553*c4762a1bSJed Brown tao - the Tao context 554*c4762a1bSJed Brown IC - the input vector 555*c4762a1bSJed Brown ctx - optional user-defined context, as set when calling TaoSetObjectiveAndGradientRoutine() 556*c4762a1bSJed Brown 557*c4762a1bSJed Brown Output Parameters: 558*c4762a1bSJed Brown f - the newly evaluated function 559*c4762a1bSJed Brown G - the newly evaluated gradient 560*c4762a1bSJed Brown 561*c4762a1bSJed Brown Notes: 562*c4762a1bSJed Brown 563*c4762a1bSJed Brown The forward equation is 564*c4762a1bSJed Brown M u_t = F(U) 565*c4762a1bSJed Brown which is converted to 566*c4762a1bSJed Brown u_t = M^{-1} F(u) 567*c4762a1bSJed Brown in the user code since TS has no direct way of providing a mass matrix. The Jacobian of this is 568*c4762a1bSJed Brown M^{-1} J 569*c4762a1bSJed Brown where J is the Jacobian of F. Now the adjoint equation is 570*c4762a1bSJed Brown M v_t = J^T v 571*c4762a1bSJed Brown but TSAdjoint does not solve this since it can only solve the transposed system for the 572*c4762a1bSJed Brown Jacobian the user provided. Hence TSAdjoint solves 573*c4762a1bSJed Brown w_t = J^T M^{-1} w (where w = M v) 574*c4762a1bSJed Brown since there is no way to indicate the mass matrix as a separate entitity to TS. Thus one 575*c4762a1bSJed Brown must be careful in initializing the "adjoint equation" and using the result. This is 576*c4762a1bSJed Brown why 577*c4762a1bSJed Brown G = -2 M(u(T) - u_d) 578*c4762a1bSJed Brown below (instead of -2(u(T) - u_d) and why the result is 579*c4762a1bSJed Brown G = G/appctx->SEMop.mass (that is G = M^{-1}w) 580*c4762a1bSJed Brown below (instead of just the result of the "adjoint solve"). 581*c4762a1bSJed Brown 582*c4762a1bSJed Brown 583*c4762a1bSJed Brown */ 584*c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao tao,Vec IC,PetscReal *f,Vec G,void *ctx) 585*c4762a1bSJed Brown { 586*c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; /* user-defined application context */ 587*c4762a1bSJed Brown PetscErrorCode ierr; 588*c4762a1bSJed Brown Vec temp; 589*c4762a1bSJed Brown PetscInt its; 590*c4762a1bSJed Brown PetscReal ff, gnorm, cnorm, xdiff,errex; 591*c4762a1bSJed Brown TaoConvergedReason reason; 592*c4762a1bSJed Brown 593*c4762a1bSJed Brown PetscFunctionBegin; 594*c4762a1bSJed Brown ierr = TSSetTime(appctx->ts,0.0);CHKERRQ(ierr); 595*c4762a1bSJed Brown ierr = TSSetStepNumber(appctx->ts,0);CHKERRQ(ierr); 596*c4762a1bSJed Brown ierr = TSSetTimeStep(appctx->ts,appctx->initial_dt);CHKERRQ(ierr); 597*c4762a1bSJed Brown ierr = VecCopy(IC,appctx->dat.curr_sol);CHKERRQ(ierr); 598*c4762a1bSJed Brown 599*c4762a1bSJed Brown ierr = TSResetTrajectory(appctx->ts);CHKERRQ(ierr); 600*c4762a1bSJed Brown ierr = TSSolve(appctx->ts,appctx->dat.curr_sol);CHKERRQ(ierr); 601*c4762a1bSJed Brown 602*c4762a1bSJed Brown ierr = VecWAXPY(G,-1.0,appctx->dat.curr_sol,appctx->dat.obj);CHKERRQ(ierr); 603*c4762a1bSJed Brown 604*c4762a1bSJed Brown /* 605*c4762a1bSJed Brown Compute the L2-norm of the objective function, cost function is f 606*c4762a1bSJed Brown */ 607*c4762a1bSJed Brown ierr = VecDuplicate(G,&temp);CHKERRQ(ierr); 608*c4762a1bSJed Brown ierr = VecPointwiseMult(temp,G,G);CHKERRQ(ierr); 609*c4762a1bSJed Brown ierr = VecDot(temp,appctx->SEMop.mass,f);CHKERRQ(ierr); 610*c4762a1bSJed Brown 611*c4762a1bSJed Brown /* local error evaluation */ 612*c4762a1bSJed Brown ierr = VecWAXPY(temp,-1.0,appctx->dat.ic,appctx->dat.true_solution);CHKERRQ(ierr); 613*c4762a1bSJed Brown ierr = VecPointwiseMult(temp,temp,temp);CHKERRQ(ierr); 614*c4762a1bSJed Brown /* for error evaluation */ 615*c4762a1bSJed Brown ierr = VecDot(temp,appctx->SEMop.mass,&errex);CHKERRQ(ierr); 616*c4762a1bSJed Brown ierr = VecDestroy(&temp);CHKERRQ(ierr); 617*c4762a1bSJed Brown errex = PetscSqrtReal(errex); 618*c4762a1bSJed Brown 619*c4762a1bSJed Brown /* 620*c4762a1bSJed Brown Compute initial conditions for the adjoint integration. See Notes above 621*c4762a1bSJed Brown */ 622*c4762a1bSJed Brown 623*c4762a1bSJed Brown ierr = VecScale(G, -2.0);CHKERRQ(ierr); 624*c4762a1bSJed Brown ierr = VecPointwiseMult(G,G,appctx->SEMop.mass);CHKERRQ(ierr); 625*c4762a1bSJed Brown ierr = TSSetCostGradients(appctx->ts,1,&G,NULL);CHKERRQ(ierr); 626*c4762a1bSJed Brown ierr = TSAdjointSolve(appctx->ts);CHKERRQ(ierr); 627*c4762a1bSJed Brown ierr = VecPointwiseDivide(G,G,appctx->SEMop.mass);CHKERRQ(ierr); 628*c4762a1bSJed Brown 629*c4762a1bSJed Brown ierr = TaoGetSolutionStatus(tao, &its, &ff, &gnorm, &cnorm, &xdiff, &reason);CHKERRQ(ierr); 630*c4762a1bSJed Brown PetscFunctionReturn(0); 631*c4762a1bSJed Brown } 632*c4762a1bSJed Brown 633*c4762a1bSJed Brown PetscErrorCode MonitorError(Tao tao,void *ctx) 634*c4762a1bSJed Brown { 635*c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; 636*c4762a1bSJed Brown Vec temp; 637*c4762a1bSJed Brown PetscReal nrm; 638*c4762a1bSJed Brown PetscErrorCode ierr; 639*c4762a1bSJed Brown 640*c4762a1bSJed Brown PetscFunctionBegin; 641*c4762a1bSJed Brown ierr = VecDuplicate(appctx->dat.ic,&temp);CHKERRQ(ierr); 642*c4762a1bSJed Brown ierr = VecWAXPY(temp,-1.0,appctx->dat.ic,appctx->dat.true_solution);CHKERRQ(ierr); 643*c4762a1bSJed Brown ierr = VecPointwiseMult(temp,temp,temp);CHKERRQ(ierr); 644*c4762a1bSJed Brown ierr = VecDot(temp,appctx->SEMop.mass,&nrm);CHKERRQ(ierr); 645*c4762a1bSJed Brown ierr = VecDestroy(&temp);CHKERRQ(ierr); 646*c4762a1bSJed Brown nrm = PetscSqrtReal(nrm); 647*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD,"Error for initial conditions %g\n",(double)nrm);CHKERRQ(ierr); 648*c4762a1bSJed Brown PetscFunctionReturn(0); 649*c4762a1bSJed Brown } 650*c4762a1bSJed Brown 651*c4762a1bSJed Brown 652*c4762a1bSJed Brown /*TEST 653*c4762a1bSJed Brown 654*c4762a1bSJed Brown build: 655*c4762a1bSJed Brown requires: !complex 656*c4762a1bSJed Brown 657*c4762a1bSJed Brown test: 658*c4762a1bSJed Brown args: -tao_max_it 5 -tao_gatol 1.e-4 659*c4762a1bSJed Brown requires: !single 660*c4762a1bSJed Brown 661*c4762a1bSJed Brown test: 662*c4762a1bSJed Brown suffix: 2 663*c4762a1bSJed Brown nsize: 2 664*c4762a1bSJed Brown args: -tao_max_it 5 -tao_gatol 1.e-4 665*c4762a1bSJed Brown requires: !single 666*c4762a1bSJed Brown 667*c4762a1bSJed Brown TEST*/ 668