int SundialsCvode::integrateOneStep(realtype tf) { assert(mathUtils::notnan(y)); CVodeSetStopTime(sundialsMem, tf); int flag = CVode(sundialsMem, tf, y.forSundials(), &tInt, CV_ONE_STEP); if (flag != CV_SUCCESS && flag != CV_TSTOP_RETURN) { errorCount += 1; if (errorCount > errorStopCount) { throw DebugException("CVODE Integrator had too many errors"); } } return flag; }
void FCV_SETRIN(char key_name[], realtype *rval, int *ier) { if (!strncmp(key_name,"INIT_STEP",9)) *ier = CVodeSetInitStep(CV_cvodemem, *rval); else if (!strncmp(key_name,"MAX_STEP",8)) *ier = CVodeSetMaxStep(CV_cvodemem, *rval); else if (!strncmp(key_name,"MIN_STEP",8)) *ier = CVodeSetMinStep(CV_cvodemem, *rval); else if (!strncmp(key_name,"STOP_TIME",9)) *ier = CVodeSetStopTime(CV_cvodemem, *rval); else if (!strncmp(key_name,"NLCONV_COEF",11)) *ier = CVodeSetNonlinConvCoef(CV_cvodemem, *rval); else { *ier = -99; fprintf(stderr, "FCVSETRIN: Unrecognized key.\n\n"); } }
void CvodeSolver::solve(double &pVoi, const double &pVoiEnd) const { // Solve the model if (!mInterpolateSolution) CVodeSetStopTime(mSolver, pVoiEnd); CVode(mSolver, pVoiEnd, mStatesVector, &pVoi, CV_NORMAL); // Compute the rates one more time to get up to date values for the rates // Note: another way of doing this would be to copy the contents of the // calculated rates in rhsFunction, but that's bound to be more time // consuming since a call to CVode() is likely to generate at least a // few calls to rhsFunction(), so that would be quite a few memory // transfers while here we 'only' compute the rates one more time... mComputeRates(pVoiEnd, mConstants, mRates, N_VGetArrayPointer_Serial(mStatesVector), mAlgebraic); }
int integrate(struct Integrator* integrator, double tout, double* t) { if (integrator->em->nRates > 0) { /* need to integrate if we have any differential equations */ int flag; /* Make sure we don't go past the specified end time - could run into trouble if we're almost reaching a threshold */ flag = CVodeSetStopTime(integrator->cvode_mem,(realtype)tout); if (check_flag(&flag,"CVode",1)) return(ERR); flag = CVode(integrator->cvode_mem,tout,integrator->y,t,CV_NORMAL); if (check_flag(&flag,"CVode",1)) return(ERR); /* we also need to evaluate all the other variables that are not required to be updated during integration */ integrator->em->evaluateVariables(*t); } else { /* no differential equations so just evaluate once */ integrator->em->computeRates(tout); integrator->em->evaluateVariables(tout); *t = tout; } /* * Now that using CV_NORMAL_TSTOP this is no longer required? */ #ifdef OLD_CODE /* only the y array is gonna be at the desired tout, so we need to also update the full variables array */ ud->BOUND[0] = *t; ud->methods->ComputeVariables(ud->BOUND,ud->RATES,ud->CONSTANTS, ud->VARIABLES); #endif /* Make sure the outputs are up-to-date */ integrator->em->getOutputs(*t); return(OK); }
int CVodeB(void *cvadj_mem, realtype tBout, N_Vector yBout, realtype *tBret, int itaskB) { CVadjMem ca_mem; CkpntMem ck_mem; CVodeMem cvb_mem; int sign, flag, cv_itask; realtype tBn; if (cvadj_mem == NULL) return(CV_ADJMEM_NULL); ca_mem = (CVadjMem) cvadj_mem; cvb_mem = ca_mem->cvb_mem; if (cvb_mem == NULL) return(CV_BCKMEM_NULL); if (itaskB == CV_NORMAL) cv_itask = CV_NORMAL_TSTOP; else if (itaskB == CV_ONE_STEP) cv_itask = CV_ONE_STEP_TSTOP; else return(CV_BAD_ITASK); ck_mem = ca_mem->ck_mem; sign = (tfinal - tinitial > ZERO) ? 1 : -1; if ( (sign*(tBout-tinitial) < ZERO) || (sign*(tfinal-tBout) < ZERO) ) return(CV_BAD_TBOUT); tBn = cvb_mem->cv_tn; while ( sign*(tBn - t0_) <= ZERO ) ck_mem = next_; loop { /* Store interpolation data if not available This is the 2nd forward integration pass */ if (ck_mem != ckpntData) { flag = CVAdataStore(ca_mem, ck_mem); if (flag != CV_SUCCESS) return(flag); } /* Backward integration */ CVodeSetStopTime((void *)cvb_mem, t0_); flag = CVode(cvb_mem, tBout, yBout, tBret, cv_itask); /* If an error occured, return now */ if (flag < 0) return(flag); /* Set the time at which CVodeGetQuadB will evaluate any quadratures */ t_for_quad = *tBret; /* If in CV_ONE_STEP mode, return now (flag=CV_SUCCESS or flag=CV_TSTOP_RETURN) */ if (itaskB == CV_ONE_STEP) return(flag); /* If succesfully reached tBout, return now */ if (*tBret == tBout) return(flag); /* Move check point in linked list to next one */ ck_mem = next_; } return(CV_SUCCESS); }
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; }
bool Bloch_McConnell_CV_Model::Calculate(double next_tStop){ if ( m_world->time < RTOL) m_world->time += RTOL; CVodeSetStopTime(m_cvode_mem,next_tStop); cout<<NV_Ith_S( ((bmnvec*) (m_world->solverSettings))->y,ZC ) << " "<< NV_Ith_S( ((bmnvec*) (m_world->solverSettings))->y,ZC+3 )<<endl; int flag; #ifndef CVODE26 flag = CVode(m_cvode_mem, m_world->time, ((bmnvec*) (m_world->solverSettings))->y, &m_tpoint, CV_NORMAL_TSTOP); #else do { flag=CVode(m_cvode_mem, m_world->time, ((bmnvec*) (m_world->solverSettings))->y, &m_tpoint, CV_NORMAL); } while ((flag==CV_TSTOP_RETURN) && (m_world->time-TIME_ERR_TOL > m_tpoint )); #endif if(flag < 0) m_world->solverSuccess=false; //reinit needed? if ( m_world->phase == -2.0 && m_world->solverSuccess ) { #ifndef CVODE26 CVodeReInit(m_cvode_mem,bloch,m_world->time + TIME_ERR_TOL,((bmnvec*) (m_world->solverSettings))->y,CV_SV,m_reltol,((bmnvec*) (m_world->solverSettings))->abstol); #else CVodeReInit(m_cvode_mem,m_world->time + TIME_ERR_TOL,((bmnvec*) (m_world->solverSettings))->y); #endif // avoiding warnings: (no idea why initial guess of steplength does not work right here...) CVodeSetInitStep(m_cvode_mem,m_world->pAtom->GetDuration()/1e9); } // loop over pools, stepsize NEQ for ( int i = 0; i< m_ncomp*NEQ; i+=NEQ ) { double solution_dummy_x = NV_Ith_S(((bmnvec*) (m_world->solverSettings))->y, XC+i ); double solution_dummy_y = NV_Ith_S(((bmnvec*) (m_world->solverSettings))->y, YC+i ); m_world->solution[AMPL+i] = sqrt(solution_dummy_x*solution_dummy_x + solution_dummy_y*solution_dummy_y); if (m_world->solution[AMPL+i] < EPS) m_world->solution[PHASE+i] = 0; else if (solution_dummy_y < 0 ) m_world->solution[PHASE+i] = 2*PI - acos(solution_dummy_x / m_world->solution[AMPL+i]); else m_world->solution[PHASE+i] = acos(solution_dummy_x / m_world->solution[AMPL+i]); m_world->solution[ZC+i] = NV_Ith_S(((bmnvec*) (m_world->solverSettings))->y, ZC+i ); // Kaveh, hier sind dann alle pools gleich :( //cout << " bloch solution "<<m_world->solution[ZC+i]<< " " <<" i " << i <<endl; } //higher accuray than 1e-10 not useful. Return success and hope for the best. if(m_reltol < 1e-10) m_world->solverSuccess=true; return m_world->solverSuccess; }
int jmi_ode_cvode_solve(jmi_ode_solver_t* solver, realtype time_final, int initialize){ int flag = 0,retval = 0; jmi_ode_cvode_t* integrator = (jmi_ode_cvode_t*)solver->integrator; jmi_ode_problem_t* problem = solver -> ode_problem; realtype tret/*,*y*/; realtype time; char step_event = 0; /* boolean step_event = FALSE */ if (initialize==JMI_TRUE){ /* statements unused*/ /* if (problem->n_real_x > 0) { y = NV_DATA_S(integrator->y_work); y = problem->states; } */ memcpy (NV_DATA_S(integrator->y_work), problem->states, problem->n_real_x*sizeof(jmi_real_t)); time = problem->time; flag = CVodeReInit(integrator->cvode_mem, time, integrator->y_work); if (flag<0){ jmi_log_node(problem->log, logError, "Error", "Failed to re-initialize the solver. " "Returned with <error_flag: %d>", flag); return JMI_ODE_ERROR; } } /* Dont integrate past t_stop */ flag = CVodeSetStopTime(integrator->cvode_mem, time_final); if (flag < 0){ jmi_log_node(problem->log, logError, "Error", "Failed to specify the stop time. " "Returned with <error_flag: %d>", flag); return JMI_ODE_ERROR; } /* flag = CVode(integrator->cvode_mem, time_final, integrator->y_work, &tret, CV_NORMAL); if(flag<0){ jmi_log_node(problem->log, logError, "Error", "Failed to calculate the next step. " "Returned with <error_flag: %d>", flag); return JMI_ODE_ERROR; } */ flag = CV_SUCCESS; while (flag == CV_SUCCESS) { /* Perform a step */ flag = CVode(integrator->cvode_mem, time_final, integrator->y_work, &tret, CV_ONE_STEP); if(flag<0){ jmi_log_node(problem->log, logError, "Error", "Failed to calculate the next step. " "Returned with <error_flag: %d>", flag); return JMI_ODE_ERROR; } /* After each step call completed integrator step */ retval = problem->complete_step_func(problem, &step_event); if (retval != 0) { jmi_log_node(problem->log, logError, "Error", "Failed to complete an integrator step. " "Returned with <error_flag: %d>", retval); return JMI_ODE_ERROR; } if (step_event == TRUE) { jmi_log_node(problem->log, logInfo, "STEPEvent", "An event was detected at <t:%g>", tret); return JMI_ODE_EVENT; } } /* time = problem->time; if (time != tret) { flag = problem->rhs_func(problem, tret, NV_DATA_S(integrator->y_work), problem->states_derivative); if(flag != 0) { jmi_log_node(problem->log, logWarning, "Warning", "Evaluating the derivatives failed (recoverable error). " "Returned with <warningFlag: %d>", flag); return JMI_ODE_ERROR; } printf("Difference at time %g\n",tret); } */ if (flag == CV_ROOT_RETURN){ jmi_log_node(problem->log, logInfo, "CVODEEvent", "An event was detected at <t:%g>", tret); return JMI_ODE_EVENT; } return JMI_ODE_OK; }
int main() { void *cvode_mem; SUNMatrix A; SUNLinearSolver LS; N_Vector y; int flag, ret; realtype reltol, abstol, t0, t1, t2, t; long int nst1, nst2, nst; reltol = RCONST(1.0e-3); abstol = RCONST(1.0e-4); t0 = RCONST(0.0); t1 = RCONST(1.0); t2 = RCONST(2.0); /* Allocate the vector of initial conditions */ y = N_VNew_Serial(NEQ); /* Set initial condition */ NV_Ith_S(y,0) = RCONST(1.0); /* * ------------------------------------------------------------ * Shared initialization and setup * ------------------------------------------------------------ */ /* Call CVodeCreate to create CVODE memory block and specify the * Backward Differentiaion Formula */ cvode_mem = CVodeCreate(CV_BDF); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Call CVodeInit to initialize integrator memory and specify the * user's right hand side function y'=f(t,y), the initial time T0 * and the initial condiition vector y. */ ret = CVodeInit(cvode_mem, f, t0, y); if (check_flag((void *)&ret, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify integration tolereances, * specifically the scalar relative and absolute tolerance. */ ret = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag((void *)&ret, "CVodeSStolerances", 1)) return(1); /* Provide RHS flag as user data which can be access in user provided routines */ ret = CVodeSetUserData(cvode_mem, &flag); if (check_flag((void *)&ret, "CVodeSetUserData", 1)) return(1); /* Create dense SUNMatrix for use in linear solver */ A = SUNDenseMatrix(NEQ, NEQ); if (check_flag((void *)A, "SUNDenseMatrix", 0)) return(1); /* Create dense linear solver for use by CVode */ LS = SUNLinSol_Dense(y, A); if (check_flag((void *)LS, "SUNLinSol_Dense", 0)) return(1); /* Attach the linear solver and matrix to CVode by calling CVodeSetLinearSolver */ ret = CVodeSetLinearSolver(cvode_mem, LS, A); if (check_flag((void *)&ret, "CVodeSetLinearSolver", 1)) return(1); /* * --------------------------------------------------------------- * Discontinuity in the solution * * 1) Integrate to the discontinuity * 2) Integrate from the discontinuity * --------------------------------------------------------------- */ /* ---- Integrate to the discontinuity */ printf("\nDiscontinuity in solution\n\n"); /* set TSTOP (max time solution proceeds to) - this is not required */ ret = CVodeSetStopTime(cvode_mem, t1); if (check_flag((void *)&ret, "CVodeSetStopTime", 1)) return(1); flag = RHS1; /* use -y for RHS */ t = t0; /* set the integrator start time */ printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); while (t<t1) { /* advance solver just one internal step */ ret = CVode(cvode_mem, t1, y, &t, CV_ONE_STEP); if (check_flag((void *)&ret, "CVode", 1)) return(1); printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); } /* Get the number of steps the solver took to get to the discont. */ ret = CVodeGetNumSteps(cvode_mem, &nst1); if (check_flag((void *)&ret, "CvodeGetNumSteps", 1)) return(1); /* ---- Integrate from the discontinuity */ /* Include discontinuity */ NV_Ith_S(y,0) = RCONST(1.0); /* Reinitialize the solver */ ret = CVodeReInit(cvode_mem, t1, y); if (check_flag((void *)&ret, "CVodeReInit", 1)) return(1); /* set TSTOP (max time solution proceeds to) - this is not required */ ret = CVodeSetStopTime(cvode_mem, t2); if (check_flag((void *)&ret, "CVodeSetStopTime", 1)) return(1); flag = RHS1; /* use -y for RHS */ t = t1; /* set the integrator start time */ printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); while (t<t2) { /* advance solver just one internal step */ ret = CVode(cvode_mem, t2, y, &t, CV_ONE_STEP); if (check_flag((void *)&ret, "CVode", 1)) return(1); printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); } /* Get the number of steps the solver took after the discont. */ ret = CVodeGetNumSteps(cvode_mem, &nst2); if (check_flag((void *)&ret, "CvodeGetNumSteps", 1)) return(1); /* Print statistics */ nst = nst1 + nst2; printf("\nNumber of steps: %ld + %ld = %ld\n",nst1, nst2, nst); /* * --------------------------------------------------------------- * Discontinuity in RHS: Case 1 - explicit treatment * Note that it is not required to set TSTOP, but without it * we would have to find y(t1) to reinitialize the solver. * --------------------------------------------------------------- */ printf("\nDiscontinuity in RHS: Case 1 - explicit treatment\n\n"); /* Set initial condition */ NV_Ith_S(y,0) = RCONST(1.0); /* Reinitialize the solver. CVodeReInit does not reallocate memory * so it can only be used when the new problem size is the same as * the problem size when CVodeCreate was called. */ ret = CVodeReInit(cvode_mem, t0, y); if (check_flag((void *)&ret, "CVodeReInit", 1)) return(1); /* ---- Integrate to the discontinuity */ /* Set TSTOP (max time solution proceeds to) to location of discont. */ ret = CVodeSetStopTime(cvode_mem, t1); if (check_flag((void *)&ret, "CVodeSetStopTime", 1)) return(1); flag = RHS1; /* use -y for RHS */ t = t0; /* set the integrator start time */ printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); while (t<t1) { /* advance solver just one internal step */ ret = CVode(cvode_mem, t1, y, &t, CV_ONE_STEP); if (check_flag((void *)&ret, "CVode", 1)) return(1); printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); } /* Get the number of steps the solver took to get to the discont. */ ret = CVodeGetNumSteps(cvode_mem, &nst1); if (check_flag((void *)&ret, "CvodeGetNumSteps", 1)) return(1); /* If TSTOP was not set, we'd need to find y(t1): */ /* CVodeGetDky(cvode_mem, t1, 0, y); */ /* ---- Integrate from the discontinuity */ /* Reinitialize solver */ ret = CVodeReInit(cvode_mem, t1, y); /* set TSTOP (max time solution proceeds to) - this is not required */ ret = CVodeSetStopTime(cvode_mem, t2); if (check_flag((void *)&ret, "CVodeSetStopTime", 1)) return(1); flag = RHS2; /* use -5y for RHS */ t = t1; /* set the integrator start time */ printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); while (t<t2) { /* advance solver just one internal step */ ret = CVode(cvode_mem, t2, y, &t, CV_ONE_STEP); if (check_flag((void *)&ret, "CVode", 1)) return(1); printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); } /* Get the number of steps the solver took after the discont. */ ret = CVodeGetNumSteps(cvode_mem, &nst2); if (check_flag((void *)&ret, "CvodeGetNumSteps", 1)) return(1); /* Print statistics */ nst = nst1 + nst2; printf("\nNumber of steps: %ld + %ld = %ld\n",nst1, nst2, nst); /* * --------------------------------------------------------------- * Discontinuity in RHS: Case 2 - let CVODE deal with it * Note that here we MUST set TSTOP to ensure that the * change in the RHS happens at the appropriate time * --------------------------------------------------------------- */ printf("\nDiscontinuity in RHS: Case 2 - let CVODE deal with it\n\n"); /* Set initial condition */ NV_Ith_S(y,0) = RCONST(1.0); /* Reinitialize the solver. CVodeReInit does not reallocate memory * so it can only be used when the new problem size is the same as * the problem size when CVodeCreate was called. */ ret = CVodeReInit(cvode_mem, t0, y); if (check_flag((void *)&ret, "CVodeReInit", 1)) return(1); /* ---- Integrate to the discontinuity */ /* Set TSTOP (max time solution proceeds to) to location of discont. */ ret = CVodeSetStopTime(cvode_mem, t1); if (check_flag((void *)&ret, "CVodeSetStopTime", 1)) return(1); flag = RHS1; /* use -y for RHS */ t = t0; /* set the integrator start time */ printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); while (t<t1) { /* advance solver just one internal step */ ret = CVode(cvode_mem, t1, y, &t, CV_ONE_STEP); if (check_flag((void *)&ret, "CVode", 1)) return(1); printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); } /* Get the number of steps the solver took to get to the discont. */ ret = CVodeGetNumSteps(cvode_mem, &nst1); if (check_flag((void *)&ret, "CvodeGetNumSteps", 1)) return(1); /* ---- Integrate from the discontinuity */ /* set TSTOP (max time solution proceeds to) - this is not required */ ret = CVodeSetStopTime(cvode_mem, t2); if (check_flag((void *)&ret, "CVodeSetStopTime", 1)) return(1); flag = RHS2; /* use -5y for RHS */ t = t1; /* set the integrator start time */ printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); while (t<t2) { /* advance solver just one internal step */ ret = CVode(cvode_mem, t2, y, &t, CV_ONE_STEP); if (check_flag((void *)&ret, "CVode", 1)) return(1); printf("%12.8e %12.8e\n",t,NV_Ith_S(y,0)); } /* Get the number of steps the solver took after the discont. */ ret = CVodeGetNumSteps(cvode_mem, &nst); if (check_flag((void *)&ret, "CvodeGetNumSteps", 1)) return(1); /* Print statistics */ nst2 = nst - nst1; printf("\nNumber of steps: %ld + %ld = %ld\n",nst1, nst2, nst); /* Free memory */ N_VDestroy(y); SUNMatDestroy(A); SUNLinSolFree(LS); CVodeFree(&cvode_mem); return(0); }
void Cvode::CVodeCore() { _idid = CVodeReInit(_cvodeMem, _tCurrent, _CV_y); _idid = CVodeSetStopTime(_cvodeMem, _tEnd); _idid = CVodeSetInitStep(_cvodeMem, 1e-12); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::ReInit"); bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == OPT_ALL); bool writeOutput = !(_settings->getGlobalSettings()->getOutputPointType() == OPT_NONE); while ((_solverStatus & ISolver::CONTINUE) && !_interrupt ) { _cv_rt = CVode(_cvodeMem, _tEnd, _CV_y, &_tCurrent, CV_ONE_STEP); _idid = CVodeGetNumSteps(_cvodeMem, &_locStps); if (_idid != CV_SUCCESS) throw ModelicaSimulationError(SOLVER,"CVodeGetNumSteps failed. The cvode mem pointer is NULL"); _idid = CVodeGetLastStep(_cvodeMem, &_h); if (_idid != CV_SUCCESS) throw ModelicaSimulationError(SOLVER,"CVodeGetLastStep failed. The cvode mem pointer is NULL"); //set completed step to system and check if terminate was called if(_continuous_system->stepCompleted(_tCurrent)) _solverStatus = DONE; //Check if there was at least one output-point within the last solver interval // -> Write output if true if (writeOutput) { writeCVodeOutput(_tCurrent, _h, _locStps); } #ifdef RUNTIME_PROFILING MEASURETIME_REGION_DEFINE(cvodeStepCompletedHandler, "CVodeStepCompleted"); if(MeasureTime::getInstance() != NULL) { MEASURETIME_START(measuredFunctionStartValues, cvodeStepCompletedHandler, "CVodeStepCompleted"); } #endif #ifdef RUNTIME_PROFILING if(MeasureTime::getInstance() != NULL) { MEASURETIME_END(measuredFunctionStartValues, measuredFunctionEndValues, (*measureTimeFunctionsArray)[5], cvodeStepCompletedHandler); } #endif // Perform state selection bool state_selection = stateSelection(); if (state_selection) _continuous_system->getContinuousStates(_z); _zeroFound = false; // Check if step was successful if (check_flag(&_cv_rt, "CVode", 1)) { _solverStatus = ISolver::SOLVERERROR; break; } // A root was found if ((_cv_rt == CV_ROOT_RETURN) && !isInterrupted()) { // CVode is setting _tCurrent to the time where the first event occurred double _abs = fabs(_tLastEvent - _tCurrent); _zeroFound = true; if ((_abs < 1e-3) && _event_n == 0) { _tLastEvent = _tCurrent; _event_n++; } else if ((_abs < 1e-3) && (_event_n >= 1 && _event_n < 500)) { _event_n++; } else if ((_abs >= 1e-3)) { //restart event counter _tLastEvent = _tCurrent; _event_n = 0; } else throw ModelicaSimulationError(EVENT_HANDLING,"Number of events exceeded in time interval " + to_string(_abs) + " at time " + to_string(_tCurrent)); // CVode has interpolated the states at time 'tCurrent' _time_system->setTime(_tCurrent); // To get steep steps in the result file, two value points (P1 and P2) must be added // // Y | (P2) X........... // | : // | : // |........X (P1) // |----------------------------------> // | ^ t // _tCurrent // Write the values of (P1) if (writeEventOutput) { _continuous_system->evaluateAll(IContinuous::CONTINUOUS); writeToFile(0, _tCurrent, _h); } _idid = CVodeGetRootInfo(_cvodeMem, _zeroSign); for (int i = 0; i < _dimZeroFunc; i++) _events[i] = bool(_zeroSign[i]); if (_mixed_system->handleSystemEvents(_events)) { // State variables were reinitialized, thus we have to give these values to the cvode-solver // Take care about the memory regions, _z is the same like _CV_y _continuous_system->getContinuousStates(_z); } } if ((_zeroFound || state_selection)&& !isInterrupted()) { // Write the values of (P2) if (writeEventOutput) { // If we want to write the event-results, we should evaluate the whole system again _continuous_system->evaluateAll(IContinuous::CONTINUOUS); writeToFile(0, _tCurrent, _h); } _idid = CVodeReInit(_cvodeMem, _tCurrent, _CV_y); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::ReInit()"); // Der Eventzeitpunkt kann auf der Endzeit liegen (Time-Events). In diesem Fall wird der Solver beendet, da CVode sonst eine interne Warnung schmeißt if (_tCurrent == _tEnd) _cv_rt = CV_TSTOP_RETURN; if(_continuous_system->stepCompleted(_tCurrent)) _solverStatus = DONE; } // Zähler für die Anzahl der ausgegebenen Schritte erhöhen ++_outStps; _tLastSuccess = _tCurrent; if (_cv_rt == CV_TSTOP_RETURN) { _time_system->setTime(_tEnd); //Solver has finished calculation - calculate the final values _continuous_system->setContinuousStates(NV_DATA_S(_CV_y)); _continuous_system->evaluateAll(IContinuous::CONTINUOUS); if(writeOutput) writeToFile(0, _tEnd, _h); _accStps += _locStps; _solverStatus = DONE; } } }
void FCV_MALLOC(realtype *t0, realtype *y0, int *meth, int *itmeth, int *iatol, realtype *rtol, realtype *atol, int *optin, long int *iopt, realtype *ropt, int *ier) { int lmm, iter, itol; void *atolptr; atolptr = NULL; if(F2C_vec->ops->nvgetarraypointer == NULL || F2C_vec->ops->nvsetarraypointer == NULL) { *ier = -1; printf("A required vector operation is not implemented.\n\n"); return; } /* Save the data array in F2C_vec into data_F2C_vec and then overwrite it with y0 */ data_F2C_vec = N_VGetArrayPointer(F2C_vec); N_VSetArrayPointer(y0, F2C_vec); lmm = (*meth == 1) ? CV_ADAMS : CV_BDF; iter = (*itmeth == 1) ? CV_FUNCTIONAL : CV_NEWTON; switch (*iatol) { case 1: F2C_atolvec = NULL; itol = CV_SS; atolptr = (void *) atol; break; case 2: F2C_atolvec = N_VClone(F2C_vec); data_F2C_atolvec = N_VGetArrayPointer(F2C_atolvec); N_VSetArrayPointer(atol, F2C_atolvec); itol = CV_SV; atolptr = (void *) F2C_atolvec; break; case 3: F2C_atolvec = NULL; itol = CV_WF; break; } /* Call CVodeCreate, CVodeSet*, and CVodeMalloc to initialize CVODE: lmm is the method specifier iter is the iteration method specifier CVf is the user's right-hand side function in y'=f(t,y) *t0 is the initial time F2C_vec is the initial dependent variable vector itol specifies tolerance type rtol is the scalar relative tolerance atolptr is the absolute tolerance pointer (to scalar or vector or function) A pointer to CVODE problem memory is createded and stored in CV_cvodemem. */ *ier = 0; CV_cvodemem = CVodeCreate(lmm, iter); if (CV_cvodemem == NULL) { *ier = -1; return; } if (*optin == 1) { CV_optin = TRUE; if (iopt[0] > 0) CVodeSetMaxOrd(CV_cvodemem, (int)iopt[0]); if (iopt[1] > 0) CVodeSetMaxNumSteps(CV_cvodemem, iopt[1]); if (iopt[2] > 0) CVodeSetMaxHnilWarns(CV_cvodemem, (int)iopt[2]); if (iopt[13] > 0) CVodeSetStabLimDet(CV_cvodemem, TRUE); if (iopt[21] > 0) CVodeSetMaxErrTestFails(CV_cvodemem, (int)iopt[21]); if (iopt[22] > 0) CVodeSetMaxNonlinIters(CV_cvodemem, (int)iopt[22]); if (iopt[23] > 0) CVodeSetMaxConvFails(CV_cvodemem, (int)iopt[23]); if (ropt[0] != ZERO) CVodeSetInitStep(CV_cvodemem, ropt[0]); if (ropt[1] > ZERO) CVodeSetMaxStep(CV_cvodemem, ropt[1]); if (ropt[2] > ZERO) CVodeSetMinStep(CV_cvodemem, ropt[2]); if (ropt[7] != ZERO) CVodeSetStopTime(CV_cvodemem, ropt[7]); if (ropt[8] > ZERO) CVodeSetNonlinConvCoef(CV_cvodemem, ropt[8]); } else { CV_optin = FALSE; } *ier = CVodeMalloc(CV_cvodemem, FCVf, *t0, F2C_vec, itol, *rtol, atolptr); /* reset data pointer into F2C_vec */ N_VSetArrayPointer(data_F2C_vec, F2C_vec); /* destroy F2C_atolvec if allocated */ if (F2C_atolvec != NULL) { N_VSetArrayPointer(data_F2C_atolvec, F2C_atolvec); N_VDestroy(F2C_atolvec); } if(*ier != CV_SUCCESS) { *ier = -1; return; } /* Store the unit roundoff in ropt for user access */ ropt[9] = UNIT_ROUNDOFF; CV_iopt = iopt; CV_ropt = ropt; return; }
void FCV_REINIT(realtype *t0, realtype *y0, int *iatol, realtype *rtol, realtype *atol, int *optin, long int *iopt, realtype *ropt, int *ier) { int itol; void *atolptr; atolptr = NULL; N_VSetArrayPointer(y0, F2C_vec); switch (*iatol) { case 1: itol = CV_SS; atolptr = (void *) atol; break; case 2: F2C_atolvec = N_VClone(F2C_vec); data_F2C_atolvec = N_VGetArrayPointer(F2C_atolvec); N_VSetArrayPointer(atol, F2C_atolvec); itol = CV_SV; atolptr = (void *) F2C_atolvec; break; case 3: itol = CV_WF; } /* Call CVodeSet* and CVReInit to re-initialize CVODE: CVf is the user's right-hand side function in y'=f(t,y) t0 is the initial time F2C_vec is the initial dependent variable vector itol specifies tolerance type rtol is the scalar relative tolerance atolptr is the absolute tolerance pointer (to scalar or vector or function) */ if (*optin == 1) { CV_optin = TRUE; if (iopt[0] > 0) CVodeSetMaxOrd(CV_cvodemem, (int)iopt[0]); if (iopt[1] > 0) CVodeSetMaxNumSteps(CV_cvodemem, iopt[1]); if (iopt[2] > 0) CVodeSetMaxHnilWarns(CV_cvodemem, (int)iopt[2]); if (iopt[13] > 0) CVodeSetStabLimDet(CV_cvodemem, TRUE); if (iopt[21] > 0) CVodeSetMaxErrTestFails(CV_cvodemem, (int)iopt[21]); if (iopt[22] > 0) CVodeSetMaxNonlinIters(CV_cvodemem, (int)iopt[22]); if (iopt[23] > 0) CVodeSetMaxConvFails(CV_cvodemem, (int)iopt[23]); if (ropt[0] != ZERO) CVodeSetInitStep(CV_cvodemem, ropt[0]); if (ropt[1] > ZERO) CVodeSetMaxStep(CV_cvodemem, ropt[1]); if (ropt[2] > ZERO) CVodeSetMinStep(CV_cvodemem, ropt[2]); if (ropt[7] != ZERO) CVodeSetStopTime(CV_cvodemem, ropt[7]); if (ropt[8] > ZERO) CVodeSetNonlinConvCoef(CV_cvodemem, ropt[8]); } else { CV_optin = FALSE; } *ier = CVodeReInit(CV_cvodemem, FCVf, *t0, F2C_vec, itol, *rtol, atolptr); /* reset data pointer into F2C_vec */ N_VSetArrayPointer(data_F2C_vec, F2C_vec); /* destroy F2C_atolvec if allocated */ if (F2C_atolvec != NULL) { N_VSetArrayPointer(data_F2C_atolvec, F2C_atolvec); N_VDestroy(F2C_atolvec); } if (*ier != CV_SUCCESS) { *ier = -1; return; } CV_iopt = iopt; CV_ropt = ropt; return; }