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); }
int main(int argc, char *argv[]) { realtype abstol=ATOL, reltol=RTOL, t; N_Vector c; WebData wdata; void *cvode_mem; int flag; void *cvadj_mem; int ncheck; realtype reltolB=RTOL, abstolB=ATOL; N_Vector cB; c = NULL; cB = NULL; wdata = NULL; cvode_mem = NULL; cvadj_mem = NULL; /* Allocate and initialize user data */ wdata = AllocUserData(); if(check_flag((void *)wdata, "AllocUserData", 2)) return(1); InitUserData(wdata); /* Set-up forward problem */ /* Initializations */ c = N_VNew_Serial(NEQ+1); if(check_flag((void *)c, "N_VNew_Serial", 0)) return(1); CInit(c, wdata); /* Call CVodeCreate/CVodeMalloc for forward run */ printf("\nCreate and allocate CVODE memory for forward run\n"); cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); wdata->cvode_memF = cvode_mem; /* Used in Precond */ flag = CVodeSetFdata(cvode_mem, wdata); if(check_flag(&flag, "CVodeSetFdata", 1)) return(1); flag = CVodeMalloc(cvode_mem, f, T0, c, CV_SS, reltol, &abstol); if(check_flag(&flag, "CVodeMalloc", 1)) return(1); /* Call CVSpgmr for forward run */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpgmrSetPreconditioner(cvode_mem, Precond, PSolve, wdata); if(check_flag(&flag, "CVSpgmrSetPreconditioner", 1)) return(1); /* Set-up adjoint calculations */ printf("\nAllocate global memory\n"); cvadj_mem = CVadjMalloc(cvode_mem, NSTEPS); if(check_flag((void *)cvadj_mem, "CVadjMalloc", 0)) return(1); wdata->cvadj_mem = cvadj_mem; /* Perform forward run */ printf("\nForward integration ... "); flag = CVodeF(cvadj_mem, TOUT, c, &t, CV_NORMAL, &ncheck); if(check_flag(&flag, "CVodeF", 1)) return(1); printf("done (ncheck = %d)\n",ncheck); #if defined(SUNDIALS_EXTENDED_PRECISION) printf("\n G = int_t int_x int_y c%d(t,x,y) dx dy dt = %Lf \n\n", ISPEC, NV_DATA_S(c)[NEQ]); #else printf("\n G = int_t int_x int_y c%d(t,x,y) dx dy dt = %f \n\n", ISPEC, NV_DATA_S(c)[NEQ]); #endif /* Set-up backward problem */ /* Allocate cB */ cB = N_VNew_Serial(NEQ); if(check_flag((void *)cB, "N_VNew_Serial", 0)) return(1); /* Initialize cB = 0 */ N_VConst(ZERO, cB); /* Create and allocate CVODES memory for backward run */ printf("\nCreate and allocate CVODES memory for backward run\n"); flag = CVodeCreateB(cvadj_mem, CV_BDF, CV_NEWTON); if(check_flag(&flag, "CVodeCreateB", 1)) return(1); flag = CVodeSetFdataB(cvadj_mem, wdata); if(check_flag(&flag, "CVodeSetFdataB", 1)) return(1); flag = CVodeMallocB(cvadj_mem, fB, TOUT, cB, CV_SS, reltolB, &abstolB); if(check_flag(&flag, "CVodeMallocB", 1)) return(1); /* Call CVSpgmr */ flag = CVSpgmrB(cvadj_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmrB", 1)) return(1); flag = CVSpgmrSetPreconditionerB(cvadj_mem, PrecondB, PSolveB, wdata); if(check_flag(&flag, "CVSpgmrSetPreconditionerB", 1)) return(1); /* Perform backward integration */ printf("\nBackward integration\n"); flag = CVodeB(cvadj_mem, T0, cB, &t, CV_NORMAL); if(check_flag(&flag, "CVodeB", 1)) return(1); PrintOutput(cB, NS, MXNS, wdata); /* Free all memory */ CVodeFree(cvode_mem); CVadjFree(cvadj_mem); N_VDestroy_Serial(c); N_VDestroy_Serial(cB); FreeUserData(wdata); return(0); }