2015-10-25 1 views
3

Я хочу решить жесткую оду с odeint. Я следовал this (rosenbrock4_dense_output stepper), но моя функция может расти довольно быстро, поэтому я хочу остановить интеграцию, если x (t)> xMAX.Остановить интеграцию в odeint с жесткой одой

В этом question у них есть решение для него, но поскольку я новичок в C++, я не знаю, как реализовать это при использовании шага rosenbrock4_dense_output.

Я хотел бы посмотреть, как написать это специально для шага rosenbrock4_dense_output.

+0

Только на прошлой неделе я добавил пример, который находит точные точки, где перекрещенные некоторый порог: https://github.com/headmyshoulder/odeint-v2/blob/master/examples/find_crossing.cpp. Он использует интерфейс итератора odeint вместе с find_if для остановки при пересечении порога. Затем он делает деление пополам, чтобы приблизиться к точке пересечения, но вам может и не понадобиться. Чтобы адаптироваться к rosenbrock, вам просто нужно изменить шагомер и функцию rhs. – mariomulansky

+0

Это похоже на то, что мне нужно, но я не знаю, как заставить его работать с шаге rosenbrock4_dense_output. Просто изменение runge_kutta_dopri5 к rosenbrock4_dense_output и вместо state_type с помощью vector_type: где vector_Type определяется: ЬурейеЕ повышение :: числовыми :: ublas :: вектор < double > vector_type; - это не все, что требуется. Не могли бы вы объяснить, как это изменится для моего конкретного случая. – marRrR

+0

Вам также необходимо отрегулировать rhs, например. auto ode = make_pair (stiff_system(), stiff_system_jacobi()); - см. также ответ headmyshoulder ниже – mariomulansky

ответ

1

В настоящее время это нелегко с odeint. Если вы можете использовать библиотеку диапазонов here, вы можете комбинировать алгоритм for_each и find_if.

В противном случае вам нужно написать цикл самостоятельно, что тоже не так уж сложно и должно быть похоже на это:

auto stepper = make_dense_output< rosenbrock4<double> >(1.0e-12 , 1.0e-12); 
auto ode = make_pair(stiff_system() , stiff_system_jacobi()); 

double t = 0.0; 
double const end_time = 50.0; 
double const dt = 0.01; 
vector_type x(2 , 1.0); 
const double y_min = 1.0; 

stepper.initialize(x , t , dt); 
cout << t << " " << x[0] << " " << x[1] << endl; // or some other output 
t += dt; 
while(t < end_time) 
{ 
    if(t > stepper.current_time()) 
    { 
     // perform a real step 
     stepper.do_step(ode); 
    } 
    else 
    { 
     // perform a dense output step 
     stepper.calc_state(t , x); 
     cout << t << " " << x[0] << " " << x[1] << endl; // or some other output 
     t += dt; 
    } 
    if(x[1] < y_min) // or some other condition 
    { 
     cout << "Bound reached." << endl; 
     break; 
    } 
} 
+0

Неужели итераторы odeint не работают с rosenbrock_dense_out? Или вы имеете в виду проблему, что с find_if мы не можем получить доступ к траектории? – mariomulansky

+0

Вторая проблема: с 'boost :: range :: find_if()' мы не можем получить доступ к траектории и выполнять наблюдение. – headmyshoulder

+0

Не могли бы вы явно написать, как код будет выглядеть с помощью шага rosenbrock4_dense_output, поскольку я читал документацию с odeint, но, похоже, я не понимаю. – marRrR