Вы находитесь на странице: 1из 7

УТВЕРЖДАЮ

Заведующий кафедрой Вычислительной математики и


Прикладных информационных технологий
__________________ Леденева Т.М.
(подпись)
02 сентября 2019 года

Направление подготовки Прикладная математика и информатика

Дисциплина Численные методы (лабораторный практикум)

Вид контроля Отчет по лабораторной работе


промежуточный контроль – экзамен, зачет, текущий зачет с указанием формы

Фамилия, имя, отчество студента: Черняев Дмитрий Евгеньевич

Курс, группа :_3 курс 3 группа

Контрольно–измерительный материал №1.

Решение задачи Коши с автоматическим выбором максимальной длины шага


Вариант № 11(4)

Преподаватель ______________ Аристова Е.М.

Дата _____________________
Лист ответа на Контрольно–измерительный материал №11(4).

1. Постановка задачи.
Реализовать численное решение задачи Коши (1), (2) методом
Рунге-Кутты 3-ого и 4-ого порядка с автоматическим выбором
максимальной для данной точности длины шага.
y’(x) = f(x, y) (1)
y(x0) = y0 (2), где x0 совпадает либо с началом либо с концом
отрезка
2. Метод решения.
На каждом шаге вычисляем новое значение yi+1 по текущим
значениям xi, yi по заданным формулам (см. Приложение).
После этого происходит оценка шага на удовлетворительность
для заданной точности. Обозначим локальную погрешность за
ρi+1. Оценка шага происходит следующим образом:
Идёт расчёт локальной погрешности метода (формулы см. в
Приложении). Если |ρi+1| > ε, то шаг надо изменить, а решение
пометить как недостоверное для заданной точности. Расчёт
нового шага осуществляется по формуле:
ε

hε* = 0,9 * s +1 |ρ |*h (3), где s подбирается для конкретного
i+ 1

