Example #1
0
  void CVodeInt::initialize(double t0, FuncEval& func) 
  {
    m_neq = func.neq();
    m_t0  = t0;

    if (m_y) {
      N_VFree(nv(m_y));    // free solution vector if already allocated
    }
    m_y = reinterpret_cast<void*>(N_VNew(m_neq, 0));   // allocate solution vector
    // check abs tolerance array size
    if (m_itol == 1 && m_nabs < m_neq) 
      throw CVodeErr("not enough absolute tolerance values specified.");
    func.getInitialConditions(m_t0, m_neq, N_VDATA(nv(m_y)));

    // set options
    m_iopt[MXSTEP] = m_maxsteps;
    m_iopt[MAXORD] = m_maxord;
    m_ropt[HMAX]   = m_hmax;

    if (m_cvode_mem) CVodeFree(m_cvode_mem);

    // pass a pointer to func in m_data 
    m_data = (void*)&func;

    if (m_itol) {
      m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, nv(m_y), m_method, 
				m_iter, m_itol, &m_reltol,
				nv(m_abstol), m_data, NULL, TRUE, m_iopt, 
				DATA_PTR(m_ropt), NULL);
    }
    else {
      m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, nv(m_y), m_method, 
				m_iter, m_itol, &m_reltol,
				&m_abstols, m_data, NULL, TRUE, m_iopt, 
				DATA_PTR(m_ropt), NULL);
    }

    if (!m_cvode_mem) throw CVodeErr("CVodeMalloc failed.");

    if (m_type == DENSE + NOJAC) {
      CVDense(m_cvode_mem, NULL, NULL);
    }
    else if (m_type == DENSE + JAC) {
      CVDense(m_cvode_mem, cvode_jac, NULL);
    }
    else if (m_type == DIAG) {
      CVDiag(m_cvode_mem);
    }
    else if (m_type == GMRES) {
      CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0,
	      NULL, NULL, NULL);
    }
    else {
      throw CVodeErr("unsupported option");
    }
  }
void ode_solver_init(ode_solver* solver, const double t0,  double* y0, int lenY, double* p, int lenP ){
  int i,flag;
  /* Get parameters */
  
  if (p != 0){
    if (lenP != solver->odeModel->P) {
      fprintf(stderr,"ode_solver_init: lenP must be equal %d, the number of parameters in the ode model.\n",solver->odeModel->P);
      return ;
    }
    
    for(i = 0; i < solver->odeModel->P; i++)
      solver->params[i] = p[i];
  }
  
  /* Get initial conditions */
  if(y0 != 0){
    if( lenY != solver->odeModel->N ){
      fprintf(stderr,"ode_solver_init: lenY must be equal %d, the number of variables in the ode model.\n",solver->odeModel->N);
      return ;
    }
    NV_DATA_S(solver->y) = y0;
  }
  
  /* initialise */
  flag = CVodeInit(solver->cvode_mem, solver->odeModel->vf_eval, t0, solver->y);
  flag = CVodeSetUserData(solver->cvode_mem, solver->params);
  flag = CVDense(solver->cvode_mem, solver->odeModel->N);
  flag = CVDlsSetDenseJacFn(solver->cvode_mem, solver->odeModel->vf_jac);
  flag = CVodeSStolerances(solver->cvode_mem, ODE_SOLVER_REL_ERR, ODE_SOLVER_ABS_ERR);
  flag = CVodeSetMaxNumSteps(solver->cvode_mem, ODE_SOLVER_MX_STEPS);
  
}
Example #3
0
  void CVodeInt::reinitialize(double t0, FuncEval& func) 
  {
    m_t0  = t0;
    func.getInitialConditions(m_t0, m_neq, N_VDATA(nv(m_y)));

    // set options
    m_iopt[MXSTEP] = m_maxsteps;
    m_iopt[MAXORD] = m_maxord;
    m_ropt[HMAX]   = m_hmax;

    //if (m_cvode_mem) CVodeFree(m_cvode_mem);

    // pass a pointer to func in m_data 
    m_data = (void*)&func;
    int result;
    if (m_itol) {
      result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, nv(m_y), m_method, 
			m_iter, m_itol, &m_reltol,
			nv(m_abstol), m_data, NULL, TRUE, m_iopt, 
			DATA_PTR(m_ropt), NULL);
    }
    else {
      result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, nv(m_y), m_method, 
			m_iter, m_itol, &m_reltol,
			&m_abstols, m_data, NULL, TRUE, m_iopt, 
			DATA_PTR(m_ropt), NULL);
    }

    if (result != 0) throw CVodeErr("CVReInit failed.");

    if (m_type == DENSE + NOJAC) {
      CVDense(m_cvode_mem, NULL, NULL);
    }
    else if (m_type == DENSE + JAC) {
      CVDense(m_cvode_mem, cvode_jac, NULL);
    }
    else if (m_type == DIAG) {
      CVDiag(m_cvode_mem);
    }
    else if (m_type == GMRES) {
      CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0,
	      NULL, NULL, NULL);
    }
    else {
      throw CVodeErr("unsupported option");
    }
  }
Example #4
0
static int PrepareNextRun(void *cvode_mem, int lmm, int miter, 
                          long int mu, long int ml)
{
  int flag = CV_SUCCESS;
  
  printf("\n\n-------------------------------------------------------------");
  
  printf("\n\nLinear Multistep Method : ");
  if (lmm == CV_ADAMS) {
    printf("ADAMS\n");
  } else {
    printf("BDF\n");
  }
  
  printf("Iteration               : ");
  if (miter == FUNC) {
    printf("FUNCTIONAL\n");
  } else {
    printf("NEWTON\n");
    printf("Linear Solver           : ");
    switch(miter) {
    case DENSE_USER : 
      printf("Dense, User-Supplied Jacobian\n");
      flag = CVDense(cvode_mem, P1_NEQ);
      check_flag(&flag, "CVDense", 1);
      if(flag != CV_SUCCESS) break;
      flag = CVDenseSetJacFn(cvode_mem, Jac1, NULL);
      check_flag(&flag, "CVDenseSetJacFn", 1);
      break;
    case DENSE_DQ   : 
      printf("Dense, Difference Quotient Jacobian\n");
      flag = CVDenseSetJacFn(cvode_mem, NULL, NULL);
      check_flag(&flag, "CVDenseSetJacFn", 1);
      break;
    case DIAG       : 
      printf("Diagonal Jacobian\n");
      flag = CVDiag(cvode_mem);
      check_flag(&flag, "CVDiag", 1);
      break;
    case BAND_USER  : 
      printf("Band, User-Supplied Jacobian\n");
      flag = CVBand(cvode_mem, P2_NEQ, mu, ml);
      check_flag(&flag, "CVBand", 1);
      if(flag != CV_SUCCESS) break;
      flag = CVBandSetJacFn(cvode_mem, Jac2, NULL);
      check_flag(&flag, "CVBandSetJacFn", 1);
      break;
    case BAND_DQ  :   
      printf("Band, Difference Quotient Jacobian\n");
      flag = CVBandSetJacFn(cvode_mem, NULL, NULL);
      check_flag(&flag, "CVBandSetJacFn", 1);
      break;    
    }
  }

  return(flag);
}
Example #5
0
void FCV_DENSE(long int *neq, int *ier)
{
  /* 
     neq  is the problem size
  */

  *ier = CVDense(CV_cvodemem, *neq);

  CV_ls = 1;
}
Example #6
0
int CVDenseB(void *cvadj_mem, long int nB)
{
  CVadjMem ca_mem;
  void *cvode_mem;
  int flag;

  if (cvadj_mem == NULL) return(CV_ADJMEM_NULL);
  ca_mem = (CVadjMem) cvadj_mem;

  cvode_mem = (void *) ca_mem->cvb_mem;
  
  flag = CVDense(cvode_mem, nB);

  return(flag);
}
void CVodesIntegrator::applyOptions()
{
    if (m_type == DENSE + NOJAC) {
        sd_size_t N = static_cast<sd_size_t>(m_neq);
        #if SUNDIALS_USE_LAPACK
            CVLapackDense(m_cvode_mem, N);
        #else
            CVDense(m_cvode_mem, N);
        #endif
    } else if (m_type == DIAG) {
        CVDiag(m_cvode_mem);
    } else if (m_type == GMRES) {
        CVSpgmr(m_cvode_mem, PREC_NONE, 0);
    } else if (m_type == BAND + NOJAC) {
        sd_size_t N = static_cast<sd_size_t>(m_neq);
        long int nu = m_mupper;
        long int nl = m_mlower;
        #if SUNDIALS_USE_LAPACK
            CVLapackBand(m_cvode_mem, N, nu, nl);
        #else
            CVBand(m_cvode_mem, N, nu, nl);
        #endif
    } else {
        throw CanteraError("CVodesIntegrator::applyOptions",
                           "unsupported option");
    }

    if (m_maxord > 0) {
        CVodeSetMaxOrd(m_cvode_mem, m_maxord);
    }
    if (m_maxsteps > 0) {
        CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
    }
    if (m_hmax > 0) {
        CVodeSetMaxStep(m_cvode_mem, m_hmax);
    }
    if (m_hmin > 0) {
        CVodeSetMinStep(m_cvode_mem, m_hmin);
    }
    if (m_maxErrTestFails > 0) {
        CVodeSetMaxErrTestFails(m_cvode_mem, m_maxErrTestFails);
    }
}
Example #8
0
cvode_mem *SOLVER(cvode, init, TARGET, SIMENGINE_STORAGE, solver_props *props){
  cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem));
  unsigned int modelid;

  // Only need to create this buffer in the first memory space as we are using this only for scratch
  // and outside of the CVODE solver to compute the last outputs
  mem[0].k1 = (CDATAFORMAT*)malloc(props->statesize*props->num_models*sizeof(CDATAFORMAT));

  for(modelid=0; modelid<props->num_models; modelid++){
    // Set the modelid on a per memory structure basis
    mem[modelid].modelid = modelid;
    // Store solver properties
    mem[modelid].props = props;
    // Create intial value vector
    // This is done to avoid having the change the internal indexing within the flows and for the output_buffer
    mem[modelid].y0 = N_VMake_Serial(props->statesize, &(props->model_states[modelid*props->statesize]));
    // Create data structure for solver
    mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON);
    // Initialize CVODE
    if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, ((N_Vector)(mem[modelid].y0))) != CV_SUCCESS){
      fprintf(stderr, "Couldn't initialize CVODE");
    }
    // Set solver tolerances
    if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){
      fprintf(stderr, "Could not set CVODE tolerances");
    }
    // Set linear solver
    if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){
      fprintf(stderr, "Could not set CVODE linear solver");
    }
    // Set user data to contain pointer to memory structure for use in model_flows
    if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){
      fprintf(stderr, "CVODE failed to initialize user data");
    }
  }

  return mem;
}
Example #9
0
int main(int narg, char **args)
{
    realtype reltol, t, tout;
    N_Vector state, abstol;
    void *cvode_mem;
    int flag, flagr;
    int rootsfound[NRF];
    int rootdir[] = {1,};

    FILE *pout;
    if(!(pout = fopen("results/iaf_v.dat", "w"))){
        fprintf(stderr, "Cannot open file results/iaf_v.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 reset = -0.07;
    realtype C = 3.2e-12;
    realtype thresh = -0.055;
    realtype gleak = 2e-10;
    realtype eleak = -0.053;
    realtype p[] = {reset, C, thresh, gleak, eleak, };

    realtype v = reset;
    NV_Ith_S(state, 0) = reset;

    reltol = RTOL;
    NV_Ith_S(abstol,0) = ATOL0;
 
    /* 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 = CVodeRootInit(cvode_mem, NRF, root_functions);
    if (check_flag(&flag, "CVodeRootInit", 1)) return(1);

    CVodeSetRootDirection(cvode_mem, rootdir);
    if (check_flag(&flag, "CVodeSetRootDirection", 1)) return(1);
        
   
    flag = CVDense(cvode_mem, NEQ);
    if (check_flag(&flag, "CVDense", 1)) return(1);


    printf(" \n Integrating iaf \n\n");
    printf("#t v, \n");
    PrintOutput(pout, t, state);
   
    tout = DT;
    while(1) {
        flag = CVode(cvode_mem, tout, state, &t, CV_NORMAL);
        
        if(flag == CV_ROOT_RETURN) {
            /* Event detected */
            flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
            if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
            PrintRootInfo(t, state, rootsfound);
          
            if(rootsfound[0]){
                //condition_0
                v = NV_Ith_S(state, 0);
                NV_Ith_S(state, 0) = reset;

        }
            

        /* Restart integration with event-corrected state */
            flag = CVodeSetUserData(cvode_mem, p);
            if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
        CVodeReInit(cvode_mem, t, state);
        //PrintRootInfo(t, state, rootsfound);
    }
        else
                {
            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);
}
Example #10
0
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);
}
Example #11
0
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);
}
Example #12
0
int cvode_init(solver_props *props){
  assert(props->statesize > 0);

  cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem));
  unsigned int modelid;

  props->mem = mem;

  for(modelid=0; modelid<props->num_models; modelid++){
    // Set location to store the value of the next states
    mem[modelid].next_states = &(props->next_states[modelid*props->statesize]);
    mem[modelid].props = props;
    // Set the modelid on a per memory structure basis
    mem[modelid].modelid = modelid;
    // Create intial value vector
    // This is done to avoid having the change the internal indexing within the flows and for the output_buffer
    mem[modelid].y0 = N_VMake_Serial(props->statesize, mem[modelid].next_states);
    // Create data structure for solver
    //    mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON);
    mem[modelid].cvmem = CVodeCreate(props->cvode.lmm, props->cvode.iter);
    
    // Initialize CVODE
    if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, mem[modelid].y0) != CV_SUCCESS){
      PRINTF( "Couldn't initialize CVODE");
    }
    // Set CVODE error handler
    if(CVodeSetErrHandlerFn(mem[modelid].cvmem, cvode_err_handler, mem)){
      PRINTF( "Couldn't set CVODE error handler");
    }
    // Set solver tolerances
    if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){
      PRINTF( "Could not set CVODE tolerances");
    }
    // Set maximum order
    if(CVodeSetMaxOrd(mem[modelid].cvmem, props->cvode.max_order) != CV_SUCCESS) {
      PRINTF( "Could not set CVODE maximum order");
    }
    // Set linear solver
    switch (props->cvode.solv) {
    case CVODE_DENSE:
      if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){
	PRINTF( "Could not set CVODE DENSE linear solver");
      }
      break;
    case CVODE_DIAG:
      if(CVDiag(mem[modelid].cvmem) != CV_SUCCESS){
	PRINTF( "Could not set CVODE DIAG linear solver");
      }
      break;
    case CVODE_BAND:
      if(CVBand(mem[modelid].cvmem, mem[modelid].props->statesize, mem[modelid].props->cvode.upperhalfbw, mem[modelid].props->cvode.lowerhalfbw) != CV_SUCCESS){
	PRINTF( "Could not set CVODE BAND linear solver");
      }
      break;
    default:
      PRINTF( "No valid CVODE solver passed");
      }

    // Set user data to contain pointer to memory structure for use in model_flows
    if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){
      PRINTF( "CVODE failed to initialize user data");
    }
  }

  return 0;
}
Example #13
0
int CVDenseB(void *cvode_mem, int which, long int nB)
{
  CVodeMem cv_mem;
  CVadjMem ca_mem;
  CVodeBMem cvB_mem;
  void *cvodeB_mem;
  CVDlsMemB cvdlsB_mem;
  int flag;

  /* Check if cvode_mem exists */
  if (cvode_mem == NULL) {
    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDENSE", "CVDenseB", MSGD_CVMEM_NULL);
    return(CVDLS_MEM_NULL);
  }
  cv_mem = (CVodeMem) cvode_mem;

  /* Was ASA initialized? */
  if (cv_mem->cv_adjMallocDone == FALSE) {
    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDENSE", "CVDenseB", MSGD_NO_ADJ);
    return(CVDLS_NO_ADJ);
  } 
  ca_mem = cv_mem->cv_adj_mem;

  /* Check which */
  if ( which >= ca_mem->ca_nbckpbs ) {
    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDENSE", "CVDenseB", MSGD_BAD_WHICH);
    return(CVDLS_ILL_INPUT);
  }

  /* Find the CVodeBMem entry in the linked list corresponding to which */
  cvB_mem = ca_mem->cvB_mem;
  while (cvB_mem != NULL) {
    if ( which == cvB_mem->cv_index ) break;
    cvB_mem = cvB_mem->cv_next;
  }

  cvodeB_mem = (void *) (cvB_mem->cv_mem);

  /* Get memory for CVDlsMemRecB */
  cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB));
  if (cvdlsB_mem == NULL) {
    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDenseB", MSGD_MEM_FAIL);
    return(CVDLS_MEM_FAIL);
  }

  /* set matrix type */
  cvdlsB_mem->d_typeB = SUNDIALS_DENSE;

  /* initialize Jacobian function */
  cvdlsB_mem->d_djacB = NULL;

  /* attach lmemB and lfreeB */
  cvB_mem->cv_lmem = cvdlsB_mem;
  cvB_mem->cv_lfree = cvDenseFreeB;

  flag = CVDense(cvodeB_mem, nB);

  if (flag != CVDLS_SUCCESS) {
    free(cvdlsB_mem);
    cvdlsB_mem = NULL;
  }

  return(flag);
}
Example #14
0
/*
 * Functions to use CVODES
 *
 */
