Загрузка данных
% ============================================================
% РЕШЕНИЕ ДИФФЕРЕНЦИАЛЬНОГО УРАВНЕНИЯ
% dy/dx = -2*x*y, y(0)=1, x ∈ [0, 2]
%
% Лекция 12: "Решение дифференциальных уравнений"
% ============================================================
clear; clc; close all;
%% ЧАСТЬ 1: АНАЛИТИЧЕСКОЕ РЕШЕНИЕ (функция dsolve)
% В лекции: syms y(x); dy = diff(y,x) == -2*x*y; y0 = y(0)==1; dsolve(dy, y0)
disp('=' * 60);
disp('ЧАСТЬ 1: АНАЛИТИЧЕСКОЕ РЕШЕНИЕ (dsolve)');
disp('=' * 60);
syms y(x) % объявляем y как символьную функцию от x
dy = diff(y, x) == -2*x*y; % определяем уравнение: dy/dx = -2*x*y
y0 = y(0) == 1; % начальное условие: при x=0, y=1
y_analytical = dsolve(dy, y0); % точное аналитическое решение
disp(' ');
disp(['Точное решение: y(x) = ', char(y_analytical)]);
disp(' ');
% Преобразуем символьное решение в анонимную функцию для вычислений
y_func = matlabFunction(y_analytical);
%% ЧАСТЬ 2: ЧИСЛЕННОЕ РЕШЕНИЕ (функция ode45)
% В лекции: dydx = @(x,y) -2*x*y; [x, y] = ode45(dydx, [0 2], 1)
disp('=' * 60);
disp('ЧАСТЬ 2: ЧИСЛЕННОЕ РЕШЕНИЕ (ode45)');
disp('=' * 60);
% Определяем правую часть уравнения (как в лекции, стр. 2-3)
dydx = @(x, y) -2 * x * y; % формируем уравнение: dy/dx = -2*x*y
x_interval = [0, 2]; % интервал интегрирования
y0 = 1; % начальное условие y(0)=1
% Решаем ДУ с помощью ode45 (как в лекции, стр. 3)
[x_numerical, y_numerical] = ode45(dydx, x_interval, y0);
disp(['Интервал интегрирования: [0, 2]']);
disp(['Начальное условие: y(0) = ', num2str(y0)]);
disp(['Количество точек решения: ', num2str(length(x_numerical))]);
disp(' ');
disp(['Значение в конце интервала: y(2) = ', num2str(y_numerical(end))]);
%% ЧАСТЬ 3: СРАВНЕНИЕ РЕЗУЛЬТАТОВ И ВИЗУАЛИЗАЦИЯ
% В лекции: fplot(@(t) exp(-t.^2), [0 2]); hold on; plot(x, y, 'ro')
disp('=' * 60);
disp('ЧАСТЬ 3: СРАВНЕНИЕ РЕЗУЛЬТАТОВ');
disp('=' * 60);
% Создаем более плотную сетку для аналитического графика
x_fine = linspace(0, 2, 200);
y_fine = y_func(x_fine);
% Вычисляем погрешность численного метода
% Интерполируем численное решение на ту же сетку, что и аналитическое
y_numerical_interp = interp1(x_numerical, y_numerical, x_fine);
error = max(abs(y_fine - y_numerical_interp));
disp(['Максимальная погрешность ode45: ', num2str(error), ' (должна быть малой)']);
%% ПОСТРОЕНИЕ ГРАФИКОВ (как в лекции, стр. 3)
figure('Position', [100, 100, 800, 600]);
% График 1: Сравнение решений
subplot(2, 1, 1);
fplot(y_analytical, [0, 2], 'b-', 'LineWidth', 2); % аналитическое решение
hold on;
plot(x_numerical, y_numerical, 'ro', 'MarkerSize', 6, 'MarkerFaceColor', 'r'); % численное
hold off;
grid on;
xlabel('x', 'FontSize', 12);
ylabel('y', 'FontSize', 12);
title('Решение дифференциального уравнения dy/dx = -2*x*y', 'FontSize', 14);
legend('Точное решение y = e^{-x^2}', 'Численное решение (ode45)', 'Location', 'best');
% График 2: Погрешность
subplot(2, 1, 2);
error_plot = abs(y_fine - y_numerical_interp);
plot(x_fine, error_plot, 'k-', 'LineWidth', 1.5);
grid on;
xlabel('x', 'FontSize', 12);
ylabel('|y_точн - y_числ|', 'FontSize', 12);
title('Погрешность численного решения', 'FontSize', 14);
% Сохраняем график
saveas(gcf, 'ODE_solution.png');
%% ДОПОЛНИТЕЛЬНО: ДРУГИЕ РЕШАТЕЛИ (из лекции, стр. 5-6)
% В лекции описаны разные решатели:
% ode45 - методы Рунге-Кутта 4-5 порядка (по умолчанию)
% ode23 - методы Рунге-Кутта 2-3 порядка (для низкой точности)
% ode113 - метод Адамса-Башворта-Мултона (для высокой точности)
% ode15s - для жестких задач
disp(' ');
disp('=' * 60);
disp('ДОПОЛНИТЕЛЬНО: ДРУГИЕ РЕШАТЕЛИ');
disp('=' * 60);
% Решаем тем же уравнением с разными методами
[x23, y23] = ode23(dydx, x_interval, y0);
[x113, y113] = ode113(dydx, x_interval, y0);
% Сравниваем количество точек (эффективность методов)
disp(['ode45: ', num2str(length(x_numerical)), ' точек']);
disp(['ode23: ', num2str(length(x23)), ' точек (меньше, но точность ниже)']);
disp(['ode113: ', num2str(length(x113)), ' точек (адаптивный, может быть эффективнее)']);
%% ВЫВОД ИТОГОВ В КОНСОЛЬ
disp(' ');
disp('=' * 60);
disp('ИТОГОВЫЕ РЕЗУЛЬТАТЫ');
disp('=' * 60);
disp(['Аналитическое решение: y(x) = exp(-x^2)']);
disp(['Значение y(2): ', num2str(y_func(2))]);
disp(['Численное решение y(2): ', num2str(y_numerical(end))]);
disp(['Погрешность в точке x=2: ', num2str(abs(y_func(2) - y_numerical(end)))]);