порядка.
После этого шаг выбирается следующем образом:
hmin , если h ε ≤ h min
*
hε =
{ ¿
h , если hmin <h ε < hmax
ε
hmax ,е hmax ≤ h ε
И дальше интегрирование будет производиться из точки
xi+1 = xi + hε*.
3. Основные процедуры и классы.
Основная функция для решения задачи Коши (1), (2) методом
Рунге-Кутты 3-ого порядка – rungeKutt3. Она принимает на
вход предыдущие значения хi,yi, шаг h, а возвращает новое
значение yi+1.

Основная функция для решения задачи Коши (1), (2) методом


Рунге-Кутты 4-ого порядка – rungeKutt4. Она принимает на
вход предыдущие значения хi,yi, шаг h, а возвращает новое
значение yi+1.
За проверку удовлетворительности шага для данной точности
отвечает класс Step. Он принимает на вход текущий шаг,
локальную погрешность на шаге, погрешность, заданную
пользователем, максимальный и минимальный шаг.
Возвращает новый шаг с проверкой на максимальный и
минимальный шаг.
Также данный класс занимается подсчётом количества шагов,
которые были выполнены с минимальным или максимальным
шагом и подсчитывает средний шаг для всех итераций.

4. Результаты тестирования.
Для проверки метода Рунге-Кутты третьего порядка были
взяты следующие функции. Поскольку метод 3-го порядка, то
он должен получать точные решения на полиномах не выше
третьей степени (аналогично для 4-ого порядка – полиномы не
выше 4-ого степени).
Поэтому была взята следующая задача Коши для обоих
случаев.
dy
=x 3+2 x 2+ 2 x
dx
y ( 0 )=0

Найдем общее решение:


1
y ( x ) = x 2+ x +2+C
3

Используя начальные условия получаем, что C = - 2.


1
y ( x ) = x 2+ x
3

5. Приложение.
Метод Рунге-Кутты 3-ого порядка точности:
k1 = h * f(xi, yi)
h k1
k2 = h * f(xi + 3 , yi + 3
)
2h 2 k2
k3=h*f(xi + 3, yi + 3
)
( k 1 +3 k 3 )
yi+1 = yi + 4

Метод Рунге-Кутты 4-ого порядка точности:


k1 = h * f(xi, yi)
h k1
k2 = h * f(xi + 3 , yi + 3
)
2h −k 1
k3=h*f(xi + 3, yi + 3
+ k 2)

k4 = h * f(xi + h, yi +k1-k2+k3)
( k 1 +3 k 2 +3 k 3 + k 4 )
yi+1 = yi + 6

6.Листинг программы:
Описание максимальной длинны шага

public class Step {

private double hMin; // минимальный шаг


private double hMax; // максимальный шаг
private double eps; // пользовательская погрешность

private int iterationsWithMinStep = 0; //итерации с минимальным шагом


private int iterationsWithMaxStep = 0; // итерации с максимальным шагом
private int iterationsWithErrorMoreThanEpsilon = 0; //итерации с погрешностью большей
чем пользовательская

private List<Double> steps = new ArrayList<>();

public Step(double hMin, double hMax, double eps) {


this.hMin = hMin;
this.hMax = hMax;
this.eps = eps;
}

public double estimate(double hn, double localError) { //оценка погрешности


if (localError > eps) {
iterationsWithErrorMoreThanEpsilon++;
if (hn < hMin) {
iterationsWithMinStep++;
hn = hMin;
}
else if (hn > hMax) {
iterationsWithMaxStep++;
hn = hMax;
}
else {
hn = 0.9 * Math.sqrt(Math.sqrt(eps / Math.abs(localError))) * hn;
}
}
steps.add(hn);
return hn;
}

public double estimateStartingStep(double A, double B) { //оценка погрешности начального


шага
double hn = (B - A) / 10;
if (hn < hMin) {
iterationsWithMinStep++;
hn = hMin;
}
else if (hn > hMax) {
iterationsWithMaxStep++;
hn = hMax;
}
steps.add(hn);
return hn;
}

public boolean isAccuracyAchieved() { //проверка на достижение точности


return iterationsWithErrorMoreThanEpsilon == 0;
}

public double gethMin() {


return hMin;
}

public double gethMax() {


return hMax;
}

public double getEps() {


return eps;
}

public int getIterationsWithMinStep() {


return iterationsWithMinStep;
}

public int getIterationsWithMaxStep() {


return iterationsWithMaxStep;
}

public int getIterationsWithErrorMoreThanEpsilon() {


return iterationsWithErrorMoreThanEpsilon;
}

public List<Double> getSteps() {


return steps;
}
}
Основной код программы:

public class RungeKuttMethod {

public static void main(String[] args) throws IOException {


if (args.length < 6 || args[0].equals("-h")) {
System.out.println("Arguments: A B hMin hMax yn epsilon");
System.exit(0);
}
double A = Double.valueOf(args[0]);
double B = Double.valueOf(args[1]);
double hMin = Double.valueOf(args[2]);
double hMax = Double.valueOf(args[3]);
double y = Double.valueOf(args[4]);
double eps = Double.valueOf(args[5]);
count(A, B, hMin, hMax, y, eps);
System.out.println("Done!");
}

public static void count(Double A, Double B, Double hMin, Double hMax, Double yc, Double eps) throws
IOException {
StringBuilder sb = new StringBuilder();
Step step = new Step(hMin, hMax, eps);
int N = 1;
double xn = A;
double yn = yc;
double yp3;
double yp4 = yc;
double localError;
double h = step.estimateStartingStep(A, B);

sb.append("N;x;y;error\n");
sb.append(String.format("%d;%f;%f;%f\n", N, xn, yn, 0d));
while (xn <= B) {
yp3 = rungeKutt3(xn, yn, h);
yp4 = rungeKutt4(xn, yp4, h);
localError = Math.abs(yp3 - yp4);
h = step.estimate(h, localError);
xn = xn + h;
yn = yp3;
N++;
sb.append(String.format("%d;%.4f;%.4f;%.16f\n", N, xn, yn, localError));
}
try (OutputStream os = new FileOutputStream("stats.csv")) {
os.write(sb.toString().getBytes());
}
StringBuilder summary = new StringBuilder();
summary.append(String.format("Всего произведено %d шагов\n", N));
String accuracy = step.isAccuracyAchieved() ? "достигнута" : "не достигнута";
summary.append(String.format("Заданная точность %f %s\n", eps, accuracy));
if (!step.isAccuracyAchieved()) {
summary.append(String.format("Шагов, для которых погрешность превысила eps:
%d\n",
step.getIterationsWithErrorMoreThanEpsilon()));
}
summary.append(String.format("Шагов с максимальным шагом %f: %d\n", hMax,
step.getIterationsWithMaxStep()));
summary.append(String.format("Шагов с минимальным шагом %f: %d\n", hMin,
step.getIterationsWithMinStep()));
double avgStep = step.getSteps().stream().reduce(0d, Double::sum) / step.getSteps().size();
summary.append(String.format("Средний шаг: %f", avgStep));
try (OutputStream os = new FileOutputStream("summary.txt")){
os.write(summary.toString().getBytes());
}
}

public static double f(double x, double y) { //функция x^3+2*x^2+2*x


return Math.pow(x, 3) + 2 * Math.pow(x, 2) + 2 * x;
}

public static double rungeKutt3(double xn, double yn, double hn) {


double k1, k2, k3, ynext;
k1 = hn * f(xn, yn);
k2 = hn * f(xn + hn / 3, yn + k1 / 3);
k3 = hn * f(xn + 2 * hn / 3, yn + 2 * k2 / 3);

ynext = yn + (k1 + 3 * k3) / 4;

return ynext;
}

public static double rungeKutt4(double xn, double yn, double hn) {


double k1, k2, k3, k4, ynext;
k1 = hn * f(xn, yn);
k2 = hn * f(xn + hn / 3, yn + k1 / 3);
k3 = hn * f(xn + 2 * hn / 3, yn - k1 / 3 + k2);
k4 = hn * f(xn + hn, yn + k1 - k2 + k3);
ynext = yn + (k1 + 3 * k2 + 3 * k3 + k4) / 8;

return ynext;
}

7.Вывод

Метод Рунге-Кутты 3-го порядка можно оценить методом


Рунге-Кутты 4-го порядка. При использовании данного метода
для функций порядка ниже 3-го погрешность метода равна 0
и количество точек интегрирования минимально.