struct Integrator* CreateIntegrator(struct Simulation* sim,
		class ExecutableModel* em)
{
  if (!(sim && em))
  {
    ERROR("CreateIntegrator","Invalid arguments when creating integrator");
    return((struct Integrator*)NULL);
  }
  int flag,mlmm,miter;
  struct Integrator* integrator =
    (struct Integrator*)malloc(sizeof(struct Integrator));
  integrator->y = NULL;
  integrator->cvode_mem = NULL;
  integrator->simulation = simulationClone(sim);
  // FIXME: really need to handle this properly, but for now simply grabbing a handle.
  integrator->em = em;

  /* Check for errors in the simulation */
  if (simulationGetATolLength(integrator->simulation) < 1)
  {
    ERROR("CreateIntegrator","Absolute tolerance(s) not set\n");
    DestroyIntegrator(&integrator);
    return(NULL);
  }
  /* Would be good if we didn't require the specification of the
     tabulation step size, but for now it is required so we should
     check that it has a sensible value */
  if (!simulationIsBvarTabStepSet(integrator->simulation))
  {
    ERROR("CreateIntegrator","Tabulation step size must be set\n");
    DestroyIntegrator(&integrator);
    return(NULL);
  }
  /* start and end also needs to be set */
  if (!simulationIsBvarStartSet(integrator->simulation))
  {
    ERROR("CreateIntegrator","Bound variable interval start must be set\n");
    DestroyIntegrator(&integrator);
    return(NULL);
  }
  if (!simulationIsBvarEndSet(integrator->simulation))
  {
    ERROR("CreateIntegrator","Bound variable interval end must be set\n");
    DestroyIntegrator(&integrator);
    return(NULL);
  }

  /* Create serial vector of length NR for I.C. */
  integrator->y = N_VNew_Serial(em->nRates);
  if (check_flag((void *)(integrator->y),"N_VNew_Serial",0))
  {
    DestroyIntegrator(&integrator);
    return(NULL);
  }
  /* Initialize y */
  realtype* yD = NV_DATA_S(integrator->y);
  int i;
  for (i=0;i<(em->nRates);i++) yD[i] = (realtype)(em->states[i]);

  /* adjust parameters accordingly */
  switch (simulationGetMultistepMethod(integrator->simulation))
  {
    case ADAMS:
    {
      mlmm = CV_ADAMS;
      break;
    }
    case BDF:
    {
      mlmm = CV_BDF;
      break;
    }
    default:
    {
      ERROR("CreateIntegrator","Invalid multistep method choice\n");
      DestroyIntegrator(&integrator);
      return(NULL);
    }
  }
  switch (simulationGetIterationMethod(integrator->simulation))
  {
    case FUNCTIONAL:
    {
      miter = CV_FUNCTIONAL;
      break;
    }
    case NEWTON:
    {
      miter = CV_NEWTON;
      break;
    }
    default:
    {
      ERROR("CreateIntegrator","Invalid iteration method choice\n");
      DestroyIntegrator(&integrator);
      return(NULL);
    }
  }
  /* 
     Call CVodeCreate to create the solver memory:     
     A pointer to the integrator problem memory is returned and
     stored in cvode_mem.
  */
  integrator->cvode_mem = CVodeCreate(mlmm,miter);
  if (check_flag((void *)(integrator->cvode_mem),"CVodeCreate",0))
  {
    DestroyIntegrator(&integrator);
    return(NULL);
  }
  
  /* 
     Call CVodeMalloc to initialize the integrator memory: 
     
     cvode_mem is the pointer to the integrator memory returned by CVodeCreate
     f         is the user's right hand side function in y'=f(t,y)
     tStart    is the initial time
     y         is the initial dependent variable vector
     CV_SS     specifies scalar relative and absolute tolerances
     reltol    the scalar relative tolerance
     &abstol   is the absolute tolerance vector
  */
  flag = CVodeInit(integrator->cvode_mem,f,
    simulationGetBvarStart(integrator->simulation),integrator->y);
  if (check_flag(&flag,"CVodeMalloc",1))
  {
	  DestroyIntegrator(&integrator);
      return(NULL);
  }

  double* atol = simulationGetATol(integrator->simulation);
  if (simulationGetATolLength(integrator->simulation) == 1)
  {
	  flag = CVodeSStolerances(integrator->cvode_mem,simulationGetRTol(integrator->simulation),atol[0]);
	  if (check_flag(&flag,"CVodeSStolerances",1))
	  {
		  DestroyIntegrator(&integrator);
		  return(NULL);
	  }
  }
  else
  {
	  ERROR("CreateIntegrator", "array abstol not supported yet.");
	  DestroyIntegrator(&integrator);
	  return(NULL);
  }
  free(atol);

  /* if using Newton iteration need a linear solver */
  if (simulationGetIterationMethod(integrator->simulation) == NEWTON)
  {
    switch (simulationGetLinearSolver(integrator->simulation))
    {
      case DENSE:
      {
        /* Call CVDense to specify the CVDENSE dense linear solver */
        flag = CVDense(integrator->cvode_mem,em->nRates);
        if (check_flag(&flag,"CVDense",1))
        {
          DestroyIntegrator(&integrator);
          return(NULL);
        }
      } break;
      case BAND:
      {
        /* Call CVBand to specify the CVBAND linear solver */
        long int upperBW = em->nRates - 1; /* FIXME: This probably doesn't make */
        long int lowerBW = em->nRates - 1; /* any sense, but should do until I */
                                           /* fix it */
        flag = CVBand(integrator->cvode_mem,em->nRates,upperBW,lowerBW);
        if (check_flag(&flag,"CVBand",1))
        {
          DestroyIntegrator(&integrator);
          return(NULL);
        }
      } break;
      case DIAG:
      {
        /* Call CVDiag to specify the CVDIAG linear solver */
        flag = CVDiag(integrator->cvode_mem);
        if (check_flag(&flag,"CVDiag",1))
        {
          DestroyIntegrator(&integrator);
          return(NULL);
        }
      } break;
      case SPGMR:
      {
        /* Call CVSpgmr to specify the linear solver CVSPGMR 
           with no preconditioning and the maximum Krylov dimension maxl */
        flag = CVSpgmr(integrator->cvode_mem,PREC_NONE,0);
        if(check_flag(&flag,"CVSpgmr",1))
        {
          DestroyIntegrator(&integrator);
          return(NULL);
        }

      } break;
      case SPBCG:
      {
        /* Call CVSpbcg to specify the linear solver CVSPBCG 
           with no preconditioning and the maximum Krylov dimension maxl */
        flag = CVSpbcg(integrator->cvode_mem,PREC_NONE,0);
        if(check_flag(&flag,"CVSpbcg",1))
        {
          DestroyIntegrator(&integrator);
          return(NULL);
        }

      } break;
      case SPTFQMR:
      {
        /* Call CVSptfqmr to specify the linear solver CVSPTFQMR 
           with no preconditioning and the maximum Krylov dimension maxl */
        flag = CVSptfqmr(integrator->cvode_mem,PREC_NONE,0);
        if(check_flag(&flag,"CVSptfqmr",1))
        {
          DestroyIntegrator(&integrator);
          return(NULL);
        }

      } break;
      default:
      {
        ERROR("CreateIntegrator",
          "Must specify a valid linear solver when using "
          "Newton iteration\n");
        DestroyIntegrator(&integrator);
        return(NULL);
      }
    }
  }

  /* Pass through the executable model to f */
  // FIXME: really need to handle this properly, but for now simply grabbing a handle.
  flag = CVodeSetUserData(integrator->cvode_mem,(void*)(em));
  if (check_flag(&flag,"CVodeSetUserData",1))
  {
    DestroyIntegrator(&integrator);
    return(NULL);
  }

