Я недавно начал использовать 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). Есть ли более профессиональный способ сохранить этот массив постоянным, чтобы использовать его в обоих интеграторах?
Нет, не совсем. Но существует более элегантное решение:
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 ++ вместо необработанных указателей и тому подобное.
Самый простой способ — сделать локальную копию массива внутри интегрирующих функций.
Измените способ передачи ‘n’ в функцию ‘const int n’, чтобы вы могли сделать что-то вроде double currentSolution[n];
внутри и скопировать элементы из исходного массива в новый. Этот подход сохранит ваш исходный массив без изменений, если только вы не «случайно» его где-нибудь не измените.
Чтобы предотвратить эту вероятность модификации аварии, нам нужно пойти глубже и использовать один из контейнеров stl. Я думаю, что вы будете в порядке с std::valarray<T>
,
Измените способ передачи const std::valarray<double>&
и снова сделайте неконстантную локальную копию.