Введение
Применение дифференциальных уравнений в математических моделях реальных процессов позволяет решать задачи в различных областях техники, науки, производства. Например, в ядерной физике – при изучении процессов радиоактивного распада веществ. Поэтому в силу компьютеризации очень полезно иметь программу, позволяющую численно решить ОДУ.
Цель исследования
Целью исследования является решение задачи Коши (1)
(1)
численными методами – методами Рунге-Кутты второго, третьего и четвёртого порядков аппроксимации.
Материал и методы исследования
Рассмотрим равномерную разностную сетку отрезка :
, где – заданное количество равных частей, на которые разбит отрезок , – шаг разбиения.
Пусть , . Тогда будут справедливы явные разностные методы Рунге-Кутты [1,2]:
явный двухэтапный метод Рунге-Кутты второго порядка аппроксимации:
явный трёхэтапный метод Рунге-Кутты третьего порядка аппроксимации:
явный четырёхэтапный метод Рунге-Кутты четвёртого порядка аппроксимации:
Будет продемонстрирована реализация на языке программирования C++ сформулированных выше методов Рунге-Кутты для решения задачи Коши (1) в случае, когда , а также будет рассмотрена визуализация следа точного решения и визуализация разностного решение задачи Коши (1) в одном окне. Однако эти данные можно несложно быстро поменять и решить задачу Коши (1) с другими данными .
Результаты исследования и их обсуждение
Программный код для решения задачи Коши
если мелкость разбиения :
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>
using namespace sf;
using namespace std;
//ширина окна для визуализации решения
const int W = 752;
//высота окна для визуализации решения
const int H = 802;
//следующие данные можно изменить, если необходимо решить другую задачу Коши (1)
const int N = 10;
const double a = 0;
const double b = 1;
const double y_0 = 1; //начальноеусловие u(0)=1
//объявление функции f(t,u)
double f(double t, double u) {
return t + u;
}
//обявление функции - точного решения задачи Коши (1)
double ExactSolution(double x) {
return 2 * exp(x) - x - 1;
}
int main() {
setlocale(LC_ALL, "Russian");
//tau - мелкость разбиения, T - массив значений равномерной разностной сетки, Y - массив значений разностного решения (1)
double tau = (b - a) / N;
double T[N + 1] = {};
for (int i = 1; i <= N; i++) T[i] = a + i * tau;
double Y[N + 1] = {};
Y[0] = y_0;
//z - условие проверки корректности введённых данных пользователем программы
double z = 0;
while (z == 0) {
cout << "Метод Рунге-Кутта какого порядка аппроксимации Вы хотите использовать для приближённого решения задачи Коши?" << endl << "Нажмите:" << endl << "2, если второго порядка аппроксимации;" << endl << "3, если третего порядка аппроксимации;" << endl << "4, если четвёртого порядка аппроксимации" << endl;
int p;
cin >> p;
if (p == 2)
for (int i = 0; i < N; i++) {
double k1 = f(T[i], Y[i]);
double k2 = f(T[i] + tau / 2, Y[i] + tau / 2 * k1);
Y[i + 1] = Y[i] + tau * k2;
z = 1;
}
else if (p == 3)
for (int i = 0; i < N; i++) {
double k1 = f(T[i], Y[i]);
double k2 = f(T[i] + tau / 2, Y[i] + tau / 2 * k1);
double k3 = f(T[i] + tau, Y[i] - tau * k1 + 2 * tau * k2);
Y[i + 1] = Y[i] + tau / 6 * (k1 + 4 * k2 + k3);
z = 1;
}
else if (p == 4)
for (int i = 0; i < N; i++) {
double k1 = f(T[i], Y[i]);
double k2 = f(T[i] + tau / 2, Y[i] + tau / 2 * k1);
double k3 = f(T[i] + tau / 2, Y[i] + tau / 2 * k2);
double k4 = f(T[i] + tau, Y[i] + tau * k3);
Y[i + 1] = Y[i] + tau / 6 * (k1 + 2 * k2 + 2 * k3 + k4);
z = 1;
}
else {
cout << "Такого варианта нет, повторите попытку" << endl;
}
}
//вывод разностного решения и следа точного решения (1)
cout << "t y_n (разностное решение) u_n (след точного решения)" <<endl;
for (int i = 0; i <= N; i++) cout << T[i] << " " << Y[i] <<" "<< ExactSolution(a+tau*i)<< endl;
//следующий фрагмент программы программы написан для визуализации разностного решения и следа точного решения (1), большая часть кода заимствована в [3]
RenderWindow window(VideoMode(W, H), "Exact (black line) and inexact (blue line) solutions of a differential equation");
//центр координатной плоскости
int x0 = W / 2;
int y0 = H / 2;
//ось ox
RectangleShape OsX(Vector2f(W, 1));
OsX.setFillColor(Color::Black);
OsX.setPosition(0, y0);
//ось oy
RectangleShape OsY(Vector2f(1, H));
OsY.setFillColor(Color::Black);
OsY.setPosition(x0, 0);
//стрелкинаосях
RectangleShape strel[4];
for (int i = 0; i < 4; i++) {
strel[i].setSize(Vector2f(1, 25));
strel[i].setFillColor(Color::Black);
if (i < 2)
strel[i].setPosition(x0, 0);
else
strel[i].setPosition(W, y0);
}
strel[0].setRotation(25);
strel[1].setRotation(-25);
strel[2].setRotation(60);
strel[3].setRotation(-250);
//выполнение действий, когда открыто окно
while (window.isOpen())
{
Event event;
//закрытие окна - нажать на крестик
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
window.close();
}
//видокна: белыйэкран
window.clear(Color::White);
//изображение в окне стрелок
window.draw(OsX);
window.draw(OsY);
for (int i = 0; i < 4; i++)
window.draw(strel[i]);
//масштабирование графика по оси ox
int scalex = 100;
//масштабирование графика по оси oy
int scaley = 100;
//визуализация разностного решения задачи Коши (1)
//синие точки радиуса 2 для визуализации разностного решения (1)
CircleShape point1(2.f);
point1.setFillColor(Color::Blue);
for (int i = 0; i <= N; i++) {
float x = T[i];
float y = Y[i]; // нашграфик
//меняем ориентацию системы координат, т.к. по опциям окна она не является "стандартной"
float x1 = x0 + x * scalex;
float y1 = y0 - y * scaley;
//выводим на экран разностное решение задачи Коши(1)
point1.setPosition(x1, y1);
window.draw(point1);
}
//визуализация следа точного решения задачи Коши (1)
//чёрные точки радиуса 1 для визуализации следа точного решения (1)
CircleShape point2(1.f);
point2.setFillColor(Color::Black);
float c = 1000;
int mass = (b - a) * c + 1;
for (int i = 0; i < mass; i++) {
float x = a + i / c;
float y = ExactSolution(x);
float x1 = x0 + x * scalex;
float y1 = y0 - y * scaley;
point2.setPosition(x1, y1);
window.draw(point2);
}
window.display();
}
return 0;
}
В результате выполнения программы, если пользователь сначала ошибётся и на вопрос о выборе метода Рунге-Кутты нажмёт 0, а затем исправится и выберет третий порядок аппроксимации будет выведено два окна (рис. 1 и рис. 2).
Рис. 1.
Рис. 2.
Заключение
Таким образом, в работе продемонстрирована программа, реализованная на языке программирования C++ для решения задачи Коши (1). Данный результат можно использовать для сравнения точности методов Рунге-Кутты второго, третьего и четвёртого порядков аппроксимации опытным путём, а также применять в различных областях техники, науки, производства.
Список литературы
1. Амосов А. А., Дубинский Ю. А., Копченова Н. В. Вычислительные методы для инженеров: Учеб. пособие. – М.: Высш. шк., 1994. – 544 с.: ил. [Электронный ресурс]. URL: https://djvu.online/file/PPFsrza9PEZHq?ysclid=lr9z29dvp6314913486 (дата обращения: 12.01.2024).
2. Мышенков В.И., Мышенков Е.В. Численные методы. Ч. 2. Численное решение обыкновенных дифференциальных уравнений: Учебное пособие для студентов специальности 073000. – М.:МГУЛ, 2005. – 109 с.: ил. [Электронный ресурс]. URL: https://mf.bmstu.ru/UserFiles/File/KF/k6/books/math/uchebniky/Mishenkov_2.pdf (дата обращения: 12.01.2024).
3. Код для визуализации графика функции. [Электронный ресурс]. URL: https://gist.github.com/Andrey-byte/c0a7189f2d422d00cdf762ed434d8fd7 (дата обращения: 12.01.2024).
4. Зенков, А.В. Численные методы: учеб. пособие. — Екатеринбург: Изд-во Урал. ун-та, 2016.— 124 с. [Электронный ресурс]. URL: https://elar.urfu.ru/bitstream/10995/40678/1/978-5-7996-1781-3_2016.pdf?ysclid=lr9zeq8vkn645122653 (дата обращения: 12.01.2024).
5. Т. А. Павловская. C/C++. Программирование на языке высокого уровня. — СПб.: Питер, 2003. —461 с: ил. [Электронный ресурс]. URL: https://studylib.ru/doc/2356765/t.a.-pavlovskaya?ysclid=lr9z9eu9rx64307149 (дата обращения: 12.01.2024).