  /* Set the maximum time step size if it looks valid */
  double mxD = simulationGetBvarMaxStep(integrator->simulation);
  double tbD = simulationGetBvarTabStep(integrator->simulation);
  double maxStep;
  if (simulationIsBvarMaxStepSet(integrator->simulation))
  {
    flag = CVodeSetMaxStep(integrator->cvode_mem,
      (realtype)mxD);
    maxStep = mxD;
    if (check_flag(&flag,"CVodeSetMaxStep (max)",1))
    {
      DestroyIntegrator(&integrator);
      return(NULL);
    }
  }
  else
  {
    flag = CVodeSetMaxStep(integrator->cvode_mem,
      (realtype)tbD);
    maxStep = tbD;
    if (check_flag(&flag,"CVodeSetMaxStep (tab)",1))
    {
      DestroyIntegrator(&integrator);
      return(NULL);
    }
  }
  simulationSetBvarMaxStep(integrator->simulation,maxStep);
  simulationSetBvarMaxStep(sim,maxStep);
  /* try and make a sensible guess at the maximal number of steps to
     get to tout to take into account case where we simply want to
     integrate over a large time period in small steps (why?) */
  double tout = simulationGetBvarStart(integrator->simulation)+
    simulationGetBvarTabStep(integrator->simulation);
  if (simulationIsBvarEndSet(integrator->simulation))
  {
    double end = simulationGetBvarEnd(integrator->simulation);
    if (tout > end) tout = end;
  }
  long int maxsteps = (long int)ceil(tout/maxStep) * 100;
  if (maxsteps < 500) maxsteps = 500; /* default value */
  flag = CVodeSetMaxNumSteps(integrator->cvode_mem,maxsteps);
  if (check_flag(&flag,"CVodeSetMaxNumSteps",1))
  {
    DestroyIntegrator(&integrator);
    return(NULL);
  }
  return(integrator);
}
Example #15
0
int dynamixMain (int argc, char * argv[]) {



  //// DECLARING VARIABLES


  // Struct of parameters
  PARAMETERS p;
  // CVode variables
  void * cvode_mem = NULL;			// pointer to block of CVode memory
  N_Vector y, yout;			// arrays of populations

  // arrays for energetic parameters
  realtype ** V = NULL;				// pointer to k-c coupling constants
  realtype * Vbridge = NULL;			// pointer to array of bridge coupling constants.
  // first element [0] is Vkb1, last [Nb] is VcbN
  realtype * Vnobridge = NULL;			// coupling constant when there is no bridge

  //// Setting defaults for parameters to be read from input
  //// done setting defaults

  int flag;
  realtype * k_pops = NULL;				// pointers to arrays of populations
  realtype * l_pops = NULL;
  realtype * c_pops = NULL;
  realtype * b_pops = NULL;
  realtype * ydata = NULL;				// pointer to ydata (contains all populations)
  realtype * wavefunction = NULL;			// (initial) wavefunction
  realtype * dm = NULL;					// density matrix
  realtype * dmt = NULL;				// density matrix in time
  realtype * wfnt = NULL;				// density matrix in time
  realtype * k_energies = NULL;				// pointers to arrays of energies
  realtype * c_energies = NULL;
  realtype * b_energies = NULL;
  realtype * l_energies = NULL;
  realtype t0 = 0.0;				// initial time
  realtype t = 0;
  realtype tret = 0;					// time returned by the solver
  time_t startRun;				// time at start of log
  time_t endRun;					// time at end of log
  struct tm * currentTime = NULL;			// time structure for localtime
#ifdef DEBUG
  FILE * realImaginary;				// file containing real and imaginary parts of the wavefunction
#endif
  FILE * log;					// log file with run times
  realtype * tkprob = NULL; 				// total probability in k, l, c, b states at each timestep
  realtype * tlprob = NULL;
  realtype * tcprob = NULL;
  realtype * tbprob = NULL;
  double ** allprob = NULL;				// populations in all states at all times
  realtype * times = NULL;
  realtype * qd_est = NULL;
  realtype * qd_est_diag = NULL;
  std::string inputFile = "ins/parameters.in";			// name of input file
  std::string cEnergiesInput = "ins/c_energies.in";
  std::string cPopsInput = "ins/c_pops.in";
  std::string bEnergiesInput = "ins/b_energies.in";
  std::string VNoBridgeInput = "ins/Vnobridge.in";
  std::string VBridgeInput = "ins/Vbridge.in";
  std::map<const std::string, bool> outs;	// map of output file names to bool

  // default output directory
  p.outputDir = "outs/";

  double summ = 0;			// sum variable

  // ---- process command line flags ---- //
  opterr = 0;
  int c;
  std::string insDir;
  /* process command line options */
  while ((c = getopt(argc, argv, "i:o:")) != -1) {
    switch (c) {
      case 'i':
	// check that it ends in a slash
	std::cerr << "[dynamix]: assigning input directory" << std::endl;
	insDir = optarg;
	if (strcmp(&(insDir.at(insDir.length() - 1)), "/")) {
	  std::cerr << "ERROR: option -i requires argument ("
	            << insDir << ") to have a trailing slash (/)." << std::endl;
	  return 1;
	}
	else {
	  // ---- assign input files ---- //
	  inputFile = insDir + "parameters.in";
	  cEnergiesInput = insDir + "c_energies.in";
	  cPopsInput = insDir + "c_pops.in";
	  bEnergiesInput = insDir + "b_energies.in";
	  VNoBridgeInput = insDir + "Vnobridge.in";
	  VBridgeInput = insDir + "Vbridge.in";
	}
	break;
      case 'o':
	std::cerr << "[dynamix]: assigning output directory" << std::endl;
	p.outputDir = optarg;
	break;
      case '?':
	if (optopt == 'i') {
	  fprintf(stderr, "Option -%c requires a directory argument.\n", optopt);
	}
	else if (isprint(optopt)) {
	  fprintf(stderr, "Unknown option -%c.\n", optopt);
	}
	else {
	  fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
	}
	return 1;
      default:
	continue;
    }
  }
  optind = 1;	// reset global variable counter for the next time this is run

  std::cerr << "[dynamix]: ARGUMENTS" << std::endl;
  for (int ii = 0; ii < argc; ii++) {
    std::cerr << "[dynamix]: " << argv[ii] << std::endl;
  }

  //// ASSIGN PARAMETERS FROM INPUT FILE


  // ---- TODO create output directory if it does not exist ---- //
  flag = mkdir(p.outputDir.c_str(), 0755);

  std::cerr << "Looking for inputs in all the " << inputFile << " places" << std::endl;
  assignParams(inputFile.c_str(), &p);

  // Decide which output files to make
#ifdef DEBUG
  std::cout << "Assigning outputs as specified in " << inputFile << "\n";
#endif
  assignOutputs(inputFile.c_str(), outs, &p);

#ifdef DEBUG
  // print out which outputs will be made
  for (std::map<const std::string, bool>::iterator it = outs.begin(); it != outs.end(); it++) {
    std::cout << "Output file: " << it->first << " will be created.\n";
  }
#endif

  // OPEN LOG FILE; PUT IN START TIME //
  if (isOutput(outs, "log.out")) {
    log = fopen("log.out", "w");			// note that this file is closed at the end of the program
  }
  time(&startRun);
  currentTime = localtime(&startRun);
  if (isOutput(outs, "log.out")) {
    fprintf(log, "Run started at %s\n", asctime(currentTime));
  }

  if (isOutput(outs, "log.out")) {
    // make a note about the laser intensity.
    fprintf(log,"The laser intensity is %.5e W/cm^2.\n\n",pow(p.pumpAmpl,2)*3.5094452e16);
  }


  //// READ DATA FROM INPUTS


  p.Nc = numberOfValuesInFile(cEnergiesInput.c_str());
  p.Nb = numberOfValuesInFile(bEnergiesInput.c_str());
  k_pops = new realtype [p.Nk];
  c_pops = new realtype [p.Nc];
  b_pops = new realtype [p.Nb];
  l_pops = new realtype [p.Nl];
  k_energies = new realtype [p.Nk];
  c_energies = new realtype [p.Nc];
  b_energies = new realtype [p.Nb];
  l_energies = new realtype [p.Nl];
  if (numberOfValuesInFile(cPopsInput.c_str()) != p.Nc) {
    fprintf(stderr, "ERROR [Inputs]: c_pops and c_energies not the same length.\n");
    return -1;
  }
  readArrayFromFile(c_energies, cEnergiesInput.c_str(), p.Nc);
  if (p.bridge_on) {
    if (p.bridge_on && (p.Nb < 1)) {
      std::cerr << "\nERROR: bridge_on but no bridge states.  The file b_energies.in is probably empty.\n";
      return -1;
    }
    p.Vbridge.resize(p.Nb+1);
    readArrayFromFile(b_energies, bEnergiesInput.c_str(), p.Nb);
    readVectorFromFile(p.Vbridge, VBridgeInput.c_str(), p.Nb + 1);
#ifdef DEBUG
    std::cout << "COUPLINGS:";
    for (int ii = 0; ii < p.Nb+1; ii++) {
      std::cout << " " << p.Vbridge[ii];
    }
    std::cout << std::endl;
#endif
  }
  else {
    p.Nb = 0;
    p.Vnobridge.resize(1);
    readVectorFromFile(p.Vnobridge, VNoBridgeInput.c_str(), 1);
  }

#ifdef DEBUG
  std::cout << "\nDone reading things from inputs.\n";
#endif


  //// PREPROCESS DATA FROM INPUTS


  // check torsion parameters, set up torsion spline
  if (p.torsion) {
#ifdef DEBUG
    std::cout << "Torsion is on." << std::endl;
#endif

    // error checking
    if (p.torsionSite > p.Nb) {
      std::cerr << "ERROR: torsion site (" << p.torsionSite
	<< ") is larger than number of bridge sites (" << p.Nb << ")." << std::endl;
      exit(-1);
    }
    else if (p.torsionSite < 0) {
      std::cerr << "ERROR: torsion site is less than zero." << std::endl;
      exit(-1);
    }

    if (!fileExists(p.torsionFile)) {
      std::cerr << "ERROR: torsion file " << p.torsionFile << " does not exist." << std::endl;
    }

    // create spline
    p.torsionV = new Spline(p.torsionFile.c_str());
    if (p.torsionV->getFirstX() != 0.0) {
      std::cerr << "ERROR: time in " << p.torsionFile << " should start at 0.0." << std::endl;
      exit(-1);
    }
    if (p.torsionV->getLastX() < p.tout) {
      std::cerr << "ERROR: time in " << p.torsionFile << " should be >= tout." << std::endl;
      exit(-1);
    }
  }


  // set number of processors for OpenMP
  //omp_set_num_threads(p.nproc);
  mkl_set_num_threads(p.nproc);

  p.NEQ = p.Nk+p.Nc+p.Nb+p.Nl;				// total number of equations set
  p.NEQ2 = p.NEQ*p.NEQ;				// number of elements in DM
#ifdef DEBUG
  std::cout << "\nTotal number of states: " << p.NEQ << std::endl;
  std::cout << p.Nk << " bulk, " << p.Nc << " QD, " << p.Nb << " bridge, " << p.Nl << " bulk VB.\n";
#endif
  tkprob = new realtype [p.numOutputSteps+1];	// total population on k, b, c at each timestep
  tcprob = new realtype [p.numOutputSteps+1];
  tbprob = new realtype [p.numOutputSteps+1];
  tlprob = new realtype [p.numOutputSteps+1];
  allprob = new double * [p.numOutputSteps+1];
  for (int ii = 0; ii <= p.numOutputSteps; ii++) {
    allprob[ii] = new double [p.NEQ];
  }
  // assign times.
  p.times.resize(p.numOutputSteps+1);
  for (int ii = 0; ii <= p.numOutputSteps; ii++) {
    p.times[ii] = float(ii)/p.numOutputSteps*p.tout;
  }
  qd_est = new realtype [p.numOutputSteps+1];
  qd_est_diag = new realtype [p.numOutputSteps+1];
  p.Ik = 0;					// set index start positions for each type of state
  p.Ic = p.Nk;
  p.Ib = p.Ic+p.Nc;
  p.Il = p.Ib+p.Nb;

  // assign bulk conduction and valence band energies
  // for RTA, bulk and valence bands have parabolic energies
  if (p.rta) {
    buildParabolicBand(k_energies, p.Nk, p.kBandEdge, CONDUCTION, &p);
    buildParabolicBand(l_energies, p.Nl, p.lBandTop, VALENCE, &p);
  }
  else {
    buildContinuum(k_energies, p.Nk, p.kBandEdge, p.kBandTop);
    buildContinuum(l_energies, p.Nl, p.kBandEdge - p.valenceBand - p.bulk_gap, p.kBandEdge - p.bulk_gap);
  }
  // calculate band width
  p.kBandWidth = k_energies[p.Nk - 1] - k_energies[0];


  //// BUILD INITIAL WAVEFUNCTION


  // bridge states (empty to start)
  initializeArray(b_pops, p.Nb, 0.0);

  // coefficients in bulk and other states depend on input conditions in bulk
  if (!p.rta) {
#ifdef DEBUG
    std::cout << "\ninitializing k_pops\n";
#endif
    if (p.bulk_constant) {
      initializeArray(k_pops, p.Nk, 0.0);
#ifdef DEBUG
      std::cout << "\ninitializing k_pops with constant probability in range of states\n";
#endif
      initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0);
      initializeArray(l_pops, p.Nl, 0.0);		// populate l states (all 0 to start off)
      initializeArray(c_pops, p.Nc, 0.0);		// QD states empty to start
    }
    else if (p.bulk_Gauss) {
      buildKPopsGaussian(k_pops, k_energies, p.kBandEdge,
	  p.bulkGaussSigma, p.bulkGaussMu, p.Nk);   // populate k states with FDD
      initializeArray(l_pops, p.Nl, 0.0);		// populate l states (all 0 to start off)
      initializeArray(c_pops, p.Nc, 0.0);		// QD states empty to start
    }
    else if (p.qd_pops) {
      readArrayFromFile(c_pops, cPopsInput.c_str(), p.Nc);	// QD populations from file
      initializeArray(l_pops, p.Nl, 0.0);		// populate l states (all 0 to start off)
      initializeArray(k_pops, p.Nk, 0.0);             // populate k states (all zero to start off)
    }
    else {
      initializeArray(k_pops, p.Nk, 0.0);             // populate k states (all zero to start off)
      initializeArray(l_pops, p.Nl, 1.0);		// populate l states (all populated to start off)
      initializeArray(c_pops, p.Nc, 0.0);		// QD states empty to start
    }
#ifdef DEBUG
    std::cout << "\nThis is k_pops:\n";
    for (int ii = 0; ii < p.Nk; ii++) {
      std::cout << k_pops[ii] << std::endl;
    }
    std::cout << "\n";
#endif
  }
  // with RTA, use different set of switches
  else {
    // bulk valence band
    if (p.VBPopFlag == POP_EMPTY) {
#ifdef DEBUG
      std::cout << "Initializing empty valence band" << std::endl;
#endif
      initializeArray(l_pops, p.Nl, 0.0);
    }
    else if (p.VBPopFlag == POP_FULL) {
#ifdef DEBUG
      std::cout << "Initializing full valence band" << std::endl;
#endif
      initializeArray(l_pops, p.Nl, 1.0);
    }
    else {
      std::cerr << "ERROR: unrecognized VBPopFlag " << p.VBPopFlag << std::endl;
    }

    // bulk conduction band
    if (p.CBPopFlag == POP_EMPTY) {
#ifdef DEBUG
      std::cout << "Initializing empty conduction band" << std::endl;
#endif
      initializeArray(k_pops, p.Nk, 0.0);
    }
    else if (p.CBPopFlag == POP_FULL) {
#ifdef DEBUG
      std::cout << "Initializing full conduction band" << std::endl;
#endif
      initializeArray(k_pops, p.Nk, 1.0);
    }
    else if (p.CBPopFlag == POP_CONSTANT) {
#ifdef DEBUG
      std::cout << "Initializing constant distribution in conduction band" << std::endl;
#endif
      initializeArray(k_pops, p.Nk, 0.0);
      initializeArray(k_pops, p.Nk, 1e-1); // FIXME
      initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0);
    }
    else if (p.CBPopFlag == POP_GAUSSIAN) {
#ifdef DEBUG
      std::cout << "Initializing Gaussian in conduction band" << std::endl;
#endif
      buildKPopsGaussian(k_pops, k_energies, p.kBandEdge,
	  p.bulkGaussSigma, p.bulkGaussMu, p.Nk);
    }
    else {
      std::cerr << "ERROR: unrecognized CBPopFlag " << p.CBPopFlag << std::endl;
    }

    //// QD
    if (p.QDPopFlag == POP_EMPTY) {
      initializeArray(c_pops, p.Nc, 0.0);
    }
    else if (p.QDPopFlag == POP_FULL) {
      initializeArray(c_pops, p.Nc, 1.0);
    }
    else {
      std::cerr << "ERROR: unrecognized QDPopFlag " << p.QDPopFlag << std::endl;
    }
  }

  // create empty wavefunction
  wavefunction = new realtype [2*p.NEQ];
  initializeArray(wavefunction, 2*p.NEQ, 0.0);

  // assign real parts of wavefunction coefficients (imaginary are zero)
  for (int ii = 0; ii < p.Nk; ii++) {
    wavefunction[p.Ik + ii] = k_pops[ii];
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    wavefunction[p.Ic + ii] = c_pops[ii];
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    wavefunction[p.Ib + ii] = b_pops[ii];
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    wavefunction[p.Il + ii] = l_pops[ii];
  }

  if (isOutput(outs, "psi_start.out")) {
    outputWavefunction(wavefunction, p.NEQ);
  }

  // Give all coefficients a random phase
  if (p.random_phase) {
    float phi;
    // set the seed
    if (p.random_seed == -1) { srand(time(NULL)); }
    else { srand(p.random_seed); }
    for (int ii = 0; ii < p.NEQ; ii++) {
      phi = 2*3.1415926535*(float)rand()/(float)RAND_MAX;
      wavefunction[ii] = wavefunction[ii]*cos(phi);
      wavefunction[ii + p.NEQ] = wavefunction[ii + p.NEQ]*sin(phi);
    }
  }

