/* Fortran interface routine to re-initialize ARKode memory structure for a problem with a new size but similar time scale; functions as an all-in-one interface to the C routines ARKodeResize (and potentially ARKodeSVtolerances); see farkode.h for further details */ void FARK_RESIZE(realtype *t0, realtype *y0, realtype *hscale, int *itol, realtype *rtol, realtype *atol, int *ier) { *ier = 0; /* Set data in F2C_ARKODE_vec to y0 */ N_VSetArrayPointer(y0, F2C_ARKODE_vec); /* Call ARKodeResize (currently does not allow Fortran user-supplied vector resize function) */ *ier = ARKodeResize(ARK_arkodemem, F2C_ARKODE_vec, *hscale, *t0, NULL, NULL); /* Reset data pointer */ N_VSetArrayPointer(NULL, F2C_ARKODE_vec); /* On failure, exit */ if (*ier != ARK_SUCCESS) { *ier = -1; return; } /* Set tolerances, based on itol argument */ if (*itol) { N_Vector Vatol = NULL; Vatol = N_VCloneEmpty(F2C_ARKODE_vec); if (Vatol == NULL) { *ier = -1; return; } N_VSetArrayPointer(atol, Vatol); *ier = ARKodeSVtolerances(ARK_arkodemem, *rtol, Vatol); N_VDestroy(Vatol); } return; }
void Arkode::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*>(_arkodesettings)->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 (_arkodesettings->getDenseOutput()) { // Ausgabeschrittweite _hOut = global_settings->gethOutput(); } // Allocate memory for the solver //arkodeCreate _arkodeMem = ARKodeCreate(); /* if (check_flag((void*) _cvodeMem, "CVodeCreate", 0)) { _idid = -5; throw ModelicaSimulationError(SOLVER,"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*>(_arkodesettings)->getATol(); _ARK_y0 = N_VMake_Serial(_dimSys, _zInit); _ARK_y = N_VMake_Serial(_dimSys, _z); _ARK_yWrite = N_VMake_Serial(_dimSys, _zWrite); _ARK_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 = ARKodeInit(_arkodeMem, NULL, ARK_fCallback, _tCurrent, _ARK_y0); if (_idid < 0) { _idid = -5; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } // Set Tolerances _idid = ARKodeSVtolerances(_arkodeMem, dynamic_cast<ISolverSettings*>(_arkodesettings)->getRTol(), _ARK_absTol); // RTOL and ATOL if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); // Set the pointer to user-defined data _idid = ARKodeSetUserData(_arkodeMem, _data); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); _idid = ARKodeSetInitStep(_arkodeMem, 1e-6); // INITIAL STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); _idid = ARKodeSetMaxConvFails(_arkodeMem, 100); // Maximale Fehler im Konvergenztest if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = ARKodeSetMinStep(_arkodeMem, dynamic_cast<ISolverSettings*>(_arkodesettings)->getLowerLimit()); // MINIMUM STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = ARKodeSetMaxStep(_arkodeMem, global_settings->getEndTime() / 10.0); // MAXIMUM STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = ARKodeSetMaxNonlinIters(_arkodeMem, 5); // Max number of iterations if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = ARKodeSetMaxErrTestFails(_arkodeMem, 100); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = ARKodeSetMaxNumSteps(_arkodeMem, 1000); // Max Number of steps if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); // Initialize linear solver /* #ifdef USE_SUNDIALS_LAPACK _idid = CVLapackDense(_cvodeMem, _dimSys); #else */ _idid = ARKDense(_arkodeMem, _dimSys); /* #endif */ if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); // Use own jacobian matrix // Check if Colored Jacobians are worth to use if (_idid < 0) throw ModelicaSimulationError(SOLVER,"ARKode::initialize()"); if (_dimZeroFunc) { _idid = ARKodeRootInit(_arkodeMem, _dimZeroFunc, &ARK_ZerofCallback); memset(_zeroSign, 0, _dimZeroFunc * sizeof(int)); _idid = ARKodeSetRootDirection(_arkodeMem, _zeroSign); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); memset(_zeroSign, -1, _dimZeroFunc * sizeof(int)); memset(_zeroVal, -1, _dimZeroFunc * sizeof(int)); } _arkode_initialized = true; // // CVODE is ready for integration // // BOOST_LOG_SEV(cvode_lg::get(), cvode_info) << "CVode initialized"; } }
/* Fortran interface routine to initialize ARKode memory structure; functions as an all-in-one interface to the C routines ARKodeCreate, ARKodeSetUserData, ARKodeInit, and ARKodeSStolerances (or ARKodeSVtolerances); see farkode.h for further details */ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex, int *iatol, realtype *rtol, realtype *atol, long int *iout, realtype *rout, long int *ipar, realtype *rpar, int *ier) { N_Vector Vatol; FARKUserData ARK_userdata; realtype reltol, abstol; *ier = 0; /* Check for required vector operations */ if(F2C_ARKODE_vec->ops->nvgetarraypointer == NULL) { *ier = -1; printf("Error: getarraypointer vector operation is not implemented.\n\n"); return; } if(F2C_ARKODE_vec->ops->nvsetarraypointer == NULL) { *ier = -1; printf("Error: setarraypointer vector operation is not implemented.\n\n"); return; } if(F2C_ARKODE_vec->ops->nvcloneempty == NULL) { *ier = -1; printf("Error: cloneempty vector operation is not implemented.\n\n"); return; } /* Initialize all pointers to NULL */ ARK_arkodemem = NULL; Vatol = NULL; /* initialize global constants to zero */ ARK_nrtfn = 0; ARK_ls = 0; ARK_mass_ls = 0; /* Create ARKODE object */ ARK_arkodemem = ARKodeCreate(); if (ARK_arkodemem == NULL) { *ier = -1; return; } /* Set and attach user data */ ARK_userdata = NULL; ARK_userdata = (FARKUserData) malloc(sizeof *ARK_userdata); if (ARK_userdata == NULL) { *ier = -1; return; } ARK_userdata->rpar = rpar; ARK_userdata->ipar = ipar; *ier = ARKodeSetUserData(ARK_arkodemem, ARK_userdata); if(*ier != ARK_SUCCESS) { free(ARK_userdata); ARK_userdata = NULL; *ier = -1; return; } /* Set data in F2C_ARKODE_vec to y0 */ N_VSetArrayPointer(y0, F2C_ARKODE_vec); /* Call ARKodeInit based on imex argument */ switch (*imex) { case 0: /* purely implicit */ *ier = ARKodeInit(ARK_arkodemem, NULL, FARKfi, *t0, F2C_ARKODE_vec); break; case 1: /* purely explicit */ *ier = ARKodeInit(ARK_arkodemem, FARKfe, NULL, *t0, F2C_ARKODE_vec); break; case 2: /* imex */ *ier = ARKodeInit(ARK_arkodemem, FARKfe, FARKfi, *t0, F2C_ARKODE_vec); break; } /* Reset data pointers */ N_VSetArrayPointer(NULL, F2C_ARKODE_vec); /* On failure, exit */ if(*ier != ARK_SUCCESS) { free(ARK_userdata); ARK_userdata = NULL; *ier = -1; return; } /* Set tolerances -- if <= 0, keep as defaults */ reltol=1.e-4; abstol=1.e-9; if (*rtol > 0.0) reltol = *rtol; switch (*iatol) { case 1: if (*atol > 0.0) abstol = *atol; *ier = ARKodeSStolerances(ARK_arkodemem, reltol, abstol); break; case 2: Vatol = N_VCloneEmpty(F2C_ARKODE_vec); if (Vatol == NULL) { free(ARK_userdata); ARK_userdata = NULL; *ier = -1; return; } N_VSetArrayPointer(atol, Vatol); if (N_VMin(Vatol) <= 0.0) N_VConst(abstol, Vatol); *ier = ARKodeSVtolerances(ARK_arkodemem, reltol, Vatol); N_VDestroy(Vatol); break; } /* On failure, exit */ if(*ier != ARK_SUCCESS) { free(ARK_userdata); ARK_userdata = NULL; *ier = -1; return; } /* store pointers to optional output arrays in global vars */ ARK_iout = iout; ARK_rout = rout; /* Store the unit roundoff in rout for user access */ ARK_rout[5] = UNIT_ROUNDOFF; return; }
/* Fortran interface routine to re-initialize ARKode memory structure; functions as an all-in-one interface to the C routines ARKodeReInit and ARKodeSStolerances (or ARKodeSVtolerances); see farkode.h for further details */ void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol, realtype *rtol, realtype *atol, int *ier) { N_Vector Vatol; realtype reltol, abstol; *ier = 0; /* Initialize all pointers to NULL */ Vatol = NULL; /* Set data in F2C_ARKODE_vec to y0 */ N_VSetArrayPointer(y0, F2C_ARKODE_vec); /* Call ARKodeReInit based on imex argument */ switch (*imex) { case 0: /* purely implicit */ *ier = ARKodeReInit(ARK_arkodemem, NULL, FARKfi, *t0, F2C_ARKODE_vec); break; case 1: /* purely explicit */ *ier = ARKodeReInit(ARK_arkodemem, FARKfe, NULL, *t0, F2C_ARKODE_vec); break; case 2: /* imex */ *ier = ARKodeReInit(ARK_arkodemem, FARKfe, FARKfi, *t0, F2C_ARKODE_vec); break; } /* Reset data pointers */ N_VSetArrayPointer(NULL, F2C_ARKODE_vec); /* On failure, exit */ if (*ier != ARK_SUCCESS) { *ier = -1; return; } /* Set tolerances */ reltol=1.e-4; abstol=1.e-9; if (*rtol > 0.0) reltol = *rtol; switch (*iatol) { case 1: if (*atol > 0.0) abstol = *atol; *ier = ARKodeSStolerances(ARK_arkodemem, reltol, abstol); break; case 2: Vatol = N_VCloneEmpty(F2C_ARKODE_vec); if (Vatol == NULL) { *ier = -1; return; } N_VSetArrayPointer(atol, Vatol); if (N_VMin(Vatol) <= 0.0) N_VConst(abstol, Vatol); *ier = ARKodeSVtolerances(ARK_arkodemem, reltol, Vatol); N_VDestroy(Vatol); break; } /* On failure, exit */ if (*ier != ARK_SUCCESS) { *ier = -1; return; } return; }
/* Main Program */ int main() { /* general problem parameters */ realtype T0 = RCONST(0.0); /* initial time */ realtype T1 = RCONST(0.4); /* first output time */ realtype TMult = RCONST(10.0); /* output time multiplication factor */ int Nt = 12; /* total number of output times */ long int NEQ = 3; /* number of dependent vars. */ realtype reltol; int rootsfound[2]; long int nst, nst_a, nfe, nfi, nsetups; long int nje, nfeLS, nni, ncfn, netf, nge; int flag, rtflag; /* reusable error-checking flags */ FILE *UFID; realtype t, tout; int iout; /* general problem variables */ N_Vector y = NULL; /* empty vector for storing solution */ N_Vector atols = NULL; /* empty vector for absolute tolerances */ void *arkode_mem = NULL; /* empty ARKode memory structure */ /* set up the initial conditions */ realtype u0 = RCONST(1.0); realtype v0 = RCONST(0.0); realtype w0 = RCONST(0.0); /* Initial problem output */ printf("\nRobertson ODE test problem (with rootfinding):\n"); printf(" initial conditions: u0 = %g, v0 = %g, w0 = %g\n",u0,v0,w0); /* Initialize data structures */ y = N_VNew_Serial(NEQ); /* Create serial vector for solution */ if (check_flag((void *) y, "N_VNew_Serial", 0)) return 1; atols = N_VNew_Serial(NEQ); /* Create serial vector absolute tolerances */ if (check_flag((void *) atols, "N_VNew_Serial", 0)) return 1; NV_Ith_S(y,0) = u0; /* Set initial conditions into y */ NV_Ith_S(y,1) = v0; NV_Ith_S(y,2) = w0; arkode_mem = ARKodeCreate(); /* Create the solver memory */ if (check_flag((void *)arkode_mem, "ARKodeCreate", 0)) return 1; /* Call ARKodeInit to initialize the integrator memory and specify the hand-side side function in y'=f(t,y), the inital time T0, and the initial dependent variable vector y. Note: since this problem is fully implicit, we set f_E to NULL and f_I to f. */ flag = ARKodeInit(arkode_mem, NULL, f, T0, y); if (check_flag(&flag, "ARKodeInit", 1)) return 1; /* Set tolerances */ reltol = RCONST(1.0e-4); NV_Ith_S(atols,0) = RCONST(1.0e-8); NV_Ith_S(atols,1) = RCONST(1.0e-11); NV_Ith_S(atols,2) = RCONST(1.0e-8); /* Set routines */ flag = ARKodeSetMaxErrTestFails(arkode_mem, 20); /* Increase max error test fails */ if (check_flag(&flag, "ARKodeSetMaxErrTestFails", 1)) return 1; flag = ARKodeSetMaxNonlinIters(arkode_mem, 8); /* Increase max nonlinear iterations */ if (check_flag(&flag, "ARKodeSetMaxNonlinIters", 1)) return 1; flag = ARKodeSetNonlinConvCoef(arkode_mem, 1.e-7); /* Update nonlinear solver convergence coeff. */ if (check_flag(&flag, "ARKodeSetNonlinConvCoef", 1)) return 1; flag = ARKodeSetMaxNumSteps(arkode_mem, 100000); /* Increase max number of steps */ if (check_flag(&flag, "ARKodeSetMaxNumSteps", 1)) return 1; flag = ARKodeSVtolerances(arkode_mem, reltol, atols); /* Specify tolerances */ if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1; /* Specify the root-finding function, having 2 equations */ flag = ARKodeRootInit(arkode_mem, 2, g); if (check_flag(&flag, "ARKodeRootInit", 1)) return 1; /* Linear solver specification */ flag = ARKDense(arkode_mem, NEQ); /* Specify dense linear solver */ if (check_flag(&flag, "ARKDense", 1)) return 1; flag = ARKDlsSetDenseJacFn(arkode_mem, Jac); /* Set the Jacobian routine */ if (check_flag(&flag, "ARKDlsSetDenseJacFn", 1)) return 1; /* Open output stream for results, output comment line */ UFID = fopen("solution.txt","w"); fprintf(UFID,"# t u v w\n"); /* output initial condition to disk */ fprintf(UFID," %.16e %.16e %.16e %.16e\n", T0, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2)); /* Main time-stepping loop: calls ARKode to perform the integration, then prints results. Stops when the final time has been reached */ t = T0; printf(" t u v w\n"); printf(" -----------------------------------------------------\n"); printf(" %12.5e %12.5e %12.5e %12.5e\n", t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2)); tout = T1; iout = 0; while(1) { flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL); /* call integrator */ if (check_flag(&flag, "ARKode", 1)) break; printf(" %12.5e %12.5e %12.5e %12.5e\n", t, /* access/print solution */ NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2)); fprintf(UFID," %.16e %.16e %.16e %.16e\n", t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2)); if (flag == ARK_ROOT_RETURN) { /* check if a root was found */ rtflag = ARKodeGetRootInfo(arkode_mem, rootsfound); if (check_flag(&rtflag, "ARKodeGetRootInfo", 1)) return 1; printf(" rootsfound[] = %3d %3d\n", rootsfound[0], rootsfound[1]); } if (flag >= 0) { /* successful solve: update output time */ iout++; tout *= TMult; } else { /* unsuccessful solve: break */ fprintf(stderr,"Solver failure, stopping integration\n"); break; } if (iout == Nt) break; /* stop after enough outputs */ } printf(" -----------------------------------------------------\n"); fclose(UFID); /* Print some final statistics */ flag = ARKodeGetNumSteps(arkode_mem, &nst); check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); flag = ARKodeGetNumRhsEvals(arkode_mem, &nfe, &nfi); check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(&flag, "ARKodeGetNumErrTestFails", 1); flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1); flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); check_flag(&flag, "ARKodeGetNumNonlinSolvConvFails", 1); flag = ARKDlsGetNumJacEvals(arkode_mem, &nje); check_flag(&flag, "ARKDlsGetNumJacEvals", 1); flag = ARKDlsGetNumRhsEvals(arkode_mem, &nfeLS); check_flag(&flag, "ARKDlsGetNumRhsEvals", 1); flag = ARKodeGetNumGEvals(arkode_mem, &nge); check_flag(&flag, "ARKodeGetNumGEvals", 1); printf("\nFinal Solver Statistics:\n"); printf(" Internal solver steps = %li (attempted = %li)\n", nst, nst_a); printf(" Total RHS evals: Fe = %li, Fi = %li\n", nfe, nfi); printf(" Total linear solver setups = %li\n", nsetups); printf(" Total RHS evals for setting up the linear system = %li\n", nfeLS); printf(" Total number of Jacobian evaluations = %li\n", nje); printf(" Total number of Newton iterations = %li\n", nni); printf(" Total root-function g evals = %li\n", nge); printf(" Total number of nonlinear solver convergence failures = %li\n", ncfn); printf(" Total number of error test failures = %li\n", netf); /* Clean up and return with successful completion */ N_VDestroy_Serial(y); /* Free y vector */ ARKodeFree(&arkode_mem); /* Free integrator memory */ return 0; }