@@ -77,10 +77,12 @@ typedef struct RK4_DATA
7777 int work_states_ndims ;
7878 double * b ;
7979 double * c ;
80+ double h ;
8081}RK4_DATA ;
8182
8283
8384static int euler_ex_step (DATA * data , SOLVER_INFO * solverInfo );
85+ static int rungekutta_step_ssc (DATA * data , threadData_t * threadData , SOLVER_INFO * solverInfo );
8486static int rungekutta_step (DATA * data , threadData_t * threadData , SOLVER_INFO * solverInfo );
8587static int sym_euler_im_step (DATA * data , threadData_t * threadData , SOLVER_INFO * solverInfo );
8688
@@ -154,6 +156,12 @@ int solver_main_step(DATA* data, threadData_t *threadData, SOLVER_INFO* solverIn
154156 TRACE_POP
155157 return retVal ;
156158#endif
159+ case S_ERKSSC :
160+ retVal = rungekutta_step_ssc (data , threadData , solverInfo );
161+ if (omc_flag [FLAG_SOLVER_STEPS ])
162+ data -> simulationInfo -> solverSteps = solverInfo -> solverStats [0 ] + solverInfo -> solverStatsTmp [0 ];
163+ TRACE_POP
164+ return retVal ;
157165 case S_SYM_EULER :
158166 retVal = sym_euler_im_step (data , threadData , solverInfo );
159167 if (omc_flag [FLAG_SOLVER_STEPS ])
@@ -214,6 +222,7 @@ int initializeSolverData(DATA* data, threadData_t *threadData, SOLVER_INFO* solv
214222 allocateSymEulerImp (solverInfo , data -> modelData -> nStates );
215223 break ;
216224 }
225+ case S_ERKSSC :
217226 case S_RUNGEKUTTA :
218227 case S_HEUN :
219228 {
@@ -237,6 +246,9 @@ int initializeSolverData(DATA* data, threadData_t *threadData, SOLVER_INFO* solv
237246 rungeData -> work_states_ndims = heun_s ;
238247 rungeData -> b = heun_b ;
239248 rungeData -> c = heun_c ;
249+ } else if (solverInfo -> solverMethod == S_ERKSSC ) {
250+ rungeData -> h = (omc_flag [FLAG_INITIAL_STEP_SIZE ]) ? atof (omc_flagValue [FLAG_INITIAL_STEP_SIZE ]) : solverInfo -> currentStepSize ;
251+ rungeData -> work_states_ndims = 5 ;
240252 } else {
241253 throwStreamPrint (threadData , "Unknown RK solver" );
242254 }
@@ -357,7 +369,8 @@ int freeSolverData(DATA* data, SOLVER_INFO* solverInfo)
357369 {
358370 freeSymEulerImp (solverInfo );
359371 }
360- else if (solverInfo -> solverMethod == S_RUNGEKUTTA || solverInfo -> solverMethod == S_HEUN )
372+ else if (solverInfo -> solverMethod == S_RUNGEKUTTA || solverInfo -> solverMethod == S_HEUN
373+ || solverInfo -> solverMethod == S_ERKSSC )
361374 {
362375 /* free RK work arrays */
363376 for (i = 0 ; i < ((RK4_DATA * )(solverInfo -> solverData ))-> work_states_ndims + 1 ; i ++ )
@@ -802,6 +815,127 @@ static int euler_ex_step(DATA* data, SOLVER_INFO* solverInfo)
802815 return 0 ;
803816}
804817
818+ /*************************************** EXP_RK_SSC *********************************/
819+ static int rungekutta_step_ssc (DATA * data , threadData_t * threadData , SOLVER_INFO * solverInfo )
820+ {
821+ // see.
822+ // Solving Stiff Systems of ODEs by Explicit Methods with Conformed Stability
823+ // Domains
824+ // 2016 9th EUROSIM Congress on Modelling and Simulation
825+ // A. E. Novikov...
826+
827+ RK4_DATA * rk = ((RK4_DATA * )(solverInfo -> solverData ));
828+ const double Atol = data -> simulationInfo -> tolerance ;
829+ const double Rtol = data -> simulationInfo -> tolerance ;
830+ const int nx = data -> modelData -> nStates ;
831+ modelica_real h = rk -> h ;
832+ double * * k = rk -> work_states ;
833+ int j , i ;
834+ double sum ;
835+ SIMULATION_DATA * sData = (SIMULATION_DATA * )data -> localData [0 ];
836+ SIMULATION_DATA * sDataOld = (SIMULATION_DATA * )data -> localData [1 ];
837+ modelica_real * stateDer = sData -> realVars + nx ;
838+ modelica_real * stateDerOld = sDataOld -> realVars + nx ;
839+ double t = sDataOld -> timeValue ;
840+ const double targetTime = t + solverInfo -> currentStepSize ;
841+ const short isMaxStepSizeSet = (short ) omc_flagValue [FLAG_MAX_STEP_SIZE ];
842+ const double maxStepSize = isMaxStepSizeSet ? atof (omc_flagValue [FLAG_MAX_STEP_SIZE ]) : -1 ;
843+ double x0 [nx ];
844+
845+ if (t + h > targetTime )
846+ h = solverInfo -> currentStepSize ;
847+
848+ memcpy (k [0 ], stateDerOld , nx * sizeof (double ));
849+ memcpy (x0 , sDataOld -> realVars , nx * sizeof (double ));
850+ while (t < targetTime && h > 0 ){
851+ //printf("\nfrom %g to %g by %g\n", t, targetTime, h);
852+ for (j = 0 ; j < 5 ; ++ j ){
853+
854+ if (j > 0 )
855+ memcpy (k [j ], stateDer , nx * sizeof (double ));
856+
857+ switch (j ){
858+ case 0 :
859+ //yn + k1/3
860+ for (i = 0 ; i < nx ; ++ i )
861+ sData -> realVars [i ] = x0 [i ] + h * k [0 ][i ]/3.0 ;
862+ sData -> timeValue = t + h /3.0 ;
863+ break ;
864+
865+ case 1 :
866+ //yn + 1/6(k1 + k2)
867+ for (i = 0 ; i < nx ; ++ i )
868+ sData -> realVars [i ] = x0 [i ] + h /6.0 * (k [0 ][i ] + k [1 ][i ]);
869+ sData -> timeValue = t + h /3.0 ;
870+ break ;
871+
872+ case 2 :
873+ //yn + 1/8*(k1 + 3*k3)
874+ for (i = 0 ; i < nx ; ++ i )
875+ sData -> realVars [i ] = x0 [i ] + h /8.0 * (k [0 ][i ] + 3 * k [2 ][i ]);
876+ sData -> timeValue = t + h /2.0 ;
877+ break ;
878+
879+ case 3 :
880+ //yn + 1/2*(k1 - 3*k3 + 4*k4)
881+ for (i = 0 ; i < nx ; ++ i )
882+ sData -> realVars [i ] = x0 [i ] + h /2.0 * (k [0 ][i ] - 3 * k [2 ][i ] + 4 * k [3 ][i ]);
883+ sData -> timeValue = t + h ;
884+ break ;
885+
886+ case 4 :
887+ //yn + 1/6*(k1 + 4*k3 + k5)
888+ for (i = 0 ; i < nx ; ++ i ){
889+ sData -> realVars [i ] = x0 [i ] + h /6.0 * (k [0 ][i ] + 4 * k [3 ][i ] + k [4 ][i ]);
890+ }
891+ sData -> timeValue = t + h ;
892+ break ;
893+
894+ }
895+ //f(yn + ...)
896+ /* read input vars */
897+ externalInputUpdate (data );
898+ data -> callback -> input_function (data , threadData );
899+ /* eval ode equations */
900+ data -> callback -> functionODE (data , threadData );
901+ }
902+ t += h ;
903+ sData -> timeValue = t ;
904+ solverInfo -> currentTime = t ;
905+
906+ /* save stats */
907+ /* steps */
908+ solverInfo -> solverStatsTmp [0 ] += 1 ;
909+ /* function ODE evaluation is done directly after this */
910+ solverInfo -> solverStatsTmp [1 ] += 4 ;
911+
912+
913+ //stepsize
914+ for (i = 0 , sum = 0.0 ; i < nx ; ++ i )
915+ sum = fmax (fabs (k [0 ][i ] + 4 * k [3 ][i ] - (4.5 * k [2 ][i ] + k [4 ][i ]))/(fabs (k [4 ][i ]) + fabs (k [2 ][i ]) + fabs (k [3 ][i ])+ + fabs (k [0 ][i ]) + Atol ), sum );
916+ sum *= 2.0 /30.0 ;
917+
918+
919+ h = fmin (0.9 * fmax (pow (sum ,1 /4.0 )/(Atol ), 1e-12 )* h + 1e-12 , (targetTime - h ));
920+ if (isMaxStepSizeSet && h > maxStepSize ) h = maxStepSize ;
921+ if (h > 0 ) rk -> h = h ;
922+
923+ if (t < targetTime ){
924+ memcpy (x0 , sData -> realVars , nx * sizeof (double ));
925+ memcpy (k [0 ], k [4 ], nx * sizeof (double ));
926+ sim_result .emit (& sim_result , data , threadData );
927+ }
928+ }
929+
930+ //assert(sData->timeValue == targetTime);
931+ //assert(solverInfo->currentTime == targetTime);
932+
933+ return 0 ;
934+ }
935+
936+
937+
938+
805939/*************************************** SYM_EULER_IMP *********************************/
806940static int sym_euler_im_step (DATA * data , threadData_t * threadData , SOLVER_INFO * solverInfo ){
807941 int retVal ,i ,j ;
0 commit comments