#ifdef DEBUG
  // print out details of wavefunction coefficients
  std::cout << std::endl;
  for (int ii = 0; ii < p.Nk; ii++) {
    std::cout << "starting wavefunction: Re[k(" << ii << ")] = " << wavefunction[p.Ik + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    std::cout << "starting wavefunction: Re[c(" << ii << ")] = " << wavefunction[p.Ic + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    std::cout << "starting wavefunction: Re[b(" << ii << ")] = " << wavefunction[p.Ib + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    std::cout << "starting wavefunction: Re[l(" << ii << ")] = " << wavefunction[p.Il + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nk; ii++) {
    std::cout << "starting wavefunction: Im[k(" << ii << ")] = " << wavefunction[p.Ik + ii + p.NEQ] << std::endl;
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    std::cout << "starting wavefunction: Im[c(" << ii << ")] = " << wavefunction[p.Ic + ii + p.NEQ] << std::endl;
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    std::cout << "starting wavefunction: Im[b(" << ii << ")] = " << wavefunction[p.Ib + ii + p.NEQ] << std::endl;
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    std::cout << "starting wavefunction: Im[l(" << ii << ")] = " << wavefunction[p.Il + ii + p.NEQ] << std::endl;
  }
  std::cout << std::endl;
  summ = 0;
  for (int ii = 0; ii < 2*p.NEQ; ii++) {
    summ += pow(wavefunction[ii],2);
  }
  std::cout << "\nTotal population is " << summ << "\n\n";
#endif


  //// ASSEMBLE ARRAY OF ENERGIES


  // TODO TODO
  p.energies.resize(p.NEQ);
  for (int ii = 0; ii < p.Nk; ii++) {
    p.energies[p.Ik + ii] = k_energies[ii];
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    p.energies[p.Ic + ii] = c_energies[ii];
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    p.energies[p.Ib + ii] = b_energies[ii];
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    p.energies[p.Il + ii] = l_energies[ii];
  }

#ifdef DEBUG
  for (int ii = 0; ii < p.NEQ; ii++) {
    std::cout << "p.energies[" << ii << "] is " << p.energies[ii] << "\n";
  }
#endif


  //// ASSIGN COUPLING CONSTANTS


  V = new realtype * [p.NEQ];
  for (int ii = 0; ii < p.NEQ; ii++) {
    V[ii] = new realtype [p.NEQ];
  }
  buildCoupling(V, &p, outs);

  if (isOutput(outs, "log.out")) {
    // make a note in the log about system timescales
    double tau = 0;		// fundamental system timescale
    if (p.Nk == 1) {
      fprintf(log, "\nThe timescale (tau) is undefined (Nk == 1).\n");
    }
    else {
      if (p.bridge_on) {
	if (p.scale_bubr) {
	  tau = 1.0/(2*p.Vbridge[0]*M_PI);
	}
	else {
	  tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vbridge[0],2)*M_PI);
	}
      }
      else {
	if (p.scale_buqd) {
	  tau = 1.0/(2*p.Vnobridge[0]*M_PI);
	}
	else {
	  tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vnobridge[0],2)*M_PI);
	}
      }
      fprintf(log, "\nThe timescale (tau) is %.9e a.u.\n", tau);
    }
  }

  //// CREATE DENSITY MATRIX
  if (! p.wavefunction) {
    // Create the initial density matrix
    dm = new realtype [2*p.NEQ2];
    initializeArray(dm, 2*p.NEQ2, 0.0);
#pragma omp parallel for
    for (int ii = 0; ii < p.NEQ; ii++) {
      // diagonal part
      dm[p.NEQ*ii + ii] = pow(wavefunction[ii],2) + pow(wavefunction[ii + p.NEQ],2);
      if (p.coherent) {
	// off-diagonal part
	for (int jj = 0; jj < ii; jj++) {
	  // real part of \rho_{ii,jj}
	  dm[p.NEQ*ii + jj] = wavefunction[ii]*wavefunction[jj] + wavefunction[ii+p.NEQ]*wavefunction[jj+p.NEQ];
	  // imaginary part of \rho_{ii,jj}
	  dm[p.NEQ*ii + jj + p.NEQ2] = wavefunction[ii]*wavefunction[jj+p.NEQ] - wavefunction[jj]*wavefunction[ii+p.NEQ];
	  // real part of \rho_{jj,ii}
	  dm[p.NEQ*jj + ii] = dm[p.NEQ*ii + jj];
	  // imaginary part of \rho_{jj,ii}
	  dm[p.NEQ*jj + ii + p.NEQ2] = -1*dm[p.NEQ*ii + jj + p.NEQ*p.NEQ];
	}
      }
    }

    // Create the array to store the density matrix in time
    dmt = new realtype [2*p.NEQ2*(p.numOutputSteps+1)];
    initializeArray(dmt, 2*p.NEQ2*(p.numOutputSteps+1), 0.0);

#ifdef DEBUG2
    // print out density matrix
    std::cout << "\nDensity matrix without normalization:\n\n";
    for (int ii = 0; ii < p.NEQ; ii++) {
      for (int jj = 0; jj < p.NEQ; jj++) {
	fprintf(stdout, "(%+.1e,%+.1e) ", dm[p.NEQ*ii + jj], dm[p.NEQ*ii + jj + p.NEQ2]);
      }
      fprintf(stdout, "\n");
    }
#endif

    // Normalize the DM so that populations add up to 1.
    // No normalization if RTA is on.
    if (!p.rta) {
      summ = 0.0;
      for (int ii = 0; ii < p.NEQ; ii++) {
	// assume here that diagonal elements are all real
	summ += dm[p.NEQ*ii + ii];
      }
      if ( summ == 0.0 ) {
	std::cerr << "\nFATAL ERROR [populations]: total population is 0!\n";
	return -1;
      }
      if (summ != 1.0) {
	// the variable 'summ' is now a multiplicative normalization factor
	summ = 1.0/summ;
	for (int ii = 0; ii < 2*p.NEQ2; ii++) {
	  dm[ii] *= summ;
	}
      }
#ifdef DEBUG
      std::cout << "\nThe normalization factor for the density matrix is " << summ << "\n\n";
#endif
    }

    // Error checking for total population; recount population first
    summ = 0.0;
    for (int ii = 0; ii < p.NEQ; ii++) {
      summ += dm[p.NEQ*ii + ii];
    }
    if ( fabs(summ-1.0) > 1e-12  && (!p.rta)) {
      std::cerr << "\nWARNING [populations]: After normalization, total population is not 1, it is " << summ << "!\n";
    }
#ifdef DEBUG
    std::cout << "\nAfter normalization, the sum of the populations in the density matrix is " << summ << "\n\n";
#endif
    // Add initial DM to parameters.
    p.startDM.resize(2*p.NEQ2);
    memcpy(&(p.startDM[0]), &(dm[0]), 2*p.NEQ2*sizeof(double));
  }
  // wavefunction
  else {

    // Create the array to store the wavefunction in time
    wfnt = new realtype [2*p.NEQ*(p.numOutputSteps+1)];
    initializeArray(wfnt, 2*p.NEQ*(p.numOutputSteps+1), 0.0);

    // normalize
    summ = 0.0;
    for (int ii = 0; ii < p.NEQ; ii++) {
      summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2);
    }
#ifdef DEBUG
    std::cout << "Before normalization, the total population is " << summ << std::endl;
#endif
    summ = 1.0/sqrt(summ);
    for (int ii = 0; ii < 2*p.NEQ; ii++) {
      wavefunction[ii] *= summ;
    }

    // check total population
    summ = 0.0;
    for (int ii = 0; ii < p.NEQ; ii++) {
      summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2);
    }
#ifdef DEBUG
    std::cout << "After normalization, the total population is " << summ << std::endl;
#endif
    if (fabs(summ - 1.0) > 1e-12) {
      std::cerr << "WARNING: wavefunction not normalized!  Total density is " << summ << std::endl;
    }

    // Add initial wavefunction to parameters.
    p.startWfn.resize(2*p.NEQ);
    memcpy(&(p.startWfn[0]), &(wavefunction[0]), 2*p.NEQ*sizeof(double));
  }


  //// BUILD HAMILTONIAN


  // //TODO TODO
#ifdef DEBUG
  fprintf(stderr, "Building Hamiltonian.\n");
#endif
  realtype * H = NULL;
  H = new realtype [p.NEQ2];
  for (int ii = 0; ii < p.NEQ2; ii++) {
    H[ii] = 0.0;
  }
  buildHamiltonian(H, p.energies, V, &p);
  // add Hamiltonian to p
  p.H.resize(p.NEQ2);
  for (int ii = 0; ii < p.NEQ2; ii++) {
    p.H[ii] = H[ii];
  }
  // create sparse version of H
  p.H_sp.resize(p.NEQ2);
  p.H_cols.resize(p.NEQ2);
  p.H_rowind.resize(p.NEQ2 + 1);
  int job [6] = {0, 0, 0, 2, p.NEQ2, 1};
  int info = 0;

  mkl_ddnscsr(&job[0], &(p.NEQ), &(p.NEQ), &(p.H)[0], &(p.NEQ), &(p.H_sp)[0],
      &(p.H_cols)[0], &(p.H_rowind)[0], &info);


  //// SET UP CVODE VARIABLES


#ifdef DEBUG
  std::cout << "\nCreating N_Vectors.\n";
  if (p.wavefunction) {
    std::cout << "\nProblem size is " << 2*p.NEQ << " elements.\n";
  }
  else {
    std::cout << "\nProblem size is " << 2*p.NEQ2 << " elements.\n";
  }
#endif
  // Creates N_Vector y with initial populations which will be used by CVode//
  if (p.wavefunction) {
    y = N_VMake_Serial(2*p.NEQ, wavefunction);
  }
  else {
    y = N_VMake_Serial(2*p.NEQ2, dm);
  }
  // put in t = 0 information
  if (! p.wavefunction) {
    updateDM(y, dmt, 0, &p);
  }
  else {
    updateWfn(y, wfnt, 0, &p);
  }
  // the vector yout has the same dimensions as y
  yout = N_VClone(y);

#ifdef DEBUG
  realImaginary = fopen("real_imaginary.out", "w");
#endif

  // Make plot files
  makePlots(outs, &p);

  // only do propagation if not just making plots
  if (! p.justPlots) {
    // Make outputs independent of time propagation
    computeGeneralOutputs(outs, &p);

    // create CVode object
    // this is a stiff problem, I guess?
#ifdef DEBUG
    std::cout << "\nCreating cvode_mem object.\n";
#endif
    cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
    flag = CVodeSetUserData(cvode_mem, (void *) &p);

#ifdef DEBUG
    std::cout << "\nInitializing CVode solver.\n";
#endif
    // initialize CVode solver //

    if (p.wavefunction) {
      //flag = CVodeInit(cvode_mem, &RHS_WFN, t0, y);
      flag = CVodeInit(cvode_mem, &RHS_WFN_SPARSE, t0, y);
    }
    else {
      if (p.kinetic) {
	flag = CVodeInit(cvode_mem, &RHS_DM_RELAX, t0, y);
      }
      else if (p.rta) {
	flag = CVodeInit(cvode_mem, &RHS_DM_RTA, t0, y);
	//flag = CVodeInit(cvode_mem, &RHS_DM_RTA_BLAS, t0, y);
      }
      else if (p.dephasing) {
	flag = CVodeInit(cvode_mem, &RHS_DM_dephasing, t0, y);
      }
      else {
	//flag = CVodeInit(cvode_mem, &RHS_DM, t0, y);
	flag = CVodeInit(cvode_mem, &RHS_DM_BLAS, t0, y);
      }
    }

#ifdef DEBUG
    std::cout << "\nSpecifying integration tolerances.\n";
#endif
    // specify integration tolerances //
    flag = CVodeSStolerances(cvode_mem, p.reltol, p.abstol);

#ifdef DEBUG
    std::cout << "\nAttaching linear solver module.\n";
#endif
    // attach linear solver module //
    if (p.wavefunction) {
      flag = CVDense(cvode_mem, 2*p.NEQ);
    }
    else {
      // Diagonal approximation to the Jacobian saves memory for large systems
      flag = CVDiag(cvode_mem);
    }

    //// CVODE TIME PROPAGATION


#ifdef DEBUG
    std::cout << "\nAdvancing the solution in time.\n";
#endif
    for (int ii = 1; ii <= p.numsteps; ii++) {
      t = (p.tout*((double) ii)/((double) p.numsteps));
      flag = CVode(cvode_mem, t, yout, &tret, 1);
#ifdef DEBUGf
      std::cout << std::endl << "CVode flag at step " << ii << ": " << flag << std::endl;
#endif
      if ((ii % (p.numsteps/p.numOutputSteps) == 0) || (ii == p.numsteps)) {
	// show progress in stdout
	if (p.progressStdout) {
	  fprintf(stdout, "\r%-.2lf percent done", ((double)ii/((double)p.numsteps))*100);
	  fflush(stdout);
	}
	// show progress in a file
	if (p.progressFile) {
	  std::ofstream progressFile("progress.tmp");
	  progressFile << ((double)ii/((double)p.numsteps))*100 << " percent done." << std::endl;
	  progressFile.close();
	}
	if (p.wavefunction) {
	  updateWfn(yout, wfnt, ii*p.numOutputSteps/p.numsteps, &p);
	}
	else {
	  updateDM(yout, dmt, ii*p.numOutputSteps/p.numsteps, &p);
	}
      }
    }

#ifdef DEBUG
    fclose(realImaginary);
#endif


    //// MAKE FINAL OUTPUTS


    // finalize log file //
    time(&endRun);
    currentTime = localtime(&endRun);
    if (isOutput(outs, "log.out")) {
      fprintf(log, "Final status of 'flag' variable: %d\n\n", flag);
      fprintf(log, "Run ended at %s\n", asctime(currentTime));
      fprintf(log, "Run took %.3g seconds.\n", difftime(endRun, startRun));
      fclose(log);					// note that the log file is opened after variable declaration
    }
    if (p.progressStdout) {
      printf("\nRun took %.3g seconds.\n", difftime(endRun, startRun));
    }

    // Compute density outputs.
#ifdef DEBUG
    std::cout << "Computing outputs..." << std::endl;
#endif
    if (p.wavefunction) {
      computeWfnOutput(wfnt, outs, &p);
    }
    else {
      computeDMOutput(dmt, outs, &p);
    }
#ifdef DEBUG
    std::cout << "done computing outputs" << std::endl;
#endif

    // do analytical propagation
    if (p.analytical && (! p.bridge_on)) {
      computeAnalyticOutputs(outs, &p);
    }
  }


  //// CLEAN UP


