int main(int argc, char *argv[]) { UserData data; SUNMatrix A, AB; SUNLinearSolver LS, LSB; void *cvode_mem; realtype reltolQ, abstolQ; N_Vector y, q, constraints; int steps; int indexB; realtype reltolB, abstolB, abstolQB; N_Vector yB, qB, constraintsB; realtype time; int retval, ncheck; long int nst, nstB; CVadjCheckPointRec *ckpnt; data = NULL; A = AB = NULL; LS = LSB = NULL; cvode_mem = NULL; ckpnt = NULL; y = yB = qB = NULL; constraints = NULL; constraintsB = NULL; /* Print problem description */ printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n"); printf("-------------------------------------------------\n\n"); printf("ODE: dy1/dt = -p1*y1 + p2*y2*y3\n"); printf(" dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2\n"); printf(" dy3/dt = p3*(y2)^2\n\n"); printf("Find dG/dp for\n"); printf(" G = int_t0^tB0 g(t,p,y) dt\n"); printf(" g(t,p,y) = y3\n\n\n"); /* User data structure */ data = (UserData) malloc(sizeof *data); if (check_retval((void *)data, "malloc", 2)) return(1); data->p[0] = RCONST(0.04); data->p[1] = RCONST(1.0e4); data->p[2] = RCONST(3.0e7); /* Initialize y */ y = N_VNew_Serial(NEQ); if (check_retval((void *)y, "N_VNew_Serial", 0)) return(1); Ith(y,1) = RCONST(1.0); Ith(y,2) = ZERO; Ith(y,3) = ZERO; /* Set constraints to all 1's for nonnegative solution values. */ constraints = N_VNew_Serial(NEQ); if(check_retval((void *)constraints, "N_VNew_Serial", 0)) return(1); N_VConst(ONE, constraints); /* Initialize q */ q = N_VNew_Serial(1); if (check_retval((void *)q, "N_VNew_Serial", 0)) return(1); Ith(q,1) = ZERO; /* Set the scalar realtive and absolute tolerances reltolQ and abstolQ */ reltolQ = RTOL; abstolQ = ATOLq; /* Create and allocate CVODES memory for forward run */ printf("Create and allocate CVODES memory for forward runs\n"); /* Call CVodeCreate to create the solver memory and specify the Backward Differentiation Formula */ cvode_mem = CVodeCreate(CV_BDF); if (check_retval((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the user's right hand side function in y'=f(t,y), the initial time T0, and the initial dependent variable vector y. */ retval = CVodeInit(cvode_mem, f, T0, y); if (check_retval(&retval, "CVodeInit", 1)) return(1); /* Call CVodeWFtolerances to specify a user-supplied function ewt that sets the multiplicative error weights w_i for use in the weighted RMS norm */ retval = CVodeWFtolerances(cvode_mem, ewt); if (check_retval(&retval, "CVodeWFtolerances", 1)) return(1); /* Attach user data */ retval = CVodeSetUserData(cvode_mem, data); if (check_retval(&retval, "CVodeSetUserData", 1)) return(1); /* Call CVodeSetConstraints to initialize constraints */ retval = CVodeSetConstraints(cvode_mem, constraints); if (check_retval(&retval, "CVODESetConstraints", 1)) return(1); N_VDestroy(constraints); /* Create dense SUNMatrix for use in linear solves */ A = SUNDenseMatrix(NEQ, NEQ); if (check_retval((void *)A, "SUNDenseMatrix", 0)) return(1); /* Create dense SUNLinearSolver object */ LS = SUNLinSol_Dense(y, A); if (check_retval((void *)LS, "SUNLinSol_Dense", 0)) return(1); /* Attach the matrix and linear solver */ retval = CVDlsSetLinearSolver(cvode_mem, LS, A); if (check_retval(&retval, "CVDlsSetLinearSolver", 1)) return(1); /* Set the user-supplied Jacobian routine Jac */ retval = CVDlsSetJacFn(cvode_mem, Jac); if (check_retval(&retval, "CVDlsSetJacFn", 1)) return(1); /* Call CVodeQuadInit to allocate initernal memory and initialize quadrature integration*/ retval = CVodeQuadInit(cvode_mem, fQ, q); if (check_retval(&retval, "CVodeQuadInit", 1)) return(1); /* Call CVodeSetQuadErrCon to specify whether or not the quadrature variables are to be used in the step size control mechanism within CVODES. Call CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration tolerances for the quadrature variables. */ retval = CVodeSetQuadErrCon(cvode_mem, SUNTRUE); if (check_retval(&retval, "CVodeSetQuadErrCon", 1)) return(1); /* Call CVodeQuadSStolerances to specify scalar relative and absolute tolerances. */ retval = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ); if (check_retval(&retval, "CVodeQuadSStolerances", 1)) return(1); /* Allocate global memory */ /* Call CVodeAdjInit to update CVODES memory block by allocting the internal memory needed for backward integration.*/ steps = STEPS; /* no. of integration steps between two consecutive ckeckpoints*/ retval = CVodeAdjInit(cvode_mem, steps, CV_HERMITE); /* retval = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL); */ if (check_retval(&retval, "CVodeAdjInit", 1)) return(1); /* Perform forward run */ printf("Forward integration ... "); /* Call CVodeF to integrate the forward problem over an interval in time and saves checkpointing data */ retval = CVodeF(cvode_mem, TOUT, y, &time, CV_NORMAL, &ncheck); if (check_retval(&retval, "CVodeF", 1)) return(1); retval = CVodeGetNumSteps(cvode_mem, &nst); if (check_retval(&retval, "CVodeGetNumSteps", 1)) return(1); printf("done ( nst = %ld )\n",nst); printf("\nncheck = %d\n\n", ncheck); retval = CVodeGetQuad(cvode_mem, &time, q); if (check_retval(&retval, "CVodeGetQuad", 1)) return(1); printf("--------------------------------------------------------\n"); #if defined(SUNDIALS_EXTENDED_PRECISION) printf("G: %12.4Le \n",Ith(q,1)); #elif defined(SUNDIALS_DOUBLE_PRECISION) printf("G: %12.4e \n",Ith(q,1)); #else printf("G: %12.4e \n",Ith(q,1)); #endif printf("--------------------------------------------------------\n\n"); /* Test check point linked list (uncomment next block to print check point information) */ /* { int i; printf("\nList of Check Points (ncheck = %d)\n\n", ncheck); ckpnt = (CVadjCheckPointRec *) malloc ( (ncheck+1)*sizeof(CVadjCheckPointRec)); CVodeGetAdjCheckPointsInfo(cvode_mem, ckpnt); for (i=0;i<=ncheck;i++) { printf("Address: %p\n",ckpnt[i].my_addr); printf("Next: %p\n",ckpnt[i].next_addr); printf("Time interval: %le %le\n",ckpnt[i].t0, ckpnt[i].t1); printf("Step number: %ld\n",ckpnt[i].nstep); printf("Order: %d\n",ckpnt[i].order); printf("Step size: %le\n",ckpnt[i].step); printf("\n"); } } */ /* Initialize yB */ yB = N_VNew_Serial(NEQ); if (check_retval((void *)yB, "N_VNew_Serial", 0)) return(1); Ith(yB,1) = ZERO; Ith(yB,2) = ZERO; Ith(yB,3) = ZERO; /* Initialize qB */ qB = N_VNew_Serial(NP); if (check_retval((void *)qB, "N_VNew", 0)) return(1); Ith(qB,1) = ZERO; Ith(qB,2) = ZERO; Ith(qB,3) = ZERO; /* Set the scalar relative tolerance reltolB */ reltolB = RTOL; /* Set the scalar absolute tolerance abstolB */ abstolB = ATOLl; /* Set the scalar absolute tolerance abstolQB */ abstolQB = ATOLq; /* Set constraints to all 1's for nonnegative solution values. */ constraintsB = N_VNew_Serial(NEQ); if(check_retval((void *)constraintsB, "N_VNew_Serial", 0)) return(1); N_VConst(ONE, constraintsB); /* Create and allocate CVODES memory for backward run */ printf("Create and allocate CVODES memory for backward run\n"); /* Call CVodeCreateB to specify the solution method for the backward problem. */ retval = CVodeCreateB(cvode_mem, CV_BDF, &indexB); if (check_retval(&retval, "CVodeCreateB", 1)) return(1); /* Call CVodeInitB to allocate internal memory and initialize the backward problem. */ retval = CVodeInitB(cvode_mem, indexB, fB, TB1, yB); if (check_retval(&retval, "CVodeInitB", 1)) return(1); /* Set the scalar relative and absolute tolerances. */ retval = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); if (check_retval(&retval, "CVodeSStolerancesB", 1)) return(1); /* Attach the user data for backward problem. */ retval = CVodeSetUserDataB(cvode_mem, indexB, data); if (check_retval(&retval, "CVodeSetUserDataB", 1)) return(1); /* Call CVodeSetConstraintsB to initialize constraints */ retval = CVodeSetConstraintsB(cvode_mem, indexB, constraintsB); if(check_retval(&retval, "CVodeSetConstraintsB", 1)) return(1); N_VDestroy(constraintsB); /* Create dense SUNMatrix for use in linear solves */ AB = SUNDenseMatrix(NEQ, NEQ); if (check_retval((void *)AB, "SUNDenseMatrix", 0)) return(1); /* Create dense SUNLinearSolver object */ LSB = SUNLinSol_Dense(yB, AB); if (check_retval((void *)LSB, "SUNLinSol_Dense", 0)) return(1); /* Attach the matrix and linear solver */ retval = CVDlsSetLinearSolverB(cvode_mem, indexB, LSB, AB); if (check_retval(&retval, "CVDlsSetLinearSolverB", 1)) return(1); /* Set the user-supplied Jacobian routine JacB */ retval = CVDlsSetJacFnB(cvode_mem, indexB, JacB); if (check_retval(&retval, "CVDlsSetJacFnB", 1)) return(1); /* Call CVodeQuadInitB to allocate internal memory and initialize backward quadrature integration. */ retval = CVodeQuadInitB(cvode_mem, indexB, fQB, qB); if (check_retval(&retval, "CVodeQuadInitB", 1)) return(1); /* Call CVodeSetQuadErrCon to specify whether or not the quadrature variables are to be used in the step size control mechanism within CVODES. Call CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration tolerances for the quadrature variables. */ retval = CVodeSetQuadErrConB(cvode_mem, indexB, SUNTRUE); if (check_retval(&retval, "CVodeSetQuadErrConB", 1)) return(1); /* Call CVodeQuadSStolerancesB to specify the scalar relative and absolute tolerances for the backward problem. */ retval = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolB, abstolQB); if (check_retval(&retval, "CVodeQuadSStolerancesB", 1)) return(1); /* Backward Integration */ PrintHead(TB1); /* First get results at t = TBout1 */ /* Call CVodeB to integrate the backward ODE problem. */ retval = CVodeB(cvode_mem, TBout1, CV_NORMAL); if (check_retval(&retval, "CVodeB", 1)) return(1); /* Call CVodeGetB to get yB of the backward ODE problem. */ retval = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_retval(&retval, "CVodeGetB", 1)) return(1); /* Call CVodeGetAdjY to get the interpolated value of the forward solution y during a backward integration. */ retval = CVodeGetAdjY(cvode_mem, TBout1, y); if (check_retval(&retval, "CVodeGetAdjY", 1)) return(1); PrintOutput1(time, TBout1, y, yB); /* Then at t = T0 */ retval = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_retval(&retval, "CVodeB", 1)) return(1); CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB); printf("Done ( nst = %ld )\n", nstB); retval = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_retval(&retval, "CVodeGetB", 1)) return(1); /* Call CVodeGetQuadB to get the quadrature solution vector after a successful return from CVodeB. */ retval = CVodeGetQuadB(cvode_mem, indexB, &time, qB); if (check_retval(&retval, "CVodeGetQuadB", 1)) return(1); retval = CVodeGetAdjY(cvode_mem, T0, y); if (check_retval(&retval, "CVodeGetAdjY", 1)) return(1); PrintOutput(time, y, yB, qB); /* Reinitialize backward phase (new tB0) */ Ith(yB,1) = ZERO; Ith(yB,2) = ZERO; Ith(yB,3) = ZERO; Ith(qB,1) = ZERO; Ith(qB,2) = ZERO; Ith(qB,3) = ZERO; printf("Re-initialize CVODES memory for backward run\n"); retval = CVodeReInitB(cvode_mem, indexB, TB2, yB); if (check_retval(&retval, "CVodeReInitB", 1)) return(1); retval = CVodeQuadReInitB(cvode_mem, indexB, qB); if (check_retval(&retval, "CVodeQuadReInitB", 1)) return(1); PrintHead(TB2); /* First get results at t = TBout1 */ retval = CVodeB(cvode_mem, TBout1, CV_NORMAL); if (check_retval(&retval, "CVodeB", 1)) return(1); retval = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_retval(&retval, "CVodeGetB", 1)) return(1); retval = CVodeGetAdjY(cvode_mem, TBout1, y); if (check_retval(&retval, "CVodeGetAdjY", 1)) return(1); PrintOutput1(time, TBout1, y, yB); /* Then at t = T0 */ retval = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_retval(&retval, "CVodeB", 1)) return(1); CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB); printf("Done ( nst = %ld )\n", nstB); retval = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_retval(&retval, "CVodeGetB", 1)) return(1); retval = CVodeGetQuadB(cvode_mem, indexB, &time, qB); if (check_retval(&retval, "CVodeGetQuadB", 1)) return(1); retval = CVodeGetAdjY(cvode_mem, T0, y); if (check_retval(&retval, "CVodeGetAdjY", 1)) return(1); PrintOutput(time, y, yB, qB); /* Free memory */ printf("Free memory\n\n"); CVodeFree(&cvode_mem); N_VDestroy(y); N_VDestroy(q); N_VDestroy(yB); N_VDestroy(qB); SUNLinSolFree(LS); SUNMatDestroy(A); SUNLinSolFree(LSB); SUNMatDestroy(AB); if (ckpnt != NULL) free(ckpnt); free(data); return(0); }
int main(int argc, char *argv[]) { UserData data; void *cvode_mem; realtype reltolQ, abstolQ; N_Vector y, q; int steps; int indexB; realtype reltolB, abstolB, abstolQB; N_Vector yB, qB; realtype time; int flag, ncheck; long int nst, nstB; CVadjCheckPointRec *ckpnt; data = NULL; cvode_mem = NULL; ckpnt = NULL; y = yB = qB = NULL; /* Print problem description */ printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n"); printf("-------------------------------------------------\n\n"); printf("ODE: dy1/dt = -p1*y1 + p2*y2*y3\n"); printf(" dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2\n"); printf(" dy3/dt = p3*(y2)^2\n\n"); printf("Find dG/dp for\n"); printf(" G = int_t0^tB0 g(t,p,y) dt\n"); printf(" g(t,p,y) = y3\n\n\n"); /* User data structure */ data = (UserData) malloc(sizeof *data); if (check_flag((void *)data, "malloc", 2)) return(1); data->p[0] = RCONST(0.04); data->p[1] = RCONST(1.0e4); data->p[2] = RCONST(3.0e7); /* Initialize y */ y = N_VNew_Serial(NEQ); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); Ith(y,1) = RCONST(1.0); Ith(y,2) = ZERO; Ith(y,3) = ZERO; /* Initialize q */ q = N_VNew_Serial(1); if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1); Ith(q,1) = ZERO; /* Set the scalar realtive and absolute tolerances reltolQ and abstolQ */ reltolQ = RTOL; abstolQ = ATOLq; /* Create and allocate CVODES memory for forward run */ printf("Create and allocate CVODES memory for forward runs\n"); cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeInit(cvode_mem, f, T0, y); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeWFtolerances(cvode_mem, ewt); if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1); flag = CVodeSetUserData(cvode_mem, data); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); flag = CVDlsSetDenseJacFn(cvode_mem, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); flag = CVodeQuadInit(cvode_mem, fQ, q); if (check_flag(&flag, "CVodeQuadInit", 1)) return(1); flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ); if (check_flag(&flag, "CVodeQuadSStolerances", 1)) return(1); flag = CVodeSetQuadErrCon(cvode_mem, TRUE); if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1); /* Allocate global memory */ steps = STEPS; flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE); /* flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL); */ if (check_flag(&flag, "CVodeAdjInit", 1)) return(1); /* Perform forward run */ printf("Forward integration ... "); flag = CVodeF(cvode_mem, TOUT, y, &time, CV_NORMAL, &ncheck); if (check_flag(&flag, "CVodeF", 1)) return(1); flag = CVodeGetNumSteps(cvode_mem, &nst); if (check_flag(&flag, "CVodeGetNumSteps", 1)) return(1); printf("done ( nst = %ld )\n",nst); flag = CVodeGetQuad(cvode_mem, &time, q); if (check_flag(&flag, "CVodeGetQuad", 1)) return(1); printf("--------------------------------------------------------\n"); #if defined(SUNDIALS_EXTENDED_PRECISION) printf("G: %12.4Le \n",Ith(q,1)); #elif defined(SUNDIALS_DOUBLE_PRECISION) printf("G: %12.4le \n",Ith(q,1)); #else printf("G: %12.4e \n",Ith(q,1)); #endif printf("--------------------------------------------------------\n\n"); /* Test check point linked list (uncomment next block to print check point information) */ /* { int i; printf("\nList of Check Points (ncheck = %d)\n\n", ncheck); ckpnt = (CVadjCheckPointRec *) malloc ( (ncheck+1)*sizeof(CVadjCheckPointRec)); CVodeGetAdjCheckPointsInfo(cvode_mem, ckpnt); for (i=0;i<=ncheck;i++) { printf("Address: %p\n",ckpnt[i].my_addr); printf("Next: %p\n",ckpnt[i].next_addr); printf("Time interval: %le %le\n",ckpnt[i].t0, ckpnt[i].t1); printf("Step number: %ld\n",ckpnt[i].nstep); printf("Order: %d\n",ckpnt[i].order); printf("Step size: %le\n",ckpnt[i].step); printf("\n"); } } */ /* Initialize yB */ yB = N_VNew_Serial(NEQ); if (check_flag((void *)yB, "N_VNew_Serial", 0)) return(1); Ith(yB,1) = ZERO; Ith(yB,2) = ZERO; Ith(yB,3) = ZERO; /* Initialize qB */ qB = N_VNew_Serial(NP); if (check_flag((void *)qB, "N_VNew", 0)) return(1); Ith(qB,1) = ZERO; Ith(qB,2) = ZERO; Ith(qB,3) = ZERO; /* Set the scalar relative tolerance reltolB */ reltolB = RTOL; /* Set the scalar absolute tolerance abstolB */ abstolB = ATOLl; /* Set the scalar absolute tolerance abstolQB */ abstolQB = ATOLq; /* Create and allocate CVODES memory for backward run */ printf("Create and allocate CVODES memory for backward run\n"); flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB); if (check_flag(&flag, "CVodeCreateB", 1)) return(1); flag = CVodeInitB(cvode_mem, indexB, fB, TB1, yB); if (check_flag(&flag, "CVodeInitB", 1)) return(1); flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); if (check_flag(&flag, "CVodeSStolerancesB", 1)) return(1); flag = CVodeSetUserDataB(cvode_mem, indexB, data); if (check_flag(&flag, "CVodeSetUserDataB", 1)) return(1); flag = CVDenseB(cvode_mem, indexB, NEQ); if (check_flag(&flag, "CVDenseB", 1)) return(1); flag = CVDlsSetDenseJacFnB(cvode_mem, indexB, JacB); if (check_flag(&flag, "CVDlsSetDenseJacFnB", 1)) return(1); flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB); if (check_flag(&flag, "CVodeQuadInitB", 1)) return(1); flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolB, abstolQB); if (check_flag(&flag, "CVodeQuadSStolerancesB", 1)) return(1); flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE); if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1); /* Backward Integration */ printf("Backward integration ... "); flag = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_flag(&flag, "CVodeB", 1)) return(1); CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB); printf("done ( nst = %ld )\n", nstB); flag = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_flag(&flag, "CVodeGetB", 1)) return(1); flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB); if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1); PrintOutput(TB1, yB, qB); /* Reinitialize backward phase (new tB0) */ Ith(yB,1) = ZERO; Ith(yB,2) = ZERO; Ith(yB,3) = ZERO; Ith(qB,1) = ZERO; Ith(qB,2) = ZERO; Ith(qB,3) = ZERO; printf("Re-initialize CVODES memory for backward run\n"); flag = CVodeReInitB(cvode_mem, indexB, TB2, yB); if (check_flag(&flag, "CVodeReInitB", 1)) return(1); flag = CVodeQuadReInitB(cvode_mem, indexB, qB); if (check_flag(&flag, "CVodeQuadReInitB", 1)) return(1); printf("Backward integration ... "); flag = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_flag(&flag, "CVodeB", 1)) return(1); CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB); printf("done ( nst = %ld )\n", nstB); flag = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_flag(&flag, "CVodeGetB", 1)) return(1); flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB); if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1); PrintOutput(TB2, yB, qB); /* Free memory */ printf("Free memory\n\n"); CVodeFree(&cvode_mem); N_VDestroy_Serial(y); N_VDestroy_Serial(q); N_VDestroy_Serial(yB); N_VDestroy_Serial(qB); if (ckpnt != NULL) free(ckpnt); free(data); return(0); }
int main(int argc, char *argv[]) { ProblemData d; MPI_Comm comm; int npes, npes_needed; int myId; long int neq, l_neq; void *cvode_mem; N_Vector y, q; realtype abstol, reltol, abstolQ, reltolQ; long int mudq, mldq, mukeep, mlkeep; int indexB; N_Vector yB, qB; realtype abstolB, reltolB, abstolQB, reltolQB; long int mudqB, mldqB, mukeepB, mlkeepB; realtype tret, *qdata, G; int ncheckpnt, flag; booleantype output; /* Initialize MPI and set Ids */ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_rank(comm, &myId); /* Check number of processes */ npes_needed = NPX * NPY; #ifdef USE3D npes_needed *= NPZ; #endif MPI_Comm_size(comm, &npes); if (npes_needed != npes) { if (myId == 0) fprintf(stderr,"I need %d processes but I only got %d\n", npes_needed, npes); MPI_Abort(comm, EXIT_FAILURE); } /* Test if matlab output is requested */ if (argc > 1) output = TRUE; else output = FALSE; /* Allocate and set problem data structure */ d = (ProblemData) malloc(sizeof *d); SetData(d, comm, npes, myId, &neq, &l_neq); if (myId == 0) PrintHeader(); /*-------------------------- Forward integration phase --------------------------*/ /* Allocate space for y and set it with the I.C. */ y = N_VNew_Parallel(comm, l_neq, neq); N_VConst(ZERO, y); /* Allocate and initialize qB (local contribution to cost) */ q = N_VNew_Parallel(comm, 1, npes); N_VConst(ZERO, q); /* Create CVODES object, attach user data, and allocate space */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); flag = CVodeSetUserData(cvode_mem, d); flag = CVodeInit(cvode_mem, f, ti, y); abstol = ATOL; reltol = RTOL; flag = CVodeSStolerances(cvode_mem, reltol, abstol); /* attach linear solver */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); /* Attach preconditioner and linear solver modules */ mudq = mldq = d->l_m[0]+1; mukeep = mlkeep = 2; flag = CVBBDPrecInit(cvode_mem, l_neq, mudq, mldq, mukeep, mlkeep, ZERO, f_local, NULL); /* Initialize quadrature calculations */ abstolQ = ATOL_Q; reltolQ = RTOL_Q; flag = CVodeQuadInit(cvode_mem, fQ, q); flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ); flag = CVodeSetQuadErrCon(cvode_mem, TRUE); /* Allocate space for the adjoint calculation */ flag = CVodeAdjInit(cvode_mem, STEPS, CV_HERMITE); /* Integrate forward in time while storing check points */ if (myId == 0) printf("Begin forward integration... "); flag = CVodeF(cvode_mem, tf, y, &tret, CV_NORMAL, &ncheckpnt); if (myId == 0) printf("done. "); /* Extract quadratures */ flag = CVodeGetQuad(cvode_mem, &tret, q); qdata = NV_DATA_P(q); MPI_Allreduce(&qdata[0], &G, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm); #if defined(SUNDIALS_EXTENDED_PRECISION) if (myId == 0) printf(" G = %Le\n",G); #elif defined(SUNDIALS_DOUBLE_PRECISION) if (myId == 0) printf(" G = %e\n",G); #else if (myId == 0) printf(" G = %e\n",G); #endif /* Print statistics for forward run */ if (myId == 0) PrintFinalStats(cvode_mem); /*-------------------------- Backward integration phase --------------------------*/ /* Allocate and initialize yB */ yB = N_VNew_Parallel(comm, l_neq, neq); N_VConst(ZERO, yB); /* Allocate and initialize qB (gradient) */ qB = N_VNew_Parallel(comm, l_neq, neq); N_VConst(ZERO, qB); /* Create and allocate backward CVODE memory */ flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB); flag = CVodeSetUserDataB(cvode_mem, indexB, d); flag = CVodeInitB(cvode_mem, indexB, fB, tf, yB); abstolB = ATOL_B; reltolB = RTOL_B; flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); /* Attach preconditioner and linear solver modules */ flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0); mudqB = mldqB = d->l_m[0]+1; mukeepB = mlkeepB = 2; flag = CVBBDPrecInitB(cvode_mem, indexB, l_neq, mudqB, mldqB, mukeepB, mlkeepB, ZERO, fB_local, NULL); /* Initialize quadrature calculations */ abstolQB = ATOL_QB; reltolQB = RTOL_QB; flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB); flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolQB, abstolQB); flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE); /* Integrate backwards */ if (myId == 0) printf("Begin backward integration... "); flag = CVodeB(cvode_mem, ti, CV_NORMAL); if (myId == 0) printf("done.\n"); /* Extract solution */ flag = CVodeGetB(cvode_mem, indexB, &tret, yB); /* Extract quadratures */ flag = CVodeGetQuadB(cvode_mem, indexB, &tret, qB); /* Print statistics for backward run */ if (myId == 0) { PrintFinalStats(CVodeGetAdjCVodeBmem(cvode_mem, indexB)); } /* Process 0 collects the gradient components and prints them */ if (output) { OutputGradient(myId, qB, d); if (myId == 0) printf("Wrote matlab file 'grad.m'.\n"); } /* Free memory */ N_VDestroy_Parallel(y); N_VDestroy_Parallel(q); N_VDestroy_Parallel(qB); N_VDestroy_Parallel(yB); CVodeFree(&cvode_mem); MPI_Finalize(); return(0); }
static int PrecondB(realtype t, N_Vector c, N_Vector cB, N_Vector fcB, booleantype jok, booleantype *jcurPtr, realtype gamma, void *user_data) { int N, retval; realtype ***P; sunindextype **pivot; int i, if0, if00, ig, igx, igy, j, jj, jx, jy; int *jxr, *jyr, ngrp, ngx, ngy, mxmp; sunindextype mp, denseretval; realtype uround, fac, r, r0, save, srur; realtype *f1, *fsave, *cdata, *rewtdata; void *cvode_mem; WebData wdata; N_Vector rewt; wdata = (WebData) user_data; cvode_mem = CVodeGetAdjCVodeBmem(wdata->cvode_mem, wdata->indexB); if(check_retval((void *)cvode_mem, "CVadjGetCVodeBmem", 0)) return(1); rewt = wdata->rewt; retval = CVodeGetErrWeights(cvode_mem, rewt); if(check_retval(&retval, "CVodeGetErrWeights", 1)) return(1); cdata = N_VGetArrayPointer(c); rewtdata = N_VGetArrayPointer(rewt); uround = UNIT_ROUNDOFF; P = wdata->P; pivot = wdata->pivot; jxr = wdata->jxr; jyr = wdata->jyr; mp = wdata->mp; srur = wdata->srur; ngrp = wdata->ngrp; ngx = wdata->ngx; ngy = wdata->ngy; mxmp = wdata->mxmp; fsave = wdata->fsave; /* Make mp calls to fblock to approximate each diagonal block of Jacobian. Here, fsave contains the base value of the rate vector and r0 is a minimum increment factor for the difference quotient. */ f1 = N_VGetArrayPointer(wdata->vtemp); fac = N_VWrmsNorm (fcB, rewt); N = NEQ; r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*N*fac; if (r0 == ZERO) r0 = ONE; for (igy = 0; igy < ngy; igy++) { jy = jyr[igy]; if00 = jy*mxmp; for (igx = 0; igx < ngx; igx++) { jx = jxr[igx]; if0 = if00 + jx*mp; ig = igx + igy*ngx; /* Generate ig-th diagonal block */ for (j = 0; j < mp; j++) { /* Generate the jth column as a difference quotient */ jj = if0 + j; save = cdata[jj]; r = SUNMAX(srur*SUNRabs(save),r0/rewtdata[jj]); cdata[jj] += r; fac = gamma/r; fblock (t, cdata, jx, jy, f1, wdata); for (i = 0; i < mp; i++) { P[ig][i][j] = (f1[i] - fsave[if0+i])*fac; } cdata[jj] = save; } } } /* Add identity matrix and do LU decompositions on blocks. */ for (ig = 0; ig < ngrp; ig++) { denseAddIdentity(P[ig], mp); denseretval = denseGETRF(P[ig], mp, mp, pivot[ig]); if (denseretval != 0) return(1); } *jcurPtr = SUNTRUE; return(0); }