C ++ числовые интеграторы для решения систем Оде

Я недавно начал использовать C ++, и я только что создал класс, который позволяет интегрировать пользовательскую систему од. Для сравнения производительности используются два разных интегратора. Вот общая схема кода:

    class integrators {
private:
double  ti;    // initial time
double *xi;  // initial solution
double  tf;    // end time
double  dt;  // time step
int      n;  // number of ode's

public:
// Function prototypes
double   f(double, double *, double *);  // function to integrate
double rk4(int, double, double, double, double *, double *);
double dp8(int, double, double, double, double *, double *);
};

// 4th Order Runge-Kutta function
double integrators::rk4(int n, double ti, double tf, double dt, double *xi, double *xf) {
// Function statements
}

// 8th Order Dormand-Prince function
double integrators::dp8(int n, double ti, double tf, double dt, double *xi, double *xf) {
// Function statements
}

// System of first order differential equations
double integrators::f(double t, double *x, double *dx) {
// Function statements
}

int main() {
// Initial conditions and time related parameters
const int n = 4;
double t0, tmax, dt;
double x0[n], xf[n];

x0[0] = 0.0;
x0[1] = 0.0;
x0[2] = 1.0;
x0[3] = 2.0;

// Calling class integrators
integrators example01;
integrators example02;

// First integrator
example02.dp8(n, t0, tmax, dt, x0, xf);

// Second integrator
example01.rk4(n, t0, tmax, dt, x0, xf);
}

Проблема в том, что массив, содержащий начальные условия x0 в основном, изменяется после выполнения первого интегратора, и я не могу использовать те же начальные условия для второго интегратора, если я не определю другой массив с такими же начальными условиями (x0_rk4 и x0_dp8). Есть ли более профессиональный способ сохранить этот массив постоянным, чтобы использовать его в обоих интеграторах?

0

Решение

Нет, не совсем. Но существует более элегантное решение:

std::array<double, n> x0_rk4 = { 0.0, 0.0, 1.0, 2.0 };
auto x0_dp8 = x0_rk4; // copy!

Вам придется использовать x0_rk4.data() для доступа к базовому массиву. Обратите внимание, что было бы лучше, если бы вы использовали std::array и другие современные функции C ++ вместо необработанных указателей и тому подобное.

1

Другие решения

Самый простой способ — сделать локальную копию массива внутри интегрирующих функций.

Измените способ передачи ‘n’ в функцию ‘const int n’, чтобы вы могли сделать что-то вроде double currentSolution[n]; внутри и скопировать элементы из исходного массива в новый. Этот подход сохранит ваш исходный массив без изменений, если только вы не «случайно» его где-нибудь не измените.

Чтобы предотвратить эту вероятность модификации аварии, нам нужно пойти глубже и использовать один из контейнеров stl. Я думаю, что вы будете в порядке с std::valarray<T>,

Измените способ передачи const std::valarray<double>& и снова сделайте неконстантную локальную копию.

2

По вопросам рекламы [email protected]