Я пытаюсь решить (большую) систему ODE с помощью решателей GSL. Когда я использую метод драйвера, я получаю сообщение об ошибке could not allocate space for gsl_interp_accel
, когда я определяю управление, ошибку и шаговый режим вручную, я получаю bad_alloc
исключение, которое вызвано, насколько я понимаю, тем же, что вызывает could not allocate space for gsl_interp_accel
в другом случае — нехватка памяти.
Я посоветовался с другими bad_alloc
запросы, такие как этот, но я не нашел там ничего полезного для моего конкретного случая. Кроме того, я пробовал другие решения ODE, но они также заканчиваются ошибками памяти. Я также проверил мою программу с помощью valgrind, чтобы убедиться, что нет ошибок / утечек памяти где-либо еще, кроме решателя.
Любой решатель имеет «пределы интеграции», и в моем случае программа работает нормально примерно на 10% от верхнего предела (который является большим по сравнению с нижним пределом — я почти уверен, что это источник ошибок, которые я получаю — но мне нужно интегрировать между этими конкретными пределами), а затем завершается с одним из исключений, которые я цитировал выше. Я пробовал различный (фиксированный / адаптивный) размер шага, но никогда не достигал более 10% от того, что я хочу.
Кусок кода, который дает исключение:
gsl_ode_struct inputstruct; // Struct that contains parameters for ODEs
gsl_odeiv2_system sys = {func, NULL, 2*G.getsize(), &inputstruct};
const gsl_odeiv2_step_type * T = gsl_odeiv2_step_rk8pd;
gsl_odeiv2_step * stepper = gsl_odeiv2_step_alloc (T, size_of_the_system);
gsl_odeiv2_control * control = gsl_odeiv2_control_standard_new (1.e-6, 0.0, 1., 0.);
gsl_odeiv2_evolve * error = gsl_odeiv2_evolve_alloc (size_of_the_system);
double hparam = 1.e-6; // Initial step size
double t = xspan[0]; // Initial time
while(t < final_time){
// Here the excpection comes
int status = gsl_odeiv2_evolve_apply (error, control, stepper, &sys, &t, final_time, &hparam, array);
if(status != GSL_SUCCESS)
break;
// Do some stuff that includes reading all the intermediate results to a container as I need them later.
}
gsl_odeiv2_evolve_free (error);
gsl_odeiv2_control_free (control);
gsl_odeiv2_step_free (stepper);
Так что, если я изменю final_time
в final_time/10
код выполняется, но результат не имеет смысла. Даже когда ничего не делается после решателя, исключение все равно выбрасывается, could not allocate space for gsl_interp_accel
, хоть.
Я попытался разделить цикл на несколько (много) циклов со стиранием памяти между ними, но это не сильно помогло.
Если это важно, я использую Ubuntu 12.10, скомпилированный с помощью компилятора GNU и Intel C ++ Composer. Также протестировано на Mac (не знаю, какая версия ОС) с тем же результатом.
Вопрос: есть ли способ «обмануть» решатель и заставить программу работать правильно?
П.С .: Решатель ODEint, который имеет более умный способ получения промежуточных результатов, также вызывает исключение.
Я столкнулся с похожими проблемами. Программа завершается с ошибкой bad_alloc в определенное время final_time. Если бы я сократил время интегрирования, программа завершилась бы должным образом, но я этого не хочу. Затем я уменьшаю epsabs с 1e-9 до 1e-6, программа может работать должным образом до нужного мне конечного времени.
Это не решение, а компромисс.
Других решений пока нет …