#ifdef DEBUG
  fprintf(stdout, "Deallocating N_Vectors.\n");
#endif
  // deallocate memory for N_Vectors //
  N_VDestroy_Serial(y);
  N_VDestroy_Serial(yout);

#ifdef DEBUG
  fprintf(stdout, "Freeing CVode memory.\n");
#endif
  // free solver memory //
  CVodeFree(&cvode_mem);

#ifdef DEBUG
  fprintf(stdout, "Freeing memory in main.\n");
#endif
  // delete all these guys
  delete [] tkprob;
  delete [] tlprob;
  delete [] tcprob;
  delete [] tbprob;
  for (int ii = 0; ii <= p.numOutputSteps; ii++) {
    delete [] allprob[ii];
  }
  delete [] allprob;
  delete [] k_pops;
  delete [] c_pops;
  delete [] b_pops;
  delete [] l_pops;
  if (p.bridge_on) {
    delete [] Vbridge;
  }
  else {
    delete [] Vnobridge;
  }
  delete [] k_energies;
  delete [] c_energies;
  delete [] b_energies;
  delete [] l_energies;
  delete [] wavefunction;
  delete [] H;
  for (int ii = 0; ii < p.NEQ; ii++) {
    delete [] V[ii];
  }
  delete [] V;
  if (p.wavefunction) {
    delete [] wfnt;
  }
  else {
    delete [] dm;
    delete [] dmt;
  }
  delete [] times;
  delete [] qd_est;
  delete [] qd_est_diag;

  std::cout << "whoo" << std::endl;

  return 0;
}
Example #16
0
  void CVodesIntegrator::initialize(double t0, FuncEval& func) 
  {
    m_neq = func.neq();
    m_t0  = t0;

    if (m_y) {
      N_VDestroy_Serial(nv(m_y));    // free solution vector if already allocated
    }
    m_y = reinterpret_cast<void*>(N_VNew_Serial(m_neq));   // allocate solution vector
    for (int i=0; i<m_neq; i++) {
      NV_Ith_S(nv(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(nv(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 = 0;
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23)
    if (m_itol == CV_SV) {
      // vector atol
      flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol,
			 m_reltol, nv(m_abstol));
    }
    else {
      // scalar atol
      flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol,
			 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 CVodeMalloc input argument.");
      }
      else 
	throw CVodesErr("CVodeMalloc failed.");
    }
#elif defined(SUNDIALS_VERSION_24)

    flag = CVodeInit(m_cvode_mem, cvodes_rhs, m_t0, nv(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.");
      }
    }

    if (m_itol == CV_SV) {
      flag = CVodeSVtolerances(m_cvode_mem, m_reltol, nv(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.");
      }
    }
#else
    printf("unknown sundials verson\n");
    exit(-1);
#endif



    if (m_type == DENSE + NOJAC) {
      long int N = m_neq;
      CVDense(m_cvode_mem, N);
    }
    else if (m_type == DIAG) {
      CVDiag(m_cvode_mem);
    }
    else if (m_type == GMRES) {
      CVSpgmr(m_cvode_mem, PREC_NONE, 0);
    }
    else if (m_type == BAND + NOJAC) {
      long int N = m_neq;
      long int nu = m_mupper;
      long int nl = m_mlower;
      CVBand(m_cvode_mem, N, nu, nl);
    }
    else {
      throw CVodesErr("unsupported option");
    }

    // pass a pointer to func in m_data 
    m_fdata = new FuncData(&func, func.nparams());

    //m_data = (void*)&func;
#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23)
    flag = CVodeSetFdata(m_cvode_mem, (void*)m_fdata);
    if (flag != CV_SUCCESS) {
      throw CVodesErr("CVodeSetFdata failed.");
    }
#elif defined(SUNDIALS_VERSION_24)
    flag = CVodeSetUserData(m_cvode_mem, (void*)m_fdata);
    if (flag != CV_SUCCESS) {
      throw CVodesErr("CVodeSetUserData failed.");
    }
#endif
    if (func.nparams() > 0) {
      sensInit(t0, func);
      flag = CVodeSetSensParams(m_cvode_mem, DATA_PTR(m_fdata->m_pars), 
				NULL, NULL);
    }

    // set options
    if (m_maxord > 0)
      flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord);
    if (m_maxsteps > 0)
      flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
    if (m_hmax > 0)
      flag = CVodeSetMaxStep(m_cvode_mem, m_hmax);
  }
Example #17
0
int main(int narg, char **args)
{
    realtype reltol, t, tout;
    N_Vector state, abstol;
    void *cvode_mem;
    int flag, flagr;
    int rootsfound[NRF];
    int rootdir[] = {1,1,1,};

    FILE *pout;
    pout = stdout;

    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 a = 0.02;
    realtype b = 0.2;
    realtype c = -50;
    realtype d = 2;
    realtype I = 0;
    realtype v0 = -70;
    realtype p[] = {a, b, c, d, I, v0, };

    realtype v = v0;
    realtype u = b * v0;
    NV_Ith_S(state, 0) = v0;
    NV_Ith_S(state, 1) = b * v0;

    reltol = RTOL;
    NV_Ith_S(abstol,0) = ATOL0;
    NV_Ith_S(abstol,1) = ATOL1;
 
    /* 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 = CVodeRootInit(cvode_mem, NRF, root_functions);
    if (check_flag(&flag, "CVodeRootInit", 1)) return(1);

    CVodeSetRootDirection(cvode_mem, rootdir);
    if (check_flag(&flag, "CVodeSetRootDirection", 1)) return(1);
        
   
    flag = CVDense(cvode_mem, NEQ);
    if (check_flag(&flag, "CVDense", 1)) return(1);


    printf(" \n Integrating izhikevich_burster \n\n");
    printf("#t v, u, \n");
    PrintOutput(pout, t, state);
   
    tout = DT;
    while(1) {
        flag = CVode(cvode_mem, tout, state, &t, CV_NORMAL);
        
        if(flag == CV_ROOT_RETURN) {
            /* Event detected */
            flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
            if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
            PrintRootInfo(t, state, rootsfound);
          
            if(rootsfound[0]){
                //spike
                v = NV_Ith_S(state, 0);
                u = NV_Ith_S(state, 1);
                NV_Ith_S(state, 0) = c;
                NV_Ith_S(state, 1) = u + d;

        }
            if(rootsfound[1]){
                //start_inj
                I = 5;
                p[0] = a;
                p[1] = b;
                p[2] = c;
                p[3] = d;
                p[4] = I;
                p[5] = v0;
        }
            if(rootsfound[2]){
                //end_inj
                I = 0;
                p[0] = a;
                p[1] = b;
                p[2] = c;
                p[3] = d;
                p[4] = I;
                p[5] = v0;
        }
            

        /* Restart integration with event-corrected state */
            flag = CVodeSetUserData(cvode_mem, p);
            if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
        CVodeReInit(cvode_mem, t, state);
        //PrintRootInfo(t, state, rootsfound);
    }
        else
                {
            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);
}
Example #18
0
int jmi_ode_cvode_new(jmi_ode_cvode_t** integrator_ptr, jmi_ode_solver_t* solver) {
    jmi_ode_cvode_t* integrator;
    jmi_ode_problem_t* problem = solver -> ode_problem;
    int flag = 0;
    void* cvode_mem;
    jmi_real_t* y;
    jmi_real_t* atol_nv;
    int i;
    
    integrator = (jmi_ode_cvode_t*)calloc(1,sizeof(jmi_ode_cvode_t));
    if(!integrator){
        jmi_log_node(problem->log, logError, "Error", "Failed to allocate the internal CVODE struct.");
        return -1;
    }

    /* DEFAULT VALUES NEEDS TO BE IMPROVED*/
    integrator->lmm  = CV_BDF;
    integrator->iter = CV_NEWTON;
    /* integrator->rtol = 1e-4; */
    integrator->rtol = solver->rel_tol;
    
    if (problem->n_real_x > 0) {
        integrator->atol = N_VNew_Serial(problem->n_real_x);
    } else {
        integrator->atol = N_VNew_Serial(1);
    }
    atol_nv = NV_DATA_S(integrator->atol);
    
    if (problem->n_real_x > 0) {
        for (i = 0; i < problem->n_real_x; i++) {
            atol_nv[i] = 0.01*integrator->rtol*problem->nominal[i];
        }
    }else{
        atol_nv[0] = 0.01*integrator->rtol*1.0;
    }

    cvode_mem = CVodeCreate(integrator->lmm,integrator->iter);
    if(!cvode_mem){
        jmi_log_node(problem->log, logError, "Error", "Failed to allocate the CVODE struct.");
        return -1;
    }

    /* Get the default values for the time and states */
    if (problem->n_real_x > 0) {
        integrator->y_work = N_VNew_Serial(problem->n_real_x);
        y = NV_DATA_S(integrator->y_work);
		memcpy (y, problem->states, problem->n_real_x*sizeof(jmi_real_t));
    }else{
        integrator->y_work = N_VNew_Serial(1);
        y = NV_DATA_S(integrator->y_work);
        y[0] = 0.0;
    }
    
    flag = CVodeInit(cvode_mem, cv_rhs, problem->time, integrator->y_work);
    if(flag != 0) {
        jmi_log_node(problem->log, logError, "Error", "Failed to initialize CVODE. Returned with <error_flag: %d>", flag);
        return -1;
    }

    flag = CVodeSVtolerances(cvode_mem, integrator->rtol, integrator->atol);
    if(flag!=0){
        jmi_log_node(problem->log, logError, "Error", "Failed to specify the tolerances. Returned with <error_flag: %d>", flag);
        return -1;
    }

    if (problem->n_real_x > 0) {
        flag = CVDense(cvode_mem, problem->n_real_x);
    }else{
        flag = CVDense(cvode_mem, 1);
    }
    if(flag!=0){
        jmi_log_node(problem->log, logError, "Error", "Failed to specify the linear solver. Returned with <error_flag: %d>", flag);
        return -1;
    }

    flag = CVodeSetUserData(cvode_mem, (void*)solver);
    if(flag!=0){
        jmi_log_node(problem->log, logError, "Error", "Failed to specify the user data. Returned with <error_flag: %d>", flag);
        return -1;
    }
    
    if (problem->n_sw > 0){
        flag = CVodeRootInit(cvode_mem, problem->n_sw, cv_root);
        if(flag!=0){
            jmi_log_node(problem->log, logError, "Error", "Failed to specify the event indicator function. Returned with <error_flag: %d>", flag);
            return -1;
        }
    }
    
    flag = CVodeSetErrHandlerFn(cvode_mem, cv_err, (void*)solver);
    if(flag!=0){
        jmi_log_node(problem->log, logError, "Error", "Failed to specify the error handling function. Returned with <error_flag: %d>", flag);
        return -1;
    }

    integrator->cvode_mem = cvode_mem;    
      
    *integrator_ptr = integrator;
    return 0;
}
Example #19
0
File: ihm10.c Project: geoxuan/PIHM
/* Main Function */
int main(int argc, char *argv[])
{  
  char *filename = "shalehills";        /* Input file name prefix    */
  char *StateFile;                /* Output file name string   */
  char *FluxFile;
  char *ETISFile;  
  char *QFile;  
  
  Model_Data mData;               /* Model Data                */
  Control_Data cData;             /* Solver Control Data       */
  
  N_Vector CV_Y;                  /* State Variables Vector    */
  M_Env machEnv;                  /* Machine Environments      */
  
  realtype ropt[OPT_SIZE];        /* Optional real type and integer type  */
  long int iopt[OPT_SIZE];        /* vecter for Message Passing to solver */
  
  void *cvode_mem;                /* Model Data Pointer        */
  int flag;                       /* flag to test return value */
  
  FILE *res_state_file;           /* Output file for States    */
  FILE *res_flux_file;            /* Output file for Flux      */
  FILE *res_etis_file;            /* Output file for ET and IS */
  FILE *res_q_file;
  
  int N;                          /* Problem size              */
  int i;                          /* loop index                */
  realtype t;                     /* simulation time           */
  realtype NextPtr, StepSize;     /* stress period & step size */
  
  clock_t start, end_r, end_s;    /* system clock at points    */
  realtype cputime_r, cputime_s;  /* for duration in realtype  */
  
  /* allocate memory for model data structure */
  mData = (Model_Data)malloc(sizeof *mData);
  start = clock();
  
  /* get user specified file name in command line */
  if(argc >= 2)
  {
    filename = (char *)malloc(strlen(argv[1])*sizeof(char));
    strcpy(filename, argv[1]);
  }  
  
  printf("\nBelt up!  PIHM 1.0 is starting ... \n");
  
  /* read in 7 input files with "filename" as prefix */
  read_alloc(filename, mData, &cData); 
    
  /* problem size */
  N = 3*mData->NumEle + mData->NumRiv;
  
  /* initial machine environment variable */
  machEnv = M_EnvInit_Serial(N);
  
  /* initial state variable depending on machine*/
  CV_Y = N_VNew(N, machEnv);
  
  /* initialize mode data structure */
  initialize(filename, mData, &cData, CV_Y);
  
  if(cData.Debug == 1) {PrintModelData(mData);}  
  
  end_r = clock();
  cputime_r = (end_r - start)/(realtype)CLOCKS_PER_SEC;
  
  printf("\nSolving ODE system ... \n");
  
  /* initial control parameter for CVODE solver. Otherwise the default value by C could cause problems. */
  for(i=0; i<OPT_SIZE; i++)
  {
    ropt[i] = 0.0;
    iopt[i] = 0;
  }
  
  /* set user specified control parameter */
  ropt[H0] = cData.InitStep;  
  ropt[HMAX] = cData.MaxStep; 
  
  /* allocate memory for solver */
  cvode_mem = CVodeMalloc(N, f, cData.StartTime, CV_Y, BDF, NEWTON, SS, &cData.reltol, 
                          &cData.abstol, mData, NULL, TRUE, iopt, ropt, machEnv);
  if(cvode_mem == NULL) {printf("CVodeMalloc failed. \n"); return(1);}
  
  if(cData.Solver == 1)
  {
    /* using dense direct solver */
    flag = CVDense(cvode_mem, NULL, NULL);
    if(flag != SUCCESS) {printf("CVDense failed. \n"); return(1);}
  } 
  else if(cData.Solver == 2)
  {
    /* using iterative solver */
    flag = CVSpgmr(cvode_mem, NONE, cData.GSType, cData.MaxK, cData.delt, NULL, NULL,
                       mData, NULL, NULL);
    if (flag != SUCCESS) {printf("CVSpgmr failed."); return(1);}
  } 
  
  /*allocate and copy to get output file name */
  StateFile = (char *)malloc((strlen(filename)+4)*sizeof(char));
  strcpy(StateFile, filename);
  FluxFile  = (char *)malloc((strlen(filename)+5)*sizeof(char));
  strcpy(FluxFile, filename);
  ETISFile  = (char *)malloc((strlen(filename)+5)*sizeof(char));
  strcpy(ETISFile, filename);
  QFile = (char *)malloc((strlen(filename)+2)*sizeof(char));
  strcpy(QFile, filename);
  
  /* open output file */
  if (cData.res_out == 1) {res_state_file = fopen(strcat(StateFile, ".res"), "w");}
  if (cData.flux_out == 1) {res_flux_file = fopen(strcat(FluxFile, ".flux"), "w");}
  if (cData.etis_out == 1) {res_etis_file = fopen(strcat(ETISFile, ".etis"), "w");}
  if (cData.q_out == 1) {res_q_file = fopen(strcat(QFile, ".q"), "w");}
  
  /* print header of output file */
  if (cData.res_out == 1) {FPrintYheader(res_state_file, mData);}
  if (cData.etis_out == 1) {FPrintETISheader(res_etis_file, mData);}
  if (cData.q_out == 1) {FPrintETISheader(res_q_file, mData);}
  printf("\n");
  
  /* set start time */
  t = cData.StartTime;
  
  /* start solver in loops */
  for(i=0; i<cData.NumSteps; i++)
  {
    /* prompt information in non-verbose mode */
    if (cData.Verbose != 1)
    {
      printf("  Running: %-4.1f%% ... ", (100*(i+1)/((realtype) cData.NumSteps))); 
      fflush(stdout);
    }
    
    /* inner loops to next output points with ET step size control */
    while(t < cData.Tout[i+1])
    {
      if (t + cData.ETStep >= cData.Tout[i+1])
      {
        NextPtr = cData.Tout[i+1];
      }
      else
      {
        NextPtr = t + cData.ETStep;
      }
      StepSize = NextPtr - t; 
      
      /* calculate Interception Storage */
      calIS(t, StepSize, mData);
      /* solving ODE system */
      flag = CVode(cvode_mem, NextPtr, CV_Y, &t, NORMAL);  
      /* calculate ET and adjust states variables*/
      calET(t, StepSize, CV_Y, mData);
    }  
    
    if(cData.Verbose == 1) {PrintVerbose(i, t, iopt, ropt);}

    /* uncomment it if user need it verbose mode */  
    /* if(cData.Verbose == 1) {PrintY(mData, CV_Y, t);} */
    
    /* print out results to files at every output time */
    if (cData.res_out == 1) {FPrintY(mData, CV_Y, t, res_state_file);}
    if (cData.flux_out == 1) {FPrintFlux(mData, t, res_flux_file);}
    if (cData.etis_out == 1) {FPrintETIS(mData, t, res_etis_file);}
    if (cData.q_out == 1) {FPrintQ(mData, t, res_q_file);}
    
    if (cData.Verbose != 1) {printf("\r");}  
    
    if(flag != SUCCESS) {printf("CVode failed, flag = %d. \n", flag); return(flag);} 
    
    /* clear buffer */
    fflush(stdout);  
  }
  
  /* free memory */
  /*
  N_VFree(CV_Y);
  CVodeFree(cvode_mem);
  M_EnvFree_Serial(machEnv); 
  */
  
  /* capture time */
  end_s = clock();
  cputime_s = (end_s - end_r)/(realtype)CLOCKS_PER_SEC;
  
  /* print out simulation statistics */
  PrintFarewell(cData, iopt, ropt, cputime_r, cputime_s);
  if (cData.res_out == 1) {FPrintFarewell(cData, res_state_file, iopt, ropt, cputime_r, cputime_s);}
  
  /* close output files */
  if (cData.res_out == 1)  {fclose(res_state_file);}
  if (cData.flux_out == 1) {fclose(res_flux_file);}
  if (cData.etis_out == 1) {fclose(res_etis_file);}
  if (cData.q_out == 1)    {fclose(res_q_file);}
  
  free(mData);
  
  return 0;
}
Example #20
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);
  }
}
Example #21
0
/*
**   ========
**   main MEX
**   ========
*/
void mexFunction( int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[] )
{
    /* variables */
    double *  return_status;
    double *  species_out;
    double *  observables_out;    
    double *  parameters;
    double *  species_init;
    double *  timepoints; 
    size_t    n_timepoints;
    size_t    i;
    size_t    j;

    /* intermediate data vectors */
    N_Vector  expressions;
    N_Vector  observables;
    N_Vector  ratelaws;

    /* array to hold pointers to data vectors */
    N_Vector  temp_data[3];
    
    /* CVODE specific variables */
    realtype  reltol;
    realtype  abstol;
    realtype  time;
    N_Vector  species;
    void *    cvode_mem;
    int       flag;

    /* check number of input/output arguments */
    if (nlhs != 3)
    {  mexErrMsgTxt("syntax: [err_flag, species_out, obsv_out] = network_mex( timepoints, species_init, params )");  }
    if (nrhs != 3)
    {  mexErrMsgTxt("syntax: [err_flag, species_out, obsv_out] = network_mex( timepoints, species_init, params )");  }


    /* make sure timepoints has correct dimensions */
    if ( (mxGetM(prhs[0]) < 2)  ||  (mxGetN(prhs[0]) != 1) )
    {  mexErrMsgTxt("TIMEPOINTS must be a column vector with 2 or more elements.");  }

    /* make sure species_init has correct dimensions */
    if ( (mxGetM(prhs[1]) != 1)  ||  (mxGetN(prhs[1]) != __N_SPECIES__) )
    {  mexErrMsgTxt("SPECIES_INIT must be a row vector with 7 elements.");  } 

    /* make sure params has correct dimensions */
    if ( (mxGetM(prhs[2]) != 1)  ||  (mxGetN(prhs[2]) != __N_PARAMETERS__) )
    {  mexErrMsgTxt("PARAMS must be a column vector with 4 elements.");  }

    /* get pointers to input arrays */
    timepoints   = mxGetPr(prhs[0]);
    species_init = mxGetPr(prhs[1]);
    parameters   = mxGetPr(prhs[2]);

    /* get number of timepoints */
    n_timepoints = mxGetM(prhs[0]);

    /* Create an mxArray for output trajectories */
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL );
    plhs[1] = mxCreateDoubleMatrix(n_timepoints, __N_SPECIES__, mxREAL);
    plhs[2] = mxCreateDoubleMatrix(n_timepoints, __N_OBSERVABLES__, mxREAL);

    /* get pointers to output arrays */
    return_status   = mxGetPr(plhs[0]);
    species_out     = mxGetPr(plhs[1]);
    observables_out = mxGetPr(plhs[2]);    
   
    /* initialize intermediate data vectors */
    expressions  = NULL;
    expressions = N_VNew_Serial(__N_EXPRESSIONS__);
    if (check_flag((void *)expressions, "N_VNew_Serial", 0))
    {
        return_status[0] = 1;
        return;
    }

    observables = NULL;
    observables = N_VNew_Serial(__N_OBSERVABLES__);
    if (check_flag((void *)observables, "N_VNew_Serial", 0))
    {
        N_VDestroy_Serial(expressions);
        return_status[0] = 1;
        return;
    }

    ratelaws    = NULL; 
    ratelaws = N_VNew_Serial(__N_RATELAWS__);
    if (check_flag((void *)ratelaws, "N_VNew_Serial", 0))
    {   
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);        
        return_status[0] = 1;
        return;
    }
    
    /* set up pointers to intermediate data vectors */
    temp_data[0] = expressions;
    temp_data[1] = observables;
    temp_data[2] = ratelaws;

    /* calculate expressions (expressions are constant, so only do this once!) */
    calc_expressions( expressions, parameters );

        
    /* SOLVE model equations! */
    species   = NULL;
    cvode_mem = NULL;

    /* Set the scalar relative tolerance */
    reltol = 1e-06;
    abstol = 1e-06;

    /* Create serial vector for Species */
    species = N_VNew_Serial(__N_SPECIES__);
    if (check_flag((void *)species, "N_VNew_Serial", 0))
    {  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);
        return_status[0] = 1;
        return;
    }
    for ( i = 0; i < __N_SPECIES__; i++ )
    {   NV_Ith_S(species,i) = species_init[i];   }
    
    /* write initial species populations into species_out */
    for ( i = 0; i < __N_SPECIES__; i++ )
    {   species_out[i*n_timepoints] = species_init[i];   }
    
    /* write initial observables populations into species_out */ 
    calc_observables( observables, species, expressions );  
    for ( i = 0; i < __N_OBSERVABLES__; i++ )
    {   observables_out[i*n_timepoints] = NV_Ith_S(observables,i);   }

    /*   Call CVodeCreate to create the solver memory:    
     *   CV_ADAMS or CV_BDF is the linear multistep method
     *   CV_FUNCTIONAL or CV_NEWTON is the nonlinear solver iteration
     *   A pointer to the integrator problem memory is returned and stored in cvode_mem.
     */
    cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
    if (check_flag((void *)cvode_mem, "CVodeCreate", 0))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  



    /*   Call CVodeInit to initialize the integrator memory:     
     *   cvode_mem is the pointer to the integrator memory returned by CVodeCreate
     *   rhs_func  is the user's right hand side function in y'=f(t,y)
     *   T0        is the initial time
     *   y         is the initial dependent variable vector
     */
    flag = CVodeInit(cvode_mem, calc_species_deriv, timepoints[0], species);
    if (check_flag(&flag, "CVodeInit", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  
   
    /* Set scalar relative and absolute tolerances */
    flag = CVodeSStolerances(cvode_mem, reltol, abstol);
    if (check_flag(&flag, "CVodeSStolerances", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                     
   
    /* pass params to rhs_func */
    flag = CVodeSetUserData(cvode_mem, &temp_data);
    if (check_flag(&flag, "CVodeSetFdata", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  
    
    /* select linear solver */
    flag = CVDense(cvode_mem, __N_SPECIES__);
    if (check_flag(&flag, "CVDense", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  
    
    flag = CVodeSetMaxNumSteps(cvode_mem, 2000);
    if (check_flag(&flag, "CVodeSetMaxNumSteps", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  

    flag = CVodeSetMaxErrTestFails(cvode_mem, 7);
    if (check_flag(&flag, "CVodeSetMaxErrTestFails", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  

    flag = CVodeSetMaxConvFails(cvode_mem, 10);
    if (check_flag(&flag, "CVodeSetMaxConvFails", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  

    flag = CVodeSetMaxStep(cvode_mem, 0.0);
    if (check_flag(&flag, "CVodeSetMaxStep", 1))
    {                                  
        N_VDestroy_Serial(expressions);
        N_VDestroy_Serial(observables);
        N_VDestroy_Serial(ratelaws);   
        N_VDestroy_Serial(species);    
        CVodeFree(&cvode_mem);         
        return_status[0] = 1;          
        return;                        
    }                                  

    /* integrate to each timepoint */
    for ( i=1;  i < n_timepoints;  i++ )
    {
        flag = CVode(cvode_mem, timepoints[i], species, &time, CV_NORMAL);
        if (check_flag(&flag, "CVode", 1))
        {
            N_VDestroy_Serial(expressions);
            N_VDestroy_Serial(observables);           
            N_VDestroy_Serial(ratelaws);
            N_VDestroy_Serial(species);
            CVodeFree(&cvode_mem);
            return_status[0] = 1; 
            return;
        }

        /* copy species output from nvector to matlab array */
        for ( j = 0; j < __N_SPECIES__; j++ )
        {   species_out[j*n_timepoints + i] = NV_Ith_S(species,j);   }
        
        /* copy observables output from nvector to matlab array */
        calc_observables( observables, species, expressions );         
        for ( j = 0; j < __N_OBSERVABLES__; j++ )
        {   observables_out[j*n_timepoints + i] = NV_Ith_S(observables,j);   }      
    }
 
    /* Free vectors */
    N_VDestroy_Serial(expressions);
    N_VDestroy_Serial(observables);  
    N_VDestroy_Serial(ratelaws);        
    N_VDestroy_Serial(species);

    /* Free integrator memory */
    CVodeFree(&cvode_mem);

    return;
}
Example #22
0
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;
}
Example #23
0
int main(int argc, char *argv[])
{
  void *cvode_mem;
  UserData data;
  realtype t, tout;
  N_Vector y;
  int iout, flag;

  realtype pbar[NS];
  int is; 
  N_Vector *yS;
  booleantype sensi, err_con;
  int sensi_meth;

  cvode_mem = NULL;
  data      = NULL;
  y         =  NULL;
  yS        = NULL;

  /* Process arguments */
  ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);

  /* User data structure */
  data = (UserData) malloc(sizeof *data);
  if (check_flag((void *)data, "malloc", 2)) return(1);
  data->p[0] = RCONST(0.04);
  data->p[1] = RCONST(1.0e4);
  data->p[2] = RCONST(3.0e7);

  /* Initial conditions */
  y = N_VNew_Serial(NEQ);
  if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);

  Ith(y,1) = Y1;
  Ith(y,2) = Y2;
  Ith(y,3) = Y3;

  /* Create CVODES object */
  cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
  if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);

  /* Allocate space for CVODES */
  flag = CVodeMalloc(cvode_mem, f, T0, y, CV_WF, 0.0, NULL);
  if (check_flag(&flag, "CVodeMalloc", 1)) return(1);

  /* Use private function to compute error weights */
  flag = CVodeSetEwtFn(cvode_mem, ewt, NULL);
  if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1);

  /* Attach user data */
  flag = CVodeSetFdata(cvode_mem, data);
  if (check_flag(&flag, "CVodeSetFdata", 1)) return(1);

  /* Attach linear solver */
  flag = CVDense(cvode_mem, NEQ);
  if (check_flag(&flag, "CVDense", 1)) return(1);

  flag = CVDenseSetJacFn(cvode_mem, Jac, data);
  if (check_flag(&flag, "CVDenseSetJacFn", 1)) return(1);

  printf("\n3-species chemical kinetics problem\n");

  /* Sensitivity-related settings */
  if (sensi) {

    pbar[0] = data->p[0];
    pbar[1] = data->p[1];
    pbar[2] = data->p[2];

    yS = N_VNewVectorArray_Serial(NS, NEQ);
    if (check_flag((void *)yS, "N_VNewVectorArray_Serial", 0)) return(1);
    for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);

    flag = CVodeSensMalloc(cvode_mem, NS, sensi_meth, yS);
    if(check_flag(&flag, "CVodeSensMalloc", 1)) return(1);

    flag = CVodeSetSensRhs1Fn(cvode_mem, fS);
    if (check_flag(&flag, "CVodeSetSensRhs1Fn", 1)) return(1);
    flag = CVodeSetSensErrCon(cvode_mem, err_con);
    if (check_flag(&flag, "CVodeSetSensFdata", 1)) return(1);
    flag = CVodeSetSensFdata(cvode_mem, data);
    if (check_flag(&flag, "CVodeSetSensFdata", 1)) return(1);
    flag = CVodeSetSensParams(cvode_mem, NULL, pbar, NULL);
    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("===================================================");
  printf("============================\n");
  printf("     T     Q       H      NST                    y1");
  printf("           y2           y3    \n");
  printf("===================================================");
  printf("============================\n");

  for (iout=1, tout=T1; iout <= NOUT; iout++, tout *= TMULT) {

    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, yS);
      if (check_flag(&flag, "CVodeGetSens", 1)) break;
      PrintOutputS(yS);
    } 
    printf("-------------------------------------------------");
    printf("------------------------------\n");

  }

  /* Print final statistics */
  PrintFinalStats(cvode_mem, sensi);

  /* Free memory */

  N_VDestroy_Serial(y);                    /* Free y vector */
  if (sensi) {
    N_VDestroyVectorArray_Serial(yS, NS);  /* Free yS vector */
  }
  free(data);                              /* Free user data */
  CVodeFree(cvode_mem);                    /* Free CVODES memory */

  return(0);
}
Example #24
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);
}
Example #25
0
int run_rate_state_sim(std::vector<std::vector<realtype> > &results, RSParams &params) {
	realtype		long_term_reltol, event_reltol, t, tout, tbase=0;
	N_Vector		y, long_term_abstol, event_abstol;
	unsigned int	i, n;
	int				flag, err_code;
	void			*long_term_cvode, *event_cvode, *current_cvode;
	
	// Create serial vector of length NEQ for I.C. and abstol
	y = N_VNew_Serial(params.num_eqs()*params.num_blocks());
	if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
	long_term_abstol = N_VNew_Serial(params.num_eqs()*params.num_blocks()); 
	if (check_flag((void *)long_term_abstol, "N_VNew_Serial", 0)) return(1);
	event_abstol = N_VNew_Serial(params.num_eqs()*params.num_blocks()); 
	if (check_flag((void *)event_abstol, "N_VNew_Serial", 0)) return(1);
	
	// Initialize y
	for (i=0;i<params.num_blocks();++i) {
		NV_Ith_S(y,i*params.num_eqs()+EQ_X) = params.init_val(i, EQ_X);
		NV_Ith_S(y,i*params.num_eqs()+EQ_V) = params.init_val(i, EQ_V);
		NV_Ith_S(y,i*params.num_eqs()+EQ_H) = params.init_val(i, EQ_H);
	}
	
	/* Initialize interactions */
	/*interaction = new realtype[NBLOCKS*NBLOCKS];
	double int_level = 1e-2;
	double dropoff = 1.1;
	for (i=0;i<NBLOCKS;++i) {
		for (n=0;n<NBLOCKS;++n) {
			interaction[i*NBLOCKS+n] = (i==n?(1.0-int_level):int_level);
		}
	}*/
	
	/* Set the scalar relative tolerance */
	long_term_reltol = RCONST(1.0e-12);
	event_reltol = RCONST(1.0e-12);
	/* Set the vector absolute tolerance */
	for (i=0;i<params.num_blocks();++i) {
		Xth(long_term_abstol,i) = RCONST(1.0e-12);
		Vth(long_term_abstol,i) = RCONST(1.0e-12);
		Hth(long_term_abstol,i) = RCONST(1.0e-12);
		Xth(event_abstol,i) = RCONST(1.0e-12);
		Vth(event_abstol,i) = RCONST(1.0e-12);
		Hth(event_abstol,i) = RCONST(1.0e-12);
	}
	
	/* Call CVodeCreate to create the solver memory and specify the 
	 * Backward Differentiation Formula and the use of a Newton iteration */
	long_term_cvode = CVodeCreate(CV_BDF, CV_NEWTON);
	if (check_flag((void *)long_term_cvode, "CVodeCreate", 0)) return(1);
	event_cvode = CVodeCreate(CV_BDF, CV_NEWTON);
	if (check_flag((void *)event_cvode, "CVodeCreate", 0)) return(1);
	
	// Turn off error messages
	//CVodeSetErrFile(long_term_cvode, NULL);
	//CVodeSetErrFile(event_cvode, NULL);
	
	/* 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(long_term_cvode, func, T0, y);
	if (check_flag(&flag, "CVodeInit", 1)) return(1);
	flag = CVodeInit(event_cvode, func, T0, y);
	if (check_flag(&flag, "CVodeInit", 1)) return(1);
	
	/* Call CVodeSVtolerances to specify the scalar relative tolerance
	 * and vector absolute tolerances */
	flag = CVodeSVtolerances(long_term_cvode, long_term_reltol, long_term_abstol);
	if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
	flag = CVodeSVtolerances(event_cvode, event_reltol, event_abstol);
	if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
	
	/* Set the root finding function */
	//flag = CVodeRootInit(long_term_cvode, params.num_blocks(), vel_switch_finder);
	//flag = CVodeRootInit(event_cvode, params.num_blocks(), vel_switch_finder);
	//if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
	
	/* Call CVDense to specify the CVDENSE dense linear solver */
	//flag = CVSpbcg(cvode_mem, PREC_NONE, 0);
	//if (check_flag(&flag, "CVSpbcg", 1)) return(1);
	//flag = CVSpgmr(cvode_mem, PREC_NONE, 0);
	//if (check_flag(&flag, "CVSpgmr", 1)) return(1);
	flag = CVDense(long_term_cvode, params.num_eqs()*params.num_blocks());
	if (check_flag(&flag, "CVDense", 1)) return(1);
	flag = CVDense(event_cvode, params.num_eqs()*params.num_blocks());
	if (check_flag(&flag, "CVDense", 1)) return(1);
	
	flag = CVodeSetUserData(long_term_cvode, &params);
	if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
	flag = CVodeSetUserData(event_cvode, &params);
	if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
	
	CVodeSetMaxNumSteps(long_term_cvode, 100000);
	CVodeSetMaxNumSteps(event_cvode, 100000);
	
	/* Set the Jacobian routine to Jac (user-supplied) */
	flag = CVDlsSetDenseJacFn(long_term_cvode, Jac);
	if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
	flag = CVDlsSetDenseJacFn(event_cvode, 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.  */
	
	tout = T0+params.time_step();
	err_code = 0;
	int mode = 0;
	int	num_res_vals = params.num_eqs()*params.num_blocks();
	while(t+tbase < params.end_time()) {
		switch (mode) {
			case 0:
				current_cvode = long_term_cvode;
				break;
			case 1:
				current_cvode = event_cvode;
				break;
		}
		flag = CVode(current_cvode, tout, y, &t, CV_NORMAL);
		record_results(results, y, t, tbase, num_res_vals);
		
		if (check_flag(&flag, "CVode", 1)) {
			err_code = flag;
			break;
		}
		if (flag == CV_ROOT_RETURN) {
			int flagr;
			int rootsfound[params.num_blocks()];
			flagr = CVodeGetRootInfo(current_cvode, rootsfound);
			if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
			//mode = !mode;
			//std::cerr << rootsfound[0] << std::endl;
		}
		if (flag == CV_SUCCESS) tout += params.time_step();
		if (t > 10) {
			t -= 10;
			tout -= 10;
			Xth(y,0) -= 10;
			tbase += 10;
			CVodeReInit(current_cvode, t, y);
		}
	}
	
	std::cerr << err_code <<
		" X:" << Xth(y,0) <<
		" V:" << Vth(y,0) <<
		" H:" << Hth(y,0) <<
		" F:" << F(0,Vth(y,0),Hth(y,0),params) <<
		" dV:" << (Xth(y,0)-t-params.param(0, K_PARAM)*F(0,Vth(y,0),Hth(y,0),params))/params.param(0, R_PARAM) <<
		" dH:" << -Hth(y,0)*Vth(y,0)*log(Hth(y,0)*Vth(y,0)) << std::endl;
	/* Print some final statistics */
	//PrintFinalStats(cvode_mem);
	
	/* Free y and abstol vectors */
	N_VDestroy_Serial(y);
	N_VDestroy_Serial(long_term_abstol);
	N_VDestroy_Serial(event_abstol);
	
	/* Free integrator memory */
	CVodeFree(&long_term_cvode);
	
	return err_code;
}
Example #26
0
static int simulate_nmr_pulse(struct bloch_sim *bs)
{
    N_Vector M = NULL;
    M = N_VNew_Serial(3 * bs->num_cells);
    if (check_flag((void *)M, "N_VNew_Serial", 0)) return(1);

    int i;
    /* Set initial (t=0) magnetization conditions */
    for(i=0; i < bs->num_cells; ++i)
    {
        X(M,i) = 0.0;
        Y(M,i) = 0.0;
        Z(M,i) = bs->cell_frequencies[i] / bs->w_avg;
    }

    realtype reltol = RCONST(1.0e-14);
    realtype abstol = RCONST(1.0e-14);

    void *cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
    if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);

    int flag;
    //TODO: check if flag should be pointer;
    flag = CVodeInit(cvode_mem, bloch_equations, 0.0, M);
    if (check_flag(&flag, "CVodeInit", 1)) return(1);

    flag = CVodeSetUserData(cvode_mem, bs);
    if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);

    flag = CVodeSStolerances(cvode_mem, reltol, abstol);
    if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);

    flag = CVDense(cvode_mem, 3 * bs->num_cells);
    if (check_flag(&flag, "CVDense", 1)) return(1);

    flag = CVDlsSetDenseJacFn(cvode_mem, bloch_jacobian);
    if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);

    ///////////////////////////
    // PI/2 PULSE SIMULATION //
    ///////////////////////////
    bs->rf_on = 1;

    flag = CVodeSetStopTime(cvode_mem, bs->pi2_duration);
    if (check_flag(&flag, "CVodeSetStopTime", 1)) return 1;

    realtype time_reached;
    flag = CVode(cvode_mem, bs->pi2_duration, M, &time_reached, CV_NORMAL);

    if (flag != CV_SUCCESS)
    {
        printf("ERROR: Failed to simulate Pi/2 pulse\n");
    }

    // {{{ PI2 PULSE DEBUG STATEMENTS
    if (DEBUG)
    {
        printf("\n");
        printf("#####################################\n");
        printf("### PI/2 PULSE SIMULATION DETAILS ###\n");
        printf("#####################################\n");
        printf("\n");

        printf("TIME REACHED: %.15e\n", time_reached);
        printf("TIME REACHED - PI2_DURATION: %.15e\n", time_reached - bs->pi2_duration);

        printf("\n");
        printf("MAGNETIZATION AT END OF PI/2 PULSE:\n");
        for (i = 0; i<bs->num_cells; ++i)
        {
            printf("CELL %d: %.4e, %.4e, %.4e\n", i, X(M,i), Y(M,i), Z(M,i));
        }
    }
    // }}}

    ////////////////////
    // FID SIMULATION //
    ////////////////////
    bs->rf_on = 0;

    if (DEBUG)
    {
        printf("##############################\n");
        printf("### FID SIMULATION DETAILS ###\n");
        printf("##############################\n");
    }

    flag = CVodeReInit(cvode_mem, 0.0, M);
    if (check_flag(&flag, "CVodeReInit", 1)) return(1);
    time_reached = 0.0;

    flag = CVodeSetStopTime(cvode_mem, bs->fid_duration);
    if (check_flag(&flag, "CVodeSetStopTime", 1)) return 1;

    flag = CVodeRootInit(cvode_mem, 1, bloch_root);
    if (check_flag(&flag, "CVodeRootInit", 1)) return 1;

    realtype time_desired, M_FID_X;
    while (time_reached < bs->fid_duration)
    {
        time_desired = time_reached + bs->fid_sampling_interval;
        flag = CVode(cvode_mem, time_desired, M, &time_reached, CV_NORMAL);

        if (flag == CV_ROOT_RETURN)
        {
            bs->zero_crossings[bs->num_zero_crossings] = time_reached;

            M_FID_X = 0.0;
            for (i=0; i < bs->num_cells; i++)
            {
                M_FID_X += X(M,i) * cos(bs->w_avg * time_reached);
                M_FID_X += Y(M,i) * sin(bs->w_avg * time_reached);
            }
            bs->envelope[bs->num_zero_crossings] = M_FID_X / bs->num_cells;
            bs->num_zero_crossings++;
        }
    }

    bs->zero_crossings = (realtype*) realloc(bs->zero_crossings, sizeof(realtype) * bs->num_zero_crossings);
    bs->envelope = (realtype*) realloc(bs->envelope, sizeof(realtype) * bs->num_zero_crossings);
    if (!bs->zero_crossings || !bs->envelope) {
        printf("ERROR: reallocating zero crossing and/or envelope array memory failed!\n");
        exit(1);
    }

    N_VDestroy_Serial(M);

    CVodeFree(&cvode_mem);

    return 0;
}
Example #27
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::Solver::OdeSolver::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);
    }
}
Example #28
0
int do_integrate(float t_start, float t_stop, int n_points)
{
  realtype reltol, t; 
  N_Vector y, abstol;
  void *cvode_mem;
  int flag, flagr, iout;


  y = abstol = NULL;
  cvode_mem = NULL;

  /* Create serial vector of length NEQ for I.C. and abstol */
  y = N_VNew_Serial(NEQ);
  if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
  abstol = N_VNew_Serial(NEQ); 
  if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1);

  
  //Setup the initial state values:
  setup_initial_states(y);
  setup_tolerances(abstol);

  /* Set the scalar relative tolerance */
  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);
  
  /* 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, t_start, y);
  if (check_flag(&flag, "CVodeInit", 1)) return(1);

  /* Call CVodeSVtolerances to specify the scalar relative tolerance
   * and vector absolute tolerances */
  flag = CVodeSVtolerances(cvode_mem, reltol, abstol);
  if (check_flag(&flag, "CVodeSVtolerances", 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.*/
  printf(" \n3-species kinetics problem\n\n");

  iout = 0;  

  int i=0;
  for(i=1;i< n_points; i++)
  {
    float t_next = t_start + (t_stop-t_start)/n_points * i;
    printf("Advancing to: %f", t_next);

    flag = CVode(cvode_mem, t_next, y, &t, CV_NORMAL);
    loop_function(t,y);


    PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));

    //printf("MH: %d %f",iout,t_next);


    if (check_flag(&flag, "CVode", 1)) break;
    assert(flag==CV_SUCCESS);
  }


  /* Print some final statistics */
  PrintFinalStats(cvode_mem);

  /* Free y and abstol vectors */
  N_VDestroy_Serial(y);
  N_VDestroy_Serial(abstol);

  /* Free integrator memory */
  CVodeFree(&cvode_mem);

  return(0);
}
Example #29
0
  void CVodesIntegrator::reinitialize(double t0, FuncEval& func) 
  {
    m_t0  = t0;
    //try {
    func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y)));
    //}
    //catch (CanteraError) {
    //showErrors();
    //error("Teminating execution");
    //}

    int result, flag;

