Я довольно хорошо разбираюсь в Python, но я новичок в C++ и таких вещах, как указатели. Я пытаюсь написать несколько кодов для решения ODE с помощью пакета Eigen для линейной алгебры (позже мне нужно будет иметь дело с множеством матриц, поэтому я планирую начать с него). У меня есть следующий код для RK4, и они работают:
#include "../eigen-eigen-b3f3d4950030/Eigen/Dense"
using namespace Eigen;
VectorXd Func(const VectorXd& a)
{ // equations for solving simple harmonic oscillator
Vector2d ans;
ans(0) = a(1); // dy/dt
ans(1) = -a(0); // d2y/dt2
return ans;
}
MatrixXd RK4(VectorXd Func(const VectorXd& y), const Ref<const VectorXd>& y0, double h, int step_num)
{
MatrixXd y(step_num, y0.rows());
y.row(0) = y0;
for (int i=1; i<step_num; i++){
VectorXd y_old = y.row(i-1).transpose();
VectorXd k1 = h*Func(y_old);
VectorXd k2 = h*Func(y_old+k1/2);
VectorXd k3 = h*Func(y_old+k2/2);
VectorXd k4 = h*Func(y_old+k3);
VectorXd dy = (k1 + 2*k2 + 2*k3 + k4)/6;
y.row(i) = y.row(i-1) + dy.transpose();
}
return y;
}
int main()
{
Vector2d v1;
v1(0) = 1.4; v1(1) = -0.1;
double h = 0.1;
int step_num = 50;
MatrixXd sol = RK4(Func,v1,h,step_num);
return 0;
}
У меня следующие вопросы:
Что означает & в аргументе функции? Пройти по ссылке? Я просто скопировал код из официальная документация, но я не уверен, понимаю ли я каждый бит в аргументах функций RK4, таких как VectorXd Func(const VectorXd& y). Существуют ли альтернативные способы принятия Eigen :: MatrixXd и функций, которые принимают Eigen :: MatrixXd в качестве аргументов функции?
Насколько я понимаю, мы не можем вернуть весь 2D-массив из функции, и мы возвращаем только первый элемент массива (поправьте меня, если я ошибаюсь). А как насчет Eigen::MatrixX? Что мы на самом деле проходим / возвращаем? Первый элемент матрицы или совершенно новый объект, определенный библиотекой Eigen?
Я не уверен, что эти коды написаны эффективно. Могу ли я что-нибудь сделать, чтобы оптимизировать эту часть? (Просто интересно, сделал ли я что-нибудь, что может значительно замедлить скорость).
Спасибо
Относительно вашего первого вопроса: да, вы правы. Функция, объявленная как ReturnType FunctionName(ArgType& arg);, принимает ссылку на переменную типа ArgType с именем arg. Примечание. Поскольку (особенно) для больших объектов передача аргумента по ссылке вместо их копирования приводит к повышению производительности, многие функции используют ссылки const для своих аргументов. См .: stackoverflow.com/questions/3694630/…
Что касается производительности, по возможности используйте векторные / матричные типы времени компиляции для крошечных объектов (скажем, <10), например Vector2d.





Да, & передается по ссылке; Последний - это синтаксис для передачи функции, которая принимает вектор по ссылке и возвращает вектор. Eigen::Matrix всегда следует передавать по ссылке. Существует множество способов передать одну функцию другой, наиболее идиоматичными в C++, вероятно, являются аргументы шаблона и std::function.
У вас не может быть нескольких возвращаемых аргументов, но вы можете вернуть объект pair, tuple или Matrix. RK4 возвращает всю матрицу.
Код довольно эффективен. Если бы это было действительно критично к производительности, можно было бы кое-что оптимизировать, но пока я бы не беспокоился.
Самым важным моментом является то, что RK4 является очень общим и работает с типами динамического размера, которые намного дороже, чем их аналоги со статическим размером (VectorXf против Vector2d). Но для этого потребуется создать специализированную версию для всех интересующих вас измерений или заставить компилятор делать это за вас с помощью шаблонов.
В общем: для начала прочтите хорошую книгу.
а) пожалуйста, по одному вопросу на вопрос б) посмотрите здесь