Что было бы эквивалентно MaxSteps с использованием решателя ODE GSL?

Я хочу воспроизвести решатель ODE, созданный с помощью Mathematica, с GSL< /а>.

Вот код Mathematica, в котором используется NDSolve:

result[r_] := NDSolve[{
    s'[t] == theta - (mu*s[t]) - ((betaA1*IA1[t] + betaA2*IA2[t] + betaB1*IB1[t] + betaB2*IB2[t]) +
                                  (betaA1T*TA1[t] + betaA2T*TA2[t] + betaB1T*TB1[t] + betaB2T*TB2[t])) * s[t] - 
                                 ((gammaA1*IA1[t] + gammaA2*IA2[t] + gammaB1*IB1[t] + gammaB2*IB2[t]) + 
                                  (gammaA1T*TA1[t] + gammaA2T*TA2[t] + gammaB1T*TB1[t] + gammaB2T*TB2[t])),

//... Some other equations



s[0] = sinit,IA1[0] = IA1init,IA2[0] = IA2init,
IB1[0] = IB1init,IB2[0] = IB2init,TA1[0] = TA1init,
TA2[0] = TA2init,TB1[0] = TB1init,TB2[0] = TB2init},
{s,IA1,IA2,IB1,IB2,TA1,TA2,TB1,TB2},{t,0,tmax},
MaxSteps->100000, StartingStepSize->0.1, Method->{"ExplicitRungeKutta"}];

Попытка получить точный эквивалент с помощью GSL:

int run_simulation() {
    gsl_odeiv_evolve*  e = gsl_odeiv_evolve_alloc(nbins);
    gsl_odeiv_control* c = gsl_odeiv_control_y_new(1e-17, 0);
    gsl_odeiv_step*    s = gsl_odeiv_step_alloc(gsl_odeiv_step_rkf45, nbins);
    gsl_odeiv_system sys = {function, NULL, nbins, this };
    while (_t < _tmax) {  //convergence check here
        int status = gsl_odeiv_evolve_apply(e, c, s, &sys, &_t, _tmax, &_h, y);
        if (status != GSL_SUCCESS) { return status; }
    }
    return 0;
}

Где nbins — количество уравнений, заданных решателю, а _h — текущий размер шага.

Я не привожу здесь сами уравнения, но единственный найденный мной способ ограничить количество шагов (как это делается с MaxSteps->100000 в системе Mathematica) — это адаптировать первый аргумент функции управления gsl_odeiv_control_y_new. Здесь 1e-17 дает мне что-то около 140000 шагов...

Кто-нибудь знает способ заставить решатель ODE GSL использовать заданное максимальное количество шагов? Как вы, наверное, поняли, для меня важно иметь результаты, которые я действительно могу сравнить между этими двумя инструментами.

Спасибо за помощь.


person Gauthier Boaglio    schedule 06.10.2013    source источник


Ответы (1)


MaxSteps в Mathematica важен только тогда, когда RK (Runge Kutta) застревает и, следовательно, не может должным образом развить вашу систему. Он не фиксирует количество шагов, которые вы хотите сделать, или точность, в которой вы нуждаетесь. Конечно, более высокая точность требует меньшего размера шага, что подразумевает большее количество шагов в фиксированном интервале. Но я хочу сказать, что если у вас не странная система, в которой RK застревает и дает сбой (и вы бы ясно видели сообщение об ошибке Mathematica в этом случае), или вы не установили maxsteps смехотворно малым, MaxSteps не поможет вам правильно сравнить mathematica и ГСЛ.

Для корректного сравнения необходимо установить одинаковые требования к точности и функции управления в обеих программах. На самом деле, вы можете настроить произвольную функцию управления в GSL, помимо стандартных опций, через функции API gsl_odeiv2_control_alloc и gsl_odeiv2_control_hadjust. Вы также должны проверить, какое именно условие остановки используется в вашем коде Mathematica.

Другим вариантом является использование неадаптивного фиксированного шага RK в обеих программах (в gsl вы можете вызвать систему с фиксированными шагами, вызвав gsl_odeiv2_driver_apply_fixed_step).

Последняя вещь. 1e-17 кажется безумным требованием относительной точности. Помните, что ошибки округления обычно не позволяют RK достичь такого уровня точности. На самом деле ошибки округления — это одна из вещей, которая может привести к зависанию RK и/или заставить Mathematica/GSL не согласиться друг с другом!!!! Вы должны установить точность > 1e-10.

person Vivian Miranda    schedule 07.10.2013
comment
Большое спасибо за это. После дальнейших раскопок я пришел к тому же выводу, что вы упомянули о MaxSteps... Что касается других ваших моментов, это звучит очень интересно, и я попробую эти возможности (я не знал ни о gsl_odeiv2_control_hadjust, ни о том, что мы могли бы использовать фиксированный шаг в GSL ). Тогда спасибо! Еще один вопрос: откуда берутся функции ..._odeiv2_...? У меня их нет. Моя версия GSL устарела? - person Gauthier Boaglio; 08.10.2013