#if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23)
    if (m_itol == CV_SV) {
      result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), 
			   m_itol, m_reltol,
			   nv(m_abstol));
    }
    else {
      result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y),
			   m_itol, m_reltol,
			   &m_abstols);
    }
    if (result != CV_SUCCESS) { 
      throw CVodesErr("CVodeReInit failed. result = "+int2str(result));
    }
#elif defined(SUNDIALS_VERSION_24)
    result = CVodeReInit(m_cvode_mem, m_t0, nv(m_y));
    if (result != CV_SUCCESS) { 
      throw CVodesErr("CVodeReInit failed. result = "+int2str(result));
    }
#endif

    if (m_type == DENSE + NOJAC) {
      long int N = m_neq;
      CVDense(m_cvode_mem, N);
    }
    else if (m_type == DIAG) {
      CVDiag(m_cvode_mem);
    }
    else if (m_type == BAND + NOJAC) {
      long int N = m_neq;
      long int nu = m_mupper;
      long int nl = m_mlower;
      CVBand(m_cvode_mem, N, nu, nl);
    }
    else if (m_type == GMRES) {
      CVSpgmr(m_cvode_mem, PREC_NONE, 0);
    }
    else {
      throw CVodesErr("unsupported option");
    }


    // set options
    if (m_maxord > 0)
      flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord);
    if (m_maxsteps > 0)
      flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
    if (m_hmax > 0)
      flag = CVodeSetMaxStep(m_cvode_mem, m_hmax);
  }
