fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <fstream>
  5. #include <limits> // Для numeric_limits
  6. #ifdef WITH_GNUPLOT
  7. #include "gnuplot-iostream.h"
  8. #endif
  9.  
  10. using namespace std;
  11.  
  12. // Структура для хранения состояния ракеты
  13. struct State {
  14. double position; // Высота над поверхностью
  15. double velocity;
  16. double mass; // Текущая масса ракеты
  17. };
  18.  
  19. // Структура для параметров модели
  20. struct Parameters {
  21. double initialMass; // Начальная масса ракеты
  22. double fuelConsumptionRate; // Скорость сгорания топлива (кг/с)
  23. double exhaustVelocity; // Скорость истечения газов относительно ракеты
  24. double gravitationalAcceleration; // Ускорение свободного падения
  25. double dragCoefficient; // Коэффициент сопротивления воздуха
  26. double area; // Площадь поперечного сечения ракеты
  27. double airDensity; // Плотность воздуха
  28. double finalTime; // Время симуляции
  29. double timeStep; // Шаг времени
  30. };
  31.  
  32. // Функция для вычисления производных (правая часть дифференциальных уравнений)
  33. vector<double> derivatives(const State& state, const Parameters& params) {
  34. double dragForce = 0.5 * params.airDensity * pow(state.velocity, 2) * params.dragCoefficient * params.area;
  35. double thrust = params.fuelConsumptionRate * params.exhaustVelocity;
  36. double netForce = thrust - dragForce - state.mass * params.gravitationalAcceleration;
  37.  
  38. double acceleration = netForce / state.mass;
  39. double massRate = -params.fuelConsumptionRate; // Масса уменьшается
  40.  
  41. return {state.velocity, acceleration, massRate};
  42. }
  43.  
  44. // Функция для выполнения одного шага метода Рунге-Кутты 4-го порядка
  45. State rk4Step(const State& state, const Parameters& params) {
  46. vector<double> k1 = derivatives(state, params);
  47.  
  48. State state2 = {state.position + params.timeStep * k1[0] / 2.0,
  49. state.velocity + params.timeStep * k1[1] / 2.0,
  50. state.mass + params.timeStep * k1[2] / 2.0};
  51. vector<double> k2 = derivatives(state2, params);
  52.  
  53. State state3 = {state.position + params.timeStep * k2[0] / 2.0,
  54. state.velocity + params.timeStep * k2[1] / 2.0,
  55. state.mass + params.timeStep * k2[2] / 2.0};
  56. vector<double> k3 = derivatives(state3, params);
  57.  
  58. State state4 = {state.position + params.timeStep * k3[0],
  59. state.velocity + params.timeStep * k3[1],
  60. state.mass + params.timeStep * k3[2]};
  61. vector<double> k4 = derivatives(state4, params);
  62.  
  63. return {state.position + params.timeStep * (k1[0] + 2.0 * k2[0] + 2.0 * k3[0] + k4[0]) / 6.0,
  64. state.velocity + params.timeStep * (k1[1] + 2.0 * k2[1] + 2.0 * k3[1] + k4[1]) / 6.0,
  65. state.mass + params.timeStep * (k1[2] + 2.0 * k2[2] + 2.0 * k3[2] + k4[2]) / 6.0};
  66. }
  67.  
  68. int main() {
  69. Parameters params;
  70.  
  71. // Ввод параметров с защитой от "дурака"
  72. cout << "Введите начальную массу ракеты (кг): ";
  73. cin >> params.initialMass;
  74. if (params.initialMass <= 0) {
  75. cout << "Ошибка: Начальная масса должна быть положительной." << endl;
  76. return 1;
  77. }
  78.  
  79. cout << "Введите скорость сгорания топлива (кг/с): ";
  80. cin >> params.fuelConsumptionRate;
  81. if (params.fuelConsumptionRate < 0) {
  82. cout << "Ошибка: Скорость сгорания топлива не может быть отрицательной." << endl;
  83. return 1;
  84. }
  85.  
  86. cout << "Введите скорость истечения газов (м/с): ";
  87. cin >> params.exhaustVelocity;
  88. if (params.exhaustVelocity <= 0) {
  89. cout << "Ошибка: Скорость истечения газов должна быть положительной." << endl;
  90. return 1;
  91. }
  92.  
  93. cout << "Введите ускорение свободного падения (м/с^2): ";
  94. cin >> params.gravitationalAcceleration;
  95. if (params.gravitationalAcceleration < 0) {
  96. cout << "Ошибка: Ускорение свободного падения не может быть отрицательным." << endl;
  97. return 1;
  98. }
  99.  
  100. cout << "Введите коэффициент сопротивления воздуха: ";
  101. cin >> params.dragCoefficient;
  102. if (params.dragCoefficient < 0) {
  103. cout << "Ошибка: Коэффициент сопротивления не может быть отрицательным." << endl;
  104. return 1;
  105. }
  106.  
  107. cout << "Введите площадь поперечного сечения ракеты (м^2): ";
  108. cin >> params.area;
  109. if (params.area <= 0) {
  110. cout << "Ошибка: Площадь должна быть положительной." << endl;
  111. return 1;
  112. }
  113.  
  114. cout << "Введите плотность воздуха (кг/м^3): ";
  115. cin >> params.airDensity;
  116. if (params.airDensity < 0) {
  117. cout << "Ошибка: Плотность воздуха не может быть отрицательной." << endl;
  118. return 1;
  119. }
  120.  
  121. cout << "Введите время симуляции (с): ";
  122. cin >> params.finalTime;
  123. if (params.finalTime <= 0) {
  124. cout << "Ошибка: Время симуляции должно быть положительным." << endl;
  125. return 1;
  126. }
  127.  
  128. cout << "Введите шаг времени (с): ";
  129. cin >> params.timeStep;
  130. if (params.timeStep <= 0) {
  131. cout << "Ошибка: Шаг времени должен быть положительным." << endl;
  132. return 1;
  133. }
  134.  
  135. // Начальное состояние
  136. State currentState = {0.0, 0.0, params.initialMass};
  137.  
  138. // Векторы для хранения данных для графика
  139. vector<pair<double, double>> positionData;
  140. vector<pair<double, double>> velocityData;
  141. vector<pair<double, double>> massData;
  142.  
  143. // Основной цикл симуляции
  144. double time = 0.0;
  145. while (time <= params.finalTime) {
  146. // Сохраняем данные для графика
  147. positionData.push_back({time, currentState.position});
  148. velocityData.push_back({time, currentState.velocity});
  149. massData.push_back({time, currentState.mass});
  150.  
  151. // Выполняем шаг Рунге-Кутты
  152. currentState = rk4Step(currentState, params);
  153.  
  154. // Проверка на "падение" ракеты (высота стала отрицательной)
  155. if (currentState.position < 0) {
  156. currentState.position = 0;
  157. currentState.velocity = 0; // Останавливаем ракету при касании земли
  158. }
  159.  
  160. // Обновляем время
  161. time += params.timeStep;
  162.  
  163. //Проверка на окончание топлива (масса стала меньше, чем масса конструкции ракеты)
  164. if(currentState.mass <= 10)
  165. {
  166. cout<<"Топливо закончилось!"<<endl;
  167. break;
  168. }
  169.  
  170. }
  171.  
  172. #ifdef WITH_GNUPLOT
  173. // Рисуем графики с использованием gnuplot-iostream
  174. Gnuplot gp;
  175. gp << "set terminal qt size 600,400\n"; // Настройка размера окна
  176.  
  177. // График высоты
  178. gp << "set title 'Высота ракеты'\n";
  179. gp << "set xlabel 'Время (с)'\n";
  180. gp << "set ylabel 'Высота (м)'\n";
  181. gp << "plot '-' with lines title 'Высота'\n";
  182. gp.send1d(positionData);
  183.  
  184. // График скорости
  185. gp << "set title 'Скорость ракеты'\n";
  186. gp << "set xlabel 'Время (с)'\n";
  187. gp << "set ylabel 'Скорость (м/с)'\n";
  188. gp << "plot '-' with lines title 'Скорость'\n";
  189. gp.send1d(velocityData);
  190.  
  191. // График массы
  192. gp << "set title 'Масса ракеты'\n";
  193. gp << "set xlabel 'Время (с)'\n";
  194. gp << "set ylabel 'Масса (кг)'\n";
  195. gp << "plot '-' with lines title 'Масса'\n";
  196. gp.send1d(massData);
  197.  
  198. cout << "Графики отображены. Закройте окна графиков для завершения программы." << endl;
  199. cin.get(); // Ждем нажатия Enter, чтобы окна графиков не закрылись сразу
  200. #else
  201. cout << "Для отображения графиков установите библиотеку gnuplot-iostream." << endl;
  202. cout << "Результаты симуляции сохранены в файлы position.dat, velocity.dat и mass.dat." << endl;
  203.  
  204. // Сохраняем данные в файлы (альтернатива gnuplot)
  205. ofstream positionFile("position.dat");
  206. ofstream velocityFile("velocity.dat");
  207. ofstream massFile("mass.dat");
  208.  
  209. for (const auto& p : positionData) positionFile << p.first << " " << p.second << endl;
  210. for (const auto& v : velocityData) velocityFile << v.first << " " << v.second << endl;
  211. for (const auto& m : massData) massFile << m.first << " " << m.second << endl;
  212.  
  213. positionFile.close();
  214. velocityFile.close();
  215. massFile.close();
  216. #endif
  217.  
  218. return 0;
  219. }
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
Введите начальную массу ракеты (кг): Введите скорость сгорания топлива (кг/с): Введите скорость истечения газов (м/с): Введите ускорение свободного падения (м/с^2): Введите коэффициент сопротивления воздуха: Введите площадь поперечного сечения ракеты (м^2): Введите плотность воздуха (кг/м^3): Введите время симуляции (с): Введите шаг времени (с): Топливо закончилось!
Для отображения графиков установите библиотеку gnuplot-iostream.
Результаты симуляции сохранены в файлы position.dat, velocity.dat и mass.dat.