int calculate_abundances_(realtype *abundance, realtype *rate, realtype *density, realtype *temperature, int *npart, int *nspec, int *nreac) { int neq = *nspec-1; /* Number of ODEs in the system */ realtype t0, t, tout; /* Initial, current and output times */ realtype *data; /* Array pointer to access data stored in vectors*/ N_Vector y; /* Vector of dependent variables that CVODE is to solve */ User_Data user_data; /* Data to be passed to the solver routines */ FILE *cvoderr; /* Log file for CVODE error messages */ void *cvode_mem; /* Memory allocated to the CVODE solver */ long int mxstep; /* Maximum number of internal steps */ int flag, status, nfails; /* CVODE return flag, status and failure counter */ /* Define the necessary external variables contained within the Fortran module CHEMISTRY_MODULE */ extern realtype chemistry_module_mp_relative_abundance_tolerance_ ; /* Relative error tolerance */ extern realtype chemistry_module_mp_absolute_abundance_tolerance_ ; /* Absolute error tolerance */ /* Define the necessary external variables contained within the Fortran module GLOBAL_MODULE */ extern realtype global_module_mp_start_time_; /* Start time for the chemical evolution (yr) */ extern realtype global_module_mp_end_time_; /* End time for the chemical evolution (yr) */ extern int global_module_mp_nelect_; /* Species index number for electron */ realtype reltol = chemistry_module_mp_relative_abundance_tolerance_; realtype abstol = chemistry_module_mp_absolute_abundance_tolerance_; realtype start_time = global_module_mp_start_time_; realtype end_time = global_module_mp_end_time_; realtype seconds_in_year = RCONST(3.1556926e7); /* Convert from years to seconds */ int nelect = global_module_mp_nelect_-1; double cpu_start, cpu_end; /* CPU times */ #ifdef OPENMP int nthread, thread; /* Number of threads and current thread number */ #endif int n, i; /* Open the error log files */ stderr = fopen("main.log", "a"); cvoderr = fopen("cvode.log", "a"); /* Specify the maximum number of internal steps */ mxstep = 10000000; /* Initialize the global status flag */ status = 0; #ifdef OPENMP cpu_start = omp_get_wtime(); #else cpu_start = clock(); #endif #pragma omp parallel for default(none) schedule(dynamic) \ shared(npart, nspec, nreac, nelect, nthread, abundance, rate, density, temperature) \ shared(neq, start_time, end_time, reltol, abstol, mxstep, status, cvoderr, stderr) \ shared(seconds_in_year) \ private(i, t0, tout, t, y, data, user_data, cvode_mem, flag, nfails) for (n = 0; n < *npart; n++) { /* Store the number of threads being used */ #ifdef OPENMP if (n == 0) nthread = omp_get_num_threads(); #endif /* Reset the integration failure counter */ nfails = 0; /* Specify the start and end time of the integration (in seconds) */ t0 = start_time*seconds_in_year; tout = end_time*seconds_in_year; /* Create a serial vector of length NEQ to contain the abundances */ y = NULL; y = N_VNew_Serial(neq); if (check_flag((void *)y, "N_VNew_Serial", 0)) status = 1; /* Initialize y from the abundance array */ data = NV_DATA_S(y); for (i = 0; i < neq; i++) { #ifdef LOG_ODES if (abundance[n*(*nspec)+i] > 0) data[i] = log(abundance[n*(*nspec)+i]); else data[i] = log(abstol*abstol); #else data[i] = abundance[n*(*nspec)+i]; #endif } /* Create and allocate memory to user_data to contain the rates */ user_data = NULL; user_data = (User_Data) malloc(sizeof *user_data); if(check_flag((void *)user_data, "malloc", 2)) status = 1; /* Initialize user_data with the array of reaction rate coefficients, * the total number density, gas temperature and electron abundance */ user_data->rate = &rate[n*(*nreac)]; user_data->n_H = density[n]; user_data->T_g = temperature[n]; user_data->x_e = abundance[n*(*nspec)+nelect]; /* Call CVodeCreate to create the solver memory and specify the * use of Backward Differentiation Formula and Newton iteration */ cvode_mem = NULL; cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) status = 1; /* Call CVodeSetErrFile to direct all error messages to the log file */ flag = CVodeSetErrFile(cvode_mem, cvoderr); if (check_flag(&flag, "CVodeSetErrFile", 1)) status = 1; /* Call CVodeInit to initialize the integrator memory and specify the * right hand side function in ydot = f(t,y), the inital time t0, and * the initial dependent variable vector y */ flag = CVodeInit(cvode_mem, f, t0, y); if (check_flag(&flag, "CVodeInit", 1)) status = 1; /* Call CVodeSStolerances to set the relative and absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) status = 1; /* Call CVodeSetMaxNumSteps to set the maximum number of steps */ flag = CVodeSetMaxNumSteps(cvode_mem, mxstep); if (check_flag(&flag, "CVodeSetMaxNumSteps", 1)) status = 1; /* Specify the user-defined data to be passed to the various routines */ flag = CVodeSetUserData(cvode_mem, user_data); if (check_flag(&flag, "CVodeSetUserData", 1)) status = 1; /* Specify that the CVDense direct dense linear solver is to be used */ flag = CVDense(cvode_mem, neq); if (check_flag(&flag, "CVDense", 1)) status = 1; /* Specify that a user-supplied Jacobian routine (Jac) is to be used */ /* flag = CVDlsSetDenseJacFn(cvode_mem, Jac); */ /* if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) status = 1; */ tout = 1.0e-4*seconds_in_year; do { /* Call CVode, check the return status and loop until the end time is reached */ flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL); #pragma omp critical (status) if (flag == 0) { if (nfails > 0) { fprintf(cvoderr, "Call to CVODE successful: particle = %d, t = %8.2le yr, # steps = %ld\n\n", n, t/seconds_in_year, mxstep); } } else { nfails++; if (flag == -1) { if (nfails < 5) { fprintf(cvoderr, " Particle %d: Doubling mxstep and continuing the integration.\n\n", n); flag = CVodeSetMaxNumSteps(cvode_mem, mxstep); if (check_flag(&flag, "CVodeSetMaxNumSteps", 1)) status = 1; } else { fprintf(stderr, " WARNING! CVODE solver failed: flag = %d\n", flag); fprintf(cvoderr, "ERROR! Fifth failure - aborting integration\n\n"); fprintf(cvoderr, "-----------------------------------------------\n"); fprintf(cvoderr, "CVODE Parameters:\n\n"); fprintf(cvoderr, "Particle %d\n\n", n); fprintf(cvoderr, "Before:\n"); fprintf(cvoderr, "flag = %d\n", 0); fprintf(cvoderr, "t = %8.2le yr\n", start_time); fprintf(cvoderr, "tout = %8.2le yr\n", end_time); fprintf(cvoderr, "dt = %8.2le yr\n\n", end_time-start_time); fprintf(cvoderr, "After:\n"); fprintf(cvoderr, "flag = %d\n", flag); fprintf(cvoderr, "t = %8.2le yr\n", t/seconds_in_year); fprintf(cvoderr, "tout = %8.2le yr\n", tout/seconds_in_year); fprintf(cvoderr, "dt = %8.2le yr\n", (tout-t)/seconds_in_year); fprintf(cvoderr, "-----------------------------------------------\n\n"); status = flag; } } else if (flag == -4) { if (nfails < 5) { fprintf(cvoderr, " Particle %d: Attempting to continue the integration using the same parameters.\n\n", n); } else { fprintf(stderr, " WARNING! CVODE solver failed: flag = %d\n", flag); fprintf(cvoderr, "ERROR! Fifth failure - aborting integration\n\n"); fprintf(cvoderr, "-----------------------------------------------\n"); fprintf(cvoderr, "CVODE Parameters:\n\n"); fprintf(cvoderr, "Particle %d\n\n", n); fprintf(cvoderr, "Before:\n"); fprintf(cvoderr, "flag = %d\n", 0); fprintf(cvoderr, "t = %8.2le yr\n", start_time); fprintf(cvoderr, "tout = %8.2le yr\n", end_time); fprintf(cvoderr, "dt = %8.2le yr\n\n", end_time-start_time); fprintf(cvoderr, "After:\n"); fprintf(cvoderr, "flag = %d\n", flag); fprintf(cvoderr, "t = %8.2le yr\n", t/seconds_in_year); fprintf(cvoderr, "tout = %8.2le yr\n", tout/seconds_in_year); fprintf(cvoderr, "dt = %8.2le yr\n", (tout-t)/seconds_in_year); fprintf(cvoderr, "-----------------------------------------------\n\n"); status = flag; } } else { fprintf(stderr, " WARNING! CVODE solver failed: flag = %d\n", flag); fprintf(cvoderr, "ERROR! CVODE failed with the following parameters:\n\n"); fprintf(cvoderr, "-----------------------------------------------\n"); fprintf(cvoderr, "CVODE Parameters:\n\n"); fprintf(cvoderr, "Particle %d\n\n", n); fprintf(cvoderr, "Before:\n"); fprintf(cvoderr, "flag = %d\n", 0); fprintf(cvoderr, "t = %8.2le yr\n", start_time); fprintf(cvoderr, "tout = %8.2le yr\n", end_time); fprintf(cvoderr, "dt = %8.2le yr\n\n", end_time-start_time); fprintf(cvoderr, "After:\n"); fprintf(cvoderr, "flag = %d\n", flag); fprintf(cvoderr, "t = %8.2le yr\n", t/seconds_in_year); fprintf(cvoderr, "tout = %8.2le yr\n", tout/seconds_in_year); fprintf(cvoderr, "dt = %8.2le yr\n", (tout-t)/seconds_in_year); fprintf(cvoderr, "-----------------------------------------------\n\n"); status = flag; nfails = 5; } } tout = tout*10; if (tout > end_time*seconds_in_year) tout = end_time*seconds_in_year; } while (t < tout && nfails < 5); /* Store the output values in the abundance array */ data = NV_DATA_S(y); for (i = 0; i < neq; i++) { #ifdef LOG_ODES abundance[n*(*nspec)+i] = exp(data[i]); #else abundance[n*(*nspec)+i] = data[i]; #endif if(abundance[n*(*nspec)+i] < abstol) abundance[n*(*nspec)+i] = 0; } abundance[n*(*nspec)+nelect] = user_data->x_e; /* Free y vector memory allocation */ N_VDestroy_Serial(y); /* Free user_data memory allocation */ free(user_data); /* Free integrator memory allocation */ CVodeFree(&cvode_mem); } /* End of for-loop over particles */ #ifdef OPENMP cpu_end = omp_get_wtime(); #else cpu_end = clock(); #endif /* Close the error log files */ fclose(cvoderr); fclose(stderr); if (status != 0) { fprintf(stdout, "\n ERROR! Calculation of abundances failed with status = %d\n\n", status); #ifdef DEBUG fprintf(stdout, " Elapsed time = %0.3f seconds\n", cpu_end-cpu_start); #ifdef OPENMP fprintf(stdout, " Threads used = %d (maximum %d)\n\n", nthread, omp_get_max_threads()); #endif #endif } else { #ifdef DEBUG fprintf(stdout, " --> Elapsed time = %0.3f seconds\n", cpu_end-cpu_start); #ifdef OPENMP fprintf(stdout, " --> Threads used = %d (maximum %d)\n", nthread, omp_get_max_threads()); #endif #endif } return(status); }
void SundialsCvode::initialize() { int flag = 0; if (_initialized) { // Starting over with a new IC, but the same ODE flag = CVodeReInit(sundialsMem, t0, y.forSundials()); if (check_flag(&flag, "CVodeReInit", 1)) { throw DebugException("SundialsCvode::reInitialize: error in CVodeReInit"); } CVodeSetMaxNumSteps(sundialsMem, maxNumSteps); CVodeSetMinStep(sundialsMem, minStep); return; } // On the first call to initialize, need to allocate and set up // the Sundials solver, set tolerances and link the ODE functions sundialsMem = CVodeCreate(linearMultistepMethod, nonlinearSolverMethod); if (check_flag((void *)sundialsMem, "CVodeCreate", 0)) { throw DebugException("SundialsCvode::initialize: error in CVodeCreate"); } flag = CVodeInit(sundialsMem, f, t0, y.forSundials()); if (check_flag(&flag, "CVodeMalloc", 1)) { throw DebugException("SundialsCvode::initialize: error in CVodeMalloc"); } CVodeSVtolerances(sundialsMem, reltol, abstol.forSundials()); CVodeSetUserData(sundialsMem, theODE); CVodeSetMaxNumSteps(sundialsMem, maxNumSteps); CVodeSetMinStep(sundialsMem, minStep); if (findRoots) { rootsFound.resize(nRoots); // Call CVodeRootInit to specify the root function g with nRoots components flag = CVodeRootInit(sundialsMem, nRoots, g); if (check_flag(&flag, "CVodeRootInit", 1)) { throw DebugException("SundialsCvode::initialize: error in CVodeRootInit"); } } if (bandwidth_upper == -1 && bandwidth_lower == -1) { // Call CVDense to specify the CVDENSE dense linear solver flag = CVDense(sundialsMem, nEq); if (check_flag(&flag, "CVDense", 1)) { throw DebugException("SundialsCvode::initialize: error in CVDense"); } // Set the Jacobian routine to denseJac (user-supplied) flag = CVDlsSetDenseJacFn(sundialsMem, denseJac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) { throw DebugException("SundialsCvode::initialize: error in CVDlsSetDenseJacFn"); } } else { // Call CVDense to specify the CVBAND Banded linear solver flag = CVBand(sundialsMem, nEq, bandwidth_upper, bandwidth_lower); if (check_flag(&flag, "CVBand", 1)) { throw DebugException("SundialsCvode::initialize: error in CVBand"); } // Set the Jacobian routine to bandJac (user-supplied) flag = CVDlsSetBandJacFn(sundialsMem, bandJac); if (check_flag(&flag, "CVDlsSetBandJacFn", 1)) { throw DebugException("SundialsCvode::initialize: error in CVDlsSetBandJacFn"); } } _initialized = true; }
int main(int argc, char *argv[]) { realtype dx, reltol, abstol, t, tout, umax; N_Vector u; UserData data; void *cvode_mem; int iout, flag, my_pe, npes; long int local_N, nperpe, nrem, my_base, nst; MPI_Comm comm; u = NULL; data = NULL; cvode_mem = NULL; /* Get processor number, total number of pe's, and my_pe. */ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &npes); MPI_Comm_rank(comm, &my_pe); /* Set local vector length. */ nperpe = NEQ/npes; nrem = NEQ - npes*nperpe; local_N = (my_pe < nrem) ? nperpe+1 : nperpe; my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem; data = (UserData) malloc(sizeof *data); /* Allocate data memory */ if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1); data->comm = comm; data->npes = npes; data->my_pe = my_pe; u = N_VNew_Parallel(comm, local_N, NEQ); /* Allocate u vector */ if(check_flag((void *)u, "N_VNew", 0, my_pe)) MPI_Abort(comm, 1); reltol = ZERO; /* Set the tolerances */ abstol = ATOL; dx = data->dx = XMAX/((realtype)(MX+1)); /* Set grid coefficients in data */ data->hdcoef = RCONST(1.0)/(dx*dx); data->hacoef = RCONST(0.5)/(RCONST(2.0)*dx); SetIC(u, dx, local_N, my_base); /* Initialize u vector */ /* Call CVodeCreate to create the solver memory and specify the * Adams-Moulton LMM and the use of a functional iteration */ cvode_mem = CVodeCreate(CV_ADAMS, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1); flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1, my_pe)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1); flag = CVDiag(cvode_mem); if (check_flag(&flag, "CVDiag", 1, my_pe)) return(1); if (my_pe == 0) PrintIntro(npes); umax = N_VMaxNorm(u); if (my_pe == 0) { t = T0; PrintData(t, umax, 0); } /* In loop over output points, call CVode, print results, test for error */ for (iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1, my_pe)) break; umax = N_VMaxNorm(u); flag = CVodeGetNumSteps(cvode_mem, &nst); check_flag(&flag, "CVodeGetNumSteps", 1, my_pe); if (my_pe == 0) PrintData(t, umax, nst); } if (my_pe == 0) PrintFinalStats(cvode_mem); /* Print some final statistics */ N_VDestroy_Parallel(u); /* Free the u vector */ CVodeFree(&cvode_mem); /* Free the integrator memory */ free(data); /* Free user data */ MPI_Finalize(); return(0); }
int Solver::init(rhsfunc f, int argc, char **argv, bool restarting, int nout, real tstep) { #ifdef CHECK int msg_point = msg_stack.push("Initialising CVODE solver"); #endif /// Call the generic initialisation first if(GenericSolver::init(f, argc, argv, restarting, nout, tstep)) return 1; // Save nout and tstep for use in run NOUT = nout; TIMESTEP = tstep; output.write("Initialising SUNDIALS' CVODE solver\n"); // Set the rhs solver function func = f; // Calculate number of variables (in generic_solver) int local_N = getLocalN(); // Get total problem size int neq; if(MPI_Allreduce(&local_N, &neq, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD)) { output.write("\tERROR: MPI_Allreduce failed!\n"); return 1; } output.write("\t3d fields = %d, 2d fields = %d neq=%d, local_N=%d\n", n3Dvars(), n2Dvars(), neq, local_N); // Allocate memory if((uvec = N_VNew_Parallel(MPI_COMM_WORLD, local_N, neq)) == NULL) bout_error("ERROR: SUNDIALS memory allocation failed\n"); // Put the variables into uvec if(save_vars(NV_DATA_P(uvec))) bout_error("\tERROR: Initial variable value not set\n"); /// Get options real abstol, reltol; int maxl; int mudq, mldq; int mukeep, mlkeep; bool use_precon, use_jacobian; real max_timestep; bool adams_moulton, func_iter; // Time-integration method options.setSection("solver"); options.get("mudq", mudq, n3Dvars()*(MXSUB+2)); options.get("mldq", mldq, n3Dvars()*(MXSUB+2)); options.get("mukeep", mukeep, n3Dvars()+n2Dvars()); options.get("mlkeep", mlkeep, n3Dvars()+n2Dvars()); options.get("ATOL", abstol, 1.0e-12); options.get("RTOL", reltol, 1.0e-5); options.get("maxl", maxl, 5); options.get("use_precon", use_precon, false); options.get("use_jacobian", use_jacobian, false); options.get("max_timestep", max_timestep, -1.); int mxsteps; // Maximum number of steps to take between outputs options.get("pvode_mxstep", mxsteps, 500); options.get("adams_moulton", adams_moulton, false); int lmm = CV_BDF; if(adams_moulton) { // By default use functional iteration for Adams-Moulton lmm = CV_ADAMS; output.write("\tUsing Adams-Moulton implicit multistep method\n"); options.get("func_iter", func_iter, true); }else { output.write("\tUsing BDF method\n"); // Use Newton iteration for BDF options.get("func_iter", func_iter, false); } int iter = CV_NEWTON; if(func_iter) iter = CV_FUNCTIONAL; // Call CVodeCreate if((cvode_mem = CVodeCreate(lmm, iter)) == NULL) bout_error("ERROR: CVodeCreate failed\n"); if( CVodeSetUserData(cvode_mem, this) < 0 ) // For callbacks, need pointer to solver object bout_error("ERROR: CVodeSetUserData failed\n"); if( CVodeInit(cvode_mem, cvode_rhs, simtime, uvec) < 0 ) bout_error("ERROR: CVodeInit failed\n"); if( CVodeSStolerances(cvode_mem, reltol, abstol) < 0 ) bout_error("ERROR: CVodeSStolerances failed\n"); CVodeSetMaxNumSteps(cvode_mem, mxsteps); if(max_timestep > 0.0) { // Setting a maximum timestep CVodeSetMaxStep(cvode_mem, max_timestep); } /// Newton method can include Preconditioners and Jacobian function if(!func_iter) { output.write("\tUsing Newton iteration\n"); /// Set Preconditioner if(use_precon) { if( CVSpgmr(cvode_mem, PREC_LEFT, maxl) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpgmr failed\n"); if(prefunc == NULL) { output.write("\tUsing BBD preconditioner\n"); if( CVBBDPrecInit(cvode_mem, local_N, mudq, mldq, mukeep, mlkeep, ZERO, cvode_bbd_rhs, NULL) ) bout_error("ERROR: CVBBDPrecInit failed\n"); }else { output.write("\tUsing user-supplied preconditioner\n"); if( CVSpilsSetPreconditioner(cvode_mem, NULL, cvode_pre) ) bout_error("ERROR: CVSpilsSetPreconditioner failed\n"); } }else { // Not using preconditioning output.write("\tNo preconditioning\n"); if( CVSpgmr(cvode_mem, PREC_NONE, maxl) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpgmr failed\n"); } /// Set Jacobian-vector multiplication function if((use_jacobian) && (jacfunc != NULL)) { output.write("\tUsing user-supplied Jacobian function\n"); if( CVSpilsSetJacTimesVecFn(cvode_mem, cvode_jac) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpilsSetJacTimesVecFn failed\n"); }else output.write("\tUsing difference quotient approximation for Jacobian\n"); }else { output.write("\tUsing Functional iteration\n"); } #ifdef CHECK msg_stack.pop(msg_point); #endif return(0); }
void CvodeSolver::initialize(const double &pVoiStart, const int &pRatesStatesCount, double *pConstants, double *pRates, double *pStates, double *pAlgebraic, ComputeRatesFunction pComputeRates) { if (!mSolver) { // Retrieve some of the CVODE properties double maximumStep = MaximumStepDefaultValue; int maximumNumberOfSteps = MaximumNumberOfStepsDefaultValue; QString integrationMethod = IntegrationMethodDefaultValue; QString iterationType = IterationTypeDefaultValue; QString linearSolver = LinearSolverDefaultValue; QString preconditioner = PreconditionerDefaultValue; int upperHalfBandwidth = UpperHalfBandwidthDefaultValue; int lowerHalfBandwidth = LowerHalfBandwidthDefaultValue; double relativeTolerance = RelativeToleranceDefaultValue; double absoluteTolerance = AbsoluteToleranceDefaultValue; if (mProperties.contains(MaximumStepId)) { maximumStep = mProperties.value(MaximumStepId).toDouble(); } else { emit error(QObject::tr("the 'maximum step' property value could not be retrieved")); return; } if (mProperties.contains(MaximumNumberOfStepsId)) { maximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsId).toInt(); } else { emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved")); return; } if (mProperties.contains(IntegrationMethodId)) { integrationMethod = mProperties.value(IntegrationMethodId).toString(); } else { emit error(QObject::tr("the 'integration method' property value could not be retrieved")); return; } if (mProperties.contains(IterationTypeId)) { iterationType = mProperties.value(IterationTypeId).toString(); if (!iterationType.compare(NewtonIteration)) { // We are dealing with a Newton iteration, so retrieve and check // its linear solver if (mProperties.contains(LinearSolverId)) { linearSolver = mProperties.value(LinearSolverId).toString(); bool needUpperAndLowerHalfBandwidths = false; if ( !linearSolver.compare(DenseLinearSolver) || !linearSolver.compare(DiagonalLinearSolver)) { // We are dealing with a dense/diagonal linear solver, // so nothing more to do } else if (!linearSolver.compare(BandedLinearSolver)) { // We are dealing with a banded linear solver, so we // need both an upper and a lower half bandwidth needUpperAndLowerHalfBandwidths = true; } else { // We are dealing with a GMRES/Bi-CGStab/TFQMR linear // solver, so retrieve and check its preconditioner if (mProperties.contains(PreconditionerId)) { preconditioner = mProperties.value(PreconditionerId).toString(); } else { emit error(QObject::tr("the 'preconditioner' property value could not be retrieved")); return; } if (!preconditioner.compare(BandedPreconditioner)) { // We are dealing with a banded preconditioner, so // we need both an upper and a lower half bandwidth needUpperAndLowerHalfBandwidths = true; } } if (needUpperAndLowerHalfBandwidths) { if (mProperties.contains(UpperHalfBandwidthId)) { upperHalfBandwidth = mProperties.value(UpperHalfBandwidthId).toInt(); if ( (upperHalfBandwidth < 0) || (upperHalfBandwidth >= pRatesStatesCount)) { emit error(QObject::tr("the 'upper half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1)); return; } } else { emit error(QObject::tr("the 'upper half-bandwidth' property value could not be retrieved")); return; } if (mProperties.contains(LowerHalfBandwidthId)) { lowerHalfBandwidth = mProperties.value(LowerHalfBandwidthId).toInt(); if ( (lowerHalfBandwidth < 0) || (lowerHalfBandwidth >= pRatesStatesCount)) { emit error(QObject::tr("the 'lower half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1)); return; } } else { emit error(QObject::tr("the 'lower half-bandwidth' property value could not be retrieved")); return; } } } else { emit error(QObject::tr("the 'linear solver' property value could not be retrieved")); return; } } } else { emit error(QObject::tr("the 'iteration type' property value could not be retrieved")); return; } if (mProperties.contains(RelativeToleranceId)) { relativeTolerance = mProperties.value(RelativeToleranceId).toDouble(); if (relativeTolerance < 0) { emit error(QObject::tr("the 'relative tolerance' property must have a value greater than or equal to 0")); return; } } else { emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved")); return; } if (mProperties.contains(AbsoluteToleranceId)) { absoluteTolerance = mProperties.value(AbsoluteToleranceId).toDouble(); if (absoluteTolerance < 0) { emit error(QObject::tr("the 'absolute tolerance' property must have a value greater than or equal to 0")); return; } } else { emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved")); return; } if (mProperties.contains(InterpolateSolutionId)) { mInterpolateSolution = mProperties.value(InterpolateSolutionId).toBool(); } else { emit error(QObject::tr("the 'interpolate solution' property value could not be retrieved")); return; } // Initialise the ODE solver itself OpenCOR::CoreSolver::CoreOdeSolver::initialize(pVoiStart, pRatesStatesCount, pConstants, pRates, pStates, pAlgebraic, pComputeRates); // Create the states vector mStatesVector = N_VMake_Serial(pRatesStatesCount, pStates); // Create the CVODE solver bool newtonIteration = !iterationType.compare(NewtonIteration); mSolver = CVodeCreate(!integrationMethod.compare(BdfMethod)?CV_BDF:CV_ADAMS, newtonIteration?CV_NEWTON:CV_FUNCTIONAL); // Use our own error handler CVodeSetErrHandlerFn(mSolver, errorHandler, this); // Initialise the CVODE solver CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector); // Set some user data mUserData = new CvodeSolverUserData(pConstants, pAlgebraic, pComputeRates); CVodeSetUserData(mSolver, mUserData); // Set the maximum step CVodeSetMaxStep(mSolver, maximumStep); // Set the maximum number of steps CVodeSetMaxNumSteps(mSolver, maximumNumberOfSteps); // Set the linear solver, if needed if (newtonIteration) { if (!linearSolver.compare(DenseLinearSolver)) { CVDense(mSolver, pRatesStatesCount); } else if (!linearSolver.compare(BandedLinearSolver)) { CVBand(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth); } else if (!linearSolver.compare(DiagonalLinearSolver)) { CVDiag(mSolver); } else { // We are dealing with a GMRES/Bi-CGStab/TFQMR linear solver if (!preconditioner.compare(BandedPreconditioner)) { if (!linearSolver.compare(GmresLinearSolver)) CVSpgmr(mSolver, PREC_LEFT, 0); else if (!linearSolver.compare(BiCgStabLinearSolver)) CVSpbcg(mSolver, PREC_LEFT, 0); else CVSptfqmr(mSolver, PREC_LEFT, 0); CVBandPrecInit(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth); } else { if (!linearSolver.compare(GmresLinearSolver)) CVSpgmr(mSolver, PREC_NONE, 0); else if (!linearSolver.compare(BiCgStabLinearSolver)) CVSpbcg(mSolver, PREC_NONE, 0); else CVSptfqmr(mSolver, PREC_NONE, 0); } } } // Set the relative and absolute tolerances CVodeSStolerances(mSolver, relativeTolerance, absoluteTolerance); } else { // Reinitialise the CVODE object CVodeReInit(mSolver, pVoiStart, mStatesVector); } }
/** \brief Call the ODE solver. * * \param neq The number of equations. * \param x_f A pointer to a vector of \c neq variables, giving the * initial state vector on entry and the final state vector on exit. * \param abstol_f A pointer to a vector of \c neq variables, giving * the absolute error tolerance for the corresponding state vector * component. * \param reltol_f The scalar relative tolerance. * \param t_initial_f The initial time (s). * \param t_final_f The final time (s). * \return A result code (0 is success). */ int condense_solver(int neq, double *x_f, double *abstol_f, double reltol_f, double t_initial_f, double t_final_f) { realtype reltol, t_initial, t_final, t, tout; N_Vector y, abstol; void *cvode_mem; CVodeMem cv_mem; int flag, i, pretype, maxl; realtype *y_data, *abstol_data; y = abstol = NULL; cvode_mem = NULL; y = N_VNew_Serial(neq); if (condense_check_flag((void *)y, "N_VNew_Serial", 0)) return PMC_CONDENSE_SOLVER_INIT_Y; abstol = N_VNew_Serial(neq); if (condense_check_flag((void *)abstol, "N_VNew_Serial", 0)) return PMC_CONDENSE_SOLVER_INIT_ABSTOL; y_data = NV_DATA_S(y); abstol_data = NV_DATA_S(abstol); for (i = 0; i < neq; i++) { y_data[i] = x_f[i]; abstol_data[i] = abstol_f[i]; } reltol = reltol_f; t_initial = t_initial_f; t_final = t_final_f; cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (condense_check_flag((void *)cvode_mem, "CVodeCreate", 0)) return PMC_CONDENSE_SOLVER_INIT_CVODE_MEM; flag = CVodeInit(cvode_mem, condense_vf, t_initial, y); if (condense_check_flag(&flag, "CVodeInit", 1)) return PMC_CONDENSE_SOLVER_INIT_CVODE; flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (condense_check_flag(&flag, "CVodeSVtolerances", 1)) return PMC_CONDENSE_SOLVER_SVTOL; flag = CVodeSetMaxNumSteps(cvode_mem, 100000); if (condense_check_flag(&flag, "CVodeSetMaxNumSteps", 1)) return PMC_CONDENSE_SOLVER_SET_MAX_STEPS; /*******************************************************/ // dense solver //flag = CVDense(cvode_mem, neq); //if (condense_check_flag(&flag, "CVDense", 1)) return(1); /*******************************************************/ /*******************************************************/ // iterative solver //pretype = PREC_LEFT; //maxl = 0; //flag = CVSptfqmr(cvode_mem, pretype, maxl); //if (condense_check_flag(&flag, "CVSptfqmr", 1)) return(1); //flag = CVSpilsSetJacTimesVecFn(cvode_mem, condense_jtimes); //if (condense_check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1); //flag = CVSpilsSetPreconditioner(cvode_mem, NULL, condense_prec); //if (condense_check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /*******************************************************/ /*******************************************************/ // explicit solver cv_mem = (CVodeMem)cvode_mem; cv_mem->cv_linit = condense_solver_Init; cv_mem->cv_lsetup = condense_solver_Setup; cv_mem->cv_lsolve = condense_solver_Solve; cv_mem->cv_lfree = condense_solver_Free; /*******************************************************/ t = t_initial; flag = CVode(cvode_mem, t_final, y, &t, CV_NORMAL); if (condense_check_flag(&flag, "CVode", 1)) return PMC_CONDENSE_SOLVER_FAIL; for (i = 0; i < neq; i++) { x_f[i] = y_data[i]; } N_VDestroy_Serial(y); N_VDestroy_Serial(abstol); CVodeFree(&cvode_mem); return PMC_CONDENSE_SOLVER_SUCCESS; }
PetscErrorCode TSSetUp_Sundials(TS ts) { TS_Sundials *cvode = (TS_Sundials*)ts->data; PetscErrorCode ierr; PetscInt glosize,locsize,i,flag; PetscScalar *y_data,*parray; void *mem; PC pc; PCType pctype; PetscBool pcnone; PetscFunctionBegin; /* get the vector size */ ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr); ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr); /* allocate the memory for N_Vec y */ cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize); if (!cvode->y) SETERRQ(PETSC_COMM_SELF,1,"cvode->y is not allocated"); /* initialize N_Vec y: copy ts->vec_sol to cvode->y */ ierr = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr); y_data = (PetscScalar*) N_VGetArrayPointer(cvode->y); for (i = 0; i < locsize; i++) y_data[i] = parray[i]; ierr = VecRestoreArray(ts->vec_sol,NULL);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->ydot);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->update);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->ydot);CHKERRQ(ierr); /* Create work vectors for the TSPSolve_Sundials() routine. Note these are allocated with zero space arrays because the actual array space is provided by Sundials and set using VecPlaceArray(). */ ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr); ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w1);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w2);CHKERRQ(ierr); /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */ mem = CVodeCreate(cvode->cvode_type, CV_NEWTON); if (!mem) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"CVodeCreate() fails"); cvode->mem = mem; /* Set the pointer to user-defined data */ flag = CVodeSetUserData(mem, ts); if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetUserData() fails"); /* Sundials may choose to use a smaller initial step, but will never use a larger step. */ flag = CVodeSetInitStep(mem,(realtype)ts->time_step); if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetInitStep() failed"); if (cvode->mindt > 0) { flag = CVodeSetMinStep(mem,(realtype)cvode->mindt); if (flag) { if (flag == CV_MEM_NULL) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, cvode_mem pointer is NULL"); else if (flag == CV_ILL_INPUT) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, hmin is nonpositive or it exceeds the maximum allowable step size"); else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed"); } } if (cvode->maxdt > 0) { flag = CVodeSetMaxStep(mem,(realtype)cvode->maxdt); if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMaxStep() failed"); } /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector cvode->y */ flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag); /* specifies scalar relative and absolute tolerances */ flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag); /* Specify max num of steps to be taken by cvode in its attempt to reach the next output time */ flag = CVodeSetMaxNumSteps(mem,ts->max_steps); /* call CVSpgmr to use GMRES as the linear solver. */ /* setup the ode integrator with the given preconditioner */ ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr); ierr = PCGetType(pc,&pctype);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)pc,PCNONE,&pcnone);CHKERRQ(ierr); if (pcnone) { flag = CVSpgmr(mem,PREC_NONE,0); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); } else { flag = CVSpgmr(mem,PREC_LEFT,cvode->maxl); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); /* Set preconditioner and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpilsSetPreconditioner() fails, flag %d", flag); } flag = CVSpilsSetGSType(mem, MODIFIED_GS); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmrSetGSType() fails, flag %d",flag); PetscFunctionReturn(0); }
int main(int argc, char *argv[]) { void *cvode_mem; UserData data; realtype abstol, reltol, t, tout; N_Vector y; int iout, flag; realtype *pbar; int is, *plist; N_Vector *uS; booleantype sensi, err_con; int sensi_meth; pbar = NULL; plist = NULL; uS = NULL; y = NULL; data = NULL; cvode_mem = NULL; /* Process arguments */ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con); /* Problem parameters */ data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); /* Initial states */ y = N_VNew_Serial(NEQ); if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1); SetInitialProfiles(y, data->dx, data->dz); /* Tolerances */ abstol=ATOL; reltol=RTOL; /* Create CVODES object */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSetMaxNumSteps(cvode_mem, 2000); if(check_flag(&flag, "CVodeSetMaxNumSteps", 1)) return(1); /* Allocate CVODES memory */ flag = CVodeInit(cvode_mem, f, T0, y); if(check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSStolerances(cvode_mem, reltol, abstol); if(check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* Attach CVSPGMR linear solver */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); printf("\n2-species diurnal advection-diffusion problem\n"); /* Forward sensitivity analysis */ if(sensi) { plist = (int *) malloc(NS * sizeof(int)); if(check_flag((void *)plist, "malloc", 2)) return(1); for(is=0; is<NS; is++) plist[is] = is; pbar = (realtype *) malloc(NS * sizeof(realtype)); if(check_flag((void *)pbar, "malloc", 2)) return(1); for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]]; uS = N_VCloneVectorArray_Serial(NS, y); if(check_flag((void *)uS, "N_VCloneVectorArray_Serial", 0)) return(1); for(is=0;is<NS;is++) N_VConst(ZERO,uS[is]); flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS); if(check_flag(&flag, "CVodeSensInit", 1)) return(1); flag = CVodeSensEEtolerances(cvode_mem); if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1); flag = CVodeSetSensErrCon(cvode_mem, err_con); if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1); flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO); if(check_flag(&flag, "CVodeSetSensDQMethod", 1)) return(1); flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist); if(check_flag(&flag, "CVodeSetSensParams", 1)) return(1); printf("Sensitivity: YES "); if(sensi_meth == CV_SIMULTANEOUS) printf("( SIMULTANEOUS +"); else if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +"); else printf("( STAGGERED1 +"); if(err_con) printf(" FULL ERROR CONTROL )"); else printf(" PARTIAL ERROR CONTROL )"); } else { printf("Sensitivity: NO "); } /* In loop over output points, call CVode, print results, test for error */ printf("\n\n"); printf("========================================================================\n"); printf(" T Q H NST Bottom left Top right \n"); printf("========================================================================\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1)) break; PrintOutput(cvode_mem, t, y); if (sensi) { flag = CVodeGetSens(cvode_mem, &t, uS); if(check_flag(&flag, "CVodeGetSens", 1)) break; PrintOutputS(uS); } printf("------------------------------------------------------------------------\n"); } /* Print final statistics */ PrintFinalStats(cvode_mem, sensi); /* Free memory */ N_VDestroy_Serial(y); if (sensi) { N_VDestroyVectorArray_Serial(uS, NS); free(pbar); free(plist); } FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
int main(int argc, char *argv[]) { void *cvode_mem; UserData data; realtype dx, reltol, abstol, t, tout; N_Vector u; int iout, flag; realtype *pbar; int is, *plist; N_Vector *uS; booleantype sensi, err_con; int sensi_meth; cvode_mem = NULL; data = NULL; u = NULL; pbar = NULL; plist = NULL; uS = NULL; /* Process arguments */ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con); /* Set user data */ data = (UserData) malloc(sizeof *data); /* Allocate data memory */ if(check_flag((void *)data, "malloc", 2)) return(1); data->p = (realtype *) malloc(NP * sizeof(realtype)); dx = data->dx = XMAX/((realtype)(MX+1)); data->p[0] = RCONST(1.0); data->p[1] = RCONST(0.5); /* Allocate and set initial states */ u = N_VNew_Serial(NEQ); if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1); SetIC(u, dx); /* Set integration tolerances */ reltol = ZERO; abstol = ATOL; /* Create CVODES object */ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Allocate CVODES memory */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSStolerances(cvode_mem, reltol, abstol); if(check_flag(&flag, "CVodeSStolerances", 1)) return(1); printf("\n1-D advection-diffusion equation, mesh size =%3d\n", MX); /* Sensitivity-related settings */ if(sensi) { plist = (int *) malloc(NS * sizeof(int)); if(check_flag((void *)plist, "malloc", 2)) return(1); for(is=0; is<NS; is++) plist[is] = is; pbar = (realtype *) malloc(NS * sizeof(realtype)); if(check_flag((void *)pbar, "malloc", 2)) return(1); for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]]; uS = N_VCloneVectorArray_Serial(NS, u); if(check_flag((void *)uS, "N_VCloneVectorArray_Serial", 0)) return(1); for(is=0;is<NS;is++) N_VConst(ZERO, uS[is]); flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS); if(check_flag(&flag, "CVodeSensInit1", 1)) return(1); flag = CVodeSensEEtolerances(cvode_mem); if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1); flag = CVodeSetSensErrCon(cvode_mem, err_con); if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1); flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO); if(check_flag(&flag, "CVodeSetSensDQMethod", 1)) return(1); flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist); if(check_flag(&flag, "CVodeSetSensParams", 1)) return(1); printf("Sensitivity: YES "); if(sensi_meth == CV_SIMULTANEOUS) printf("( SIMULTANEOUS +"); else if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +"); else printf("( STAGGERED1 +"); if(err_con) printf(" FULL ERROR CONTROL )"); else printf(" PARTIAL ERROR CONTROL )"); } else { printf("Sensitivity: NO "); } /* In loop over output points, call CVode, print results, test for error */ printf("\n\n"); printf("============================================================\n"); printf(" T Q H NST Max norm \n"); printf("============================================================\n"); for (iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1)) break; PrintOutput(cvode_mem, t, u); if (sensi) { flag = CVodeGetSens(cvode_mem, &t, uS); if(check_flag(&flag, "CVodeGetSens", 1)) break; PrintOutputS(uS); } printf("------------------------------------------------------------\n"); } /* Print final statistics */ PrintFinalStats(cvode_mem, sensi); /* Free memory */ N_VDestroy_Serial(u); if (sensi) { N_VDestroyVectorArray_Serial(uS, NS); free(plist); free(pbar); } free(data); CVodeFree(&cvode_mem); return(0); }
void CVodesIntegrator::initialize(double t0, FuncEval& func) { m_neq = func.neq(); m_t0 = t0; m_time = t0; if (m_y) { N_VDestroy_Serial(m_y); // free solution vector if already allocated } m_y = N_VNew_Serial(static_cast<sd_size_t>(m_neq)); // allocate solution vector for (size_t i = 0; i < m_neq; i++) { NV_Ith_S(m_y, i) = 0.0; } // check abs tolerance array size if (m_itol == CV_SV && m_nabs < m_neq) { throw CVodesErr("not enough absolute tolerance values specified."); } func.getInitialConditions(m_t0, m_neq, NV_DATA_S(m_y)); if (m_cvode_mem) { CVodeFree(&m_cvode_mem); } /* * Specify the method and the iteration type: * Cantera Defaults: * CV_BDF - Use BDF methods * CV_NEWTON - use Newton's method */ m_cvode_mem = CVodeCreate(m_method, m_iter); if (!m_cvode_mem) { throw CVodesErr("CVodeCreate failed."); } int flag = CVodeInit(m_cvode_mem, cvodes_rhs, m_t0, m_y); if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeInit input argument."); } else { throw CVodesErr("CVodeInit failed."); } } CVodeSetErrHandlerFn(m_cvode_mem, &cvodes_err, this); if (m_itol == CV_SV) { flag = CVodeSVtolerances(m_cvode_mem, m_reltol, m_abstol); } else { flag = CVodeSStolerances(m_cvode_mem, m_reltol, m_abstols); } if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeInit input argument."); } else { throw CVodesErr("CVodeInit failed."); } } // pass a pointer to func in m_data m_fdata.reset(new FuncData(&func, func.nparams())); flag = CVodeSetUserData(m_cvode_mem, m_fdata.get()); if (flag != CV_SUCCESS) { throw CVodesErr("CVodeSetUserData failed."); } if (func.nparams() > 0) { sensInit(t0, func); flag = CVodeSetSensParams(m_cvode_mem, m_fdata->m_pars.data(), NULL, NULL); } applyOptions(); }
void FCV_MALLOC(realtype *t0, realtype *y0, int *meth, int *iatol, realtype *rtol, realtype *atol, long int *iout, realtype *rout, long int *ipar, realtype *rpar, int *ier) { int lmm; N_Vector Vatol; FCVUserData CV_userdata; *ier = 0; /* Check for required vector operations */ if(F2C_CVODE_vec->ops->nvgetarraypointer == NULL || F2C_CVODE_vec->ops->nvsetarraypointer == NULL) { *ier = -1; fprintf(stderr, "A required vector operation is not implemented.\n\n"); return; } /* Initialize all pointers to NULL */ CV_cvodemem = NULL; Vatol = NULL; FCVNullNonlinSol(); /* initialize global constants to disable each option */ CV_nrtfn = 0; CV_ls = -1; /* Create CVODE object */ lmm = (*meth == 1) ? CV_ADAMS : CV_BDF; CV_cvodemem = CVodeCreate(lmm); if (CV_cvodemem == NULL) { *ier = -1; return; } /* Set and attach user data */ CV_userdata = NULL; CV_userdata = (FCVUserData) malloc(sizeof *CV_userdata); if (CV_userdata == NULL) { *ier = -1; return; } CV_userdata->rpar = rpar; CV_userdata->ipar = ipar; *ier = CVodeSetUserData(CV_cvodemem, CV_userdata); if(*ier != CV_SUCCESS) { free(CV_userdata); CV_userdata = NULL; *ier = -1; return; } /* Set data in F2C_CVODE_vec to y0 */ N_VSetArrayPointer(y0, F2C_CVODE_vec); /* Call CVodeInit */ *ier = CVodeInit(CV_cvodemem, FCVf, *t0, F2C_CVODE_vec); /* Reset data pointers */ N_VSetArrayPointer(NULL, F2C_CVODE_vec); /* On failure, exit */ if(*ier != CV_SUCCESS) { free(CV_userdata); CV_userdata = NULL; *ier = -1; return; } /* Set tolerances */ switch (*iatol) { case 1: *ier = CVodeSStolerances(CV_cvodemem, *rtol, *atol); break; case 2: Vatol = NULL; Vatol = N_VCloneEmpty(F2C_CVODE_vec); if (Vatol == NULL) { free(CV_userdata); CV_userdata = NULL; *ier = -1; return; } N_VSetArrayPointer(atol, Vatol); *ier = CVodeSVtolerances(CV_cvodemem, *rtol, Vatol); N_VDestroy(Vatol); break; } /* On failure, exit */ if(*ier != CV_SUCCESS) { free(CV_userdata); CV_userdata = NULL; *ier = -1; return; } /* Grab optional output arrays and store them in global variables */ CV_iout = iout; CV_rout = rout; /* Store the unit roundoff in rout for user access */ CV_rout[5] = UNIT_ROUNDOFF; return; }
void OpenSMOKE_CVODE_Sundials<T>::Solve(const double xend) { int flag; this->x_ = this->x0_; this->xend_ = xend; for(int i=0;i<this->n_;i++) NV_Ith_S(y0Sundials_,i) = this->y0_[i]; if (firstCall_ == true) { firstCall_ = false; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem_ = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem_, std::string("CVodeCreate"), 0)) exit(-1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in y'=f(t,y), the inital time t0, and * the initial dependent variable vector y0Sundials_. */ flag = CVodeInit(cvode_mem_, this->odeSystem_->GetSystemFunctionsStatic, this->odeSystem_->GetWriteFunctionStatic, this->x0_, y0Sundials_); if (check_flag(&flag, std::string("CVodeInit"), 1)) exit(-1); /* Call CVodeSVtolerances to specify the scalar relative tolerance * and vector absolute tolerances */ flag = CVodeSStolerances(cvode_mem_, this->relTolerance_[0], this->absTolerance_[0]); if (check_flag(&flag, std::string("CVodeSVtolerances"), 1)) exit(-1); /* Call Solver */ if (this->iUseLapack_ == false) { if (this->mUpper_ == 0 && this->mLower_ == 0) { // std::cout << "CVODE Solver: Dense Jacobian (without Lapack)..." << std::endl; flag = CVDense(cvode_mem_, this->n_); if (check_flag(&flag, std::string("CVDense"), 1)) exit(-1); } else { // std::cout << "CVODE Solver: Band Jacobian (without Lapack)..." << std::endl; flag = CVBand(cvode_mem_, this->n_, this->mUpper_, this->mLower_); if (check_flag(&flag, std::string("CVBand"), 1)) exit(-1); } } else { if (this->mUpper_ == 0 && this->mLower_ == 0) { // std::cout << "CVODE Solver: Dense Jacobian (with Lapack)..." << std::endl; flag = CVLapackDense(cvode_mem_, this->n_); if (check_flag(&flag, std::string("CVLapackDense"), 1)) exit(-1); } else { // std::cout << "CVODE Solver: Band Jacobian (with Lapack)..." << std::endl; flag = CVLapackBand(cvode_mem_, this->n_, this->mUpper_, this->mLower_); if (check_flag(&flag, std::string("CVLapackBand"), 1)) exit(-1); } } } else { flag = CVodeReInit(cvode_mem_, this->x0_, y0Sundials_); if (check_flag(&flag, std::string("CVodeReInit"), 1)) exit(-1); } AnalyzeUserOptions(); /* Solving */ this->tStart_ = this->GetClockTime(); flag = CVode(cvode_mem_, this->xend_, ySundials_, &this->x_, CV_NORMAL); this->tEnd_ = this->GetClockTime(); this->x0_ = this->x_; for(int i=0;i<this->n_;i++) NV_Ith_S(y0Sundials_,i) = NV_Ith_S(ySundials_,i); for(int i=0;i<this->n_;i++) this->y_[i] = NV_Ith_S(ySundials_,i); }
void CVodesIntegrator::initialize(double t0, FuncEval& func) { m_neq = func.neq(); m_t0 = t0; m_time = t0; if (m_y) { N_VDestroy_Serial(m_y); // free solution vector if already allocated } m_y = N_VNew_Serial(static_cast<sd_size_t>(m_neq)); // allocate solution vector N_VConst(0.0, m_y); // check abs tolerance array size if (m_itol == CV_SV && m_nabs < m_neq) { throw CanteraError("CVodesIntegrator::initialize", "not enough absolute tolerance values specified."); } func.getState(NV_DATA_S(m_y)); if (m_cvode_mem) { CVodeFree(&m_cvode_mem); } //! Specify the method and the iteration type. Cantera Defaults: //! CV_BDF - Use BDF methods //! CV_NEWTON - use Newton's method m_cvode_mem = CVodeCreate(m_method, m_iter); if (!m_cvode_mem) { throw CanteraError("CVodesIntegrator::initialize", "CVodeCreate failed."); } int flag = CVodeInit(m_cvode_mem, cvodes_rhs, m_t0, m_y); if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CanteraError("CVodesIntegrator::initialize", "Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CanteraError("CVodesIntegrator::initialize", "Illegal value for CVodeInit input argument."); } else { throw CanteraError("CVodesIntegrator::initialize", "CVodeInit failed."); } } CVodeSetErrHandlerFn(m_cvode_mem, &cvodes_err, this); if (m_itol == CV_SV) { flag = CVodeSVtolerances(m_cvode_mem, m_reltol, m_abstol); } else { flag = CVodeSStolerances(m_cvode_mem, m_reltol, m_abstols); } if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CanteraError("CVodesIntegrator::initialize", "Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CanteraError("CVodesIntegrator::initialize", "Illegal value for CVodeInit input argument."); } else { throw CanteraError("CVodesIntegrator::initialize", "CVodeInit failed."); } } flag = CVodeSetUserData(m_cvode_mem, &func); if (flag != CV_SUCCESS) { throw CanteraError("CVodesIntegrator::initialize", "CVodeSetUserData failed."); } if (func.nparams() > 0) { sensInit(t0, func); flag = CVodeSetSensParams(m_cvode_mem, func.m_sens_params.data(), func.m_paramScales.data(), NULL); if (flag != CV_SUCCESS) { throw CanteraError("CVodesIntegrator::initialize", "CVodeSetSensParams failed."); } } applyOptions(); }
int main() { realtype t, tout; N_Vector y; void *cvode_mem; int flag, flagr, iout; int rootsfound[2]; y = NULL; cvode_mem = NULL; /* Create serial vector of length NEQ for I.C. */ y = N_VNew_Serial(NEQ); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); /* Initialize y */ Ith(y,1) = Y1; Ith(y,2) = Y2; Ith(y,3) = Y3; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((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 inital time T0, and * the initial dependent variable vector y. */ flag = CVodeInit(cvode_mem, f, T0, y); if (check_flag(&flag, "CVodeInit", 1)) return(1); /* Use private function to compute error weights */ flag = CVodeWFtolerances(cvode_mem, ewt); if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1); /* Call CVodeRootInit to specify the root function g with 2 components */ flag = CVodeRootInit(cvode_mem, 2, g); if (check_flag(&flag, "CVodeRootInit", 1)) return(1); /* Call CVDense to specify the CVDENSE dense linear solver */ flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); /* Set the Jacobian routine to Jac (user-supplied) */ flag = CVDlsSetDenseJacFn(cvode_mem, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); /* In loop, call CVode, print results, and test for error. Break out of loop when NOUT preset output times have been reached. */ printf(" \n3-species kinetics problem\n\n"); iout = 0; tout = T1; while(1) { flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL); PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3)); if (flag == CV_ROOT_RETURN) { flagr = CVodeGetRootInfo(cvode_mem, rootsfound); check_flag(&flagr, "CVodeGetRootInfo", 1); PrintRootInfo(rootsfound[0],rootsfound[1]); } if (check_flag(&flag, "CVode", 1)) break; if (flag == CV_SUCCESS) { iout++; tout *= TMULT; } if (iout == NOUT) break; } /* Print some final statistics */ PrintFinalStats(cvode_mem); /* Free y vector */ N_VDestroy_Serial(y); /* Free integrator memory */ CVodeFree(&cvode_mem); return(0); }
int main(int argc, char *argv[]) { UserData data; void *cvode_mem; N_Vector u; realtype reltol, abstol; int indexB; N_Vector uB; realtype dx, t, g_val; int retval, my_pe, nprocs, npes, ncheck; sunindextype local_N=0, nperpe, nrem, my_base=-1; SUNNonlinearSolver NLS, NLSB; MPI_Comm comm; data = NULL; cvode_mem = NULL; u = uB = NULL; /*------------------------------------------------------ Initialize MPI and get total number of pe's, and my_pe ------------------------------------------------------*/ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &nprocs); MPI_Comm_rank(comm, &my_pe); npes = nprocs - 1; /* pe's dedicated to PDE integration */ if ( npes <= 0 ) { if (my_pe == npes) fprintf(stderr, "\nMPI_ERROR(%d): number of processes must be >= 2\n\n", my_pe); MPI_Finalize(); return(1); } /*----------------------- Set local vector length -----------------------*/ nperpe = NEQ/npes; nrem = NEQ - npes*nperpe; if (my_pe < npes) { /* PDE vars. distributed to this proccess */ local_N = (my_pe < nrem) ? nperpe+1 : nperpe; my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem; } else { /* Make last process inactive for forward phase */ local_N = 0; } /*------------------------------------- Allocate and load user data structure -------------------------------------*/ data = (UserData) malloc(sizeof *data); if (check_retval((void *)data , "malloc", 2, my_pe)) MPI_Abort(comm, 1); data->p[0] = ONE; data->p[1] = RCONST(0.5); dx = data->dx = XMAX/((realtype)(MX+1)); data->hdcoef = data->p[0]/(dx*dx); data->hacoef = data->p[1]/(TWO*dx); data->comm = comm; data->npes = npes; data->my_pe = my_pe; data->nperpe = nperpe; data->nrem = nrem; data->local_N = local_N; /*------------------------- Forward integration phase -------------------------*/ /* Set relative and absolute tolerances for forward phase */ reltol = ZERO; abstol = ATOL; /* Allocate and initialize forward variables */ u = N_VNew_Parallel(comm, local_N, NEQ); if (check_retval((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1); SetIC(u, dx, local_N, my_base); /* Allocate CVODES memory for forward integration */ cvode_mem = CVodeCreate(CV_ADAMS); if (check_retval((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1); retval = CVodeSetUserData(cvode_mem, data); if (check_retval(&retval, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 1); retval = CVodeInit(cvode_mem, f, T0, u); if (check_retval(&retval, "CVodeInit", 1, my_pe)) MPI_Abort(comm, 1); retval = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_retval(&retval, "CVodeSStolerances", 1, my_pe)) MPI_Abort(comm, 1); /* create fixed point nonlinear solver object */ NLS = SUNNonlinSol_FixedPoint(u, 0); if(check_retval((void *)NLS, "SUNNonlinSol_FixedPoint", 0, my_pe)) MPI_Abort(comm, 1); /* attach nonlinear solver object to CVode */ retval = CVodeSetNonlinearSolver(cvode_mem, NLS); if(check_retval(&retval, "CVodeSetNonlinearSolver", 1, my_pe)) MPI_Abort(comm, 1); /* Allocate combined forward/backward memory */ retval = CVodeAdjInit(cvode_mem, STEPS, CV_HERMITE); if (check_retval(&retval, "CVadjInit", 1, my_pe)) MPI_Abort(comm, 1); /* Integrate to TOUT and collect check point information */ retval = CVodeF(cvode_mem, TOUT, u, &t, CV_NORMAL, &ncheck); if (check_retval(&retval, "CVodeF", 1, my_pe)) MPI_Abort(comm, 1); /*--------------------------- Compute and value of g(t_f) ---------------------------*/ g_val = Compute_g(u, data); /*-------------------------- Backward integration phase --------------------------*/ if (my_pe == npes) { /* Activate last process for integration of the quadrature equations */ local_N = NP; } else { /* Allocate work space */ data->z1 = (realtype *)malloc(local_N*sizeof(realtype)); if (check_retval((void *)data->z1, "malloc", 2, my_pe)) MPI_Abort(comm, 1); data->z2 = (realtype *)malloc(local_N*sizeof(realtype)); if (check_retval((void *)data->z2, "malloc", 2, my_pe)) MPI_Abort(comm, 1); } /* Allocate and initialize backward variables */ uB = N_VNew_Parallel(comm, local_N, NEQ+NP); if (check_retval((void *)uB, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1); SetICback(uB, my_base); /* Allocate CVODES memory for the backward integration */ retval = CVodeCreateB(cvode_mem, CV_ADAMS, &indexB); if (check_retval(&retval, "CVodeCreateB", 1, my_pe)) MPI_Abort(comm, 1); retval = CVodeSetUserDataB(cvode_mem, indexB, data); if (check_retval(&retval, "CVodeSetUserDataB", 1, my_pe)) MPI_Abort(comm, 1); retval = CVodeInitB(cvode_mem, indexB, fB, TOUT, uB); if (check_retval(&retval, "CVodeInitB", 1, my_pe)) MPI_Abort(comm, 1); retval = CVodeSStolerancesB(cvode_mem, indexB, reltol, abstol); if (check_retval(&retval, "CVodeSStolerancesB", 1, my_pe)) MPI_Abort(comm, 1); /* create fixed point nonlinear solver object */ NLSB = SUNNonlinSol_FixedPoint(uB, 0); if(check_retval((void *)NLSB, "SUNNonlinSol_FixedPoint", 0, my_pe)) MPI_Abort(comm, 1); /* attach nonlinear solver object to CVode */ retval = CVodeSetNonlinearSolverB(cvode_mem, indexB, NLSB); if(check_retval(&retval, "CVodeSetNonlinearSolver", 1, my_pe)) MPI_Abort(comm, 1); /* Integrate to T0 */ retval = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_retval(&retval, "CVodeB", 1, my_pe)) MPI_Abort(comm, 1); retval = CVodeGetB(cvode_mem, indexB, &t, uB); if (check_retval(&retval, "CVodeGetB", 1, my_pe)) MPI_Abort(comm, 1); /* Print results (adjoint states and quadrature variables) */ PrintOutput(g_val, uB, data); /* Free memory */ N_VDestroy_Parallel(u); N_VDestroy_Parallel(uB); CVodeFree(&cvode_mem); SUNNonlinSolFree(NLS); SUNNonlinSolFree(NLSB); if (my_pe != npes) { free(data->z1); free(data->z2); } free(data); MPI_Finalize(); return(0); }
int main(void) { realtype dx, dy, reltol, abstol, t, tout, umax; N_Vector u; UserData data; void *cvode_mem; int iout, flag; long int nst; u = NULL; data = NULL; cvode_mem = NULL; /* Create a serial vector */ u = N_VNew_Serial(NEQ); /* Allocate u vector */ if(check_flag((void*)u, "N_VNew_Serial", 0)) return(1); reltol = ZERO; /* Set the tolerances */ abstol = ATOL; data = (UserData) malloc(sizeof *data); /* Allocate data memory */ if(check_flag((void *)data, "malloc", 2)) return(1); dx = data->dx = XMAX/(MX+1); /* Set grid coefficients in data */ dy = data->dy = YMAX/(MY+1); data->hdcoef = ONE/(dx*dx); data->hacoef = HALF/(TWO*dx); data->vdcoef = ONE/(dy*dy); SetIC(u, data); /* Initialize u vector */ /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerance */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Call CVBand to specify the CVBAND band linear solver */ flag = CVBand(cvode_mem, NEQ, MY, MY); if(check_flag(&flag, "CVBand", 1)) return(1); /* Set the user-supplied Jacobian routine Jac */ flag = CVDlsSetBandJacFn(cvode_mem, Jac); if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1); /* In loop over output points: call CVode, print results, test for errors */ umax = N_VMaxNorm(u); PrintHeader(reltol, abstol, umax); for(iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1)) break; umax = N_VMaxNorm(u); flag = CVodeGetNumSteps(cvode_mem, &nst); check_flag(&flag, "CVodeGetNumSteps", 1); PrintOutput(t, umax, nst); } PrintFinalStats(cvode_mem); /* Print some final statistics */ N_VDestroy_Serial(u); /* Free the u vector */ CVodeFree(&cvode_mem); /* Free the integrator memory */ free(data); /* Free the user data */ return(0); }
int main(void) { realtype abstol, reltol, t, tout; N_Vector u; UserData data; void *cvode_mem; int linsolver, iout, flag; u = NULL; data = NULL; cvode_mem = NULL; /* Allocate memory, and set problem data, initial values, tolerances */ u = N_VNew_Serial(NEQ); if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1); data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); SetInitialProfiles(u, data->dx, data->dy); abstol=ATOL; reltol=RTOL; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* START: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */ for (linsolver = 0; linsolver < 3; ++linsolver) { if (linsolver != 0) { /* Re-initialize user data */ InitUserData(data); SetInitialProfiles(u, data->dx, data->dy); /* Re-initialize CVode for the solution of the same problem, but using a different linear solver module */ flag = CVodeReInit(cvode_mem, T0, u); if (check_flag(&flag, "CVodeReInit", 1)) return(1); } /* Attach a linear solver module */ switch(linsolver) { /* (a) SPGMR */ case(USE_SPGMR): /* Print header */ printf(" -------"); printf(" \n| SPGMR |\n"); printf(" -------\n"); /* Call CVSpgmr to specify the linear solver CVSPGMR with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); /* Set modified Gram-Schmidt orthogonalization, preconditioner setup and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS); if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1); break; /* (b) SPBCG */ case(USE_SPBCG): /* Print header */ printf(" -------"); printf(" \n| SPBCG |\n"); printf(" -------\n"); /* Call CVSpbcg to specify the linear solver CVSPBCG with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpbcg(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpbcg", 1)) return(1); break; /* (c) SPTFQMR */ case(USE_SPTFQMR): /* Print header */ printf(" ---------"); printf(" \n| SPTFQMR |\n"); printf(" ---------\n"); /* Call CVSptfqmr to specify the linear solver CVSPTFQMR with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSptfqmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSptfqmr", 1)) return(1); break; } /* Set preconditioner setup and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /* In loop over output points, call CVode, print results, test for error */ printf(" \n2-species diurnal advection-diffusion problem\n\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); PrintOutput(cvode_mem, u, t); if(check_flag(&flag, "CVode", 1)) break; } PrintFinalStats(cvode_mem, linsolver); } /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */ /* Free memory */ N_VDestroy_Serial(u); FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
int main(int argc, char *argv[]) { realtype dx, reltol, abstol, t, tout; N_Vector u; UserData data; void *cvode_mem; int iout, flag, my_pe, npes; long int local_N, nperpe, nrem, my_base; realtype *pbar; int is, *plist; N_Vector *uS; booleantype sensi, err_con; int sensi_meth; MPI_Comm comm; u = NULL; data = NULL; cvode_mem = NULL; pbar = NULL; plist = NULL; uS = NULL; /* Get processor number, total number of pe's, and my_pe. */ MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &npes); MPI_Comm_rank(comm, &my_pe); /* Process arguments */ ProcessArgs(argc, argv, my_pe, &sensi, &sensi_meth, &err_con); /* Set local vector length. */ nperpe = NEQ/npes; nrem = NEQ - npes*nperpe; local_N = (my_pe < nrem) ? nperpe+1 : nperpe; my_base = (my_pe < nrem) ? my_pe*local_N : my_pe*nperpe + nrem; /* USER DATA STRUCTURE */ data = (UserData) malloc(sizeof *data); /* Allocate data memory */ data->p = NULL; if(check_flag((void *)data, "malloc", 2, my_pe)) MPI_Abort(comm, 1); data->comm = comm; data->npes = npes; data->my_pe = my_pe; data->p = (realtype *) malloc(NP * sizeof(realtype)); if(check_flag((void *)data->p, "malloc", 2, my_pe)) MPI_Abort(comm, 1); dx = data->dx = XMAX/((realtype)(MX+1)); data->p[0] = RCONST(1.0); data->p[1] = RCONST(0.5); /* INITIAL STATES */ u = N_VNew_Parallel(comm, local_N, NEQ); /* Allocate u vector */ if(check_flag((void *)u, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1); SetIC(u, dx, local_N, my_base); /* Initialize u vector */ /* TOLERANCES */ reltol = ZERO; /* Set the tolerances */ abstol = ATOL; /* CVODE_CREATE & CVODE_MALLOC */ cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL); if(check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1); flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1, my_pe)) MPI_Abort(comm, 1); flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1, my_pe)) MPI_Abort(comm, 1); flag = CVodeSStolerances(cvode_mem, reltol, abstol); if(check_flag(&flag, "CVodeSStolerances", 1, my_pe)) MPI_Abort(comm, 1); if (my_pe == 0) { printf("\n1-D advection-diffusion equation, mesh size =%3d \n", MX); printf("\nNumber of PEs = %3d \n",npes); } if(sensi) { plist = (int *) malloc(NS * sizeof(int)); if(check_flag((void *)plist, "malloc", 2, my_pe)) MPI_Abort(comm, 1); for(is=0; is<NS; is++) plist[is] = is; /* sensitivity w.r.t. i-th parameter */ pbar = (realtype *) malloc(NS * sizeof(realtype)); if(check_flag((void *)pbar, "malloc", 2, my_pe)) MPI_Abort(comm, 1); for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]]; uS = N_VCloneVectorArray_Parallel(NS, u); if(check_flag((void *)uS, "N_VCloneVectorArray_Parallel", 0, my_pe)) MPI_Abort(comm, 1); for(is=0;is<NS;is++) N_VConst(ZERO,uS[is]); flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, NULL, uS); if(check_flag(&flag, "CVodeSensInit1", 1, my_pe)) MPI_Abort(comm, 1); flag = CVodeSensEEtolerances(cvode_mem); if(check_flag(&flag, "CVodeSensEEtolerances", 1, my_pe)) MPI_Abort(comm, 1); flag = CVodeSetSensErrCon(cvode_mem, err_con); if(check_flag(&flag, "CVodeSetSensErrCon", 1, my_pe)) MPI_Abort(comm, 1); flag = CVodeSetSensDQMethod(cvode_mem, CV_CENTERED, ZERO); if(check_flag(&flag, "CVodeSetSensDQMethod", 1, my_pe)) MPI_Abort(comm, 1); flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist); if(check_flag(&flag, "CVodeSetSensParams", 1, my_pe)) MPI_Abort(comm, 1); if(my_pe == 0) { printf("Sensitivity: YES "); if(sensi_meth == CV_SIMULTANEOUS) printf("( SIMULTANEOUS +"); else if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +"); else printf("( STAGGERED1 +"); if(err_con) printf(" FULL ERROR CONTROL )"); else printf(" PARTIAL ERROR CONTROL )"); } } else { if(my_pe == 0) printf("Sensitivity: NO "); } /* In loop over output points, call CVode, print results, test for error */ if(my_pe == 0) { printf("\n\n"); printf("============================================================\n"); printf(" T Q H NST Max norm \n"); printf("============================================================\n"); } for (iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1, my_pe)) break; PrintOutput(cvode_mem, my_pe, t, u); if (sensi) { flag = CVodeGetSens(cvode_mem, &t, uS); if(check_flag(&flag, "CVodeGetSens", 1, my_pe)) break; PrintOutputS(my_pe, uS); } if (my_pe == 0) printf("------------------------------------------------------------\n"); } /* Print final statistics */ if (my_pe == 0) PrintFinalStats(cvode_mem, sensi); /* Free memory */ N_VDestroy(u); /* Free the u vector */ if (sensi) N_VDestroyVectorArray(uS, NS); /* Free the uS vectors */ free(data->p); /* Free the p vector */ free(data); /* Free block of UserData */ CVodeFree(&cvode_mem); /* Free the CVODES problem memory */ free(pbar); if(sensi) free(plist); MPI_Finalize(); return(0); }
int main(int argc, char *argv[]) { realtype abstol=ATOL, reltol=RTOL, t; N_Vector c; WebData wdata; void *cvode_mem; SUNLinearSolver LS, LSB; int retval, ncheck; int indexB; realtype reltolB=RTOL, abstolB=ATOL; N_Vector cB; c = NULL; cB = NULL; wdata = NULL; cvode_mem = NULL; LS = LSB = NULL; /* Allocate and initialize user data */ wdata = AllocUserData(); if(check_retval((void *)wdata, "AllocUserData", 2)) return(1); InitUserData(wdata); /* Set-up forward problem */ /* Initializations */ c = N_VNew_Serial(NEQ+1); if(check_retval((void *)c, "N_VNew_Serial", 0)) return(1); CInit(c, wdata); /* Call CVodeCreate/CVodeInit for forward run */ printf("\nCreate and allocate CVODES memory for forward run\n"); cvode_mem = CVodeCreate(CV_BDF); if(check_retval((void *)cvode_mem, "CVodeCreate", 0)) return(1); wdata->cvode_mem = cvode_mem; /* Used in Precond */ retval = CVodeSetUserData(cvode_mem, wdata); if(check_retval(&retval, "CVodeSetUserData", 1)) return(1); retval = CVodeInit(cvode_mem, f, T0, c); if(check_retval(&retval, "CVodeInit", 1)) return(1); retval = CVodeSStolerances(cvode_mem, reltol, abstol); if(check_retval(&retval, "CVodeSStolerances", 1)) return(1); /* Create SUNLinSol_SPGMR linear solver for forward run */ LS = SUNLinSol_SPGMR(c, PREC_LEFT, 0); if(check_retval((void *)LS, "SUNLinSol_SPGMR", 0)) return(1); /* Attach the linear sovler */ retval = CVodeSetLinearSolver(cvode_mem, LS, NULL); if (check_retval(&retval, "CVodeSetLinearSolver", 1)) return 1; /* Set the preconditioner solve and setup functions */ retval = CVodeSetPreconditioner(cvode_mem, Precond, PSolve); if(check_retval(&retval, "CVodeSetPreconditioner", 1)) return(1); /* Set-up adjoint calculations */ printf("\nAllocate global memory\n"); retval = CVodeAdjInit(cvode_mem, NSTEPS, CV_HERMITE); if(check_retval(&retval, "CVadjInit", 1)) return(1); /* Perform forward run */ printf("\nForward integration\n"); retval = CVodeF(cvode_mem, TOUT, c, &t, CV_NORMAL, &ncheck); if(check_retval(&retval, "CVodeF", 1)) return(1); printf("\nncheck = %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, N_VGetArrayPointer(c)[NEQ]); #else printf("\n G = int_t int_x int_y c%d(t,x,y) dx dy dt = %f \n\n", ISPEC, N_VGetArrayPointer(c)[NEQ]); #endif /* Set-up backward problem */ /* Allocate cB */ cB = N_VNew_Serial(NEQ); if(check_retval((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"); retval = CVodeCreateB(cvode_mem, CV_BDF, &indexB); if(check_retval(&retval, "CVodeCreateB", 1)) return(1); retval = CVodeSetUserDataB(cvode_mem, indexB, wdata); if(check_retval(&retval, "CVodeSetUserDataB", 1)) return(1); retval = CVodeSetMaxNumStepsB(cvode_mem, indexB, 1000); if(check_retval(&retval, "CVodeSetMaxNumStepsB", 1)) return(1); retval = CVodeInitB(cvode_mem, indexB, fB, TOUT, cB); if(check_retval(&retval, "CVodeInitB", 1)) return(1); retval = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); if(check_retval(&retval, "CVodeSStolerancesB", 1)) return(1); wdata->indexB = indexB; /* Create SUNLinSol_SPGMR linear solver for backward run */ LSB = SUNLinSol_SPGMR(cB, PREC_LEFT, 0); if(check_retval((void *)LSB, "SUNLinSol_SPGMR", 0)) return(1); /* Attach the linear sovler */ retval = CVodeSetLinearSolverB(cvode_mem, indexB, LSB, NULL); if (check_retval(&retval, "CVodeSetLinearSolverB", 1)) return 1; /* Set the preconditioner solve and setup functions */ retval = CVodeSetPreconditionerB(cvode_mem, indexB, PrecondB, PSolveB); if(check_retval(&retval, "CVodeSetPreconditionerB", 1)) return(1); /* Perform backward integration */ printf("\nBackward integration\n"); retval = CVodeB(cvode_mem, T0, CV_NORMAL); if(check_retval(&retval, "CVodeB", 1)) return(1); retval = CVodeGetB(cvode_mem, indexB, &t, cB); if(check_retval(&retval, "CVodeGetB", 1)) return(1); PrintOutput(cB, NS, MXNS, wdata); /* Free all memory */ CVodeFree(&cvode_mem); N_VDestroy(c); N_VDestroy(cB); SUNLinSolFree(LS); SUNLinSolFree(LSB); FreeUserData(wdata); return(0); }
int main(int narg, char **args) { realtype reltol, t, tout; N_Vector state, abstol; void *cvode_mem; int flag, flagr; FILE *pout; if(!(pout = fopen("Locke2008_Circadian_Clock.dat", "w"))){ fprintf(stderr, "Cannot open file Locke2008_Circadian_Clock.dat. Are you trying to write to a non-existent directory? Exiting...\n"); exit(1); } state = abstol = NULL; cvode_mem = NULL; state = N_VNew_Serial(NEQ); if (check_flag((void *)state, "N_VNew_Serial", 0)) return(1); abstol = N_VNew_Serial(NEQ); if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1); realtype Kc = 4.8283; realtype v_4 = 1.0841; realtype v_6 = 4.6645; realtype vc = 6.7924; realtype v_1 = 6.8355; realtype v_2 = 8.4297; realtype K = 1.0; realtype v_8 = 3.5216; realtype L = 0.0; realtype n = 5.6645; realtype k3 = 0.1177; realtype K2 = 0.291; realtype K1 = 2.7266; realtype k7 = 0.2282; realtype K6 = 9.9849; realtype k5 = 0.3352; realtype K4 = 8.1343; realtype K8 = 7.4519; realtype init_X1 = 4.25; realtype tscale = 1.0; realtype init_Z1 = 2.25; realtype init_Z2 = 0.0; realtype init_V1 = 2.5; realtype init_V2 = 0.0; realtype init_X2 = 0.0; realtype compartment = 1.0; realtype init_Y1 = 3.25; realtype init_Y2 = 0.0; realtype p[] = {Kc, v_4, v_6, vc, v_1, v_2, K, v_8, L, n, k3, K2, K1, k7, K6, k5, K4, K8, init_X1, tscale, init_Z1, init_Z2, init_V1, init_V2, init_X2, compartment, init_Y1, init_Y2, }; realtype X1 = init_X1; realtype X2 = init_X2; realtype V1 = init_V1; realtype V2 = init_V2; realtype Y1 = init_Y1; realtype Y2 = init_Y2; realtype Z1 = init_Z1; realtype Z2 = init_Z2; NV_Ith_S(state, 0) = init_Y2; NV_Ith_S(state, 1) = init_V1; NV_Ith_S(state, 2) = init_Y1; NV_Ith_S(state, 3) = init_V2; NV_Ith_S(state, 4) = init_X2; NV_Ith_S(state, 5) = init_X1; NV_Ith_S(state, 6) = init_Z1; NV_Ith_S(state, 7) = init_Z2; reltol = RTOL; NV_Ith_S(abstol,0) = ATOL0; NV_Ith_S(abstol,1) = ATOL1; NV_Ith_S(abstol,2) = ATOL2; NV_Ith_S(abstol,3) = ATOL3; NV_Ith_S(abstol,4) = ATOL4; NV_Ith_S(abstol,5) = ATOL5; NV_Ith_S(abstol,6) = ATOL6; NV_Ith_S(abstol,7) = ATOL7; /* Allocations and initializations */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeInit(cvode_mem, dstate_dt, T0, state); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSetUserData(cvode_mem, p); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); printf(" \n Integrating Locke2008_Circadian_Clock_0 \n\n"); printf("#t Y2, V1, Y1, V2, X2, X1, Z1, Z2, \n"); PrintOutput(pout, t, state); tout = DT; while(1) { flag = CVode(cvode_mem, tout, state, &t, CV_NORMAL); { PrintOutput(pout, t, state); if(check_flag(&flag, "CVode", 1)) break; if(flag == CV_SUCCESS) { tout += DT; } if (t >= T1) break; } } PrintFinalStats(cvode_mem); N_VDestroy_Serial(state); N_VDestroy_Serial(abstol); CVodeFree(&cvode_mem); fclose(pout); return(0); }
void Cvode::initialize() { _properties = dynamic_cast<ISystemProperties*>(_system); _continuous_system = dynamic_cast<IContinuous*>(_system); _event_system = dynamic_cast<IEvent*>(_system); _mixed_system = dynamic_cast<IMixedSystem*>(_system); _time_system = dynamic_cast<ITime*>(_system); IGlobalSettings* global_settings = dynamic_cast<ISolverSettings*>(_cvodesettings)->getGlobalSettings(); // Kennzeichnung, dass initialize()() (vor der Integration) aufgerufen wurde _idid = 5000; _tLastEvent = 0.0; _event_n = 0; SolverDefaultImplementation::initialize(); _dimSys = _continuous_system->getDimContinuousStates(); _dimZeroFunc = _event_system->getDimZeroFunc(); if (_dimSys == 0) _dimSys = 1; // introduce dummy state if (_dimSys <= 0) { _idid = -1; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } else { // Allocate state vectors, stages and temporary arrays if (_z) delete[] _z; if (_zInit) delete[] _zInit; if (_zWrite) delete[] _zWrite; if (_zeroSign) delete[] _zeroSign; if (_absTol) delete[] _absTol; if(_delta) delete [] _delta; if(_deltaInv) delete [] _deltaInv; if(_ysave) delete [] _ysave; _z = new double[_dimSys]; _zInit = new double[_dimSys]; _zWrite = new double[_dimSys]; _zeroSign = new int[_dimZeroFunc]; _absTol = new double[_dimSys]; _delta =new double[_dimSys]; _deltaInv =new double[_dimSys]; _ysave =new double[_dimSys]; memset(_z, 0, _dimSys * sizeof(double)); memset(_zInit, 0, _dimSys * sizeof(double)); memset(_ysave, 0, _dimSys * sizeof(double)); // Counter initialisieren _outStps = 0; if (_cvodesettings->getDenseOutput()) { // Ausgabeschrittweite _hOut = global_settings->gethOutput(); } // Allocate memory for the solver _cvodeMem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void*) _cvodeMem, "CVodeCreate", 0)) { _idid = -5; throw ModelicaSimulationError(SOLVER,/*_idid,_tCurrent,*/"Cvode::initialize()"); } // // Make Cvode ready for integration // // Set initial values for CVODE _continuous_system->evaluateAll(IContinuous::CONTINUOUS); _continuous_system->getContinuousStates(_zInit); memcpy(_z, _zInit, _dimSys * sizeof(double)); // Get nominal values _absTol[0] = 1.0; // in case of dummy state _continuous_system->getNominalStates(_absTol); for (int i = 0; i < _dimSys; i++) _absTol[i] *= dynamic_cast<ISolverSettings*>(_cvodesettings)->getATol(); _CV_y0 = N_VMake_Serial(_dimSys, _zInit); _CV_y = N_VMake_Serial(_dimSys, _z); _CV_yWrite = N_VMake_Serial(_dimSys, _zWrite); _CV_absTol = N_VMake_Serial(_dimSys, _absTol); if (check_flag((void*) _CV_y0, "N_VMake_Serial", 0)) { _idid = -5; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } // Initialize Cvode (Initial values are required) _idid = CVodeInit(_cvodeMem, CV_fCallback, _tCurrent, _CV_y0); if (_idid < 0) { _idid = -5; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } // Set Tolerances _idid = CVodeSVtolerances(_cvodeMem, dynamic_cast<ISolverSettings*>(_cvodesettings)->getRTol(), _CV_absTol); // RTOL and ATOL if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); // Set the pointer to user-defined data _idid = CVodeSetUserData(_cvodeMem, _data); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); _idid = CVodeSetInitStep(_cvodeMem, 1e-6); // INITIAL STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); _idid = CVodeSetMaxOrd(_cvodeMem, 5); // Max Order if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = CVodeSetMaxConvFails(_cvodeMem, 100); // Maximale Fehler im Konvergenztest if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = CVodeSetStabLimDet(_cvodeMem, TRUE); // Stability Detection if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = CVodeSetMinStep(_cvodeMem, dynamic_cast<ISolverSettings*>(_cvodesettings)->getLowerLimit()); // MINIMUM STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxStep(_cvodeMem, global_settings->getEndTime() / 10.0); // MAXIMUM STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxNonlinIters(_cvodeMem, 5); // Max number of iterations if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxErrTestFails(_cvodeMem, 100); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxNumSteps(_cvodeMem, 1e3); // Max Number of steps if (_idid < 0) throw ModelicaSimulationError(SOLVER,/*_idid,_tCurrent,*/"Cvode::initialize()"); // Initialize linear solver #ifdef USE_SUNDIALS_LAPACK _idid = CVLapackDense(_cvodeMem, _dimSys); #else _idid = CVDense(_cvodeMem, _dimSys); #endif if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); // Use own jacobian matrix // Check if Colored Jacobians are worth to use #if SUNDIALS_MAJOR_VERSION >= 2 || (SUNDIALS_MAJOR_VERSION == 2 && SUNDIALS_MINOR_VERSION >= 4) _maxColors = _system->getAMaxColors(); if(_maxColors < _dimSys && _continuous_system->getDimContinuousStates() > 0) { // _idid = CVDlsSetDenseJacFn(_cvodeMem, &CV_JCallback); // initializeColoredJac(); } #endif if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); if (_dimZeroFunc) { _idid = CVodeRootInit(_cvodeMem, _dimZeroFunc, &CV_ZerofCallback); memset(_zeroSign, 0, _dimZeroFunc * sizeof(int)); _idid = CVodeSetRootDirection(_cvodeMem, _zeroSign); if (_idid < 0) throw ModelicaSimulationError(SOLVER,/*_idid,_tCurrent,*/"CVode::initialize()"); memset(_zeroSign, -1, _dimZeroFunc * sizeof(int)); memset(_zeroVal, -1, _dimZeroFunc * sizeof(int)); } _cvode_initialized = true; LOGGER_WRITE("Cvode: initialized",LC_SOLV,LL_DEBUG); } }
/** * Solves an initial value problem using CVODES to integrate over a system of * ODEs with optional forward sensitivity analysis. The initial conditions for * the system and for the sensitivity analysis are expected to be in the first * rows of simdata and sensitivities, respectively. * * @param [in] rhs the right-hand side of the system of ODEs * @param [in] num_timepoints the number of timepoints * @param [in] num_species the number of independent variables * @param [in] num_sens the number of parameters to compute sensitivities * for (set to zero to disable sensitivity * calculations) * @param [in] timepoints the timepoints at which data is to be returned * @param [in] params parameters * @param [in] sensi the indices of the parameters to compute the * sensitivities for (may be NULL to compute the * sensitivities for all parameters) * @param [in] options additional options for the integrator * @param [out] simdata contains the state values for each species at * each timepoint in column-major order. * @param [out] sensitivities sensitivities of each parameter in sensi * with respect to each independent variable. * The sensitivity of parameter j with respect to * variable k at timepoint i is stored at * (j * num_species + k) * lds + i. * May be NULL if sensitivities are not to be * calculated. * @param [in] lds leading dimension of simdata and sensitivities * * @return 0 on success, * GMCMC_ENOMEM if there was not enough memory to create the solver, * GMCMC_EINVAL if there was an invalid argument to the function, * GMCMC_ELINAL if the solution could not be found. */ int cvodes_solve(gmcmc_ode_rhs rhs, size_t num_timepoints, size_t num_species, size_t num_params, size_t num_sens, const double * timepoints, const double * params, const size_t * sensi, const cvodes_options * options, double * simdata, double * sensitivities, size_t lds) { int error; // Set vector of initial values N_Vector y = N_VNew_Serial((long int)num_species); for (size_t j = 0; j < num_species; j++) NV_Ith_S(y, j) = simdata[j * lds]; // Create CVODES object void * cvode_mem; if ((cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON)) == NULL) GMCMC_ERROR("Failed to allocate ODE solver", GMCMC_ENOMEM); // Initialise CVODES solver if ((error = CVodeInit(cvode_mem, cvodes_rhs, timepoints[0], y)) != CV_SUCCESS) { CVodeFree(&cvode_mem); GMCMC_ERROR("Failed to initialise ODE solver", (error == CV_ILL_INPUT) ? GMCMC_EINVAL : GMCMC_ENOMEM); } // Set integration tolerances if ((error = CVodeSStolerances(cvode_mem, options->reltol, options->abstol)) != CV_SUCCESS) { CVodeFree(&cvode_mem); GMCMC_ERROR("Failed to set ODE solver integration tolerances", (error == CV_ILL_INPUT) ? GMCMC_EINVAL : GMCMC_ENOMEM); } // Create a copy of the parameters in case CVODES modifies them realtype * sens_params; if ((sens_params = malloc(num_params * sizeof(realtype))) == NULL) { CVodeFree(&cvode_mem); GMCMC_ERROR("Failed to allocate copy of parameter vector for sensitivity analysis", GMCMC_ENOMEM); } for (size_t i = 0; i < num_params; i++) sens_params[i] = (realtype)params[i]; // Set optional inputs cvodes_userdata userdata = { rhs, sens_params }; if ((error = CVodeSetUserData(cvode_mem, &userdata)) != CV_SUCCESS) { CVodeFree(&cvode_mem); free(sens_params); GMCMC_ERROR("Failed to set ODE solver user data", GMCMC_EINVAL); } // Attach linear solver module if ((error = CVLapackDense(cvode_mem, (int)num_species)) != CV_SUCCESS) { CVodeFree(&cvode_mem); free(sens_params); GMCMC_ERROR("Failed to attach ODE solver module", (error == CV_ILL_INPUT) ? GMCMC_EINVAL : GMCMC_ENOMEM); } N_Vector * yS = NULL; int * plist = NULL; if (num_sens > 0) { // Set sensitivity initial conditions yS = N_VCloneVectorArray_Serial((int)num_sens, y); for (size_t j = 0; j < num_sens; j++) { for (size_t i = 0; i < num_species; i++) NV_Ith_S(yS[j], i) = sensitivities[(j * num_species + i) * lds]; } // Activate sensitivity calculations // Use default finite differences if ((error = CVodeSensInit(cvode_mem, (int)num_sens, CV_SIMULTANEOUS, NULL, yS)) != CV_SUCCESS) { CVodeFree(&cvode_mem); free(sens_params); GMCMC_ERROR("Failed to activate ODE solver sensitivity calculations", (error == CV_ILL_INPUT) ? GMCMC_EINVAL : GMCMC_ENOMEM); } // Set sensitivity tolerances if ((error = CVodeSensEEtolerances(cvode_mem)) != CV_SUCCESS) { CVodeFree(&cvode_mem); free(sens_params); GMCMC_ERROR("Failed to set ODE solver sensitivity tolerances", (error == CV_ILL_INPUT) ? GMCMC_EINVAL : GMCMC_ENOMEM); } if (sensi != NULL) { if ((plist = malloc(num_sens * sizeof(int))) == NULL) { CVodeFree(&cvode_mem); free(sens_params); GMCMC_ERROR("Failed to allocate sensitivity parameter list", GMCMC_ENOMEM); } for (size_t i = 0; i < num_sens; i++) plist[i] = (int)sensi[i]; } // Set sensitivity analysis optional inputs if ((error = CVodeSetSensParams(cvode_mem, sens_params, NULL, plist)) != CV_SUCCESS) { CVodeFree(&cvode_mem); free(plist); free(sens_params); GMCMC_ERROR("Failed to set ODE solver sensitivity parameters", (error == CV_ILL_INPUT) ? GMCMC_EINVAL : GMCMC_ENOMEM); } } // Advance solution in time realtype tret; for (size_t i = 1; i < num_timepoints; i++) { if ((error = CVode(cvode_mem, timepoints[i], y, &tret, CV_NORMAL)) != CV_SUCCESS) { free(plist); free(sens_params); CVodeFree(&cvode_mem); GMCMC_ERROR("Failed to advance ODE solution", GMCMC_ELINAL); } for (size_t j = 0; j < num_species; j++) simdata[j * lds + i] = NV_Ith_S(y, j); // Extract the sensitivity solution if (yS != NULL) { if ((error = CVodeGetSens(cvode_mem, &tret, yS)) != CV_SUCCESS) { free(plist); free(sens_params); CVodeFree(&cvode_mem); GMCMC_ERROR("Failed to extract ODE sensitivity solution", GMCMC_ELINAL); } for (size_t j = 0; j < num_sens; j++) { for (size_t k = 0; k < num_species; k++) sensitivities[(j * num_species + k) * lds + i] = NV_Ith_S(yS[j], k); } } } N_VDestroy(y); if (yS != NULL) N_VDestroyVectorArray_Serial(yS, (int)num_sens); free(plist); free(sens_params); // Free solver memory CVodeFree(&cvode_mem); return 0; }
int main() { realtype abstol, reltol, t, tout; N_Vector u; UserData data; void *cvode_mem; int iout, flag; u = NULL; data = NULL; cvode_mem = NULL; /* Allocate memory, and set problem data, initial values, tolerances */ u = N_VNew_Serial(NEQ); if(check_flag((void *)u, "N_VNew_Serial", 0)) return(1); data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); SetInitialProfiles(u, data->dx, data->dy); abstol=ATOL; reltol=RTOL; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* Call CVSpgmr to specify the linear solver CVSPGMR * with left preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); /* set the JAcobian-times-vector function */ flag = CVSpilsSetJacTimesVecFn(cvode_mem, jtv); if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1); /* Set modified Gram-Schmidt orthogonalization */ flag = CVSpilsSetGSType(cvode_mem, MODIFIED_GS); if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1); /* Set the preconditioner solve and setup functions */ flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /* In loop over output points, call CVode, print results, test for error */ printf(" \n2-species diurnal advection-diffusion problem\n\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); PrintOutput(cvode_mem, u, t); if(check_flag(&flag, "CVode", 1)) break; } PrintFinalStats(cvode_mem); /* Free memory */ N_VDestroy_Serial(u); FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
void CvodeSolver::initialize(const double &pVoiStart, const int &pStatesCount, double *pConstants, double *pStates, double *pRates, double *pAlgebraic, ComputeRatesFunction pComputeRates) { if (!mSolver) { // Initialise the ODE solver itself OpenCOR::CoreSolver::CoreOdeSolver::initialize(pVoiStart, pStatesCount, pConstants, pStates, pRates, pAlgebraic, pComputeRates); // Retrieve some of the CVODE properties if (mProperties.contains(MaximumStepProperty)) { mMaximumStep = mProperties.value(MaximumStepProperty).toDouble(); } else { emit error(QObject::tr("the 'maximum step' property value could not be retrieved")); return; } if (mProperties.contains(MaximumNumberOfStepsProperty)) { mMaximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsProperty).toInt(); } else { emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved")); return; } if (mProperties.contains(RelativeToleranceProperty)) { mRelativeTolerance = mProperties.value(RelativeToleranceProperty).toDouble(); } else { emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved")); return; } if (mProperties.contains(AbsoluteToleranceProperty)) { mAbsoluteTolerance = mProperties.value(AbsoluteToleranceProperty).toDouble(); } else { emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved")); return; } // Create the states vector mStatesVector = N_VMake_Serial(pStatesCount, pStates); // Create the CVODE solver mSolver = CVodeCreate(CV_BDF, CV_NEWTON); // Use our own error handler CVodeSetErrHandlerFn(mSolver, errorHandler, this); // Initialise the CVODE solver CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector); // Set some user data delete mUserData; // Just in case the solver got initialised before mUserData = new CvodeSolverUserData(pConstants, pAlgebraic, pComputeRates); CVodeSetUserData(mSolver, mUserData); // Set the linear solver CVDense(mSolver, pStatesCount); // Set the maximum step CVodeSetMaxStep(mSolver, mMaximumStep); // Set the maximum number of steps CVodeSetMaxNumSteps(mSolver, mMaximumNumberOfSteps); // Set the relative and absolute tolerances CVodeSStolerances(mSolver, mRelativeTolerance, mAbsoluteTolerance); } else { // Reinitialise the CVODE object CVodeReInit(mSolver, pVoiStart, mStatesVector); } }