Example #30
0
int main(int argc, char *argv[])
{
  UserData data;

  void *cvode_mem;

  realtype reltolQ, abstolQ;
  N_Vector y, q;

  int steps;

  int indexB;

  realtype reltolB, abstolB, abstolQB;
  N_Vector yB, qB;

  realtype time;
  int flag, ncheck;

  long int nst, nstB;

  CVadjCheckPointRec *ckpnt;

  data = NULL;
  cvode_mem = NULL;
  ckpnt = NULL;
  y = yB = qB = NULL;

  /* Print problem description */
  printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
  printf("-------------------------------------------------\n\n");
  printf("ODE: dy1/dt = -p1*y1 + p2*y2*y3\n");
  printf("     dy2/dt =  p1*y1 - p2*y2*y3 - p3*(y2)^2\n");
  printf("     dy3/dt =  p3*(y2)^2\n\n");
  printf("Find dG/dp for\n");
  printf("     G = int_t0^tB0 g(t,p,y) dt\n");
  printf("     g(t,p,y) = y3\n\n\n");

  /* User data structure */
  data = (UserData) malloc(sizeof *data);
  if (check_flag((void *)data, "malloc", 2)) return(1);
  data->p[0] = RCONST(0.04);
  data->p[1] = RCONST(1.0e4);
  data->p[2] = RCONST(3.0e7);

  /* Initialize y */
  y = N_VNew_Serial(NEQ);
  if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
  Ith(y,1) = RCONST(1.0);
  Ith(y,2) = ZERO;
  Ith(y,3) = ZERO;

  /* Initialize q */
  q = N_VNew_Serial(1);
  if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1);
  Ith(q,1) = ZERO;

  /* Set the scalar realtive and absolute tolerances reltolQ and abstolQ */
  reltolQ = RTOL;
  abstolQ = ATOLq;

  /* Create and allocate CVODES memory for forward run */
  printf("Create and allocate CVODES memory for forward runs\n");

  cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
  if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);

  flag = CVodeInit(cvode_mem, f, T0, y);
  if (check_flag(&flag, "CVodeInit", 1)) return(1);

  flag = CVodeWFtolerances(cvode_mem, ewt);
  if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);

  flag = CVodeSetUserData(cvode_mem, data);
  if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);

  flag = CVDense(cvode_mem, NEQ);
  if (check_flag(&flag, "CVDense", 1)) return(1);

  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);

  flag = CVodeQuadInit(cvode_mem, fQ, q);
  if (check_flag(&flag, "CVodeQuadInit", 1)) return(1);

  flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ);
  if (check_flag(&flag, "CVodeQuadSStolerances", 1)) return(1);

  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
  if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);

  /* Allocate global memory */

  steps = STEPS;
  flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE);
  /*
  flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
  */
  if (check_flag(&flag, "CVodeAdjInit", 1)) return(1);

  /* Perform forward run */
  printf("Forward integration ... ");
  
  flag = CVodeF(cvode_mem, TOUT, y, &time, CV_NORMAL, &ncheck);
  if (check_flag(&flag, "CVodeF", 1)) return(1);
  flag = CVodeGetNumSteps(cvode_mem, &nst);
  if (check_flag(&flag, "CVodeGetNumSteps", 1)) return(1);

  printf("done ( nst = %ld )\n",nst);

  flag = CVodeGetQuad(cvode_mem, &time, q);
  if (check_flag(&flag, "CVodeGetQuad", 1)) return(1);

  printf("--------------------------------------------------------\n");
#if defined(SUNDIALS_EXTENDED_PRECISION)
  printf("G:          %12.4Le \n",Ith(q,1));
#elif defined(SUNDIALS_DOUBLE_PRECISION)
  printf("G:          %12.4le \n",Ith(q,1));
#else
  printf("G:          %12.4e \n",Ith(q,1));
#endif
  printf("--------------------------------------------------------\n\n");

  /* Test check point linked list 
     (uncomment next block to print check point information) */
  
  /*
  {
    int i;
    
    printf("\nList of Check Points (ncheck = %d)\n\n", ncheck);
    ckpnt = (CVadjCheckPointRec *) malloc ( (ncheck+1)*sizeof(CVadjCheckPointRec));
    CVodeGetAdjCheckPointsInfo(cvode_mem, ckpnt);
    for (i=0;i<=ncheck;i++) {
      printf("Address:       %p\n",ckpnt[i].my_addr);
      printf("Next:          %p\n",ckpnt[i].next_addr);
      printf("Time interval: %le  %le\n",ckpnt[i].t0, ckpnt[i].t1);
      printf("Step number:   %ld\n",ckpnt[i].nstep);
      printf("Order:         %d\n",ckpnt[i].order);
      printf("Step size:     %le\n",ckpnt[i].step);
      printf("\n");
    }
    
  }
  */
  
  /* Initialize yB */
  yB = N_VNew_Serial(NEQ);
  if (check_flag((void *)yB, "N_VNew_Serial", 0)) return(1);
  Ith(yB,1) = ZERO;
  Ith(yB,2) = ZERO;
  Ith(yB,3) = ZERO;

  /* Initialize qB */
  qB = N_VNew_Serial(NP);
  if (check_flag((void *)qB, "N_VNew", 0)) return(1);
  Ith(qB,1) = ZERO;
  Ith(qB,2) = ZERO;
  Ith(qB,3) = ZERO;

  /* Set the scalar relative tolerance reltolB */
  reltolB = RTOL;               

  /* Set the scalar absolute tolerance abstolB */
  abstolB = ATOLl;

  /* Set the scalar absolute tolerance abstolQB */
  abstolQB = ATOLq;

  /* Create and allocate CVODES memory for backward run */
  printf("Create and allocate CVODES memory for backward run\n");

  flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
  if (check_flag(&flag, "CVodeCreateB", 1)) return(1);

  flag = CVodeInitB(cvode_mem, indexB, fB, TB1, yB);
  if (check_flag(&flag, "CVodeInitB", 1)) return(1);

  flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
  if (check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);

  flag = CVodeSetUserDataB(cvode_mem, indexB, data);
  if (check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);

  flag = CVDenseB(cvode_mem, indexB, NEQ);
  if (check_flag(&flag, "CVDenseB", 1)) return(1);

  flag = CVDlsSetDenseJacFnB(cvode_mem, indexB, JacB);
  if (check_flag(&flag, "CVDlsSetDenseJacFnB", 1)) return(1);

  flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB);
  if (check_flag(&flag, "CVodeQuadInitB", 1)) return(1);

  flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolB, abstolQB);
  if (check_flag(&flag, "CVodeQuadSStolerancesB", 1)) return(1);

  flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE);
  if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);

  /* Backward Integration */
  printf("Backward integration ... ");

  flag = CVodeB(cvode_mem, T0, CV_NORMAL);
  if (check_flag(&flag, "CVodeB", 1)) return(1);
  CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB);
  printf("done ( nst = %ld )\n", nstB);

  flag = CVodeGetB(cvode_mem, indexB, &time, yB);
  if (check_flag(&flag, "CVodeGetB", 1)) return(1);

  flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB);
  if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1);

  PrintOutput(TB1, yB, qB);

  /* Reinitialize backward phase (new tB0) */

  Ith(yB,1) = ZERO;
  Ith(yB,2) = ZERO;
  Ith(yB,3) = ZERO;

  Ith(qB,1) = ZERO;
  Ith(qB,2) = ZERO;
  Ith(qB,3) = ZERO;

  printf("Re-initialize CVODES memory for backward run\n");

  flag = CVodeReInitB(cvode_mem, indexB, TB2, yB);
  if (check_flag(&flag, "CVodeReInitB", 1)) return(1);

  flag = CVodeQuadReInitB(cvode_mem, indexB, qB); 
  if (check_flag(&flag, "CVodeQuadReInitB", 1)) return(1);

  printf("Backward integration ... ");

  flag = CVodeB(cvode_mem, T0, CV_NORMAL);
  if (check_flag(&flag, "CVodeB", 1)) return(1);
  CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB);
  printf("done ( nst = %ld )\n", nstB);

  flag = CVodeGetB(cvode_mem, indexB, &time, yB);
  if (check_flag(&flag, "CVodeGetB", 1)) return(1);

  flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB);
  if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1);

  PrintOutput(TB2, yB, qB);

  /* Free memory */
  printf("Free memory\n\n");

  CVodeFree(&cvode_mem);
  N_VDestroy_Serial(y); 
  N_VDestroy_Serial(q);
  N_VDestroy_Serial(yB);
  N_VDestroy_Serial(qB);

  if (ckpnt != NULL) free(ckpnt);
  free(data);

  return(0);

}